1/* gskgltexturelibraryprivate.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_GL_TEXTURE_LIBRARY_PRIVATE_H__
22#define __GSK_GL_TEXTURE_LIBRARY_PRIVATE_H__
23
24#include "gskgltypesprivate.h"
25#include "gskgltextureprivate.h"
26
27#include "stb_rect_pack.h"
28
29G_BEGIN_DECLS
30
31#define GSK_TYPE_GL_TEXTURE_LIBRARY (gsk_gl_texture_library_get_type ())
32#define GSK_GL_TEXTURE_LIBRARY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSK_TYPE_GL_TEXTURE_LIBRARY, GskGLTextureLibrary))
33#define GSK_IS_GL_TEXTURE_LIBRARY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GSK_TYPE_GL_TEXTURE_LIBRARY))
34#define GSK_GL_TEXTURE_LIBRARY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GSK_TYPE_GL_TEXTURE_LIBRARY, GskGLTextureLibraryClass))
35#define GSK_IS_GL_TEXTURE_LIBRARY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GSK_TYPE_GL_TEXTURE_LIBRARY))
36#define GSK_GL_TEXTURE_LIBRARY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GSK_TYPE_GL_TEXTURE_LIBRARY, GskGLTextureLibraryClass))
37
38typedef struct _GskGLTextureAtlas
39{
40 struct stbrp_context context;
41 struct stbrp_node *nodes;
42
43 int width;
44 int height;
45
46 guint texture_id;
47
48 /* Pixels of rects that have been used at some point,
49 * But are now unused.
50 */
51 int unused_pixels;
52
53 void *user_data;
54} GskGLTextureAtlas;
55
56typedef struct _GskGLTextureAtlasEntry
57{
58 /* A backreference to either the atlas or texture containing
59 * the contents of the atlas entry. For larger items, no atlas
60 * is used and instead a direct texture.
61 */
62 union {
63 GskGLTextureAtlas *atlas;
64 GskGLTexture *texture;
65 };
66
67 /* The area within the atlas translated to 0..1 bounds */
68 struct {
69 float x;
70 float y;
71 float x2;
72 float y2;
73 } area;
74
75 /* Number of pixels in the entry, used to calculate usage
76 * of an atlas while processing.
77 */
78 guint n_pixels : 29;
79
80 /* If entry has marked pixels as used in the atlas this frame */
81 guint used : 1;
82
83 /* If entry was accessed this frame */
84 guint accessed : 1;
85
86 /* When true, backref is an atlas, otherwise texture */
87 guint is_atlased : 1;
88} GskGLTextureAtlasEntry;
89
90typedef struct _GskGLTextureLibrary
91{
92 GObject parent_instance;
93 GskGLDriver *driver;
94 GHashTable *hash_table;
95 guint max_entry_size;
96} GskGLTextureLibrary;
97
98typedef struct _GskGLTextureLibraryClass
99{
100 GObjectClass parent_class;
101
102 void (*begin_frame) (GskGLTextureLibrary *library,
103 gint64 frame_id,
104 GPtrArray *removed_atlases);
105} GskGLTextureLibraryClass;
106
107G_DEFINE_AUTOPTR_CLEANUP_FUNC (GskGLTextureLibrary, g_object_unref)
108
109GType gsk_gl_texture_library_get_type (void) G_GNUC_CONST;
110void gsk_gl_texture_library_set_funcs (GskGLTextureLibrary *self,
111 GHashFunc hash_func,
112 GEqualFunc equal_func,
113 GDestroyNotify key_destroy,
114 GDestroyNotify value_destroy);
115void gsk_gl_texture_library_begin_frame (GskGLTextureLibrary *self,
116 gint64 frame_id,
117 GPtrArray *removed_atlases);
118gpointer gsk_gl_texture_library_pack (GskGLTextureLibrary *self,
119 gpointer key,
120 gsize valuelen,
121 guint width,
122 guint height,
123 int padding,
124 guint *out_packed_x,
125 guint *out_packed_y);
126
127static inline void
128gsk_gl_texture_atlas_mark_unused (GskGLTextureAtlas *self,
129 int n_pixels)
130{
131 g_assert (n_pixels >= 0);
132
133 self->unused_pixels += n_pixels;
134}
135
136static inline void
137gsk_gl_texture_atlas_entry_mark_used (GskGLTextureAtlasEntry *entry)
138{
139 if (entry->used == TRUE || entry->is_atlased == FALSE)
140 return;
141
142 entry->atlas->unused_pixels -= entry->n_pixels;
143 entry->used = TRUE;
144}
145
146static inline void
147gsk_gl_texture_atlas_entry_mark_unused (GskGLTextureAtlasEntry *entry)
148{
149 if (entry->used == FALSE || entry->is_atlased == FALSE)
150 return;
151
152 entry->atlas->unused_pixels += entry->n_pixels;
153 entry->used = FALSE;
154}
155
156static inline gboolean
157gsk_gl_texture_library_lookup (GskGLTextureLibrary *self,
158 gconstpointer key,
159 GskGLTextureAtlasEntry **out_entry)
160{
161 GskGLTextureAtlasEntry *entry = g_hash_table_lookup (hash_table: self->hash_table, key);
162
163 if G_LIKELY (entry != NULL && entry->accessed && entry->used)
164 {
165 *out_entry = entry;
166 return TRUE;
167 }
168
169 if (entry != NULL)
170 {
171 gsk_gl_texture_atlas_entry_mark_used (entry);
172 entry->accessed = TRUE;
173 *out_entry = entry;
174 return TRUE;
175 }
176
177 return FALSE;
178}
179
180static inline guint
181GSK_GL_TEXTURE_ATLAS_ENTRY_TEXTURE (gconstpointer d)
182{
183 const GskGLTextureAtlasEntry *e = d;
184
185 return e->is_atlased ? e->atlas->texture_id
186 : e->texture ? e->texture->texture_id : 0;
187}
188
189static inline double
190gsk_gl_texture_atlas_get_unused_ratio (const GskGLTextureAtlas *self)
191{
192 if (self->unused_pixels > 0)
193 return (double)(self->unused_pixels) / (double)(self->width * self->height);
194 return 0.0;
195}
196
197static inline gboolean
198gsk_gl_texture_library_can_cache (GskGLTextureLibrary *self,
199 int width,
200 int height)
201{
202 g_assert (self->max_entry_size > 0);
203 return width <= self->max_entry_size && height <= self->max_entry_size;
204}
205
206G_END_DECLS
207
208#endif /* __GSK_GL_TEXTURE_LIBRARY_PRIVATE_H__ */
209

source code of gtk/gsk/gl/gskgltexturelibraryprivate.h