[gtk/wip/matthiasc/shared-glyph-cache: 3/3] More hackery



commit c77cedeba06786d604123de142af196254cc3bda
Author: Matthias Clasen <mclasen redhat com>
Date:   Mon Jun 3 22:16:41 2019 +0000

    More hackery
    
    This gets a shared glyph cache mostly working.
    A few glyphs go missing, for whatever reason.

 gdk/gdksurface.c                   |   1 +
 gdk/wayland/gdkglcontext-wayland.c |  45 ++++++++++++++-
 gsk/gl/gskglglyphcache.c           | 112 ++++++++++++++++++++++++++++++++-----
 3 files changed, 141 insertions(+), 17 deletions(-)
---
diff --git a/gdk/gdksurface.c b/gdk/gdksurface.c
index f670291477..082918d895 100644
--- a/gdk/gdksurface.c
+++ b/gdk/gdksurface.c
@@ -1110,6 +1110,7 @@ gdk_surface_get_state (GdkSurface *surface)
   return surface->state;
 }
 
+
 GdkGLContext *
 gdk_surface_get_paint_gl_context (GdkSurface  *surface,
                                   GError    **error)
diff --git a/gdk/wayland/gdkglcontext-wayland.c b/gdk/wayland/gdkglcontext-wayland.c
index 79751cb8fc..4fbcf89852 100644
--- a/gdk/wayland/gdkglcontext-wayland.c
+++ b/gdk/wayland/gdkglcontext-wayland.c
@@ -40,6 +40,44 @@ static void gdk_wayland_gl_context_dispose (GObject *gobject);
 
 #define N_EGL_ATTRS     16
 
+static int in_shared_data_creation;
+
+static GdkGLContext *
+ensure_shared_data_context (GdkSurface *surface)
+{ 
+  GdkDisplay *display;
+  GdkGLContext *context;
+
+  in_shared_data_creation = 1;
+
+  display = gdk_surface_get_display (surface);
+  context = (GdkGLContext *)g_object_get_data (G_OBJECT (display), "shared_data_gl_context");
+  if (context == NULL)
+    {
+      GError *error = NULL;
+      context = GDK_SURFACE_GET_CLASS (surface)->create_gl_context (surface, FALSE, NULL, &error);
+      if (context == NULL)
+        {
+          g_warning ("Failed to create shared context: %s", error->message);
+          g_clear_error (&error);
+        }
+
+      gdk_gl_context_realize (context, &error);
+      if (context == NULL)
+        {
+          g_warning ("Failed to realize shared context: %s", error->message);
+          g_clear_error (&error);
+        }
+
+
+      g_object_set_data (G_OBJECT (display), "shared_data_gl_context", context);
+    }
+
+  in_shared_data_creation = 0;
+
+  return context;
+}
+
 static gboolean
 gdk_wayland_gl_context_realize (GdkGLContext *context,
                                 GError      **error)
