[gtk/wip/otte/for-main: 1/2] glrenderer: Don't return NULL form render_texture()




commit 6863f9f05918a25f767df544a92491039a2aaa36
Author: Benjamin Otte <otte redhat com>
Date:   Fri Feb 25 03:40:57 2022 +0100

    glrenderer: Don't return NULL form render_texture()
    
    Instead, draw multiple tiles and assemble them into a memory texture.
    
    Tests added to the testsuite for this.

 gsk/gl/gskglrenderer.c                 |  40 ++++++++++++++++++++++++++++++---
 gsk/gskcairorenderer.c                 |  38 ++++++++++++++++++++++++++++++-
 testsuite/gsk/compare/huge-height.node |   7 ++++++
 testsuite/gsk/compare/huge-height.png  | Bin 0 -> 689 bytes
 testsuite/gsk/compare/huge-width.node  |   7 ++++++
 testsuite/gsk/compare/huge-width.png   | Bin 0 -> 657 bytes
 testsuite/gsk/meson.build              |   2 ++
 7 files changed, 90 insertions(+), 4 deletions(-)
---
diff --git a/gsk/gl/gskglrenderer.c b/gsk/gl/gskglrenderer.c
index fe244a7a4f..dc78c583a4 100644
--- a/gsk/gl/gskglrenderer.c
+++ b/gsk/gl/gskglrenderer.c
@@ -306,10 +306,9 @@ gsk_gl_renderer_render_texture (GskRenderer           *renderer,
   GskGLRenderer *self = (GskGLRenderer *)renderer;
   GskGLRenderTarget *render_target;
   GskGLRenderJob *job;
-  GdkTexture *texture = NULL;
+  GdkTexture *texture;
   guint texture_id;
-  int width;
-  int height;
+  int width, height, max_size;
   int format;
 
   g_assert (GSK_IS_GL_RENDERER (renderer));
@@ -317,6 +316,37 @@ gsk_gl_renderer_render_texture (GskRenderer           *renderer,
 
   width = ceilf (viewport->size.width);
   height = ceilf (viewport->size.height);
+  max_size = self->command_queue->max_texture_size;
+  if (width > max_size || height > max_size)
+    {
+      gsize x, y, size, stride;
+      GBytes *bytes;
+      guchar *data;
+
+      stride = width * 4;
+      size = stride * height;
+      data = g_malloc_n (stride, height);
+
+      for (y = 0; y < height; y += max_size)
+        {
+          for (x = 0; x < width; x += max_size)
+            {
+              texture = gsk_gl_renderer_render_texture (renderer, root, 
+                                                        &GRAPHENE_RECT_INIT (x, y,
+                                                                             MIN (max_size, 
viewport->size.width - x),
+                                                                             MIN (max_size, 
viewport->size.height - y)));
+              gdk_texture_download (texture,
+                                    data + stride * y + x,
+                                    stride);
+              g_object_unref (texture);
+            }
+        }
+
+      bytes = g_bytes_new_take (data, size);
+      texture = gdk_memory_texture_new (width, height, GDK_MEMORY_DEFAULT, bytes, stride);
+      g_bytes_unref (bytes);
+      return texture;
+    }
 
   format = gsk_render_node_prefers_high_depth (root) ? GL_RGBA32F : GL_RGBA8;
 
@@ -342,6 +372,10 @@ gsk_gl_renderer_render_texture (GskRenderer           *renderer,
 
       gsk_gl_driver_after_frame (self->driver);
     }
+  else
+    {
+      g_assert_not_reached ();
+    }
 
   return g_steal_pointer (&texture);
 }
diff --git a/gsk/gskcairorenderer.c b/gsk/gskcairorenderer.c
index 3135acfdb1..3c3c0cbb46 100644
--- a/gsk/gskcairorenderer.c
+++ b/gsk/gskcairorenderer.c
@@ -107,8 +107,44 @@ gsk_cairo_renderer_render_texture (GskRenderer           *renderer,
   GdkTexture *texture;
   cairo_surface_t *surface;
   cairo_t *cr;
+  int width, height;
+  /* limit from cairo's source code */
+#define MAX_IMAGE_SIZE 32767
 
-  surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, ceil (viewport->size.width), ceil 
(viewport->size.height));
+  width = ceil (viewport->size.width);
+  height = ceil (viewport->size.height);
+  if (width > MAX_IMAGE_SIZE || height > MAX_IMAGE_SIZE)
+    {
+      gsize x, y, size, stride;
+      GBytes *bytes;
+      guchar *data;
+
+      stride = width * 4;
+      size = stride * height;
+      data = g_malloc_n (stride, height);
+
+      for (y = 0; y < height; y += MAX_IMAGE_SIZE)
+        {
+          for (x = 0; x < width; x += MAX_IMAGE_SIZE)
+            {
+              texture = gsk_cairo_renderer_render_texture (renderer, root, 
+                                                           &GRAPHENE_RECT_INIT (x, y,
+                                                                                MIN (MAX_IMAGE_SIZE, 
viewport->size.width - x),
+                                                                                MIN (MAX_IMAGE_SIZE, 
viewport->size.height - y)));
+              gdk_texture_download (texture,
+                                    data + stride * y + x,
+                                    stride);
+              g_object_unref (texture);
+            }
+        }
+
+      bytes = g_bytes_new_take (data, size);
+      texture = gdk_memory_texture_new (width, height, GDK_MEMORY_DEFAULT, bytes, stride);
+      g_bytes_unref (bytes);
+      return texture;
+    }
+
+  surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
   cr = cairo_create (surface);
 
   cairo_translate (cr, - viewport->origin.x, - viewport->origin.y);
diff --git a/testsuite/gsk/compare/huge-height.node b/testsuite/gsk/compare/huge-height.node
new file mode 100644
index 0000000000..ce33081ff8
--- /dev/null
+++ b/testsuite/gsk/compare/huge-height.node
@@ -0,0 +1,7 @@
+color {
+  color: transparent;
+  /* - more than 32k, to trip modern GPUs and Cairo
+   * - non-integer to test rounding code
+   */
+  bounds: 0 0 135.7 33333.3;
+}
diff --git a/testsuite/gsk/compare/huge-height.png b/testsuite/gsk/compare/huge-height.png
new file mode 100644
index 0000000000..0162f5307b
Binary files /dev/null and b/testsuite/gsk/compare/huge-height.png differ
diff --git a/testsuite/gsk/compare/huge-width.node b/testsuite/gsk/compare/huge-width.node
new file mode 100644
index 0000000000..db9533bf57
--- /dev/null
+++ b/testsuite/gsk/compare/huge-width.node
@@ -0,0 +1,7 @@
+color {
+  color: transparent;
+  /* - more than 32k, to trip modern GPUs and Cairo
+   * - non-integer to test rounding code
+   */
+  bounds: 0 0 33333.3 135.7;
+}
diff --git a/testsuite/gsk/compare/huge-width.png b/testsuite/gsk/compare/huge-width.png
new file mode 100644
index 0000000000..e7d0e91314
Binary files /dev/null and b/testsuite/gsk/compare/huge-width.png differ
diff --git a/testsuite/gsk/meson.build b/testsuite/gsk/meson.build
index 71e18f824d..106661a708 100644
--- a/testsuite/gsk/meson.build
+++ b/testsuite/gsk/meson.build
@@ -58,6 +58,8 @@ compare_render_tests = [
   'empty-shadow',
   'empty-texture',
   'empty-transform',
+  'huge-height',
+  'huge-width',
   'inset-shadow-multiple',
   'invalid-transform',
   'issue-3615',


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