[gegl] graph, process: replace DFS/BFS with topological search



commit f68e28b21b434717aa27a300dc635bc9949d1358
Author: Ell <ell_se yahoo com>
Date:   Sat Nov 11 10:25:58 2017 -0500

    graph, process: replace DFS/BFS with topological search
    
    Remove gegl_visitor_{dfs,bfs}_traverse().  They weren't actually
    performing DFS and BFS, but were rather characterized by performing
    topological (dependencies-first) and reverse-topological
    (dependencies-last) search.
    
    Instead, add gegl_visitor_traverse_[reverse_]topological(), which
    perform a forward- and reverse-topological search, with lower
    overhead (in the BFS case, the specific order is different than
    before.)
    
    Adapt the rest of the code to use the new functions.  In
    particular, use a single GQueue in GeglGraphTraversal to store the
    path in topological order, instead of separate DFS and BFS paths.
    We forward-iterate over the path where we'd previously used the DFS
    list, and reverse-iterate where we'd previously used the BFS list.
    
    Remove GeglListVisitor, since it's no longer used.

 gegl/gegl-dot.c                             |    6 +-
 gegl/graph/gegl-node.c                      |    4 +-
 gegl/graph/gegl-visitor.c                   |  136 ++++++++++++---------------
 gegl/graph/gegl-visitor.h                   |   26 +++---
 gegl/process/Makefile.am                    |    2 -
 gegl/process/gegl-graph-traversal-debug.c   |    8 +-
 gegl/process/gegl-graph-traversal-private.h |    5 +-
 gegl/process/gegl-graph-traversal.c         |   53 +++++++---
 gegl/process/gegl-list-visitor.c            |  121 ------------------------
 gegl/process/gegl-list-visitor.h            |   60 ------------
 gegl/process/gegl-processor.c               |   31 +++---
 11 files changed, 138 insertions(+), 314 deletions(-)
---
diff --git a/gegl/gegl-dot.c b/gegl/gegl-dot.c
index 40c50b9..4845fe9 100644
--- a/gegl/gegl-dot.c
+++ b/gegl/gegl-dot.c
@@ -262,8 +262,7 @@ gegl_dot_add_node_and_dependencies (GString  *string,
                                          string);
 
   /* Add the nodes */
-  gegl_visitor_bfs_traverse (GEGL_VISITOR (dot_visitor),
-                             GEGL_VISITABLE (node));
+  gegl_visitor_traverse (GEGL_VISITOR (dot_visitor), GEGL_VISITABLE (node));
 
   /* Add the edges */
   pad = gegl_node_get_pad (node, "output");
@@ -285,8 +284,7 @@ gegl_dot_add_node_and_dependencies (GString  *string,
     }
 
 
-  gegl_visitor_bfs_traverse (GEGL_VISITOR (dot_visitor),
-                             GEGL_VISITABLE (pad));
+  gegl_visitor_traverse (GEGL_VISITOR (dot_visitor), GEGL_VISITABLE (pad));
 
   g_object_unref (dot_visitor);
 }
diff --git a/gegl/graph/gegl-node.c b/gegl/graph/gegl-node.c
index 5d997d2..9d71c56 100644
--- a/gegl/graph/gegl-node.c
+++ b/gegl/graph/gegl-node.c
@@ -688,7 +688,7 @@ gegl_node_invalidated (GeglNode            *node,
                                          regions);
   visitable = gegl_node_output_visitable_new (node);
 
-  gegl_visitor_bfs_traverse (visitor, visitable);
+  gegl_visitor_traverse_reverse_topological (visitor, visitable);
 
   g_object_unref (visitable);
   g_object_unref (visitor);
@@ -771,7 +771,7 @@ gegl_node_invalidated (GeglNode            *node,
                                          rects);
   visitable = gegl_node_output_visitable_new (node);
 
-  gegl_visitor_bfs_traverse (visitor, visitable);
+  gegl_visitor_traverse_reverse_topological (visitor, visitable);
 
   g_object_unref (visitable);
   g_object_unref (visitor);
