[gimp] app: add an optional gegl:cache at the output of GimpApplicator



commit db2ea536daa835f3d561253499e2e82a8f4a4567
Author: Michael Natterer <mitch gimp org>
Date:   Wed Jun 18 18:50:53 2014 +0200

    app: add an optional gegl:cache at the output of GimpApplicator
    
    Add "gboolean use_cache" to gimp_applicator_new(). Don't use a cache
    anywhere but in GimpImageMap because it incrementally fills that cache
    via the projection update. In gimp_drawable_merge_filter(), get that
    cache and pass it to gimp_gegl_apply_cached_operation() which then
    avoids doing the work twice for the already cached results. Win!

 app/core/gimpdrawable-combine.c |    3 +-
 app/core/gimpdrawable-filter.c  |   33 ++++++++++++++++---
 app/core/gimpdrawable.c         |    2 +-
 app/core/gimpimage-merge.c      |    3 +-
 app/core/gimpimagemap.c         |    3 +-
 app/gegl/gimpapplicator.c       |   66 +++++++++++++++++++++++++++++++++------
 app/gegl/gimpapplicator.h       |    8 ++++-
 app/paint/gimppaintcore.c       |    2 +-
 8 files changed, 99 insertions(+), 21 deletions(-)
---
diff --git a/app/core/gimpdrawable-combine.c b/app/core/gimpdrawable-combine.c
index 6f37c2d..cd80dad 100644
--- a/app/core/gimpdrawable-combine.c
+++ b/app/core/gimpdrawable-combine.c
@@ -118,7 +118,8 @@ gimp_drawable_real_apply_buffer (GimpDrawable         *drawable,
         }
     }
 
