[gimp] app: use GimpChunkIterator in gimp_gegl_apply_cached_operation()



commit 4110f7b7b186a609d9ca9882cf1f8a1e12b4169e
Author: Ell <ell_se yahoo com>
Date:   Sat Jan 12 03:41:00 2019 -0500

    app: use GimpChunkIterator in gimp_gegl_apply_cached_operation()
    
    In gimp_gegl_apply_cached_operation(), replace the use of
    GeglProcessor with GimpChunkIterator, so that we use the same
    chunking logic as for rendering projections.  This has the
    advantage of better chunk alignment to the tile grid and dynamic
    chunk sizing, which improve performance.
    
    Use chunking even when there's no progress indication, since it
    generally results in better cache locality.

 app/gegl/gimp-gegl-apply-operation.c | 131 +++++++++++++++--------------------
 1 file changed, 54 insertions(+), 77 deletions(-)
---
diff --git a/app/gegl/gimp-gegl-apply-operation.c b/app/gegl/gimp-gegl-apply-operation.c
index df4f3dd96e..4b4f121f63 100644
--- a/app/gegl/gimp-gegl-apply-operation.c
+++ b/app/gegl/gimp-gegl-apply-operation.c
@@ -30,6 +30,7 @@
 
 #include "core/gimp-transform-utils.h"
 #include "core/gimp-utils.h"
+#include "core/gimpchunkiterator.h"
 #include "core/gimpprogress.h"
 
 #include "gimp-gegl-apply-operation.h"
@@ -77,15 +78,17 @@ gimp_gegl_apply_cached_operation (GeglBuffer          *src_buffer,
                                   gint                 n_valid_rects,
                                   gboolean             cancelable)
 {
-  GeglNode      *gegl;
-  GeglNode      *effect;
-  GeglNode      *dest_node;
-  GeglNode      *operation_src_node = NULL;
-  GeglRectangle  rect = { 0, };
-  GeglProcessor *processor          = NULL;
-  gboolean       progress_started   = FALSE;
-  gdouble        value;
-  gboolean       cancel             = FALSE;
+  GeglNode          *gegl;
+  GeglNode          *effect;
+  GeglNode          *dest_node;
+  GeglNode          *operation_src_node = NULL;
+  GimpChunkIterator *iter;
+  cairo_region_t    *region;
+  GeglRectangle      rect = { 0, };
+  gboolean           progress_started   = FALSE;
+  gboolean           cancel             = FALSE;
+  gint               all_pixels;
+  gint               done_pixels;
 
   g_return_val_if_fail (src_buffer == NULL || GEGL_IS_BUFFER (src_buffer), FALSE);
   g_return_val_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress), FALSE);
