[gtk/wip/otte/memoryformat: 6/7] gl: Refactor texture uploading




commit ddc4a40c3302b5a78c9eeaac4585bd7d2ae03127
Author: Benjamin Otte <otte redhat com>
Date:   Wed Oct 13 00:07:08 2021 +0200

    gl: Refactor texture uploading
    
    Don't pass texture + rect, but instead have
      gdk_memory_texture_new_subtexture()
    and use it to generate subtextures and pass them.
    
    This has the advantage of downloading the a too large texture only once
    instead of N times.

 gdk/gdkmemorytexture.c            | 33 +++++++++++++++++++++++++++++++++
 gdk/gdkmemorytextureprivate.h     |  5 +++++
 gsk/gl/gskglcommandqueue.c        | 15 +++++----------
 gsk/gl/gskglcommandqueueprivate.h |  4 ----
 gsk/gl/gskgldriver.c              | 18 +++++++++++-------
 5 files changed, 54 insertions(+), 21 deletions(-)
---
diff --git a/gdk/gdkmemorytexture.c b/gdk/gdkmemorytexture.c
index 4402998ebb..71df887b0b 100644
--- a/gdk/gdkmemorytexture.c
+++ b/gdk/gdkmemorytexture.c
@@ -166,6 +166,39 @@ gdk_memory_texture_new (int              width,
   return GDK_TEXTURE (self);
 }
 
+GdkTexture *
+gdk_memory_texture_new_subtexture (GdkMemoryTexture  *source,
+                                   int                x,
+                                   int                y,
+                                   int                width,
+                                   int                height)
+{
+  GdkTexture *texture, *result;
+  gsize bpp, offset, size;
+  GBytes *bytes;
+
+  g_return_val_if_fail (GDK_IS_MEMORY_TEXTURE (source), NULL);
+  g_return_val_if_fail (x < 0 || x >= GDK_TEXTURE (source)->width, NULL);
+  g_return_val_if_fail (y < 0 || y >= GDK_TEXTURE (source)->height, NULL);
+  g_return_val_if_fail (width <= 0 || x + width > GDK_TEXTURE (source)->width, NULL);
+  g_return_val_if_fail (height <= 0 || y + height > GDK_TEXTURE (source)->height, NULL);
+
+  texture = GDK_TEXTURE (source);
+  bpp = gdk_memory_format_bytes_per_pixel (texture->format);
+  offset = y * source->stride + x * bpp;
+  size = source->stride * (height - 1) + x * bpp;
+  bytes = g_bytes_new_from_bytes (source->bytes, offset, size);
+
+  result = gdk_memory_texture_new (texture->width,
+                                   texture->height,
+                                   texture->format,
+                                   bytes,
+                                   source->stride);
+  g_bytes_unref (bytes);
+
+  return result;
+}
+
 GdkMemoryTexture *
 gdk_memory_texture_from_texture (GdkTexture      *texture,
                                  GdkMemoryFormat  format)
diff --git a/gdk/gdkmemorytextureprivate.h b/gdk/gdkmemorytextureprivate.h
index a71648a950..57dafd567b 100644
--- a/gdk/gdkmemorytextureprivate.h
+++ b/gdk/gdkmemorytextureprivate.h
@@ -31,6 +31,11 @@ G_BEGIN_DECLS
 
 GdkMemoryTexture *      gdk_memory_texture_from_texture     (GdkTexture        *texture,
                                                              GdkMemoryFormat    format);
+GdkTexture *            gdk_memory_texture_new_subtexture   (GdkMemoryTexture  *texture,
+                                                             int                x,
+                                                             int                y,
+                                                             int                width,
+                                                             int                height);
 
 const guchar *          gdk_memory_texture_get_data         (GdkMemoryTexture  *self);
 gsize                   gdk_memory_texture_get_stride       (GdkMemoryTexture  *self);
