gl: Do less work to maintain caches
authorMatthias Clasen <mclasen@redhat.com>
Sat, 12 Oct 2019 00:42:24 +0000 (20:42 -0400)
committerMatthias Clasen <mclasen@redhat.com>
Sat, 12 Oct 2019 00:42:24 +0000 (20:42 -0400)
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
gsk/gl/gskglglyphcacheprivate.h
gsk/gl/gskgliconcache.c
gsk/gl/gskgliconcacheprivate.h
gsk/gl/gskglrenderer.c
gsk/gl/gskgltextureatlas.c
gsk/gl/gskgltextureatlasprivate.h

index f6206ca1f4602a2d2a78f1c43a4cad47e7826390..0357f9910de5ca0c5030afe1fedd6c445b1d4039 100644 (file)
@@ -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++;
 
-  g_hash_table_iter_init (&iter, self->hash_table);
-  while (g_hash_table_iter_next (&iter, (gpointer *)&key, (gpointer *)&value))
+  if (removed_atlases->len > 0)
     {
-      guint pos;
+      guint dropped = 0;
 
-      if (!g_ptr_array_find (self->atlases->atlases, value->atlas, &pos))
+      g_hash_table_iter_init (&iter, self->hash_table);
+      while (g_hash_table_iter_next (&iter, (gpointer *)&key, (gpointer *)&value))
         {
-          g_hash_table_iter_remove (&iter);
-          dropped++;
+          if (g_ptr_array_find (removed_atlases, value->atlas, NULL))
+            {
+              g_hash_table_iter_remove (&iter);
+              dropped++;
+            }
         }
-      else
+
+      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))
+    {
+      const guint age = self->timestamp - value->timestamp;
+
+      if (age > MAX_FRAME_AGE)
         {
-          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));
 }
index da1b018fd3f4336c4ebee67618d2d4174fb8bc57..dbe5196cca8ac210c6a5db471d9dc9ceaf95f0ce 100644 (file)
@@ -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,
index 93ac0897d767fb1111f0d1e8e370ce0d04b388e0..da3838219acb7ca05c86bceb634a01221105dc56 100644 (file)
@@ -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))
-        {
-          g_hash_table_iter_remove (&iter);
-        }
-      else
+      if (icon_data->frame_age > MAX_FRAME_AGE)
         {
-          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.
+           */
         }
     }
 }
index ade371b9301d75df5a5717b2b945b7de61ebc27b..5785871bf22c0484de97636e90333eb8d63d3b3f 100644 (file)
@@ -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,
index e0e5420df1d0b103212971aa5f415a0cef74c910..2600a35c903cb352484ad1b2fa8f3f321b917ab7 100644 (file)
@@ -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);
index 04dbb710b646f8c8e2ad6e72a3f7ccc5792cbbf5..3349d06cf7462db3739390ac4ad48d3378983344 100644 (file)
@@ -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);
        }
     }
index 2864fd8d050bcdf4b154a3d535290986aaecbf56..fc4f0365c02358ea99f7f637bff6154276cf59c6 100644 (file)
@@ -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,