[gimp] app: render layer-group preview in chunks



commit 64bf77aed88667d0f7b05205e33a19c50e5f3887
Author: Ell <ell_se yahoo com>
Date:   Sat Mar 14 16:02:14 2020 +0200

    app: render layer-group preview in chunks
    
    In gimp_drawable_get_sub_preview_async(), when the drawable buffer
    has a validate handler (i.e., when it's a group layer), use a chunk
    iterator to validate the buffer in chunks, where each chunk is
    validated in a separate invocation of the async function.  This
    prevents validation from blocking the main thread for too long when
    the buffer is not already fully validated.

 app/core/gimpdrawable-preview.c | 66 +++++++++++++++++++++++++++++++----------
 1 file changed, 50 insertions(+), 16 deletions(-)
---
diff --git a/app/core/gimpdrawable-preview.c b/app/core/gimpdrawable-preview.c
index d3bb3136f0..570865e5e0 100644
--- a/app/core/gimpdrawable-preview.c
+++ b/app/core/gimpdrawable-preview.c
@@ -39,6 +39,7 @@
 #include "gimp-utils.h"
 #include "gimpasync.h"
 #include "gimpchannel.h"
+#include "gimpchunkiterator.h"
 #include "gimpimage.h"
 #include "gimpimage-color-profile.h"
 #include "gimpdrawable-preview.h"
@@ -51,10 +52,12 @@
 
 typedef struct
 {
-  const Babl    *format;
-  GeglBuffer    *buffer;
-  GeglRectangle  rect;
-  gdouble        scale;
+  const Babl        *format;
+  GeglBuffer        *buffer;
+  GeglRectangle      rect;
+  gdouble            scale;
+
+  GimpChunkIterator *iter;
 } SubPreviewData;
 
 
@@ -84,6 +87,8 @@ sub_preview_data_new (const Babl          *format,
   data->rect   = *rect;
   data->scale  = scale;
 
+  data->iter   = NULL;
+
   return data;
 }
 
@@ -92,6 +97,9 @@ sub_preview_data_free (SubPreviewData *data)
 {
   g_object_unref (data->buffer);
 
+  if (data->iter)
+    gimp_chunk_iterator_stop (data->iter, TRUE);
+
   g_slice_free (SubPreviewData, data);
 }
 
@@ -337,18 +345,44 @@ gimp_drawable_get_sub_preview_async_func (GimpAsync      *async,
 
   if (validate)
     {
-      GeglRectangle rect;
-
-      rect.x      = floor (data->rect.x / data->scale);
-      rect.y      = floor (data->rect.y / data->scale);
-      rect.width  = ceil ((data->rect.x + data->rect.width)  / data->scale) -
-                    rect.x;
-      rect.height = ceil ((data->rect.x + data->rect.height) / data->scale) -
-                    rect.y;
-
-      gimp_tile_handler_validate_validate (validate,
-                                           data->buffer, &rect,
-                                           TRUE, TRUE);
+      if (! data->iter)
+        {
+          cairo_region_t        *region;
+          cairo_rectangle_int_t  rect;
+
+          rect.x      = floor (data->rect.x / data->scale);
+          rect.y      = floor (data->rect.y / data->scale);
+          rect.width  = ceil ((data->rect.x + data->rect.width)  /
+                              data->scale) - rect.x;
+          rect.height = ceil ((data->rect.x + data->rect.height) /
+                              data->scale) - rect.y;
+
+          region = cairo_region_copy (validate->dirty_region);
+
+          cairo_region_intersect_rectangle (region, &rect);
+
+          data->iter = gimp_chunk_iterator_new (region);
+        }
+
+      if (gimp_chunk_iterator_next (data->iter))
+        {
+          GeglRectangle rect;
+
+          gimp_tile_handler_validate_begin_validate (validate);
+
+          while (gimp_chunk_iterator_get_rect (data->iter, &rect))
+            {
+              gimp_tile_handler_validate_validate (validate,
+                                                   data->buffer, &rect,
+                                                   FALSE, FALSE);
+            }
+
+          gimp_tile_handler_validate_end_validate (validate);
+
+          return;
+        }
+
+      data->iter = NULL;
     }
 
   gegl_buffer_get (data->buffer, &data->rect, data->scale,


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