util: Implement YUV and subsampled RGB format conversion.
authorJosé Fonseca <jfonseca@vmware.com>
Wed, 7 Apr 2010 18:47:24 +0000 (19:47 +0100)
committerJosé Fonseca <jfonseca@vmware.com>
Wed, 7 Apr 2010 18:47:24 +0000 (19:47 +0100)
progs/gallium/unit/u_format_test.c
src/gallium/auxiliary/Makefile
src/gallium/auxiliary/SConscript
src/gallium/auxiliary/util/u_format_pack.py
src/gallium/auxiliary/util/u_format_tests.c
src/gallium/auxiliary/util/u_format_yuv.c [new file with mode: 0644]
src/gallium/auxiliary/util/u_format_yuv.h [new file with mode: 0644]

index 53e028482bb13aba2da293bdafe77dc512e71f97..eeb853c30f3a39ea9a59d5f3bd56253129956104 100644 (file)
@@ -169,7 +169,9 @@ test_format_unpack_float(const struct util_format_description *format_desc,
    unsigned i, j, k;
    boolean success;
 
-   format_desc->unpack_float(&unpacked[0][0][0], sizeof unpacked[0], test->packed, 0, format_desc->block.width, format_desc->block.height);
+   format_desc->unpack_float(&unpacked[0][0][0], sizeof unpacked[0],
+                             test->packed, 0,
+                             format_desc->block.width, format_desc->block.height);
 
    success = TRUE;
    for (i = 0; i < format_desc->block.height; ++i) {
@@ -219,7 +221,9 @@ test_format_pack_float(const struct util_format_description *format_desc,
       }
    }
 
-   format_desc->pack_float(packed, 0, &unpacked[0][0][0], sizeof unpacked[0], format_desc->block.width, format_desc->block.height);
+   format_desc->pack_float(packed, 0,
+                           &unpacked[0][0][0], sizeof unpacked[0],
+                           format_desc->block.width, format_desc->block.height);
 
    success = TRUE;
    for (i = 0; i < format_desc->block.bits/8; ++i)
@@ -268,7 +272,9 @@ test_format_unpack_8unorm(const struct util_format_description *format_desc,
    unsigned i, j, k;
    boolean success;
 
-   format_desc->unpack_8unorm(&unpacked[0][0][0], sizeof unpacked[0], test->packed, 0, 1, 1);
+   format_desc->unpack_8unorm(&unpacked[0][0][0], sizeof unpacked[0],
+                              test->packed, 0,
+                              format_desc->block.width, format_desc->block.height);
 
    convert_float_to_8unorm(&expected[0][0][0], &test->unpacked[0][0][0]);
 
@@ -319,7 +325,9 @@ test_format_pack_8unorm(const struct util_format_description *format_desc,
 
    memset(packed, 0, sizeof packed);
 
-   format_desc->pack_8unorm(packed, 0, &unpacked[0][0][0], sizeof unpacked[0], 1, 1);
+   format_desc->pack_8unorm(packed, 0,
+                            &unpacked[0][0][0], sizeof unpacked[0],
+                            format_desc->block.width, format_desc->block.height);
 
    success = TRUE;
    for (i = 0; i < format_desc->block.bits/8; ++i)
index e6cc70e4cfbf380174821c7e56a90fe63f64df63..0015ccd715c3987e4b0536547ecc40e6fabca0f7 100644 (file)
@@ -110,6 +110,7 @@ C_SOURCES = \
        util/u_format_srgb.c \
        util/u_format_table.c \
        util/u_format_tests.c \
+       util/u_format_yuv.c \
        util/u_gen_mipmap.c \
        util/u_half.c \
        util/u_handle_table.c \
index ca5fab6742aade10bafb0c5294ae62a10bf41a8e..b6dcd54a35d2aaef6a3e553743e73bfcf4f873d6 100644 (file)
@@ -159,6 +159,7 @@ source = [
     'util/u_format_srgb.c',
     'util/u_format_table.c',
     'util/u_format_tests.c',
+    'util/u_format_yuv.c',
     'util/u_gen_mipmap.c',
     'util/u_half.c',
     'util/u_handle_table.c',
index 3d89c68eaa7cae2d36197fe42e2d65912aee22d1..aaeb4ce34ca4064cac996487570beb27048f0ef1 100644 (file)
@@ -611,12 +611,16 @@ def generate_format_fetch(format, dst_channel, dst_native_type, dst_suffix):
     print
 
 
+def is_format_hand_written(format):
+    return format.layout in ('s3tc', 'subsampled')
+
 def generate(formats):
     print
     print '#include "pipe/p_compiler.h"'
     print '#include "u_math.h"'
     print '#include "u_format.h"'
     print '#include "u_format_srgb.h"'
+    print '#include "u_format_yuv.h"'
     print '#include "u_half.h"'
     print
 
@@ -629,7 +633,7 @@ def generate(formats):
     suffix = 'float'
 
     for format in formats:
-        if format.layout != 's3tc':
+        if not is_format_hand_written(format):
             generate_format_unpack(format, channel, native_type, suffix)
             generate_format_pack(format, channel, native_type, suffix)
             generate_format_fetch(format, channel, native_type, suffix)
@@ -639,7 +643,7 @@ def generate(formats):
     suffix = '8unorm'
 
     for format in formats:
-        if format.layout != 's3tc':
+        if not is_format_hand_written(format):
             generate_format_unpack(format, channel, native_type, suffix)
             generate_format_pack(format, channel, native_type, suffix)
 
index a16e676e38d17d94a63ce93cbb865969bb0bd46a..55ce283f026328903a16327f288dd0431d1f018b 100644 (file)
        {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, \
        {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}}
 
+#define UNPACKED_2x1(r0, g0, b0, a0, r1, g1, b1, a1) \
+      {{{r0, g0, b0, a0}, {r1, g1, b1, a1}, {0, 0, 0, 0}, {0, 0, 0, 0}}, \
+       {{ 0,  0,  0,  0}, { 0,  0,  0,  0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, \
+       {{ 0,  0,  0,  0}, { 0,  0,  0,  0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, \
+       {{ 0,  0,  0,  0}, { 0,  0,  0,  0}, {0, 0, 0, 0}, {0, 0, 0, 0}}}
+
 
 /**
  * Test cases.
@@ -294,9 +300,34 @@ util_format_test_cases[] =
     */
 
    /*
-    * TODO: YUV formats
+    * YUV formats
     */
 
+   {PIPE_FORMAT_R8G8_B8G8_UNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0x00, 0x00), UNPACKED_2x1(0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0)},
+   {PIPE_FORMAT_R8G8_B8G8_UNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0xff, 0x00, 0x00, 0x00), UNPACKED_2x1(1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0)},
+   {PIPE_FORMAT_R8G8_B8G8_UNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0xff, 0x00, 0x00), UNPACKED_2x1(0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0)},
+   {PIPE_FORMAT_R8G8_B8G8_UNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0xff, 0x00), UNPACKED_2x1(0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0)},
+   {PIPE_FORMAT_R8G8_B8G8_UNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0x00, 0xff), UNPACKED_2x1(0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0)},
+   {PIPE_FORMAT_R8G8_B8G8_UNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0xff, 0xff, 0xff, 0xff), UNPACKED_2x1(1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0)},
+
+   {PIPE_FORMAT_G8R8_G8B8_UNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0x00, 0x00), UNPACKED_2x1(0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0)},
+   {PIPE_FORMAT_G8R8_G8B8_UNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0xff, 0x00, 0x00, 0x00), UNPACKED_2x1(0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0)},
+   {PIPE_FORMAT_G8R8_G8B8_UNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0xff, 0x00, 0x00), UNPACKED_2x1(1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0)},
+   {PIPE_FORMAT_G8R8_G8B8_UNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0xff, 0x00), UNPACKED_2x1(0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0)},
+   {PIPE_FORMAT_G8R8_G8B8_UNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0x00, 0xff), UNPACKED_2x1(0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0)},
+   {PIPE_FORMAT_G8R8_G8B8_UNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0xff, 0xff, 0xff, 0xff), UNPACKED_2x1(1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0)},
+
+   /*
+    * TODO: Exercise the UV channels as well.
+    */
+   {PIPE_FORMAT_UYVY, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x80, 0x10, 0x80, 0x10), UNPACKED_2x1(0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0)},
+   {PIPE_FORMAT_UYVY, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x80, 0xeb, 0x80, 0x10), UNPACKED_2x1(1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0)},
+   {PIPE_FORMAT_UYVY, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x80, 0x10, 0x80, 0xeb), UNPACKED_2x1(0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0)},
+
+   {PIPE_FORMAT_YUYV, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x10, 0x80, 0x10, 0x80), UNPACKED_2x1(0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0)},
+   {PIPE_FORMAT_YUYV, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0xeb, 0x80, 0x10, 0x80), UNPACKED_2x1(1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0)},
+   {PIPE_FORMAT_YUYV, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x10, 0x80, 0xeb, 0x80), UNPACKED_2x1(0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0)},
+
    /*
     * Compressed formats
     */
