[gegl] gegl-operation-filter: add get_split_strategy() vfunc



commit 8ef3346165313ecbca871c4d1b638b26eb079b0c
Author: Ell <ell_se yahoo com>
Date:   Sat Aug 12 17:29:12 2017 -0400

    gegl-operation-filter: add get_split_strategy() vfunc
    
    Add a get_split_strategy() virtual function to GeglOperationFilter,
    which can be used by ops to affect the way the processed area is
    subdivided for multithreaded processing.  The function returns a
    a GeglSplitStrategy value, which is currently one of:
    
      - GEGL_SPLIT_STRATEGY_AUTO:  Split the area arbitrarily
        (currently, the area is split either horizontally or
        vertically, along the longer dimension of the ROI.)  This is
        the default behavior, if the op doesn't override the function.
    
      - GEGL_SPLIT_STRATEGY_HORIZONTAL:  Split the area horizontally.
    
      - GEGL_SPLIT_STRATEGY_VERTICAL:  Split the area vertically.

 gegl/gegl-types.h                      |    7 +++++++
 gegl/operation/gegl-operation-filter.c |   23 +++++++++++++++++++++--
 gegl/operation/gegl-operation-filter.h |   22 ++++++++++++++++------
 3 files changed, 44 insertions(+), 8 deletions(-)
---
diff --git a/gegl/gegl-types.h b/gegl/gegl-types.h
index a7b5954..743b51e 100644
--- a/gegl/gegl-types.h
+++ b/gegl/gegl-types.h
@@ -41,6 +41,13 @@ typedef enum
   GEGL_BLIT_DIRTY    = 1 << 1
 } GeglBlitFlags;
 
+typedef enum
+{
+  GEGL_SPLIT_STRATEGY_AUTO,
+  GEGL_SPLIT_STRATEGY_HORIZONTAL,
+  GEGL_SPLIT_STRATEGY_VERTICAL
+} GeglSplitStrategy;
+
 
 typedef struct _GeglConfig GeglConfig;
 GType gegl_config_get_type (void) G_GNUC_CONST;
diff --git a/gegl/operation/gegl-operation-filter.c b/gegl/operation/gegl-operation-filter.c
index ee96382..34198d9 100644
--- a/gegl/operation/gegl-operation-filter.c
+++ b/gegl/operation/gegl-operation-filter.c
@@ -168,11 +168,26 @@ gegl_operation_filter_process (GeglOperation        *operation,
   if (gegl_operation_use_threading (operation, result))
   {
     gint threads = gegl_config_threads ();
+    GeglSplitStrategy split_strategy = GEGL_SPLIT_STRATEGY_AUTO;
     GThreadPool *pool = thread_pool ();
     ThreadData thread_data[GEGL_MAX_THREADS];
     gint pending = threads;
 
-    if (result->width > result->height)
+    if (klass->get_split_strategy)
+    {
+      split_strategy = klass->get_split_strategy (operation, context,
+                                                  output_prop, result, level);
+    }
+
+    if (split_strategy == GEGL_SPLIT_STRATEGY_AUTO)
+    {
+      if (result->width > result->height)
+        split_strategy = GEGL_SPLIT_STRATEGY_VERTICAL;
+      else
+        split_strategy = GEGL_SPLIT_STRATEGY_HORIZONTAL;
+    }
+
+    if (split_strategy == GEGL_SPLIT_STRATEGY_VERTICAL)
     {
       gint bit = result->width / threads;
       for (gint j = 0; j < threads; j++)
@@ -184,7 +199,7 @@ gegl_operation_filter_process (GeglOperation        *operation,
       }
       thread_data[threads-1].roi.width = result->width - (bit * (threads-1));
     }
-    else
+    else if (split_strategy == GEGL_SPLIT_STRATEGY_HORIZONTAL)
     {
       gint bit = result->height / threads;
       for (gint j = 0; j < threads; j++)
@@ -196,6 +211,10 @@ gegl_operation_filter_process (GeglOperation        *operation,
       }
       thread_data[threads-1].roi.height = result->height - (bit * (threads-1));
     }
+    else
+    {
+      g_return_val_if_reached (FALSE);
+    }
     for (gint i = 0; i < threads; i++)
     {
       thread_data[i].klass = klass;
diff --git a/gegl/operation/gegl-operation-filter.h b/gegl/operation/gegl-operation-filter.h
index d6ed095..3badde4 100644
--- a/gegl/operation/gegl-operation-filter.h
+++ b/gegl/operation/gegl-operation-filter.h
@@ -45,12 +45,22 @@ struct _GeglOperationFilterClass
 {
   GeglOperationClass 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);
+
+  /* How to split the area for multithreaded processing.  Should be irrelevant
+   * for most ops.
+   */
+  GeglSplitStrategy (* get_split_strategy) (GeglOperation        *self,
+                                            GeglOperationContext *context,
+                                            const gchar          *output_prop,
+                                            const GeglRectangle  *roi,
+                                            gint                  level);
+
+  gpointer                                  pad[3];
 };
 
 GType gegl_operation_filter_get_type (void) G_GNUC_CONST;


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