diff --git a/gegl/graph/gegl-visitor.c b/gegl/graph/gegl-visitor.c
index 1a0805e..0a3bdea 100644
--- a/gegl/graph/gegl-visitor.c
+++ b/gegl/graph/gegl-visitor.c
@@ -30,17 +30,18 @@
 #include "gegl-visitable.h"
 
 
-static void       gegl_visitor_class_init        (GeglVisitorClass *klass);
-static void       gegl_visitor_init              (GeglVisitor      *self);
-static gboolean   gegl_visitor_traverse_step     (GeglVisitor      *self,
-                                                  GeglVisitable    *visitable,
-                                                  GHashTable       *visited_set);
-static gboolean   gegl_visitor_dfs_traverse_step (GeglVisitor      *self,
-                                                  GeglVisitable    *visitable,
-                                                  GHashTable       *visited_set);
-static void       gegl_visitor_bfs_init_step     (GeglVisitor      *self,
-                                                  GeglVisitable    *visitable,
-                                                  GHashTable       *edge_counts);
+static void       gegl_visitor_class_init                        (GeglVisitorClass  *klass);
+static void       gegl_visitor_init                              (GeglVisitor       *self);
+static gboolean   gegl_visitor_traverse_step                     (GeglVisitor       *self,
+                                                                  GeglVisitable     *visitable,
+                                                                  GHashTable        *visited_set);
+static gboolean   gegl_visitor_traverse_topological_step         (GeglVisitor       *self,
+                                                                  GeglVisitable     *visitable,
+                                                                  GHashTable        *visited_set);
+static void       gegl_visitor_traverse_reverse_topological_step (GeglVisitor       *self,
+                                                                  GeglVisitable     *visitable,
+                                                                  GHashTable        *visited_set,
+                                                                  GSList           **stack);
 
 
 G_DEFINE_TYPE (GeglVisitor, gegl_visitor, G_TYPE_OBJECT)
