diff options
Diffstat (limited to 'gsk/gl/gskgltexturelibraryprivate.h')
-rw-r--r-- | gsk/gl/gskgltexturelibraryprivate.h | 208 |
1 files changed, 208 insertions, 0 deletions
diff --git a/gsk/gl/gskgltexturelibraryprivate.h b/gsk/gl/gskgltexturelibraryprivate.h new file mode 100644 index 0000000000..a784449889 --- /dev/null +++ b/gsk/gl/gskgltexturelibraryprivate.h @@ -0,0 +1,208 @@ +/* gskgltexturelibraryprivate.h + * + * Copyright 2020 Christian Hergert <chergert@redhat.com> + * + * This file is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the Free + * Software Foundation; either version 2.1 of the License, or (at your option) + * any later version. + * + * This file is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#ifndef __GSK_GL_TEXTURE_LIBRARY_PRIVATE_H__ +#define __GSK_GL_TEXTURE_LIBRARY_PRIVATE_H__ + +#include "gskgltypesprivate.h" +#include "gskgltextureprivate.h" + +#include "stb_rect_pack.h" + +G_BEGIN_DECLS + +#define GSK_TYPE_GL_TEXTURE_LIBRARY (gsk_gl_texture_library_get_type ()) +#define GSK_GL_TEXTURE_LIBRARY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSK_TYPE_GL_TEXTURE_LIBRARY, GskGLTextureLibrary)) +#define GSK_IS_GL_TEXTURE_LIBRARY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GSK_TYPE_GL_TEXTURE_LIBRARY)) +#define GSK_GL_TEXTURE_LIBRARY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GSK_TYPE_GL_TEXTURE_LIBRARY, GskGLTextureLibraryClass)) +#define GSK_IS_GL_TEXTURE_LIBRARY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GSK_TYPE_GL_TEXTURE_LIBRARY)) +#define GSK_GL_TEXTURE_LIBRARY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GSK_TYPE_GL_TEXTURE_LIBRARY, GskGLTextureLibraryClass)) + +typedef struct _GskGLTextureAtlas +{ + struct stbrp_context context; + struct stbrp_node *nodes; + + int width; + int height; + + guint texture_id; + + /* Pixels of rects that have been used at some point, + * But are now unused. + */ + int unused_pixels; + + void *user_data; +} GskGLTextureAtlas; + +typedef struct _GskGLTextureAtlasEntry +{ + /* A backreference to either the atlas or texture containing + * the contents of the atlas entry. For larger items, no atlas + * is used and instead a direct texture. + */ + union { + GskGLTextureAtlas *atlas; + GskGLTexture *texture; + }; + + /* The area within the atlas translated to 0..1 bounds */ + struct { + float x; + float y; + float x2; + float y2; + } area; + + /* Number of pixels in the entry, used to calculate usage + * of an atlas while processing. + */ + guint n_pixels : 29; + + /* If entry has marked pixels as used in the atlas this frame */ + guint used : 1; + + /* If entry was accessed this frame */ + guint accessed : 1; + + /* When true, backref is an atlas, otherwise texture */ + guint is_atlased : 1; +} GskGLTextureAtlasEntry; + +typedef struct _GskGLTextureLibrary +{ + GObject parent_instance; + GskGLDriver *driver; + GHashTable *hash_table; + guint max_entry_size; +} GskGLTextureLibrary; + +typedef struct _GskGLTextureLibraryClass +{ + GObjectClass parent_class; + + void (*begin_frame) (GskGLTextureLibrary *library, + gint64 frame_id, + GPtrArray *removed_atlases); +} GskGLTextureLibraryClass; + +G_DEFINE_AUTOPTR_CLEANUP_FUNC (GskGLTextureLibrary, g_object_unref) + +GType gsk_gl_texture_library_get_type (void) G_GNUC_CONST; +void gsk_gl_texture_library_set_funcs (GskGLTextureLibrary *self, + GHashFunc hash_func, + GEqualFunc equal_func, + GDestroyNotify key_destroy, + GDestroyNotify value_destroy); +void gsk_gl_texture_library_begin_frame (GskGLTextureLibrary *self, + gint64 frame_id, + GPtrArray *removed_atlases); +gpointer gsk_gl_texture_library_pack (GskGLTextureLibrary *self, + gpointer key, + gsize valuelen, + guint width, + guint height, + int padding, + guint *out_packed_x, + guint *out_packed_y); + +static inline void +gsk_gl_texture_atlas_mark_unused (GskGLTextureAtlas *self, + int n_pixels) +{ + g_assert (n_pixels >= 0); + + self->unused_pixels += n_pixels; +} + +static inline void +gsk_gl_texture_atlas_entry_mark_used (GskGLTextureAtlasEntry *entry) +{ + if (entry->used == TRUE || entry->is_atlased == FALSE) + return; + + entry->atlas->unused_pixels -= entry->n_pixels; + entry->used = TRUE; +} + +static inline void +gsk_gl_texture_atlas_entry_mark_unused (GskGLTextureAtlasEntry *entry) +{ + if (entry->used == FALSE || entry->is_atlased == FALSE) + return; + + entry->atlas->unused_pixels += entry->n_pixels; + entry->used = FALSE; +} + +static inline gboolean +gsk_gl_texture_library_lookup (GskGLTextureLibrary *self, + gconstpointer key, + GskGLTextureAtlasEntry **out_entry) +{ + GskGLTextureAtlasEntry *entry = g_hash_table_lookup (self->hash_table, key); + + if G_LIKELY (entry != NULL && entry->accessed && entry->used) + { + *out_entry = entry; + return TRUE; + } + + if (entry != NULL) + { + gsk_gl_texture_atlas_entry_mark_used (entry); + entry->accessed = TRUE; + *out_entry = entry; + return TRUE; + } + + return FALSE; +} + +static inline guint +GSK_GL_TEXTURE_ATLAS_ENTRY_TEXTURE (gconstpointer d) +{ + const GskGLTextureAtlasEntry *e = d; + + return e->is_atlased ? e->atlas->texture_id + : e->texture ? e->texture->texture_id : 0; +} + +static inline double +gsk_gl_texture_atlas_get_unused_ratio (const GskGLTextureAtlas *self) +{ + if (self->unused_pixels > 0) + return (double)(self->unused_pixels) / (double)(self->width * self->height); + return 0.0; +} + +static inline gboolean +gsk_gl_texture_library_can_cache (GskGLTextureLibrary *self, + int width, + int height) +{ + g_assert (self->max_entry_size > 0); + return width <= self->max_entry_size && height <= self->max_entry_size; +} + +G_END_DECLS + +#endif /* __GSK_GL_TEXTURE_LIBRARY_PRIVATE_H__ */ |