[gtk/mask-nodes: 7/8] gl: Add a path cache




commit 9135288893acc11cf2a6f780a677d42287c4db0b
Author: Matthias Clasen <mclasen redhat com>
Date:   Tue Dec 15 19:07:06 2020 -0500

    gl: Add a path cache
    
    This is very similar to the shadow cache.
    We cache masks that we've rendered for paths,
    including the fill rule and the stroke parameters
    in the cache.

 gsk/gl/gskglpathcache.c        | 134 +++++++++++++++++++++++++++++++++++++++++
 gsk/gl/gskglpathcacheprivate.h |  31 ++++++++++
 gsk/meson.build                |   1 +
 3 files changed, 166 insertions(+)
---
diff --git a/gsk/gl/gskglpathcache.c b/gsk/gl/gskglpathcache.c
new file mode 100644
index 0000000000..0fdf0d45df
--- /dev/null
+++ b/gsk/gl/gskglpathcache.c
@@ -0,0 +1,134 @@
+#include "config.h"
+
+#include "gskglpathcacheprivate.h"
+#include "gskstrokeprivate.h"
+
+#define MAX_UNUSED_FRAMES (16 * 5)
+
+typedef struct
+{
+  GskPath *path;
+  GskFillRule fill_rule;
+  gboolean has_stroke;
+  GskStroke stroke;
+
+  graphene_rect_t bounds;
+  int texture_id;
+  int unused_frames;
+} CacheItem;
+
+void
+gsk_gl_path_cache_init (GskGLPathCache *self)
+{
+  self->textures = g_array_new (FALSE, TRUE, sizeof (CacheItem));
+}
+
+void
+gsk_gl_path_cache_free (GskGLPathCache *self,
+                        GskGLDriver    *gl_driver)
+{
+  guint i, p;
+
+  for (i = 0, p = self->textures->len; i < p; i ++)
+    {
+      const CacheItem *item = &g_array_index (self->textures, CacheItem, i);
+
+      gsk_gl_driver_destroy_texture (gl_driver, item->texture_id);
+    }
+
+  g_array_free (self->textures, TRUE);
+  self->textures = NULL;
+}
+
+void
+gsk_gl_path_cache_begin_frame (GskGLPathCache *self,
+                               GskGLDriver    *gl_driver)
+{
+  guint i, p;
+
+  for (i = 0, p = self->textures->len; i < p; i ++)
+    {
+      CacheItem *item = &g_array_index (self->textures, CacheItem, i);
+
+      if (item->unused_frames > MAX_UNUSED_FRAMES)
+        {
+          gsk_gl_driver_destroy_texture (gl_driver, item->texture_id);
+          g_array_remove_index_fast (self->textures, i);
+          p --;
+          i --;
+        }
+      else
+        {
+          item->unused_frames ++;
+        }
+    }
+}
+
+int
+gsk_gl_path_cache_get_texture_id (GskGLPathCache  *self,
+                                  GskPath         *path,
+                                  GskFillRule      fill_rule,
+                                  const GskStroke *stroke,
+                                  graphene_rect_t *out_bounds)
+{
+  CacheItem *item = NULL;
+  guint i;
+
+  g_assert (self != NULL);
+
+  for (i = 0; i < self->textures->len; i ++)
+    {
+      CacheItem *k = &g_array_index (self->textures, CacheItem, i);
+
+      if (k->path == path &&
+          k->fill_rule == fill_rule &&
+          ((k->has_stroke && stroke && gsk_stroke_equal (&k->stroke, stroke)) ||
+           (!k->has_stroke && !stroke)))
+        {
+          item = k;
+          break;
+        }
+    }
+
+  if (item == NULL)
+    return 0;
+
+  item->unused_frames = 0;
+
+  g_assert (item->texture_id != 0);
+
+  *out_bounds = item->bounds;
+
+  return item->texture_id;
+}
+
+void
+gsk_gl_path_cache_commit (GskGLPathCache        *self,
+                          GskPath               *path,
+                          GskFillRule            fill_rule,
+                          const GskStroke       *stroke,
+                          int                    texture_id,
+                          const graphene_rect_t *bounds)
+{
+  CacheItem *item;
+
+  g_assert (self != NULL);
+  g_assert (texture_id > 0);
+
+  g_array_set_size (self->textures, self->textures->len + 1);
+  item = &g_array_index (self->textures, CacheItem, self->textures->len - 1);
+
+  item->path = path;
+  item->fill_rule = fill_rule;
+  if (stroke)
+    {
+      item->has_stroke = TRUE;
+      gsk_stroke_init_copy (&item->stroke, stroke);
+    }
+  else
+    item->has_stroke = FALSE;
+
+  item->unused_frames = 0;
+  item->texture_id = texture_id;
+  item->bounds = *bounds;
+}
diff --git a/gsk/gl/gskglpathcacheprivate.h b/gsk/gl/gskglpathcacheprivate.h
new file mode 100644
index 0000000000..d56cacbc15
--- /dev/null
+++ b/gsk/gl/gskglpathcacheprivate.h
@@ -0,0 +1,31 @@
+#ifndef __GSK_GL_PATH_CACHE_H__
+#define __GSK_GL_PATH_CACHE_H__
+
+#include <glib.h>
+#include "gskgldriverprivate.h"
+#include "gskpath.h"
+
+typedef struct
+{
+  GArray *textures;
+} GskGLPathCache;
+
+
+void gsk_gl_path_cache_init           (GskGLPathCache        *self);
+void gsk_gl_path_cache_free           (GskGLPathCache        *self,
+                                       GskGLDriver           *gl_driver);
+void gsk_gl_path_cache_begin_frame    (GskGLPathCache        *self,
+                                       GskGLDriver           *gl_driver);
+int  gsk_gl_path_cache_get_texture_id (GskGLPathCache        *self,
+                                       GskPath               *path,
+                                       GskFillRule            fill_rule,
+                                       const GskStroke       *stroke,
+                                       graphene_rect_t       *out_bounds);
+void gsk_gl_path_cache_commit         (GskGLPathCache        *self,
+                                       GskPath               *path,
+                                       GskFillRule            fill_rule,
+                                       const GskStroke       *stroke,
+                                       int                    texture_id,
+                                       const graphene_rect_t *bounds);
+
+#endif
diff --git a/gsk/meson.build b/gsk/meson.build
index f7f3894e23..e16cae8f4f 100644
--- a/gsk/meson.build
+++ b/gsk/meson.build
@@ -59,6 +59,7 @@ gsk_private_sources = files([
   'gl/gskgliconcache.c',
   'gl/opbuffer.c',
   'gl/stb_rect_pack.c',
+  'gl/gskglpathcache.c',
 ])
 
 gsk_public_headers = files([


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]