[Mesa-dev] [PATCH 2/2] util: implement table-based + linear interpolation linear-to-srgb conversion

sroland at vmware.com sroland at vmware.com
Fri Aug 2 15:38:07 PDT 2013


From: Roland Scheidegger <sroland at vmware.com>

Should be much faster, seems to work in softpipe.
While here (also it's now disabled) fix up the pow factor - the former value
is what is in GL core it is however not actually accurate to fp32 standard
(as it is 1.0/2.4), and if someone would do all the accurate math there's no
reason to waste 8 mantissa bits or so...
---
 src/gallium/auxiliary/util/u_format_srgb.h  |   55 ++++++++++++++++++++++-----
 src/gallium/auxiliary/util/u_format_srgb.py |   33 ++++++++++++++++
 2 files changed, 78 insertions(+), 10 deletions(-)

diff --git a/src/gallium/auxiliary/util/u_format_srgb.h b/src/gallium/auxiliary/util/u_format_srgb.h
index 82ed957..f3e1b20 100644
--- a/src/gallium/auxiliary/util/u_format_srgb.h
+++ b/src/gallium/auxiliary/util/u_format_srgb.h
@@ -39,6 +39,7 @@
 
 
 #include "pipe/p_compiler.h"
+#include "u_pack_color.h"
 #include "u_math.h"
 
 
@@ -51,23 +52,57 @@ util_format_srgb_to_linear_8unorm_table[256];
 extern const uint8_t
 util_format_linear_to_srgb_8unorm_table[256];
 
+extern const unsigned
+util_format_linear_to_srgb_helper_table[104];
+
 
 /**
  * Convert a unclamped linear float to srgb value in the [0,255].
- * XXX this hasn't been tested (render to srgb surface).
- * XXX this needs optimization.
  */
 static INLINE uint8_t
 util_format_linear_float_to_srgb_8unorm(float x)
 {
-   if (x >= 1.0f)
-      return 255;
-   else if (x >= 0.0031308f)
-      return float_to_ubyte(1.055f * powf(x, 0.41666f) - 0.055f);
-   else if (x > 0.0f)
-      return float_to_ubyte(12.92f * x);
-   else
-      return 0;
+   if (0) {
+      if (x >= 1.0f)
+         return 255;
+      else if (x >= 0.0031308f)
+         return float_to_ubyte(1.055f * powf(x, 0.41666666f) - 0.055f);
+      else if (x > 0.0f)
+         return float_to_ubyte(12.92f * x);
+      else
+         return 0;
+   }
+   else {
+      /*
+       * This is taken from https://gist.github.com/rygorous/2203834
+       * Use LUT and do linear interpolation.
+       */
+      union fi almostone, minval, f;
+      unsigned tab, bias, scale, t;
+
+      almostone.ui = 0x3f7fffff;
+      minval.ui = (127-13) << 23;
+
+      /*
+       * Clamp to [2^(-13), 1-eps]; these two values map to 0 and 1, respectively.
+       * The tests are carefully written so that NaNs map to 0, same as in the
+       * reference implementation.
+       */
+      if (!(x > minval.f))
+         x = minval.f;
+      if (x > almostone.f)
+         x = almostone.f;
+
+      /* Do the table lookup and unpack bias, scale */
+      f.f = x;
+      tab = util_format_linear_to_srgb_helper_table[(f.ui - minval.ui) >> 20];
+      bias = (tab >> 16) << 9;
+      scale = tab & 0xffff;
+
+      /* Grab next-highest mantissa bits and perform linear interpolation */
+      t = (f.ui >> 12) & 0xff;
+      return (uint8_t) ((bias + scale*t) >> 16);
+   }
 }
 
 
diff --git a/src/gallium/auxiliary/util/u_format_srgb.py b/src/gallium/auxiliary/util/u_format_srgb.py
index cd63ae7..f95b22f 100644
--- a/src/gallium/auxiliary/util/u_format_srgb.py
+++ b/src/gallium/auxiliary/util/u_format_srgb.py
@@ -84,6 +84,39 @@ def generate_srgb_tables():
     print '};'
     print
 
+    # Hmm.
+    print 'const unsigned'
+    print 'util_format_linear_to_srgb_helper_table[104] = {'
+    print '   0x0073000d, 0x007a000d, 0x0080000d, 0x0087000d,'
+    print '   0x008d000d, 0x0094000d, 0x009a000d, 0x00a1000d,'
+    print '   0x00a7001a, 0x00b4001a, 0x00c1001a, 0x00ce001a,'
+    print '   0x00da001a, 0x00e7001a, 0x00f4001a, 0x0101001a,'
+    print '   0x010e0033, 0x01280033, 0x01410033, 0x015b0033,'
+    print '   0x01750033, 0x018f0033, 0x01a80033, 0x01c20033,'
+    print '   0x01dc0067, 0x020f0067, 0x02430067, 0x02760067,'
+    print '   0x02aa0067, 0x02dd0067, 0x03110067, 0x03440067,'
+    print '   0x037800ce, 0x03df00ce, 0x044600ce, 0x04ad00ce,'
+    print '   0x051400ce, 0x057b00c5, 0x05dd00bc, 0x063b00b5,'
+    print '   0x06970158, 0x07420142, 0x07e30130, 0x087b0120,'
+    print '   0x090b0112, 0x09940106, 0x0a1700fc, 0x0a9500f2,'
+    print '   0x0b0f01cb, 0x0bf401ae, 0x0ccb0195, 0x0d950180,'
+    print '   0x0e56016e, 0x0f0d015e, 0x0fbc0150, 0x10630143,'
+    print '   0x11070264, 0x1238023e, 0x1357021d, 0x14660201,'
+    print '   0x156601e9, 0x165a01d3, 0x174401c0, 0x182401af,'
+    print '   0x18fe0331, 0x1a9602fe, 0x1c1502d2, 0x1d7e02ad,'
+    print '   0x1ed4028d, 0x201a0270, 0x21520256, 0x227d0240,'
+    print '   0x239f0443, 0x25c003fe, 0x27bf03c4, 0x29a10392,'
+    print '   0x2b6a0367, 0x2d1d0341, 0x2ebe031f, 0x304d0300,'
+    print '   0x31d105b0, 0x34a80555, 0x37520507, 0x39d504c5,'
+    print '   0x3c37048b, 0x3e7c0458, 0x40a8042a, 0x42bd0401,'
+    print '   0x44c20798, 0x488e071e, 0x4c1c06b6, 0x4f76065d,'
+    print '   0x52a50610, 0x55ac05cc, 0x5892058f, 0x5b590559,'
+    print '   0x5e0c0a23, 0x631c0980, 0x67db08f6, 0x6c55087f,'
+    print '   0x70940818, 0x74a007bd, 0x787d076c, 0x7c330723,'
+    print '};'
+    print
+
+
 
 def main():
     print '/* This file is autogenerated by u_format_srgb.py. Do not edit directly. */'
-- 
1.7.9.5


More information about the mesa-dev mailing list