[babl] babl: speed up trc dispatch



commit bf92fa0a974755d510456b8425c32b4cdb759671
Author: Øyvind Kolås <pippin gimp org>
Date:   Wed Aug 30 17:09:28 2017 +0200

    babl: speed up trc dispatch
    
    By splitting the core computation done by the TRC down to callbacks of
    different types, that all optionally can use the provided trc object.  This way
    we can move the conditional for the polymorphism out of loops. The higher level
    API of using the TRC still works - and is also accelerated by this change.

 babl/babl-fish-path.c |  142 +++++++++++++++++++++++++++---------------------
 babl/babl-fish.c      |    2 +-
 babl/babl-trc.c       |   22 +++++++-
 babl/babl-trc.h       |   96 ++++++++++++++++++++++-----------
 4 files changed, 165 insertions(+), 97 deletions(-)
---
diff --git a/babl/babl-fish-path.c b/babl/babl-fish-path.c
index 4ac5016..f89aae1 100644
--- a/babl/babl-fish-path.c
+++ b/babl/babl-fish-path.c
@@ -283,14 +283,11 @@ _babl_fish_path_destroy (void *data)
   return 0;
 }
 
-BablList *accum = NULL;
-
 static int
 show_item (Babl *babl,
            void *user_data)
 {
   BablConversion *conv = (void *)babl;
-  //BablSpace *space = user_data;
 
   if (conv->destination->class_type == BABL_FORMAT)
   {
@@ -413,14 +410,27 @@ alias_conversion (Babl *babl,
 static void prep_conversion (const Babl *babl)
 {
   Babl *conversion = (void*) babl;
-  float *matrixf = babl_calloc (sizeof (float), 9); // we leak this matrix , which is a singleton
+  const Babl *source_space = babl_conversion_get_source_space (conversion);
+  float *matrixf;
+  int i;
+  float *lut;
+
   double matrix[9];
   babl_matrix_mul_matrix (
      (conversion->conversion.destination)->format.space->space.XYZtoRGB,
      (conversion->conversion.source)->format.space->space.RGBtoXYZ,
      matrix);
+
+  matrixf = babl_calloc (sizeof (float), 9 + 256); // we leak this matrix , which is a singleton
   babl_matrix_to_float (matrix, matrixf);
   conversion->conversion.data = matrixf;
+
+  lut = matrixf + 9;
+  for (i = 0; i < 256; i++)
+  {
+    lut[i] = _babl_trc_to_linear (source_space->space.trc[0], i/255.0);
+    // XXX: should have green and blue luts as well
+  }
 }
 
 static inline long
@@ -429,6 +439,19 @@ universal_nonlinear_rgb_converter (const Babl *conversion,unsigned char *src_cha
   const Babl *source_space = babl_conversion_get_source_space (conversion);
   const Babl *destination_space = babl_conversion_get_destination_space (conversion);
 
+  void   *to_trc_red;
+  void   *to_trc_green;
+  void   *to_trc_blue;
+  float (*to_linear_red) (void *trc, float value);
+  float (*to_linear_green) (void *trc, float value);
+  float (*to_linear_blue) (void *trc, float value);
+  void   *from_trc_red;
+  void   *from_trc_green;
+  void   *from_trc_blue;
+  float (*from_linear_red) (void *trc, float value);
+  float (*from_linear_green) (void *trc, float value);
+  float (*from_linear_blue) (void *trc, float value);
+
   float * matrixf = conversion->conversion.data;
   int i;
   float *rgba_in = (void*)src_char;
@@ -436,17 +459,34 @@ universal_nonlinear_rgb_converter (const Babl *conversion,unsigned char *src_cha
   assert (source_space);
   assert (destination_space);
 
+  to_linear_red   = (void*)source_space->space.trc[0]->trc.fun_to_linear;
+  to_trc_red      = (void*)source_space->space.trc[0];
+  from_linear_red = (void*)destination_space->space.trc[0]->trc.fun_from_linear;
+  from_trc_red    = (void*)destination_space->space.trc[0];
+
+  to_linear_green = (void*)source_space->space.trc[1]->trc.fun_to_linear;
+  to_trc_green    = (void*)source_space->space.trc[1];
+  from_linear_green= (void*)destination_space->space.trc[1]->trc.fun_from_linear;
+  from_trc_green  = (void*)destination_space->space.trc[1];
+
+  to_linear_blue  = (void*)source_space->space.trc[2]->trc.fun_to_linear;
+  to_trc_blue     = (void*)source_space->space.trc[2];
+  from_linear_blue= (void*)destination_space->space.trc[2]->trc.fun_from_linear;
+  from_trc_blue   = (void*)destination_space->space.trc[2];
+
   for (i = 0; i < samples; i++)
   {
     float rgba_tmp[4];
-    int c;
-    for (c = 0; c < 3; c ++)
-      rgba_tmp[c] = _babl_trc_to_linear (source_space->space.trc[c], rgba_in[c]);
-    babl_matrix_mul_vectorff (matrixf, rgba_tmp, rgba_out);
 
-    for (c = 0; c < 3; c ++)
-      rgba_out[c] = _babl_trc_from_linear (destination_space->space.trc[c], rgba_out[c]);
+    rgba_tmp[0] = to_linear_red(to_trc_red, rgba_in[0]);
+    rgba_tmp[1] = to_linear_green(to_trc_green, rgba_in[1]);
+    rgba_tmp[2] = to_linear_blue(to_trc_blue, rgba_in[2]);
+
+    babl_matrix_mul_vectorff (matrixf, rgba_tmp, rgba_out);
 
+    rgba_out[0] = from_linear_red(from_trc_red, rgba_out[0]);
+    rgba_out[1] = from_linear_green(from_trc_green, rgba_out[1]);
+    rgba_out[2] = from_linear_blue(from_trc_blue, rgba_out[2]);
     rgba_out[3] = rgba_in[3];
     rgba_in  += 4;
     rgba_out += 4;
@@ -455,36 +495,53 @@ universal_nonlinear_rgb_converter (const Babl *conversion,unsigned char *src_cha
   return samples;
 }
 
-#if 0
+#if 1
 // does not seem to be valid
 static inline long
 universal_nonlinear_rgba_u8_converter (const Babl *conversion,unsigned char *src_char, unsigned char 
*dst_char, long samples)
 {
-  const Babl *source_space = babl_conversion_get_source_space (conversion);
-  const Babl *destination_space = babl_conversion_get_destination_space (conversion);
+  const Babl *destination_space = conversion->conversion.destination->format.space;
 
   float * matrixf = conversion->conversion.data;
+  float * in_trc_lut = matrixf + 9;
   int i;
   uint8_t *rgba_in_u8 = (void*)src_char;
   uint8_t *rgba_out_u8 = (void*)dst_char;
 
-  assert (source_space);
-  assert (destination_space);
+  void   *from_trc_red;
+  void   *from_trc_green;
+  void   *from_trc_blue;
+  float (*from_linear_red) (void *trc, float value);
+  float (*from_linear_green) (void *trc, float value);
+  float (*from_linear_blue) (void *trc, float value);
+
+  from_linear_red = (void*)destination_space->space.trc[0]->trc.fun_from_linear;
+  from_trc_red    = (void*)destination_space->space.trc[0];
+  from_linear_green= (void*)destination_space->space.trc[1]->trc.fun_from_linear;
+  from_trc_green  = (void*)destination_space->space.trc[1];
+  from_linear_blue= (void*)destination_space->space.trc[2]->trc.fun_from_linear;
+  from_trc_blue   = (void*)destination_space->space.trc[2];
 
   for (i = 0; i < samples; i++)
   {
-    float rgba_tmp[4];
-    float rgba_out[4];
+    float rgb[3];
     int c;
     for (c = 0; c < 3; c ++)
-      rgba_tmp[c] = _babl_trc_to_linear (source_space->space.trc[c], rgba_in_u8[c]/255.0);
+      rgb[c] = in_trc_lut[rgba_in_u8[c]]; 
 
-    babl_matrix_mul_vectorff (matrixf, rgba_tmp, rgba_out);
+    babl_matrix_mul_vectorff (matrixf, rgb, rgb);
 
-    for (c = 0; c < 3; c ++)
     {
-      int v = _babl_trc_from_linear (destination_space->space.trc[c], rgba_out[c]) * 255.5;
-      rgba_out_u8[c] = v < 0 ?  0 : v > 255 ? 255 : v;
+      int v = from_linear_red (from_trc_red, rgb[0]) * 255.5;
+      rgba_out_u8[0] = v; //v < 0 ?  0 : v > 255 ? 255 : v;
+    }
+    {
+      int v = from_linear_green (from_trc_green, rgb[1]) * 255.5;
+      rgba_out_u8[1] = v; //v < 0 ?  0 : v > 255 ? 255 : v;
+    }
+    {
+      int v = from_linear_blue (from_trc_blue , rgb[2]) * 255.5;
+      rgba_out_u8[2] = v; //v < 0 ?  0 : v > 255 ? 255 : v;
     }
 
     rgba_out_u8[3] = rgba_in_u8[3];
@@ -515,43 +572,6 @@ universal_rgb_converter (const Babl *conversion,unsigned char *src_char, unsigne
   return samples;
 }
 
-#if 0
-static inline long
-universal_rgb_converter_u16 (const Babl *conversion,unsigned char *src_char, unsigned char *dst_char, long 
samples)
-{
-  double matrix[9];
-  float matrixf[9];
-  int i;
-  float rgba_inf[4];
-  float rgba_outf[4];
-  uint16_t *rgba_in = (void*)src_char;
-  uint16_t *rgba_out = (void*)dst_char;
-
-  babl_matrix_mul_matrix (
-     (conversion->conversion.destination)->format.space->space.XYZtoRGB,
-     (conversion->conversion.source)->format.space->space.RGBtoXYZ,
-     matrix);
-  /* XXX: this floating point matrix could be cached, avoiding the overhead of double precision matrix 
multiplication
-   *      for short spans
-   */
-  babl_matrix_to_float (matrix, matrixf);
-
-  for (i = 0; i < samples; i++)
-  {
-    int c;
-    for (c = 0; c < 4; c ++)
-      rgba_inf[c] = rgba_in[c] / 65535.0;
-    babl_matrix_mul_vectorff (matrixf, rgba_inf, rgba_outf);
-    for (c = 0; c < 4; c ++)
-      rgba_out[c] = rgba_outf[c] * 65535.5;
-    rgba_in  += 4;
-    rgba_out += 4;
-  }
-
-  return samples;
-}
-#endif
-
 static int
 add_rgb_adapter (Babl *babl,
                  void *space)
@@ -575,7 +595,6 @@ add_rgb_adapter (Babl *babl,
                         babl_format_with_space("R'G'B'A float", space),
                         "linear", universal_nonlinear_rgb_converter,
                         NULL));
-#if 0
     prep_conversion(babl_conversion_new(babl_format_with_space("R'G'B'A u8", space),
                         babl_format_with_space("R'G'B'A u8", babl),
                         "linear", universal_nonlinear_rgba_u8_converter,
@@ -584,7 +603,6 @@ add_rgb_adapter (Babl *babl,
                         babl_format_with_space("R'G'B'A u8", space),
                         "linear", universal_nonlinear_rgba_u8_converter,
                         NULL));
-#endif
   }
   return 0;
 }
@@ -648,7 +666,7 @@ babl_fish_path (const Babl *source,
 
     if (!done)
     {
-      if(0)babl_conversion_class_for_each (show_item, (void*)source->format.space);
+      if(1)babl_conversion_class_for_each (show_item, (void*)source->format.space);
       //babl_format_class_for_each (show_fmt, NULL);
       //babl_model_class_for_each (show_fmt, NULL);
     }
diff --git a/babl/babl-fish.c b/babl/babl-fish.c
index 587c549..6e22f89 100644
--- a/babl/babl-fish.c
+++ b/babl/babl-fish.c
@@ -169,7 +169,7 @@ babl_fish_get_id (const Babl *source,
   /* value of 'id' will be used as argument for hash function,
    * substraction serves as simple combination of
    * source/destination values. */
-  int id = (((int)source * 93)) ^ ((int)destination);
+  int id = (((size_t)source * 93)) ^ ((size_t)destination);
   /* instances with id 0 won't be inserted into database */
   id *= ((((size_t)  (destination))) % 37);
 
diff --git a/babl/babl-trc.c b/babl/babl-trc.c
index f63a984..cabd64d 100644
--- a/babl/babl-trc.c
+++ b/babl/babl-trc.c
@@ -98,9 +98,27 @@ babl_trc_new (const char *name,
     for (j = 0; j < n_lut; j++)
       trc_db[i].inv_lut[j] =
         babl_trc_to_linear (BABL(&trc_db[i]), trc_db[i].lut[(int) ( j/(n_lut-1.0) * (n_lut-1))]);
-    
   }
- 
+
+  switch (trc_db[i].type)
+  {
+    case BABL_TRC_LINEAR:
+      trc_db[i].fun_to_linear = _babl_trc_linearf;
+      trc_db[i].fun_from_linear = _babl_trc_linearf;
+      break;
+    case BABL_TRC_GAMMA:
+      trc_db[i].fun_to_linear = _babl_trc_gamma_to_linearf;
+      trc_db[i].fun_from_linear = _babl_trc_gamma_from_linearf;
+      break;
+    case BABL_TRC_SRGB:
+      trc_db[i].fun_to_linear = _babl_trc_srgb_to_linearf;
+      trc_db[i].fun_from_linear = _babl_trc_srgb_from_linearf;
+      break;
+    case BABL_TRC_LUT:
+      trc_db[i].fun_to_linear = babl_trc_lut_to_linearf;
+      trc_db[i].fun_from_linear = babl_trc_lut_from_linearf;
+      break;
+  }
   return (Babl*)&trc_db[i];
 }
 
diff --git a/babl/babl-trc.h b/babl/babl-trc.h
index abdf52a..3f36dac 100644
--- a/babl/babl-trc.h
+++ b/babl/babl-trc.h
@@ -39,8 +39,35 @@ typedef struct
   char             name[128];
   float           *lut;
   float           *inv_lut;
+  float          (*fun_to_linear)(const Babl *trc_, float val);
+  float          (*fun_from_linear)(const Babl *trc_, float val);
 } BablTRC;
 
+
+static inline float babl_trc_lut_from_linearf (const Babl *trc_, float value)
+{
+  BablTRC *trc = (void*)trc_;
+  int entry = value * trc->lut_size + 0.5;
+  float ret = trc->inv_lut[
+    (entry >= 0 && entry < trc->lut_size) ?
+                               entry :
+                               trc->lut_size-1];
+  /* XXX: fixme, do linear interpolation */
+  return ret;
+}
+
+static inline float babl_trc_lut_to_linearf (const Babl *trc_, float value)
+{
+  BablTRC *trc = (void*)trc_;
+  int entry = value * trc->lut_size + 0.5;
+  float ret = trc->lut[
+    (entry >= 0 && entry < trc->lut_size) ?
+                               entry :
+                               trc->lut_size-1];
+  /* XXX: fixme, do linear interpolation */
+  return ret;
+}
+
 static inline double babl_trc_lut_from_linear (const Babl *trc_, double value)
 {
   BablTRC *trc = (void*)trc_;
@@ -70,14 +97,10 @@ static inline double _babl_trc_from_linear (const Babl *trc_, double value)
   BablTRC *trc = (void*)trc_;
   switch (trc->type)
   {
-    case BABL_TRC_LINEAR:
-            return value;
-    case BABL_TRC_GAMMA:
-            return pow (value, 1.0/trc->gamma);
-    case BABL_TRC_SRGB:
-            return babl_linear_to_gamma_2_2 (value);
-    case BABL_TRC_LUT:
-            return babl_trc_lut_from_linear (trc_, value);
+    case BABL_TRC_LINEAR: return value;
+    case BABL_TRC_GAMMA:  return pow (value, 1.0/trc->gamma);
+    case BABL_TRC_SRGB:   return babl_linear_to_gamma_2_2 (value);
+    case BABL_TRC_LUT:    return babl_trc_lut_from_linear (trc_, value);
   }
   return value;
 }
@@ -87,42 +110,51 @@ static inline double _babl_trc_to_linear (const Babl *trc_, double value)
   BablTRC *trc = (void*)trc_;
   switch (trc->type)
   {
-    case BABL_TRC_LINEAR:
-            return value;
-    case BABL_TRC_GAMMA:
-            return pow (value, trc->gamma);
-    case BABL_TRC_SRGB:
-            return babl_gamma_2_2_to_linear (value);
-    case BABL_TRC_LUT:
-            return babl_trc_lut_to_linear (trc_, value);
+    case BABL_TRC_LINEAR: return value;
+    case BABL_TRC_GAMMA:  return pow (value, trc->gamma);
+    case BABL_TRC_SRGB:   return babl_gamma_2_2_to_linear (value);
+    case BABL_TRC_LUT:    return babl_trc_lut_to_linear (trc_, value);
   }
   return value;
 }
 
+static inline float _babl_trc_linearf (const Babl *trc_, float value)
+{
+  return 1.0;
+}
+
+static inline float _babl_trc_gamma_to_linearf (const Babl *trc_, float value)
+{
+  BablTRC *trc = (void*)trc_;
+  return powf (value, trc->gamma);
+}
+
+static inline float _babl_trc_gamma_from_linearf (const Babl *trc_, float value)
+{
+  BablTRC *trc = (void*)trc_;
+  return powf (value, 1.0f/trc->gamma);
+}
+
+static inline float _babl_trc_srgb_to_linearf (const Babl *trc_, float value)
+{
+  return babl_gamma_2_2_to_linearf (value);
+}
+
+static inline float _babl_trc_srgb_from_linearf (const Babl *trc_, float value)
+{
+  return babl_linear_to_gamma_2_2f (value);
+}
+
 static inline float _babl_trc_from_linearf (const Babl *trc_, float value)
 {
   BablTRC *trc = (void*)trc_;
-  switch (trc->type)
-  {
-    case BABL_TRC_LINEAR: return value;
-    case BABL_TRC_GAMMA:  return powf (value, 1.0f/trc->gamma);
-    case BABL_TRC_SRGB:   return babl_linear_to_gamma_2_2f (value);
-    case BABL_TRC_LUT:    return babl_trc_lut_from_linear (trc_, value);
-  }
-  return value;
+  return trc->fun_from_linear (trc_, value);
 }
 
 static inline float _babl_trc_to_linearf (const Babl *trc_, float value)
 {
   BablTRC *trc = (void*)trc_;
-  switch (trc->type)
-  {
-    case BABL_TRC_LINEAR: return value;
-    case BABL_TRC_GAMMA:  return powf (value, trc->gamma);
-    case BABL_TRC_SRGB:   return babl_gamma_2_2_to_linearf (value);
-    case BABL_TRC_LUT:    return babl_trc_lut_to_linear (trc_, value);
-  }
-  return value;
+  return trc->fun_to_linear (trc_, value);
 }
 
 void


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