[gegl] operation: add gegl_operation_context_dup_input_maybe_copy()
- From: Øyvind Kolås <ok src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gegl] operation: add gegl_operation_context_dup_input_maybe_copy()
- Date: Wed, 13 Dec 2017 23:23:28 +0000 (UTC)
commit 9cb3c7a25b21983709a227d7d27cf1506eb8ffb8
Author: Ell <ell_se yahoo com>
Date: Wed Dec 13 03:19:02 2017 -0500
operation: add gegl_operation_context_dup_input_maybe_copy()
gegl_operation_context_dup_input_maybe_copy() takes a ROI, and
returns either a reference to the input buffer, or a copy of the
input buffer, containing (at least) the region required to process
ROI, if the copy has a low-enough overhead. Note that the copied
input-buffer tiles are generally COWed, so this is rather cheap.
This is useful for threaded ops, which can use this function to
create a separate copy of the input buffer for each thread, to
avoid contention over the input's tile-storage lock. See the next
commit.
gegl/operation/gegl-operation-context.c | 97 +++++++++++++++++++++++++++++++
gegl/operation/gegl-operation-context.h | 11 ++-
2 files changed, 104 insertions(+), 4 deletions(-)
---
diff --git a/gegl/operation/gegl-operation-context.c b/gegl/operation/gegl-operation-context.c
index 74429ed..98c43e0 100644
--- a/gegl/operation/gegl-operation-context.c
+++ b/gegl/operation/gegl-operation-context.c
@@ -21,6 +21,7 @@
#include "config.h"
#include <string.h>
+#include <math.h>
#include <glib-object.h>
@@ -29,6 +30,7 @@
#include "gegl-operation-context.h"
#include "gegl-operation-context-private.h"
#include "gegl-node-private.h"
+#include "gegl-buffer-private.h"
#include "gegl-config.h"
#include "operation/gegl-operation.h"
@@ -397,3 +399,98 @@ gegl_operation_context_get_output_maybe_in_place (GeglOperation *operation,
}
return output;
}
+
+GeglBuffer *
+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;
+
+ 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
+ * input buffer will occupy space in the cache after the original is modified
+ */
+ 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);
+
+ /* 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);
+
+ return result;
+}
diff --git a/gegl/operation/gegl-operation-context.h b/gegl/operation/gegl-operation-context.h
index 1437620..a6e5279 100644
--- a/gegl/operation/gegl-operation-context.h
+++ b/gegl/operation/gegl-operation-context.h
@@ -45,10 +45,13 @@ gint gegl_operation_context_get_level (GeglOperationContext *se
/* the rest of these functions are for internal use only */
-GeglBuffer * gegl_operation_context_get_output_maybe_in_place (GeglOperation *operation,
- GeglOperationContext *context,
- GeglBuffer *input,
- const GeglRectangle *roi);
+GeglBuffer * gegl_operation_context_get_output_maybe_in_place (GeglOperation *operation,
+ GeglOperationContext *context,
+ GeglBuffer *input,
+ const GeglRectangle *roi);
+GeglBuffer * gegl_operation_context_dup_input_maybe_copy (GeglOperationContext *context,
+ const gchar *padname,
+ const GeglRectangle *roi);
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]