[babl] babl: refactor code to get rid of more branches in babl_process



commit 9debb9d7f68afb5b9028343e3b33cbf4aa7edc6c
Author: Øyvind Kolås <pippin gimp org>
Date:   Sun Jan 14 22:49:40 2018 +0100

    babl: refactor code to get rid of more branches in babl_process
    
    In the best case scenario now, babl_process increments instrumentation
    counters and directly calls the relevant registered fast path function,
    with no additional call stack frames in-between.

 babl/babl-fish-path.c      |  119 +++++++++++++++++++++++---------------------
 babl/babl-fish-reference.c |    7 ++-
 babl/babl-fish-simple.c    |    3 +-
 babl/babl-fish.c           |    1 +
 babl/babl-fish.h           |    2 +-
 babl/babl-internal.h       |    5 ++-
 6 files changed, 75 insertions(+), 62 deletions(-)
---
diff --git a/babl/babl-fish-path.c b/babl/babl-fish-path.c
index dbfa4de..301dd5c 100644
--- a/babl/babl-fish-path.c
+++ b/babl/babl-fish-path.c
@@ -596,12 +596,8 @@ babl_fish_path2 (const Babl *source,
       return NULL;
     }
 
-  if (babl_list_size (babl->fish_path.conversion_list) == 1)
-    {
-      babl->class_type = BABL_FISH_SIMPLE;
-      babl->fish_simple.conversion = (void*)babl_list_get_first (babl->fish_path.conversion_list);
-    }
-
+  babl_fish_prepare_bpp (babl);
+  _babl_fish_rig_dispatch (babl);
   /* Since there is not an already registered instance by the required
    * name, inserting newly created class into database.
    */
@@ -610,7 +606,6 @@ babl_fish_path2 (const Babl *source,
     babl_db_insert (babl_fish_db (), babl);
   }
   babl_mutex_unlock (babl_format_mutex);
-  babl_fish_prepare_bpp (babl);
   return babl;
 }
 
