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



commit fbaf3c4290d9e1a7a506250a6328102cb9e0189e
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.
    
    (cherry picked from commit 64bf77aed88667d0f7b05205e33a19c50e5f3887)

 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 93ff17d742..28ae1e224e 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);
 }
 
@@ -340,18 +348,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]