forked from AuroraMiddleware/gtk
Merge branch 'wip/chergert/gsk-gl-texture-library' into 'main'
gsk/gl: texture libraries, shader creation See merge request GNOME/gtk!4583
This commit is contained in:
commit
dcc7cf7114
@ -512,7 +512,7 @@ load_file (const char *demoname,
|
|||||||
|
|
||||||
info_buffer = gtk_text_buffer_new (NULL);
|
info_buffer = gtk_text_buffer_new (NULL);
|
||||||
gtk_text_buffer_create_tag (info_buffer, "title",
|
gtk_text_buffer_create_tag (info_buffer, "title",
|
||||||
"font", "Sans 18",
|
"size", 18 * 1024,
|
||||||
"pixels-below-lines", 10,
|
"pixels-below-lines", 10,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
|
@ -282,7 +282,7 @@ snapshot_uniforms (GskGLUniformState *state,
|
|||||||
{
|
{
|
||||||
const GskGLUniformMapping *mapping = &program->mappings[i];
|
const GskGLUniformMapping *mapping = &program->mappings[i];
|
||||||
|
|
||||||
if (!mapping->info.initial && mapping->location > -1)
|
if (!mapping->info.initial && mapping->info.format && mapping->location > -1)
|
||||||
{
|
{
|
||||||
uniform[count].location = mapping->location;
|
uniform[count].location = mapping->location;
|
||||||
uniform[count].info = mapping->info;
|
uniform[count].info = mapping->info;
|
||||||
|
@ -44,9 +44,6 @@
|
|||||||
#include <gdk/gdkprofilerprivate.h>
|
#include <gdk/gdkprofilerprivate.h>
|
||||||
#include <gdk/gdktextureprivate.h>
|
#include <gdk/gdktextureprivate.h>
|
||||||
|
|
||||||
#define ATLAS_SIZE 512
|
|
||||||
#define MAX_OLD_RATIO 0.5
|
|
||||||
|
|
||||||
G_DEFINE_TYPE (GskGLDriver, gsk_gl_driver, G_TYPE_OBJECT)
|
G_DEFINE_TYPE (GskGLDriver, gsk_gl_driver, G_TYPE_OBJECT)
|
||||||
|
|
||||||
static guint
|
static guint
|
||||||
@ -156,50 +153,6 @@ gsk_gl_driver_collect_unused_textures (GskGLDriver *self,
|
|||||||
return collected;
|
return collected;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
gsk_gl_texture_atlas_free (GskGLTextureAtlas *atlas)
|
|
||||||
{
|
|
||||||
if (atlas->texture_id != 0)
|
|
||||||
{
|
|
||||||
glDeleteTextures (1, &atlas->texture_id);
|
|
||||||
atlas->texture_id = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_clear_pointer (&atlas->nodes, g_free);
|
|
||||||
g_slice_free (GskGLTextureAtlas, atlas);
|
|
||||||
}
|
|
||||||
|
|
||||||
GskGLTextureAtlas *
|
|
||||||
gsk_gl_driver_create_atlas (GskGLDriver *self)
|
|
||||||
{
|
|
||||||
GskGLTextureAtlas *atlas;
|
|
||||||
|
|
||||||
g_return_val_if_fail (GSK_IS_GL_DRIVER (self), NULL);
|
|
||||||
|
|
||||||
atlas = g_slice_new0 (GskGLTextureAtlas);
|
|
||||||
atlas->width = ATLAS_SIZE;
|
|
||||||
atlas->height = ATLAS_SIZE;
|
|
||||||
/* TODO: We might want to change the strategy about the amount of
|
|
||||||
* nodes here? stb_rect_pack.h says width is optimal. */
|
|
||||||
atlas->nodes = g_malloc0_n (atlas->width, sizeof (struct stbrp_node));
|
|
||||||
stbrp_init_target (&atlas->context, atlas->width, atlas->height, atlas->nodes, atlas->width);
|
|
||||||
atlas->texture_id = gsk_gl_command_queue_create_texture (self->command_queue,
|
|
||||||
atlas->width,
|
|
||||||
atlas->height,
|
|
||||||
GL_RGBA8,
|
|
||||||
GL_LINEAR,
|
|
||||||
GL_LINEAR);
|
|
||||||
|
|
||||||
gdk_gl_context_label_object_printf (gdk_gl_context_get_current (),
|
|
||||||
GL_TEXTURE, atlas->texture_id,
|
|
||||||
"Texture atlas %d",
|
|
||||||
atlas->texture_id);
|
|
||||||
|
|
||||||
g_ptr_array_add (self->atlases, atlas);
|
|
||||||
|
|
||||||
return atlas;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
remove_program (gpointer data)
|
remove_program (gpointer data)
|
||||||
{
|
{
|
||||||
@ -226,6 +179,29 @@ gsk_gl_driver_shader_weak_cb (gpointer data,
|
|||||||
g_hash_table_remove (self->shader_cache, where_object_was);
|
g_hash_table_remove (self->shader_cache, where_object_was);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
G_GNUC_NULL_TERMINATED static inline GBytes *
|
||||||
|
join_sources (GBytes *first_bytes,
|
||||||
|
...)
|
||||||
|
{
|
||||||
|
GByteArray *byte_array = g_byte_array_new ();
|
||||||
|
GBytes *bytes = first_bytes;
|
||||||
|
va_list args;
|
||||||
|
|
||||||
|
va_start (args, first_bytes);
|
||||||
|
while (bytes != NULL)
|
||||||
|
{
|
||||||
|
gsize len;
|
||||||
|
const guint8 *data = g_bytes_get_data (bytes, &len);
|
||||||
|
if (len > 0)
|
||||||
|
g_byte_array_append (byte_array, data, len);
|
||||||
|
g_bytes_unref (bytes);
|
||||||
|
bytes = va_arg (args, GBytes *);
|
||||||
|
}
|
||||||
|
va_end (args);
|
||||||
|
|
||||||
|
return g_byte_array_free_to_bytes (byte_array);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gsk_gl_driver_dispose (GObject *object)
|
gsk_gl_driver_dispose (GObject *object)
|
||||||
{
|
{
|
||||||
@ -235,6 +211,10 @@ gsk_gl_driver_dispose (GObject *object)
|
|||||||
g_assert (self->in_frame == FALSE);
|
g_assert (self->in_frame == FALSE);
|
||||||
|
|
||||||
#define GSK_GL_NO_UNIFORMS
|
#define GSK_GL_NO_UNIFORMS
|
||||||
|
#define GSK_GL_SHADER_RESOURCE(name)
|
||||||
|
#define GSK_GL_SHADER_STRING(str)
|
||||||
|
#define GSK_GL_SHADER_SINGLE(name)
|
||||||
|
#define GSK_GL_SHADER_JOINED(kind, ...)
|
||||||
#define GSK_GL_ADD_UNIFORM(pos, KEY, name)
|
#define GSK_GL_ADD_UNIFORM(pos, KEY, name)
|
||||||
#define GSK_GL_DEFINE_PROGRAM(name, resource, uniforms) \
|
#define GSK_GL_DEFINE_PROGRAM(name, resource, uniforms) \
|
||||||
GSK_GL_DELETE_PROGRAM(name); \
|
GSK_GL_DELETE_PROGRAM(name); \
|
||||||
@ -248,6 +228,10 @@ gsk_gl_driver_dispose (GObject *object)
|
|||||||
} G_STMT_END;
|
} G_STMT_END;
|
||||||
# include "gskglprograms.defs"
|
# include "gskglprograms.defs"
|
||||||
#undef GSK_GL_NO_UNIFORMS
|
#undef GSK_GL_NO_UNIFORMS
|
||||||
|
#undef GSK_GL_SHADER_RESOURCE
|
||||||
|
#undef GSK_GL_SHADER_STRING
|
||||||
|
#undef GSK_GL_SHADER_SINGLE
|
||||||
|
#undef GSK_GL_SHADER_JOINED
|
||||||
#undef GSK_GL_ADD_UNIFORM
|
#undef GSK_GL_ADD_UNIFORM
|
||||||
#undef GSK_GL_DEFINE_PROGRAM
|
#undef GSK_GL_DEFINE_PROGRAM
|
||||||
|
|
||||||
@ -289,11 +273,10 @@ gsk_gl_driver_dispose (GObject *object)
|
|||||||
g_assert (!self->texture_id_to_key || g_hash_table_size (self->texture_id_to_key) == 0);
|
g_assert (!self->texture_id_to_key || g_hash_table_size (self->texture_id_to_key) == 0);
|
||||||
g_assert (!self->key_to_texture_id|| g_hash_table_size (self->key_to_texture_id) == 0);
|
g_assert (!self->key_to_texture_id|| g_hash_table_size (self->key_to_texture_id) == 0);
|
||||||
|
|
||||||
g_clear_object (&self->glyphs);
|
g_clear_object (&self->glyphs_library);
|
||||||
g_clear_object (&self->icons);
|
g_clear_object (&self->icons_library);
|
||||||
g_clear_object (&self->shadows);
|
g_clear_object (&self->shadows_library);
|
||||||
|
|
||||||
g_clear_pointer (&self->atlases, g_ptr_array_unref);
|
|
||||||
g_clear_pointer (&self->autorelease_framebuffers, g_array_unref);
|
g_clear_pointer (&self->autorelease_framebuffers, g_array_unref);
|
||||||
g_clear_pointer (&self->key_to_texture_id, g_hash_table_unref);
|
g_clear_pointer (&self->key_to_texture_id, g_hash_table_unref);
|
||||||
g_clear_pointer (&self->textures, g_hash_table_unref);
|
g_clear_pointer (&self->textures, g_hash_table_unref);
|
||||||
@ -330,7 +313,6 @@ gsk_gl_driver_init (GskGLDriver *self)
|
|||||||
self->shader_cache = g_hash_table_new_full (NULL, NULL, NULL, remove_program);
|
self->shader_cache = g_hash_table_new_full (NULL, NULL, NULL, remove_program);
|
||||||
self->texture_pool = g_array_new (FALSE, FALSE, sizeof (guint));
|
self->texture_pool = g_array_new (FALSE, FALSE, sizeof (guint));
|
||||||
self->render_targets = g_ptr_array_new ();
|
self->render_targets = g_ptr_array_new ();
|
||||||
self->atlases = g_ptr_array_new_with_free_func ((GDestroyNotify)gsk_gl_texture_atlas_free);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
@ -348,14 +330,14 @@ gsk_gl_driver_load_programs (GskGLDriver *self,
|
|||||||
|
|
||||||
/* Setup preambles that are shared by all shaders */
|
/* Setup preambles that are shared by all shaders */
|
||||||
gsk_gl_compiler_set_preamble_from_resource (compiler,
|
gsk_gl_compiler_set_preamble_from_resource (compiler,
|
||||||
GSK_GL_COMPILER_ALL,
|
GSK_GL_COMPILER_ALL,
|
||||||
"/org/gtk/libgsk/gl/preamble.glsl");
|
"/org/gtk/libgsk/gl/preamble.glsl");
|
||||||
gsk_gl_compiler_set_preamble_from_resource (compiler,
|
gsk_gl_compiler_set_preamble_from_resource (compiler,
|
||||||
GSK_GL_COMPILER_VERTEX,
|
GSK_GL_COMPILER_VERTEX,
|
||||||
"/org/gtk/libgsk/gl/preamble.vs.glsl");
|
"/org/gtk/libgsk/gl/preamble.vs.glsl");
|
||||||
gsk_gl_compiler_set_preamble_from_resource (compiler,
|
gsk_gl_compiler_set_preamble_from_resource (compiler,
|
||||||
GSK_GL_COMPILER_FRAGMENT,
|
GSK_GL_COMPILER_FRAGMENT,
|
||||||
"/org/gtk/libgsk/gl/preamble.fs.glsl");
|
"/org/gtk/libgsk/gl/preamble.fs.glsl");
|
||||||
|
|
||||||
/* Setup attributes that are provided via VBO */
|
/* Setup attributes that are provided via VBO */
|
||||||
gsk_gl_compiler_bind_attribute (compiler, "aPosition", 0);
|
gsk_gl_compiler_bind_attribute (compiler, "aPosition", 0);
|
||||||
@ -365,10 +347,28 @@ gsk_gl_driver_load_programs (GskGLDriver *self,
|
|||||||
|
|
||||||
/* Use XMacros to register all of our programs and their uniforms */
|
/* Use XMacros to register all of our programs and their uniforms */
|
||||||
#define GSK_GL_NO_UNIFORMS
|
#define GSK_GL_NO_UNIFORMS
|
||||||
|
#define GSK_GL_SHADER_RESOURCE(name) \
|
||||||
|
g_bytes_ref(g_resources_lookup_data("/org/gtk/libgsk/gl/" name, 0, NULL))
|
||||||
|
#define GSK_GL_SHADER_STRING(str) \
|
||||||
|
g_bytes_new_static(str, strlen(str))
|
||||||
|
#define GSK_GL_SHADER_SINGLE(bytes) \
|
||||||
|
G_STMT_START { \
|
||||||
|
GBytes *b = bytes; \
|
||||||
|
gsk_gl_compiler_set_source (compiler, GSK_GL_COMPILER_ALL, b); \
|
||||||
|
g_bytes_unref (b); \
|
||||||
|
} G_STMT_END;
|
||||||
|
#define GSK_GL_SHADER_JOINED(kind, ...) \
|
||||||
|
G_STMT_START { \
|
||||||
|
GBytes *bytes = join_sources(__VA_ARGS__); \
|
||||||
|
gsk_gl_compiler_set_source (compiler, GSK_GL_COMPILER_##kind, bytes); \
|
||||||
|
g_bytes_unref (bytes); \
|
||||||
|
} G_STMT_END;
|
||||||
#define GSK_GL_ADD_UNIFORM(pos, KEY, name) \
|
#define GSK_GL_ADD_UNIFORM(pos, KEY, name) \
|
||||||
gsk_gl_program_add_uniform (program, #name, UNIFORM_##KEY);
|
gsk_gl_program_add_uniform (program, #name, UNIFORM_##KEY);
|
||||||
#define GSK_GL_DEFINE_PROGRAM(name, resource, uniforms) \
|
#define GSK_GL_DEFINE_PROGRAM(name, sources, uniforms) \
|
||||||
gsk_gl_compiler_set_source_from_resource (compiler, GSK_GL_COMPILER_ALL, resource); \
|
gsk_gl_compiler_set_source (compiler, GSK_GL_COMPILER_VERTEX, NULL); \
|
||||||
|
gsk_gl_compiler_set_source (compiler, GSK_GL_COMPILER_FRAGMENT, NULL); \
|
||||||
|
sources \
|
||||||
GSK_GL_COMPILE_PROGRAM(name ## _no_clip, uniforms, "#define NO_CLIP 1\n"); \
|
GSK_GL_COMPILE_PROGRAM(name ## _no_clip, uniforms, "#define NO_CLIP 1\n"); \
|
||||||
GSK_GL_COMPILE_PROGRAM(name ## _rect_clip, uniforms, "#define RECT_CLIP 1\n"); \
|
GSK_GL_COMPILE_PROGRAM(name ## _rect_clip, uniforms, "#define RECT_CLIP 1\n"); \
|
||||||
GSK_GL_COMPILE_PROGRAM(name, uniforms, "");
|
GSK_GL_COMPILE_PROGRAM(name, uniforms, "");
|
||||||
@ -401,6 +401,11 @@ gsk_gl_driver_load_programs (GskGLDriver *self,
|
|||||||
#undef GSK_GL_DEFINE_PROGRAM_CLIP
|
#undef GSK_GL_DEFINE_PROGRAM_CLIP
|
||||||
#undef GSK_GL_DEFINE_PROGRAM
|
#undef GSK_GL_DEFINE_PROGRAM
|
||||||
#undef GSK_GL_ADD_UNIFORM
|
#undef GSK_GL_ADD_UNIFORM
|
||||||
|
#undef GSK_GL_SHADER_SINGLE
|
||||||
|
#undef GSK_GL_SHADER_JOINED
|
||||||
|
#undef GSK_GL_SHADER_RESOURCE
|
||||||
|
#undef GSK_GL_SHADER_STRING
|
||||||
|
#undef GSK_GL_NO_UNIFORMS
|
||||||
|
|
||||||
ret = TRUE;
|
ret = TRUE;
|
||||||
|
|
||||||
@ -456,9 +461,9 @@ gsk_gl_driver_new (GskGLCommandQueue *command_queue,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
self->glyphs = gsk_gl_glyph_library_new (self);
|
self->glyphs_library = gsk_gl_glyph_library_new (self);
|
||||||
self->icons = gsk_gl_icon_library_new (self);
|
self->icons_library = gsk_gl_icon_library_new (self);
|
||||||
self->shadows = gsk_gl_shadow_library_new (self);
|
self->shadows_library = gsk_gl_shadow_library_new (self);
|
||||||
|
|
||||||
gdk_profiler_end_mark (before, "create GskGLDriver", NULL);
|
gdk_profiler_end_mark (before, "create GskGLDriver", NULL);
|
||||||
|
|
||||||
@ -518,37 +523,6 @@ failure:
|
|||||||
return g_steal_pointer (&driver);
|
return g_steal_pointer (&driver);
|
||||||
}
|
}
|
||||||
|
|
||||||
static GPtrArray *
|
|
||||||
gsk_gl_driver_compact_atlases (GskGLDriver *self)
|
|
||||||
{
|
|
||||||
GPtrArray *removed = NULL;
|
|
||||||
|
|
||||||
g_assert (GSK_IS_GL_DRIVER (self));
|
|
||||||
|
|
||||||
for (guint i = self->atlases->len; i > 0; i--)
|
|
||||||
{
|
|
||||||
GskGLTextureAtlas *atlas = g_ptr_array_index (self->atlases, i - 1);
|
|
||||||
|
|
||||||
if (gsk_gl_texture_atlas_get_unused_ratio (atlas) > MAX_OLD_RATIO)
|
|
||||||
{
|
|
||||||
GSK_NOTE (GLYPH_CACHE,
|
|
||||||
g_message ("Dropping atlas %d (%g.2%% old)", i,
|
|
||||||
100.0 * gsk_gl_texture_atlas_get_unused_ratio (atlas)));
|
|
||||||
if (removed == NULL)
|
|
||||||
removed = g_ptr_array_new_with_free_func ((GDestroyNotify)gsk_gl_texture_atlas_free);
|
|
||||||
g_ptr_array_add (removed, g_ptr_array_steal_index (self->atlases, i - 1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
GSK_NOTE (GLYPH_CACHE, {
|
|
||||||
static guint timestamp;
|
|
||||||
if (timestamp++ % 60 == 0)
|
|
||||||
g_message ("%d atlases", self->atlases->len);
|
|
||||||
});
|
|
||||||
|
|
||||||
return removed;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gsk_gl_driver_begin_frame:
|
* gsk_gl_driver_begin_frame:
|
||||||
* @self: a `GskGLDriver`
|
* @self: a `GskGLDriver`
|
||||||
@ -565,7 +539,6 @@ gsk_gl_driver_begin_frame (GskGLDriver *self,
|
|||||||
GskGLCommandQueue *command_queue)
|
GskGLCommandQueue *command_queue)
|
||||||
{
|
{
|
||||||
gint64 last_frame_id;
|
gint64 last_frame_id;
|
||||||
GPtrArray *removed;
|
|
||||||
|
|
||||||
g_return_if_fail (GSK_IS_GL_DRIVER (self));
|
g_return_if_fail (GSK_IS_GL_DRIVER (self));
|
||||||
g_return_if_fail (GSK_IS_GL_COMMAND_QUEUE (command_queue));
|
g_return_if_fail (GSK_IS_GL_COMMAND_QUEUE (command_queue));
|
||||||
@ -580,19 +553,14 @@ gsk_gl_driver_begin_frame (GskGLDriver *self,
|
|||||||
|
|
||||||
gsk_gl_command_queue_begin_frame (self->command_queue);
|
gsk_gl_command_queue_begin_frame (self->command_queue);
|
||||||
|
|
||||||
/* Compact atlases with too many freed pixels */
|
|
||||||
removed = gsk_gl_driver_compact_atlases (self);
|
|
||||||
|
|
||||||
/* Mark unused pixel regions of the atlases */
|
/* Mark unused pixel regions of the atlases */
|
||||||
gsk_gl_texture_library_begin_frame (GSK_GL_TEXTURE_LIBRARY (self->icons),
|
gsk_gl_texture_library_begin_frame (GSK_GL_TEXTURE_LIBRARY (self->icons_library),
|
||||||
self->current_frame_id,
|
self->current_frame_id);
|
||||||
removed);
|
gsk_gl_texture_library_begin_frame (GSK_GL_TEXTURE_LIBRARY (self->glyphs_library),
|
||||||
gsk_gl_texture_library_begin_frame (GSK_GL_TEXTURE_LIBRARY (self->glyphs),
|
self->current_frame_id);
|
||||||
self->current_frame_id,
|
|
||||||
removed);
|
|
||||||
|
|
||||||
/* Cleanup old shadows */
|
/* Cleanup old shadows */
|
||||||
gsk_gl_shadow_library_begin_frame (self->shadows);
|
gsk_gl_shadow_library_begin_frame (self->shadows_library);
|
||||||
|
|
||||||
/* Remove all textures that are from a previous frame or are no
|
/* Remove all textures that are from a previous frame or are no
|
||||||
* longer used by linked GdkTexture. We do this at the beginning
|
* longer used by linked GdkTexture. We do this at the beginning
|
||||||
@ -600,9 +568,6 @@ gsk_gl_driver_begin_frame (GskGLDriver *self,
|
|||||||
* we block on any resources while delivering our frames.
|
* we block on any resources while delivering our frames.
|
||||||
*/
|
*/
|
||||||
gsk_gl_driver_collect_unused_textures (self, last_frame_id - 1);
|
gsk_gl_driver_collect_unused_textures (self, last_frame_id - 1);
|
||||||
|
|
||||||
/* Now free atlas textures */
|
|
||||||
g_clear_pointer (&removed, g_ptr_array_unref);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1182,14 +1147,23 @@ void
|
|||||||
gsk_gl_driver_save_atlases_to_png (GskGLDriver *self,
|
gsk_gl_driver_save_atlases_to_png (GskGLDriver *self,
|
||||||
const char *directory)
|
const char *directory)
|
||||||
{
|
{
|
||||||
|
GPtrArray *atlases;
|
||||||
|
|
||||||
g_return_if_fail (GSK_IS_GL_DRIVER (self));
|
g_return_if_fail (GSK_IS_GL_DRIVER (self));
|
||||||
|
|
||||||
if (directory == NULL)
|
if (directory == NULL)
|
||||||
directory = ".";
|
directory = ".";
|
||||||
|
|
||||||
for (guint i = 0; i < self->atlases->len; i++)
|
#define copy_atlases(dst, library) \
|
||||||
|
g_ptr_array_extend(dst, GSK_GL_TEXTURE_LIBRARY(library)->atlases, NULL, NULL)
|
||||||
|
atlases = g_ptr_array_new ();
|
||||||
|
copy_atlases (atlases, self->glyphs_library);
|
||||||
|
copy_atlases (atlases, self->icons_library);
|
||||||
|
#undef copy_atlases
|
||||||
|
|
||||||
|
for (guint i = 0; i < atlases->len; i++)
|
||||||
{
|
{
|
||||||
GskGLTextureAtlas *atlas = g_ptr_array_index (self->atlases, i);
|
GskGLTextureAtlas *atlas = g_ptr_array_index (atlases, i);
|
||||||
char *filename = g_strdup_printf ("%s%sframe-%d-atlas-%d.png",
|
char *filename = g_strdup_printf ("%s%sframe-%d-atlas-%d.png",
|
||||||
directory,
|
directory,
|
||||||
G_DIR_SEPARATOR_S,
|
G_DIR_SEPARATOR_S,
|
||||||
@ -1198,6 +1172,8 @@ gsk_gl_driver_save_atlases_to_png (GskGLDriver *self,
|
|||||||
write_atlas_to_png (self, atlas, filename);
|
write_atlas_to_png (self, atlas, filename);
|
||||||
g_free (filename);
|
g_free (filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g_ptr_array_unref (atlases);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -100,17 +100,15 @@ struct _GskGLDriver
|
|||||||
GskGLCommandQueue *shared_command_queue;
|
GskGLCommandQueue *shared_command_queue;
|
||||||
GskGLCommandQueue *command_queue;
|
GskGLCommandQueue *command_queue;
|
||||||
|
|
||||||
GskGLGlyphLibrary *glyphs;
|
GskGLGlyphLibrary *glyphs_library;
|
||||||
GskGLIconLibrary *icons;
|
GskGLIconLibrary *icons_library;
|
||||||
GskGLShadowLibrary *shadows;
|
GskGLShadowLibrary *shadows_library;
|
||||||
|
|
||||||
GArray *texture_pool;
|
GArray *texture_pool;
|
||||||
GHashTable *textures;
|
GHashTable *textures;
|
||||||
GHashTable *key_to_texture_id;
|
GHashTable *key_to_texture_id;
|
||||||
GHashTable *texture_id_to_key;
|
GHashTable *texture_id_to_key;
|
||||||
|
|
||||||
GPtrArray *atlases;
|
|
||||||
|
|
||||||
GHashTable *shader_cache;
|
GHashTable *shader_cache;
|
||||||
|
|
||||||
GArray *autorelease_framebuffers;
|
GArray *autorelease_framebuffers;
|
||||||
@ -184,7 +182,6 @@ void gsk_gl_driver_add_texture_slices (GskGLDriver *s
|
|||||||
GskGLProgram * gsk_gl_driver_lookup_shader (GskGLDriver *self,
|
GskGLProgram * gsk_gl_driver_lookup_shader (GskGLDriver *self,
|
||||||
GskGLShader *shader,
|
GskGLShader *shader,
|
||||||
GError **error);
|
GError **error);
|
||||||
GskGLTextureAtlas * gsk_gl_driver_create_atlas (GskGLDriver *self);
|
|
||||||
|
|
||||||
#ifdef G_ENABLE_DEBUG
|
#ifdef G_ENABLE_DEBUG
|
||||||
void gsk_gl_driver_save_atlases_to_png (GskGLDriver *self,
|
void gsk_gl_driver_save_atlases_to_png (GskGLDriver *self,
|
||||||
|
@ -84,15 +84,64 @@ gsk_gl_glyph_value_free (gpointer data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gsk_gl_glyph_library_begin_frame (GskGLTextureLibrary *library,
|
gsk_gl_glyph_library_clear_cache (GskGLTextureLibrary *library)
|
||||||
gint64 frame_id,
|
|
||||||
GPtrArray *removed_atlases)
|
|
||||||
{
|
{
|
||||||
GskGLGlyphLibrary *self = (GskGLGlyphLibrary *)library;
|
GskGLGlyphLibrary *self = (GskGLGlyphLibrary *)library;
|
||||||
|
|
||||||
|
g_assert (GSK_IS_GL_GLYPH_LIBRARY (self));
|
||||||
|
|
||||||
memset (self->front, 0, sizeof self->front);
|
memset (self->front, 0, sizeof self->front);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsk_gl_glyph_library_init_atlas (GskGLTextureLibrary *self,
|
||||||
|
GskGLTextureAtlas *atlas)
|
||||||
|
{
|
||||||
|
gboolean packed G_GNUC_UNUSED;
|
||||||
|
int x, y;
|
||||||
|
guint gl_format;
|
||||||
|
guint gl_type;
|
||||||
|
guint8 pixel_data[4 * 3 * 3];
|
||||||
|
|
||||||
|
g_assert (GSK_IS_GL_GLYPH_LIBRARY (self));
|
||||||
|
g_assert (atlas != NULL);
|
||||||
|
|
||||||
|
/* Insert a single pixel at 0,0 for use in coloring */
|
||||||
|
|
||||||
|
gdk_gl_context_push_debug_group_printf (gdk_gl_context_get_current (),
|
||||||
|
"Initializing Atlas");
|
||||||
|
|
||||||
|
packed = gsk_gl_texture_library_allocate (self, atlas, 3, 3, &x, &y);
|
||||||
|
g_assert (packed);
|
||||||
|
g_assert (x == 0 && y == 0);
|
||||||
|
|
||||||
|
memset (pixel_data, 255, sizeof pixel_data);
|
||||||
|
|
||||||
|
if (gdk_gl_context_get_use_es (gdk_gl_context_get_current ()))
|
||||||
|
{
|
||||||
|
gl_format = GL_RGBA;
|
||||||
|
gl_type = GL_UNSIGNED_BYTE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gl_format = GL_BGRA;
|
||||||
|
gl_type = GL_UNSIGNED_INT_8_8_8_8_REV;
|
||||||
|
}
|
||||||
|
|
||||||
|
glBindTexture (GL_TEXTURE_2D, atlas->texture_id);
|
||||||
|
|
||||||
|
glTexSubImage2D (GL_TEXTURE_2D, 0,
|
||||||
|
0, 0,
|
||||||
|
3, 3,
|
||||||
|
gl_format, gl_type,
|
||||||
|
pixel_data);
|
||||||
|
|
||||||
|
gdk_gl_context_pop_debug_group (gdk_gl_context_get_current ());
|
||||||
|
|
||||||
|
self->driver->command_queue->n_uploads++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gsk_gl_glyph_library_finalize (GObject *object)
|
gsk_gl_glyph_library_finalize (GObject *object)
|
||||||
{
|
{
|
||||||
@ -111,7 +160,8 @@ gsk_gl_glyph_library_class_init (GskGLGlyphLibraryClass *klass)
|
|||||||
|
|
||||||
object_class->finalize = gsk_gl_glyph_library_finalize;
|
object_class->finalize = gsk_gl_glyph_library_finalize;
|
||||||
|
|
||||||
library_class->begin_frame = gsk_gl_glyph_library_begin_frame;
|
library_class->clear_cache = gsk_gl_glyph_library_clear_cache;
|
||||||
|
library_class->init_atlas = gsk_gl_glyph_library_init_atlas;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -1,71 +1,71 @@
|
|||||||
GSK_GL_DEFINE_PROGRAM (blend,
|
GSK_GL_DEFINE_PROGRAM (blend,
|
||||||
"/org/gtk/libgsk/gl/blend.glsl",
|
GSK_GL_SHADER_SINGLE (GSK_GL_SHADER_RESOURCE ("blend.glsl")),
|
||||||
GSK_GL_ADD_UNIFORM (1, BLEND_SOURCE2, u_source2)
|
GSK_GL_ADD_UNIFORM (1, BLEND_SOURCE2, u_source2)
|
||||||
GSK_GL_ADD_UNIFORM (2, BLEND_MODE, u_mode))
|
GSK_GL_ADD_UNIFORM (2, BLEND_MODE, u_mode))
|
||||||
|
|
||||||
GSK_GL_DEFINE_PROGRAM (blit,
|
GSK_GL_DEFINE_PROGRAM (blit,
|
||||||
"/org/gtk/libgsk/gl/blit.glsl",
|
GSK_GL_SHADER_SINGLE (GSK_GL_SHADER_RESOURCE ("blit.glsl")),
|
||||||
GSK_GL_NO_UNIFORMS)
|
GSK_GL_NO_UNIFORMS)
|
||||||
|
|
||||||
GSK_GL_DEFINE_PROGRAM (blur,
|
GSK_GL_DEFINE_PROGRAM (blur,
|
||||||
"/org/gtk/libgsk/gl/blur.glsl",
|
GSK_GL_SHADER_SINGLE (GSK_GL_SHADER_RESOURCE ("blur.glsl")),
|
||||||
GSK_GL_ADD_UNIFORM (1, BLUR_RADIUS, u_blur_radius)
|
GSK_GL_ADD_UNIFORM (1, BLUR_RADIUS, u_blur_radius)
|
||||||
GSK_GL_ADD_UNIFORM (2, BLUR_SIZE, u_blur_size)
|
GSK_GL_ADD_UNIFORM (2, BLUR_SIZE, u_blur_size)
|
||||||
GSK_GL_ADD_UNIFORM (3, BLUR_DIR, u_blur_dir))
|
GSK_GL_ADD_UNIFORM (3, BLUR_DIR, u_blur_dir))
|
||||||
|
|
||||||
GSK_GL_DEFINE_PROGRAM (border,
|
GSK_GL_DEFINE_PROGRAM (border,
|
||||||
"/org/gtk/libgsk/gl/border.glsl",
|
GSK_GL_SHADER_SINGLE (GSK_GL_SHADER_RESOURCE ("border.glsl")),
|
||||||
GSK_GL_ADD_UNIFORM (1, BORDER_WIDTHS, u_widths)
|
GSK_GL_ADD_UNIFORM (1, BORDER_WIDTHS, u_widths)
|
||||||
GSK_GL_ADD_UNIFORM (2, BORDER_OUTLINE_RECT, u_outline_rect))
|
GSK_GL_ADD_UNIFORM (2, BORDER_OUTLINE_RECT, u_outline_rect))
|
||||||
|
|
||||||
GSK_GL_DEFINE_PROGRAM (color,
|
GSK_GL_DEFINE_PROGRAM (color,
|
||||||
"/org/gtk/libgsk/gl/color.glsl",
|
GSK_GL_SHADER_SINGLE (GSK_GL_SHADER_RESOURCE ("color.glsl")),
|
||||||
GSK_GL_NO_UNIFORMS)
|
GSK_GL_NO_UNIFORMS)
|
||||||
|
|
||||||
GSK_GL_DEFINE_PROGRAM (coloring,
|
GSK_GL_DEFINE_PROGRAM (coloring,
|
||||||
"/org/gtk/libgsk/gl/coloring.glsl",
|
GSK_GL_SHADER_SINGLE (GSK_GL_SHADER_RESOURCE ("coloring.glsl")),
|
||||||
GSK_GL_NO_UNIFORMS)
|
GSK_GL_NO_UNIFORMS)
|
||||||
|
|
||||||
GSK_GL_DEFINE_PROGRAM (color_matrix,
|
GSK_GL_DEFINE_PROGRAM (color_matrix,
|
||||||
"/org/gtk/libgsk/gl/color_matrix.glsl",
|
GSK_GL_SHADER_SINGLE (GSK_GL_SHADER_RESOURCE ("color_matrix.glsl")),
|
||||||
GSK_GL_ADD_UNIFORM (1, COLOR_MATRIX_COLOR_MATRIX, u_color_matrix)
|
GSK_GL_ADD_UNIFORM (1, COLOR_MATRIX_COLOR_MATRIX, u_color_matrix)
|
||||||
GSK_GL_ADD_UNIFORM (2, COLOR_MATRIX_COLOR_OFFSET, u_color_offset))
|
GSK_GL_ADD_UNIFORM (2, COLOR_MATRIX_COLOR_OFFSET, u_color_offset))
|
||||||
|
|
||||||
GSK_GL_DEFINE_PROGRAM (conic_gradient,
|
GSK_GL_DEFINE_PROGRAM (conic_gradient,
|
||||||
"/org/gtk/libgsk/gl/conic_gradient.glsl",
|
GSK_GL_SHADER_SINGLE (GSK_GL_SHADER_RESOURCE ("conic_gradient.glsl")),
|
||||||
GSK_GL_ADD_UNIFORM (1, CONIC_GRADIENT_COLOR_STOPS, u_color_stops)
|
GSK_GL_ADD_UNIFORM (1, CONIC_GRADIENT_COLOR_STOPS, u_color_stops)
|
||||||
GSK_GL_ADD_UNIFORM (2, CONIC_GRADIENT_NUM_COLOR_STOPS, u_num_color_stops)
|
GSK_GL_ADD_UNIFORM (2, CONIC_GRADIENT_NUM_COLOR_STOPS, u_num_color_stops)
|
||||||
GSK_GL_ADD_UNIFORM (3, CONIC_GRADIENT_GEOMETRY, u_geometry))
|
GSK_GL_ADD_UNIFORM (3, CONIC_GRADIENT_GEOMETRY, u_geometry))
|
||||||
|
|
||||||
GSK_GL_DEFINE_PROGRAM (cross_fade,
|
GSK_GL_DEFINE_PROGRAM (cross_fade,
|
||||||
"/org/gtk/libgsk/gl/cross_fade.glsl",
|
GSK_GL_SHADER_SINGLE (GSK_GL_SHADER_RESOURCE ("cross_fade.glsl")),
|
||||||
GSK_GL_ADD_UNIFORM (1, CROSS_FADE_PROGRESS, u_progress)
|
GSK_GL_ADD_UNIFORM (1, CROSS_FADE_PROGRESS, u_progress)
|
||||||
GSK_GL_ADD_UNIFORM (2, CROSS_FADE_SOURCE2, u_source2))
|
GSK_GL_ADD_UNIFORM (2, CROSS_FADE_SOURCE2, u_source2))
|
||||||
|
|
||||||
GSK_GL_DEFINE_PROGRAM (filled_border,
|
GSK_GL_DEFINE_PROGRAM (filled_border,
|
||||||
"/org/gtk/libgsk/gl/filled_border.glsl",
|
GSK_GL_SHADER_SINGLE (GSK_GL_SHADER_RESOURCE ("filled_border.glsl")),
|
||||||
GSK_GL_ADD_UNIFORM (1, FILLED_BORDER_WIDTHS, u_widths)
|
GSK_GL_ADD_UNIFORM (1, FILLED_BORDER_WIDTHS, u_widths)
|
||||||
GSK_GL_ADD_UNIFORM (2, FILLED_BORDER_OUTLINE_RECT, u_outline_rect))
|
GSK_GL_ADD_UNIFORM (2, FILLED_BORDER_OUTLINE_RECT, u_outline_rect))
|
||||||
|
|
||||||
GSK_GL_DEFINE_PROGRAM (inset_shadow,
|
GSK_GL_DEFINE_PROGRAM (inset_shadow,
|
||||||
"/org/gtk/libgsk/gl/inset_shadow.glsl",
|
GSK_GL_SHADER_SINGLE (GSK_GL_SHADER_RESOURCE ("inset_shadow.glsl")),
|
||||||
GSK_GL_ADD_UNIFORM (1, INSET_SHADOW_SPREAD, u_spread)
|
GSK_GL_ADD_UNIFORM (1, INSET_SHADOW_SPREAD, u_spread)
|
||||||
GSK_GL_ADD_UNIFORM (2, INSET_SHADOW_OFFSET, u_offset)
|
GSK_GL_ADD_UNIFORM (2, INSET_SHADOW_OFFSET, u_offset)
|
||||||
GSK_GL_ADD_UNIFORM (3, INSET_SHADOW_OUTLINE_RECT, u_outline_rect))
|
GSK_GL_ADD_UNIFORM (3, INSET_SHADOW_OUTLINE_RECT, u_outline_rect))
|
||||||
|
|
||||||
GSK_GL_DEFINE_PROGRAM (linear_gradient,
|
GSK_GL_DEFINE_PROGRAM (linear_gradient,
|
||||||
"/org/gtk/libgsk/gl/linear_gradient.glsl",
|
GSK_GL_SHADER_SINGLE (GSK_GL_SHADER_RESOURCE ("linear_gradient.glsl")),
|
||||||
GSK_GL_ADD_UNIFORM (1, LINEAR_GRADIENT_COLOR_STOPS, u_color_stops)
|
GSK_GL_ADD_UNIFORM (1, LINEAR_GRADIENT_COLOR_STOPS, u_color_stops)
|
||||||
GSK_GL_ADD_UNIFORM (2, LINEAR_GRADIENT_NUM_COLOR_STOPS, u_num_color_stops)
|
GSK_GL_ADD_UNIFORM (2, LINEAR_GRADIENT_NUM_COLOR_STOPS, u_num_color_stops)
|
||||||
GSK_GL_ADD_UNIFORM (3, LINEAR_GRADIENT_POINTS, u_points)
|
GSK_GL_ADD_UNIFORM (3, LINEAR_GRADIENT_POINTS, u_points)
|
||||||
GSK_GL_ADD_UNIFORM (4, LINEAR_GRADIENT_REPEAT, u_repeat))
|
GSK_GL_ADD_UNIFORM (4, LINEAR_GRADIENT_REPEAT, u_repeat))
|
||||||
|
|
||||||
GSK_GL_DEFINE_PROGRAM (outset_shadow,
|
GSK_GL_DEFINE_PROGRAM (outset_shadow,
|
||||||
"/org/gtk/libgsk/gl/outset_shadow.glsl",
|
GSK_GL_SHADER_SINGLE (GSK_GL_SHADER_RESOURCE ("outset_shadow.glsl")),
|
||||||
GSK_GL_ADD_UNIFORM (1, OUTSET_SHADOW_OUTLINE_RECT, u_outline_rect))
|
GSK_GL_ADD_UNIFORM (1, OUTSET_SHADOW_OUTLINE_RECT, u_outline_rect))
|
||||||
|
|
||||||
GSK_GL_DEFINE_PROGRAM (radial_gradient,
|
GSK_GL_DEFINE_PROGRAM (radial_gradient,
|
||||||
"/org/gtk/libgsk/gl/radial_gradient.glsl",
|
GSK_GL_SHADER_SINGLE (GSK_GL_SHADER_RESOURCE ("radial_gradient.glsl")),
|
||||||
GSK_GL_ADD_UNIFORM (1, RADIAL_GRADIENT_COLOR_STOPS, u_color_stops)
|
GSK_GL_ADD_UNIFORM (1, RADIAL_GRADIENT_COLOR_STOPS, u_color_stops)
|
||||||
GSK_GL_ADD_UNIFORM (2, RADIAL_GRADIENT_NUM_COLOR_STOPS, u_num_color_stops)
|
GSK_GL_ADD_UNIFORM (2, RADIAL_GRADIENT_NUM_COLOR_STOPS, u_num_color_stops)
|
||||||
GSK_GL_ADD_UNIFORM (3, RADIAL_GRADIENT_REPEAT, u_repeat)
|
GSK_GL_ADD_UNIFORM (3, RADIAL_GRADIENT_REPEAT, u_repeat)
|
||||||
@ -73,12 +73,12 @@ GSK_GL_DEFINE_PROGRAM (radial_gradient,
|
|||||||
GSK_GL_ADD_UNIFORM (5, RADIAL_GRADIENT_GEOMETRY, u_geometry))
|
GSK_GL_ADD_UNIFORM (5, RADIAL_GRADIENT_GEOMETRY, u_geometry))
|
||||||
|
|
||||||
GSK_GL_DEFINE_PROGRAM (repeat,
|
GSK_GL_DEFINE_PROGRAM (repeat,
|
||||||
"/org/gtk/libgsk/gl/repeat.glsl",
|
GSK_GL_SHADER_SINGLE (GSK_GL_SHADER_RESOURCE ("repeat.glsl")),
|
||||||
GSK_GL_ADD_UNIFORM (1, REPEAT_CHILD_BOUNDS, u_child_bounds)
|
GSK_GL_ADD_UNIFORM (1, REPEAT_CHILD_BOUNDS, u_child_bounds)
|
||||||
GSK_GL_ADD_UNIFORM (2, REPEAT_TEXTURE_RECT, u_texture_rect))
|
GSK_GL_ADD_UNIFORM (2, REPEAT_TEXTURE_RECT, u_texture_rect))
|
||||||
|
|
||||||
GSK_GL_DEFINE_PROGRAM (unblurred_outset_shadow,
|
GSK_GL_DEFINE_PROGRAM (unblurred_outset_shadow,
|
||||||
"/org/gtk/libgsk/gl/unblurred_outset_shadow.glsl",
|
GSK_GL_SHADER_SINGLE (GSK_GL_SHADER_RESOURCE ("unblurred_outset_shadow.glsl")),
|
||||||
GSK_GL_ADD_UNIFORM (1, UNBLURRED_OUTSET_SHADOW_SPREAD, u_spread)
|
GSK_GL_ADD_UNIFORM (1, UNBLURRED_OUTSET_SHADOW_SPREAD, u_spread)
|
||||||
GSK_GL_ADD_UNIFORM (2, UNBLURRED_OUTSET_SHADOW_OFFSET, u_offset)
|
GSK_GL_ADD_UNIFORM (2, UNBLURRED_OUTSET_SHADOW_OFFSET, u_offset)
|
||||||
GSK_GL_ADD_UNIFORM (3, UNBLURRED_OUTSET_SHADOW_OUTLINE_RECT, u_outline_rect))
|
GSK_GL_ADD_UNIFORM (3, UNBLURRED_OUTSET_SHADOW_OUTLINE_RECT, u_outline_rect))
|
||||||
|
@ -2512,7 +2512,9 @@ gsk_gl_render_job_visit_blurred_outset_shadow_node (GskGLRenderJob *job,
|
|||||||
scaled_outline.corner[i].height *= scale_y;
|
scaled_outline.corner[i].height *= scale_y;
|
||||||
}
|
}
|
||||||
|
|
||||||
cached_tid = gsk_gl_shadow_library_lookup (job->driver->shadows, &scaled_outline, blur_radius);
|
cached_tid = gsk_gl_shadow_library_lookup (job->driver->shadows_library,
|
||||||
|
&scaled_outline,
|
||||||
|
blur_radius);
|
||||||
|
|
||||||
if (cached_tid == 0)
|
if (cached_tid == 0)
|
||||||
{
|
{
|
||||||
@ -2574,7 +2576,7 @@ gsk_gl_render_job_visit_blurred_outset_shadow_node (GskGLRenderJob *job,
|
|||||||
blur_radius * scale_x,
|
blur_radius * scale_x,
|
||||||
blur_radius * scale_y);
|
blur_radius * scale_y);
|
||||||
|
|
||||||
gsk_gl_shadow_library_insert (job->driver->shadows,
|
gsk_gl_shadow_library_insert (job->driver->shadows_library,
|
||||||
&scaled_outline,
|
&scaled_outline,
|
||||||
blur_radius,
|
blur_radius,
|
||||||
blurred_texture_id);
|
blurred_texture_id);
|
||||||
@ -2996,7 +2998,7 @@ gsk_gl_render_job_visit_text_node (GskGLRenderJob *job,
|
|||||||
guint num_glyphs = gsk_text_node_get_num_glyphs (node);
|
guint num_glyphs = gsk_text_node_get_num_glyphs (node);
|
||||||
float x = offset->x + job->offset_x;
|
float x = offset->x + job->offset_x;
|
||||||
float y = offset->y + job->offset_y;
|
float y = offset->y + job->offset_y;
|
||||||
GskGLGlyphLibrary *library = job->driver->glyphs;
|
GskGLGlyphLibrary *library = job->driver->glyphs_library;
|
||||||
GskGLCommandBatch *batch;
|
GskGLCommandBatch *batch;
|
||||||
int x_position = 0;
|
int x_position = 0;
|
||||||
GskGLGlyphKey lookup;
|
GskGLGlyphKey lookup;
|
||||||
@ -3499,14 +3501,14 @@ gsk_gl_render_job_upload_texture (GskGLRenderJob *job,
|
|||||||
GdkTexture *texture,
|
GdkTexture *texture,
|
||||||
GskGLRenderOffscreen *offscreen)
|
GskGLRenderOffscreen *offscreen)
|
||||||
{
|
{
|
||||||
if (gsk_gl_texture_library_can_cache ((GskGLTextureLibrary *)job->driver->icons,
|
if (gsk_gl_texture_library_can_cache ((GskGLTextureLibrary *)job->driver->icons_library,
|
||||||
texture->width,
|
texture->width,
|
||||||
texture->height) &&
|
texture->height) &&
|
||||||
!GDK_IS_GL_TEXTURE (texture))
|
!GDK_IS_GL_TEXTURE (texture))
|
||||||
{
|
{
|
||||||
const GskGLIconData *icon_data;
|
const GskGLIconData *icon_data;
|
||||||
|
|
||||||
gsk_gl_icon_library_lookup_or_add (job->driver->icons, texture, &icon_data);
|
gsk_gl_icon_library_lookup_or_add (job->driver->icons_library, texture, &icon_data);
|
||||||
offscreen->texture_id = GSK_GL_TEXTURE_ATLAS_ENTRY_TEXTURE (icon_data);
|
offscreen->texture_id = GSK_GL_TEXTURE_ATLAS_ENTRY_TEXTURE (icon_data);
|
||||||
memcpy (&offscreen->area, &icon_data->entry.area, sizeof offscreen->area);
|
memcpy (&offscreen->area, &icon_data->entry.area, sizeof offscreen->area);
|
||||||
}
|
}
|
||||||
|
@ -29,9 +29,9 @@
|
|||||||
|
|
||||||
struct _GskGLShadowLibrary
|
struct _GskGLShadowLibrary
|
||||||
{
|
{
|
||||||
GObject parent_instance;
|
GObject parent_instance;
|
||||||
GskGLDriver *driver;
|
GskGLDriver *driver;
|
||||||
GArray *shadows;
|
GArray *shadows;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct _Shadow
|
typedef struct _Shadow
|
||||||
|
@ -27,7 +27,10 @@
|
|||||||
#include "gskgldriverprivate.h"
|
#include "gskgldriverprivate.h"
|
||||||
#include "gskgltexturelibraryprivate.h"
|
#include "gskgltexturelibraryprivate.h"
|
||||||
|
|
||||||
#define MAX_FRAME_AGE 60
|
#define DEFAULT_MAX_FRAME_AGE 60
|
||||||
|
#define DEFAULT_ATLAS_WIDTH 512
|
||||||
|
#define DEFAULT_ATLAS_HEIGHT 512
|
||||||
|
#define MAX_OLD_RATIO 0.5
|
||||||
|
|
||||||
G_DEFINE_ABSTRACT_TYPE (GskGLTextureLibrary, gsk_gl_texture_library, G_TYPE_OBJECT)
|
G_DEFINE_ABSTRACT_TYPE (GskGLTextureLibrary, gsk_gl_texture_library, G_TYPE_OBJECT)
|
||||||
|
|
||||||
@ -39,6 +42,143 @@ enum {
|
|||||||
|
|
||||||
static GParamSpec *properties [N_PROPS];
|
static GParamSpec *properties [N_PROPS];
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsk_gl_texture_atlas_free (GskGLTextureAtlas *atlas)
|
||||||
|
{
|
||||||
|
if (atlas->texture_id != 0)
|
||||||
|
{
|
||||||
|
glDeleteTextures (1, &atlas->texture_id);
|
||||||
|
atlas->texture_id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_clear_pointer (&atlas->nodes, g_free);
|
||||||
|
g_slice_free (GskGLTextureAtlas, atlas);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gsk_gl_texture_library_real_compact (GskGLTextureLibrary *self,
|
||||||
|
gint64 frame_id)
|
||||||
|
{
|
||||||
|
GPtrArray *removed = NULL;
|
||||||
|
gboolean ret = FALSE;
|
||||||
|
gboolean periodic_scan;
|
||||||
|
|
||||||
|
g_assert (GSK_IS_GL_TEXTURE_LIBRARY (self));
|
||||||
|
|
||||||
|
periodic_scan = (self->max_frame_age > 0 &&
|
||||||
|
(frame_id % self->max_frame_age) == 0);
|
||||||
|
|
||||||
|
for (guint i = self->atlases->len; i > 0; i--)
|
||||||
|
{
|
||||||
|
GskGLTextureAtlas *atlas = g_ptr_array_index (self->atlases, i - 1);
|
||||||
|
|
||||||
|
if (gsk_gl_texture_atlas_get_unused_ratio (atlas) > MAX_OLD_RATIO)
|
||||||
|
{
|
||||||
|
GSK_NOTE (GLYPH_CACHE,
|
||||||
|
g_message ("Dropping atlas %d (%g.2%% old)", i,
|
||||||
|
100.0 * gsk_gl_texture_atlas_get_unused_ratio (atlas)));
|
||||||
|
if (removed == NULL)
|
||||||
|
removed = g_ptr_array_new_with_free_func ((GDestroyNotify)gsk_gl_texture_atlas_free);
|
||||||
|
g_ptr_array_add (removed, g_ptr_array_steal_index (self->atlases, i - 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (periodic_scan || removed != NULL)
|
||||||
|
{
|
||||||
|
GskGLTextureAtlasEntry *entry;
|
||||||
|
GHashTableIter iter;
|
||||||
|
guint dropped = 0;
|
||||||
|
guint atlased = 0;
|
||||||
|
|
||||||
|
g_hash_table_iter_init (&iter, self->hash_table);
|
||||||
|
while (g_hash_table_iter_next (&iter, NULL, (gpointer *)&entry))
|
||||||
|
{
|
||||||
|
if (entry->is_atlased)
|
||||||
|
{
|
||||||
|
if (removed && g_ptr_array_find (removed, entry->atlas, NULL))
|
||||||
|
{
|
||||||
|
g_hash_table_iter_remove (&iter);
|
||||||
|
dropped++;
|
||||||
|
}
|
||||||
|
else if (periodic_scan)
|
||||||
|
{
|
||||||
|
gsk_gl_texture_atlas_entry_mark_unused (entry);
|
||||||
|
entry->accessed = FALSE;
|
||||||
|
if (entry->is_atlased)
|
||||||
|
atlased++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!entry->accessed)
|
||||||
|
{
|
||||||
|
gsk_gl_driver_release_texture (self->driver, entry->texture);
|
||||||
|
g_hash_table_iter_remove (&iter);
|
||||||
|
dropped++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GSK_NOTE (GLYPH_CACHE, g_message ("%s: Dropped %d individual items",
|
||||||
|
G_OBJECT_TYPE_NAME (self),
|
||||||
|
dropped);
|
||||||
|
g_message ("%s: %d items cached (%d atlased, %d individually)",
|
||||||
|
G_OBJECT_TYPE_NAME (self),
|
||||||
|
g_hash_table_size (self->hash_table),
|
||||||
|
atlased,
|
||||||
|
g_hash_table_size (self->hash_table) - atlased));
|
||||||
|
|
||||||
|
if (dropped > 0)
|
||||||
|
gsk_gl_texture_library_clear_cache (self);
|
||||||
|
|
||||||
|
ret = TRUE;
|
||||||
|
|
||||||
|
g_clear_pointer (&removed, g_ptr_array_unref);
|
||||||
|
}
|
||||||
|
|
||||||
|
GSK_NOTE (GLYPH_CACHE, {
|
||||||
|
static gint64 last_message;
|
||||||
|
gint64 now = g_get_monotonic_time ();
|
||||||
|
if (now - last_message > G_USEC_PER_SEC)
|
||||||
|
{
|
||||||
|
last_message = now;
|
||||||
|
g_message ("%s contains %d atlases",
|
||||||
|
G_OBJECT_TYPE_NAME (self),
|
||||||
|
self->atlases->len);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gsk_gl_texture_library_real_allocate (GskGLTextureLibrary *self,
|
||||||
|
GskGLTextureAtlas *atlas,
|
||||||
|
int width,
|
||||||
|
int height,
|
||||||
|
int *out_x,
|
||||||
|
int *out_y)
|
||||||
|
{
|
||||||
|
stbrp_rect rect;
|
||||||
|
|
||||||
|
g_assert (GSK_IS_GL_TEXTURE_LIBRARY (self));
|
||||||
|
g_assert (atlas != NULL);
|
||||||
|
g_assert (width > 0);
|
||||||
|
g_assert (height > 0);
|
||||||
|
g_assert (out_x != NULL);
|
||||||
|
g_assert (out_y != NULL);
|
||||||
|
|
||||||
|
rect.w = width;
|
||||||
|
rect.h = height;
|
||||||
|
|
||||||
|
stbrp_pack_rects (&atlas->context, &rect, 1);
|
||||||
|
|
||||||
|
if (rect.was_packed)
|
||||||
|
{
|
||||||
|
*out_x = rect.x;
|
||||||
|
*out_y = rect.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rect.was_packed;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gsk_gl_texture_library_constructed (GObject *object)
|
gsk_gl_texture_library_constructed (GObject *object)
|
||||||
{
|
{
|
||||||
@ -52,6 +192,7 @@ gsk_gl_texture_library_dispose (GObject *object)
|
|||||||
{
|
{
|
||||||
GskGLTextureLibrary *self = (GskGLTextureLibrary *)object;
|
GskGLTextureLibrary *self = (GskGLTextureLibrary *)object;
|
||||||
|
|
||||||
|
g_clear_pointer (&self->atlases, g_ptr_array_unref);
|
||||||
g_clear_object (&self->driver);
|
g_clear_object (&self->driver);
|
||||||
|
|
||||||
G_OBJECT_CLASS (gsk_gl_texture_library_parent_class)->dispose (object);
|
G_OBJECT_CLASS (gsk_gl_texture_library_parent_class)->dispose (object);
|
||||||
@ -105,6 +246,9 @@ gsk_gl_texture_library_class_init (GskGLTextureLibraryClass *klass)
|
|||||||
object_class->get_property = gsk_gl_texture_library_get_property;
|
object_class->get_property = gsk_gl_texture_library_get_property;
|
||||||
object_class->set_property = gsk_gl_texture_library_set_property;
|
object_class->set_property = gsk_gl_texture_library_set_property;
|
||||||
|
|
||||||
|
klass->compact = gsk_gl_texture_library_real_compact;
|
||||||
|
klass->allocate = gsk_gl_texture_library_real_allocate;
|
||||||
|
|
||||||
properties [PROP_DRIVER] =
|
properties [PROP_DRIVER] =
|
||||||
g_param_spec_object ("driver",
|
g_param_spec_object ("driver",
|
||||||
"Driver",
|
"Driver",
|
||||||
@ -118,6 +262,10 @@ gsk_gl_texture_library_class_init (GskGLTextureLibraryClass *klass)
|
|||||||
static void
|
static void
|
||||||
gsk_gl_texture_library_init (GskGLTextureLibrary *self)
|
gsk_gl_texture_library_init (GskGLTextureLibrary *self)
|
||||||
{
|
{
|
||||||
|
self->max_frame_age = DEFAULT_MAX_FRAME_AGE;
|
||||||
|
self->atlas_width = DEFAULT_ATLAS_WIDTH;
|
||||||
|
self->atlas_height = DEFAULT_ATLAS_HEIGHT;
|
||||||
|
self->atlases = g_ptr_array_new_with_free_func ((GDestroyNotify)gsk_gl_texture_atlas_free);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -136,78 +284,14 @@ gsk_gl_texture_library_set_funcs (GskGLTextureLibrary *self,
|
|||||||
|
|
||||||
void
|
void
|
||||||
gsk_gl_texture_library_begin_frame (GskGLTextureLibrary *self,
|
gsk_gl_texture_library_begin_frame (GskGLTextureLibrary *self,
|
||||||
gint64 frame_id,
|
gint64 frame_id)
|
||||||
GPtrArray *removed_atlases)
|
|
||||||
{
|
{
|
||||||
GHashTableIter iter;
|
|
||||||
|
|
||||||
g_return_if_fail (GSK_IS_GL_TEXTURE_LIBRARY (self));
|
g_return_if_fail (GSK_IS_GL_TEXTURE_LIBRARY (self));
|
||||||
|
|
||||||
|
gsk_gl_texture_library_compact (self, frame_id);
|
||||||
|
|
||||||
if (GSK_GL_TEXTURE_LIBRARY_GET_CLASS (self)->begin_frame)
|
if (GSK_GL_TEXTURE_LIBRARY_GET_CLASS (self)->begin_frame)
|
||||||
GSK_GL_TEXTURE_LIBRARY_GET_CLASS (self)->begin_frame (self, frame_id, removed_atlases);
|
GSK_GL_TEXTURE_LIBRARY_GET_CLASS (self)->begin_frame (self, frame_id);
|
||||||
|
|
||||||
if (removed_atlases != NULL)
|
|
||||||
{
|
|
||||||
GskGLTextureAtlasEntry *entry;
|
|
||||||
guint dropped = 0;
|
|
||||||
|
|
||||||
g_hash_table_iter_init (&iter, self->hash_table);
|
|
||||||
while (g_hash_table_iter_next (&iter, NULL, (gpointer *)&entry))
|
|
||||||
{
|
|
||||||
if (entry->is_atlased)
|
|
||||||
{
|
|
||||||
for (guint i = 0; i < removed_atlases->len; i++)
|
|
||||||
{
|
|
||||||
GskGLTextureAtlas *atlas = g_ptr_array_index (removed_atlases, i);
|
|
||||||
|
|
||||||
if (atlas == entry->atlas)
|
|
||||||
{
|
|
||||||
g_hash_table_iter_remove (&iter);
|
|
||||||
dropped++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
GSK_NOTE (GLYPH_CACHE,
|
|
||||||
if (dropped > 0)
|
|
||||||
g_message ("%s: Dropped %d items",
|
|
||||||
G_OBJECT_TYPE_NAME (self), dropped));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (frame_id % MAX_FRAME_AGE == 0)
|
|
||||||
{
|
|
||||||
GskGLTextureAtlasEntry *entry;
|
|
||||||
int atlased = 0;
|
|
||||||
int dropped = 0;
|
|
||||||
|
|
||||||
g_hash_table_iter_init (&iter, self->hash_table);
|
|
||||||
while (g_hash_table_iter_next (&iter, NULL, (gpointer *)&entry))
|
|
||||||
{
|
|
||||||
if (!entry->is_atlased && !entry->accessed)
|
|
||||||
{
|
|
||||||
gsk_gl_driver_release_texture (self->driver, entry->texture);
|
|
||||||
g_hash_table_iter_remove (&iter);
|
|
||||||
dropped++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
gsk_gl_texture_atlas_entry_mark_unused (entry);
|
|
||||||
entry->accessed = FALSE;
|
|
||||||
if (entry->is_atlased)
|
|
||||||
atlased++;
|
|
||||||
}
|
|
||||||
|
|
||||||
GSK_NOTE (GLYPH_CACHE, g_message ("%s: Dropped %d individual items",
|
|
||||||
G_OBJECT_TYPE_NAME (self),
|
|
||||||
dropped);
|
|
||||||
g_message ("%s: %d items cached (%d atlased, %d individually)",
|
|
||||||
G_OBJECT_TYPE_NAME (self),
|
|
||||||
g_hash_table_size (self->hash_table),
|
|
||||||
atlased,
|
|
||||||
g_hash_table_size (self->hash_table) - atlased));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static GskGLTexture *
|
static GskGLTexture *
|
||||||
@ -234,90 +318,29 @@ gsk_gl_texture_library_pack_one (GskGLTextureLibrary *self,
|
|||||||
return texture;
|
return texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline gboolean
|
|
||||||
gsk_gl_texture_atlas_pack (GskGLTextureAtlas *self,
|
|
||||||
int width,
|
|
||||||
int height,
|
|
||||||
int *out_x,
|
|
||||||
int *out_y)
|
|
||||||
{
|
|
||||||
stbrp_rect rect;
|
|
||||||
|
|
||||||
rect.w = width;
|
|
||||||
rect.h = height;
|
|
||||||
|
|
||||||
stbrp_pack_rects (&self->context, &rect, 1);
|
|
||||||
|
|
||||||
if (rect.was_packed)
|
|
||||||
{
|
|
||||||
*out_x = rect.x;
|
|
||||||
*out_y = rect.y;
|
|
||||||
}
|
|
||||||
|
|
||||||
return rect.was_packed;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gsk_gl_texture_atlas_initialize (GskGLDriver *driver,
|
gsk_gl_texture_library_pack_any_atlas (GskGLTextureLibrary *self,
|
||||||
GskGLTextureAtlas *atlas)
|
int width,
|
||||||
{
|
int height,
|
||||||
/* Insert a single pixel at 0,0 for use in coloring */
|
GskGLTextureAtlas **out_atlas,
|
||||||
|
int *out_x,
|
||||||
gboolean packed G_GNUC_UNUSED;
|
int *out_y)
|
||||||
int x, y;
|
|
||||||
guint gl_format;
|
|
||||||
guint gl_type;
|
|
||||||
guint8 pixel_data[4 * 3 * 3];
|
|
||||||
|
|
||||||
gdk_gl_context_push_debug_group_printf (gdk_gl_context_get_current (),
|
|
||||||
"Initializing Atlas");
|
|
||||||
|
|
||||||
packed = gsk_gl_texture_atlas_pack (atlas, 3, 3, &x, &y);
|
|
||||||
g_assert (packed);
|
|
||||||
g_assert (x == 0 && y == 0);
|
|
||||||
|
|
||||||
memset (pixel_data, 255, sizeof pixel_data);
|
|
||||||
|
|
||||||
if (gdk_gl_context_get_use_es (gdk_gl_context_get_current ()))
|
|
||||||
{
|
|
||||||
gl_format = GL_RGBA;
|
|
||||||
gl_type = GL_UNSIGNED_BYTE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
gl_format = GL_BGRA;
|
|
||||||
gl_type = GL_UNSIGNED_INT_8_8_8_8_REV;
|
|
||||||
}
|
|
||||||
|
|
||||||
glBindTexture (GL_TEXTURE_2D, atlas->texture_id);
|
|
||||||
|
|
||||||
glTexSubImage2D (GL_TEXTURE_2D, 0,
|
|
||||||
0, 0,
|
|
||||||
3, 3,
|
|
||||||
gl_format, gl_type,
|
|
||||||
pixel_data);
|
|
||||||
|
|
||||||
gdk_gl_context_pop_debug_group (gdk_gl_context_get_current ());
|
|
||||||
|
|
||||||
driver->command_queue->n_uploads++;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
gsk_gl_texture_atlases_pack (GskGLDriver *driver,
|
|
||||||
int width,
|
|
||||||
int height,
|
|
||||||
GskGLTextureAtlas **out_atlas,
|
|
||||||
int *out_x,
|
|
||||||
int *out_y)
|
|
||||||
{
|
{
|
||||||
GskGLTextureAtlas *atlas = NULL;
|
GskGLTextureAtlas *atlas = NULL;
|
||||||
int x, y;
|
int x, y;
|
||||||
|
|
||||||
for (guint i = 0; i < driver->atlases->len; i++)
|
g_assert (GSK_IS_GL_TEXTURE_LIBRARY (self));
|
||||||
{
|
g_assert (width > 0);
|
||||||
atlas = g_ptr_array_index (driver->atlases, i);
|
g_assert (height > 0);
|
||||||
|
g_assert (out_atlas != NULL);
|
||||||
|
g_assert (out_x != NULL);
|
||||||
|
g_assert (out_y != NULL);
|
||||||
|
|
||||||
if (gsk_gl_texture_atlas_pack (atlas, width, height, &x, &y))
|
for (guint i = 0; i < self->atlases->len; i++)
|
||||||
|
{
|
||||||
|
atlas = g_ptr_array_index (self->atlases, i);
|
||||||
|
|
||||||
|
if (gsk_gl_texture_library_allocate (self, atlas, width, height, &x, &y))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
atlas = NULL;
|
atlas = NULL;
|
||||||
@ -326,12 +349,10 @@ gsk_gl_texture_atlases_pack (GskGLDriver *driver,
|
|||||||
if (atlas == NULL)
|
if (atlas == NULL)
|
||||||
{
|
{
|
||||||
/* No atlas has enough space, so create a new one... */
|
/* No atlas has enough space, so create a new one... */
|
||||||
atlas = gsk_gl_driver_create_atlas (driver);
|
atlas = gsk_gl_texture_library_acquire_atlas (self);
|
||||||
|
|
||||||
gsk_gl_texture_atlas_initialize (driver, atlas);
|
|
||||||
|
|
||||||
/* Pack it onto that one, which surely has enough space... */
|
/* Pack it onto that one, which surely has enough space... */
|
||||||
if (!gsk_gl_texture_atlas_pack (atlas, width, height, &x, &y))
|
if (!gsk_gl_texture_library_allocate (self, atlas, width, height, &x, &y))
|
||||||
g_assert_not_reached ();
|
g_assert_not_reached ();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -380,17 +401,19 @@ gsk_gl_texture_library_pack (GskGLTextureLibrary *self,
|
|||||||
*out_packed_x = 0;
|
*out_packed_x = 0;
|
||||||
*out_packed_y = 0;
|
*out_packed_y = 0;
|
||||||
}
|
}
|
||||||
else if (width <= self->max_entry_size && height <= self->max_entry_size)
|
else if (self->max_entry_size == 0 ||
|
||||||
|
(width <= self->max_entry_size &&
|
||||||
|
height <= self->max_entry_size))
|
||||||
{
|
{
|
||||||
int packed_x;
|
int packed_x;
|
||||||
int packed_y;
|
int packed_y;
|
||||||
|
|
||||||
gsk_gl_texture_atlases_pack (self->driver,
|
gsk_gl_texture_library_pack_any_atlas (self,
|
||||||
padding + width + padding,
|
padding + width + padding,
|
||||||
padding + height + padding,
|
padding + height + padding,
|
||||||
&atlas,
|
&atlas,
|
||||||
&packed_x,
|
&packed_x,
|
||||||
&packed_y);
|
&packed_y);
|
||||||
|
|
||||||
entry->atlas = atlas;
|
entry->atlas = atlas;
|
||||||
entry->is_atlased = TRUE;
|
entry->is_atlased = TRUE;
|
||||||
@ -424,3 +447,134 @@ gsk_gl_texture_library_pack (GskGLTextureLibrary *self,
|
|||||||
|
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* gsk_gl_texture_library_clear_cache:
|
||||||
|
*
|
||||||
|
* Clear the front cache if the texture library is using one. For
|
||||||
|
* example the glyph cache would drop it's front cache to force
|
||||||
|
* next lookups to fall through to the GHashTable key lookup.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
gsk_gl_texture_library_clear_cache (GskGLTextureLibrary *self)
|
||||||
|
{
|
||||||
|
g_return_if_fail (GSK_IS_GL_TEXTURE_LIBRARY (self));
|
||||||
|
|
||||||
|
if (GSK_GL_TEXTURE_LIBRARY_GET_CLASS (self)->clear_cache)
|
||||||
|
GSK_GL_TEXTURE_LIBRARY_GET_CLASS (self)->clear_cache (self);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* gsk_gl_texture_library_compact:
|
||||||
|
*
|
||||||
|
* Requests that the texture library compact it's altases. That
|
||||||
|
* generally means to traverse them to look for unused pixels over
|
||||||
|
* a certain threshold and release them if necessary.
|
||||||
|
*
|
||||||
|
* Returns: %TRUE if any compaction occurred.
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
gsk_gl_texture_library_compact (GskGLTextureLibrary *self,
|
||||||
|
gint64 frame_id)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (GSK_IS_GL_TEXTURE_LIBRARY (self), FALSE);
|
||||||
|
|
||||||
|
if (GSK_GL_TEXTURE_LIBRARY_GET_CLASS (self)->compact)
|
||||||
|
return GSK_GL_TEXTURE_LIBRARY_GET_CLASS (self)->compact (self, frame_id);
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gsk_gl_texture_library_reset (GskGLTextureLibrary *self)
|
||||||
|
{
|
||||||
|
g_return_if_fail (GSK_IS_GL_TEXTURE_LIBRARY (self));
|
||||||
|
|
||||||
|
gsk_gl_texture_library_clear_cache (self);
|
||||||
|
|
||||||
|
g_hash_table_remove_all (self->hash_table);
|
||||||
|
|
||||||
|
if (self->atlases->len)
|
||||||
|
g_ptr_array_remove_range (self->atlases, 0, self->atlases->len);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gsk_gl_texture_library_set_atlas_size (GskGLTextureLibrary *self,
|
||||||
|
int width,
|
||||||
|
int height)
|
||||||
|
{
|
||||||
|
g_return_if_fail (GSK_IS_GL_TEXTURE_LIBRARY (self));
|
||||||
|
|
||||||
|
if (width <= 0)
|
||||||
|
width = DEFAULT_ATLAS_WIDTH;
|
||||||
|
|
||||||
|
if (height <= 0)
|
||||||
|
height = DEFAULT_ATLAS_HEIGHT;
|
||||||
|
|
||||||
|
self->atlas_height = height;
|
||||||
|
self->atlas_width = width;
|
||||||
|
|
||||||
|
gsk_gl_texture_library_reset (self);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* gsk_gl_texture_library_acquire_atlas:
|
||||||
|
*
|
||||||
|
* Allocates a new texture atlas based on the current size
|
||||||
|
* and format requirements.
|
||||||
|
*/
|
||||||
|
GskGLTextureAtlas *
|
||||||
|
gsk_gl_texture_library_acquire_atlas (GskGLTextureLibrary *self)
|
||||||
|
{
|
||||||
|
GskGLTextureAtlas *atlas;
|
||||||
|
|
||||||
|
g_return_val_if_fail (GSK_IS_GL_TEXTURE_LIBRARY (self), NULL);
|
||||||
|
g_return_val_if_fail (GSK_IS_GL_DRIVER (self->driver), NULL);
|
||||||
|
g_return_val_if_fail (GSK_IS_GL_COMMAND_QUEUE (self->driver->command_queue), NULL);
|
||||||
|
g_return_val_if_fail (self->atlas_width > 0, NULL);
|
||||||
|
g_return_val_if_fail (self->atlas_height > 0, NULL);
|
||||||
|
|
||||||
|
atlas = g_slice_new0 (GskGLTextureAtlas);
|
||||||
|
atlas->width = self->atlas_width;
|
||||||
|
atlas->height = self->atlas_height;
|
||||||
|
/* TODO: We might want to change the strategy about the amount of
|
||||||
|
* nodes here? stb_rect_pack.h says width is optimal. */
|
||||||
|
atlas->nodes = g_malloc0_n (atlas->width, sizeof (struct stbrp_node));
|
||||||
|
stbrp_init_target (&atlas->context, atlas->width, atlas->height, atlas->nodes, atlas->width);
|
||||||
|
atlas->texture_id = gsk_gl_command_queue_create_texture (self->driver->command_queue,
|
||||||
|
atlas->width,
|
||||||
|
atlas->height,
|
||||||
|
GL_RGBA8,
|
||||||
|
GL_LINEAR,
|
||||||
|
GL_LINEAR);
|
||||||
|
|
||||||
|
gdk_gl_context_label_object_printf (gdk_gl_context_get_current (),
|
||||||
|
GL_TEXTURE, atlas->texture_id,
|
||||||
|
"Texture atlas %d",
|
||||||
|
atlas->texture_id);
|
||||||
|
|
||||||
|
g_ptr_array_add (self->atlases, atlas);
|
||||||
|
|
||||||
|
if (GSK_GL_TEXTURE_LIBRARY_GET_CLASS (self)->init_atlas)
|
||||||
|
GSK_GL_TEXTURE_LIBRARY_GET_CLASS (self)->init_atlas (self, atlas);
|
||||||
|
|
||||||
|
return atlas;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gsk_gl_texture_library_allocate (GskGLTextureLibrary *self,
|
||||||
|
GskGLTextureAtlas *atlas,
|
||||||
|
int width,
|
||||||
|
int height,
|
||||||
|
int *out_x,
|
||||||
|
int *out_y)
|
||||||
|
{
|
||||||
|
g_assert (GSK_IS_GL_TEXTURE_LIBRARY (self));
|
||||||
|
g_assert (atlas != NULL);
|
||||||
|
g_assert (width > 0);
|
||||||
|
g_assert (height > 0);
|
||||||
|
g_assert (out_x != NULL);
|
||||||
|
g_assert (out_y != NULL);
|
||||||
|
|
||||||
|
return GSK_GL_TEXTURE_LIBRARY_GET_CLASS (self)->allocate (self, atlas, width, height, out_x, out_y);
|
||||||
|
}
|
||||||
|
@ -50,7 +50,6 @@ typedef struct _GskGLTextureAtlas
|
|||||||
*/
|
*/
|
||||||
int unused_pixels;
|
int unused_pixels;
|
||||||
|
|
||||||
void *user_data;
|
|
||||||
} GskGLTextureAtlas;
|
} GskGLTextureAtlas;
|
||||||
|
|
||||||
typedef struct _GskGLTextureAtlasEntry
|
typedef struct _GskGLTextureAtlasEntry
|
||||||
@ -89,40 +88,67 @@ typedef struct _GskGLTextureAtlasEntry
|
|||||||
|
|
||||||
typedef struct _GskGLTextureLibrary
|
typedef struct _GskGLTextureLibrary
|
||||||
{
|
{
|
||||||
GObject parent_instance;
|
GObject parent_instance;
|
||||||
GskGLDriver *driver;
|
GskGLDriver *driver;
|
||||||
GHashTable *hash_table;
|
GPtrArray *atlases;
|
||||||
guint max_entry_size;
|
GHashTable *hash_table;
|
||||||
|
guint max_entry_size;
|
||||||
|
guint max_frame_age;
|
||||||
|
guint atlas_width;
|
||||||
|
guint atlas_height;
|
||||||
} GskGLTextureLibrary;
|
} GskGLTextureLibrary;
|
||||||
|
|
||||||
typedef struct _GskGLTextureLibraryClass
|
typedef struct _GskGLTextureLibraryClass
|
||||||
{
|
{
|
||||||
GObjectClass parent_class;
|
GObjectClass parent_class;
|
||||||
|
|
||||||
void (*begin_frame) (GskGLTextureLibrary *library,
|
void (*begin_frame) (GskGLTextureLibrary *library,
|
||||||
gint64 frame_id,
|
gint64 frame_id);
|
||||||
GPtrArray *removed_atlases);
|
gboolean (*compact) (GskGLTextureLibrary *library,
|
||||||
|
gint64 frame_id);
|
||||||
|
void (*clear_cache) (GskGLTextureLibrary *library);
|
||||||
|
void (*init_atlas) (GskGLTextureLibrary *library,
|
||||||
|
GskGLTextureAtlas *atlas);
|
||||||
|
gboolean (*allocate) (GskGLTextureLibrary *library,
|
||||||
|
GskGLTextureAtlas *atlas,
|
||||||
|
int width,
|
||||||
|
int height,
|
||||||
|
int *out_x,
|
||||||
|
int *out_y);
|
||||||
} GskGLTextureLibraryClass;
|
} GskGLTextureLibraryClass;
|
||||||
|
|
||||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GskGLTextureLibrary, g_object_unref)
|
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GskGLTextureLibrary, g_object_unref)
|
||||||
|
|
||||||
GType gsk_gl_texture_library_get_type (void) G_GNUC_CONST;
|
GType gsk_gl_texture_library_get_type (void) G_GNUC_CONST;
|
||||||
void gsk_gl_texture_library_set_funcs (GskGLTextureLibrary *self,
|
gboolean gsk_gl_texture_library_compact (GskGLTextureLibrary *self,
|
||||||
GHashFunc hash_func,
|
gint64 frame_id);
|
||||||
GEqualFunc equal_func,
|
void gsk_gl_texture_library_clear_cache (GskGLTextureLibrary *self);
|
||||||
GDestroyNotify key_destroy,
|
void gsk_gl_texture_library_reset (GskGLTextureLibrary *self);
|
||||||
GDestroyNotify value_destroy);
|
void gsk_gl_texture_library_set_atlas_size (GskGLTextureLibrary *self,
|
||||||
void gsk_gl_texture_library_begin_frame (GskGLTextureLibrary *self,
|
int width,
|
||||||
gint64 frame_id,
|
int height);
|
||||||
GPtrArray *removed_atlases);
|
GskGLTextureAtlas *gsk_gl_texture_library_acquire_atlas (GskGLTextureLibrary *self);
|
||||||
gpointer gsk_gl_texture_library_pack (GskGLTextureLibrary *self,
|
void gsk_gl_texture_library_set_funcs (GskGLTextureLibrary *self,
|
||||||
gpointer key,
|
GHashFunc hash_func,
|
||||||
gsize valuelen,
|
GEqualFunc equal_func,
|
||||||
guint width,
|
GDestroyNotify key_destroy,
|
||||||
guint height,
|
GDestroyNotify value_destroy);
|
||||||
int padding,
|
void gsk_gl_texture_library_begin_frame (GskGLTextureLibrary *self,
|
||||||
guint *out_packed_x,
|
gint64 frame_id);
|
||||||
guint *out_packed_y);
|
gboolean gsk_gl_texture_library_allocate (GskGLTextureLibrary *self,
|
||||||
|
GskGLTextureAtlas *atlas,
|
||||||
|
int width,
|
||||||
|
int height,
|
||||||
|
int *out_x,
|
||||||
|
int *out_y);
|
||||||
|
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
|
static inline void
|
||||||
gsk_gl_texture_atlas_mark_unused (GskGLTextureAtlas *self,
|
gsk_gl_texture_atlas_mark_unused (GskGLTextureAtlas *self,
|
||||||
|
Loading…
Reference in New Issue
Block a user