[gtk/wip/baedert/transforms6: 4/31] gl renderer: Cache offscreen textures per node, not size



commit c0cf592336370bcec95b60fde4cbe0fa5f067002
Author: Timm Bäder <mail baedert org>
Date:   Wed Nov 28 18:40:48 2018 +0100

    gl renderer: Cache offscreen textures per node, not size

 gsk/gl/gskgldriver.c        | 84 ++++++++++++++++++++++++++-------------------
 gsk/gl/gskgldriverprivate.h |  5 +++
 gsk/gl/gskglrenderer.c      | 35 ++++++++++++++-----
 3 files changed, 80 insertions(+), 44 deletions(-)
---
diff --git a/gsk/gl/gskgldriver.c b/gsk/gl/gskgldriver.c
index 2a2c980ce4..c88b93b52a 100644
--- a/gsk/gl/gskgldriver.c
+++ b/gsk/gl/gskgldriver.c
@@ -46,6 +46,7 @@ struct _GskGLDriver
   Fbo default_fbo;
 
   GHashTable *textures;
+  GHashTable *pointer_textures;
 
   const Texture *bound_source_texture;
   const Fbo *bound_fbo;
@@ -119,6 +120,7 @@ gsk_gl_driver_finalize (GObject *gobject)
   gdk_gl_context_make_current (self->gl_context);
 
   g_clear_pointer (&self->textures, g_hash_table_unref);
+  g_clear_pointer (&self->pointer_textures, g_hash_table_unref);
   g_clear_object (&self->profiler);
 
   if (self->gl_context == gdk_gl_context_get_current ())
@@ -263,7 +265,28 @@ gsk_gl_driver_collect_textures (GskGLDriver *self)
             }
         }
       else
-        g_hash_table_iter_remove (&iter);
+        {
+          /* Remove from self->pointer_textures. */
+          /* TODO: Is there a better way for this? */
+          if (self->pointer_textures)
+            {
+              GHashTableIter pointer_iter;
+              gpointer value;
+              gpointer p;
+
+              g_hash_table_iter_init (&pointer_iter, self->pointer_textures);
+              while (g_hash_table_iter_next (&pointer_iter, &p, &value))
+                {
+                  if (GPOINTER_TO_INT (value) == t->texture_id)
+                    {
+                      g_hash_table_iter_remove (&pointer_iter);
+                      break;
+                    }
+                }
+            }
+
+          g_hash_table_iter_remove (&iter);
+        }
     }
 
   return old_size - g_hash_table_size (self->textures);
@@ -307,26 +330,6 @@ gsk_gl_driver_get_fbo (GskGLDriver *self,
   return &t->fbo;
 }
 
