[gtk/gamma-shenanigans: 1/9] Add private api to download textures




commit af087579d150ed61ae1c6e3e9b3b7cf0690a2de3
Author: Matthias Clasen <mclasen redhat com>
Date:   Tue Sep 7 12:18:31 2021 -0400

    Add private api to download textures
    
    Add a private api to download textures in formats
    other than the cairo one. This will let us download
    16bit and float textures without downgrading them
    to 8bpp.

 gdk/gdkgltexture.c      | 61 +++++++++++++++++++++++++++++++++++++++++++++++++
 gdk/gdkmemorytexture.c  | 13 +++++++++++
 gdk/gdktexture.c        | 18 +++++++++++++++
 gdk/gdktextureprivate.h |  6 +++++
 4 files changed, 98 insertions(+)
---
diff --git a/gdk/gdkgltexture.c b/gdk/gdkgltexture.c
index caf3e7ab6b..f0d3e40ac6 100644
--- a/gdk/gdkgltexture.c
+++ b/gdk/gdkgltexture.c
@@ -22,6 +22,8 @@
 
 #include "gdkcairo.h"
 #include "gdktextureprivate.h"
+#include "gdkmemorytextureprivate.h"
+#include "gdkinternals.h"
 
 #include <epoxy/gl.h>
 
@@ -110,6 +112,64 @@ gdk_gl_texture_download (GdkTexture         *texture,
   cairo_surface_destroy (surface);
 }
 
+static int
+type_from_internal_format (int internal_format)
+{
+  switch (internal_format)
+    {
+    case GL_RGB16:
+    case GL_RGBA16:
+      return GL_UNSIGNED_SHORT;
+    default:
+      g_assert_not_reached ();
+    }
+}
+
+static int
+internal_format_for_format (GdkMemoryFormat format)
+{
+  switch ((int)format)
+    {
+    case GDK_MEMORY_R16G16B16:
+      return GL_RGB16;
+    case GDK_MEMORY_R16G16B16A16_PREMULTIPLIED:
+      return GL_RGBA16;
+    default:
+      g_assert_not_reached ();
+    }
+}
+
+static GBytes *
+gdk_gl_texture_download_format (GdkTexture      *texture,
+                                GdkMemoryFormat  format)
+{
+  GdkGLTexture *self = GDK_GL_TEXTURE (texture);
+  GdkSurface *surface;
+  GdkGLContext *context;
+  int internal_format = 0;
+  gpointer data;
+  gsize size;
+
+  surface = gdk_gl_context_get_surface (self->context);
+  context = gdk_surface_get_paint_gl_context (surface, NULL);
+
+  gdk_gl_context_make_current (context);
+  glBindTexture (GL_TEXTURE_2D, self->id);
+  glGetTexLevelParameteriv (GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &internal_format);
+
+  if (internal_format != internal_format_for_format (format))
+    return NULL;
+
+  size = texture->width * texture->height * gdk_memory_format_bytes_per_pixel (format);
+  data = malloc (size);
+
+  glReadPixels (0, 0, texture->width, texture->height,
+                internal_format, type_from_internal_format (internal_format),
+                 data);
+
+  return g_bytes_new_take (data, size);
+}
+
 static void
 gdk_gl_texture_class_init (GdkGLTextureClass *klass)
 {
@@ -117,6 +177,7 @@ gdk_gl_texture_class_init (GdkGLTextureClass *klass)
   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 
   texture_class->download = gdk_gl_texture_download;
+  texture_class->download_format = gdk_gl_texture_download_format;
   gobject_class->dispose = gdk_gl_texture_dispose;
 }
 
diff --git a/gdk/gdkmemorytexture.c b/gdk/gdkmemorytexture.c
index 6b85901cf1..d6460ffc71 100644
--- a/gdk/gdkmemorytexture.c
+++ b/gdk/gdkmemorytexture.c
@@ -103,6 +103,18 @@ gdk_memory_texture_download (GdkTexture         *texture,
                       area->width, area->height);
 }
 
+static GBytes *
+gdk_memory_texture_download_format (GdkTexture      *texture,
+                                    GdkMemoryFormat  format)
+{
+  GdkMemoryTexture *self = GDK_MEMORY_TEXTURE (texture);
+
+  if (self->format == format)
+    return g_bytes_ref (self->bytes);
+
+  return NULL;
+}
+
 static void
 gdk_memory_texture_class_init (GdkMemoryTextureClass *klass)
 {
@@ -110,6 +122,7 @@ gdk_memory_texture_class_init (GdkMemoryTextureClass *klass)
   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 
   texture_class->download = gdk_memory_texture_download;
+  texture_class->download_format = gdk_memory_texture_download_format;
   gobject_class->dispose = gdk_memory_texture_dispose;
 }
 
diff --git a/gdk/gdktexture.c b/gdk/gdktexture.c
index 7ac4f1bb53..4681eec531 100644
--- a/gdk/gdktexture.c
+++ b/gdk/gdktexture.c
@@ -124,6 +124,13 @@ gdk_texture_real_download (GdkTexture         *self,
   GDK_TEXTURE_WARN_NOT_IMPLEMENTED_METHOD (self, download);
 }
 
+static GBytes *
+gdk_texture_real_download_format (GdkTexture      *self,
+                                  GdkMemoryFormat  format)
+{
+  return NULL;
+}
+
 static void
 gdk_texture_set_property (GObject      *gobject,
                           guint         prop_id,
@@ -188,6 +195,7 @@ gdk_texture_class_init (GdkTextureClass *klass)
   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 
   klass->download = gdk_texture_real_download;
+  klass->download_format = gdk_texture_real_download_format;
 
   gobject_class->set_property = gdk_texture_set_property;
   gobject_class->get_property = gdk_texture_get_property;
@@ -491,6 +499,16 @@ gdk_texture_download (GdkTexture *texture,
                              stride);
 }
 
+/* Returns the texture data in the requested format if that
+ * can be done without conversion. NULL, otherwise.
+ */
+GBytes *
+gdk_texture_download_format (GdkTexture      *texture,
+                             GdkMemoryFormat  format)
+{
+  return GDK_TEXTURE_GET_CLASS (texture)->download_format (texture, format);
+}
+
 gboolean
 gdk_texture_set_render_data (GdkTexture     *self,
                              gpointer        key,
diff --git a/gdk/gdktextureprivate.h b/gdk/gdktextureprivate.h
index 3e2e9f3a49..f00d712d08 100644
--- a/gdk/gdktextureprivate.h
+++ b/gdk/gdktextureprivate.h
@@ -2,6 +2,7 @@
 #define __GDK_TEXTURE_PRIVATE_H__
 
 #include "gdktexture.h"
+#include "gdkmemorytexture.h"
 
 G_BEGIN_DECLS
 
@@ -28,6 +29,8 @@ struct _GdkTextureClass {
                                                          const GdkRectangle     *area,
                                                          guchar                 *data,
                                                          gsize                   stride);
+  GBytes *              (* download_format)             (GdkTexture             *texture,
+                                                         GdkMemoryFormat         format);
 };
 
 gpointer                gdk_texture_new                 (const GdkTextureClass  *klass,
@@ -48,6 +51,9 @@ void                    gdk_texture_clear_render_data   (GdkTexture
 gpointer                gdk_texture_get_render_data     (GdkTexture             *self,
                                                          gpointer                key);
 
+GBytes *                gdk_texture_download_format     (GdkTexture             *texture,
+                                                         GdkMemoryFormat         format);
+
 G_END_DECLS
 
 #endif /* __GDK_TEXTURE_PRIVATE_H__ */


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