[gtk/wip/chergert/glproto: 208/493] implement basics for icon library




commit 30428094a3751b505bae9c8eb23b77d4a6cb7bdd
Author: Christian Hergert <chergert redhat com>
Date:   Tue Jan 19 17:13:46 2021 -0800

    implement basics for icon library

 gsk/next/gskgliconlibrary.c        | 149 ++++++++++++++++++++++++++++++++++++-
 gsk/next/gskgliconlibraryprivate.h |  24 +++++-
 2 files changed, 171 insertions(+), 2 deletions(-)
---
diff --git a/gsk/next/gskgliconlibrary.c b/gsk/next/gskgliconlibrary.c
index 207ff04ea5..b7b3c54a6c 100644
--- a/gsk/next/gskgliconlibrary.c
+++ b/gsk/next/gskgliconlibrary.c
@@ -20,6 +20,10 @@
 
 #include "config.h"
 
+#include <gdk/gdkglcontextprivate.h>
+#include <gdk/gdkmemorytextureprivate.h>
+#include <gdk/gdktextureprivate.h>
+
 #include "gskgldriverprivate.h"
 #include "gskgliconlibraryprivate.h"
 
@@ -40,6 +44,15 @@ gsk_gl_icon_library_new (GskNextDriver *driver)
                        NULL);
 }
 
+static void
+gsk_gl_icon_data_free (gpointer data)
+{
+  GskGLIconData *icon_data = data;
+
+  g_clear_object (&icon_data->source_texture);
+  g_slice_free (GskGLIconData, icon_data);
+}
+
 static void
 gsk_gl_icon_library_class_init (GskGLIconLibraryClass *klass)
 {
@@ -49,5 +62,139 @@ static void
 gsk_gl_icon_library_init (GskGLIconLibrary *self)
 {
   gsk_gl_texture_library_set_funcs (GSK_GL_TEXTURE_LIBRARY (self),
-                                    NULL, NULL, NULL, NULL);
+                                    NULL, NULL, NULL,
+                                    gsk_gl_icon_data_free);
+}
+
+void
+gsk_gl_icon_library_add (GskGLIconLibrary     *self,
+                         GdkTexture           *key,
+                         const GskGLIconData **out_value)
+{
+  cairo_surface_t *surface;
+  GskGLIconData *icon_data;
+  guint8 *pixel_data;
+  guint8 *surface_data;
+  guint8 *free_data = NULL;
+  guint gl_format;
+  guint gl_type;
+  int packed_x = 0;
+  int packed_y = 0;
+  int width;
+  int height;
+  guint texture_id;
+
+  g_return_if_fail (GSK_IS_GL_ICON_LIBRARY (self));
+  g_return_if_fail (GDK_IS_TEXTURE (key));
+  g_return_if_fail (out_value != NULL);
+
+  width = key->width;
+  height = key->height;
+
+  icon_data = gsk_gl_texture_library_pack (GSK_GL_TEXTURE_LIBRARY (self),
+                                           key,
+                                           sizeof (GskGLIconData),
+                                           width + 2,
+                                           height + 2);
+  icon_data->source_texture = g_object_ref (key);
+
+  /* actually upload the texture */
+  surface = gdk_texture_download_surface (key);
+  surface_data = cairo_image_surface_get_data (surface);
+  gdk_gl_context_push_debug_group_printf (gdk_gl_context_get_current (),
+                                          "Uploading texture");
+
+  if (gdk_gl_context_get_use_es (gdk_gl_context_get_current ()))
+    {
+      pixel_data = free_data = g_malloc (width * height * 4);
+      gdk_memory_convert (pixel_data, width * 4,
+                          GDK_MEMORY_R8G8B8A8_PREMULTIPLIED,
+                          surface_data, cairo_image_surface_get_stride (surface),
+                          GDK_MEMORY_DEFAULT, width, height);
+      gl_format = GL_RGBA;
+      gl_type = GL_UNSIGNED_BYTE;
+    }
+  else
+    {
+      pixel_data = surface_data;
+      gl_format = GL_BGRA;
+      gl_type = GL_UNSIGNED_INT_8_8_8_8_REV;
+    }
+
+  texture_id = GSK_GL_TEXTURE_ATLAS_ENTRY_TEXTURE (icon_data);
+
+  glBindTexture (GL_TEXTURE_2D, texture_id);
+
+  glTexSubImage2D (GL_TEXTURE_2D, 0,
+                   packed_x + 1, packed_y + 1,
+                   width, height,
+                   gl_format, gl_type,
+                   pixel_data);
+  /* Padding top */
+  glTexSubImage2D (GL_TEXTURE_2D, 0,
+                   packed_x + 1, packed_y,
+                   width, 1,
+                   gl_format, gl_type,
+                   pixel_data);
+  /* Padding left */
+  glTexSubImage2D (GL_TEXTURE_2D, 0,
+                   packed_x, packed_y + 1,
+                   1, height,
+                   gl_format, gl_type,
+                   pixel_data);
+  /* Padding top left */
+  glTexSubImage2D (GL_TEXTURE_2D, 0,
+                   packed_x, packed_y,
+                   1, 1,
+                   gl_format, gl_type,
+                   pixel_data);
+
+  /* Padding right */
+  glPixelStorei (GL_UNPACK_ROW_LENGTH, width);
+  glPixelStorei (GL_UNPACK_SKIP_PIXELS, width - 1);
+  glTexSubImage2D (GL_TEXTURE_2D, 0,
+                   packed_x + width + 1, packed_y + 1,
+                   1, height,
+                   gl_format, gl_type,
+                   pixel_data);
+  /* Padding top right */
+  glTexSubImage2D (GL_TEXTURE_2D, 0,
+                   packed_x + width + 1, packed_y,
+                   1, 1,
+                   gl_format, gl_type,
+                   pixel_data);
+  /* Padding bottom */
+  glPixelStorei (GL_UNPACK_SKIP_PIXELS, 0);
+  glPixelStorei (GL_UNPACK_ROW_LENGTH, 0);
+  glPixelStorei (GL_UNPACK_SKIP_ROWS, height - 1);
+  glTexSubImage2D (GL_TEXTURE_2D, 0,
+                   packed_x + 1, packed_y + 1 + height,
+                   width, 1,
+                   gl_format, gl_type,
+                   pixel_data);
+  /* Padding bottom left */
+  glTexSubImage2D (GL_TEXTURE_2D, 0,
+                   packed_x, packed_y + 1 + height,
+                   1, 1,
+                   gl_format, gl_type,
+                   pixel_data);
+  /* Padding bottom right */
+  glPixelStorei (GL_UNPACK_ROW_LENGTH, width);
+  glPixelStorei (GL_UNPACK_SKIP_PIXELS, width - 1);
+  glTexSubImage2D (GL_TEXTURE_2D, 0,
+                   packed_x + 1 + width, packed_y + 1 + height,
+                   1, 1,
+                   gl_format, gl_type,
+                   pixel_data);
+  /* Reset this */
+  glPixelStorei (GL_UNPACK_SKIP_PIXELS, 0);
+  glPixelStorei (GL_UNPACK_ROW_LENGTH, 0);
+  glPixelStorei (GL_UNPACK_SKIP_ROWS, 0);
+
+  gdk_gl_context_pop_debug_group (gdk_gl_context_get_current ());
+
+  *out_value = icon_data;
+
+  cairo_surface_destroy (surface);
+  g_free (free_data);
 }
