[gtk/wip/otte/memoryformat: 25/28] texture: Refactor downloading




commit 0bf38ebeec59aafbf64a41448d45cd105f246576
Author: Benjamin Otte <otte redhat com>
Date:   Thu Oct 7 06:19:41 2021 +0200

    texture: Refactor downloading
    
    Pass a format do GdkTextureClass::download(). That way we can download
    data in any format.
    
    Also replace gdk_texture_download_texture() with
    gdk_memory_texture_from_texture() which again takes a format.
    
    The old functionality is still there for code that wants it: Just pass
    gdk_texture_get_format (texture) as the format argument.

 gdk/gdkgltexture.c            | 173 ++++++++++++------------------------------
 gdk/gdkmemorytexture.c        |  69 ++++++++++-------
 gdk/gdkmemorytextureprivate.h |   3 +
 gdk/gdktexture.c              |  71 ++++++-----------
 gdk/gdktextureprivate.h       |  14 ++--
 gdk/loaders/gdkpng.c          |   4 +-
 gdk/loaders/gdktiff.c         |   4 +-
 gsk/ngl/gskngldriver.c        |  21 ++---
 8 files changed, 138 insertions(+), 221 deletions(-)
---
diff --git a/gdk/gdkgltexture.c b/gdk/gdkgltexture.c
index e39fcd3fbb..a6d6d6e9b3 100644
--- a/gdk/gdkgltexture.c
+++ b/gdk/gdkgltexture.c
@@ -109,15 +109,27 @@ gdk_gl_texture_run (GdkGLTexture *self,
   while (g_atomic_int_get (&invoke.spinlock) == 0);
 }
 
+typedef struct _Download Download;
+
+struct _Download
+{
+  guint gl_internalformat;
+  guint gl_format;
+  guint gl_type;
+  guchar *data;
+  gsize stride;
+};
+
 static inline void
-gdk_gl_texture_get_tex_image (GdkGLTexture *self,
-                              GLenum        gl_format,
-                              GLenum        gl_type,
-                              GLvoid       *data)
+gdk_gl_texture_do_download (gpointer texture_,
+                            gpointer download_)
 {
+  GdkGLTexture *self = texture_;
+  GdkTexture *texture = texture_;
+  Download *download = download_;
+
   if (gdk_gl_context_get_use_es (self->context))
     {
-      GdkTexture *texture = GDK_TEXTURE (self);
       GLuint fbo;
 
       glGenFramebuffers (1, &fbo);
@@ -125,9 +137,9 @@ gdk_gl_texture_get_tex_image (GdkGLTexture *self,
       glFramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, self->id, 0);
       glReadPixels (0, 0,
                     texture->width, texture->height, 
-                    gl_format,
-                    gl_type,
-                    data);
+                    download->gl_format,
+                    download->gl_type,
+                    download->data);
       glBindFramebuffer (GL_FRAMEBUFFER, 0);
       glDeleteFramebuffers (1, &fbo);
     }
@@ -135,136 +147,48 @@ gdk_gl_texture_get_tex_image (GdkGLTexture *self,
     {
       glGetTexImage (GL_TEXTURE_2D,
                      0,
-                     gl_format,
-                     gl_type,
-                     data);
+                     download->gl_format,
+                     download->gl_type,
+                     download->data);
     }
 }
 
 static void