diff --git a/src/gallium/auxiliary/util/u_format_yuv.c b/src/gallium/auxiliary/util/u_format_yuv.c
new file mode 100644 (file)
index 0000000..0847476
--- /dev/null
@@ -0,0 +1,1047 @@
+/**************************************************************************
+ *
+ * Copyright 2010 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ **************************************************************************/
+
+
+/**
+ * @file
+ * YUV and RGB subsampled formats conversion.
+ *
+ * @author Jose Fonseca <jfonseca@vmware.com>
+ */
+
+
+#include "util/u_format_yuv.h"
+
+
+void
+util_format_r8g8_b8g8_unorm_unpack_float(float *dst_row, unsigned dst_stride,
+                                         const uint8_t *src_row, unsigned src_stride,
+                                         unsigned width, unsigned height)
+{
+   unsigned x, y;
+
+   for (y = 0; y < height; y += 1) {
+      float *dst = dst_row;
+      const uint32_t *src = (const uint32_t *)src_row;
+      uint32_t value;
+      float r, g0, g1, b;
+
+      for (x = 0; x + 1 < width; x += 2) {
+         value = *src++;
+
+#ifdef PIPE_ARCH_BIG_ENDIAN
+         value = util_bswap32(value);
+#endif
+
+         r  = ubyte_to_float((value >>  0) & 0xff);
+         g0 = ubyte_to_float((value >>  8) & 0xff);
+         b  = ubyte_to_float((value >> 16) & 0xff);
+         g1 = ubyte_to_float((value >> 24) & 0xff);
+
+         dst[0] = r;    /* r */
+         dst[1] = g0;   /* g */
+         dst[2] = b;    /* b */
+         dst[3] = 1.0f; /* a */
+         dst += 4;
+
+         dst[0] = r;    /* r */
+         dst[1] = g1;   /* g */
+         dst[2] = b;    /* b */
+         dst[3] = 1.0f; /* a */
+         dst += 4;
+      }
+
+      if (x < width) {
+         value = *src;
+
+#ifdef PIPE_ARCH_BIG_ENDIAN
+         value = util_bswap32(value);
+#endif
+
+         r  = ubyte_to_float((value >>  0) & 0xff);
+         g0 = ubyte_to_float((value >>  8) & 0xff);
+         b  = ubyte_to_float((value >> 16) & 0xff);
+         g1 = ubyte_to_float((value >> 24) & 0xff);
+
+         dst[0] = r;    /* r */
+         dst[1] = g0;   /* g */
+         dst[2] = b;    /* b */
+         dst[3] = 1.0f; /* a */
+      }
+
+      src_row += src_stride/sizeof(*src_row);
+      dst_row += dst_stride/sizeof(*dst_row);
+   }
+}
+
+
+void
+util_format_r8g8_b8g8_unorm_unpack_8unorm(uint8_t *dst_row, unsigned dst_stride,
+                                          const uint8_t *src_row, unsigned src_stride,
+                                          unsigned width, unsigned height)
+{
+   unsigned x, y;
+
+   for (y = 0; y < height; y += 1) {
+      uint8_t *dst = dst_row;
+      const uint32_t *src = (const uint32_t *)src_row;
+      uint32_t value;
+      uint8_t r, g0, g1, b;
+
+      for (x = 0; x + 1 < width; x += 2) {
+         value = *src++;
+
+#ifdef PIPE_ARCH_BIG_ENDIAN
+         value = util_bswap32(value);
+#endif
+
+         r  = (value >>  0) & 0xff;
+         g0 = (value >>  8) & 0xff;
+         b  = (value >> 16) & 0xff;
+         g1 = (value >> 24) & 0xff;
+
+         dst[0] = r;    /* r */
+         dst[1] = g0;   /* g */
+         dst[2] = b;    /* b */
+         dst[3] = 0xff; /* a */
+         dst += 4;
+
+         dst[0] = r;    /* r */
+         dst[1] = g1;   /* g */
+         dst[2] = b;    /* b */
+         dst[3] = 0xff; /* a */
+         dst += 4;
+      }
+
+      if (x < width) {
+         value = *src;
+
+#ifdef PIPE_ARCH_BIG_ENDIAN
+         value = util_bswap32(value);
+#endif
+
+         r  = (value >>  0) & 0xff;
+         g0 = (value >>  8) & 0xff;
+         b  = (value >> 16) & 0xff;
+         g1 = (value >> 24) & 0xff;
+
+         dst[0] = r;    /* r */
+         dst[1] = g0;   /* g */
+         dst[2] = b;    /* b */
+         dst[3] = 0xff; /* a */
+      }
+
+      src_row += src_stride/sizeof(*src_row);
+      dst_row += dst_stride/sizeof(*dst_row);
+   }
+}
+
+
+void
+util_format_r8g8_b8g8_unorm_pack_float(uint8_t *dst_row, unsigned dst_stride,
+                                       const float *src_row, unsigned src_stride,
+                                       unsigned width, unsigned height)
+{
+   unsigned x, y;
+
+   for (y = 0; y < height; y += 1) {
+      const float *src = src_row;
+      uint32_t *dst = (uint32_t *)dst_row;
+      float r, g0, g1, b;
+      uint32_t value;
+
+      for (x = 0; x + 1 < width; x += 2) {
+         r  = 0.5f*(src[0] + src[4]);
+         g0 = src[1];
+         g1 = src[5];
+         b  = 0.5f*(src[2] + src[6]);
+
+         value  = float_to_ubyte(r);
+         value |= float_to_ubyte(g0) <<  8;
+         value |= float_to_ubyte(b)  << 16;
+         value |= float_to_ubyte(g1) << 24;
+
+#ifdef PIPE_ARCH_BIG_ENDIAN
+         value = util_bswap32(value);
+#endif
+
+         *dst++ = value;
+
+         src += 8;
+      }
+
+      if (x < width) {
+         r  = src[0];
+         g0 = src[1];
+         g1 = 0;
+         b  = src[2];
+
+         value  = float_to_ubyte(r);
+         value |= float_to_ubyte(g0) <<  8;
+         value |= float_to_ubyte(b)  << 16;
+         value |= float_to_ubyte(g1) << 24;
+
+#ifdef PIPE_ARCH_BIG_ENDIAN
+         value = util_bswap32(value);
+#endif
+
+         *dst = value;
+      }
+
+      dst_row += dst_stride/sizeof(*dst_row);
+      src_row += src_stride/sizeof(*src_row);
+   }
+}
+
+
+void
+util_format_r8g8_b8g8_unorm_pack_8unorm(uint8_t *dst_row, unsigned dst_stride,
+                                        const uint8_t *src_row, unsigned src_stride,
+                                        unsigned width, unsigned height)
+{
+   unsigned x, y;
+
+   for (y = 0; y < height; y += 1) {
+      const uint8_t *src = src_row;
+      uint32_t *dst = (uint32_t *)dst_row;
+      uint32_t r, g0, g1, b;
+      uint32_t value;
+
+      for (x = 0; x + 1 < width; x += 2) {
+         r  = (src[0] + src[4] + 1) >> 1;
+         g0 = src[1];
+         g1 = src[5];
+         b  = (src[2] + src[6] + 1) >> 1;
+
+         value  = r;
+         value |= g0 <<  8;
+         value |= b  << 16;
+         value |= g1 << 24;
+
+#ifdef PIPE_ARCH_BIG_ENDIAN
+         value = util_bswap32(value);
+#endif
+
+         *dst++ = value;
+
+         src += 8;
+      }
+
+      if (x < width) {
+         r  = src[0];
+         g0 = src[1];
+         g1 = 0;
+         b  = src[2];
+
+         value  = r;
+         value |= g0 <<  8;
+         value |= b  << 16;
+         value |= g1 << 24;
+
+#ifdef PIPE_ARCH_BIG_ENDIAN
+         value = util_bswap32(value);
+#endif
+
+         *dst = value;
+      }
+
+      dst_row += dst_stride/sizeof(*dst_row);
+      src_row += src_stride/sizeof(*src_row);
+   }
+}
+
+
+void
+util_format_r8g8_b8g8_unorm_fetch_float(float *dst, const uint8_t *src,
+                                        unsigned i, unsigned j)
+{
+   assert(i < 2);
+   assert(j < 1);
+
+   dst[0] = ubyte_to_float(src[0]);             /* r */
+   dst[1] = ubyte_to_float(src[1 + 2*i]);       /* g */
+   dst[2] = ubyte_to_float(src[2]);             /* b */
+   dst[3] = 1.0f;                               /* a */
+}
+
+
+void
+util_format_g8r8_g8b8_unorm_unpack_float(float *dst_row, unsigned dst_stride,
+                                         const uint8_t *src_row, unsigned src_stride,
+                                         unsigned width, unsigned height)
+{
+   unsigned x, y;
+
+   for (y = 0; y < height; y += 1) {
+      float *dst = dst_row;
+      const uint32_t *src = (const uint32_t *)src_row;
+      uint32_t value;
+      float r, g0, g1, b;
+
+      for (x = 0; x + 1 < width; x += 2) {
+         value = *src++;
+
+#ifdef PIPE_ARCH_BIG_ENDIAN
+         value = util_bswap32(value);
+#endif
+
+         g0 = ubyte_to_float((value >>  0) & 0xff);
+         r  = ubyte_to_float((value >>  8) & 0xff);
+         g1 = ubyte_to_float((value >> 16) & 0xff);
+         b  = ubyte_to_float((value >> 24) & 0xff);
+
+         dst[0] = r;    /* r */
+         dst[1] = g0;   /* g */
+         dst[2] = b;    /* b */
+         dst[3] = 1.0f; /* a */
+         dst += 4;
+
+         dst[0] = r;    /* r */
+         dst[1] = g1;   /* g */
+         dst[2] = b;    /* b */
+         dst[3] = 1.0f; /* a */
+         dst += 4;
+      }
+
+      if (x < width) {
+         value = *src;
+
+#ifdef PIPE_ARCH_BIG_ENDIAN
+         value = util_bswap32(value);
+#endif
+
+         g0 = ubyte_to_float((value >>  0) & 0xff);
+         r  = ubyte_to_float((value >>  8) & 0xff);
+         g1 = ubyte_to_float((value >> 16) & 0xff);
+         b  = ubyte_to_float((value >> 24) & 0xff);
+
+         dst[0] = r;    /* r */
+         dst[1] = g0;   /* g */
+         dst[2] = b;    /* b */
+         dst[3] = 1.0f; /* a */
+      }
+
+      src_row += src_stride/sizeof(*src_row);
+      dst_row += dst_stride/sizeof(*dst_row);
+   }
+}
+
+
+void
+util_format_g8r8_g8b8_unorm_unpack_8unorm(uint8_t *dst_row, unsigned dst_stride,
+                                          const uint8_t *src_row, unsigned src_stride,
+                                          unsigned width, unsigned height)
+{
+   unsigned x, y;
+
+   for (y = 0; y < height; y += 1) {
+      uint8_t *dst = dst_row;
+      const uint32_t *src = (const uint32_t *)src_row;
+      uint32_t value;
+      uint8_t r, g0, g1, b;
+
+      for (x = 0; x + 1 < width; x += 2) {
+         value = *src++;
+
+#ifdef PIPE_ARCH_BIG_ENDIAN
+         value = util_bswap32(value);
+#endif
+
+         g0 = (value >>  0) & 0xff;
+         r  = (value >>  8) & 0xff;
+         g1 = (value >> 16) & 0xff;
+         b  = (value >> 24) & 0xff;
+
+         dst[0] = r;    /* r */
+         dst[1] = g0;   /* g */
+         dst[2] = b;    /* b */
+         dst[3] = 0xff; /* a */
+         dst += 4;
+
+         dst[0] = r;    /* r */
+         dst[1] = g1;   /* g */
+         dst[2] = b;    /* b */
+         dst[3] = 0xff; /* a */
+         dst += 4;
+      }
+
+      if (x < width) {
+         value = *src;
+
+#ifdef PIPE_ARCH_BIG_ENDIAN
+         value = util_bswap32(value);
+#endif
+
+         g0 = (value >>  0) & 0xff;
+         r  = (value >>  8) & 0xff;
+         g1 = (value >> 16) & 0xff;
+         b  = (value >> 24) & 0xff;
+
+         dst[0] = r;    /* r */
+         dst[1] = g0;   /* g */
+         dst[2] = b;    /* b */
+         dst[3] = 0xff; /* a */
+      }
+
+      src_row += src_stride/sizeof(*src_row);
+      dst_row += dst_stride/sizeof(*dst_row);
+   }
+}
+
+
+void
+util_format_g8r8_g8b8_unorm_pack_float(uint8_t *dst_row, unsigned dst_stride,
+                                       const float *src_row, unsigned src_stride,
+                                       unsigned width, unsigned height)
+{
+   unsigned x, y;
+
+   for (y = 0; y < height; y += 1) {
+      const float *src = src_row;
+      uint32_t *dst = (uint32_t *)dst_row;
+      float r, g0, g1, b;
+      uint32_t value;
+
+      for (x = 0; x + 1 < width; x += 2) {
+         r  = 0.5f*(src[0] + src[4]);
+         g0 = src[1];
+         g1 = src[5];
+         b  = 0.5f*(src[2] + src[6]);
+
+         value  = float_to_ubyte(g0);
+         value |= float_to_ubyte(r)  <<  8;
+         value |= float_to_ubyte(g1) << 16;
+         value |= float_to_ubyte(b)  << 24;
+
+#ifdef PIPE_ARCH_BIG_ENDIAN
+         value = util_bswap32(value);
+#endif
+
+         *dst++ = value;
+
+         src += 8;
+      }
+
+      if (x < width) {
+         r  = src[0];
+         g0 = src[1];
+         g1 = 0;
+         b  = src[2];
+
+         value  = float_to_ubyte(g0);
+         value |= float_to_ubyte(r)  <<  8;
+         value |= float_to_ubyte(g1) << 16;
+         value |= float_to_ubyte(b)  << 24;
+
+#ifdef PIPE_ARCH_BIG_ENDIAN
+         value = util_bswap32(value);
+#endif
+
+         *dst = value;
+      }
+
+      dst_row += dst_stride/sizeof(*dst_row);
+      src_row += src_stride/sizeof(*src_row);
+   }
+}
+
+
+void
+util_format_g8r8_g8b8_unorm_pack_8unorm(uint8_t *dst_row, unsigned dst_stride,
+                                        const uint8_t *src_row, unsigned src_stride,
+                                        unsigned width, unsigned height)
+{
+   unsigned x, y;
+
+   for (y = 0; y < height; y += 1) {
+      const uint8_t *src = src_row;
+      uint32_t *dst = (uint32_t *)dst_row;
+      uint32_t r, g0, g1, b;
+      uint32_t value;
+
+      for (x = 0; x + 1 < width; x += 2) {
+         r  = (src[0] + src[4] + 1) >> 1;
+         g0 = src[1];
+         g1 = src[5];
+         b  = (src[2] + src[6] + 1) >> 1;
+
+         value  = g0;
+         value |= r  <<  8;
+         value |= g1 << 16;
+         value |= b  << 24;
+
+#ifdef PIPE_ARCH_BIG_ENDIAN
+         value = util_bswap32(value);
+#endif
+
+         *dst++ = value;
+
+         src += 8;
+      }
+
+      if (x < width) {
+         r  = src[0];
+         g0 = src[1];
+         g1 = 0;
+         b  = src[2];
+
+         value  = g0;
+         value |= r  <<  8;
+         value |= g1 << 16;
+         value |= b  << 24;
+
+#ifdef PIPE_ARCH_BIG_ENDIAN
+         value = util_bswap32(value);
+#endif
+
+         *dst = value;
+      }
+
+      dst_row += dst_stride/sizeof(*dst_row);
+      src_row += src_stride/sizeof(*src_row);
+   }
+}
+
+
+void
+util_format_g8r8_g8b8_unorm_fetch_float(float *dst, const uint8_t *src,
+                                        unsigned i, unsigned j)
+{
+   assert(i < 2);
+   assert(j < 1);
+
+   dst[0] = ubyte_to_float(src[1]);             /* r */
+   dst[1] = ubyte_to_float(src[0 + 2*i]);       /* g */
+   dst[2] = ubyte_to_float(src[3]);             /* b */
+   dst[3] = 1.0f;                               /* a */
+}
+
+
+void
+util_format_uyvy_unpack_float(float *dst_row, unsigned dst_stride,
+                              const uint8_t *src_row, unsigned src_stride,
+                              unsigned width, unsigned height)
+{
+   unsigned x, y;
+
+   for (y = 0; y < height; y += 1) {
+      float *dst = dst_row;
+      const uint32_t *src = (const uint32_t *)src_row;
+      uint32_t value;
+      uint8_t y0, y1, u, v;
+
+      for (x = 0; x + 1 < width; x += 2) {
+         value = *src++;
+
+#ifdef PIPE_ARCH_BIG_ENDIAN
+         value = util_bswap32(value);
+#endif
+
+         u  = (value >>  0) & 0xff;
+         y0 = (value >>  8) & 0xff;
+         v  = (value >> 16) & 0xff;
+         y1 = (value >> 24) & 0xff;
+
+         util_format_yuv_to_rgb_float(y0, u, v, &dst[0], &dst[1], &dst[2]);
+         dst[3] = 1.0f; /* a */
+         dst += 4;
+
+         util_format_yuv_to_rgb_float(y1, u, v, &dst[0], &dst[1], &dst[2]);
+         dst[3] = 1.0f; /* a */
+         dst += 4;
+      }
+
+      if (x < width) {
+         value = *src;
+
+#ifdef PIPE_ARCH_BIG_ENDIAN
+         value = util_bswap32(value);
+#endif
+
+         u  = (value >>  0) & 0xff;
+         y0 = (value >>  8) & 0xff;
+         v  = (value >> 16) & 0xff;
+         y1 = (value >> 24) & 0xff;
+
+         util_format_yuv_to_rgb_float(y0, u, v, &dst[0], &dst[1], &dst[2]);
+         dst[3] = 1.0f; /* a */
+      }
+
+      src_row += src_stride/sizeof(*src_row);
+      dst_row += dst_stride/sizeof(*dst_row);
+   }
+}
+
+
+void
+util_format_uyvy_unpack_8unorm(uint8_t *dst_row, unsigned dst_stride,
+                               const uint8_t *src_row, unsigned src_stride,
+                               unsigned width, unsigned height)
+{
+   unsigned x, y;
+
+   for (y = 0; y < height; y += 1) {
+      uint8_t *dst = dst_row;
+      const uint32_t *src = (const uint32_t *)src_row;
+      uint32_t value;
+      uint8_t y0, y1, u, v;
+
+      for (x = 0; x + 1 < width; x += 2) {
+         value = *src++;
+
+#ifdef PIPE_ARCH_BIG_ENDIAN
+         value = util_bswap32(value);
+#endif
+
+         u  = (value >>  0) & 0xff;
+         y0 = (value >>  8) & 0xff;
+         v  = (value >> 16) & 0xff;
+         y1 = (value >> 24) & 0xff;
+
+         util_format_yuv_to_rgb_8unorm(y0, u, v, &dst[0], &dst[1], &dst[2]);
+         dst[3] = 0xff; /* a */
+         dst += 4;
+
+         util_format_yuv_to_rgb_8unorm(y1, u, v, &dst[0], &dst[1], &dst[2]);
+         dst[3] = 0xff; /* a */
+         dst += 4;
+      }
+
+      if (x < width) {
+         value = *src;
+
+#ifdef PIPE_ARCH_BIG_ENDIAN
+         value = util_bswap32(value);
+#endif
+
+         u  = (value >>  0) & 0xff;
+         y0 = (value >>  8) & 0xff;
+         v  = (value >> 16) & 0xff;
+         y1 = (value >> 24) & 0xff;
+
+         util_format_yuv_to_rgb_8unorm(y0, u, v, &dst[0], &dst[1], &dst[2]);
+         dst[3] = 0xff; /* a */
+      }
+
+      src_row += src_stride/sizeof(*src_row);
+      dst_row += dst_stride/sizeof(*dst_row);
+   }
+}
+
+
+void
+util_format_uyvy_pack_float(uint8_t *dst_row, unsigned dst_stride,
+                            const float *src_row, unsigned src_stride,
+                            unsigned width, unsigned height)
+{
+   unsigned x, y;
+
+   for (y = 0; y < height; y += 1) {
+      const float *src = src_row;
+      uint32_t *dst = (uint32_t *)dst_row;
+      uint8_t y0, y1, u, v;
+      uint32_t value;
+
+      for (x = 0; x + 1 < width; x += 2) {
+         uint8_t y0, y1, u0, u1, v0, v1, u, v;
+
+         util_format_rgb_float_to_yuv(src[0], src[1], src[2],
+                                      &y0, &u0, &v0);
+         util_format_rgb_float_to_yuv(src[4], src[5], src[6],
+                                      &y1, &u1, &v1);
+
+         u = (u0 + u1 + 1) >> 1;
+         v = (v0 + v1 + 1) >> 1;
+
+         value  = u;
+         value |= y0 <<  8;
+         value |= v  << 16;
+         value |= y1 << 24;
+
+#ifdef PIPE_ARCH_BIG_ENDIAN
+         value = util_bswap32(value);
+#endif
+
+         *dst++ = value;
+
+         src += 8;
+      }
+
+      if (x < width) {
+         util_format_rgb_float_to_yuv(src[0], src[1], src[2],
+                                      &y0, &u, &v);
+         y1 = 0;
+
+         value  = u;
+         value |= y0 <<  8;
+         value |= v  << 16;
+         value |= y1 << 24;
+
+#ifdef PIPE_ARCH_BIG_ENDIAN
+         value = util_bswap32(value);
+#endif
+
+         *dst = value;
+      }
+
+      dst_row += dst_stride/sizeof(*dst_row);
+      src_row += src_stride/sizeof(*src_row);
+   }
+}
+
+
+void
+util_format_uyvy_pack_8unorm(uint8_t *dst_row, unsigned dst_stride,
+                             const uint8_t *src_row, unsigned src_stride,
+                             unsigned width, unsigned height)
+{
+   unsigned x, y;
+
+   for (y = 0; y < height; y += 1) {
+      const uint8_t *src = src_row;
+      uint32_t *dst = (uint32_t *)dst_row;
+      uint8_t y0, y1, u, v;
+      uint32_t value;
+
+      for (x = 0; x + 1 < width; x += 2) {
+         uint8_t y0, y1, u0, u1, v0, v1, u, v;
+
+         util_format_rgb_8unorm_to_yuv(src[0], src[1], src[2],
+                                       &y0, &u0, &v0);
+         util_format_rgb_8unorm_to_yuv(src[4], src[5], src[6],
+                                       &y1, &u1, &v1);
+
+         u = (u0 + u1 + 1) >> 1;
+         v = (v0 + v1 + 1) >> 1;
+
+         value  = u;
+         value |= y0 <<  8;
+         value |= v  << 16;
+         value |= y1 << 24;
+
+#ifdef PIPE_ARCH_BIG_ENDIAN
+         value = util_bswap32(value);
+#endif
+
+         *dst++ = value;
+
+         src += 8;
+      }
+
+      if (x < width) {
+         util_format_rgb_8unorm_to_yuv(src[0], src[1], src[2],
+                                       &y0, &u, &v);
+         y1 = 0;
+
+         value  = u;
+         value |= y0 <<  8;
+         value |= v  << 16;
+         value |= y1 << 24;
+
+#ifdef PIPE_ARCH_BIG_ENDIAN
+         value = util_bswap32(value);
+#endif
+
+         *dst = value;
+      }
+
+      dst_row += dst_stride/sizeof(*dst_row);
+      src_row += src_stride/sizeof(*src_row);
+   }
+}
+
+
+void
+util_format_uyvy_fetch_float(float *dst, const uint8_t *src,
+                             unsigned i, unsigned j)
+{
+   uint8_t y, u, v;
+
+   assert(i < 2);
+   assert(j < 1);
+
+   y = src[1 + i*2];
+   u = src[0];
+   v = src[2];
+
+   util_format_yuv_to_rgb_float(y, u, v, &dst[0], &dst[1], &dst[2]);
+
+   dst[3] = 1.0f;
+}
+
+
+void
+util_format_yuyv_unpack_float(float *dst_row, unsigned dst_stride,
+                              const uint8_t *src_row, unsigned src_stride,
+                              unsigned width, unsigned height)
+{
+   unsigned x, y;
+
+   for (y = 0; y < height; y += 1) {
+      float *dst = dst_row;
+      const uint32_t *src = (const uint32_t *)src_row;
+      uint32_t value;
+      uint8_t y0, y1, u, v;
+
+      for (x = 0; x + 1 < width; x += 2) {
+         value = *src++;
+
+#ifdef PIPE_ARCH_BIG_ENDIAN
+         value = util_bswap32(value);
+#endif
+
+         y0 = (value >>  0) & 0xff;
+         u  = (value >>  8) & 0xff;
+         y1 = (value >> 16) & 0xff;
+         v  = (value >> 24) & 0xff;
+
+         util_format_yuv_to_rgb_float(y0, u, v, &dst[0], &dst[1], &dst[2]);
+         dst[3] = 1.0f; /* a */
+         dst += 4;
+
+         util_format_yuv_to_rgb_float(y1, u, v, &dst[0], &dst[1], &dst[2]);
+         dst[3] = 1.0f; /* a */
+         dst += 4;
+      }
+
+      if (x < width) {
+         value = *src;
+
+#ifdef PIPE_ARCH_BIG_ENDIAN
+         value = util_bswap32(value);
+#endif
+
+         y0 = (value >>  0) & 0xff;
+         u  = (value >>  8) & 0xff;
+         y1 = (value >> 16) & 0xff;
+         v  = (value >> 24) & 0xff;
+
+         util_format_yuv_to_rgb_float(y0, u, v, &dst[0], &dst[1], &dst[2]);
+         dst[3] = 1.0f; /* a */
+      }
+
+      src_row += src_stride/sizeof(*src_row);
+      dst_row += dst_stride/sizeof(*dst_row);
+   }
+}
+
+
+void
+util_format_yuyv_unpack_8unorm(uint8_t *dst_row, unsigned dst_stride,
+                               const uint8_t *src_row, unsigned src_stride,
+                               unsigned width, unsigned height)
+{
+   unsigned x, y;
+
+   for (y = 0; y < height; y += 1) {
+      uint8_t *dst = dst_row;
+      const uint32_t *src = (const uint32_t *)src_row;
+      uint32_t value;
+      uint8_t y0, y1, u, v;
+
+      for (x = 0; x + 1 < width; x += 2) {
+         value = *src++;
+
+#ifdef PIPE_ARCH_BIG_ENDIAN
+         value = util_bswap32(value);
+#endif
+
+         y0 = (value >>  0) & 0xff;
+         u  = (value >>  8) & 0xff;
+         y1 = (value >> 16) & 0xff;
+         v  = (value >> 24) & 0xff;
+
+         util_format_yuv_to_rgb_8unorm(y0, u, v, &dst[0], &dst[1], &dst[2]);
+         dst[3] = 0xff; /* a */
+         dst += 4;
+
+         util_format_yuv_to_rgb_8unorm(y1, u, v, &dst[0], &dst[1], &dst[2]);
+         dst[3] = 0xff; /* a */
+         dst += 4;
+      }
+
+      if (x < width) {
+         value = *src;
+
+#ifdef PIPE_ARCH_BIG_ENDIAN
+         value = util_bswap32(value);
+#endif
+
+         y0 = (value >>  0) & 0xff;
+         u  = (value >>  8) & 0xff;
+         y1 = (value >> 16) & 0xff;
+         v  = (value >> 24) & 0xff;
+
+         util_format_yuv_to_rgb_8unorm(y0, u, v, &dst[0], &dst[1], &dst[2]);
+         dst[3] = 0xff; /* a */
+      }
+
+      src_row += src_stride/sizeof(*src_row);
+      dst_row += dst_stride/sizeof(*dst_row);
+   }
+}
+
+
+void
+util_format_yuyv_pack_float(uint8_t *dst_row, unsigned dst_stride,
+                            const float *src_row, unsigned src_stride,
+                            unsigned width, unsigned height)
+{
+   unsigned x, y;
+
+   for (y = 0; y < height; y += 1) {
+      const float *src = src_row;
+      uint32_t *dst = (uint32_t *)dst_row;
+      uint8_t y0, y1, u, v;
+      uint32_t value;
+
+      for (x = 0; x + 1 < width; x += 2) {
+         uint8_t y0, y1, u0, u1, v0, v1, u, v;
+
+         util_format_rgb_float_to_yuv(src[0], src[1], src[2],
+                                      &y0, &u0, &v0);
+         util_format_rgb_float_to_yuv(src[4], src[5], src[6],
+                                      &y1, &u1, &v1);
+
+         u = (u0 + u1 + 1) >> 1;
+         v = (v0 + v1 + 1) >> 1;
+
+         value  = y0;
+         value |= u  <<  8;
+         value |= y1 << 16;
+         value |= v  << 24;
+
+#ifdef PIPE_ARCH_BIG_ENDIAN
+         value = util_bswap32(value);
+#endif
+
+         *dst++ = value;
+
+         src += 8;
+      }
+
+      if (x < width) {
+         util_format_rgb_float_to_yuv(src[0], src[1], src[2],
+                                      &y0, &u, &v);
+         y1 = 0;
+
+         value  = y0;
+         value |= u  <<  8;
+         value |= y1 << 16;
+         value |= v  << 24;
+
+#ifdef PIPE_ARCH_BIG_ENDIAN
+         value = util_bswap32(value);
+#endif
+
+         *dst = value;
+      }
+
+      dst_row += dst_stride/sizeof(*dst_row);
+      src_row += src_stride/sizeof(*src_row);
+   }
+}
+
+
+void
+util_format_yuyv_pack_8unorm(uint8_t *dst_row, unsigned dst_stride,
+                             const uint8_t *src_row, unsigned src_stride,
+                             unsigned width, unsigned height)
+{
+   unsigned x, y;
+
+   for (y = 0; y < height; y += 1) {
+      const uint8_t *src = src_row;
+      uint32_t *dst = (uint32_t *)dst_row;
+      uint8_t y0, y1, u, v;
+      uint32_t value;
+
+      for (x = 0; x + 1 < width; x += 2) {
+         uint8_t y0, y1, u0, u1, v0, v1, u, v;
+
+         util_format_rgb_8unorm_to_yuv(src[0], src[1], src[2],
+                                       &y0, &u0, &v0);
+         util_format_rgb_8unorm_to_yuv(src[4], src[5], src[6],
+                                       &y1, &u1, &v1);
+
+         u = (u0 + u1 + 1) >> 1;
+         v = (v0 + v1 + 1) >> 1;
+
+         value  = y0;
+         value |= u  <<  8;
+         value |= y1 << 16;
+         value |= v  << 24;
+
+#ifdef PIPE_ARCH_BIG_ENDIAN
+         value = util_bswap32(value);
+#endif
+
+         *dst++ = value;
+
+         src += 8;
+      }
+
+      if (x < width) {
+         util_format_rgb_8unorm_to_yuv(src[0], src[1], src[2],
+                                       &y0, &u, &v);
+         y1 = 0;
+
+         value  = y0;
+         value |= u  <<  8;
+         value |= y1 << 16;
+         value |= v  << 24;
+
+#ifdef PIPE_ARCH_BIG_ENDIAN
+         value = util_bswap32(value);
+#endif
+
+         *dst = value;
+      }
+
+      dst_row += dst_stride/sizeof(*dst_row);
+      src_row += src_stride/sizeof(*src_row);
+   }
+}
+
+
+void
+util_format_yuyv_fetch_float(float *dst, const uint8_t *src,
+                             unsigned i, unsigned j)
+{
+   uint8_t y, u, v;
+
+   assert(i < 2);
+   assert(j < 1);
+
+   y = src[0 + i*2];
+   u = src[1];
+   v = src[3];
+
+   util_format_yuv_to_rgb_float(y, u, v, &dst[0], &dst[1], &dst[2]);
+
+   dst[3] = 1.0f;
+}
diff --git a/src/gallium/auxiliary/util/u_format_yuv.h b/src/gallium/auxiliary/util/u_format_yuv.h
new file mode 100644 (file)
index 0000000..10cf678
--- /dev/null
@@ -0,0 +1,223 @@
+/**************************************************************************
+ *
+ * Copyright 2010 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ **************************************************************************/
+
+
+/**
+ * @file
+ * YUV colorspace conversion.
+ *
+ * @author Brian Paul <brianp@vmware.com>
+ * @author Michal Krol <michal@vmware.com>
+ * @author Jose Fonseca <jfonseca@vmware.com>
+ *
+ * See also:
+ * - http://www.fourcc.org/fccyvrgb.php
+ * - http://msdn.microsoft.com/en-us/library/ms893078
+ * - http://en.wikipedia.org/wiki/YUV
+ */
+
+
+#ifndef U_FORMAT_YUV_H_
+#define U_FORMAT_YUV_H_
+
+
+#include "pipe/p_compiler.h"
+#include "u_math.h"
+
+
+/*
+ * TODO: Ensure we use consistent and right floating formulas, with enough
+ * precision in the coefficients.
+ */
+
+static INLINE void
+util_format_rgb_float_to_yuv(float r, float g, float b,
+                             uint8_t *y, uint8_t *u, uint8_t *v)
+{
+   const float _r = CLAMP(r, 0.0f, 1.0f);
+   const float _g = CLAMP(g, 0.0f, 1.0f);
+   const float _b = CLAMP(b, 0.0f, 1.0f);
+
+   const float scale = 255.0f;
+
+   const int _y = scale * ( (0.257f * _r) + (0.504f * _g) + (0.098f * _b));
+   const int _u = scale * (-(0.148f * _r) - (0.291f * _g) + (0.439f * _b));
+   const int _v = scale * ( (0.439f * _r) - (0.368f * _g) - (0.071f * _b));
+
+   *y = _y + 16; 
+   *u = _u + 128; 
+   *v = _v + 128; 
+}
+
+
+static INLINE void
+util_format_yuv_to_rgb_float(uint8_t y, uint8_t u, uint8_t v,
+                             float *r, float *g, float *b)
+{
+   const int _y = y - 16;
+   const int _u = u - 128;
+   const int _v = v - 128;
+
+   const float y_factor = 255.0f / 219.0f;
+
+   const float scale = 1.0f / 255.0f;
+
+   *r = scale * (y_factor * _y               + 1.596f * _v);
+   *g = scale * (y_factor * _y - 0.391f * _u - 0.813f * _v);
+   *b = scale * (y_factor * _y + 2.018f * _u              );
+}
+
+
+static INLINE void
+util_format_rgb_8unorm_to_yuv(uint8_t r, uint8_t g, uint8_t b,
+                             uint8_t *y, uint8_t *u, uint8_t *v)
+{
+   *y = ((  66 * r + 129 * g +  25 * b + 128) >> 8) +  16;
+   *u = (( -38 * r -  74 * g + 112 * b + 128) >> 8) + 128;
+   *v = (( 112 * r -  94 * g -  18 * b + 128) >> 8) + 128;
+}
+
+
+static INLINE void
+util_format_yuv_to_rgb_8unorm(uint8_t y, uint8_t u, uint8_t v,
+                              uint8_t *r, uint8_t *g, uint8_t *b)
+{
+   const int _y = y - 16;
+   const int _u = u - 128;
+   const int _v = v - 128;
+
+   const int _r = (298 * _y            + 409 * _v + 128) >> 8;
+   const int _g = (298 * _y - 100 * _u - 208 * _v + 128) >> 8;
+   const int _b = (298 * _y + 516 * _u            + 128) >> 8;
+
+   *r = CLAMP(_r, 0, 255);
+   *g = CLAMP(_g, 0, 255);
+   *b = CLAMP(_b, 0, 255);
+}
+
+
+
+void
+util_format_uyvy_unpack_float(float *dst_row, unsigned dst_stride,
+                              const uint8_t *src_row, unsigned src_stride,
+                              unsigned width, unsigned height);
+
+void
+util_format_uyvy_unpack_8unorm(uint8_t *dst_row, unsigned dst_stride,
+                               const uint8_t *src_row, unsigned src_stride,
+                               unsigned width, unsigned height);
+
+void
+util_format_uyvy_pack_float(uint8_t *dst_row, unsigned dst_stride,
+                            const float *src_row, unsigned src_stride,
+                            unsigned width, unsigned height);
+
+void
+util_format_uyvy_pack_8unorm(uint8_t *dst_row, unsigned dst_stride,
+                             const uint8_t *src_row, unsigned src_stride,
+                             unsigned width, unsigned height);
+
+void
+util_format_uyvy_fetch_float(float *dst, const uint8_t *src,
+                             unsigned i, unsigned j);
+
+void
+util_format_yuyv_unpack_float(float *dst_row, unsigned dst_stride,
+                              const uint8_t *src_row, unsigned src_stride,
+                              unsigned width, unsigned height);
+
+void
+util_format_yuyv_unpack_8unorm(uint8_t *dst_row, unsigned dst_stride,
+                               const uint8_t *src_row, unsigned src_stride,
+                               unsigned width, unsigned height);
+
+void
+util_format_yuyv_pack_float(uint8_t *dst_row, unsigned dst_stride,
+                            const float *src_row, unsigned src_stride,
+                            unsigned width, unsigned height);
+
+void
+util_format_yuyv_pack_8unorm(uint8_t *dst_row, unsigned dst_stride,
+                             const uint8_t *src_row, unsigned src_stride,
+                             unsigned width, unsigned height);
+
+void
+util_format_yuyv_fetch_float(float *dst, const uint8_t *src,
+                             unsigned i, unsigned j);
+
+
+void
+util_format_r8g8_b8g8_unorm_unpack_float(float *dst_row, unsigned dst_stride,
+                                         const uint8_t *src_row, unsigned src_stride,
+                                         unsigned width, unsigned height);
+
+void
+util_format_r8g8_b8g8_unorm_unpack_8unorm(uint8_t *dst_row, unsigned dst_stride,
+                                          const uint8_t *src_row, unsigned src_stride,
+                                          unsigned width, unsigned height);
+
+void
+util_format_r8g8_b8g8_unorm_pack_float(uint8_t *dst_row, unsigned dst_stride,
+                                       const float *src_row, unsigned src_stride,
+                                       unsigned width, unsigned height);
+
+void
+util_format_r8g8_b8g8_unorm_pack_8unorm(uint8_t *dst_row, unsigned dst_stride,
+                                        const uint8_t *src_row, unsigned src_stride,
+                                        unsigned width, unsigned height);
+
+void
+util_format_r8g8_b8g8_unorm_fetch_float(float *dst, const uint8_t *src,
+                                        unsigned i, unsigned j);
+
+void
+util_format_g8r8_g8b8_unorm_unpack_float(float *dst_row, unsigned dst_stride,
+                                         const uint8_t *src_row, unsigned src_stride,
+                                         unsigned width, unsigned height);
+
+void
+util_format_g8r8_g8b8_unorm_unpack_8unorm(uint8_t *dst_row, unsigned dst_stride,
+                                          const uint8_t *src_row, unsigned src_stride,
+                                          unsigned width, unsigned height);
+
+void
+util_format_g8r8_g8b8_unorm_pack_float(uint8_t *dst_row, unsigned dst_stride,
+                                       const float *src_row, unsigned src_stride,
+                                       unsigned width, unsigned height);
+
+void
+util_format_g8r8_g8b8_unorm_pack_8unorm(uint8_t *dst_row, unsigned dst_stride,
+                                        const uint8_t *src_row, unsigned src_stride,
+                                        unsigned width, unsigned height);
+
+void
+util_format_g8r8_g8b8_unorm_fetch_float(float *dst, const uint8_t *src,
+                                        unsigned i, unsigned j);
+
+
+
+#endif /* U_FORMAT_YUV_H_ */