gl: Do less work on glyph caching
authorMatthias Clasen <mclasen@redhat.com>
Sat, 12 Oct 2019 15:03:04 +0000 (11:03 -0400)
committerMatthias Clasen <mclasen@redhat.com>
Sat, 12 Oct 2019 15:35:46 +0000 (11:35 -0400)
There is no need for us to be very precise about
aging the glyph entries. It is enough to check
occasionally and mark old entries. This reduces
the overhead of work we do every frame on the
caches, at the cost of letting glyphs linger
a bit longer in the cache.

gsk/gl/gskglglyphcache.c
gsk/gl/gskglglyphcacheprivate.h

index 21121b1ce5f06f88c0d886f91cb43214ee5a7a95..f68837444c6fcef637f0fad652af30bdd17dbbaf 100644 (file)
@@ -15,9 +15,9 @@
 
 /* Cache eviction strategy
  *
- * Each cached glyph has an age that gets reset every time a cached
- * glyph gets used. Glyphs that have not been used for the
- * MAX_FRAME_AGE frames are considered old.
+ * We mark glyphs as accessed every time we use them. Every
+ * few frames, we mark glyphs that haven't been accessed since
+ * the last check as old.
  *
  * We keep count of the pixels of each atlas that are taken up by old
  * data. When the fraction of old pixels gets too high, we drop the
@@ -264,12 +264,12 @@ gsk_gl_glyph_cache_lookup_or_add (GskGLGlyphCache         *cache,
 
   if (value)
     {
-      value->timestamp = cache->timestamp;
       if (value->atlas && !value->used)
         {
           gsk_gl_texture_atlas_mark_used (value->atlas, value->draw_width, value->draw_height);
           value->used = TRUE;
         }
+      value->accessed = TRUE;
 
       *cached_glyph_out = value;
       return;
@@ -292,7 +292,7 @@ gsk_gl_glyph_cache_lookup_or_add (GskGLGlyphCache         *cache,
     value->draw_y = ink_rect.y;
     value->draw_width = ink_rect.width;
     value->draw_height = ink_rect.height;
-    value->timestamp = cache->timestamp;
+    value->accessed = TRUE;
     value->atlas = NULL; /* For now */
 
     key = g_new0 (GlyphCacheKey, 1);
@@ -341,20 +341,21 @@ gsk_gl_glyph_cache_begin_frame (GskGLGlyphCache *self,
       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))
+  if (self->timestamp % MAX_FRAME_AGE == 0)
     {
-      const guint age = self->timestamp - value->timestamp;
-
-      if (age > MAX_FRAME_AGE)
+      g_hash_table_iter_init (&iter, self->hash_table);
+      while (g_hash_table_iter_next (&iter, (gpointer *)&key, (gpointer *)&value))
         {
-          GskGLTextureAtlas *atlas = value->atlas;
-
-          if (atlas && value->used)
+          if (!value->accessed)
             {
-              gsk_gl_texture_atlas_mark_unused (atlas, value->draw_width, value->draw_height);
-              value->used = FALSE;
+              if (value->atlas && value->used)
+                {
+                  gsk_gl_texture_atlas_mark_unused (value->atlas, value->draw_width, value->draw_height);
+                  value->used = FALSE;
+                }
             }
-        }
+
+          value->accessed = FALSE;
+       }
     }
 }
index 259688fbb7e4911357ecea374ef23e42bc846e91..75f7a8de19efc246d01bff07ec6bf791ffaf07d1 100644 (file)
@@ -15,7 +15,7 @@ typedef struct
   GHashTable *hash_table;
   GskGLTextureAtlases *atlases;
 
-  guint64 timestamp;
+  int timestamp;
 } GskGLGlyphCache;
 
 typedef struct
@@ -63,8 +63,8 @@ struct _GskGLCachedGlyph
   int draw_width;
   int draw_height;
 
-  guint used: 1;
-  guint64 timestamp;
+  guint accessed : 1; /* accessed since last check */
+  guint used     : 1; /* accounted as used in the atlas */
 };