diff --git a/gsk/gl/gskglcommandqueue.c b/gsk/gl/gskglcommandqueue.c
index 38f879c5c1..6842b032b8 100644
--- a/gsk/gl/gskglcommandqueue.c
+++ b/gsk/gl/gskglcommandqueue.c
@@ -1422,10 +1422,6 @@ gsk_gl_command_queue_do_upload_texture (GskGLCommandQueue *self,
 int
 gsk_gl_command_queue_upload_texture (GskGLCommandQueue *self,
                                      GdkTexture        *texture,
-                                     guint              x_offset,
-                                     guint              y_offset,
-                                     guint              width,
-                                     guint              height,
                                      int                min_filter,
                                      int                mag_filter)
 {
@@ -1434,16 +1430,17 @@ gsk_gl_command_queue_upload_texture (GskGLCommandQueue *self,
   GdkMemoryFormat data_format;
   const guchar *data;
   gsize data_stride;
-  gsize bpp;
+  int width, height;
   int texture_id;
 
   g_assert (GSK_IS_GL_COMMAND_QUEUE (self));
   g_assert (!GDK_IS_GL_TEXTURE (texture));
-  g_assert (x_offset + width <= gdk_texture_get_width (texture));
-  g_assert (y_offset + height <= gdk_texture_get_height (texture));
   g_assert (min_filter == GL_LINEAR || min_filter == GL_NEAREST);
   g_assert (mag_filter == GL_LINEAR || min_filter == GL_NEAREST);
 
+  width = gdk_texture_get_width (texture);
+  height = gdk_texture_get_height (texture);
+
   if (width > self->max_texture_size || height > self->max_texture_size)
     {
       g_warning ("Attempt to create texture of size %ux%u but max size is %d. "
@@ -1476,14 +1473,12 @@ gsk_gl_command_queue_upload_texture (GskGLCommandQueue *self,
 
   self->n_uploads++;
 
-  bpp = gdk_memory_format_bytes_per_pixel (data_format);
-
   /* Switch to texture0 as 2D. We'll restore it later. */
   glActiveTexture (GL_TEXTURE0);
   glBindTexture (GL_TEXTURE_2D, texture_id);
 
   gsk_gl_command_queue_do_upload_texture (self,
-                                          data + x_offset * bpp + y_offset * data_stride,
+                                          data,
                                           width, height, data_stride,
                                           data_format);
 
diff --git a/gsk/gl/gskglcommandqueueprivate.h b/gsk/gl/gskglcommandqueueprivate.h
index c4da7231c9..4147283e6d 100644
--- a/gsk/gl/gskglcommandqueueprivate.h
+++ b/gsk/gl/gskglcommandqueueprivate.h
@@ -281,10 +281,6 @@ void                gsk_gl_command_queue_execute              (GskGLCommandQueue
                                                                const cairo_region_t *scissor);
 int                 gsk_gl_command_queue_upload_texture       (GskGLCommandQueue    *self,
                                                                GdkTexture           *texture,
-                                                               guint                 x_offset,
-                                                               guint                 y_offset,
-                                                               guint                 width,
-                                                               guint                 height,
                                                                int                   min_filter,
                                                                int                   mag_filter);
 int                 gsk_gl_command_queue_create_texture       (GskGLCommandQueue    *self,
diff --git a/gsk/gl/gskgldriver.c b/gsk/gl/gskgldriver.c
index 33fcf380b3..327dea93ff 100644
--- a/gsk/gl/gskgldriver.c
+++ b/gsk/gl/gskgldriver.c
@@ -798,10 +798,6 @@ gsk_gl_driver_load_texture (GskGLDriver *self,
   height = gdk_texture_get_height (texture);
   texture_id = gsk_gl_command_queue_upload_texture (self->command_queue,
                                                     GDK_TEXTURE (downloaded_texture),
-                                                    0,
-                                                    0,
-                                                    width,
-                                                    height,
                                                     min_filter,
                                                     mag_filter);
 
@@ -1230,6 +1226,7 @@ gsk_gl_driver_add_texture_slices (GskGLDriver        *self,
   int tex_width;
   int tex_height;
   int x = 0, y = 0;
+  GdkMemoryTexture *memtex;
 
   g_assert (GSK_IS_GL_DRIVER (self));
   g_assert (GDK_IS_TEXTURE (texture));
@@ -1253,6 +1250,8 @@ gsk_gl_driver_add_texture_slices (GskGLDriver        *self,
 
   n_slices = cols * rows;
   slices = g_new0 (GskGLTextureSlice, n_slices);
+  memtex = gdk_memory_texture_from_texture (texture,
+                                            gdk_texture_get_format (texture));
 
   for (guint col = 0; col < cols; col ++)
     {
@@ -1262,13 +1261,16 @@ gsk_gl_driver_add_texture_slices (GskGLDriver        *self,
         {
           int slice_height = MIN (max_texture_size, texture->height - y);
           int slice_index = (col * rows) + row;
+          GdkTexture *subtex;
           guint texture_id;
 
+          subtex = gdk_memory_texture_new_subtexture (memtex,
+                                                      x, y,
+                                                      slice_width, slice_height);
           texture_id = gsk_gl_command_queue_upload_texture (self->command_queue,
-                                                            texture,
-                                                            x, y,
-                                                            slice_width, slice_height,
+                                                            subtex,
                                                             GL_NEAREST, GL_NEAREST);
+          g_object_unref (subtex);
 
           slices[slice_index].rect.x = x;
           slices[slice_index].rect.y = y;
@@ -1283,6 +1285,8 @@ gsk_gl_driver_add_texture_slices (GskGLDriver        *self,
       x += slice_width;
     }
 
+  g_object_unref (memtex);
+
   /* Allocate one Texture for the entire thing. */
   t = gsk_gl_texture_new (0,
                           tex_width, tex_height,


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