[gtk/wip/chergert/glproto: 337/526] port over texture slicing




commit 06846bc5dbc6df136c63a495353a0be403bb41bf
Author: Christian Hergert <chergert redhat com>
Date:   Wed Jan 27 21:30:59 2021 -0800

    port over texture slicing

 gsk/next/gskgldriver.c             | 84 ++++++++++++++++++++++++++++++++++++++
 gsk/next/gskgldriverprivate.h      |  4 ++
 gsk/next/gskgltexturepool.c        |  8 ++++
 gsk/next/gskgltexturepoolprivate.h | 40 +++++++++++-------
 gsk/next/gskgltypesprivate.h       |  1 +
 5 files changed, 123 insertions(+), 14 deletions(-)
---
diff --git a/gsk/next/gskgldriver.c b/gsk/next/gskgldriver.c
index a2db9b8855..6f1bada783 100644
--- a/gsk/next/gskgldriver.c
+++ b/gsk/next/gskgldriver.c
@@ -1162,3 +1162,87 @@ gsk_next_driver_create_command_queue (GskNextDriver *self,
 
   return gsk_gl_command_queue_new (context, self->shared_command_queue->uniforms);
 }
+
+void
+gsk_next_driver_slice_texture (GskNextDriver      *self,
+                               GdkTexture         *texture,
+                               GskGLTextureSlice **out_slices,
+                               guint              *out_n_slices)
+{
+  int max_texture_size;
+  GskGLTextureSlice *slices;
+  GskGLTexture *t;
+  guint n_slices;
+  guint cols;
+  guint rows;
+  int tex_width;
+  int tex_height;
+  int x = 0, y = 0;
+
+  g_return_if_fail (GSK_IS_NEXT_DRIVER (self));
+  g_return_if_fail (GDK_IS_TEXTURE (texture));
+  g_return_if_fail (out_slices != NULL);
+  g_return_if_fail (out_n_slices != NULL);
+
+  /* XXX: Too much? */
+  max_texture_size = self->command_queue->max_texture_size / 4;
+
+  tex_width = texture->width;
+  tex_height = texture->height;
+  cols = (texture->width / max_texture_size) + 1;
+  rows = (texture->height / max_texture_size) + 1;
+
+  if ((t = gdk_texture_get_render_data (texture, self)))
+    {
+      *out_slices = t->slices;
+      *out_n_slices = t->n_slices;
+      return;
+    }
+
+  n_slices = cols * rows;
+  slices = g_new0 (GskGLTextureSlice, n_slices);
+
+  for (guint col = 0; col < cols; col ++)
+    {
+      int slice_width = MIN (max_texture_size, texture->width - x);
+
+      for (guint row = 0; row < rows; row ++)
+        {
+          int slice_height = MIN (max_texture_size, texture->height - y);
+          int slice_index = (col * rows) + row;
+          guint texture_id;
+
+          texture_id = gsk_gl_command_queue_upload_texture (self->command_queue,
+                                                            texture,
+                                                            x, y,
+                                                            slice_width, slice_height,
+                                                            GL_NEAREST, GL_NEAREST);
+
+          slices[slice_index].rect.x = x;
+          slices[slice_index].rect.y = y;
+          slices[slice_index].rect.width = slice_width;
+          slices[slice_index].rect.height = slice_height;
+          slices[slice_index].texture_id = texture_id;
+
+          y += slice_height;
+        }
+
+      y = 0;
+      x += slice_width;
+    }
+
+  /* Allocate one Texture for the entire thing. */
+  t = gsk_gl_texture_new (0,
+                          tex_width, tex_height,
+                          GL_NEAREST, GL_NEAREST,
+                          self->current_frame_id);
+
+  /* Use gsk_gl_texture_free() as destroy notify here since we are
+   * not inserting this GskGLTexture into self->textures!
+   */
+  gdk_texture_set_render_data (texture, self, t,
+                               (GDestroyNotify)gsk_gl_texture_free);
+
+  t->slices = *out_slices = slices;
+  t->n_slices = *out_n_slices = n_slices;
+}
diff --git a/gsk/next/gskgldriverprivate.h b/gsk/next/gskgldriverprivate.h
index b23cbdd649..b56310ba8b 100644
--- a/gsk/next/gskgldriverprivate.h
+++ b/gsk/next/gskgldriverprivate.h
@@ -156,6 +156,10 @@ GskGLTexture      *gsk_next_driver_acquire_texture       (GskNextDriver        *
                                                           int                   mag_filter);
 void               gsk_next_driver_release_texture       (GskNextDriver        *self,
                                                           GskGLTexture         *texture);
