[gtk/wip/chergert/glproto: 342/526] add shadow library
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/wip/chergert/glproto: 342/526] add shadow library
- Date: Tue, 16 Feb 2021 01:14:34 +0000 (UTC)
commit c4447dd7c1cdd4bdc94cdae20e47292d9d38d1e9
Author: Christian Hergert <chergert redhat com>
Date: Thu Jan 28 12:11:26 2021 -0800
add shadow library
gsk/next/TODO.md | 1 +
gsk/next/gskgldriver.c | 31 +++++-
gsk/next/gskgldriverprivate.h | 4 +
gsk/next/gskglshadowlibrary.c | 183 ++++++++++++++++++++++++++++++++++-
gsk/next/gskglshadowlibraryprivate.h | 20 ++--
5 files changed, 224 insertions(+), 15 deletions(-)
---
diff --git a/gsk/next/TODO.md b/gsk/next/TODO.md
index 6523abd32f..028ed5d661 100644
--- a/gsk/next/TODO.md
+++ b/gsk/next/TODO.md
@@ -8,4 +8,5 @@
* Try to hold on to cached textures for more frames
* Add debug tooling for sysprof so we can capture frame information
* OpenGL Shader transitions missing main()
+ * Ensure drivers are disposed when surface is released
diff --git a/gsk/next/gskgldriver.c b/gsk/next/gskgldriver.c
index 6f1bada783..231ca3c4f3 100644
--- a/gsk/next/gskgldriver.c
+++ b/gsk/next/gskgldriver.c
@@ -505,7 +505,7 @@ gsk_next_driver_begin_frame (GskNextDriver *self,
gsk_gl_texture_library_begin_frame (GSK_GL_TEXTURE_LIBRARY (self->icons));
gsk_gl_texture_library_begin_frame (GSK_GL_TEXTURE_LIBRARY (self->glyphs));
- gsk_gl_texture_library_begin_frame (GSK_GL_TEXTURE_LIBRARY (self->shadows));
+ gsk_gl_shadow_library_begin_frame (self->shadows);
/* Remove all textures that are from a previous frame or are no
* longer used by linked GdkTexture. We do this at the beginning
@@ -535,7 +535,6 @@ gsk_next_driver_end_frame (GskNextDriver *self)
gsk_gl_texture_library_end_frame (GSK_GL_TEXTURE_LIBRARY (self->icons));
gsk_gl_texture_library_end_frame (GSK_GL_TEXTURE_LIBRARY (self->glyphs));
- gsk_gl_texture_library_end_frame (GSK_GL_TEXTURE_LIBRARY (self->shadows));
while (self->render_targets->len > 0)
{
@@ -1246,3 +1245,31 @@ gsk_next_driver_slice_texture (GskNextDriver *self,
t->slices = *out_slices = slices;
t->n_slices = *out_n_slices = n_slices;
}
+
+void
+gsk_next_driver_mark_texture_permanent (GskNextDriver *self,
+ guint texture_id)
+{
+ GskGLTexture *t;
+
+ g_return_if_fail (GSK_IS_NEXT_DRIVER (self));
+ g_return_if_fail (texture_id > 0);
+
+ if ((t = g_hash_table_lookup (self->textures, GUINT_TO_POINTER (texture_id))))
+ t->permanent = TRUE;
+}
+
+void
+gsk_next_driver_release_texture_by_id (GskNextDriver *self,
+ guint texture_id)
+{
+ GskGLTexture *texture;
+
+ g_return_if_fail (GSK_IS_NEXT_DRIVER (self));
+ g_return_if_fail (texture_id > 0);
+
+ if ((texture = g_hash_table_lookup (self->textures, GUINT_TO_POINTER (texture_id))))
+ gsk_next_driver_release_texture (self, texture);
+ else
+ remove_texture_key_for_id (self, texture_id);
+}
diff --git a/gsk/next/gskgldriverprivate.h b/gsk/next/gskgldriverprivate.h
index b56310ba8b..12bc7a4fed 100644
--- a/gsk/next/gskgldriverprivate.h
+++ b/gsk/next/gskgldriverprivate.h
@@ -156,6 +156,10 @@ GskGLTexture *gsk_next_driver_acquire_texture (GskNextDriver *
int mag_filter);
void gsk_next_driver_release_texture (GskNextDriver *self,
GskGLTexture *texture);
+void gsk_next_driver_release_texture_by_id (GskNextDriver *self,
+ guint texture_id);
+void gsk_next_driver_mark_texture_permanent(GskNextDriver *self,
+ guint texture_id);
void gsk_next_driver_slice_texture (GskNextDriver *self,
GdkTexture *texture,
GskGLTextureSlice **out_slices,
diff --git a/gsk/next/gskglshadowlibrary.c b/gsk/next/gskglshadowlibrary.c
index f33c608b10..79ede9c95d 100644
--- a/gsk/next/gskglshadowlibrary.c
+++ b/gsk/next/gskglshadowlibrary.c
@@ -20,15 +20,37 @@
#include "config.h"
+#include <string.h>
+
#include "gskgldriverprivate.h"
#include "gskglshadowlibraryprivate.h"
+#define MAX_UNUSED_FRAMES (16 * 5)
+
struct _GskGLShadowLibrary
{
- GskGLTextureLibrary parent_instance;
+ GObject parent_instance;
+ GskNextDriver *driver;
+ GArray *shadows;
+};
+
+typedef struct _Shadow
+{
+ GskRoundedRect outline;
+ float blur_radius;
+ guint texture_id;
+ gint64 last_used_in_frame;
+} Shadow;
+
+G_DEFINE_TYPE (GskGLShadowLibrary, gsk_gl_shadow_library, G_TYPE_OBJECT)
+
+enum {
+ PROP_0,
+ PROP_DRIVER,
+ N_PROPS
};
-G_DEFINE_TYPE (GskGLShadowLibrary, gsk_gl_shadow_library, GSK_TYPE_GL_TEXTURE_LIBRARY)
+static GParamSpec *properties [N_PROPS];
GskGLShadowLibrary *
gsk_gl_shadow_library_new (GskNextDriver *driver)
@@ -40,14 +62,167 @@ gsk_gl_shadow_library_new (GskNextDriver *driver)
NULL);
}
+static void
+gsk_gl_shadow_library_dispose (GObject *object)
+{
+ GskGLShadowLibrary *self = (GskGLShadowLibrary *)object;
+
+ for (guint i = 0; i < self->shadows->len; i++)
+ {
+ const Shadow *shadow = &g_array_index (self->shadows, Shadow, i);
+ gsk_next_driver_release_texture_by_id (self->driver, shadow->texture_id);
+ }
+
+ g_clear_pointer (&self->shadows, g_array_unref);
+ g_clear_object (&self->driver);
+
+ G_OBJECT_CLASS (gsk_gl_shadow_library_parent_class)->dispose (object);
+}
+
+static void
+gsk_gl_shadow_library_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GskGLShadowLibrary *self = GSK_GL_SHADOW_LIBRARY (object);
+
+ switch (prop_id)
+ {
+ case PROP_DRIVER:
+ g_value_set_object (value, self->driver);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+gsk_gl_shadow_library_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GskGLShadowLibrary *self = GSK_GL_SHADOW_LIBRARY (object);
+
+ switch (prop_id)
+ {
+ case PROP_DRIVER:
+ self->driver = g_value_dup_object (value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
static void
gsk_gl_shadow_library_class_init (GskGLShadowLibraryClass *klass)
{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->dispose = gsk_gl_shadow_library_dispose;
+ object_class->get_property = gsk_gl_shadow_library_get_property;
+ object_class->set_property = gsk_gl_shadow_library_set_property;
+
+ properties [PROP_DRIVER] =
+ g_param_spec_object ("driver",
+ "Driver",
+ "Driver",
+ GSK_TYPE_NEXT_DRIVER,
+ (G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_properties (object_class, N_PROPS, properties);
}
static void
gsk_gl_shadow_library_init (GskGLShadowLibrary *self)
{
- gsk_gl_texture_library_set_funcs (GSK_GL_TEXTURE_LIBRARY (self),
- NULL, NULL, NULL, NULL);
+ self->shadows = g_array_new (FALSE, FALSE, sizeof (Shadow));
+}
+
+void
+gsk_gl_shadow_library_insert (GskGLShadowLibrary *self,
+ const GskRoundedRect *outline,
+ float blur_radius,
+ guint texture_id)
+{
+ Shadow *shadow;
+
+ g_return_if_fail (GSK_IS_GL_SHADOW_LIBRARY (self));
+ g_return_if_fail (outline != NULL);
+ g_return_if_fail (texture_id != 0);
+
+ gsk_next_driver_mark_texture_permanent (self->driver, texture_id);
+
+ g_array_set_size (self->shadows, self->shadows->len + 1);
+
+ shadow = &g_array_index (self->shadows, Shadow, self->shadows->len - 1);
+ shadow->outline = *outline;
+ shadow->blur_radius = blur_radius;
+ shadow->texture_id = texture_id;
+ shadow->last_used_in_frame = self->driver->current_frame_id;
+}
+
+guint
+gsk_gl_shadow_library_lookup (GskGLShadowLibrary *self,
+ const GskRoundedRect *outline,
+ float blur_radius)
+{
+ Shadow *ret = NULL;
+
+ g_return_val_if_fail (GSK_IS_GL_SHADOW_LIBRARY (self), 0);
+ g_return_val_if_fail (outline != NULL, 0);
+
+ /* Ensure GskRoundedRect is 12 packed floats without padding
+ * so that we can use memcmp instead of float comparisons.
+ */
+ G_STATIC_ASSERT (sizeof *outline == (sizeof (float) * 12));
+
+ for (guint i = 0; i < self->shadows->len; i++)
+ {
+ Shadow *shadow = &g_array_index (self->shadows, Shadow, i);
+
+ if (blur_radius == shadow->blur_radius &&
+ memcmp (outline, &shadow->outline, sizeof *outline) == 0)
+ {
+ ret = shadow;
+ break;
+ }
+ }
+
+ if (ret == NULL)
+ return 0;
+
+ g_assert (ret->texture_id != 0);
+
+ ret->last_used_in_frame = self->driver->current_frame_id;
+
+ return ret->texture_id;
+}
+
+void
+gsk_gl_shadow_library_begin_frame (GskGLShadowLibrary *self)
+{
+ gint64 watermark;
+ int i;
+ int p;
+
+ g_return_if_fail (GSK_IS_GL_SHADOW_LIBRARY (self));
+
+ watermark = self->driver->current_frame_id - MAX_UNUSED_FRAMES;
+
+ for (i = 0, p = self->shadows->len; i < p; i++)
+ {
+ const Shadow *shadow = &g_array_index (self->shadows, Shadow, i);
+
+ if (shadow->last_used_in_frame < watermark)
+ {
+ gsk_next_driver_release_texture_by_id (self->driver, shadow->texture_id);
+ g_array_remove_index_fast (self->shadows, i);
+ p--;
+ i--;
+ }
+ }
}
diff --git a/gsk/next/gskglshadowlibraryprivate.h b/gsk/next/gskglshadowlibraryprivate.h
index 57f952395c..437ad6d39d 100644
--- a/gsk/next/gskglshadowlibraryprivate.h
+++ b/gsk/next/gskglshadowlibraryprivate.h
@@ -25,17 +25,19 @@
G_BEGIN_DECLS
-typedef struct _GskGLShadowKey
-{
- GskRoundedRect rounded_rect;
- float blur_radius;
-} GskGLShadowKey;
-
#define GSK_TYPE_GL_SHADOW_LIBRARY (gsk_gl_shadow_library_get_type())
-G_DECLARE_FINAL_TYPE (GskGLShadowLibrary, gsk_gl_shadow_library, GSK, GL_SHADOW_LIBRARY, GskGLTextureLibrary)
-
-GskGLShadowLibrary *gsk_gl_shadow_library_new (GskNextDriver *driver);
+G_DECLARE_FINAL_TYPE (GskGLShadowLibrary, gsk_gl_shadow_library, GSK, GL_SHADOW_LIBRARY, GObject)
+
+GskGLShadowLibrary *gsk_gl_shadow_library_new (GskNextDriver *driver);
+void gsk_gl_shadow_library_begin_frame (GskGLShadowLibrary *self);
+guint gsk_gl_shadow_library_lookup (GskGLShadowLibrary *self,
+ const GskRoundedRect *outline,
+ float blur_radius);
+void gsk_gl_shadow_library_insert (GskGLShadowLibrary *self,
+ const GskRoundedRect *outline,
+ float blur_radius,
+ guint texture_id);
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]