[gegl/wip/Jehan/gegl_node_process_success] gegl: new gegl_node_process_success() function.
- From: Jehan <jehanp src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gegl/wip/Jehan/gegl_node_process_success] gegl: new gegl_node_process_success() function.
- Date: Tue, 26 Mar 2019 15:48:16 +0000 (UTC)
commit 447c4d6a998e18d3731f4dc146bb13f0765bdbe0
Author: Jehan <jehan girinstud io>
Date: Fri Mar 22 19:08:49 2019 +0100
gegl: new gegl_node_process_success() function.
gegl_node_process_success() returns TRUE if the last call of
gegl_node_process(), gegl_node_blit() or gegl_node_blit_buffer() was a
success.
This will also return the success from a call to gegl_processor_work() if
you use the node given to gegl_node_new_processor() as argument.
Additionally in case of process failure, a GError is returned, allowing
calling applications to process failure appropriately.
To make usage of this new possibility, GeglOperation subclass should
implement the new virtual method process2() (same as process() with the
added GError parameter).
A similar virtual method process2() was added to various GeglOperation
families (GeglOperationSink, GeglOperationSource, GeglOperationTemporal,
GeglOperation*Composer(3), GeglOperation*Filter and
GelOperationPointRender).
gegl/graph/gegl-node-private.h | 3 +
gegl/graph/gegl-node.c | 21 ++++++
gegl/graph/gegl-node.h | 16 +++++
gegl/operation/gegl-operation-composer.c | 40 +++++++----
gegl/operation/gegl-operation-composer.h | 21 ++++--
gegl/operation/gegl-operation-composer3.c | 43 ++++++++----
gegl/operation/gegl-operation-composer3.h | 24 ++++---
gegl/operation/gegl-operation-filter.c | 37 ++++++----
gegl/operation/gegl-operation-filter.h | 6 ++
gegl/operation/gegl-operation-point-composer.c | 94 ++++++++++++++++++-------
gegl/operation/gegl-operation-point-composer.h | 22 ++++--
gegl/operation/gegl-operation-point-filter.c | 96 ++++++++++++++++++--------
gegl/operation/gegl-operation-point-filter.h | 25 ++++---
gegl/operation/gegl-operation-point-render.c | 26 ++++---
gegl/operation/gegl-operation-point-render.h | 18 +++--
gegl/operation/gegl-operation-sink.c | 33 ++++++---
gegl/operation/gegl-operation-sink.h | 17 +++--
gegl/operation/gegl-operation-source.c | 40 +++++++----
gegl/operation/gegl-operation-source.h | 17 +++--
gegl/operation/gegl-operation-temporal.c | 17 +++--
gegl/operation/gegl-operation-temporal.h | 18 +++--
gegl/operation/gegl-operation.c | 35 ++++++++--
gegl/operation/gegl-operation.h | 13 ++++
gegl/process/gegl-eval-manager.c | 4 +-
gegl/process/gegl-graph-traversal.c | 35 +++++++---
gegl/process/gegl-graph-traversal.h | 3 +-
gegl/process/gegl-processor.c | 14 ++--
27 files changed, 529 insertions(+), 209 deletions(-)
---
diff --git a/gegl/graph/gegl-node-private.h b/gegl/graph/gegl-node-private.h
index 21d127dd7..2ea3b0c0e 100644
--- a/gegl/graph/gegl-node-private.h
+++ b/gegl/graph/gegl-node-private.h
@@ -91,6 +91,9 @@ struct _GeglNode
gint passthrough;
+ gboolean success;
+ GError *error;
+
/*< private >*/
GeglNodePrivate *priv;
};
diff --git a/gegl/graph/gegl-node.c b/gegl/graph/gegl-node.c
index 80152605f..9a962fab3 100644
--- a/gegl/graph/gegl-node.c
+++ b/gegl/graph/gegl-node.c
@@ -239,6 +239,8 @@ gegl_node_init (GeglNode *self)
self->is_graph = FALSE;
self->cache = NULL;
self->output_visitable = gegl_node_output_visitable_new (self);
+ self->success = FALSE;
+ self->error = NULL;
g_mutex_init (&self->mutex);
}
@@ -288,6 +290,7 @@ gegl_node_finalize (GObject *gobject)
g_clear_object (&self->output_visitable);
g_free (self->priv->name);
g_free (self->priv->debug_name);
+ g_clear_error (&self->error);
g_mutex_clear (&self->mutex);
@@ -1850,6 +1853,24 @@ gegl_node_process (GeglNode *self) /* XXX: add level argument? */
g_object_unref (processor);
}
+gboolean
+gegl_node_process_success (GeglNode *self,
+ GError **error)
+{
+ GeglNode *real_node;
+
+ /* If @self is a graph, the error will be set on its output proxy. */
+ if (GEGL_IS_OPERATION (self->operation))
+ real_node = self;
+ else
+ real_node = gegl_node_get_output_proxy (self, "output");
+
+ if (error && ! real_node->success && real_node->error)
+ *error = g_error_copy (real_node->error);
+
+ return real_node->success;
+}
+
GeglNode *
gegl_node_detect (GeglNode *root,
gint x,
diff --git a/gegl/graph/gegl-node.h b/gegl/graph/gegl-node.h
index 6eca2cfb9..8d63df977 100644
--- a/gegl/graph/gegl-node.h
+++ b/gegl/graph/gegl-node.h
@@ -342,6 +342,22 @@ void gegl_node_blit_buffer (GeglNode *node,
*/
void gegl_node_process (GeglNode *sink_node);
+/**
+ * gegl_node_process_success:
+ * @node: a #GeglNode.
+ * @error: (out): an optional error string.
+ *
+ * Returns: TRUE is the last call to gegl_node_process(), gegl_node_blit() or
+ * gegl_node_blit_buffer() on @node was a success, FALSE otherwise.
+ *
+ * This will also return the success from a call to gegl_processor_work() if
+ * you use the node given to gegl_node_new_processor().
+ *
+ * In case of failure and if @error was not NULL, a copy of the error string
+ * will be allocated.
+ */
+gboolean gegl_node_process_success (GeglNode *node,
+ GError **error);
/***
* Reparenting:
diff --git a/gegl/operation/gegl-operation-composer.c b/gegl/operation/gegl-operation-composer.c
index 526d40b23..91073ae68 100644
--- a/gegl/operation/gegl-operation-composer.c
+++ b/gegl/operation/gegl-operation-composer.c
@@ -26,11 +26,12 @@
#include "gegl-operation-context.h"
#include "gegl-config.h"
-static gboolean gegl_operation_composer_process (GeglOperation *operation,
+static gboolean gegl_operation_composer_process2 (GeglOperation *operation,
GeglOperationContext *context,
const gchar *output_prop,
const GeglRectangle *result,
- gint level);
+ gint level,
+ GError **error);
static void attach (GeglOperation *operation);
static GeglNode*detect (GeglOperation *operation,
gint x,
@@ -50,7 +51,7 @@ gegl_operation_composer_class_init (GeglOperationComposerClass * klass)
{
GeglOperationClass *operation_class = GEGL_OPERATION_CLASS (klass);
- operation_class->process = gegl_operation_composer_process;
+ operation_class->process2 = gegl_operation_composer_process2;
operation_class->threaded = TRUE;
operation_class->attach = attach;
operation_class->detect = detect;
@@ -108,6 +109,7 @@ typedef struct ThreadData
const GeglRectangle *roi;
gint level;
gboolean success;
+ GError **error;
} ThreadData;
static void
@@ -115,6 +117,7 @@ thread_process (const GeglRectangle *area,
ThreadData *data)
{
GeglBuffer *input;
+ gboolean success = TRUE;
if (area->x == data->roi->x && area->y == data->roi->y)
{
@@ -126,20 +129,27 @@ thread_process (const GeglRectangle *area,
"input", area);
}
- if (!data->klass->process (data->operation,
- input, data->aux, data->output,
- area, data->level))
+ if (data->klass->process2)
+ success = data->klass->process2 (data->operation,
+ input, data->aux, data->output,
+ area, data->level, data->error);
+ else
+ success = data->klass->process (data->operation,
+ input, data->aux, data->output,
+ area, data->level);
+ if (! success)
data->success = FALSE;
g_object_unref (input);
}
static gboolean
-gegl_operation_composer_process (GeglOperation *operation,
- GeglOperationContext *context,
- const gchar *output_prop,
- const GeglRectangle *result,
- gint level)
+gegl_operation_composer_process2 (GeglOperation *operation,
+ GeglOperationContext *context,
+ const gchar *output_prop,
+ const GeglRectangle *result,
+ gint level,
+ GError **error)
{
GeglOperationComposerClass *klass = GEGL_OPERATION_COMPOSER_GET_CLASS (operation);
GeglBuffer *input;
@@ -179,6 +189,7 @@ gegl_operation_composer_process (GeglOperation *operation,
data.roi = result;
data.level = level;
data.success = TRUE;
+ data.error = error;
gegl_parallel_distribute_area (
result,
@@ -191,7 +202,12 @@ gegl_operation_composer_process (GeglOperation *operation,
}
else
{
- success = klass->process (operation, input, aux, output, result, level);
+ if (klass->process2)
+ success = klass->process2 (operation, input, aux, output,
+ result, level, error);
+ else
+ success = klass->process (operation, input, aux, output,
+ result, level);
}
g_clear_object (&input);
diff --git a/gegl/operation/gegl-operation-composer.h b/gegl/operation/gegl-operation-composer.h
index 783498610..cb0fac606 100644
--- a/gegl/operation/gegl-operation-composer.h
+++ b/gegl/operation/gegl-operation-composer.h
@@ -46,13 +46,20 @@ struct _GeglOperationComposerClass
{
GeglOperationClass parent_class;
- gboolean (* process) (GeglOperation *self,
- GeglBuffer *input,
- GeglBuffer *aux,
- GeglBuffer *output,
- const GeglRectangle *result,
- gint level);
- gpointer pad[4];
+ gboolean (* process) (GeglOperation *self,
+ GeglBuffer *input,
+ GeglBuffer *aux,
+ GeglBuffer *output,
+ const GeglRectangle *result,
+ gint level);
+ gboolean (* process2) (GeglOperation *self,
+ GeglBuffer *input,
+ GeglBuffer *aux,
+ GeglBuffer *output,
+ const GeglRectangle *result,
+ gint level,
+ GError **error);
+ gpointer pad[4];
};
GType gegl_operation_composer_get_type (void) G_GNUC_CONST;
diff --git a/gegl/operation/gegl-operation-composer3.c b/gegl/operation/gegl-operation-composer3.c
index 91691ee47..0fe09a1b4 100644
--- a/gegl/operation/gegl-operation-composer3.c
+++ b/gegl/operation/gegl-operation-composer3.c
@@ -26,12 +26,13 @@
#include "gegl-operation-context.h"
#include "gegl-config.h"
-static gboolean gegl_operation_composer3_process
+static gboolean gegl_operation_composer3_process2
(GeglOperation *operation,
GeglOperationContext *context,
const gchar *output_prop,
const GeglRectangle *result,
- gint level);
+ gint level,
+ GError **error);
static void attach (GeglOperation *operation);
static GeglNode*detect (GeglOperation *operation,
gint x,
@@ -51,7 +52,7 @@ gegl_operation_composer3_class_init (GeglOperationComposer3Class * klass)
{
GeglOperationClass *operation_class = GEGL_OPERATION_CLASS (klass);
- operation_class->process = gegl_operation_composer3_process;
+ operation_class->process2 = gegl_operation_composer3_process2;
operation_class->attach = attach;
operation_class->detect = detect;
operation_class->get_bounding_box = get_bounding_box;
@@ -118,6 +119,7 @@ typedef struct ThreadData
const GeglRectangle *roi;
gint level;
gboolean success;
+ GError **error;
} ThreadData;
static void
@@ -125,6 +127,7 @@ thread_process (const GeglRectangle *area,
ThreadData *data)
{
GeglBuffer *input;
+ gboolean success = TRUE;
if (area->x == data->roi->x && area->y == data->roi->y)
{
@@ -136,21 +139,29 @@ thread_process (const GeglRectangle *area,
"input", area);
}
- if (!data->klass->process (data->operation,
- input, data->aux, data->aux2,
- data->output, area, data->level))
+ if (data->klass->process2)
+ success = data->klass->process2 (data->operation,
+ input, data->aux, data->aux2,
+ data->output, area, data->level,
+ data->error);
+ else
+ success = data->klass->process (data->operation,
+ input, data->aux, data->aux2,
+ data->output, area, data->level);
+ if (! success)
data->success = FALSE;
g_object_unref (input);
}
- static gboolean
-gegl_operation_composer3_process (GeglOperation *operation,
- GeglOperationContext *context,
- const gchar *output_prop,
- const GeglRectangle *result,
- gint level)
+static gboolean
+gegl_operation_composer3_process2 (GeglOperation *operation,
+ GeglOperationContext *context,
+ const gchar *output_prop,
+ const GeglRectangle *result,
+ gint level,
+ GError **error)
{
GeglOperationComposer3Class *klass = GEGL_OPERATION_COMPOSER3_GET_CLASS (operation);
GeglBuffer *input;
@@ -201,6 +212,7 @@ gegl_operation_composer3_process (GeglOperation *operation,
data.roi = result;
data.level = level;
data.success = TRUE;
+ data.error = error;
gegl_parallel_distribute_area (
result,
@@ -208,12 +220,15 @@ gegl_operation_composer3_process (GeglOperation *operation,
GEGL_SPLIT_STRATEGY_AUTO,
(GeglParallelDistributeAreaFunc) thread_process,
&data);
-
+
success = data.success;
}
else
{
- success = klass->process (operation, input, aux, aux2, output, result, level);
+ if (klass->process2)
+ success = klass->process2 (operation, input, aux, aux2, output, result, level, error);
+ else
+ success = klass->process (operation, input, aux, aux2, output, result, level);
}
g_clear_object (&input);
diff --git a/gegl/operation/gegl-operation-composer3.h b/gegl/operation/gegl-operation-composer3.h
index c8b6c7bf3..0db2e3d5c 100644
--- a/gegl/operation/gegl-operation-composer3.h
+++ b/gegl/operation/gegl-operation-composer3.h
@@ -41,14 +41,22 @@ struct _GeglOperationComposer3Class
{
GeglOperationClass parent_class;
- gboolean (* process) (GeglOperation *self,
- GeglBuffer *input,
- GeglBuffer *aux,
- GeglBuffer *aux2,
- GeglBuffer *output,
- const GeglRectangle *result,
- gint level);
- gpointer pad[4];
+ gboolean (* process) (GeglOperation *self,
+ GeglBuffer *input,
+ GeglBuffer *aux,
+ GeglBuffer *aux2,
+ GeglBuffer *output,
+ const GeglRectangle *result,
+ gint level);
+ gboolean (* process2) (GeglOperation *self,
+ GeglBuffer *input,
+ GeglBuffer *aux,
+ GeglBuffer *aux2,
+ GeglBuffer *output,
+ const GeglRectangle *result,
+ gint level,
+ GError **error);
+ gpointer pad[4];
};
GType gegl_operation_composer3_get_type (void) G_GNUC_CONST;
diff --git a/gegl/operation/gegl-operation-filter.c b/gegl/operation/gegl-operation-filter.c
index 5a43f9e1b..a69aace9e 100644
--- a/gegl/operation/gegl-operation-filter.c
+++ b/gegl/operation/gegl-operation-filter.c
@@ -26,12 +26,13 @@
#include "gegl-operation-context.h"
#include "gegl-config.h"
-static gboolean gegl_operation_filter_process
+static gboolean gegl_operation_filter_process2
(GeglOperation *operation,
GeglOperationContext *context,
const gchar *output_prop,
const GeglRectangle *result,
- gint level);
+ gint level,
+ GError **error);
static void attach (GeglOperation *operation);
static GeglNode *detect (GeglOperation *operation,
@@ -61,7 +62,7 @@ gegl_operation_filter_class_init (GeglOperationFilterClass * klass)
{
GeglOperationClass *operation_class = GEGL_OPERATION_CLASS (klass);
- operation_class->process = gegl_operation_filter_process;
+ operation_class->process2 = gegl_operation_filter_process2;
operation_class->threaded = TRUE;
operation_class->attach = attach;
operation_class->detect = detect;
@@ -125,6 +126,7 @@ typedef struct ThreadData
const GeglRectangle *roi;
gint level;
gboolean success;
+ GError **error;
} ThreadData;
static void
@@ -132,6 +134,7 @@ thread_process (const GeglRectangle *area,
ThreadData *data)
{
GeglBuffer *input;
+ gboolean success = TRUE;
if (area->x == data->roi->x && area->y == data->roi->y)
{
@@ -143,19 +146,25 @@ thread_process (const GeglRectangle *area,
"input", area);
}
- if (!data->klass->process (data->operation,
- input, data->output, area, data->level))
+ if (data->klass->process2)
+ success = data->klass->process2 (data->operation,
+ input, data->output, area, data->level, data->error);
+ else
+ success = data->klass->process (data->operation,
+ input, data->output, area, data->level);
+ if (! success)
data->success = FALSE;
g_object_unref (input);
}
static gboolean
-gegl_operation_filter_process (GeglOperation *operation,
- GeglOperationContext *context,
- const gchar *output_prop,
- const GeglRectangle *result,
- gint level)
+gegl_operation_filter_process2 (GeglOperation *operation,
+ GeglOperationContext *context,
+ const gchar *output_prop,
+ const GeglRectangle *result,
+ gint level,
+ GError **error)
{
GeglOperationFilterClass *klass;
GeglBuffer *input;
@@ -164,7 +173,7 @@ gegl_operation_filter_process (GeglOperation *operation,
klass = GEGL_OPERATION_FILTER_GET_CLASS (operation);
- g_assert (klass->process);
+ g_assert (klass->process || klass->process2);
if (strcmp (output_prop, "output"))
{
@@ -197,6 +206,7 @@ gegl_operation_filter_process (GeglOperation *operation,
data.roi = result;
data.level = level;
data.success = TRUE;
+ data.error = error;
gegl_parallel_distribute_area (
result,
@@ -209,7 +219,10 @@ gegl_operation_filter_process (GeglOperation *operation,
}
else
{
- success = klass->process (operation, input, output, result, level);
+ if (klass->process2)
+ success = klass->process2 (operation, input, output, result, level, error);
+ else
+ success = klass->process (operation, input, output, result, level);
}
g_clear_object (&input);
diff --git a/gegl/operation/gegl-operation-filter.h b/gegl/operation/gegl-operation-filter.h
index 20ce3e293..3ac19e5c7 100644
--- a/gegl/operation/gegl-operation-filter.h
+++ b/gegl/operation/gegl-operation-filter.h
@@ -50,6 +50,12 @@ struct _GeglOperationFilterClass
GeglBuffer *output,
const GeglRectangle *roi,
gint level);
+ gboolean (* process2) (GeglOperation *self,
+ GeglBuffer *input,
+ GeglBuffer *output,
+ const GeglRectangle *roi,
+ gint level,
+ GError **error);
/* How to split the area for multithreaded processing. Should be irrelevant
* for most ops.
diff --git a/gegl/operation/gegl-operation-point-composer.c b/gegl/operation/gegl-operation-point-composer.c
index e13f8b8ed..5b469ed6f 100644
--- a/gegl/operation/gegl-operation-point-composer.c
+++ b/gegl/operation/gegl-operation-point-composer.c
@@ -47,6 +47,7 @@ typedef struct ThreadData
GeglBuffer *output;
gint level;
gboolean success;
+ GError **error;
const Babl *input_format;
const Babl *aux_format;
@@ -78,19 +79,27 @@ thread_process (const GeglRectangle *area,
while (gegl_buffer_iterator_next (i))
{
- data->success =
- data->klass->process (data->operation, data->input?i->items[read].data:NULL,
- data->aux?i->items[aux].data:NULL,
- i->items[0].data, i->length, &(i->items[0].roi), data->level);
+ if (data->klass->process2)
+ data->success =
+ data->klass->process2 (data->operation, data->input?i->items[read].data:NULL,
+ data->aux?i->items[aux].data:NULL,
+ i->items[0].data, i->length, &(i->items[0].roi),
+ data->level, data->error);
+ else
+ data->success =
+ data->klass->process (data->operation, data->input?i->items[read].data:NULL,
+ data->aux?i->items[aux].data:NULL,
+ i->items[0].data, i->length, &(i->items[0].roi), data->level);
}
}
static gboolean
-gegl_operation_composer_process (GeglOperation *operation,
- GeglOperationContext *context,
- const gchar *output_prop,
- const GeglRectangle *result,
- gint level)
+gegl_operation_composer_process2 (GeglOperation *operation,
+ GeglOperationContext *context,
+ const gchar *output_prop,
+ const GeglRectangle *result,
+ gint level,
+ GError **error)
{
GeglOperationComposerClass *klass = GEGL_OPERATION_COMPOSER_GET_CLASS (operation);
GeglBuffer *input;
@@ -110,7 +119,18 @@ gegl_operation_composer_process (GeglOperation *operation,
if (strcmp (output_prop, "output"))
{
- g_warning ("requested processing of %s pad on a composer", output_prop);
+ if (error)
+ {
+ gchar *msg;
+
+ msg = g_strdup_printf ("requested processing of %s pad on a composer",
+ output_prop);
+ *error = g_error_new (g_quark_from_static_string ("gegl"),
+ 0, "Operation %s failed: %s",
+ gegl_operation_get_name (operation),
+ msg);
+ g_free (msg);
+ }
return FALSE;
}
@@ -134,27 +154,41 @@ gegl_operation_composer_process (GeglOperation *operation,
if (input != NULL ||
aux != NULL)
{
- success = klass->process (operation, input, aux, output, result, level);
+ if (klass->process2)
+ success = klass->process2 (operation, input, aux, output, result, level, error);
+ else
+ success = klass->process (operation, input, aux, output, result, level);
g_clear_object (&input);
g_clear_object (&aux);
}
else
{
- g_warning ("%s received NULL input, aux, and aux2",
- gegl_node_get_operation (operation->node));
+ if (error)
+ {
+ gchar *msg;
+
+ msg = g_strdup_printf ("%s received NULL input, aux, and aux2",
+ gegl_node_get_operation (operation->node));
+ *error = g_error_new (g_quark_from_static_string ("gegl"),
+ 0, "Operation %s failed: %s",
+ gegl_operation_get_name (operation),
+ msg);
+ g_free (msg);
+ }
}
return success;
}
-static gboolean gegl_operation_point_composer_process
+static gboolean gegl_operation_point_composer_process2
(GeglOperation *operation,
GeglBuffer *input,
GeglBuffer *aux,
GeglBuffer *output,
const GeglRectangle *result,
- gint level);
+ gint level,
+ GError **error);
G_DEFINE_TYPE (GeglOperationPointComposer, gegl_operation_point_composer, GEGL_TYPE_OPERATION_COMPOSER)
@@ -269,8 +303,8 @@ gegl_operation_point_composer_class_init (GeglOperationPointComposerClass *klass
GeglOperationClass *operation_class = GEGL_OPERATION_CLASS (klass);
GeglOperationComposerClass *composer_class = GEGL_OPERATION_COMPOSER_CLASS (klass);
- composer_class->process = gegl_operation_point_composer_process;
- operation_class->process = gegl_operation_composer_process;
+ composer_class->process2 = gegl_operation_point_composer_process2;
+ operation_class->process2 = gegl_operation_composer_process2;
operation_class->prepare = prepare;
operation_class->want_in_place = TRUE;
operation_class->threaded = TRUE;
@@ -283,12 +317,13 @@ gegl_operation_point_composer_init (GeglOperationPointComposer *self)
}
static gboolean
-gegl_operation_point_composer_process (GeglOperation *operation,
- GeglBuffer *input,
- GeglBuffer *aux,
- GeglBuffer *output,
- const GeglRectangle *result,
- gint level)
+gegl_operation_point_composer_process2 (GeglOperation *operation,
+ GeglBuffer *input,
+ GeglBuffer *aux,
+ GeglBuffer *output,
+ const GeglRectangle *result,
+ gint level,
+ GError **error)
{
GeglOperationClass *operation_class = GEGL_OPERATION_GET_CLASS (operation);
GeglOperationPointComposerClass *point_composer_class = GEGL_OPERATION_POINT_COMPOSER_GET_CLASS
(operation);
@@ -318,6 +353,7 @@ gegl_operation_point_composer_process (GeglOperation *operation,
data.input_format = in_format;
data.aux_format = aux_format;
data.output_format = out_format;
+ data.error = error;
if (gegl_cl_is_accelerated ())
{
@@ -348,9 +384,15 @@ gegl_operation_point_composer_process (GeglOperation *operation,
while (gegl_buffer_iterator_next (i))
{
- point_composer_class->process (operation, input?i->items[read].data:NULL,
- aux?i->items[foo].data:NULL,
- i->items[0].data, i->length, &(i->items[0].roi),
level);
+ if (point_composer_class->process2)
+ point_composer_class->process2 (operation, input?i->items[read].data:NULL,
+ aux?i->items[foo].data:NULL,
+ i->items[0].data, i->length, &(i->items[0].roi),
+ level, error);
+ else
+ point_composer_class->process (operation, input?i->items[read].data:NULL,
+ aux?i->items[foo].data:NULL,
+ i->items[0].data, i->length, &(i->items[0].roi), level);
}
return TRUE;
}
diff --git a/gegl/operation/gegl-operation-point-composer.h b/gegl/operation/gegl-operation-point-composer.h
index 1305ec36e..f40cb0ef9 100644
--- a/gegl/operation/gegl-operation-point-composer.h
+++ b/gegl/operation/gegl-operation-point-composer.h
@@ -50,13 +50,21 @@ struct _GeglOperationPointComposerClass
{
GeglOperationComposerClass parent_class;
- gboolean (* process) (GeglOperation *self, /* for parameters */
- void *in,
- void *aux,
- void *out,
- glong samples, /* number of samples */
- const GeglRectangle *roi, /* rectangular region in output buffer */
- gint level);
+ gboolean (* process) (GeglOperation *self, /* for parameters */
+ void *in,
+ void *aux,
+ void *out,
+ glong samples, /* number of samples */
+ const GeglRectangle *roi, /* rectangular region in output buffer */
+ gint level);
+ gboolean (* process2) (GeglOperation *self,
+ void *in,
+ void *aux,
+ void *out,
+ glong samples,
+ const GeglRectangle *roi,
+ gint level,
+ GError **error);
gboolean (* cl_process) (GeglOperation *self,
cl_mem in_tex,
diff --git a/gegl/operation/gegl-operation-point-filter.c b/gegl/operation/gegl-operation-point-filter.c
index 3197e5c83..7f0e792ea 100644
--- a/gegl/operation/gegl-operation-point-filter.c
+++ b/gegl/operation/gegl-operation-point-filter.c
@@ -45,6 +45,7 @@ typedef struct ThreadData
GeglBuffer *output;
gint level;
gboolean success;
+ GError **error;
const Babl *input_format;
const Babl *output_format;
} ThreadData;
@@ -67,23 +68,30 @@ thread_process (const GeglRectangle *area,
while (gegl_buffer_iterator_next (i))
{
- data->success =
- data->klass->process (data->operation, data->input?i->items[read].data:NULL,
- i->items[0].data, i->length, &(i->items[0].roi), data->level);
+ if (data->klass->process2)
+ data->success =
+ data->klass->process2 (data->operation, data->input?i->items[read].data:NULL,
+ i->items[0].data, i->length, &(i->items[0].roi),
+ data->level, data->error);
+ else
+ data->success =
+ data->klass->process (data->operation, data->input?i->items[read].data:NULL,
+ i->items[0].data, i->length, &(i->items[0].roi), data->level);
}
}
static gboolean
-gegl_operation_filter_process (GeglOperation *operation,
- GeglOperationContext *context,
- const gchar *output_prop,
- const GeglRectangle *result,
- gint level)
+gegl_operation_filter_process2 (GeglOperation *operation,
+ GeglOperationContext *context,
+ const gchar *output_prop,
+ const GeglRectangle *result,
+ gint level,
+ GError **error)
{
- GeglOperationFilterClass *klass = GEGL_OPERATION_FILTER_GET_CLASS (operation);
- GeglBuffer *input;
- GeglBuffer *output;
- gboolean success = FALSE;
+ GeglOperationFilterClass *klass = GEGL_OPERATION_FILTER_GET_CLASS (operation);
+ GeglBuffer *input;
+ GeglBuffer *output;
+ gboolean success = FALSE;
GeglRectangle scaled_result = *result;
if (level)
@@ -97,7 +105,18 @@ gegl_operation_filter_process (GeglOperation *operation,
if (strcmp (output_prop, "output"))
{
- g_warning ("requested processing of %s pad on a filter", output_prop);
+ if (error)
+ {
+ gchar *msg;
+
+ msg = g_strdup_printf ("requested processing of %s pad on a filter",
+ output_prop);
+ *error = g_error_new (g_quark_from_static_string ("gegl"),
+ 0, "Operation %s failed: %s",
+ gegl_operation_get_name (operation),
+ msg);
+ g_free (msg);
+ }
return FALSE;
}
@@ -115,24 +134,38 @@ gegl_operation_filter_process (GeglOperation *operation,
if (input != NULL)
{
- success = klass->process (operation, input, output, result, level);
+ if (klass->process2)
+ success = klass->process2 (operation, input, output, result, level, error);
+ else
+ success = klass->process (operation, input, output, result, level);
g_clear_object (&input);
}
else
{
- g_warning ("%s received NULL input",
- gegl_node_get_operation (operation->node));
+ if (error)
+ {
+ gchar *msg;
+
+ msg = g_strdup_printf ("%s received NULL input",
+ gegl_node_get_operation (operation->node));
+ *error = g_error_new (g_quark_from_static_string ("gegl"),
+ 0, "Operation %s failed: %s",
+ gegl_operation_get_name (operation),
+ msg);
+ g_free (msg);
+ }
}
return success;
}
-static gboolean gegl_operation_point_filter_process
+static gboolean gegl_operation_point_filter_process2
(GeglOperation *operation,
GeglBuffer *input,
GeglBuffer *output,
const GeglRectangle *result,
- gint level);
+ gint level,
+ GError **error);
G_DEFINE_TYPE (GeglOperationPointFilter, gegl_operation_point_filter, GEGL_TYPE_OPERATION_FILTER)
@@ -233,11 +266,11 @@ error:
static void
gegl_operation_point_filter_class_init (GeglOperationPointFilterClass *klass)
{
- GeglOperationClass *operation_class = GEGL_OPERATION_CLASS (klass);
+ GeglOperationClass *operation_class = GEGL_OPERATION_CLASS (klass);
GeglOperationFilterClass *filter_class = GEGL_OPERATION_FILTER_CLASS (klass);
- filter_class->process = gegl_operation_point_filter_process;
- operation_class->process = gegl_operation_filter_process;
+ filter_class->process2 = gegl_operation_point_filter_process2;
+ operation_class->process2 = gegl_operation_filter_process2;
operation_class->prepare = prepare;
operation_class->want_in_place = TRUE;
operation_class->threaded = TRUE;
@@ -250,11 +283,12 @@ gegl_operation_point_filter_init (GeglOperationPointFilter *self)
}
static gboolean
-gegl_operation_point_filter_process (GeglOperation *operation,
- GeglBuffer *input,
- GeglBuffer *output,
- const GeglRectangle *result,
- gint level)
+gegl_operation_point_filter_process2 (GeglOperation *operation,
+ GeglBuffer *input,
+ GeglBuffer *output,
+ const GeglRectangle *result,
+ gint level,
+ GError **error)
{
GeglOperationClass *operation_class = GEGL_OPERATION_GET_CLASS (operation);
GeglOperationPointFilterClass *point_filter_class = GEGL_OPERATION_POINT_FILTER_GET_CLASS (operation);
@@ -281,6 +315,7 @@ gegl_operation_point_filter_process (GeglOperation *operation,
data.level = level;
data.input_format = in_format;
data.output_format = out_format;
+ data.error = error;
if (gegl_cl_is_accelerated () && input)
gegl_buffer_flush_ext (input, result);
@@ -306,8 +341,13 @@ gegl_operation_point_filter_process (GeglOperation *operation,
while (gegl_buffer_iterator_next (i))
{
- point_filter_class->process (operation, input?i->items[read].data:NULL,
- i->items[0].data, i->length, &(i->items[0].roi), level);
+ if (point_filter_class->process2)
+ point_filter_class->process2 (operation, input?i->items[read].data:NULL,
+ i->items[0].data, i->length, &(i->items[0].roi),
+ level, error);
+ else
+ point_filter_class->process (operation, input?i->items[read].data:NULL,
+ i->items[0].data, i->length, &(i->items[0].roi), level);
}
return TRUE;
}
diff --git a/gegl/operation/gegl-operation-point-filter.h b/gegl/operation/gegl-operation-point-filter.h
index 64fe4d852..2437b2f97 100644
--- a/gegl/operation/gegl-operation-point-filter.h
+++ b/gegl/operation/gegl-operation-point-filter.h
@@ -50,15 +50,22 @@ struct _GeglOperationPointFilterClass
{
GeglOperationFilterClass parent_class;
- gboolean (* process) (GeglOperation *self, /* for parameters */
- void *in_buf, /* input buffer */
- void *out_buf, /* output buffer */
- glong samples, /* number of samples */
- const GeglRectangle *roi, /* rectangle out_buf spans
- in in buffer, see the
- checkerboard op for
- semantics */
- gint level);
+ gboolean (* process) (GeglOperation *self, /* for parameters */
+ void *in_buf, /* input buffer */
+ void *out_buf, /* output buffer */
+ glong samples, /* number of samples */
+ const GeglRectangle *roi, /* rectangle out_buf spans
+ in in buffer, see the
+ checkerboard op for
+ semantics */
+ gint level);
+ gboolean (* process2) (GeglOperation *self,
+ void *in_buf,
+ void *out_buf,
+ glong samples,
+ const GeglRectangle *roi,
+ gint level,
+ GError **error);
gboolean (* cl_process) (GeglOperation *self,
cl_mem in_tex,
cl_mem out_tex,
diff --git a/gegl/operation/gegl-operation-point-render.c b/gegl/operation/gegl-operation-point-render.c
index 5060d022f..cc63827f5 100644
--- a/gegl/operation/gegl-operation-point-render.c
+++ b/gegl/operation/gegl-operation-point-render.c
@@ -26,11 +26,12 @@
#include "gegl-operation-context.h"
#include "gegl-types-internal.h"
-static gboolean gegl_operation_point_render_process
+static gboolean gegl_operation_point_render_process2
(GeglOperation *operation,
GeglBuffer *output,
const GeglRectangle *result,
- gint level);
+ gint level,
+ GError **error);
G_DEFINE_TYPE (GeglOperationPointRender, gegl_operation_point_render, GEGL_TYPE_OPERATION_SOURCE)
@@ -54,7 +55,7 @@ gegl_operation_point_render_class_init (GeglOperationPointRenderClass *klass)
GeglOperationSourceClass *source_class = GEGL_OPERATION_SOURCE_CLASS (klass);
GeglOperationClass *operation_class = GEGL_OPERATION_CLASS (klass);
- source_class->process = gegl_operation_point_render_process;
+ source_class->process2 = gegl_operation_point_render_process2;
operation_class->prepare = prepare;
operation_class->detect = detect;
@@ -68,10 +69,11 @@ gegl_operation_point_render_init (GeglOperationPointRender *self)
static gboolean
-gegl_operation_point_render_process (GeglOperation *operation,
- GeglBuffer *output,
- const GeglRectangle *result,
- gint level)
+gegl_operation_point_render_process2 (GeglOperation *operation,
+ GeglBuffer *output,
+ const GeglRectangle *result,
+ gint level,
+ GError **error)
{
const Babl *out_format;
GeglOperationPointRenderClass *point_render_class;
@@ -102,7 +104,15 @@ gegl_operation_point_render_process (GeglOperation *operation,
GEGL_ACCESS_WRITE, GEGL_ABYSS_NONE, 2);
while (gegl_buffer_iterator_next (i))
- point_render_class->process (operation, i->items[0].data, i->length, &i->items[0].roi, level);
+ {
+ if (point_render_class->process2)
+ point_render_class->process2 (operation, i->items[0].data,
+ i->length, &i->items[0].roi,
+ level, error);
+ else
+ point_render_class->process (operation, i->items[0].data,
+ i->length, &i->items[0].roi, level);
+ }
}
return TRUE;
diff --git a/gegl/operation/gegl-operation-point-render.h b/gegl/operation/gegl-operation-point-render.h
index 26f68d5cc..199ca3ebb 100644
--- a/gegl/operation/gegl-operation-point-render.h
+++ b/gegl/operation/gegl-operation-point-render.h
@@ -47,12 +47,18 @@ struct _GeglOperationPointRenderClass
{
GeglOperationSourceClass parent_class;
- gboolean (* process) (GeglOperation *self, /* for parameters */
- void *out_buf, /* output buffer */
- glong samples, /* number of samples */
- const GeglRectangle *roi, /* can be used if position is of importance*/
- gint level);
- gpointer pad[4];
+ gboolean (* process) (GeglOperation *self, /* for parameters */
+ void *out_buf, /* output buffer */
+ glong samples, /* number of samples */
+ const GeglRectangle *roi, /* can be used if position is of importance*/
+ gint level);
+ gboolean (* process2) (GeglOperation *self, /* for parameters */
+ void *out_buf, /* output buffer */
+ glong samples, /* number of samples */
+ const GeglRectangle *roi, /* can be used if position is of importance*/
+ gint level,
+ GError **error);
+ gpointer pad[4];
};
GType gegl_operation_point_render_get_type (void) G_GNUC_CONST;
diff --git a/gegl/operation/gegl-operation-sink.c b/gegl/operation/gegl-operation-sink.c
index 823551e83..d161e658c 100644
--- a/gegl/operation/gegl-operation-sink.c
+++ b/gegl/operation/gegl-operation-sink.c
@@ -26,11 +26,12 @@
#include "gegl-operation-sink.h"
#include "gegl-operation-context.h"
-static gboolean gegl_operation_sink_process (GeglOperation *operation,
+static gboolean gegl_operation_sink_process2 (GeglOperation *operation,
GeglOperationContext *context,
const gchar *output_prop,
const GeglRectangle *result,
- gint level);
+ gint level,
+ GError **error);
static void gegl_operation_sink_attach (GeglOperation *operation);
static GeglRectangle gegl_operation_sink_get_bounding_box (GeglOperation *self);
static GeglRectangle gegl_operation_sink_get_required_for_output (GeglOperation *operation,
@@ -48,7 +49,7 @@ gegl_operation_sink_class_init (GeglOperationSinkClass * klass)
klass->needs_full = FALSE;
- operation_class->process = gegl_operation_sink_process;
+ operation_class->process2 = gegl_operation_sink_process2;
operation_class->attach = gegl_operation_sink_attach;
operation_class->get_bounding_box = gegl_operation_sink_get_bounding_box;
operation_class->get_required_for_output = gegl_operation_sink_get_required_for_output;
@@ -76,26 +77,36 @@ gegl_operation_sink_attach (GeglOperation *self)
}
static gboolean
-gegl_operation_sink_process (GeglOperation *operation,
- GeglOperationContext *context,
- const gchar *output_prop,
- const GeglRectangle *result,
- gint level)
+gegl_operation_sink_process2 (GeglOperation *operation,
+ GeglOperationContext *context,
+ const gchar *output_prop,
+ const GeglRectangle *result,
+ gint level,
+ GError **error)
{
GeglOperationSinkClass *klass;
GeglBuffer *input;
gboolean success = FALSE;
- klass = GEGL_OPERATION_SINK_GET_CLASS (operation);
+ klass = GEGL_OPERATION_SINK_GET_CLASS (operation);
- g_assert (klass->process);
+ g_assert (klass->process || klass->process2);
input = (GeglBuffer*) gegl_operation_context_dup_object (context, "input");
if (input)
{
- success = klass->process (operation, input, result, level);
+ if (klass->process2)
+ success = klass->process2 (operation, input, result, level, error);
+ else
+ success = klass->process (operation, input, result, level);
+
g_object_unref (input);
}
+ else if (error)
+ {
+ *error = g_error_new (g_quark_from_static_string ("gegl"),
+ 0, "Sink operation has no input");
+ }
return success;
}
diff --git a/gegl/operation/gegl-operation-sink.h b/gegl/operation/gegl-operation-sink.h
index 6859a35b6..586e87695 100644
--- a/gegl/operation/gegl-operation-sink.h
+++ b/gegl/operation/gegl-operation-sink.h
@@ -49,13 +49,18 @@ struct _GeglOperationSinkClass
/* Whether or not the sink operation needs full input data in one go
* in order to be able to do its processing
*/
- gboolean needs_full;
+ gboolean needs_full;
- gboolean (* process) (GeglOperation *self,
- GeglBuffer *input,
- const GeglRectangle *roi,
- gint level);
- gpointer pad[4];
+ gboolean (* process) (GeglOperation *self,
+ GeglBuffer *input,
+ const GeglRectangle *roi,
+ gint level);
+ gboolean (* process2) (GeglOperation *self,
+ GeglBuffer *input,
+ const GeglRectangle *roi,
+ gint level,
+ GError **error);
+ gpointer pad[4];
};
GType gegl_operation_sink_get_type (void) G_GNUC_CONST;
diff --git a/gegl/operation/gegl-operation-source.c b/gegl/operation/gegl-operation-source.c
index 35fc471a9..053405969 100644
--- a/gegl/operation/gegl-operation-source.c
+++ b/gegl/operation/gegl-operation-source.c
@@ -26,12 +26,13 @@
#include "gegl-operation-context.h"
#include "gegl-config.h"
-static gboolean gegl_operation_source_process
+static gboolean gegl_operation_source_process2
(GeglOperation *operation,
GeglOperationContext *context,
const gchar *output_prop,
const GeglRectangle *result,
- gint level);
+ gint level,
+ GError **error);
static void attach (GeglOperation *operation);
@@ -49,8 +50,8 @@ gegl_operation_source_class_init (GeglOperationSourceClass * klass)
{
GeglOperationClass *operation_class = GEGL_OPERATION_CLASS (klass);
- operation_class->process = gegl_operation_source_process;
- operation_class->attach = attach;
+ operation_class->process2 = gegl_operation_source_process2;
+ operation_class->attach = attach;
operation_class->get_bounding_box = get_bounding_box;
operation_class->get_required_for_output = get_required_for_output;
@@ -84,23 +85,32 @@ typedef struct ThreadData
GeglBuffer *output;
gint level;
gboolean success;
+ GError **error;
} ThreadData;
static void
thread_process (const GeglRectangle *area,
ThreadData *data)
{
- if (!data->klass->process (data->operation,
- data->output, area, data->level))
+ gboolean success = TRUE;
+
+ if (data->klass->process2)
+ success = data->klass->process2 (data->operation,
+ data->output, area, data->level, data->error);
+ else
+ success = data->klass->process (data->operation,
+ data->output, area, data->level);
+ if (! success)
data->success = FALSE;
}
static gboolean
-gegl_operation_source_process (GeglOperation *operation,
- GeglOperationContext *context,
- const gchar *output_prop,
- const GeglRectangle *result,
- gint level)
+gegl_operation_source_process2 (GeglOperation *operation,
+ GeglOperationContext *context,
+ const gchar *output_prop,
+ const GeglRectangle *result,
+ gint level,
+ GError **error)
{
GeglOperationSourceClass *klass = GEGL_OPERATION_SOURCE_GET_CLASS (operation);
GeglBuffer *output;
@@ -112,7 +122,7 @@ gegl_operation_source_process (GeglOperation *operation,
return FALSE;
}
- g_assert (klass->process);
+ g_assert (klass->process || klass->process2);
output = gegl_operation_context_get_target (context, "output");
if (gegl_operation_use_threading (operation, result))
@@ -124,6 +134,7 @@ gegl_operation_source_process (GeglOperation *operation,
data.output = output;
data.level = level;
data.success = TRUE;
+ data.error = error;
gegl_parallel_distribute_area (
result,
@@ -136,7 +147,10 @@ gegl_operation_source_process (GeglOperation *operation,
}
else
{
- success = klass->process (operation, output, result, level);
+ if (klass->process2)
+ success = klass->process2 (operation, output, result, level, error);
+ else
+ success = klass->process (operation, output, result, level);
}
return success;
diff --git a/gegl/operation/gegl-operation-source.h b/gegl/operation/gegl-operation-source.h
index fc19c8245..77cfbfb85 100644
--- a/gegl/operation/gegl-operation-source.h
+++ b/gegl/operation/gegl-operation-source.h
@@ -44,13 +44,18 @@ struct _GeglOperationSource
typedef struct _GeglOperationSourceClass GeglOperationSourceClass;
struct _GeglOperationSourceClass
{
- GeglOperationClass parent_class;
+ GeglOperationClass parent_class;
- gboolean (* process) (GeglOperation *self,
- GeglBuffer *output,
- const GeglRectangle *roi,
- gint level);
- gpointer pad[4];
+ gboolean (* process) (GeglOperation *self,
+ GeglBuffer *output,
+ const GeglRectangle *roi,
+ gint level);
+ gboolean (* process2) (GeglOperation *self,
+ GeglBuffer *output,
+ const GeglRectangle *roi,
+ gint level,
+ GError **error);
+ gpointer pad[4];
};
GType gegl_operation_source_get_type (void) G_GNUC_CONST;
diff --git a/gegl/operation/gegl-operation-temporal.c b/gegl/operation/gegl-operation-temporal.c
index 7e0a3db62..67d920a63 100644
--- a/gegl/operation/gegl-operation-temporal.c
+++ b/gegl/operation/gegl-operation-temporal.c
@@ -79,11 +79,12 @@ gegl_operation_temporal_get_frame (GeglOperation *op,
return buffer;
}
-static gboolean gegl_operation_temporal_process (GeglOperation *self,
- GeglBuffer *input,
- GeglBuffer *output,
- const GeglRectangle *result,
- gint level)
+static gboolean gegl_operation_temporal_process2 (GeglOperation *self,
+ GeglBuffer *input,
+ GeglBuffer *output,
+ const GeglRectangle *result,
+ gint level,
+ GError **error)
{
GeglOperationTemporal *temporal = GEGL_OPERATION_TEMPORAL (self);
GeglOperationTemporalPrivate *priv = temporal->priv;
@@ -105,7 +106,9 @@ static gboolean gegl_operation_temporal_process (GeglOperation *self,
priv->next_to_write=0;
}
- if (temporal_class->process)
+ if (temporal_class->process2)
+ return temporal_class->process2 (self, input, output, result, level, error);
+ else
return temporal_class->process (self, input, output, result, level);
return FALSE;
}
@@ -125,7 +128,7 @@ gegl_operation_temporal_class_init (GeglOperationTemporalClass *klass)
GeglOperationFilterClass *operation_filter_class = GEGL_OPERATION_FILTER_CLASS (klass);
operation_class->prepare = gegl_operation_temporal_prepare;
- operation_filter_class->process = gegl_operation_temporal_process;
+ operation_filter_class->process2 = gegl_operation_temporal_process2;
}
static void
diff --git a/gegl/operation/gegl-operation-temporal.h b/gegl/operation/gegl-operation-temporal.h
index 0a369fc4c..4e8863ae6 100644
--- a/gegl/operation/gegl-operation-temporal.h
+++ b/gegl/operation/gegl-operation-temporal.h
@@ -48,12 +48,18 @@ typedef struct _GeglOperationTemporalClass GeglOperationTemporalClass;
struct _GeglOperationTemporalClass
{
GeglOperationFilterClass parent_class;
- gboolean (* process) (GeglOperation *self,
- GeglBuffer *input,
- GeglBuffer *output,
- const GeglRectangle *roi,
- gint level);
- gpointer pad[4];
+ gboolean (* process) (GeglOperation *self,
+ GeglBuffer *input,
+ GeglBuffer *output,
+ const GeglRectangle *roi,
+ gint level);
+ gboolean (* process2) (GeglOperation *self,
+ GeglBuffer *input,
+ GeglBuffer *output,
+ const GeglRectangle *roi,
+ gint level,
+ GError **error);
+ gpointer pad[4];
};
GType gegl_operation_temporal_get_type (void) G_GNUC_CONST;
diff --git a/gegl/operation/gegl-operation.c b/gegl/operation/gegl-operation.c
index 0b31c146f..08356c979 100644
--- a/gegl/operation/gegl-operation.c
+++ b/gegl/operation/gegl-operation.c
@@ -20,6 +20,7 @@
#include "config.h"
#include <glib-object.h>
+#include <glib/gi18n-lib.h>
#include <string.h>
#include "gegl.h"
@@ -146,20 +147,31 @@ gegl_operation_process (GeglOperation *operation,
const GeglRectangle *result,
gint level)
{
- GeglOperationClass *klass;
+ GeglOperationClass *klass;
+ gboolean success = TRUE;
g_return_val_if_fail (GEGL_IS_OPERATION (operation), FALSE);
klass = GEGL_OPERATION_GET_CLASS (operation);
+ operation->node->success = TRUE;
+ g_clear_error (&operation->node->error);
+
if (!strcmp (output_pad, "output") &&
(result->width == 0 || result->height == 0))
{
GeglBuffer *output = gegl_buffer_new (NULL, NULL);
- g_warning ("%s Eeek: processing 0px rectangle", G_STRLOC);
+
+ operation->node->error = g_error_new (g_quark_from_static_string ("gegl"),
+ 0, _("Operation %s failed: %s"),
+ gegl_operation_get_name (operation),
+ _("processing 0px rectangle."));
+ operation->node->success = FALSE;
+
/* when this case is hit.. we've done something bad.. */
gegl_operation_context_take_object (context, "output", G_OBJECT (output));
- return TRUE;
+
+ return FALSE;
}
if (operation->node->passthrough)
@@ -169,9 +181,22 @@ gegl_operation_process (GeglOperation *operation,
return TRUE;
}
- g_return_val_if_fail (klass->process, FALSE);
+ g_return_val_if_fail (klass->process || klass->process2, FALSE);
+
+ if (klass->process2)
+ success = klass->process2 (operation, context, output_pad, result, level,
+ &operation->node->error);
+ else
+ success = klass->process (operation, context, output_pad, result, level);
+
+ operation->node->success = success;
+ if (! success && operation->node->error == NULL)
+ operation->node->error = g_error_new (g_quark_from_static_string ("gegl"),
+ 0, _("Operation %s failed: %s"),
+ gegl_operation_get_name (operation),
+ _("unknown error."));
- return klass->process (operation, context, output_pad, result, level);
+ return success;
}
/* Calls an extending class' get_bound_box method if defined otherwise
diff --git a/gegl/operation/gegl-operation.h b/gegl/operation/gegl-operation.h
index fa100034c..11c031240 100644
--- a/gegl/operation/gegl-operation.h
+++ b/gegl/operation/gegl-operation.h
@@ -133,6 +133,8 @@ struct _GeglOperationClass
/* Compute the rectangular region output roi for the specified output_pad.
* For operations that are sinks (have no output pads), roi is the rectangle
* to consume and the output_pad argument is to be ignored.
+ * If the processing may fail and return FALSE, you should implement
+ * process2() instead.
*/
gboolean (*process) (GeglOperation *operation,
GeglOperationContext *context,
@@ -140,6 +142,17 @@ struct _GeglOperationClass
const GeglRectangle *roi,
gint level);
+ /* Same as process() but allows to report an error. Operations should
+ * implement process2() rather than process() unless the operation always
+ * succeed. If both virtual methods are implemented, process() is ignored.
+ */
+ gboolean (*process2) (GeglOperation *operation,
+ GeglOperationContext *context,
+ const gchar *output_pad,
+ const GeglRectangle *roi,
+ gint level,
+ GError **error);
+
/* The node providing data for a specific location within the operations
* output. The node is responsible for delegating blame to one of it's
* inputs taking into account opacity and similar issues.
diff --git a/gegl/process/gegl-eval-manager.c b/gegl/process/gegl-eval-manager.c
index 6934ced4e..351b9b26e 100644
--- a/gegl/process/gegl-eval-manager.c
+++ b/gegl/process/gegl-eval-manager.c
@@ -113,6 +113,8 @@ gegl_eval_manager_apply (GeglEvalManager *self,
g_return_val_if_fail (GEGL_IS_EVAL_MANAGER (self), NULL);
g_return_val_if_fail (GEGL_IS_NODE (self->node), NULL);
+ g_clear_error (&self->node->error);
+
if (level >= GEGL_CACHE_VALID_MIPMAPS)
level = GEGL_CACHE_VALID_MIPMAPS-1;
@@ -125,7 +127,7 @@ gegl_eval_manager_apply (GeglEvalManager *self,
GEGL_INSTRUMENT_END ("gegl", "prepare-request");
GEGL_INSTRUMENT_START();
- object = gegl_graph_process (self->traversal, level);
+ object = gegl_graph_process (self->traversal, level, &self->node->error);
GEGL_INSTRUMENT_END ("gegl", "process");
return object;
diff --git a/gegl/process/gegl-graph-traversal.c b/gegl/process/gegl-graph-traversal.c
index e095c9c66..b4d964029 100644
--- a/gegl/process/gegl-graph-traversal.c
+++ b/gegl/process/gegl-graph-traversal.c
@@ -396,6 +396,7 @@ gegl_graph_get_shared_empty (GeglGraphTraversal *path)
/**
* gegl_graph_process:
* @path: The traversal path
+ * @error: an optional #GError.
*
* Process the prepared request. This will return the
* resulting buffer from the final node, or NULL if
@@ -404,18 +405,22 @@ gegl_graph_get_shared_empty (GeglGraphTraversal *path)
* If gegl_graph_prepare_request has not been called
* the behavior of this function is undefined.
*
- * Return value: (transfer full): The result of the graph, or NULL if
- * there is no output pad.
+ * Return value: (transfer full): The result of the graph, or #NULL either if
+ * there is no output pad or if an error was encountered. If @error is not
+ * #NULL, it will be set in case of error.
+
*/
GeglBuffer *
-gegl_graph_process (GeglGraphTraversal *path,
- gint level)
+gegl_graph_process (GeglGraphTraversal *path,
+ gint level,
+ GError **error)
{
GList *list_iter = NULL;
GeglBuffer *result = NULL;
GeglOperationContext *context = NULL;
GeglOperationContext *last_context = NULL;
GeglBuffer *operation_result = NULL;
+ gboolean success = TRUE;
for (list_iter = g_queue_peek_head_link (&path->path);
list_iter;
@@ -467,7 +472,16 @@ gegl_graph_process (GeglGraphTraversal *path,
/* note: this hard-coding of "output" makes some more custom
* graph topologies harder than necessary.
*/
- gegl_operation_process (operation, context, "output", &context->need_rect, context->level);
+ if (! gegl_operation_process (operation, context, "output", &context->need_rect,
context->level))
+ {
+ /* Propagate the error to the calling node, because this is
+ * where we will look when checking for errors.
+ */
+ g_propagate_error (error, operation->node->error);
+ operation->node->error = NULL;
+ success = FALSE;
+ break;
+ }
operation_result = GEGL_BUFFER (gegl_operation_context_get_object (context, "output"));
if (operation_result && operation_result == (GeglBuffer *)operation->node->cache)
@@ -507,10 +521,13 @@ gegl_graph_process (GeglGraphTraversal *path,
}
if (last_context)
{
- if (operation_result)
- result = g_object_ref (operation_result);
- else if (gegl_node_has_pad (last_context->operation->node, "output"))
- result = g_object_ref (gegl_graph_get_shared_empty (path));
+ if (success)
+ {
+ if (operation_result)
+ result = g_object_ref (operation_result);
+ else if (gegl_node_has_pad (last_context->operation->node, "output"))
+ result = g_object_ref (gegl_graph_get_shared_empty (path));
+ }
gegl_operation_context_purge (last_context);
}
diff --git a/gegl/process/gegl-graph-traversal.h b/gegl/process/gegl-graph-traversal.h
index 38f3774a0..c7eb658cd 100644
--- a/gegl/process/gegl-graph-traversal.h
+++ b/gegl/process/gegl-graph-traversal.h
@@ -30,7 +30,8 @@ void gegl_graph_prepare_request (GeglGraphTraversal *path,
const GeglRectangle *roi,
gint level);
GeglBuffer *gegl_graph_process (GeglGraphTraversal *path,
- gint level);
+ gint level,
+ GError **error);
GeglRectangle gegl_graph_get_bounding_box (GeglGraphTraversal *path);
diff --git a/gegl/process/gegl-processor.c b/gegl/process/gegl-processor.c
index 15668d758..dcdbe936a 100644
--- a/gegl/process/gegl-processor.c
+++ b/gegl/process/gegl-processor.c
@@ -785,20 +785,20 @@ gegl_processor_work (GeglProcessor *processor,
*progress = 1.0;
}
+ more_work = FALSE;
if (processor->context)
{
/* the actual writing to the destination */
- gegl_operation_process (processor->real_node->operation,
- processor->context,
- "output" /* ignored output_pad */,
- &processor->context->result_rect, processor->context->level);
+ more_work = gegl_operation_process (processor->real_node->operation,
+ processor->context,
+ "output" /* ignored output_pad */,
+ &processor->context->result_rect, processor->context->level);
+ processor->real_node->success = more_work;
gegl_operation_context_destroy (processor->context);
processor->context = NULL;
-
- return TRUE;
}
- return FALSE;
+ return more_work;
}
GeglProcessor *
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]