[gegl] operation: use GeglTileBackendBuffer in gegl_operation_context_dup_input_maybe_copy()



commit 417221a05e59fc857a2dee07f6bafe49af5ecd6d
Author: Ell <ell_se yahoo com>
Date:   Thu May 3 16:12:44 2018 -0400

    operation: use GeglTileBackendBuffer in gegl_operation_context_dup_input_maybe_copy()
    
    In gegl_operation_context_dup_input_maybe_copy(), use a
    GeglTileBackendBuffer, backed by the input buffer, as the backend
    for the local-copy buffer, instead of copying the required portion
    of the input buffer into the local-copy buffer.  This allows input-
    buffer tiles to be COWed on-demand, instead of upfront, into the
    local-copy, which can significantly improve performance if the op's
    get_required_for_output() returns a larger region than actually
    necessary (in particular, if it always returns the entire input
    extents).  This also allows using the local-copy optimization when
    processing a level > 0.
    
    Leave the original version #if 0-ed, since it may be useful for
    testing.

 gegl/operation/gegl-operation-context.c |  169 ++++++++++++++++++------------
 1 files changed, 101 insertions(+), 68 deletions(-)
---
diff --git a/gegl/operation/gegl-operation-context.c b/gegl/operation/gegl-operation-context.c
index 98c43e0..c4787b6 100644
--- a/gegl/operation/gegl-operation-context.c
+++ b/gegl/operation/gegl-operation-context.c
@@ -31,6 +31,7 @@
 #include "gegl-operation-context-private.h"
 #include "gegl-node-private.h"
 #include "gegl-buffer-private.h"
+#include "gegl-tile-backend-buffer.h"
 #include "gegl-config.h"
 
 #include "operation/gegl-operation.h"