@@ -99,9 +100,9 @@ gegl_visitor_visit_node (GeglVisitor *self,
  * @self: #GeglVisitor
  * @visitable: the start #GeglVisitable
  *
- * Traverse starting at @visitable in arbitrary order.
- * Use this function when you don't need a DFS/BFS
- * specifically, since it can be more efficient.
+ * Traverse in arbitrary order, starting at @visitable.
+ * Use this function when you don't need a specific
+ * traversal order, since it can be more efficient.
  *
  * Returns: %TRUE if traversal was terminated early.
  **/
@@ -117,7 +118,8 @@ gegl_visitor_traverse (GeglVisitor   *self,
 
   visited_set = g_hash_table_new (NULL, NULL);
 
-  result = gegl_visitor_traverse_step (self, visitable, visited_set);
+  result = gegl_visitor_traverse_step (self, visitable,
+                                       visited_set);
 
   g_hash_table_unref (visited_set);
 
@@ -143,7 +145,8 @@ gegl_visitor_traverse_step (GeglVisitor   *self,
 
       if (! g_hash_table_contains (visited_set, dependency))
         {
-          if (gegl_visitor_traverse_step (self, dependency, visited_set))
+          if (gegl_visitor_traverse_step (self, dependency,
+                                          visited_set))
             {
               g_slist_free (dependencies);
 
@@ -160,17 +163,18 @@ gegl_visitor_traverse_step (GeglVisitor   *self,
 }
 
 /**
- * gegl_visitor_dfs_traverse:
+ * gegl_visitor_traverse_topological:
  * @self: #GeglVisitor
  * @visitable: the start #GeglVisitable
  *
- * Traverse depth first starting at @visitable.
+ * Traverse in topological order (dependencies first),
+ * starting at @visitable.
  *
  * Returns: %TRUE if traversal was terminated early.
  **/
 gboolean
-gegl_visitor_dfs_traverse (GeglVisitor   *self,
-                           GeglVisitable *visitable)
+gegl_visitor_traverse_topological (GeglVisitor   *self,
+                                   GeglVisitable *visitable)
 {
   GHashTable *visited_set;
   gboolean    result;
@@ -180,7 +184,8 @@ gegl_visitor_dfs_traverse (GeglVisitor   *self,
 
   visited_set = g_hash_table_new (NULL, NULL);
 
-  result = gegl_visitor_dfs_traverse_step (self, visitable, visited_set);
+  result = gegl_visitor_traverse_topological_step (self, visitable,
+                                                   visited_set);
 
   g_hash_table_unref (visited_set);
 
@@ -188,9 +193,9 @@ gegl_visitor_dfs_traverse (GeglVisitor   *self,
 }
 
 static gboolean
-gegl_visitor_dfs_traverse_step (GeglVisitor   *self,
-                                GeglVisitable *visitable,
-                                GHashTable    *visited_set)
+gegl_visitor_traverse_topological_step (GeglVisitor   *self,
+                                        GeglVisitable *visitable,
+                                        GHashTable    *visited_set)
 {
   GSList *dependencies;
   GSList *iter;
@@ -203,7 +208,8 @@ gegl_visitor_dfs_traverse_step (GeglVisitor   *self,
 
       if (! g_hash_table_contains (visited_set, dependency))
         {
-          if (gegl_visitor_dfs_traverse_step (self, dependency, visited_set))
+          if (gegl_visitor_traverse_topological_step (self, dependency,
+                                                      visited_set))
             {
               g_slist_free (dependencies);
 
@@ -223,75 +229,54 @@ gegl_visitor_dfs_traverse_step (GeglVisitor   *self,
 }
 
 /**
- * gegl_visitor_bfs_traverse:
- * @self: a #GeglVisitor
- * @visitable: the root #GeglVisitable.
+ * gegl_visitor_traverse_reverse_topological:
+ * @self: #GeglVisitor
+ * @visitable: the start #GeglVisitable
  *
- * Traverse breadth-first starting at @visitable.
+ * Traverse in reverse-topological order (dependencies
+ * last), starting at @visitable.
  *
  * Returns: %TRUE if traversal was terminated early.
  **/
 gboolean
-gegl_visitor_bfs_traverse (GeglVisitor   *self,
-                           GeglVisitable *visitable)
+gegl_visitor_traverse_reverse_topological (GeglVisitor   *self,
+                                           GeglVisitable *visitable)
 {
-  GHashTable *edge_counts;
-  GQueue      queue = G_QUEUE_INIT;
+  GHashTable *visited_set;
+  GSList     *stack = NULL;
 
   g_return_val_if_fail (GEGL_IS_VISITOR (self), FALSE);
   g_return_val_if_fail (GEGL_IS_VISITABLE (visitable), FALSE);
 
-  edge_counts = g_hash_table_new (NULL, NULL);
+  visited_set = g_hash_table_new (NULL, NULL);
 
-  gegl_visitor_bfs_init_step (self, visitable, edge_counts);
+  gegl_visitor_traverse_reverse_topological_step (self, visitable,
+                                                  visited_set, &stack);
 
-  g_queue_push_tail (&queue, visitable);
+  g_hash_table_unref (visited_set);
 
-  while ((visitable = g_queue_pop_head (&queue)))
+  while (stack)
     {
-      GSList *dependencies;
-      GSList *iter;
+      visitable = stack->data;
+
+      stack = g_slist_delete_link (stack, stack);
 
       if (gegl_visitable_accept (visitable, self))
         {
-          g_queue_clear (&queue);
-          g_hash_table_unref (edge_counts);
+          g_slist_free (stack);
 
           return TRUE;
         }
-
-      dependencies = gegl_visitable_depends_on (visitable);
-
-      for (iter = dependencies; iter; iter = g_slist_next (iter))
-        {
-          GeglVisitable *dependency = iter->data;
-          gint           edges;
-
-          edges = GPOINTER_TO_INT (g_hash_table_lookup (edge_counts, dependency));
-
-          if (edges == 1)
-            {
-              g_queue_push_tail (&queue, dependency);
-            }
-          else
-            {
-              g_hash_table_insert (edge_counts,
-                                   dependency, GINT_TO_POINTER (edges - 1));
-            }
-        }
-
-      g_slist_free (dependencies);
     }
 
-  g_hash_table_unref (edge_counts);
-
   return FALSE;
 }
 
 static void
-gegl_visitor_bfs_init_step (GeglVisitor   *self,
-                            GeglVisitable *visitable,
-                            GHashTable    *edge_counts)
+gegl_visitor_traverse_reverse_topological_step (GeglVisitor    *self,
+                                                GeglVisitable  *visitable,
+                                                GHashTable     *visited_set,
+                                                GSList        **stack)
 {
   GSList *dependencies;
   GSList *iter;
@@ -301,15 +286,16 @@ gegl_visitor_bfs_init_step (GeglVisitor   *self,
   for (iter = dependencies; iter; iter = g_slist_next (iter))
     {
       GeglVisitable *dependency = iter->data;
-      gint           edges;
 
-      edges = GPOINTER_TO_INT (g_hash_table_lookup (edge_counts, dependency));
-      g_hash_table_insert (edge_counts,
-                           dependency, GINT_TO_POINTER (edges + 1));
-
-      if (edges == 0)
-        gegl_visitor_bfs_init_step (self, dependency, edge_counts);
+      if (! g_hash_table_contains (visited_set, dependency))
+        {
+          gegl_visitor_traverse_reverse_topological_step (self, dependency,
+                                                          visited_set, stack);
+        }
     }
 
   g_slist_free (dependencies);
+
+  *stack = g_slist_prepend (*stack, visitable);
+  g_hash_table_add (visited_set, visitable);
 }
diff --git a/gegl/graph/gegl-visitor.h b/gegl/graph/gegl-visitor.h
index c53a615..d02e7d6 100644
--- a/gegl/graph/gegl-visitor.h
+++ b/gegl/graph/gegl-visitor.h
@@ -50,19 +50,19 @@ struct _GeglVisitorClass
 };
 
 
-GType      gegl_visitor_get_type     (void) G_GNUC_CONST;
-
-gboolean   gegl_visitor_visit_pad    (GeglVisitor   *self,
-                                      GeglPad       *pad);
-gboolean   gegl_visitor_visit_node   (GeglVisitor   *self,
-                                      GeglNode      *node);
-
-gboolean   gegl_visitor_traverse     (GeglVisitor   *self,
-                                      GeglVisitable *visitable);
-gboolean   gegl_visitor_dfs_traverse (GeglVisitor   *self,
-                                      GeglVisitable *visitable);
-gboolean   gegl_visitor_bfs_traverse (GeglVisitor   *self,
-                                      GeglVisitable *visitable);
+GType      gegl_visitor_get_type                     (void) G_GNUC_CONST;
+
+gboolean   gegl_visitor_visit_pad                    (GeglVisitor   *self,
+                                                      GeglPad       *pad);
+gboolean   gegl_visitor_visit_node                   (GeglVisitor   *self,
+                                                      GeglNode      *node);
+
+gboolean   gegl_visitor_traverse                     (GeglVisitor   *self,
+                                                      GeglVisitable *visitable);
+gboolean   gegl_visitor_traverse_topological         (GeglVisitor   *self,
+                                                      GeglVisitable *visitable);
+gboolean   gegl_visitor_traverse_reverse_topological (GeglVisitor   *self,
+                                                      GeglVisitable *visitable);
 
 
 G_END_DECLS
diff --git a/gegl/process/Makefile.am b/gegl/process/Makefile.am
index 408cd03..8d106ee 100644
--- a/gegl/process/Makefile.am
+++ b/gegl/process/Makefile.am
@@ -27,14 +27,12 @@ libprocess_la_SOURCES = \
        gegl-eval-manager.c             \
        gegl-graph-traversal.c          \
        gegl-graph-traversal-debug.c    \
-       gegl-list-visitor.c             \
        gegl-processor.c                \
        \
        gegl-eval-manager.h             \
        gegl-graph-debug.h              \
        gegl-graph-traversal.h          \
        gegl-graph-traversal-private.h  \
-       gegl-list-visitor.h             \
        gegl-processor.h                \
        gegl-processor-private.h
 
diff --git a/gegl/process/gegl-graph-traversal-debug.c b/gegl/process/gegl-graph-traversal-debug.c
index 7331b68..878c147 100644
--- a/gegl/process/gegl-graph-traversal-debug.c
+++ b/gegl/process/gegl-graph-traversal-debug.c
@@ -44,7 +44,9 @@ gegl_graph_dump_outputs (GeglNode *node)
 
   gegl_graph_prepare (path);
 
-  for (list_iter = path->dfs_path; list_iter; list_iter = list_iter->next)
+  for (list_iter = g_queue_peek_head_link (&path->path);
+       list_iter;
+       list_iter = list_iter->next)
   {
     GeglNode *cur_node = GEGL_NODE (list_iter->data);
     if (gegl_node_get_pad (cur_node, "output"))
@@ -78,7 +80,9 @@ gegl_graph_dump_request (GeglNode            *node,
   gegl_graph_prepare (path);
   gegl_graph_prepare_request (path, roi, 0);
 
-  for (list_iter = path->dfs_path; list_iter; list_iter = list_iter->next)
+  for (list_iter = g_queue_peek_head_link (&path->path);
+       list_iter;
+       list_iter = list_iter->next)
   {
     GeglNode *cur_node = GEGL_NODE (list_iter->data);
     GeglOperationContext *context = g_hash_table_lookup (path->contexts, cur_node);
diff --git a/gegl/process/gegl-graph-traversal-private.h b/gegl/process/gegl-graph-traversal-private.h
index cad0856..f8e03b6 100644
--- a/gegl/process/gegl-graph-traversal-private.h
+++ b/gegl/process/gegl-graph-traversal-private.h
@@ -22,9 +22,8 @@
 struct _GeglGraphTraversal
 {
   GHashTable *contexts;
-  GList *dfs_path;
-  GList *bfs_path;
-  gboolean rects_dirty;
+  GQueue      path;
+  gboolean    rects_dirty;
   GeglBuffer *shared_empty;
 };
 
diff --git a/gegl/process/gegl-graph-traversal.c b/gegl/process/gegl-graph-traversal.c
index 2d4c2ab..6b6cc03 100644
--- a/gegl/process/gegl-graph-traversal.c
+++ b/gegl/process/gegl-graph-traversal.c
@@ -30,12 +30,13 @@
 
 #include "graph/gegl-node-private.h"
 #include "graph/gegl-pad.h"
+#include "graph/gegl-visitor.h"
+#include "graph/gegl-callback-visitor.h"
 #include "graph/gegl-visitable.h"
 #include "graph/gegl-connection.h"
 
 #include "process/gegl-graph-traversal.h"
 #include "process/gegl-graph-traversal-private.h"
-#include "process/gegl-list-visitor.h"
 
 #include "operation/gegl-operation.h"
 #include "operation/gegl-operation-context.h"
@@ -54,11 +55,22 @@ static void   _gegl_graph_do_build                     (GeglGraphTraversal *path
                                                         GeglNode           *node);
 static GeglBuffer *gegl_graph_get_shared_empty         (GeglGraphTraversal *path);
 
+static gboolean
+_gegl_graph_do_build_add_node (GeglNode *node,
+                               gpointer  data)
+{
+  GeglGraphTraversal *path = data;
+
+  g_queue_push_tail (&path->path, node);
+
+  return FALSE;
+}
+
 static void
 _gegl_graph_do_build (GeglGraphTraversal *path, GeglNode *node)
 {
   GeglPad *pad = NULL;
-  GeglListVisitor *list_visitor = g_object_new (GEGL_TYPE_LIST_VISITOR, NULL);
+  GeglVisitor *visitor;
 
   /* We need to check the real node of the output/input pad in case this is a proxy node */
   pad = gegl_node_get_pad (node, "output");
@@ -73,14 +85,17 @@ _gegl_graph_do_build (GeglGraphTraversal *path, GeglNode *node)
         node = gegl_pad_get_node (pad);
     }
 
-  path->dfs_path = gegl_list_visitor_get_dfs_path (list_visitor, GEGL_VISITABLE (node));
-  path->bfs_path = gegl_list_visitor_get_bfs_path (list_visitor, GEGL_VISITABLE (node));
+  visitor = gegl_callback_visitor_new (_gegl_graph_do_build_add_node, path);
+
+  gegl_visitor_traverse_topological (visitor, GEGL_VISITABLE (node));
+
+  g_object_unref (visitor);
+
   path->contexts = g_hash_table_new_full (NULL,
                                           NULL,
                                           NULL,
                                           (GDestroyNotify)gegl_operation_context_destroy);
   path->rects_dirty = FALSE;
-  g_object_unref (list_visitor);
 }
 
 /**
@@ -112,8 +127,7 @@ gegl_graph_build (GeglNode *node)
 void
 gegl_graph_rebuild (GeglGraphTraversal *path, GeglNode *node)
 {
-  g_list_free (path->dfs_path);
-  g_list_free (path->bfs_path);
+  g_queue_clear (&path->path);
   g_hash_table_unref (path->contexts);
 
   /* Replaces everything but shared_empty */
@@ -123,8 +137,7 @@ gegl_graph_rebuild (GeglGraphTraversal *path, GeglNode *node)
 void
 gegl_graph_free (GeglGraphTraversal *path)
 {
-  g_list_free (path->dfs_path);
-  g_list_free (path->bfs_path);
+  g_queue_clear (&path->path);
   g_hash_table_unref (path->contexts);
   g_clear_object (&path->shared_empty);
   g_free (path);
@@ -143,7 +156,7 @@ gegl_graph_free (GeglGraphTraversal *path)
 GeglRectangle
 gegl_graph_get_bounding_box (GeglGraphTraversal *path)
 {
-  GeglNode *node = GEGL_NODE (g_list_last (path->dfs_path)->data);
+  GeglNode *node = GEGL_NODE (g_queue_peek_tail (&path->path));
   if (node->valid_have_rect)
     {
       return node->have_rect;
@@ -162,7 +175,9 @@ gegl_graph_prepare (GeglGraphTraversal *path)
 {
   GList *list_iter = NULL;
 
-  for (list_iter = path->dfs_path; list_iter; list_iter = list_iter->next)
+  for (list_iter = g_queue_peek_head_link (&path->path);
+       list_iter;
+       list_iter = list_iter->next)
   {
     GeglNode *node = GEGL_NODE (list_iter->data);
     GeglNode *parent;
@@ -218,12 +233,14 @@ gegl_graph_prepare_request (GeglGraphTraversal  *path,
   GList *list_iter = NULL;
   static const GeglRectangle empty_rect = {0, 0, 0, 0};
 
-  g_return_if_fail (path->bfs_path);
+  g_return_if_fail (! g_queue_is_empty (&path->path));
 
   if (path->rects_dirty)
     {
       /* Zero all the needs rects so we can intersect with them below */
-      for (list_iter = path->bfs_path; list_iter; list_iter = list_iter->next)
+      for (list_iter = g_queue_peek_tail_link (&path->path);
+           list_iter;
+           list_iter = list_iter->prev)
         {
           GeglNode *node = GEGL_NODE (list_iter->data);
           GeglOperationContext *context = g_hash_table_lookup (path->contexts, node);
@@ -240,7 +257,7 @@ gegl_graph_prepare_request (GeglGraphTraversal  *path,
 
   {
     /* Prep the first node */
-    GeglNode *node = GEGL_NODE (path->bfs_path->data);
+    GeglNode *node = GEGL_NODE (g_queue_peek_tail (&path->path));
     GeglOperationContext *context = g_hash_table_lookup (path->contexts, node);
     GeglRectangle new_need;
 
@@ -253,7 +270,9 @@ gegl_graph_prepare_request (GeglGraphTraversal  *path,
   }
   
   /* Iterate over all the nodes and propagate the requested rectangle */
-  for (list_iter = path->bfs_path; list_iter; list_iter = list_iter->next)
+  for (list_iter = g_queue_peek_tail_link (&path->path);
+       list_iter;
+       list_iter = list_iter->prev)
     {
       GeglNode             *node      = GEGL_NODE (list_iter->data);
       GeglOperation        *operation = node->operation;
@@ -395,7 +414,9 @@ gegl_graph_process (GeglGraphTraversal *path,
   GeglOperationContext *last_context = NULL;
   GeglBuffer *operation_result = NULL;
 
-  for (list_iter = path->dfs_path; list_iter; list_iter = list_iter->next)
+  for (list_iter = g_queue_peek_head_link (&path->path);
+       list_iter;
+       list_iter = list_iter->next)
     {
       GeglNode *node = GEGL_NODE (list_iter->data);
       GeglOperation *operation = node->operation;
diff --git a/gegl/process/gegl-processor.c b/gegl/process/gegl-processor.c
index a86a8fb..477fe38 100644
--- a/gegl/process/gegl-processor.c
+++ b/gegl/process/gegl-processor.c
@@ -36,8 +36,8 @@
 #include "gegl-processor-private.h"
 
 #include "graph/gegl-visitor.h"
+#include "graph/gegl-callback-visitor.h"
 #include "graph/gegl-visitable.h"
-#include "process/gegl-list-visitor.h"
 
 #include "opencl/gegl-cl.h"
 
@@ -760,6 +760,14 @@ gegl_processor_render (GeglProcessor *processor,
   return !gegl_processor_is_rendered (processor);
 }
 
+static gboolean
+gegl_processor_work_is_opencl_node (GeglNode *node,
+                                    gpointer  data)
+{
+  return GEGL_OPERATION_GET_CLASS (node->operation)->cl_data ||
+         GEGL_OPERATION_GET_CLASS (node->operation)->opencl_support;
+}
+
 /* Will call gegl_processor_render and when there is no more work to be done,
  * it will write the result to the destination */
 gboolean
@@ -773,23 +781,14 @@ gegl_processor_work (GeglProcessor *processor,
       if (gegl_cl_is_accelerated ()
           && processor->chunk_size != GEGL_CL_CHUNK_SIZE)
         {
-          GeglListVisitor *visitor = g_object_new (GEGL_TYPE_LIST_VISITOR, NULL);
-          GList *iterator = NULL;
-          GList *visits_list = NULL;
-          visits_list = gegl_list_visitor_get_dfs_path (visitor, GEGL_VISITABLE (processor->real_node));
+          GeglVisitor *visitor;
 
-          for (iterator = visits_list; iterator; iterator = iterator->next)
-            {
-              GeglNode *node = (GeglNode*) iterator->data;
-              if (GEGL_OPERATION_GET_CLASS(node->operation)->cl_data
-                  || GEGL_OPERATION_GET_CLASS(node->operation)->opencl_support)
-                {
-                  processor->chunk_size = GEGL_CL_CHUNK_SIZE;
-                  break;
-                }
-            }
+          visitor = gegl_callback_visitor_new (gegl_processor_work_is_opencl_node,
+                                               NULL);
+
+          if (gegl_visitor_traverse (visitor, GEGL_VISITABLE (processor->real_node)))
+            processor->chunk_size = GEGL_CL_CHUNK_SIZE;
 
-          g_list_free (visits_list);
           g_object_unref (visitor);
         }
     }


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