-static Texture *
-find_texture_by_size (GHashTable *textures,
-                      int         width,
-                      int         height)
-{
-  GHashTableIter iter;
-  gpointer value_p = NULL;
-
-  g_hash_table_iter_init (&iter, textures);
-  while (g_hash_table_iter_next (&iter, NULL, &value_p))
-    {
-      Texture *t = value_p;
-
-      if (t->width == width && t->height == height)
-        return t;
-    }
-
-  return NULL;
-}
-
 static Texture *
 create_texture (GskGLDriver *self,
                 float        fwidth,
@@ -351,21 +354,7 @@ create_texture (GskGLDriver *self,
       height = MIN (height, self->max_texture_size);
     }
 
-  t = find_texture_by_size (self->textures, width, height);
-  if (t != NULL && !t->in_use && t->user == NULL)
-    {
-      GSK_NOTE (OPENGL, g_message ("Reusing Texture(%d) for size %dx%d",
-                                 t->texture_id, t->width, t->height));
-      t->in_use = TRUE;
-
-#ifdef G_ENABLE_DEBUG
-      gsk_profiler_counter_inc (self->profiler, self->counters.reused_textures);
-#endif
-      return t;
-    }
-
   glGenTextures (1, &texture_id);
-
   t = texture_new ();
   t->texture_id = texture_id;
   t->width = width;
@@ -547,6 +536,31 @@ gsk_gl_driver_get_texture_for_texture (GskGLDriver *self,
   return t->texture_id;
 }
 
+int
+gsk_gl_driver_get_texture_for_pointer (GskGLDriver *self,
+                                       gpointer     pointer)
+{
+  int id = 0;
+
+  if (G_UNLIKELY (self->pointer_textures == NULL))
+    self->pointer_textures = g_hash_table_new (NULL, NULL);
+
+  id = GPOINTER_TO_INT (g_hash_table_lookup (self->pointer_textures, pointer));
+
+  return id;
+}
+
+void
+gsk_gl_driver_set_texture_for_pointer (GskGLDriver *self,
+                                       gpointer     pointer,
+                                       int          texture_id)
+{
+  if (G_UNLIKELY (self->pointer_textures == NULL))
+    self->pointer_textures = g_hash_table_new (NULL, NULL);
+
+  g_hash_table_insert (self->pointer_textures, pointer, GINT_TO_POINTER (texture_id));
+}
+
 int
 gsk_gl_driver_create_permanent_texture (GskGLDriver *self,
                                         float        width,
diff --git a/gsk/gl/gskgldriverprivate.h b/gsk/gl/gskgldriverprivate.h
index 7d7a41fe28..8ceecb183a 100644
--- a/gsk/gl/gskgldriverprivate.h
+++ b/gsk/gl/gskgldriverprivate.h
@@ -33,6 +33,11 @@ int             gsk_gl_driver_get_texture_for_texture   (GskGLDriver     *driver
                                                          GdkTexture      *texture,
                                                          int              min_filter,
                                                          int              mag_filter);
+int             gsk_gl_driver_get_texture_for_pointer   (GskGLDriver     *driver,
+                                                         gpointer         pointer);
+void            gsk_gl_driver_set_texture_for_pointer   (GskGLDriver     *driver,
+                                                         gpointer         pointer,
+                                                         int              texture_id);
 int             gsk_gl_driver_create_permanent_texture  (GskGLDriver     *driver,
                                                          float            width,
                                                          float            height);
diff --git a/gsk/gl/gskglrenderer.c b/gsk/gl/gskglrenderer.c
index f8074a4531..a75f8b3823 100644
--- a/gsk/gl/gskglrenderer.c
+++ b/gsk/gl/gskglrenderer.c
@@ -2255,7 +2255,7 @@ add_offscreen_ops (GskGLRenderer   *self,
                    float            min_y,
                    float            max_y,
                    GskRenderNode   *child_node,
-                   int             *texture_id,
+                   int             *texture_id_out,
                    gboolean        *is_offscreen,
                    gboolean         force_offscreen,
                    gboolean         reset_clip)
@@ -2271,6 +2271,7 @@ add_offscreen_ops (GskGLRenderer   *self,
   graphene_rect_t prev_viewport;
   graphene_matrix_t item_proj;
   GskRoundedRect prev_clip;
+  int texture_id = 0;
 
   /* We need the child node as a texture. If it already is one, we don't need to draw
    * it on a framebuffer of course. */
@@ -2281,18 +2282,31 @@ add_offscreen_ops (GskGLRenderer   *self,
 
       get_gl_scaling_filters (child_node, &gl_min_filter, &gl_mag_filter);
 
-      *texture_id = gsk_gl_driver_get_texture_for_texture (self->gl_driver,
-                                                           texture,
-                                                           gl_min_filter,
-                                                           gl_mag_filter);
+      *texture_id_out = gsk_gl_driver_get_texture_for_texture (self->gl_driver,
+                                                               texture,
+                                                               gl_min_filter,
+                                                               gl_mag_filter);
       *is_offscreen = FALSE;
       return;
     }
 
-  *texture_id = gsk_gl_driver_create_texture (self->gl_driver, width, height);
-  gsk_gl_driver_bind_source_texture (self->gl_driver, *texture_id);
-  gsk_gl_driver_init_texture_empty (self->gl_driver, *texture_id);
-  render_target = gsk_gl_driver_create_render_target (self->gl_driver, *texture_id, TRUE, TRUE);
+  /* Check if we've already cached the drawn texture. */
+  {
+    const int cached_id = gsk_gl_driver_get_texture_for_pointer (self->gl_driver, child_node);
+
+    if (cached_id != 0)
+      {
+        *texture_id_out = cached_id;
+        /* We didn't render it offscreen, but hand out an offscreen texture id */
+        *is_offscreen = TRUE;
+        return;
+      }
+  }
+
+  texture_id = gsk_gl_driver_create_texture (self->gl_driver, width, height);
+  gsk_gl_driver_bind_source_texture (self->gl_driver, texture_id);
+  gsk_gl_driver_init_texture_empty (self->gl_driver, texture_id);
+  render_target = gsk_gl_driver_create_render_target (self->gl_driver, texture_id, TRUE, TRUE);
 
   graphene_matrix_init_ortho (&item_proj,
                               min_x * scale, max_x * scale,
@@ -2328,6 +2342,9 @@ add_offscreen_ops (GskGLRenderer   *self,
   ops_set_render_target (builder, prev_render_target);
 
   *is_offscreen = TRUE;
+  *texture_id_out = texture_id;
+
+  gsk_gl_driver_set_texture_for_pointer (self->gl_driver, child_node, texture_id);
 }
 
 static void


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