@@ -117,9 +120,9 @@ gimp_gegl_apply_cached_operation (GeglBuffer          *src_buffer,
       GeglNode *src_node;
 
       /* dup() because reading and writing the same buffer doesn't
-       * work with area ops when using a processor. See bug #701875.
+       * work with area ops when working in chunks. See bug #701875.
        */
-      if (progress && (src_buffer == dest_buffer))
+      if (src_buffer == dest_buffer)
         src_buffer = gegl_buffer_dup (src_buffer);
       else
         g_object_ref (src_buffer);
@@ -175,8 +178,6 @@ gimp_gegl_apply_cached_operation (GeglBuffer          *src_buffer,
 
   if (progress)
     {
-      processor = gegl_node_new_processor (dest_node, &rect);
-
       if (gimp_progress_is_active (progress))
         {
           if (undo_desc)
@@ -197,18 +198,21 @@ gimp_gegl_apply_cached_operation (GeglBuffer          *src_buffer,
           progress_started = TRUE;
         }
     }
-
-  if (cache)
+  else
     {
-      cairo_region_t *region;
-      gint            all_pixels;
-      gint            done_pixels = 0;
-      gint            n_rects;
-      gint            i;
+      cancelable = FALSE;
+    }
+
+  gegl_buffer_freeze_changed (dest_buffer);
 
-      region = cairo_region_create_rectangle ((cairo_rectangle_int_t *) &rect);
+  all_pixels  = rect.width * rect.height;
+  done_pixels = 0;
 
-      all_pixels = rect.width * rect.height;
+  region = cairo_region_create_rectangle ((cairo_rectangle_int_t *) &rect);
+
+  if (cache)
+    {
+      gint i;
 
       for (i = 0; i < n_valid_rects; i++)
         {
@@ -230,75 +234,48 @@ gimp_gegl_apply_cached_operation (GeglBuffer          *src_buffer,
           done_pixels += valid_rect.width * valid_rect.height;
 
           if (progress)
-            gimp_progress_set_value (progress,
-                                     (gdouble) done_pixels /
-                                     (gdouble) all_pixels);
+            {
+              gimp_progress_set_value (progress,
+                                       (gdouble) done_pixels /
+                                       (gdouble) all_pixels);
+            }
         }
+    }
 
-      n_rects = cairo_region_num_rectangles (region);
+  iter = gimp_chunk_iterator_new (region);
 
-      for (i = 0; ! cancel && (i < n_rects); i++)
-        {
-          cairo_rectangle_int_t render_rect;
+  while (gimp_chunk_iterator_next (iter))
+    {
+      GeglRectangle render_rect;
 
-          cairo_region_get_rectangle (region, i, &render_rect);
+      if (progress)
+        {
+          while (! cancel && g_main_context_pending (NULL))
+            g_main_context_iteration (NULL, FALSE);
 
-          if (progress)
-            {
-              gint rect_pixels = render_rect.width * render_rect.height;
-
-#ifdef REUSE_PROCESSOR
-              gegl_processor_set_rectangle (processor,
-                                            (GeglRectangle *) &render_rect);
-#else
-              g_object_unref (processor);
-              processor = gegl_node_new_processor (dest_node,
-                                                   (GeglRectangle *) &render_rect);
-#endif
-
-              while (! cancel && gegl_processor_work (processor, &value))
-                {
-                  gimp_progress_set_value (progress,
-                                           ((gdouble) done_pixels +
-                                            value * rect_pixels) /
-                                           (gdouble) all_pixels);
-
-                  while (! cancel && g_main_context_pending (NULL))
-                    g_main_context_iteration (NULL, FALSE);
-                }
-
-              done_pixels += rect_pixels;
-            }
-          else
-            {
-              gegl_node_blit (dest_node, 1.0, (GeglRectangle *) &render_rect,
-                              NULL, NULL, 0, GEGL_BLIT_DEFAULT);
-            }
+          if (cancel)
+            break;
         }
 
-      cairo_region_destroy (region);
-    }
-  else
-    {
-      if (progress)
+      while (gimp_chunk_iterator_get_rect (iter, &render_rect))
         {
-          while (! cancel && gegl_processor_work (processor, &value))
-            {
-              gimp_progress_set_value (progress, value);
+          gint rect_pixels = render_rect.width * render_rect.height;
 
-              while (! cancel && g_main_context_pending (NULL))
-                g_main_context_iteration (NULL, FALSE);
-            }
+          gegl_node_blit (dest_node, 1.0, &render_rect, NULL, NULL, 0,
+                          GEGL_BLIT_DEFAULT);
+
+          done_pixels += rect_pixels;
         }
-      else
+
+      if (progress)
         {
-          gegl_node_blit (dest_node, 1.0, &rect,
-                          NULL, NULL, 0, GEGL_BLIT_DEFAULT);
+          gimp_progress_set_value (progress,
+                                   (gdouble) done_pixels /
+                                   (gdouble) all_pixels);
         }
     }
 
-  if (processor)
-    g_object_unref (processor);
+  gegl_buffer_thaw_changed (dest_buffer);
 
   g_object_unref (gegl);
 


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