diff options
Diffstat (limited to 'src/gallium')
| -rw-r--r-- | src/gallium/auxiliary/util/u_tile.c | 196 | 
1 files changed, 196 insertions, 0 deletions
diff --git a/src/gallium/auxiliary/util/u_tile.c b/src/gallium/auxiliary/util/u_tile.c index 422bc76003..aa16fe771f 100644 --- a/src/gallium/auxiliary/util/u_tile.c +++ b/src/gallium/auxiliary/util/u_tile.c @@ -596,6 +596,184 @@ r16g16b16a16_put_tile_rgba(short *dst,  } +/*** PIPE_FORMAT_R8G8B8A8_SRGB ***/ + +/** + * Convert an 8-bit sRGB value from non-linear space to a + * linear RGB value in [0, 1]. + * Implemented with a 256-entry lookup table. + */ +static INLINE float +srgb_to_linear(ubyte cs8) +{ +   static float table[256]; +   static boolean tableReady = FALSE; +   if (!tableReady) { +      /* compute lookup table now */ +      uint i; +      for (i = 0; i < 256; i++) { +         const float cs = ubyte_to_float(i); +         if (cs <= 0.04045) { +            table[i] = cs / 12.92f; +         } +         else { +            table[i] = (float) powf((cs + 0.055) / 1.055, 2.4); +         } +      } +      tableReady = TRUE; +   } +   return table[cs8]; +} + + +/** + * Convert linear float in [0,1] to an srgb ubyte value in [0,255]. + * XXX this hasn't been tested (render to srgb surface). + * XXX this needs optimization. + */ +static INLINE ubyte +linear_to_srgb(float cl) +{ +   if (cl >= 1.0F) +      return 255; +   else if (cl >= 0.0031308F) +      return float_to_ubyte(1.055F * powf(cl, 0.41666F) - 0.055F); +   else if (cl > 0.0F) +      return float_to_ubyte(12.92F * cl); +   else +      return 0.0; +} + + +static void +a8r8g8b8_srgb_get_tile_rgba(const unsigned *src, +                            unsigned w, unsigned h, +                            float *p, +                            unsigned dst_stride) +{ +   unsigned i, j; + +   for (i = 0; i < h; i++) { +      float *pRow = p; +      for (j = 0; j < w; j++, pRow += 4) { +         const unsigned pixel = *src++; +         pRow[0] = srgb_to_linear((pixel >> 16) & 0xff); +         pRow[1] = srgb_to_linear((pixel >>  8) & 0xff); +         pRow[2] = srgb_to_linear((pixel >>  0) & 0xff); +         pRow[3] = ubyte_to_float((pixel >> 24) & 0xff); +      } +      p += dst_stride; +   } +} + +static void +a8r8g8b8_srgb_put_tile_rgba(unsigned *dst, +                            unsigned w, unsigned h, +                            const float *p, +                            unsigned src_stride) +{ +   unsigned i, j; + +   for (i = 0; i < h; i++) { +      const float *pRow = p; +      for (j = 0; j < w; j++, pRow += 4) { +         unsigned r, g, b, a; +         r = linear_to_srgb(pRow[0]); +         g = linear_to_srgb(pRow[1]); +         b = linear_to_srgb(pRow[2]); +         a = float_to_ubyte(pRow[3]); +         *dst++ = (a << 24) | (r << 16) | (g << 8) | b; +      } +      p += src_stride; +   } +} + + +/*** PIPE_FORMAT_A8L8_SRGB ***/ + +static void +a8l8_srgb_get_tile_rgba(const ushort *src, +                        unsigned w, unsigned h, +                        float *p, +                        unsigned dst_stride) +{ +   unsigned i, j; + +   for (i = 0; i < h; i++) { +      float *pRow = p; +      for (j = 0; j < w; j++, pRow += 4) { +         ushort p = *src++; +         pRow[0] = +         pRow[1] = +         pRow[2] = srgb_to_linear(p & 0xff); +         pRow[3] = ubyte_to_float(p >> 8); +      } +      p += dst_stride; +   } +} + +static void +a8l8_srgb_put_tile_rgba(ushort *dst, +                        unsigned w, unsigned h, +                        const float *p, +                        unsigned src_stride) +{ +   unsigned i, j; + +   for (i = 0; i < h; i++) { +      const float *pRow = p; +      for (j = 0; j < w; j++, pRow += 4) { +         unsigned r, a; +         r = linear_to_srgb(pRow[0]); +         a = float_to_ubyte(pRow[3]); +         *dst++ = (a << 8) | r; +      } +      p += src_stride; +   } +} + + +/*** PIPE_FORMAT_L8_SRGB ***/ + +static void +l8_srgb_get_tile_rgba(const ubyte *src, +                      unsigned w, unsigned h, +                      float *p, +                      unsigned dst_stride) +{ +   unsigned i, j; + +   for (i = 0; i < h; i++) { +      float *pRow = p; +      for (j = 0; j < w; j++, src++, pRow += 4) { +         pRow[0] = +         pRow[1] = +         pRow[2] = srgb_to_linear(*src); +         pRow[3] = 1.0; +      } +      p += dst_stride; +   } +} + +static void +l8_srgb_put_tile_rgba(ubyte *dst, +                      unsigned w, unsigned h, +                      const float *p, +                      unsigned src_stride) +{ +   unsigned i, j; + +   for (i = 0; i < h; i++) { +      const float *pRow = p; +      for (j = 0; j < w; j++, pRow += 4) { +         unsigned r; +         r = linear_to_srgb(pRow[0]); +         *dst++ = (ubyte) r; +      } +      p += src_stride; +   } +} +  /*** PIPE_FORMAT_I8_UNORM ***/ @@ -946,6 +1124,15 @@ pipe_tile_raw_to_rgba(enum pipe_format format,     case PIPE_FORMAT_R16G16B16A16_SNORM:        r16g16b16a16_get_tile_rgba((short *) src, w, h, dst, dst_stride);        break; +   case PIPE_FORMAT_A8R8G8B8_SRGB: +      a8r8g8b8_srgb_get_tile_rgba((unsigned *) src, w, h, dst, dst_stride); +      break; +   case PIPE_FORMAT_A8L8_SRGB: +      a8l8_srgb_get_tile_rgba((ushort *) src, w, h, dst, dst_stride); +      break; +   case PIPE_FORMAT_L8_SRGB: +      l8_srgb_get_tile_rgba((ubyte *) src, w, h, dst, dst_stride); +      break;     case PIPE_FORMAT_Z16_UNORM:        z16_get_tile_rgba((ushort *) src, w, h, dst, dst_stride);        break; @@ -1059,6 +1246,15 @@ pipe_put_tile_rgba(struct pipe_transfer *pt,     case PIPE_FORMAT_R16G16B16A16_SNORM:        r16g16b16a16_put_tile_rgba((short *) packed, w, h, p, src_stride);        break; +   case PIPE_FORMAT_A8R8G8B8_SRGB: +      a8r8g8b8_srgb_put_tile_rgba((unsigned *) packed, w, h, p, src_stride); +      break; +   case PIPE_FORMAT_A8L8_SRGB: +      a8l8_srgb_put_tile_rgba((ushort *) packed, w, h, p, src_stride); +      break; +   case PIPE_FORMAT_L8_SRGB: +      l8_srgb_put_tile_rgba((ubyte *) packed, w, h, p, src_stride); +      break;     case PIPE_FORMAT_Z16_UNORM:        /*z16_put_tile_rgba((ushort *) packed, w, h, p, src_stride);*/        break;  | 