@@ -405,27 +406,15 @@ gegl_operation_context_dup_input_maybe_copy (GeglOperationContext *context,
                                              const gchar          *padname,
                                              const GeglRectangle  *roi)
 {
-  GeglBuffer    *input;
-  GeglBuffer    *output;
-  GeglBuffer    *result;
-  GeglRectangle  required;
-  GeglRectangle  temp;
-  gint           shift_x;
-  gint           shift_y;
-  gint           tile_width;
-  gint           tile_height;
+  GeglBuffer *input;
+  GeglBuffer *output;
+  GeglBuffer *result;
 
   input = GEGL_BUFFER (gegl_operation_context_get_object (context, padname));
 
   if (! input)
     return NULL;
 
-  /* return input directly when processing a level greater than 0, since
-   * gegl_buffer_copy() only copies level-0 tiles
-   */
-  if (context->level > 0)
-    return g_object_ref (input);
-
   output = GEGL_BUFFER (gegl_operation_context_get_object (context, "output"));
 
   /* return input directly when processing in-place, otherwise, the copied
@@ -434,63 +423,107 @@ gegl_operation_context_dup_input_maybe_copy (GeglOperationContext *context,
   if (input == output)
     return g_object_ref (input);
 
-  /* get required region to copy */
-  required = gegl_operation_get_required_for_output (context->operation,
-                                                     padname, roi);
-
-  /* return input directly if the required rectangle is infinite, so that we
-   * don't attempt to copy an infinite region
-   */
-  if (gegl_rectangle_is_infinite_plane (&required))
-    return g_object_ref (input);
+#if 1
+  {
+    GeglTileBackend *backend;
+
+    backend = gegl_tile_backend_buffer_new (input);
+    gegl_tile_backend_set_flush_on_destroy (backend, FALSE);
+
+    /* create new buffer with similar characteristics to the input buffer */
+    result = g_object_new (GEGL_TYPE_BUFFER,
+                           "format",       input->soft_format,
+                           "x",            input->extent.x,
+                           "y",            input->extent.y,
+                           "width",        input->extent.width,
+                           "height",       input->extent.height,
+                           "abyss-x",      input->abyss.x,
+                           "abyss-y",      input->abyss.y,
+                           "abyss-width",  input->abyss.width,
+                           "abyss-height", input->abyss.height,
+                           "shift-x",      input->shift_x,
+                           "shift-y",      input->shift_y,
+                           "tile-width",   input->tile_width,
+                           "tile-height",  input->tile_height,
+                           "backend",      backend,
+                           NULL);
+
+    g_object_unref (backend);
+  }
+#else
+  {
+    GeglRectangle required;
+    GeglRectangle temp;
+    gint          shift_x;
+    gint          shift_y;
+    gint          tile_width;
+    gint          tile_height;
+
+    /* return input directly when processing a level greater than 0, since
+     * gegl_buffer_copy() only copies level-0 tiles
+     */
+    if (context->level > 0)
+      return g_object_ref (input);
 
-  /* align required region to the tile grid */
-  shift_x     = input->shift_x;
-  shift_y     = input->shift_y;
-  tile_width  = input->tile_width;
-  tile_height = input->tile_height;
-
-  temp.x      = (gint) floor ((gdouble) (required.x                   + shift_x) / tile_width)  * tile_width;
-  temp.y      = (gint) floor ((gdouble) (required.y                   + shift_y) / tile_height) * 
tile_height;
-  temp.width  = (gint) ceil  ((gdouble) (required.x + required.width  + shift_x) / tile_width)  * tile_width 
 - temp.x;
-  temp.height = (gint) ceil  ((gdouble) (required.y + required.height + shift_y) / tile_height) * 
tile_height - temp.y;
-
-  temp.x -= shift_x;
-  temp.y -= shift_y;
-
-  required = temp;
-
-  /* intersect required region with input abyss */
-  gegl_rectangle_intersect (&required, &required, &input->abyss);
-
-  /* create new buffer with similar characteristics to the input buffer */
-  result = g_object_new (GEGL_TYPE_BUFFER,
-                         "format",       input->soft_format,
-                         "x",            input->extent.x,
-                         "y",            input->extent.y,
-                         "width",        input->extent.width,
-                         "height",       input->extent.height,
-                         "abyss-x",      input->abyss.x,
-                         "abyss-y",      input->abyss.y,
-                         "abyss-width",  input->abyss.width,
-                         "abyss-height", input->abyss.height,
-                         "shift-x",      shift_x,
-                         "shift-y",      shift_y,
-                         "tile-width",   tile_width,
-                         "tile-height",  tile_height,
-                         NULL);
-
-  /* if the tile size doesn't match, bail */
-  if (result->tile_width != tile_width || result->tile_height != tile_height)
-    {
-      g_object_unref (result);
+    /* get required region to copy */
+    required = gegl_operation_get_required_for_output (context->operation,
+                                                       padname, roi);
 
+    /* return input directly if the required rectangle is infinite, so that we
+     * don't attempt to copy an infinite region
+     */
+    if (gegl_rectangle_is_infinite_plane (&required))
       return g_object_ref (input);
-    }
 
-  /* copy required region from input to result -- tiles will generally be COWed */
-  gegl_buffer_copy (input,  &required, GEGL_ABYSS_NONE,
-                    result, &required);
+    /* align required region to the tile grid */
+    shift_x     = input->shift_x;
+    shift_y     = input->shift_y;
+    tile_width  = input->tile_width;
+    tile_height = input->tile_height;
+
+    temp.x      = (gint) floor ((gdouble) (required.x                   + shift_x) / tile_width)  * 
tile_width;
+    temp.y      = (gint) floor ((gdouble) (required.y                   + shift_y) / tile_height) * 
tile_height;
+    temp.width  = (gint) ceil  ((gdouble) (required.x + required.width  + shift_x) / tile_width)  * 
tile_width  - temp.x;
+    temp.height = (gint) ceil  ((gdouble) (required.y + required.height + shift_y) / tile_height) * 
tile_height - temp.y;
+
+    temp.x -= shift_x;
+    temp.y -= shift_y;
+
+    required = temp;
+
+    /* intersect required region with input abyss */
+    gegl_rectangle_intersect (&required, &required, &input->abyss);
+
+    /* create new buffer with similar characteristics to the input buffer */
+    result = g_object_new (GEGL_TYPE_BUFFER,
+                           "format",       input->soft_format,
+                           "x",            input->extent.x,
+                           "y",            input->extent.y,
+                           "width",        input->extent.width,
+                           "height",       input->extent.height,
+                           "abyss-x",      input->abyss.x,
+                           "abyss-y",      input->abyss.y,
+                           "abyss-width",  input->abyss.width,
+                           "abyss-height", input->abyss.height,
+                           "shift-x",      shift_x,
+                           "shift-y",      shift_y,
+                           "tile-width",   tile_width,
+                           "tile-height",  tile_height,
+                           NULL);
+
+    /* if the tile size doesn't match, bail */
+    if (result->tile_width != tile_width || result->tile_height != tile_height)
+      {
+        g_object_unref (result);
+
+        return g_object_ref (input);
+      }
+
+    /* copy required region from input to result -- tiles will generally be COWed */
+    gegl_buffer_copy (input,  &required, GEGL_ABYSS_NONE,
+                      result, &required);
+  }
+#endif
 
   return result;
 }


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