-  applicator = gimp_applicator_new (NULL, gimp_drawable_get_linear (drawable));
+  applicator = gimp_applicator_new (NULL, gimp_drawable_get_linear (drawable),
+                                    FALSE);
 
   if (mask)
     {
diff --git a/app/core/gimpdrawable-filter.c b/app/core/gimpdrawable-filter.c
index 284a692..82a091e 100644
--- a/app/core/gimpdrawable-filter.c
+++ b/app/core/gimpdrawable-filter.c
@@ -97,6 +97,9 @@ gimp_drawable_merge_filter (GimpDrawable *drawable,
                                 &rect.width, &rect.height))
     {
       GimpApplicator *applicator;
+      GeglBuffer     *cache   = NULL;
+      GeglRectangle  *rects   = NULL;
+      gint            n_rects = 0;
 
       gimp_drawable_push_undo (drawable, undo_desc, NULL,
                                rect.x, rect.y,
@@ -119,13 +122,33 @@ gimp_drawable_merge_filter (GimpDrawable *drawable,
               undo->applied_buffer =
                 gimp_applicator_dup_apply_buffer (applicator, &rect);
             }
+
+          cache = gimp_applicator_get_cache_buffer (applicator,
+                                                    &rects, &n_rects);
+
+          if (cache)
+            {
+              gint i;
+
+              for (i = 0; i < n_rects; i++)
+                g_printerr ("valid: %d %d %d %d\n",
+                            rects[i].x, rects[i].y,
+                            rects[i].width, rects[i].height);
+            }
         }
 
-      gimp_gegl_apply_operation (gimp_drawable_get_buffer (drawable),
-                                 progress, undo_desc,
-                                 gimp_filter_get_node (filter),
-                                 gimp_drawable_get_buffer (drawable),
-                                 &rect);
+      gimp_gegl_apply_cached_operation (gimp_drawable_get_buffer (drawable),
+                                        progress, undo_desc,
+                                        gimp_filter_get_node (filter),
+                                        gimp_drawable_get_buffer (drawable),
+                                        &rect,
+                                        cache, rects, n_rects);
+
+      if (cache)
+        {
+          g_object_unref (cache);
+          g_free (rects);
+        }
 
       gimp_drawable_update (drawable,
                             rect.x, rect.y,
diff --git a/app/core/gimpdrawable.c b/app/core/gimpdrawable.c
index b4636ef..110756a 100644
--- a/app/core/gimpdrawable.c
+++ b/app/core/gimpdrawable.c
@@ -957,7 +957,7 @@ gimp_drawable_sync_fs_filter (GimpDrawable *drawable,
 
           gegl_node_add_child (node, fs_source);
 
-          private->fs_applicator = gimp_applicator_new (node, linear);
+          private->fs_applicator = gimp_applicator_new (node, linear, FALSE);
 
           private->fs_crop_node =
             gegl_node_new_child (node,
diff --git a/app/core/gimpimage-merge.c b/app/core/gimpimage-merge.c
index 7892ead..aec9c75 100644
--- a/app/core/gimpimage-merge.c
+++ b/app/core/gimpimage-merge.c
@@ -614,7 +614,8 @@ gimp_image_merge_layers (GimpImage     *image,
 
       applicator =
         gimp_applicator_new (NULL,
-                             gimp_drawable_get_linear (GIMP_DRAWABLE (layer)));
+                             gimp_drawable_get_linear (GIMP_DRAWABLE (layer)),
+                             FALSE);
 
       if (gimp_layer_get_mask (layer) &&
           gimp_layer_get_apply_mask (layer))
diff --git a/app/core/gimpimagemap.c b/app/core/gimpimagemap.c
index 1cea9a2..73439b0 100644
--- a/app/core/gimpimagemap.c
+++ b/app/core/gimpimagemap.c
@@ -288,7 +288,8 @@ gimp_image_map_apply (GimpImageMap        *image_map,
 
       image_map->applicator =
         gimp_applicator_new (filter_node,
-                             gimp_drawable_get_linear (image_map->drawable));
+                             gimp_drawable_get_linear (image_map->drawable),
+                             TRUE);
 
       gimp_filter_set_applicator (image_map->filter,
                                   image_map->applicator);
diff --git a/app/gegl/gimpapplicator.c b/app/gegl/gimpapplicator.c
index fc85be8..b8dd90b 100644
--- a/app/gegl/gimpapplicator.c
+++ b/app/gegl/gimpapplicator.c
@@ -106,7 +106,8 @@ gimp_applicator_get_property (GObject    *object,
 
 GimpApplicator *
 gimp_applicator_new (GeglNode *parent,
-                     gboolean  linear)
+                     gboolean  linear,
+                     gboolean  use_cache)
 {
   GimpApplicator *applicator;
 
@@ -148,16 +149,15 @@ gimp_applicator_new (GeglNode *parent,
                          "operation", "gegl:translate",
                          NULL);
 
-  gegl_node_connect_to (applicator->aux_node,          "output",
-                        applicator->apply_offset_node, "input");
-
   applicator->dup_apply_buffer_node =
     gegl_node_new_child (applicator->node,
                          "operation", "gegl:copy-buffer",
                          NULL);
 
-  gegl_node_connect_to (applicator->apply_offset_node,     "output",
-                        applicator->dup_apply_buffer_node, "input");
+  gegl_node_link_many (applicator->aux_node,
+                       applicator->apply_offset_node,
+                       applicator->dup_apply_buffer_node,
+                       NULL);
   gegl_node_connect_to (applicator->dup_apply_buffer_node, "output",
                         applicator->mode_node,             "aux");
 
@@ -181,12 +181,29 @@ gimp_applicator_new (GeglNode *parent,
                          "mask",      applicator->affect,
                          NULL);
 
-  gegl_node_connect_to (applicator->input_node,  "output",
-                        applicator->affect_node, "input");
+  if (use_cache)
+    {
+      applicator->cache_node =
+        gegl_node_new_child (applicator->node,
+                             "operation", "gegl:cache",
+                             NULL);
+
+      gegl_node_link_many (applicator->input_node,
+                           applicator->affect_node,
+                           applicator->cache_node,
+                           applicator->output_node,
+                           NULL);
+    }
+  else
+    {
+      gegl_node_link_many (applicator->input_node,
+                           applicator->affect_node,
+                           applicator->output_node,
+                           NULL);
+    }
+
   gegl_node_connect_to (applicator->mode_node,   "output",
                         applicator->affect_node, "aux");
-  gegl_node_connect_to (applicator->affect_node, "output",
-                        applicator->output_node, "input");
 
   return applicator;
 }
@@ -450,3 +467,32 @@ gimp_applicator_dup_apply_buffer (GimpApplicator      *applicator,
 
   return buffer;
 }
+
+gboolean gegl_buffer_list_valid_rectangles (GeglBuffer     *buffer,
+                                            GeglRectangle **rectangles,
+                                            gint           *n_rectangles);
+
+GeglBuffer *
+gimp_applicator_get_cache_buffer (GimpApplicator  *applicator,
+                                  GeglRectangle  **rectangles,
+                                  gint            *n_rectangles)
+{
+  if (applicator->cache_node)
+    {
+      GeglBuffer *cache;
+
+      gegl_node_get (applicator->cache_node,
+                     "cache", &cache,
+                     NULL);
+
+      if (cache)
+        {
+          if (gegl_buffer_list_valid_rectangles (cache, rectangles, n_rectangles))
+            return cache;
+
+          g_object_unref (cache);
+        }
+    }
+
+  return NULL;
+}
diff --git a/app/gegl/gimpapplicator.h b/app/gegl/gimpapplicator.h
index f434bc8..9ba5e70 100644
--- a/app/gegl/gimpapplicator.h
+++ b/app/gegl/gimpapplicator.h
@@ -58,6 +58,8 @@ struct _GimpApplicator
   GimpComponentMask     affect;
   GeglNode             *affect_node;
 
+  GeglNode             *cache_node;
+
   GeglBuffer           *src_buffer;
   GeglNode             *src_node;
 
@@ -81,7 +83,8 @@ struct _GimpApplicatorClass
 GType        gimp_applicator_get_type         (void) G_GNUC_CONST;
 
 GimpApplicator * gimp_applicator_new          (GeglNode             *parent,
-                                               gboolean              linear);
+                                               gboolean              linear,
+                                               gboolean              use_cache);
 
 void         gimp_applicator_set_src_buffer   (GimpApplicator       *applicator,
                                                GeglBuffer           *dest_buffer);
@@ -111,6 +114,9 @@ void         gimp_applicator_blit             (GimpApplicator       *applicator,
 
 GeglBuffer * gimp_applicator_dup_apply_buffer (GimpApplicator       *applicator,
                                                const GeglRectangle  *rect);
+GeglBuffer * gimp_applicator_get_cache_buffer (GimpApplicator       *applicator,
+                                               GeglRectangle       **rectangles,
+                                               gint                 *n_rectangles);
 
 
 #endif  /*  __GIMP_APPLICATOR_H__  */
diff --git a/app/paint/gimppaintcore.c b/app/paint/gimppaintcore.c
index 117cbf1..87e1258 100644
--- a/app/paint/gimppaintcore.c
+++ b/app/paint/gimppaintcore.c
@@ -429,7 +429,7 @@ gimp_paint_core_start (GimpPaintCore     *core,
 
   if (paint_options->use_applicator)
     {
-      core->applicator = gimp_applicator_new (NULL, core->linear_mode);
+      core->applicator = gimp_applicator_new (NULL, core->linear_mode, FALSE);
 
       if (core->mask_buffer)
         {


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