-gdk_gl_texture_do_download_texture (gpointer texture_,
-                                    gpointer result_)
-{
-  GdkTexture *texture = texture_;
-  GdkTexture **result = result_;
-  guint gl_internalformat, gl_format, gl_type;
-  guchar *data;
-  gsize stride;
-  GBytes *bytes;
-
-  if (!gdk_memory_format_gl_format (texture->format,
-                                    gdk_gl_context_get_use_es (gdk_gl_context_get_current ()),
-                                    &gl_internalformat,
-                                    &gl_format,
-                                    &gl_type))
-    {
-      g_assert_not_reached ();
-    }
-
-  stride = gdk_memory_format_bytes_per_pixel (texture->format) * texture->width;
-  data = g_malloc_n (stride, texture->height);
-
-  gdk_gl_texture_get_tex_image (texture_,
-                                gl_format,
-                                gl_type,
-                                data);
-
-  bytes = g_bytes_new_take (data, stride * texture->height);
-  *result = gdk_memory_texture_new (texture->width,
-                                    texture->height,
-                                    texture->format,
-                                    bytes,
-                                    stride);
-
-  g_bytes_unref (bytes);
-}
-
-static GdkTexture *
-gdk_gl_texture_download_texture (GdkTexture *texture)
-{
-  GdkGLTexture *self = GDK_GL_TEXTURE (texture);
-  GdkTexture *result;
-
-  if (self->saved)
-    return g_object_ref (self->saved);
-
-  gdk_gl_texture_run (self, gdk_gl_texture_do_download_texture, &result);
-
-  return result;
-}
-
-static void
-gdk_gl_texture_do_download (gpointer texture,
-                            gpointer data)
-{
-  glGetTexImage (GL_TEXTURE_2D,
-                 0,
-                 GL_BGRA,
-#if G_BYTE_ORDER == G_LITTLE_ENDIAN
-                 GL_UNSIGNED_INT_8_8_8_8_REV,
-#elif G_BYTE_ORDER == G_BIG_ENDIAN
-                 GL_UNSIGNED_BYTE,
-#else
-#error "Unknown byte order for gdk_gl_texture_download()"
-#endif
-                 data);
-}
-
-static void
-gdk_gl_texture_download (GdkTexture *texture,
-                         guchar     *data,
-                         gsize       stride)
+gdk_gl_texture_download (GdkTexture      *texture,
+                         GdkMemoryFormat  format,
+                         guchar          *data,
+                         gsize            stride)
 {
   GdkGLTexture *self = GDK_GL_TEXTURE (texture);
+  Download download;
 
   if (self->saved)
     {
-      gdk_texture_download (self->saved, data, stride);
+      gdk_texture_do_download (self->saved, format, data, stride);
       return;
     }
 
-  if (gdk_gl_context_get_use_es (self->context) ||
-      stride != texture->width * 4)
-    {
-      GDK_TEXTURE_CLASS (gdk_gl_texture_parent_class)->download (texture, data, stride);
-      return;
-    }
-
-  gdk_gl_texture_run (self, gdk_gl_texture_do_download, data);
-}
-
-static void
-gdk_gl_texture_do_download_float (gpointer texture,
-                                  gpointer data)
-{
-  glGetTexImage (GL_TEXTURE_2D,
-                 0,
-                 GL_RGBA,
-                 GL_FLOAT,
-                 data);
-}
-
-static void
-gdk_gl_texture_download_float (GdkTexture *texture,
-                               float      *data,
-                               gsize       stride)
-{
-  GdkGLTexture *self = GDK_GL_TEXTURE (texture);
+  download.data = data;
+  download.stride = stride;
 
-  if (self->saved)
+  if (stride != texture->width * gdk_memory_format_bytes_per_pixel (format) ||
+      !gdk_memory_format_gl_format (format,
+                                    gdk_gl_context_get_use_es (self->context),
+                                    &download.gl_internalformat,
+                                    &download.gl_format,
+                                    &download.gl_type))
     {
-      gdk_texture_download_float (self->saved, data, stride);
-      return;
-    }
+      GdkMemoryTexture *memtex;
 
-  if (gdk_gl_context_get_use_es (self->context) ||
-      stride != texture->width * 4)
-    {
-      GDK_TEXTURE_CLASS (gdk_gl_texture_parent_class)->download_float (texture, data, stride);
+      memtex = gdk_memory_texture_from_texture (texture,
+                                                format == texture->format ? GDK_MEMORY_R8G8B8A8_PREMULTIPLIED
+                                                                          : texture->format);
+      gdk_texture_do_download (GDK_TEXTURE (memtex), format, data, stride);
+      g_object_unref (memtex);
       return;
     }
 
-  gdk_gl_texture_run (self, gdk_gl_texture_do_download_float, data);
+  gdk_gl_texture_run (self, gdk_gl_texture_do_download, &download);
 }
 
 static void