@@ -47,6 +85,7 @@ gdk_wayland_gl_context_realize (GdkGLContext *context,
   GdkWaylandGLContext *context_wayland = GDK_WAYLAND_GL_CONTEXT (context);
   GdkDisplay *display = gdk_gl_context_get_display (context);
   GdkGLContext *share = gdk_gl_context_get_shared_context (context);
+  GdkGLContext *shared_data_context = in_shared_data_creation ? NULL : ensure_shared_data_context 
(gdk_gl_context_get_surface (context));
   GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (display);
   EGLContext ctx;
   EGLint context_attribs[N_EGL_ATTRS];
@@ -114,7 +153,8 @@ gdk_wayland_gl_context_realize (GdkGLContext *context,
   ctx = eglCreateContext (display_wayland->egl_display,
                           context_wayland->egl_config,
                           share != NULL ? GDK_WAYLAND_GL_CONTEXT (share)->egl_context
-                                        : EGL_NO_CONTEXT,
+                             : shared_data_context != NULL ? GDK_WAYLAND_GL_CONTEXT 
(shared_data_context)->egl_context
+                                                  : EGL_NO_CONTEXT,
                           context_attribs);
 
   /* If context creation failed without the legacy bit, let's try again with it */
@@ -136,7 +176,8 @@ gdk_wayland_gl_context_realize (GdkGLContext *context,
       ctx = eglCreateContext (display_wayland->egl_display,
                               context_wayland->egl_config,
                               share != NULL ? GDK_WAYLAND_GL_CONTEXT (share)->egl_context
-                                            : EGL_NO_CONTEXT,
+                                 : shared_data_context != NULL ? GDK_WAYLAND_GL_CONTEXT 
(shared_data_context)->egl_context
+                                    : EGL_NO_CONTEXT,
                               context_attribs);
     }
 
diff --git a/gsk/gl/gskglglyphcache.c b/gsk/gl/gskglglyphcache.c
index 1699d227d2..7080380762 100644
--- a/gsk/gl/gskglglyphcache.c
+++ b/gsk/gl/gskglglyphcache.c
@@ -53,7 +53,7 @@ free_atlas (gpointer v)
 {
   GskGLTextureAtlas *atlas = v;
 
-  g_assert (atlas->image.texture_id == 0);
+  //g_assert (atlas->image.texture_id == 0);
   gsk_gl_texture_atlas_free (atlas);
 
   g_free (atlas);
@@ -73,6 +73,7 @@ gsk_gl_glyph_cache_free (GskGLGlyphCache *self,
 {
   guint i;
 
+#if 0
   for (i = 0; i < self->atlases->len; i ++)
     {
       GskGLTextureAtlas *atlas = g_ptr_array_index (self->atlases, i);
@@ -83,6 +84,7 @@ gsk_gl_glyph_cache_free (GskGLGlyphCache *self,
           atlas->image.texture_id = 0;
         }
     }
+#endif
 
   g_ptr_array_unref (self->atlases);
   g_hash_table_unref (self->hash_table);
@@ -260,36 +262,72 @@ render_glyph (const GskGLTextureAtlas *atlas,
 }
 
 static void
-upload_region_or_else (guint           texture_id,
+check_gl_error (const char *s)
+{
+  int error = glGetError ();
+
+  switch (error)
+    {
+    case GL_INVALID_OPERATION:
+      g_print ("%s: INVALID_OPERATION\n", s);
+      break;
+    case GL_INVALID_ENUM:
+      g_print ("%s: INVALID_ENUM\n", s);
+      break;
+    case GL_INVALID_VALUE:
+      g_print ("%s: INVALID_VALUE\n", s);
+      break;
+    case GL_OUT_OF_MEMORY:
+      g_print ("%s: OUT_OF_MEMORY\n", s);
+      break;
+    case GL_INVALID_FRAMEBUFFER_OPERATION:
+      g_print ("%s: INVALID_FRAMEBUFFER_OPERATION\n", s);
+      break;
+    case GL_NO_ERROR:
+      break;
+    default:
+      g_print ("%s: error %d\n", s, error);
+    }
+}
+
+static void
+upload_region_or_else (GdkDisplay *display,
+                       guint           texture_id,
                        GskImageRegion *region)
 {
+  GdkGLContext *previous;
+  GdkGLContext *context;
+
+  previous = gdk_gl_context_get_current ();
+
+  context = (GdkGLContext *)g_object_get_data (G_OBJECT (display), "shared_data_gl_context");
+  gdk_gl_context_make_current (context);
+
+  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);
+  check_gl_error ("upload region");
 
+  gdk_gl_context_make_current (previous);
 }
 
 static void
 upload_dirty_glyph (GskGLGlyphCache   *self,
-                    GskGLTextureAtlas *atlas,
-                    GskGLDriver       *driver)
+                    GskGLDriver       *driver,
+                    GskGLTextureAtlas *atlas)
 {
   GskImageRegion region;
 
   g_assert (atlas->user_data != NULL);
 
-  gdk_gl_context_push_debug_group_printf (gsk_gl_driver_get_gl_context (driver),
-                                          "Uploading glyph %d", ((DirtyGlyph 
*)atlas->user_data)->key->glyph);
-
   if (render_glyph (atlas, (DirtyGlyph *)atlas->user_data, &region))
     {
-      upload_region_or_else (atlas->image.texture_id, &region);
+      GdkDisplay *display =  gdk_gl_context_get_display (gsk_gl_driver_get_gl_context (driver));
+      upload_region_or_else (display, atlas->image.texture_id, &region);
 
       g_free (region.data);
     }
 
-  gdk_gl_context_pop_debug_group (gsk_gl_driver_get_gl_context (driver));
-  /* TODO: This could be unnecessary. We can just reuse the allocated
-   *       DirtyGlyph next time. */
   g_clear_pointer (&atlas->user_data, g_free);
 }
 
@@ -361,6 +399,44 @@ gsk_gl_glyph_cache_lookup (GskGLGlyphCache *cache,
   return value;
 }
 
+static guint
+create_shared_texture (GdkDisplay *display,
+                       int width,
+                       int height)
+{
+  GdkGLContext *previous;
+  GdkGLContext *context;
+  guint texture_id;
+
+  previous = gdk_gl_context_get_current ();
+
+  context = (GdkGLContext *)g_object_get_data (G_OBJECT (display), "shared_data_gl_context");
+  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);
+
+  check_gl_error ("create shared texture");
+
+  gdk_gl_context_make_current (previous);
+
+g_print ("shared glyph atlas texture: %d\n", texture_id);
+  return texture_id;
+}
+
 guint
 gsk_gl_glyph_cache_get_glyph_texture_id (GskGLGlyphCache        *self,
                                          GskGLDriver            *driver,
@@ -372,14 +448,18 @@ gsk_gl_glyph_cache_get_glyph_texture_id (GskGLGlyphCache        *self,
 
   if (atlas->image.texture_id == 0)
     {
+#if 1
+      GdkDisplay *display =  gdk_gl_context_get_display (gsk_gl_driver_get_gl_context (driver));
+      atlas->image.texture_id = create_shared_texture (display, atlas->width, atlas->height);
+      atlas->image.width = atlas->width;
+      atlas->image.height = atlas->height;
+#else
       gsk_gl_image_create (&atlas->image, driver, atlas->width, atlas->height, GL_LINEAR, GL_LINEAR);
-      gdk_gl_context_label_object_printf (gsk_gl_driver_get_gl_context (driver),
-                                          GL_TEXTURE, atlas->image.texture_id,
-                                          "Glyph atlas %d", atlas->image.texture_id);
+#endif
     }
 
   if (atlas->user_data != NULL)
-    upload_dirty_glyph (self, atlas, driver);
+    upload_dirty_glyph (self, driver, atlas);
 
   return atlas->image.texture_id;
 }
@@ -420,11 +500,13 @@ gsk_gl_glyph_cache_begin_frame (GskGLGlyphCache *self,
                                      g_strdup_printf ("dropped_%d.png", kk++));
 #endif
 
+#if 0
           if (atlas->image.texture_id != 0)
             {
               gsk_gl_image_destroy (&atlas->image, driver);
               atlas->image.texture_id = 0;
             }
+#endif
 
           g_hash_table_add (removed, atlas);
 


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