@@ -648,9 +643,10 @@ babl_fish_path (const Babl *source,
 
 static inline void
 babl_fish_path_process (const Babl *babl,
-                        const void *source,
-                        void       *destination,
-                        long        n)
+                        const char *source,
+                        char       *destination,
+                        long        n,
+                        void       *data)
 {
   process_conversion_path (babl->fish_path.conversion_list,
                            source,
@@ -660,34 +656,40 @@ babl_fish_path_process (const Babl *babl,
                            n);
 }
 
-static long
-_babl_process (Babl *babl,
-               const void *source,
-               void       *destination,
-               long        n)
+static inline void
+babl_fish_memcpy_process (const Babl *babl,
+                          const char *source,
+                          char       *destination,
+                          long        n,
+                          void       *data)
+{
+  memcpy (destination, source, n * babl->fish.source->format.bytes_per_pixel);
+}
+
+void
+_babl_fish_rig_dispatch (Babl *babl)
 {
   switch (babl->class_type)
     {
       case BABL_FISH_REFERENCE:
-        babl->fish.processings++;
-        babl->fish.pixels += n;
         if (babl->fish.source == babl->fish.destination)
-          { /* XXX: we're assuming linear buffers */
-            memcpy (destination, source, n * babl->fish.source->format.bytes_per_pixel);
+          {
+            babl->fish.dispatch = babl_fish_memcpy_process;
           }
         else
           {
-            babl_fish_reference_process (babl, source, destination, n);
+            babl->fish.dispatch = babl_fish_reference_process;
           }
         break;
 
       case BABL_FISH_SIMPLE:
-        babl->fish.processings++;
-        babl->fish.pixels += n;
         if (BABL (babl->fish_simple.conversion)->class_type == BABL_CONVERSION_LINEAR)
           {
-            babl_conversion_process (BABL (babl->fish_simple.conversion),
-                                     source, destination, n);
+            /* lift out conversion from single step conversion and make it be the dispatch function
+             * itself
+             */
+            babl->fish.data = babl->fish_simple.conversion->data;
+            babl->fish.dispatch = babl->fish_simple.conversion->dispatch;
           }
         else
           {
@@ -696,9 +698,19 @@ _babl_process (Babl *babl,
         break;
 
       case BABL_FISH_PATH:
-        babl->fish.processings++;
-        babl->fish.pixels += n;
-        babl_fish_path_process (babl, source, destination, n);
+        if (babl_list_size(babl->fish_path.conversion_list) == 1)
+        {
+          BablConversion *conversion = (void*)babl_list_get_first(babl->fish_path.conversion_list);
+
+          /* do same short-circuit optimization as for simple fishes */
+
+          babl->fish.dispatch = conversion->dispatch;
+          babl->fish.data     = conversion->data;
+        }
+        else
+        {
+          babl->fish.dispatch = babl_fish_path_process;
+        }
         break;
 
       case BABL_CONVERSION:
@@ -706,14 +718,24 @@ _babl_process (Babl *babl,
       case BABL_CONVERSION_PLANE:
       case BABL_CONVERSION_PLANAR:
         babl_assert (0);
-        babl_conversion_process (babl, source, destination, n);
         break;
 
       default:
         babl_log ("NYI");
-        return -1;
         break;
     }
+}
+
+static long
+_babl_process (const Babl *cbabl,
+               const void *source,
+               void       *destination,
+               long        n)
+{
+  Babl *babl = (void*)cbabl;
+  babl->fish.processings++;
+  babl->fish.pixels += n;
+  babl->fish.dispatch (babl, source, destination, n, babl->fish.data);
   return n;
 }
 
@@ -745,33 +767,16 @@ babl_process_rows (const Babl *fish,
   if (n <= 0)
     return 0;
 
-  /* first check if it is a fish since that is our fast path */
-  if (babl->class_type >= BABL_FISH &&
-      babl->class_type <= BABL_FISH_PATH)
+  babl->fish.processings++;
+  babl->fish.pixels += n * rows;
+  for (row = 0; row < rows; row++)
     {
-      babl->fish.processings++;
-      babl->fish.pixels += n * rows;
-      for (row = 0; row < rows; row++)
-        {
-          _babl_process ((void*)babl, src, dst, n);
-          src += source_stride;
-          dst += dest_stride;
-        }
-      return n * rows;
-    }
+      babl->fish.dispatch (babl, (void*)src, (void*)dst, n, babl->fish.data);
 
-  /* matches all conversion classes */
-  if (babl->class_type >= BABL_CONVERSION &&
-      babl->class_type <= BABL_CONVERSION_PLANAR)
-  {
-    for (row = 0; row < rows; row++)
-    {
-      babl_conversion_process (babl, (void*)src, (void*)dst, n);
       src += source_stride;
       dst += dest_stride;
     }
-    return n * rows;
-  }
+  return n * rows;
 
   babl_fatal ("eek");
   return -1;
@@ -894,8 +899,8 @@ init_path_instrumentation (FishPathInstrumentation *fpi,
                                              fpi->fmt_rgba_double->format.bytes_per_pixel);
 
   /* create sourcebuffer from testbuffer in the correct format */
-  babl_process (fpi->fish_rgba_to_source,
-                test_pixels, fpi->source, fpi->num_test_pixels);
+  _babl_process (fpi->fish_rgba_to_source,
+                 test_pixels, fpi->source, fpi->num_test_pixels);
 
   /* calculate the reference buffer of how it should be */
   ticks_start = babl_ticks ();
@@ -905,8 +910,8 @@ init_path_instrumentation (FishPathInstrumentation *fpi,
   fpi->reference_cost = ticks_end - ticks_start;
 
   /* transform the reference destination buffer to RGBA */
-  babl_process (fpi->fish_destination_to_rgba,
-                fpi->ref_destination, fpi->ref_destination_rgba_double, fpi->num_test_pixels);
+  _babl_process (fpi->fish_destination_to_rgba,
+                 fpi->ref_destination, fpi->ref_destination_rgba_double, fpi->num_test_pixels);
 }
 
 static void
@@ -983,8 +988,8 @@ get_path_instrumentation (FishPathInstrumentation *fpi,
   /* transform the reference and the actual destination buffers to RGBA
    * for comparison with each other
    */
-  babl_process (fpi->fish_destination_to_rgba,
-                fpi->destination, fpi->destination_rgba_double, fpi->num_test_pixels);
+  _babl_process (fpi->fish_destination_to_rgba,
+                 fpi->destination, fpi->destination_rgba_double, fpi->num_test_pixels);
 
   *path_error = babl_rel_avg_error (fpi->destination_rgba_double,
                                     fpi->ref_destination_rgba_double,
diff --git a/babl/babl-fish-reference.c b/babl/babl-fish-reference.c
index 072c10f..695c3ca 100644
--- a/babl/babl-fish-reference.c
+++ b/babl/babl-fish-reference.c
@@ -115,6 +115,7 @@ babl_fish_reference (const Babl *source,
 #ifndef HAVE_TLS
       free (name);
 #endif
+      _babl_fish_rig_dispatch (babl);
       return babl;
     }
 
@@ -124,7 +125,7 @@ babl_fish_reference (const Babl *source,
   babl_assert (source->class_type == BABL_FORMAT);
   babl_assert (destination->class_type == BABL_FORMAT);
 
-  babl = babl_malloc (sizeof (BablFishReference) +
+  babl = babl_calloc (1, sizeof (BablFishReference) +
                       strlen (name) + 1);
   babl->class_type    = BABL_FISH_REFERENCE;
   babl->instance.id   = babl_fish_get_id (source, destination);
@@ -138,6 +139,7 @@ babl_fish_reference (const Babl *source,
   babl->fish.error       = 0.0;  /* assuming the provided reference conversions for types
                                     and models are as exact as possible
                                   */
+  _babl_fish_rig_dispatch (babl);
 
   /* Since there is not an already registered instance by the required
    * name, inserting newly created class into database.
@@ -443,7 +445,8 @@ void
 babl_fish_reference_process (const Babl *babl,
                              const char *source,
                              char       *destination,
-                             long        n)
+                             long        n,
+                             void       *data)
 {
   void *source_double_buf;
   void *rgba_double_buf;
diff --git a/babl/babl-fish-simple.c b/babl/babl-fish-simple.c
index eeaed51..1fa3384 100644
--- a/babl/babl-fish-simple.c
+++ b/babl/babl-fish-simple.c
@@ -42,7 +42,7 @@ babl_fish_simple (BablConversion *conversion)
       return babl;
     }
 
-  babl = babl_malloc (sizeof (BablFishSimple) +
+  babl = babl_calloc (1, sizeof (BablFishSimple) +
                       strlen (name) + 1);
   babl->class_type    = BABL_FISH_SIMPLE;
   babl->instance.id   = babl_fish_get_id (conversion->source, conversion->destination);
@@ -58,6 +58,7 @@ babl_fish_simple (BablConversion *conversion)
                                    reference, and babl fish reference only requests clean
                                    conversions */
 
+  _babl_fish_rig_dispatch (babl);
   /* Since there is not an already registered instance by the required
    * name, inserting newly created class into database.
    */
diff --git a/babl/babl-fish.c b/babl/babl-fish.c
index 749b075..8c73a2b 100644
--- a/babl/babl-fish.c
+++ b/babl/babl-fish.c
@@ -257,6 +257,7 @@ babl_fish (const void *source,
         if (ffish.fish_path)
           {
             /* we have found suitable fish path in the database */
+            _babl_fish_rig_dispatch (ffish.fish_path);
             return ffish.fish_path;
           }
 
diff --git a/babl/babl-fish.h b/babl/babl-fish.h
index 9f0cdd6..36ef098 100644
--- a/babl/babl-fish.h
+++ b/babl/babl-fish.h
@@ -31,7 +31,7 @@ typedef struct
   BablInstance    instance;
   const Babl     *source;
   const Babl     *destination;
-  void           (*dispatch) (const Babl *babl, const char *src, char *dst, long n);
+  void           (*dispatch) (const Babl *babl, const char *src, char *dst, long n, void *data);
   void            *data;  /* user data */
   double          error;    /* the amount of noise introduced by the fish */
 
diff --git a/babl/babl-internal.h b/babl/babl-internal.h
index 337541b..9d29b47 100644
--- a/babl/babl-internal.h
+++ b/babl/babl-internal.h
@@ -78,7 +78,8 @@ void     babl_extension_deinit          (void);
 void     babl_fish_reference_process    (const Babl *babl,
                                          const char *source,
                                          char       *destination,
-                                         long        n);
+                                         long        n,
+                                         void       *data); // data is ignored
 
 Babl   * babl_fish_reference            (const Babl     *source,
                                          const Babl     *destination);
@@ -495,4 +496,6 @@ babl_conversion_process (const Babl *babl,
   conversion->dispatch (babl, source, destination, n, conversion->data);
 }
 
+void _babl_fish_rig_dispatch (Babl *babl);
+
 #endif


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