[gegl] operation, graph: add {GeglOperationClass, GeglNode}::cache-policy



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]