+void               gsk_next_driver_slice_texture         (GskNextDriver        *self,
+                                                          GdkTexture           *texture,
+                                                          GskGLTextureSlice   **out_slices,
+                                                          guint                *out_n_slices);
 GskGLProgram      *gsk_next_driver_lookup_shader         (GskNextDriver        *self,
                                                           GskGLShader          *shader,
                                                           GError              **error);
diff --git a/gsk/next/gskgltexturepool.c b/gsk/next/gskgltexturepool.c
index 3df7856a05..49bc7c19e4 100644
--- a/gsk/next/gskgltexturepool.c
+++ b/gsk/next/gskgltexturepool.c
@@ -40,6 +40,14 @@ gsk_gl_texture_free (GskGLTexture *texture)
           texture->texture_id = 0;
         }
 
+      for (guint i = 0; i < texture->n_slices; i++)
+        {
+          glDeleteTextures (1, &texture->slices[i].texture_id);
+          texture->slices[i].texture_id = 0;
+        }
+
+      g_clear_pointer (&texture->slices, g_free);
+
       g_slice_free (GskGLTexture, texture);
     }
 }
diff --git a/gsk/next/gskgltexturepoolprivate.h b/gsk/next/gskgltexturepoolprivate.h
index 0215db90c8..8c000b5ee8 100644
--- a/gsk/next/gskgltexturepoolprivate.h
+++ b/gsk/next/gskgltexturepoolprivate.h
@@ -25,32 +25,44 @@
 
 G_BEGIN_DECLS
 
-typedef struct _GskGLTexture GskGLTexture;
-typedef struct _GskGLTexturePool GskGLTexturePool;
-
-struct _GskGLTexturePool
+typedef struct _GskGLTexturePool
 {
   GQueue by_width;
   GQueue by_height;
+} GskGLTexturePool;
+
+struct _GskGLTextureSlice
+{
+  cairo_rectangle_int_t rect;
+  guint texture_id;
 };
 
 struct _GskGLTexture
 {
-  GList       width_link;  /* Used to sort textures by width */
-  GList       height_link; /* Used to sort textures by height */
+  /* Used to sort by width/height in pool */
+  GList              width_link;
+  GList              height_link;
+
+  /* Identifier of the frame that created it */
+  gint64             last_used_in_frame;
 
-  gint64      last_used_in_frame;
+  /* Backpointer to texture (can be cleared asynchronously) */
+  GdkTexture        *user;
 
-  GdkTexture *user;
+  /* Only used by sliced textures */
+  GskGLTextureSlice *slices;
+  guint              n_slices;
 
-  guint       texture_id;
+  /* The actual GL texture identifier in some shared context */
+  guint              texture_id;
 
-  float       width;
-  float       height;
-  int         min_filter;
-  int         mag_filter;
+  float              width;
+  float              height;
+  int                min_filter;
+  int                mag_filter;
 
-  guint       permanent : 1;
+  /* Set when used by an atlas so we don't drop the texture */
+  guint              permanent : 1;
 };
 
 void          gsk_gl_texture_pool_init  (GskGLTexturePool *self);
diff --git a/gsk/next/gskgltypesprivate.h b/gsk/next/gskgltypesprivate.h
index efb2c4c500..5927d780fc 100644
--- a/gsk/next/gskgltypesprivate.h
+++ b/gsk/next/gskgltypesprivate.h
@@ -42,6 +42,7 @@ typedef struct _GskGLProgram GskGLProgram;
 typedef struct _GskGLRenderJob GskGLRenderJob;
 typedef struct _GskGLShadowLibrary GskGLShadowLibrary;
 typedef struct _GskGLTexture GskGLTexture;
+typedef struct _GskGLTextureSlice GskGLTextureSlice;
 typedef struct _GskGLTextureAtlas GskGLTextureAtlas;
 typedef struct _GskGLTextureLibrary GskGLTextureLibrary;
 typedef struct _GskGLUniformState GskGLUniformState;


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