[gtk/mask-nodes: 122/123] gl: Add a path cache
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/mask-nodes: 122/123] gl: Add a path cache
- Date: Mon, 21 Dec 2020 02:57:31 +0000 (UTC)
commit 3db97785989c62637f3dabcd18719e7e27beb06a
Author: Matthias Clasen <mclasen redhat com>
Date: Sun Dec 20 21:46:00 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 key.
The cache is not used yet.
gsk/gl/gskglpathcache.c | 157 +++++++++++++++++++++++++++++++++++++++++
gsk/gl/gskglpathcacheprivate.h | 31 ++++++++
gsk/gl/gskglrenderer.c | 5 ++
gsk/meson.build | 1 +
4 files changed, 194 insertions(+)
---
diff --git a/gsk/gl/gskglpathcache.c b/gsk/gl/gskglpathcache.c
new file mode 100644
index 0000000000..1dcb0c33d8
--- /dev/null
+++ b/gsk/gl/gskglpathcache.c
@@ -0,0 +1,157 @@
+#include "config.h"
+
+#include "gskglpathcacheprivate.h"
+#include "gskstrokeprivate.h"
+
+#define MAX_UNUSED_FRAMES (16 * 5)
+
+typedef struct
+{
+ GskPath *path;
+ GskFillRule fill_rule;
+ const GskStroke *stroke;
+ guint hash;
+
+ GskStroke stroke_copy;
+ graphene_rect_t bounds;
+ int texture_id;
+ int unused_frames;
+} CacheItem;
+
+static guint
+compute_hash (CacheItem *item)
+{
+ guint hash;
+
+ hash = GPOINTER_TO_UINT (item->path);
+ hash += item->fill_rule;
+ if (item->stroke)
+ hash += gsk_stroke_hash (item->stroke);
+
+ return hash;
+}
+
+static guint
+cache_key_hash (gconstpointer v)
+{
+ const CacheItem *item = v;
+
+ return item->hash;
+}
+
+static gboolean
+cache_key_equal (gconstpointer v1,
+ gconstpointer v2)
+{
+ const CacheItem *item1 = v1;
+ const CacheItem *item2 = v2;
+
+ return item1->path == item2->path &&
+ item1->fill_rule == item2->fill_rule &&
+ (item1->stroke == item2->stroke ||
+ (item1->stroke && item2->stroke &&
+ gsk_stroke_equal (item1->stroke, item2->stroke)));
+}
+
+void
+gsk_gl_path_cache_init (GskGLPathCache *self)
+{
+ self->textures = g_hash_table_new_full (cache_key_hash,
+ cache_key_equal,
+ NULL,
+ g_free);
+}
+
+void
+gsk_gl_path_cache_free (GskGLPathCache *self,
+ GskGLDriver *gl_driver)
+{
+ GHashTableIter iter;
+ CacheItem *item;
+
+ g_hash_table_iter_init (&iter, self->textures);
+ while (g_hash_table_iter_next (&iter, NULL, (gpointer *)&item))
+ {
+ gsk_gl_driver_destroy_texture (gl_driver, item->texture_id);
+ }
+
+ g_hash_table_unref (self->textures);
+ self->textures = NULL;
+}
+
+void
+gsk_gl_path_cache_begin_frame (GskGLPathCache *self,
+ GskGLDriver *gl_driver)
+{
+ GHashTableIter iter;
+ CacheItem *item;
+
+ g_hash_table_iter_init (&iter, self->textures);
+ while (g_hash_table_iter_next (&iter, NULL, (gpointer *)&item))
+ {
+ if (item->unused_frames > MAX_UNUSED_FRAMES)
+ {
+ gsk_gl_driver_destroy_texture (gl_driver, item->texture_id);
+ g_hash_table_iter_remove (&iter);
+ }
+ }
+}
+
+int
+gsk_gl_path_cache_get_texture_id (GskGLPathCache *self,
+ GskPath *path,
+ GskFillRule fill_rule,
+ const GskStroke *stroke,
+ graphene_rect_t *out_bounds)
+{
+ CacheItem key;
+ CacheItem *item;
+
+ key.path = path;
+ key.fill_rule = fill_rule;
+ key.stroke = stroke;
+ key.hash = compute_hash (&key);
+
+ item = g_hash_table_lookup (self->textures, &key);
+ 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);
+
+ item = g_new0 (CacheItem, 1);
+
+ item->path = path;
+ item->fill_rule = fill_rule;
+ if (stroke)
+ {
+ gsk_stroke_init_copy (&item->stroke_copy, stroke);
+ item->stroke = &item->stroke_copy;
+ }
+ item->hash = compute_hash (item);
+
+ item->unused_frames = 0;
+ item->texture_id = texture_id;
+ item->bounds = *bounds;
+
+ g_hash_table_add (self->textures, item);
+}
diff --git a/gsk/gl/gskglpathcacheprivate.h b/gsk/gl/gskglpathcacheprivate.h
new file mode 100644
index 0000000000..181d4be26f
--- /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
+{
+ GHashTable *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/gl/gskglrenderer.c b/gsk/gl/gskglrenderer.c
index c00805c6e5..09b7b4f0a1 100644
--- a/gsk/gl/gskglrenderer.c
+++ b/gsk/gl/gskglrenderer.c
@@ -16,6 +16,7 @@
#include "gskglrenderopsprivate.h"
#include "gskcairoblurprivate.h"
#include "gskglshadowcacheprivate.h"
+#include "gskglpathcacheprivate.h"
#include "gskglnodesampleprivate.h"
#include "gsktransform.h"
#include "glutilsprivate.h"
@@ -542,6 +543,7 @@ struct _GskGLRenderer
GskGLGlyphCache *glyph_cache;
GskGLIconCache *icon_cache;
GskGLShadowCache shadow_cache;
+ GskGLPathCache path_cache;
#ifdef G_ENABLE_DEBUG
struct {
@@ -3636,6 +3638,7 @@ gsk_gl_renderer_realize (GskRenderer *renderer,
self->glyph_cache = get_glyph_cache_for_display (gdk_surface_get_display (surface), self->atlases);
self->icon_cache = get_icon_cache_for_display (gdk_surface_get_display (surface), self->atlases);
gsk_gl_shadow_cache_init (&self->shadow_cache);
+ gsk_gl_path_cache_init (&self->path_cache);
gdk_profiler_end_mark (before, "gl renderer realize", NULL);
@@ -3663,6 +3666,7 @@ gsk_gl_renderer_unrealize (GskRenderer *renderer)
g_clear_pointer (&self->icon_cache, gsk_gl_icon_cache_unref);
g_clear_pointer (&self->atlases, gsk_gl_texture_atlases_unref);
gsk_gl_shadow_cache_free (&self->shadow_cache, self->gl_driver);
+ gsk_gl_path_cache_free (&self->path_cache, self->gl_driver);
g_clear_object (&self->gl_profiler);
g_clear_object (&self->gl_driver);
@@ -4304,6 +4308,7 @@ gsk_gl_renderer_do_render (GskRenderer *renderer,
gsk_gl_glyph_cache_begin_frame (self->glyph_cache, self->gl_driver, removed);
gsk_gl_icon_cache_begin_frame (self->icon_cache, removed);
gsk_gl_shadow_cache_begin_frame (&self->shadow_cache, self->gl_driver);
+ gsk_gl_path_cache_begin_frame (&self->path_cache, self->gl_driver);
g_ptr_array_unref (removed);
/* Set up the modelview and projection matrices to fit our viewport */
diff --git a/gsk/meson.build b/gsk/meson.build
index 5925594c29..618ed14651 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]