@@ -273,9 +197,8 @@ gdk_gl_texture_class_init (GdkGLTextureClass *klass)
   GdkTextureClass *texture_class = GDK_TEXTURE_CLASS (klass);
   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 
-  texture_class->download_texture = gdk_gl_texture_download_texture;
   texture_class->download = gdk_gl_texture_download;
-  texture_class->download_float = gdk_gl_texture_download_float;
+
   gobject_class->dispose = gdk_gl_texture_dispose;
 }
 
@@ -309,10 +232,14 @@ gdk_gl_texture_get_id (GdkGLTexture *self)
 void
 gdk_gl_texture_release (GdkGLTexture *self)
 {
+  GdkTexture *texture;
+
   g_return_if_fail (GDK_IS_GL_TEXTURE (self));
   g_return_if_fail (self->saved == NULL);
 
-  self->saved = gdk_texture_download_texture (GDK_TEXTURE (self));
+  texture = GDK_TEXTURE (self);
+  self->saved = GDK_TEXTURE (gdk_memory_texture_from_texture (texture,
+                                                              gdk_texture_get_format (texture)));
 
   if (self->destroy)
     {
diff --git a/gdk/gdkmemorytexture.c b/gdk/gdkmemorytexture.c
index 52723ef805..8e44aed36a 100644
--- a/gdk/gdkmemorytexture.c
+++ b/gdk/gdkmemorytexture.c
@@ -55,38 +55,16 @@ gdk_memory_texture_dispose (GObject *object)
   G_OBJECT_CLASS (gdk_memory_texture_parent_class)->dispose (object);
 }
 
-static GdkTexture *
-gdk_memory_texture_download_texture (GdkTexture *texture)
-{
-  return g_object_ref (texture);
-}
-
 static void
-gdk_memory_texture_download (GdkTexture *texture,
-                             guchar     *data,
-                             gsize       stride)
+gdk_memory_texture_download (GdkTexture      *texture,
+                             GdkMemoryFormat  format,
+                             guchar          *data,
+                             gsize            stride)
 {
   GdkMemoryTexture *self = GDK_MEMORY_TEXTURE (texture);
 
   gdk_memory_convert (data, stride,
-                      GDK_MEMORY_DEFAULT,
-                      (guchar *) g_bytes_get_data (self->bytes, NULL),
-                      self->stride,
-                      texture->format,
-                      gdk_texture_get_width (texture),
-                      gdk_texture_get_height (texture));
-}
-
-static void
-gdk_memory_texture_download_float (GdkTexture *texture,
-                                   float      *data,
-                                   gsize       stride)
-{
-  GdkMemoryTexture *self = GDK_MEMORY_TEXTURE (texture);
-
-  gdk_memory_convert ((guchar *) data,
-                      stride * sizeof (float),
-                      GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED,
+                      format,
                       (guchar *) g_bytes_get_data (self->bytes, NULL),
                       self->stride,
                       texture->format,
@@ -100,9 +78,8 @@ gdk_memory_texture_class_init (GdkMemoryTextureClass *klass)
   GdkTextureClass *texture_class = GDK_TEXTURE_CLASS (klass);
   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 
-  texture_class->download_texture = gdk_memory_texture_download_texture;
   texture_class->download = gdk_memory_texture_download;
-  texture_class->download_float = gdk_memory_texture_download_float;
+
   gobject_class->dispose = gdk_memory_texture_dispose;
 }
 
@@ -189,6 +166,40 @@ gdk_memory_texture_new (int              width,
   return GDK_TEXTURE (self);
 }
 
+GdkMemoryTexture *
+gdk_memory_texture_from_texture (GdkTexture      *texture,
+                                 GdkMemoryFormat  format)
+{
+  GdkTexture *result;
+  GBytes *bytes;
+  guchar *data;
+  gsize stride;
+
+  g_return_val_if_fail (GDK_IS_TEXTURE (texture), NULL);
+
+  if (GDK_IS_MEMORY_TEXTURE (texture))
+    {
+      GdkMemoryTexture *memtex = GDK_MEMORY_TEXTURE (texture);
+
+      if (gdk_texture_get_format (texture) == format)
+        return g_object_ref (memtex);
+    }
+
+  stride = texture->width * gdk_memory_format_bytes_per_pixel (format);
+  data = g_malloc_n (stride, texture->height);
+
+  gdk_texture_do_download (texture, format, data, stride);
+  bytes = g_bytes_new_take (data, stride);
+  result = gdk_memory_texture_new (texture->width,
+                                   texture->height,
+                                   format,
+                                   bytes,
+                                   stride);
+  g_bytes_unref (bytes);
+
+  return GDK_MEMORY_TEXTURE (result);
+}
+
 const guchar *
 gdk_memory_texture_get_data (GdkMemoryTexture *self)
 {
diff --git a/gdk/gdkmemorytextureprivate.h b/gdk/gdkmemorytextureprivate.h
index 0cd5e91f27..a71648a950 100644
--- a/gdk/gdkmemorytextureprivate.h
+++ b/gdk/gdkmemorytextureprivate.h
@@ -29,6 +29,9 @@ G_BEGIN_DECLS
 #define GDK_MEMORY_GDK_PIXBUF_OPAQUE GDK_MEMORY_R8G8B8
 #define GDK_MEMORY_GDK_PIXBUF_ALPHA GDK_MEMORY_R8G8B8A8
 
+GdkMemoryTexture *      gdk_memory_texture_from_texture     (GdkTexture        *texture,
+                                                             GdkMemoryFormat    format);
+
 const guchar *          gdk_memory_texture_get_data         (GdkMemoryTexture  *self);
 gsize                   gdk_memory_texture_get_stride       (GdkMemoryTexture  *self);
 
diff --git a/gdk/gdktexture.c b/gdk/gdktexture.c
index f4c5928c8d..b2213fd367 100644
--- a/gdk/gdktexture.c
+++ b/gdk/gdktexture.c
@@ -221,35 +221,13 @@ G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GdkTexture, gdk_texture, G_TYPE_OBJECT,
 #define GDK_TEXTURE_WARN_NOT_IMPLEMENTED_METHOD(obj,method) \
   g_critical ("Texture of type '%s' does not implement GdkTexture::" # method, G_OBJECT_TYPE_NAME (obj))
 
-static GdkTexture *
-gdk_texture_real_download_texture (GdkTexture *self)
-{
-  GDK_TEXTURE_WARN_NOT_IMPLEMENTED_METHOD (self, download_texture);
-  return NULL;
-}
-
-static void
-gdk_texture_real_download (GdkTexture *texture,
-                           guchar     *data,
-                           gsize      stride)
-{
-  GdkTexture *memory_texture;
-
-  memory_texture = gdk_texture_download_texture (texture);
-  gdk_texture_download (memory_texture, data, stride);
-  g_object_unref (memory_texture);
-}
-
 static void
-gdk_texture_real_download_float (GdkTexture *self,
-                                 float      *data,
-                                 gsize       stride)
+gdk_texture_default_download (GdkTexture      *texture,
+                              GdkMemoryFormat  format,
+                              guchar          *data,
+                              gsize            stride)
 {
-  GdkTexture *memory_texture;
-
-  memory_texture = gdk_texture_download_texture (self);
-  gdk_texture_download_float (memory_texture, data, stride);
-  g_object_unref (memory_texture);
+  GDK_TEXTURE_WARN_NOT_IMPLEMENTED_METHOD (texture, download);
 }
 
 static void
@@ -315,9 +293,7 @@ gdk_texture_class_init (GdkTextureClass *klass)
 {
   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 
-  klass->download_texture = gdk_texture_real_download_texture;
-  klass->download = gdk_texture_real_download;
-  klass->download_float = gdk_texture_real_download_float;
+  klass->download = gdk_texture_default_download;
 
   gobject_class->set_property = gdk_texture_set_property;
   gobject_class->get_property = gdk_texture_get_property;
@@ -692,6 +668,15 @@ gdk_texture_get_height (GdkTexture *texture)
   return texture->height;
 }
 
+void
+gdk_texture_do_download (GdkTexture      *texture,
+                         GdkMemoryFormat  format,
+                         guchar          *data,
+                         gsize            stride)
+{
+  GDK_TEXTURE_GET_CLASS (texture)->download (texture, format, data,stride);
+}
+
 cairo_surface_t *
 gdk_texture_download_surface (GdkTexture *texture)
 {
@@ -750,7 +735,10 @@ gdk_texture_download (GdkTexture *texture,
   g_return_if_fail (data != NULL);
   g_return_if_fail (stride >= gdk_texture_get_width (texture) * 4);
 
-  GDK_TEXTURE_GET_CLASS (texture)->download (texture, data, stride);
+  gdk_texture_do_download (texture,
+                           GDK_MEMORY_DEFAULT,
+                           data,
+                           stride);
 }
 
 /**
@@ -789,23 +777,10 @@ gdk_texture_download_float (GdkTexture *texture,
   g_return_if_fail (data != NULL);
   g_return_if_fail (stride >= gdk_texture_get_width (texture) * 4);
 
-  GDK_TEXTURE_GET_CLASS (texture)->download_float (texture, data, stride);
-}
-
-GdkTexture *
-gdk_texture_download_texture (GdkTexture *texture)
-{
-  g_return_val_if_fail (GDK_IS_TEXTURE (texture), NULL);
-
-  g_object_ref (texture);
-  while (!GDK_IS_MEMORY_TEXTURE (texture))
-    {
-      GdkTexture *downloaded = GDK_TEXTURE_GET_CLASS (texture)->download_texture (texture);
-      g_object_unref (texture);
-      texture = downloaded;
-    }
-
-  return texture;
+  gdk_texture_do_download (texture,
+                           GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED,
+                           (guchar *) data,
+                           stride);
 }
 
 GdkMemoryFormat
diff --git a/gdk/gdktextureprivate.h b/gdk/gdktextureprivate.h
index 994c9901f8..a9e6ac51a2 100644
--- a/gdk/gdktextureprivate.h
+++ b/gdk/gdktextureprivate.h
@@ -27,24 +27,22 @@ struct _GdkTexture
 struct _GdkTextureClass {
   GObjectClass parent_class;
 
-  /* mandatory: Download into a GdkMemoryTexture */
-  GdkTexture *          (* download_texture)            (GdkTexture             *texture);
-  /* optional */
+  /* mandatory: Download in the given format into data */
   void                  (* download)                    (GdkTexture             *texture,
+                                                         GdkMemoryFormat         format,
                                                          guchar                 *data,
                                                          gsize                   stride);
-  void                  (* download_float)              (GdkTexture             *texture,
-                                                         float                  *data,
-                                                         gsize                   stride);
 };
 
 gboolean                gdk_texture_can_load            (GBytes                 *bytes);
 
 GdkTexture *            gdk_texture_new_for_surface     (cairo_surface_t        *surface);
 cairo_surface_t *       gdk_texture_download_surface    (GdkTexture             *texture);
-/* NB: GdkMemoryTexture */
-GdkTexture *            gdk_texture_download_texture    (GdkTexture             *texture);
 
+void                    gdk_texture_do_download         (GdkTexture             *texture,
+                                                         GdkMemoryFormat         format,
+                                                         guchar                 *data,
+                                                         gsize                   stride);
 GdkMemoryFormat         gdk_texture_get_format          (GdkTexture             *self);
 gboolean                gdk_texture_set_render_data     (GdkTexture             *self,
                                                          gpointer                key,
diff --git a/gdk/loaders/gdkpng.c b/gdk/loaders/gdkpng.c
index 9bdc5e3a43..0dd9394590 100644
--- a/gdk/loaders/gdkpng.c
+++ b/gdk/loaders/gdkpng.c
@@ -479,9 +479,9 @@ gdk_save_png (GdkTexture *texture)
 
   width = gdk_texture_get_width (texture);
   height = gdk_texture_get_height (texture);
+  format = gdk_texture_get_format (texture);
 
-  mtexture = gdk_texture_download_texture (texture);
-  format = gdk_texture_get_format (mtexture);
+  mtexture = GDK_TEXTURE (gdk_memory_texture_from_texture (texture, format));
 
   switch (format)
     {
diff --git a/gdk/loaders/gdktiff.c b/gdk/loaders/gdktiff.c
index d2d8dfdbde..994f50e353 100644
--- a/gdk/loaders/gdktiff.c
+++ b/gdk/loaders/gdktiff.c
@@ -283,8 +283,8 @@ gdk_save_tiff (GdkTexture *texture)
   width = gdk_texture_get_width (texture);
   height = gdk_texture_get_height (texture);
 
-  memory_texture = gdk_texture_download_texture (texture);
-  format = gdk_texture_get_format (memory_texture);
+  format = gdk_texture_get_format (texture);
+  memory_texture = GDK_TEXTURE (gdk_memory_texture_from_texture (texture, format));
 
   for (int i = 0; i < G_N_ELEMENTS (format_data); i++)
     {
diff --git a/gsk/ngl/gskngldriver.c b/gsk/ngl/gskngldriver.c
index 87f2864241..f940c4aa03 100644
--- a/gsk/ngl/gskngldriver.c
+++ b/gsk/ngl/gskngldriver.c
@@ -23,17 +23,14 @@
 
 #include "config.h"
 
-#include <gdk/gdkglcontextprivate.h>
-#include <gdk/gdkdisplayprivate.h>
-#include <gdk/gdktextureprivate.h>
-#include <gdk/gdkprofilerprivate.h>
+#include "gskngldriverprivate.h"
+
 #include <gsk/gskdebugprivate.h>
 #include <gsk/gskglshaderprivate.h>
 #include <gsk/gskrendererprivate.h>
 
 #include "gsknglcommandqueueprivate.h"
 #include "gsknglcompilerprivate.h"
-#include "gskngldriverprivate.h"
 #include "gsknglglyphlibraryprivate.h"
 #include "gskngliconlibraryprivate.h"
 #include "gsknglprogramprivate.h"
@@ -41,6 +38,12 @@
 #include "gskngltextureprivate.h"
 #include "fp16private.h"
 
+#include <gdk/gdkglcontextprivate.h>
+#include <gdk/gdkdisplayprivate.h>
+#include <gdk/gdkmemorytextureprivate.h>
+#include <gdk/gdkprofilerprivate.h>
+#include <gdk/gdktextureprivate.h>
+
 #define ATLAS_SIZE 512
 #define MAX_OLD_RATIO 0.5
 
@@ -746,7 +749,7 @@ gsk_ngl_driver_load_texture (GskNglDriver *self,
                              int           mag_filter)
 {
   GdkGLContext *context;
-  GdkTexture *downloaded_texture;
+  GdkMemoryTexture *downloaded_texture;
   GskNglTexture *t;
   guint texture_id;
   int height;
@@ -773,7 +776,7 @@ gsk_ngl_driver_load_texture (GskNglDriver *self,
         }
       else
         {
-          downloaded_texture = gdk_texture_download_texture (texture);
+          downloaded_texture = gdk_memory_texture_from_texture (texture, gdk_texture_get_format (texture));
         }
     }
   else
@@ -784,7 +787,7 @@ gsk_ngl_driver_load_texture (GskNglDriver *self,
             return t->texture_id;
         }
 
-      downloaded_texture = gdk_texture_download_texture (texture);
+      downloaded_texture = gdk_memory_texture_from_texture (texture, gdk_texture_get_format (texture));
     }
 
   /* The download_texture() call may have switched the GL context. Make sure
@@ -794,7 +797,7 @@ gsk_ngl_driver_load_texture (GskNglDriver *self,
   width = gdk_texture_get_width (texture);
   height = gdk_texture_get_height (texture);
   texture_id = gsk_ngl_command_queue_upload_texture (self->command_queue,
-                                                     downloaded_texture,
+                                                     GDK_TEXTURE (downloaded_texture),
                                                      0,
                                                      0,
                                                      width,


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