[gtk/wip/matthiasc/shared-glyph-cache] Make the icon cache shared too



commit 86023b095381a50ea6d43b3c3c86b71363e8db6e
Author: Matthias Clasen <mclasen redhat com>
Date:   Tue Jun 4 02:49:14 2019 +0000

    Make the icon cache shared too
    
    Use the same approach to the icon cache
    that works for the glyph cache already.

 gsk/gl/gskgliconcache.c           | 108 +++++++++++++++++++++++++++++++-------
 gsk/gl/gskgliconcacheprivate.h    |   6 +--
 gsk/gl/gskglrenderer.c            |  25 +++++++--
 gsk/gl/gskgltextureatlas.c        |   1 -
 gsk/gl/gskgltextureatlasprivate.h |   1 -
 5 files changed, 112 insertions(+), 29 deletions(-)
---
diff --git a/gsk/gl/gskgliconcache.c b/gsk/gl/gskgliconcache.c
index 2ed2e568c5..6a4890d560 100644
--- a/gsk/gl/gskgliconcache.c
+++ b/gsk/gl/gskgliconcache.c
@@ -27,42 +27,54 @@ free_atlas (gpointer v)
 {
   GskGLTextureAtlas *atlas = v;
 
-  g_assert (atlas->image.texture_id == 0);
   gsk_gl_texture_atlas_free (atlas);
 
   g_free (atlas);
 }
 
-void
-gsk_gl_icon_cache_init (GskGLIconCache *self,
-                        GskRenderer    *renderer,
-                        GskGLDriver    *gl_driver)
+GskGLIconCache *
+gsk_gl_icon_cache_new (GdkDisplay *display)
 {
-  self->renderer = renderer;
-  self->gl_driver = gl_driver;
+  GskGLIconCache *self;
+
+  self = g_new0 (GskGLIconCache, 1);
+
+  self->display = display;
 
   self->atlases = g_ptr_array_new_with_free_func ((GDestroyNotify)free_atlas);
   self->icons = g_hash_table_new_full (NULL, NULL, NULL, icon_data_free);
+
+  return self;
+}
+
+static GdkGLContext *
+get_context (GskGLIconCache *cache)
+{
+  return (GdkGLContext *)g_object_get_data (G_OBJECT (cache->display), "shared_data_gl_context");
 }
 
 void
 gsk_gl_icon_cache_free (GskGLIconCache *self)
 {
+  GdkGLContext *context = get_context (self);
   guint i, p;
 
+  gdk_gl_context_make_current (context);
+
   for (i = 0, p = self->atlases->len; i < p; i ++)
     {
       GskGLTextureAtlas *atlas = g_ptr_array_index (self->atlases, i);
 
-      if (atlas->image.texture_id != 0)
+      if (atlas->texture_id != 0)
         {
-          gsk_gl_image_destroy (&atlas->image, self->gl_driver);
-          atlas->image.texture_id = 0;
+          glDeleteTextures (1, &atlas->texture_id);
+          atlas->texture_id = 0;
         }
     }
   g_ptr_array_free (self->atlases, TRUE);
-
   g_hash_table_unref (self->icons);
+
+  g_free (self);
 }
 
 void
@@ -72,6 +84,7 @@ gsk_gl_icon_cache_begin_frame (GskGLIconCache *self)
   GHashTableIter iter;
   GdkTexture *texture;
   IconData *icon_data;
+  GdkGLContext *previous = NULL;
 
   /* Increase frame age of all icons */
   g_hash_table_iter_init (&iter, self->icons);
@@ -108,16 +121,23 @@ gsk_gl_icon_cache_begin_frame (GskGLIconCache *self)
                 g_hash_table_iter_remove (&iter);
             }
 
-          if (atlas->image.texture_id != 0)
+          if (atlas->texture_id != 0)
             {
-              gsk_gl_image_destroy (&atlas->image, self->gl_driver);
-              atlas->image.texture_id = 0;
+              previous = gdk_gl_context_get_current ();
+              if (previous != get_context (self))
+                gdk_gl_context_make_current (get_context (self));
+
+              glDeleteTextures (1, &atlas->texture_id);
+              atlas->texture_id = 0;
             }
 
           g_ptr_array_remove_index_fast (self->atlases, i);
           i --; /* Check the current index again */
         }
     }
+
+  if (previous)
+    gdk_gl_context_make_current (previous);
 }
 
 /* FIXME: this could probably be done more efficiently */
