babl-fish-reference: factor out separate function for float/double
authorØyvind Kolås <pippin@gimp.org>
Fri, 31 Aug 2018 09:18:30 +0000 (11:18 +0200)
committerØyvind Kolås <pippin@gimp.org>
Fri, 31 Aug 2018 09:24:47 +0000 (11:24 +0200)
babl_fish_reference_process now only contains the dispatch tree that
tries various fast paths first before ending up in the float or double
synthetic references.

babl/babl-fish-reference.c

index 35b9d95d3708547029dd387afc90d8e100367a9f..619ceb58b7ada18920feacc0ae76df7816a3090d 100644 (file)
@@ -611,15 +611,6 @@ process_same_model (const Babl  *babl,
 {
   const void *type_float = babl_type_from_id (BABL_FLOAT);
 #define MAX(a, b) ((a) > (b) ? (a) : (b))
-  if (BABL (babl->fish.source) == BABL (babl->fish.destination))
-  {
-    if (source == destination)
-    {
-      memcpy (destination, source, n * babl->fish.source->format.bytes_per_pixel);
-    }
-    return;
-  }
-
 
 
 
@@ -699,45 +690,175 @@ process_same_model (const Babl  *babl,
   }
 }
 
-void
-babl_fish_reference_process (const Babl *babl,
-                             const char *source,
-                             char       *destination,
-                             long        n,
-                             void       *data)
+
+static void
+babl_fish_reference_process_double (const Babl *babl,
+                                    const char *source,
+                                    char       *destination,
+                                    long        n,
+                                    void       *data)
 {
-  const void *type_float = babl_type_from_id (BABL_FLOAT);
-  const void *type_double = babl_type_from_id (BABL_DOUBLE);
-  Babl *source_image = NULL;
-  Babl *rgba_image = NULL;
-  Babl *destination_image = NULL;
+    Babl *source_image = NULL;
+    Babl *rgba_image = NULL;
+    Babl *destination_image = NULL;
+    void *source_double_buf_alloc = NULL;
+    void *source_double_buf;
+    void *rgba_double_buf_alloc = NULL;
+    void *rgba_double_buf;
+    void *destination_double_buf_alloc = NULL;
+    void *destination_double_buf;
+    const void *type_double  = babl_type_from_id (BABL_DOUBLE);
 
-  static int allow_float_reference = -1;
-  if (allow_float_reference == -1)
-    allow_float_reference = getenv ("BABL_REFERENCE_NOFLOAT") ? 0 : 1;
+    if (babl->fish.source->format.type[0] == type_double &&
+        BABL(babl->fish.source)->format.components ==
+        BABL(babl->fish.source)->format.model->components && 0)
+    {
+      source_double_buf = (void*)source;
+      source_image = babl_image_from_linear (
+         source_double_buf, BABL (BABL ((babl->fish.source))->format.model));
+    }
+    else
+    {
+      source_double_buf_alloc = babl_malloc (sizeof (double) * n *
+                                  BABL (babl->fish.source)->format.model->components);
 
-  if ((BABL (babl->fish.source)->format.model ==
-       BABL (babl->fish.destination)->format.model) &&
-      (BABL (babl->fish.source)->format.space ==
-       BABL (babl->fish.destination)->format.space)
-      )
-  {
-    process_same_model (babl, source, destination, n);
-    return;
-  }
+      source_double_buf = source_double_buf_alloc;
+      source_image = babl_image_from_linear (
+        source_double_buf, BABL (BABL ((babl->fish.source))->format.model));
+      convert_to_double (
+        (BablFormat *) BABL (babl->fish.source),
+        source,
+        source_double_buf,
+        n
+      );
+    }
 
-  if (babl_format_is_format_n (BABL (babl->fish.destination)))
-  {
-    process_to_n_component (babl, source, destination, n);
-    return;
-  }
+    if (babl_model_is ((void*)babl->fish.source->format.model, "RGBA"))
+    {
+      rgba_double_buf = source_double_buf;
+      rgba_image = babl_image_from_linear (
+          rgba_double_buf,
+          (void*)babl->fish.source->format.model);
+    }
+    else
+    {
+      Babl *conv =
+        assert_conversion_find (
+        BABL (babl->fish.source)->format.model,
 
-  if (allow_float_reference &&
-      (babl->fish.source->format.type[0]->bits < 32 ||
-      babl->fish.source->format.type[0] == type_float) &&
-      (babl->fish.destination->format.type[0]->bits < 32 ||
-      babl->fish.destination->format.type[0] == type_float))
-  {
+      babl_remodel_with_space (babl_model_from_id (BABL_RGBA),
+                           BABL (BABL ((babl->fish.source))->format.space)));
+
+      rgba_double_buf_alloc  = babl_malloc (sizeof (double) * n * 4);
+      rgba_double_buf        = rgba_double_buf_alloc;
+
+      rgba_image = babl_image_from_linear (
+          rgba_double_buf, babl_remodel_with_space (babl_model_from_id (BABL_RGBA),
+          BABL (BABL ((babl->fish.source))->format.space)) );
+
+      if (conv->class_type == BABL_CONVERSION_PLANAR)
+      {
+        babl_conversion_process (
+          conv,
+          (void*)source_image, (void*)rgba_image,
+          n);
+      }
+      else if (conv->class_type == BABL_CONVERSION_LINEAR)
+      {
+        babl_conversion_process (
+          conv,
+          source_double_buf, rgba_double_buf,
+          n);
+      }
+      else babl_fatal ("oops");
+    }
+
+    if (((babl->fish.source)->format.space !=
+        ((babl->fish.destination)->format.space)))
+    {
+      double matrix[9];
+      double *rgba = rgba_double_buf;
+      babl_matrix_mul_matrix (
+        (babl->fish.destination)->format.space->space.XYZtoRGB,
+        (babl->fish.source)->format.space->space.RGBtoXYZ,
+        matrix);
+
+      babl_matrix_mul_vector_buf4 (matrix, rgba, rgba, n);
+    }
+
+    {
+      const Babl *destination_rgba_format =
+        babl_remodel_with_space (babl_model_from_id (BABL_RGBA),
+             BABL (BABL ((babl->fish.destination))->format.space));
+
+      if(BABL (babl->fish.destination)->format.model == (void*)destination_rgba_format)
+      {
+         destination_double_buf = rgba_double_buf;
+      }
+      else
+      {
+      Babl *conv =
+        assert_conversion_find (destination_rgba_format,
+           BABL (babl->fish.destination)->format.model);
+
+         destination_double_buf_alloc = babl_malloc (sizeof (double) * n *
+                                          BABL (babl->fish.destination)->format.model->components);
+         destination_double_buf = destination_double_buf_alloc;
+
+      if (conv->class_type == BABL_CONVERSION_PLANAR)
+        {
+          destination_image = babl_image_from_linear (
+            destination_double_buf, BABL (BABL ((babl->fish.destination))->format.model));
+
+
+          babl_conversion_process (
+            conv,
+            (void*)rgba_image, (void*)destination_image,
+            n);
+        }
+      else if (conv->class_type == BABL_CONVERSION_LINEAR)
+        {
+          babl_conversion_process (
+            conv,
+            rgba_double_buf, destination_double_buf,
+            n);
+        }
+      else babl_fatal ("oops");
+      }
+   }
+
+    convert_from_double (
+      (BablFormat *) BABL (babl->fish.destination),
+      destination_double_buf,
+      destination,
+      n
+    );
+
+    if (destination_double_buf_alloc)
+      babl_free (destination_double_buf_alloc);
+    if (rgba_double_buf_alloc)
+      babl_free (rgba_double_buf_alloc);
+    if (source_double_buf_alloc)
+      babl_free (source_double_buf_alloc);
+    if (source_image)
+      babl_free (source_image);
+    if (rgba_image)
+      babl_free (rgba_image);
+    if (destination_image)
+      babl_free (destination_image);
+}
+
+static void
+babl_fish_reference_process_float (const Babl *babl,
+                                   const char *source,
+                                   char       *destination,
+                                   long        n,
+                                   void       *data)
+{
+  const void *type_float = babl_type_from_id (BABL_FLOAT);
+    Babl *source_image = NULL;
+    Babl *rgba_image = NULL;
+    Babl *destination_image = NULL;
     void *source_float_buf_alloc = NULL;
     void *source_float_buf;
     void *rgba_float_buf_alloc = NULL;
@@ -773,9 +894,11 @@ babl_fish_reference_process (const Babl *babl,
     }
 
     if (!conv_to_rgba || !conv_from_rgba)
-      goto double_entry;
-
-
+    {
+      /* needed float conversions not found, using double code path instead */
+      babl_fish_reference_process_double (babl, source, destination, n, data);
+      return;
+    }
 
     if (babl->fish.source->format.type[0] == type_float &&
         BABL(babl->fish.source)->format.components ==
@@ -854,39 +977,35 @@ babl_fish_reference_process (const Babl *babl,
 
     {
 
-      if(
-        babl_format_with_space ("RGBA float",
+      if(babl_format_with_space ("RGBA float",
                    BABL (BABL ((babl->fish.destination))->format.space)) ==
-        babl_format_with_space (dst_name,
+         babl_format_with_space (dst_name,
                    BABL (BABL ((babl->fish.destination))->format.space)))
       {
-         destination_float_buf = rgba_float_buf;
+        destination_float_buf = rgba_float_buf;
       }
       else
       {
-         destination_float_buf_alloc = babl_malloc (sizeof (float) * n *
-                                         BABL (babl->fish.destination)->format.model->components);
-         destination_float_buf = destination_float_buf_alloc;
+        destination_float_buf_alloc = babl_malloc (sizeof (float) * n *
+                                        BABL (babl->fish.destination)->format.model->components);
+        destination_float_buf = destination_float_buf_alloc;
 
-      if (conv_from_rgba->class_type == BABL_CONVERSION_PLANAR)
+        if (conv_from_rgba->class_type == BABL_CONVERSION_PLANAR)
         {
-          destination_image = babl_image_from_linear (
-            destination_float_buf, destination_float_format);
-        babl_conversion_process (
-          conv_from_rgba,
-          (void*)rgba_image, (void*)destination_image,
-          n);
-      }
-    else if (conv_from_rgba->class_type == BABL_CONVERSION_LINEAR)
-      {
-        babl_conversion_process (
-          conv_from_rgba,
-          rgba_float_buf, destination_float_buf,
-          n);
-      }
-
+           destination_image = babl_image_from_linear (
+             destination_float_buf, destination_float_format);
+             babl_conversion_process (
+               conv_from_rgba,
+               (void*)rgba_image, (void*)destination_image,
+             n);
+        }
+        else if (conv_from_rgba->class_type == BABL_CONVERSION_LINEAR)
+        {
+          babl_conversion_process (conv_from_rgba, rgba_float_buf,
+                                   destination_float_buf, n);
+        }
       }
-   }
+    }
 
     convert_from_float (
       (BablFormat *) BABL (babl->fish.destination),
@@ -901,154 +1020,79 @@ babl_fish_reference_process (const Babl *babl,
       babl_free (rgba_float_buf_alloc);
     if (source_float_buf_alloc)
       babl_free (source_float_buf_alloc);
-  }
-  else /*   double  */
-  {
-    void *source_double_buf_alloc = NULL;
-    void *source_double_buf;
-    void *rgba_double_buf_alloc = NULL;
-    void *rgba_double_buf;
-    void *destination_double_buf_alloc = NULL;
-    void *destination_double_buf;
-    double_entry:
-
-    if (babl->fish.source->format.type[0] == type_double &&
-        BABL(babl->fish.source)->format.components ==
-        BABL(babl->fish.source)->format.model->components && 0)
-    {
-      source_double_buf = (void*)source;
-      source_image = babl_image_from_linear (
-         source_double_buf, BABL (BABL ((babl->fish.source))->format.model));
-    }
-    else
-    {
-      source_double_buf_alloc = babl_malloc (sizeof (double) * n *
-                                  BABL (babl->fish.source)->format.model->components);
-
-      source_double_buf = source_double_buf_alloc;
-      source_image = babl_image_from_linear (
-        source_double_buf, BABL (BABL ((babl->fish.source))->format.model));
-      convert_to_double (
-        (BablFormat *) BABL (babl->fish.source),
-        source,
-        source_double_buf,
-        n
-      );
-    }
-
-    if (babl_model_is ((void*)babl->fish.source->format.model, "RGBA"))
-    {
-      rgba_double_buf = source_double_buf;
-      rgba_image = babl_image_from_linear (
-          rgba_double_buf,
-          (void*)babl->fish.source->format.model);
-    }
-    else
-    {
-      Babl *conv =
-        assert_conversion_find (
-        BABL (babl->fish.source)->format.model,
-
-      babl_remodel_with_space (babl_model_from_id (BABL_RGBA),
-                           BABL (BABL ((babl->fish.source))->format.space)));
-
-      rgba_double_buf_alloc  = babl_malloc (sizeof (double) * n * 4);
-      rgba_double_buf        = rgba_double_buf_alloc;
+    if (source_image)
+      babl_free (source_image);
+    if (rgba_image)
+      babl_free (rgba_image);
+    if (destination_image)
+      babl_free (destination_image);
+}
 
-      rgba_image = babl_image_from_linear (
-          rgba_double_buf, babl_remodel_with_space (babl_model_from_id (BABL_RGBA),
-          BABL (BABL ((babl->fish.source))->format.space)) );
+void
+babl_fish_reference_process (const Babl *babl,
+                             const char *source,
+                             char       *destination,
+                             long        n,
+                             void       *data)
+{
+  static const void *type_float = NULL;
+  static int allow_float_reference = -1;
 
-      if (conv->class_type == BABL_CONVERSION_PLANAR)
-      {
-        babl_conversion_process (
-          conv,
-          (void*)source_image, (void*)rgba_image,
-          n);
-      }
-      else if (conv->class_type == BABL_CONVERSION_LINEAR)
-      {
-        babl_conversion_process (
-          conv,
-          source_double_buf, rgba_double_buf,
-          n);
-      }
-      else babl_fatal ("oops");
-    }
+  if (!type_float) type_float = babl_type_from_id (BABL_FLOAT);
 
-    if (((babl->fish.source)->format.space !=
-        ((babl->fish.destination)->format.space)))
+  /* same format in source/destination */
+  if (BABL (babl->fish.source) == BABL (babl->fish.destination))
+  {
+    if (source == destination)
     {
-      double matrix[9];
-      double *rgba = rgba_double_buf;
-      babl_matrix_mul_matrix (
-        (babl->fish.destination)->format.space->space.XYZtoRGB,
-        (babl->fish.source)->format.space->space.RGBtoXYZ,
-        matrix);
-
-      babl_matrix_mul_vector_buf4 (matrix, rgba, rgba, n);
+      memcpy (destination, source, n * babl->fish.source->format.bytes_per_pixel);
     }
+    return;
+  }
 
-    {
-      const Babl *destination_rgba_format =
-        babl_remodel_with_space (babl_model_from_id (BABL_RGBA),
-             BABL (BABL ((babl->fish.destination))->format.space));
-
-      if(BABL (babl->fish.destination)->format.model == (void*)destination_rgba_format)
-      {
-         destination_double_buf = rgba_double_buf;
-      }
-      else
-      {
-      Babl *conv =
-        assert_conversion_find (destination_rgba_format,
-           BABL (babl->fish.destination)->format.model);
-
-         destination_double_buf_alloc = babl_malloc (sizeof (double) * n *
-                                          BABL (babl->fish.destination)->format.model->components);
-         destination_double_buf = destination_double_buf_alloc;
-
-      if (conv->class_type == BABL_CONVERSION_PLANAR)
-        {
-          destination_image = babl_image_from_linear (
-            destination_double_buf, BABL (BABL ((babl->fish.destination))->format.model));
-
+  /* same model and space, only convert type */
+  if ((BABL (babl->fish.source)->format.model ==
+       BABL (babl->fish.destination)->format.model) &&
+      (BABL (babl->fish.source)->format.space ==
+       BABL (babl->fish.destination)->format.space)
+      )
+  {
+    process_same_model (babl, source, destination, n);
+    return;
+  }
 
-          babl_conversion_process (
-            conv,
-            (void*)rgba_image, (void*)destination_image,
-            n);
-        }
-      else if (conv->class_type == BABL_CONVERSION_LINEAR)
-        {
-          babl_conversion_process (
-            conv,
-            rgba_double_buf, destination_double_buf,
-            n);
-        }
-      else babl_fatal ("oops");
-      }
-   }
+  /* we're converting to a n_component format - special case   */
+  if (babl_format_is_format_n (BABL (babl->fish.destination)))
+  {
+    process_to_n_component (babl, source, destination, n);
+    return;
+  }
 
-    convert_from_double (
-      (BablFormat *) BABL (babl->fish.destination),
-      destination_double_buf,
-      destination,
-      n
-    );
+  if (allow_float_reference == -1)
+    allow_float_reference = getenv ("BABL_REFERENCE_NOFLOAT") ? 0 : 1;
 
-    if (destination_double_buf_alloc)
-      babl_free (destination_double_buf_alloc);
-    if (rgba_double_buf_alloc)
-      babl_free (rgba_double_buf_alloc);
-    if (source_double_buf_alloc)
-      babl_free (source_double_buf_alloc);
+  /* both source and destination are either single precision float or <32bit component,
+     we then do a similar to the double reference - using the first registered
+     float conversions - note that this makes the first registered float conversion of
+     a given type a reference, and we thus rely on the *first* float conversion regsitered
+     to be correct, this will be the case if the code paths are duplicated and we register
+     either a planar or linear conversion to and from "RGBA float" at the same time as
+     registering conversions for double. When needed conversions do not exist, we defer
+     to the double code paths
+   */
+  if (allow_float_reference &&
+      (babl->fish.source->format.type[0]->bits < 32 ||
+      babl->fish.source->format.type[0] == type_float) &&
+      (babl->fish.destination->format.type[0]->bits < 32 ||
+      babl->fish.destination->format.type[0] == type_float) &&
+      !babl_format_is_palette (babl->fish.source) &&
+      !babl_format_is_palette (babl->fish.destination))
+  {
+    babl_fish_reference_process_float (babl, source, destination, n, data);
+  }
+  else /*   double  */
+  {
+    babl_fish_reference_process_double (babl, source, destination, n, data);
   }
 
-  if (source_image)
-    babl_free (source_image);
-  if (rgba_image)
-    babl_free (rgba_image);
-  if (destination_image)
-    babl_free (destination_image);
 }