diff --git a/gsk/next/gskgliconlibraryprivate.h b/gsk/next/gskgliconlibraryprivate.h
index 37812cc554..130c49d2bb 100644
--- a/gsk/next/gskgliconlibraryprivate.h
+++ b/gsk/next/gskgliconlibraryprivate.h
@@ -29,9 +29,31 @@ G_BEGIN_DECLS
 
 #define GSK_TYPE_GL_ICON_LIBRARY (gsk_gl_icon_library_get_type())
 
+typedef struct _GskGLIconData
+{
+  GskGLTextureAtlasEntry entry;
+  GdkTexture *source_texture;
+} GskGLIconData;
+
 G_DECLARE_FINAL_TYPE (GskGLIconLibrary, gsk_gl_icon_library, GSK, GL_ICON_LIBRARY, GskGLTextureLibrary)
 
-GskGLIconLibrary *gsk_gl_icon_library_new (GskNextDriver *driver);
+GskGLIconLibrary *gsk_gl_icon_library_new (GskNextDriver        *driver);
+void              gsk_gl_icon_library_add (GskGLIconLibrary     *self,
+                                           GdkTexture           *key,
+                                           const GskGLIconData **out_value);
+
+static inline void
+gsk_gl_icon_library_lookup_or_add (GskGLIconLibrary     *self,
+                                   GdkTexture           *key,
+                                   const GskGLIconData **out_value)
+{
+  GskGLTextureAtlasEntry *entry;
+
+  if G_LIKELY (gsk_gl_texture_library_lookup ((GskGLTextureLibrary *)self, key, &entry))
+    *out_value = (GskGLIconData *)entry;
+  else
+    gsk_gl_icon_library_add (self, key, out_value);
+}
 
 G_END_DECLS
 


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