1 /* gskngldriverprivate.h
2  *
3  * Copyright 2020 Christian Hergert <chergert@redhat.com>
4  *
5  * This file is free software; you can redistribute it and/or modify it under
6  * the terms of the GNU Lesser General Public License as published by the Free
7  * Software Foundation; either version 2.1 of the License, or (at your option)
8  * any later version.
9  *
10  * This file is distributed in the hope that it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
13  * License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program.  If not, see <http://www.gnu.org/licenses/>.
17  *
18  * SPDX-License-Identifier: LGPL-2.1-or-later
19  */
20 
21 #ifndef __GSK_NGL_DRIVER_PRIVATE_H__
22 #define __GSK_NGL_DRIVER_PRIVATE_H__
23 
24 #include <gdk/gdkgltextureprivate.h>
25 
26 #include "gskngltypesprivate.h"
27 #include "gskngltexturepoolprivate.h"
28 
29 G_BEGIN_DECLS
30 
31 enum {
32   UNIFORM_SHARED_ALPHA,
33   UNIFORM_SHARED_SOURCE,
34   UNIFORM_SHARED_CLIP_RECT,
35   UNIFORM_SHARED_VIEWPORT,
36   UNIFORM_SHARED_PROJECTION,
37   UNIFORM_SHARED_MODELVIEW,
38 
39   UNIFORM_SHARED_LAST
40 };
41 
42 enum {
43   UNIFORM_CUSTOM_SIZE = UNIFORM_SHARED_LAST,
44   UNIFORM_CUSTOM_TEXTURE1,
45   UNIFORM_CUSTOM_TEXTURE2,
46   UNIFORM_CUSTOM_TEXTURE3,
47   UNIFORM_CUSTOM_TEXTURE4,
48   UNIFORM_CUSTOM_ARG0,
49   UNIFORM_CUSTOM_ARG1,
50   UNIFORM_CUSTOM_ARG2,
51   UNIFORM_CUSTOM_ARG3,
52   UNIFORM_CUSTOM_ARG4,
53   UNIFORM_CUSTOM_ARG5,
54   UNIFORM_CUSTOM_ARG6,
55   UNIFORM_CUSTOM_ARG7,
56 
57   UNIFORM_CUSTOM_LAST
58 };
59 
60 typedef struct {
61   gconstpointer   pointer;
62   float           scale_x;
63   float           scale_y;
64   int             filter;
65   int             pointer_is_child;
66   graphene_rect_t parent_rect; /* Valid when pointer_is_child */
67 } GskTextureKey;
68 
69 #define GSK_NGL_NO_UNIFORMS CONCAT_EXPANDED(UNIFORM_INVALID_,__COUNTER__)
70 #define CONCAT_EXPANDED(a,b) CONCAT_EXPANDED2(a,b)
71 #define CONCAT_EXPANDED2(a,b) a##b
72 #define GSK_NGL_ADD_UNIFORM(pos, KEY, name) UNIFORM_##KEY = UNIFORM_SHARED_LAST + pos,
73 #define GSK_NGL_DEFINE_PROGRAM(name, resource, uniforms) enum { uniforms };
74 # include "gsknglprograms.defs"
75 #undef GSK_NGL_DEFINE_PROGRAM
76 #undef GSK_NGL_ADD_UNIFORM
77 #undef GSK_NGL_NO_UNIFORMS
78 #undef CONCAT_EXPANDED
79 #undef CONCAT_EXPANDED2
80 
81 #define GSK_TYPE_NGL_DRIVER (gsk_ngl_driver_get_type())
82 
83 G_DECLARE_FINAL_TYPE (GskNglDriver, gsk_ngl_driver, GSK, NGL_DRIVER, GObject)
84 
85 struct _GskNglRenderTarget
86 {
87   guint framebuffer_id;
88   guint texture_id;
89   int min_filter;
90   int mag_filter;
91   int width;
92   int height;
93 };
94 
95 struct _GskNglDriver
96 {
97   GObject parent_instance;
98 
99   GskNglCommandQueue *shared_command_queue;
100   GskNglCommandQueue *command_queue;
101 
102   GskNglTexturePool texture_pool;
103 
104   GskNglGlyphLibrary *glyphs;
105   GskNglIconLibrary *icons;
106   GskNglShadowLibrary *shadows;
107 
108   GHashTable *textures;
109   GHashTable *key_to_texture_id;
110   GHashTable *texture_id_to_key;
111 
112   GPtrArray *atlases;
113 
114   GHashTable *shader_cache;
115 
116   GArray *autorelease_framebuffers;
117   GPtrArray *render_targets;
118 
119 #define GSK_NGL_NO_UNIFORMS
120 #define GSK_NGL_ADD_UNIFORM(pos, KEY, name)
121 #define GSK_NGL_DEFINE_PROGRAM(name, resource, uniforms) \
122   GskNglProgram *name ## _no_clip; \
123   GskNglProgram *name ## _rect_clip; \
124   GskNglProgram *name;
125 # include "gsknglprograms.defs"
126 #undef GSK_NGL_NO_UNIFORMS
127 #undef GSK_NGL_ADD_UNIFORM
128 #undef GSK_NGL_DEFINE_PROGRAM
129 
130   gint64 current_frame_id;
131 
132   /* Used to reduce number of comparisons */
133   guint stamps[UNIFORM_SHARED_LAST];
134 
135   guint debug : 1;
136   guint in_frame : 1;
137 };
138 
139 GskNglDriver       *gsk_ngl_driver_for_display            (GdkDisplay           *display,
140                                                            gboolean              debug_shaders,
141                                                            GError              **error);
142 GskNglCommandQueue *gsk_ngl_driver_create_command_queue   (GskNglDriver         *self,
143                                                            GdkGLContext         *context);
144 GdkGLContext       *gsk_ngl_driver_get_context            (GskNglDriver         *self);
145 gboolean            gsk_ngl_driver_create_render_target   (GskNglDriver         *self,
146                                                            int                   width,
147                                                            int                   height,
148                                                            int                   min_filter,
149                                                            int                   mag_filter,
150                                                            GskNglRenderTarget  **render_target);
151 guint               gsk_ngl_driver_release_render_target  (GskNglDriver         *self,
152                                                            GskNglRenderTarget   *render_target,
153                                                            gboolean              release_texture);
154 void                gsk_ngl_driver_begin_frame            (GskNglDriver         *self,
155                                                            GskNglCommandQueue   *command_queue);
156 void                gsk_ngl_driver_end_frame              (GskNglDriver         *self);
157 void                gsk_ngl_driver_after_frame            (GskNglDriver         *self);
158 GdkTexture         *gsk_ngl_driver_create_gdk_texture     (GskNglDriver         *self,
159                                                            guint                 texture_id);
160 void                gsk_ngl_driver_cache_texture          (GskNglDriver         *self,
161                                                            const GskTextureKey  *key,
162                                                            guint                 texture_id);
163 guint               gsk_ngl_driver_load_texture           (GskNglDriver         *self,
164                                                            GdkTexture           *texture,
165                                                            int                   min_filter,
166                                                            int                   mag_filter);
167 GskNglTexture      *gsk_ngl_driver_create_texture         (GskNglDriver         *self,
168                                                            float                 width,
169                                                            float                 height,
170                                                            int                   min_filter,
171                                                            int                   mag_filter);
172 void                gsk_ngl_driver_release_texture        (GskNglDriver         *self,
173                                                            GskNglTexture        *texture);
174 void                gsk_ngl_driver_release_texture_by_id  (GskNglDriver         *self,
175                                                            guint                 texture_id);
176 GskNglTexture      *gsk_ngl_driver_mark_texture_permanent (GskNglDriver         *self,
177                                                            guint                 texture_id);
178 void                gsk_ngl_driver_add_texture_slices     (GskNglDriver         *self,
179                                                            GdkTexture           *texture,
180                                                            GskNglTextureSlice  **out_slices,
181                                                            guint                *out_n_slices);
182 GskNglProgram      *gsk_ngl_driver_lookup_shader          (GskNglDriver         *self,
183                                                            GskGLShader          *shader,
184                                                            GError              **error);
185 GskNglTextureAtlas *gsk_ngl_driver_create_atlas           (GskNglDriver         *self);
186 
187 #ifdef G_ENABLE_DEBUG
188 void                gsk_ngl_driver_save_atlases_to_png    (GskNglDriver         *self,
189                                                            const char           *directory);
190 #endif
191 
192 static inline GskNglTexture *
gsk_ngl_driver_get_texture_by_id(GskNglDriver * self,guint texture_id)193 gsk_ngl_driver_get_texture_by_id (GskNglDriver *self,
194                                   guint         texture_id)
195 {
196   return g_hash_table_lookup (self->textures, GUINT_TO_POINTER (texture_id));
197 }
198 
199 /**
200  * gsk_ngl_driver_lookup_texture:
201  * @self: a `GskNglDriver`
202  * @key: the key for the texture
203  *
204  * Looks up a texture in the texture cache by @key.
205  *
206  * If the texture could not be found, then zero is returned.
207  *
208  * Returns: a positive integer if the texture was found; otherwise 0.
209  */
210 static inline guint
gsk_ngl_driver_lookup_texture(GskNglDriver * self,const GskTextureKey * key)211 gsk_ngl_driver_lookup_texture (GskNglDriver        *self,
212                                const GskTextureKey *key)
213 {
214   gpointer id;
215 
216   if (g_hash_table_lookup_extended (self->key_to_texture_id, key, NULL, &id))
217     {
218       GskNglTexture *texture = g_hash_table_lookup (self->textures, id);
219 
220       if (texture != NULL)
221         texture->last_used_in_frame = self->current_frame_id;
222 
223       return GPOINTER_TO_UINT (id);
224     }
225 
226   return 0;
227 }
228 
229 static inline void
gsk_ngl_driver_slice_texture(GskNglDriver * self,GdkTexture * texture,GskNglTextureSlice ** out_slices,guint * out_n_slices)230 gsk_ngl_driver_slice_texture (GskNglDriver        *self,
231                               GdkTexture          *texture,
232                               GskNglTextureSlice **out_slices,
233                               guint               *out_n_slices)
234 {
235   GskNglTexture *t;
236 
237   if ((t = gdk_texture_get_render_data (texture, self)))
238     {
239       *out_slices = t->slices;
240       *out_n_slices = t->n_slices;
241       return;
242     }
243 
244   gsk_ngl_driver_add_texture_slices (self, texture, out_slices, out_n_slices);
245 }
246 
247 G_END_DECLS
248 
249 #endif /* __GSK_NGL_DRIVER_PRIVATE_H__ */
250