From 8839e10d44e240d8e6e342dd1a7d8d1bc7f78b69 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Fri, 11 Oct 2019 20:42:24 -0400 Subject: [PATCH] gl: Do less work to maintain caches Remember which atlases were removed, and only check those when looking for icons or glyphs to remove. For most frames, we don't have to check at all since no atlases were removed. --- gsk/gl/gskglglyphcache.c | 45 ++++++++++++++++------------- gsk/gl/gskglglyphcacheprivate.h | 3 +- gsk/gl/gskgliconcache.c | 47 ++++++++++++++++--------------- gsk/gl/gskgliconcacheprivate.h | 3 +- gsk/gl/gskglrenderer.c | 9 ++++-- gsk/gl/gskgltextureatlas.c | 4 ++- gsk/gl/gskgltextureatlasprivate.h | 3 +- 7 files changed, 65 insertions(+), 49 deletions(-) diff --git a/gsk/gl/gskglglyphcache.c b/gsk/gl/gskglglyphcache.c index f6206ca1f4..0357f9910d 100644 --- a/gsk/gl/gskglglyphcache.c +++ b/gsk/gl/gskglglyphcache.c @@ -312,41 +312,46 @@ gsk_gl_glyph_cache_lookup (GskGLGlyphCache *cache, } void -gsk_gl_glyph_cache_begin_frame (GskGLGlyphCache *self) +gsk_gl_glyph_cache_begin_frame (GskGLGlyphCache *self, + GPtrArray *removed_atlases) { GHashTableIter iter; GlyphCacheKey *key; GskGLCachedGlyph *value; - guint dropped = 0; self->timestamp++; + if (removed_atlases->len > 0) + { + guint dropped = 0; + + g_hash_table_iter_init (&iter, self->hash_table); + while (g_hash_table_iter_next (&iter, (gpointer *)&key, (gpointer *)&value)) + { + if (g_ptr_array_find (removed_atlases, value->atlas, NULL)) + { + g_hash_table_iter_remove (&iter); + dropped++; + } + } + + GSK_NOTE(GLYPH_CACHE, if (dropped > 0) g_message ("Dropped %d glyphs", dropped)); + } + g_hash_table_iter_init (&iter, self->hash_table); while (g_hash_table_iter_next (&iter, (gpointer *)&key, (gpointer *)&value)) { - guint pos; + const guint age = self->timestamp - value->timestamp; - if (!g_ptr_array_find (self->atlases->atlases, value->atlas, &pos)) + if (age > MAX_FRAME_AGE) { - g_hash_table_iter_remove (&iter); - dropped++; - } - else - { - const guint age = self->timestamp - value->timestamp; + GskGLTextureAtlas *atlas = value->atlas; - if (age > MAX_FRAME_AGE) + if (atlas && value->used) { - GskGLTextureAtlas *atlas = value->atlas; - - if (atlas && value->used) - { - gsk_gl_texture_atlas_mark_unused (atlas, value->draw_width, value->draw_height); - value->used = FALSE; - } + gsk_gl_texture_atlas_mark_unused (atlas, value->draw_width, value->draw_height); + value->used = FALSE; } } } - - GSK_NOTE(GLYPH_CACHE, if (dropped > 0) g_message ("Dropped %d glyphs", dropped)); } diff --git a/gsk/gl/gskglglyphcacheprivate.h b/gsk/gl/gskglglyphcacheprivate.h index da1b018fd3..dbe5196cca 100644 --- a/gsk/gl/gskglglyphcacheprivate.h +++ b/gsk/gl/gskglglyphcacheprivate.h @@ -72,7 +72,8 @@ GskGLGlyphCache * gsk_gl_glyph_cache_new (GdkDisplay *display GskGLTextureAtlases *atlases); GskGLGlyphCache * gsk_gl_glyph_cache_ref (GskGLGlyphCache *self); void gsk_gl_glyph_cache_unref (GskGLGlyphCache *self); -void gsk_gl_glyph_cache_begin_frame (GskGLGlyphCache *self); +void gsk_gl_glyph_cache_begin_frame (GskGLGlyphCache *self, + GPtrArray *removed_atlases); gboolean gsk_gl_glyph_cache_lookup (GskGLGlyphCache *self, GlyphCacheKey *lookup, GskGLDriver *driver, diff --git a/gsk/gl/gskgliconcache.c b/gsk/gl/gskgliconcache.c index 93ac0897d7..da3838219a 100644 --- a/gsk/gl/gskgliconcache.c +++ b/gsk/gl/gskgliconcache.c @@ -64,40 +64,43 @@ gsk_gl_icon_cache_unref (GskGLIconCache *self) } void -gsk_gl_icon_cache_begin_frame (GskGLIconCache *self) +gsk_gl_icon_cache_begin_frame (GskGLIconCache *self, + GPtrArray *removed_atlases) { GHashTableIter iter; GdkTexture *texture; IconData *icon_data; - /* Increase frame age of all icons */ + /* Drop icons on removed atlases */ + if (removed_atlases->len > 0) + { + g_hash_table_iter_init (&iter, self->icons); + while (g_hash_table_iter_next (&iter, (gpointer *)&texture, (gpointer *)&icon_data)) + { + if (g_ptr_array_find (removed_atlases, icon_data->atlas, NULL)) + g_hash_table_iter_remove (&iter); + } + } + + /* Increase frame age of all remaining icons */ g_hash_table_iter_init (&iter, self->icons); while (g_hash_table_iter_next (&iter, (gpointer *)&texture, (gpointer *)&icon_data)) { - guint pos; + icon_data->frame_age ++; - if (!g_ptr_array_find (self->atlases->atlases, icon_data->atlas, &pos)) + if (icon_data->frame_age > MAX_FRAME_AGE) { - g_hash_table_iter_remove (&iter); - } - else - { - icon_data->frame_age ++; - - if (icon_data->frame_age > MAX_FRAME_AGE) + if (icon_data->used) { - - if (icon_data->used) - { - const int w = icon_data->texture_rect.size.width * icon_data->atlas->width; - const int h = icon_data->texture_rect.size.height * icon_data->atlas->height; - - gsk_gl_texture_atlas_mark_unused (icon_data->atlas, w + 2, h + 2); - icon_data->used = FALSE; - } - /* We do NOT remove the icon here. Instead, We wait until we drop the entire atlas. - * This way we can revive it when we use it again. */ + const int w = icon_data->texture_rect.size.width * icon_data->atlas->width; + const int h = icon_data->texture_rect.size.height * icon_data->atlas->height; + gsk_gl_texture_atlas_mark_unused (icon_data->atlas, w + 2, h + 2); + icon_data->used = FALSE; } + + /* We do NOT remove the icon here. Instead, We wait until we drop the entire atlas. + * This way we can revive it when we use it again. + */ } } } diff --git a/gsk/gl/gskgliconcacheprivate.h b/gsk/gl/gskgliconcacheprivate.h index ade371b930..5785871bf2 100644 --- a/gsk/gl/gskgliconcacheprivate.h +++ b/gsk/gl/gskgliconcacheprivate.h @@ -24,7 +24,8 @@ GskGLIconCache * gsk_gl_icon_cache_new (GdkDisplay *display, GskGLTextureAtlases *atlases); GskGLIconCache * gsk_gl_icon_cache_ref (GskGLIconCache *self); void gsk_gl_icon_cache_unref (GskGLIconCache *self); -void gsk_gl_icon_cache_begin_frame (GskGLIconCache *self); +void gsk_gl_icon_cache_begin_frame (GskGLIconCache *self, + GPtrArray *removed_atlases); void gsk_gl_icon_cache_lookup_or_add (GskGLIconCache *self, GdkTexture *texture, int *out_texture_id, diff --git a/gsk/gl/gskglrenderer.c b/gsk/gl/gskglrenderer.c index e0e5420df1..2600a35c90 100644 --- a/gsk/gl/gskglrenderer.c +++ b/gsk/gl/gskglrenderer.c @@ -3181,6 +3181,7 @@ gsk_gl_renderer_do_render (GskRenderer *renderer, GskProfiler *profiler; gint64 gpu_time, cpu_time, start_time; #endif + GPtrArray *removed; #ifdef G_ENABLE_DEBUG profiler = gsk_renderer_get_profiler (renderer); @@ -3204,10 +3205,12 @@ gsk_gl_renderer_do_render (GskRenderer *renderer, ORTHO_FAR_PLANE); graphene_matrix_scale (&projection, 1, -1, 1); - gsk_gl_texture_atlases_begin_frame (self->atlases); - gsk_gl_glyph_cache_begin_frame (self->glyph_cache); - gsk_gl_icon_cache_begin_frame (self->icon_cache); + removed = g_ptr_array_new (); + gsk_gl_texture_atlases_begin_frame (self->atlases, removed); + gsk_gl_glyph_cache_begin_frame (self->glyph_cache, removed); + gsk_gl_icon_cache_begin_frame (self->icon_cache, removed); gsk_gl_shadow_cache_begin_frame (&self->shadow_cache, self->gl_driver); + g_ptr_array_unref (removed); ops_set_projection (&self->op_builder, &projection); ops_set_viewport (&self->op_builder, viewport); diff --git a/gsk/gl/gskgltextureatlas.c b/gsk/gl/gskgltextureatlas.c index 04dbb710b6..3349d06cf7 100644 --- a/gsk/gl/gskgltextureatlas.c +++ b/gsk/gl/gskgltextureatlas.c @@ -74,7 +74,8 @@ write_atlas_to_png (GskGLTextureAtlas *atlas, #endif void -gsk_gl_texture_atlases_begin_frame (GskGLTextureAtlases *self) +gsk_gl_texture_atlases_begin_frame (GskGLTextureAtlases *self, + GPtrArray *removed) { int i; @@ -94,6 +95,7 @@ gsk_gl_texture_atlases_begin_frame (GskGLTextureAtlases *self) atlas->texture_id = 0; } + g_ptr_array_add (removed, atlas); g_ptr_array_remove_index (self->atlases, i); } } diff --git a/gsk/gl/gskgltextureatlasprivate.h b/gsk/gl/gskgltextureatlasprivate.h index 2864fd8d05..fc4f0365c0 100644 --- a/gsk/gl/gskgltextureatlasprivate.h +++ b/gsk/gl/gskgltextureatlasprivate.h @@ -35,7 +35,8 @@ GskGLTextureAtlases *gsk_gl_texture_atlases_new (void); GskGLTextureAtlases *gsk_gl_texture_atlases_ref (GskGLTextureAtlases *atlases); void gsk_gl_texture_atlases_unref (GskGLTextureAtlases *atlases); -void gsk_gl_texture_atlases_begin_frame (GskGLTextureAtlases *atlases); +void gsk_gl_texture_atlases_begin_frame (GskGLTextureAtlases *atlases, + GPtrArray *removed); gboolean gsk_gl_texture_atlases_pack (GskGLTextureAtlases *atlases, int width, int height,