@@ -150,6 +170,58 @@ pad_surface (cairo_surface_t *surface)
   return padded;
 }
 
+static guint
+create_shared_texture (GskGLIconCache *self,
+                       int             width,
+                       int             height)
+{
+  GdkGLContext *previous;
+  GdkGLContext *context;
+  guint texture_id;
+
+  previous = gdk_gl_context_get_current ();
+  context = get_context (self);
+
+  gdk_gl_context_make_current (context);
+
+  glGenTextures (1, &texture_id);
+  glBindTexture (GL_TEXTURE_2D, texture_id);
+
+  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+  glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+  if (gdk_gl_context_get_use_es (context))
+    glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+  else
+    glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
+
+  glBindTexture (GL_TEXTURE_2D, 0);
+
+  gdk_gl_context_make_current (previous);
+
+  return texture_id;
+}
+
+static void
+upload_region_or_else (GskGLIconCache *self,
+                       guint           texture_id,
+                       GskImageRegion *region)
+{
+  GdkGLContext *previous;
+
+  previous = gdk_gl_context_get_current ();
+  gdk_gl_context_make_current (get_context (self));
+
+  glBindTexture (GL_TEXTURE_2D, texture_id);
+  glTextureSubImage2D (texture_id, 0, region->x, region->y, region->width, region->height,
+                   GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, region->data);
+
+  gdk_gl_context_make_current (previous);
+}
+
 void
 gsk_gl_icon_cache_lookup_or_add (GskGLIconCache  *self,
                                  GdkTexture      *texture,
@@ -170,7 +242,7 @@ gsk_gl_icon_cache_lookup_or_add (GskGLIconCache  *self,
           icon_data->used = TRUE;
         }
 
-      *out_texture_id = icon_data->atlas->image.texture_id;
+      *out_texture_id = icon_data->atlas->texture_id;
       *out_texture_rect = icon_data->texture_rect;
       return;
     }
