[gegl] operation, graph: add {GeglOperationClass, GeglNode}::cache-policy
- From: Ell <ell src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gegl] operation, graph: add {GeglOperationClass, GeglNode}::cache-policy
- Date: Thu, 21 Feb 2019 18:06:32 +0000 (UTC)
commit 7f24430cda0d8c3eff311868823d445edc2a4e12
Author: Ell <ell_se yahoo com>
Date: Thu Feb 21 12:35:45 2019 -0500
operation, graph: add {GeglOperationClass,GeglNode}::cache-policy
Caching of operation output is currently controlled by the
GeglOperationClass::no_cache field on a per-operation-class basis,
and by the GeglNode::dont-cache property on a per-node basis.
However, since these fields are boolean, they prevent us from
automating the decision of whether an op should be cached, or,
altenatively, they don't provide sufficient control over this
decision.
Instead, add a ternary GeglCachePolicy enum, which can be one of
AUTO, NEVER, or ALWAYS, and add a GeglOperationClass::cache_policy
field, and a GeglNode::cache-policy property, which use this type.
When the cache-policy property of a node in NEVER or ALWAYS, its
result isn't/is cached, respectively; when it's AUTO, the deicision
depends on the operation: When the cache_policy field of the
operation class is NEVER or ALWAYS, the result isn't/is cached,
respectively; when it's AUTO, the result is cached only if the
operation implements get_cached_region(). Both of these field are
set to AUTO by default -- the idea is that we generally don't want
to implicitly cache results, unless they correspond to a different
region than the ROI.
The existing dont-cache/no_cache fields are deprecated, but are
still used for now: when GeglNode::cache-policy is AUTO and
GeglNode::dont-cache is TRUE, the node isn't cached; when
GeglOperationClass::cache_policy is AUTO and
GeglOperationClass::no_cache is TRUE, the operation isn't cached.
Like GeglNode::dont-cache, GeglNode::cache-policy is inherited by
the node's children.
gegl/gegl-enums.c | 26 +++++++++++++++
gegl/gegl-enums.h | 11 +++++++
gegl/graph/gegl-node-private.h | 8 ++++-
gegl/graph/gegl-node.c | 57 ++++++++++++++++++++++++++++++---
gegl/operation/Makefile.am | 1 +
gegl/operation/gegl-operation-context.c | 3 +-
gegl/operation/gegl-operation-private.h | 30 +++++++++++++++++
gegl/operation/gegl-operation.c | 22 +++++++++++++
gegl/operation/gegl-operation.h | 6 ++--
9 files changed, 154 insertions(+), 10 deletions(-)
---
diff --git a/gegl/gegl-enums.c b/gegl/gegl-enums.c
index 1ecb123ce..44262d6a4 100644
--- a/gegl/gegl-enums.c
+++ b/gegl/gegl-enums.c
@@ -138,3 +138,29 @@ gegl_babl_variant_get_type (void)
return etype;
}
+
+GType
+gegl_cache_policy_get_type (void)
+{
+ static GType etype = 0;
+
+ if (etype == 0)
+ {
+ static GEnumValue values[] = {
+ { GEGL_CACHE_POLICY_AUTO, N_("Auto"), "auto" },
+ { GEGL_CACHE_POLICY_NEVER, N_("Never"), "never" },
+ { GEGL_CACHE_POLICY_ALWAYS, N_("Always"), "always" },
+ { 0, NULL, NULL }
+ };
+ gint i;
+
+ for (i = 0; i < G_N_ELEMENTS (values); i++)
+ if (values[i].value_name)
+ values[i].value_name =
+ dgettext (GETTEXT_PACKAGE, values[i].value_name);
+
+ etype = g_enum_register_static ("GeglCachePolicy", values);
+ }
+
+ return etype;
+}
diff --git a/gegl/gegl-enums.h b/gegl/gegl-enums.h
index 1855872ac..5809fa521 100644
--- a/gegl/gegl-enums.h
+++ b/gegl/gegl-enums.h
@@ -100,6 +100,17 @@ GType gegl_babl_variant_get_type (void) G_GNUC_CONST;
#define GEGL_TYPE_BABL_VARIANT (gegl_babl_variant_get_type ())
+
+typedef enum {
+ GEGL_CACHE_POLICY_AUTO,
+ GEGL_CACHE_POLICY_NEVER,
+ GEGL_CACHE_POLICY_ALWAYS
+} GeglCachePolicy;
+
+GType gegl_cache_policy_get_type (void) G_GNUC_CONST;
+
+#define GEGL_TYPE_CACHE_POLICY (gegl_cache_policy_get_type ())
+
G_END_DECLS
#endif /* __GEGL_ENUMS_H__ */
diff --git a/gegl/graph/gegl-node-private.h b/gegl/graph/gegl-node-private.h
index 5b892940c..21d127dd7 100644
--- a/gegl/graph/gegl-node-private.h
+++ b/gegl/graph/gegl-node-private.h
@@ -77,9 +77,14 @@ struct _GeglNode
*/
GeglVisitable *output_visitable;
- /* Whether result is cached or not, inherited by children */
+ /* Whether result is cached or not, inherited by children
+ * (deprecated for "cache_policy")
+ */
gboolean dont_cache;
+ /* Cache policy for the current node, inherited by children */
+ GeglCachePolicy cache_policy;
+
gboolean use_opencl;
GMutex mutex;
@@ -126,6 +131,7 @@ const gchar * gegl_node_get_debug_name (GeglNode *node);
void gegl_node_insert_before (GeglNode *self,
GeglNode *to_be_inserted);
+gboolean gegl_node_use_cache (GeglNode *node);
GeglCache * gegl_node_get_cache (GeglNode *node);
void gegl_node_invalidated (GeglNode *node,
const GeglRectangle *rect,
diff --git a/gegl/graph/gegl-node.c b/gegl/graph/gegl-node.c
index 31d5318a2..80152605f 100644
--- a/gegl/graph/gegl-node.c
+++ b/gegl/graph/gegl-node.c
@@ -42,6 +42,7 @@
#include "graph/gegl-node-output-visitable.h"
#include "operation/gegl-operation.h"
+#include "operation/gegl-operation-private.h"
#include "operation/gegl-operations.h"
#include "operation/gegl-operation-meta.h"
@@ -54,6 +55,7 @@ enum
PROP_OPERATION,
PROP_NAME,
PROP_DONT_CACHE,
+ PROP_CACHE_POLICY,
PROP_USE_OPENCL,
PROP_PASSTHROUGH
};
@@ -155,11 +157,21 @@ gegl_node_class_init (GeglNodeClass *klass)
g_object_class_install_property (gobject_class, PROP_DONT_CACHE,
g_param_spec_boolean ("dont-cache",
"Do not cache",
- "Do not cache the result of this operation, the
property is inherited by children created from a node.",
+ "Do not cache the result of this operation, the
property is inherited by children created from a node."
+ " (Deprecated for \"cache-policy\".)",
FALSE,
G_PARAM_CONSTRUCT |
G_PARAM_READWRITE));
+ g_object_class_install_property (gobject_class, PROP_CACHE_POLICY,
+ g_param_spec_enum ("cache-policy",
+ "Cache Policy",
+ "Cache policy for this node, the property is inherited
by children created from a node.",
+ GEGL_TYPE_CACHE_POLICY,
+ GEGL_CACHE_POLICY_AUTO,
+ G_PARAM_CONSTRUCT |
+ G_PARAM_READWRITE));
+
g_object_class_install_property (gobject_class, PROP_USE_OPENCL,
g_param_spec_boolean ("use-opencl",
"Use OpenCL",
@@ -300,6 +312,10 @@ gegl_node_local_set_property (GObject *gobject,
node->dont_cache = g_value_get_boolean (value);
break;
+ case PROP_CACHE_POLICY:
+ node->cache_policy = g_value_get_enum (value);
+ break;
+
case PROP_PASSTHROUGH:
node->passthrough = g_value_get_boolean (value);
break;
@@ -350,6 +366,10 @@ gegl_node_local_get_property (GObject *gobject,
g_value_set_boolean (value, node->dont_cache);
break;
+ case PROP_CACHE_POLICY:
+ g_value_set_enum (value, node->cache_policy);
+ break;
+
case PROP_PASSTHROUGH:
g_value_set_boolean (value, node->passthrough);
break;
@@ -1975,6 +1995,31 @@ gegl_node_emit_computed (GeglNode *node,
g_signal_emit (node, gegl_node_signals[COMPUTED], 0, rect, NULL, NULL);
}
+gboolean
+gegl_node_use_cache (GeglNode *node)
+{
+ g_return_val_if_fail (GEGL_IS_NODE (node), FALSE);
+
+ switch (node->cache_policy)
+ {
+ case GEGL_CACHE_POLICY_AUTO:
+ if (node->dont_cache)
+ return FALSE;
+ else if (node->operation)
+ return gegl_operation_use_cache (node->operation);
+ else
+ return FALSE;
+
+ case GEGL_CACHE_POLICY_NEVER:
+ return FALSE;
+
+ case GEGL_CACHE_POLICY_ALWAYS:
+ return TRUE;
+ }
+
+ g_return_val_if_reached (FALSE);
+}
+
GeglCache *
gegl_node_get_cache (GeglNode *node)
{
@@ -2089,8 +2134,9 @@ gegl_node_add_child (GeglNode *self,
self->is_graph = TRUE;
child->priv->parent = self;
- child->dont_cache = self->dont_cache;
- child->use_opencl = self->use_opencl;
+ child->dont_cache = self->dont_cache;
+ child->cache_policy = self->cache_policy;
+ child->use_opencl = self->use_opencl;
return child;
}
@@ -2199,8 +2245,9 @@ gegl_node_create_child (GeglNode *self,
ret = gegl_node_new_child (self, "operation", operation, NULL);
if (ret && self)
{
- ret->dont_cache = self->dont_cache;
- ret->use_opencl = self->use_opencl;
+ ret->dont_cache = self->dont_cache;
+ ret->cache_policy = self->cache_policy;
+ ret->use_opencl = self->use_opencl;
}
return ret;
}
diff --git a/gegl/operation/Makefile.am b/gegl/operation/Makefile.am
index c9aaaf543..25efffa5c 100644
--- a/gegl/operation/Makefile.am
+++ b/gegl/operation/Makefile.am
@@ -55,6 +55,7 @@ liboperation_sources = \
gegl-operation-point-composer3.c \
gegl-operation-point-filter.c \
gegl-operation-point-render.c \
+ gegl-operation-private.h \
gegl-operation-property-keys.c \
gegl-operation-sink.c \
gegl-operation-source.c \
diff --git a/gegl/operation/gegl-operation-context.c b/gegl/operation/gegl-operation-context.c
index cff0d91f6..580c32012 100644
--- a/gegl/operation/gegl-operation-context.c
+++ b/gegl/operation/gegl-operation-context.c
@@ -340,8 +340,7 @@ gegl_operation_context_get_target (GeglOperationContext *context,
else
output = gegl_buffer_new (GEGL_RECTANGLE (0, 0, 0, 0), format);
}
- else if (node->dont_cache == FALSE &&
- ! GEGL_OPERATION_CLASS (G_OBJECT_GET_CLASS (operation))->no_cache)
+ else if (gegl_node_use_cache (node))
{
GeglBuffer *cache;
cache = GEGL_BUFFER (gegl_node_get_cache (node));
diff --git a/gegl/operation/gegl-operation-private.h b/gegl/operation/gegl-operation-private.h
new file mode 100644
index 000000000..5c646519f
--- /dev/null
+++ b/gegl/operation/gegl-operation-private.h
@@ -0,0 +1,30 @@
+/* This file is part of GEGL
+ *
+ * GEGL is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * GEGL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with GEGL; if not, see <https://www.gnu.org/licenses/>.
+ *
+ * Copyright 2019 Ell
+ */
+
+#ifndef __GEGL_OPERATION_PRIVATE_H__
+#define __GEGL_OPERATION_PRIVATE_H__
+
+G_BEING_DECLS
+
+
+gboolean gegl_operation_use_cache (GeglOperation *operation);
+
+
+G_END_DECLS
+
+#endif /* __GEGL_OPERATION_PRIVATE_H__ */
diff --git a/gegl/operation/gegl-operation.c b/gegl/operation/gegl-operation.c
index c3e55dd4f..0b31c146f 100644
--- a/gegl/operation/gegl-operation.c
+++ b/gegl/operation/gegl-operation.c
@@ -26,6 +26,7 @@
#include "gegl-config.h"
#include "gegl-types-internal.h"
#include "gegl-operation.h"
+#include "gegl-operation-private.h"
#include "gegl-operation-context.h"
#include "gegl-operations-util.h"
#include "graph/gegl-node-private.h"
@@ -89,6 +90,7 @@ gegl_operation_class_init (GeglOperationClass *klass)
klass->prepare = NULL;
klass->no_cache = FALSE;
klass->threaded = FALSE;
+ klass->cache_policy = GEGL_CACHE_POLICY_AUTO;
klass->get_bounding_box = get_bounding_box;
klass->get_invalidated_by_change = get_invalidated_by_change;
klass->get_required_for_output = get_required_for_output;
@@ -874,3 +876,23 @@ gegl_operation_get_source_space (GeglOperation *operation, const char *in_pad)
return babl_format_get_space (source_format);
return NULL;
}
+
+gboolean
+gegl_operation_use_cache (GeglOperation *operation)
+{
+ GeglOperationClass *klass = GEGL_OPERATION_GET_CLASS (operation);
+
+ switch (klass->cache_policy)
+ {
+ case GEGL_CACHE_POLICY_AUTO:
+ return ! klass->no_cache && klass->get_cached_region != NULL;
+
+ case GEGL_CACHE_POLICY_NEVER:
+ return FALSE;
+
+ case GEGL_CACHE_POLICY_ALWAYS:
+ return TRUE;
+ }
+
+ g_return_val_if_reached (FALSE);
+}
diff --git a/gegl/operation/gegl-operation.h b/gegl/operation/gegl-operation.h
index 39dbf9152..fa100034c 100644
--- a/gegl/operation/gegl-operation.h
+++ b/gegl/operation/gegl-operation.h
@@ -76,7 +76,8 @@ struct _GeglOperationClass
gegl_operation_class_set_key(s) */
GHashTable *keys; /* hashtable used for storing meta-data about an op */
- guint no_cache :1; /* do not create a cache for this operation */
+ guint no_cache :1; /* do not create a cache for this operation
+ (deprecated for "cache_policy") */
guint opencl_support:1;
guint want_in_place:1; /* if possible to use for in-place
processing, making output buffer =
@@ -87,7 +88,8 @@ struct _GeglOperationClass
to accelerate rendering; this allows opting in/out
in the sub-classes of these.
*/
- guint64 bit_pad:60;
+ guint cache_policy:2; /* cache policy for this operation */
+ guint64 bit_pad:58;
/* attach this operation with a GeglNode, override this if you are creating a
* GeglGraph, it is already defined for Filters/Sources/Composers.
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]