@@ -208,7 +280,7 @@ gsk_gl_icon_cache_lookup_or_add (GskGLIconCache  *self,
         /* No atlas has enough space, so create a new one... */
         atlas = g_malloc (sizeof (GskGLTextureAtlas));
         gsk_gl_texture_atlas_init (atlas, ATLAS_SIZE, ATLAS_SIZE);
-        gsk_gl_image_create (&atlas->image, self->gl_driver, atlas->width, atlas->height, GL_LINEAR, 
GL_LINEAR);
+        atlas->texture_id = create_shared_texture (self, atlas->width, atlas->height);
         /* Pack it onto that one, which surely has enought space... */
         gsk_gl_texture_atlas_pack (atlas, twidth + 2, theight + 2, &packed_x, &packed_y);
         packed_x += 1;
@@ -238,9 +310,9 @@ gsk_gl_icon_cache_lookup_or_add (GskGLIconCache  *self,
     region.height = theight + 2;
     region.data = cairo_image_surface_get_data (padded_surface);
 
-    gsk_gl_image_upload_region (&atlas->image, self->gl_driver, &region);
+    upload_region_or_else (self, atlas->texture_id, &region);
 
-    *out_texture_id = atlas->image.texture_id;
+    *out_texture_id = atlas->texture_id;
     *out_texture_rect = icon_data->texture_rect;
 
     cairo_surface_destroy (surface);
diff --git a/gsk/gl/gskgliconcacheprivate.h b/gsk/gl/gskgliconcacheprivate.h
index 883a274ded..36f30087fa 100644
--- a/gsk/gl/gskgliconcacheprivate.h
+++ b/gsk/gl/gskgliconcacheprivate.h
@@ -10,17 +10,15 @@
 
 typedef struct
 {
+  GdkDisplay *display;
   GskGLDriver *gl_driver;
-  GskRenderer *renderer;
 
   GPtrArray *atlases;
   GHashTable *icons; /* GdkTexture -> IconData */
 
 } GskGLIconCache;
 
-void             gsk_gl_icon_cache_init           (GskGLIconCache        *self,
-                                                   GskRenderer            *renderer,
-                                                   GskGLDriver            *gl_driver);
+GskGLIconCache * gsk_gl_icon_cache_new            (GdkDisplay *display);
 void             gsk_gl_icon_cache_free           (GskGLIconCache        *self);
 void             gsk_gl_icon_cache_begin_frame    (GskGLIconCache        *self);
 void             gsk_gl_icon_cache_lookup_or_add  (GskGLIconCache        *self,
diff --git a/gsk/gl/gskglrenderer.c b/gsk/gl/gskglrenderer.c
index 75a8e2969f..a090340f59 100644
--- a/gsk/gl/gskglrenderer.c
+++ b/gsk/gl/gskglrenderer.c
@@ -336,7 +336,7 @@ struct _GskGLRenderer
   GArray *render_ops;
 
   GskGLGlyphCache *glyph_cache;
-  GskGLIconCache icon_cache;
+  GskGLIconCache *icon_cache;
   GskGLShadowCache shadow_cache;
 
 #ifdef G_ENABLE_DEBUG
@@ -832,7 +832,7 @@ render_texture_node (GskGLRenderer       *self,
         {
           graphene_rect_t trect;
 
-          gsk_gl_icon_cache_lookup_or_add (&self->icon_cache,
+          gsk_gl_icon_cache_lookup_or_add (self->icon_cache,
                                            texture,
                                            &texture_id,
                                            &trect);
@@ -2479,6 +2479,21 @@ get_glyph_cache_for_display (GdkDisplay *display)
   return glyph_cache;
 }
 
+static GskGLIconCache *
+get_icon_cache_for_display (GdkDisplay *display)
+{
+  GskGLIconCache *icon_cache;
+
+  icon_cache = (GskGLIconCache*)g_object_get_data (G_OBJECT (display), "gl-icon-cache");
+  if (icon_cache == NULL)
+    {
+      icon_cache = gsk_gl_icon_cache_new (display);
+      g_object_set_data_full (G_OBJECT (display), "gl-icon-cache", icon_cache, (GDestroyNotify) 
gsk_gl_icon_cache_free);
+    }
+
+  return icon_cache;
+}
+
 static gboolean
 gsk_gl_renderer_realize (GskRenderer  *renderer,
                          GdkSurface    *surface,
@@ -2510,7 +2525,7 @@ gsk_gl_renderer_realize (GskRenderer  *renderer,
     return FALSE;
 
   self->glyph_cache = get_glyph_cache_for_display (gdk_surface_get_display (surface));
-  gsk_gl_icon_cache_init (&self->icon_cache, renderer, self->gl_driver);
+  self->icon_cache = get_icon_cache_for_display (gdk_surface_get_display (surface));
   gsk_gl_shadow_cache_init (&self->shadow_cache);
 
   return TRUE;
@@ -2536,7 +2551,7 @@ gsk_gl_renderer_unrealize (GskRenderer *renderer)
     glDeleteProgram (self->programs[i].id);
 
   self->glyph_cache = NULL;
-  gsk_gl_icon_cache_free (&self->icon_cache);
+  self->icon_cache = NULL;
   gsk_gl_shadow_cache_free (&self->shadow_cache, self->gl_driver);
 
   g_clear_object (&self->gl_profiler);
@@ -3103,7 +3118,7 @@ gsk_gl_renderer_do_render (GskRenderer           *renderer,
   graphene_matrix_scale (&projection, 1, -1, 1);
 
   gsk_gl_glyph_cache_begin_frame (self->glyph_cache);
-  gsk_gl_icon_cache_begin_frame (&self->icon_cache);
+  gsk_gl_icon_cache_begin_frame (self->icon_cache);
   gsk_gl_shadow_cache_begin_frame (&self->shadow_cache, self->gl_driver);
 
   ops_set_projection (&self->op_builder, &projection);
diff --git a/gsk/gl/gskgltextureatlas.c b/gsk/gl/gskgltextureatlas.c
index 370f97bd89..7befcfbbe3 100644
--- a/gsk/gl/gskgltextureatlas.c
+++ b/gsk/gl/gskgltextureatlas.c
@@ -10,7 +10,6 @@ gsk_gl_texture_atlas_init (GskGLTextureAtlas *self,
   memset (self, 0, sizeof (*self));
 
   self->texture_id = 0;
-  self->image.texture_id = 0;
   self->width = width;
   self->height = height;
 
diff --git a/gsk/gl/gskgltextureatlasprivate.h b/gsk/gl/gskgltextureatlasprivate.h
index d780b13395..cfa865446d 100644
--- a/gsk/gl/gskgltextureatlasprivate.h
+++ b/gsk/gl/gskgltextureatlasprivate.h
@@ -15,7 +15,6 @@ struct _GskGLTextureAtlas
   int height;
 
   guint texture_id;
-  GskGLImage image;
 
   int unused_pixels; /* Pixels of rects that have been used at some point,
                         But are now unused. */


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