summaryrefslogtreecommitdiff
path: root/src/gallium
diff options
context:
space:
mode:
authorJosé Fonseca <jfonseca@vmware.com>2010-07-02 11:40:22 +0100
committerJosé Fonseca <jfonseca@vmware.com>2010-07-02 11:50:01 +0100
commit3cc4301c146e2a6e680939456ea3df4ec2d12e3e (patch)
tree8017d2aab10858445bd0bccbce83393b516eebd6 /src/gallium
parent37f4c2f906c8e2a6df609a190e4ca9ff028b265b (diff)
gallivm: Code generate YUV format unpacking.
Diffstat (limited to 'src/gallium')
-rw-r--r--src/gallium/auxiliary/Makefile1
-rw-r--r--src/gallium/auxiliary/SConscript1
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_format.h12
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_format_aos.c22
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_format_yuv.c395
5 files changed, 431 insertions, 0 deletions
diff --git a/src/gallium/auxiliary/Makefile b/src/gallium/auxiliary/Makefile
index 103d1d65880..36a46aee3ba 100644
--- a/src/gallium/auxiliary/Makefile
+++ b/src/gallium/auxiliary/Makefile
@@ -154,6 +154,7 @@ GALLIVM_SOURCES = \
gallivm/lp_bld_flow.c \
gallivm/lp_bld_format_aos.c \
gallivm/lp_bld_format_soa.c \
+ gallivm/lp_bld_format_yuv.c \
gallivm/lp_bld_init.c \
gallivm/lp_bld_intr.c \
gallivm/lp_bld_logic.c \
diff --git a/src/gallium/auxiliary/SConscript b/src/gallium/auxiliary/SConscript
index 1f400575a76..0b19444ad3b 100644
--- a/src/gallium/auxiliary/SConscript
+++ b/src/gallium/auxiliary/SConscript
@@ -203,6 +203,7 @@ if env['llvm']:
'gallivm/lp_bld_flow.c',
'gallivm/lp_bld_format_aos.c',
'gallivm/lp_bld_format_soa.c',
+ 'gallivm/lp_bld_format_yuv.c',
'gallivm/lp_bld_intr.c',
'gallivm/lp_bld_logic.c',
'gallivm/lp_bld_init.c',
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_format.h b/src/gallium/auxiliary/gallivm/lp_bld_format.h
index c335ca46a76..a853d7ca411 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_format.h
+++ b/src/gallium/auxiliary/gallivm/lp_bld_format.h
@@ -94,5 +94,17 @@ lp_build_fetch_rgba_soa(LLVMBuilderRef builder,
LLVMValueRef j,
LLVMValueRef rgba_out[4]);
+/*
+ * YUV
+ */
+
+
+LLVMValueRef
+lp_build_unpack_subsampled_to_rgba_aos(LLVMBuilderRef builder,
+ const struct util_format_description *format_desc,
+ unsigned n,
+ LLVMValueRef packed,
+ LLVMValueRef i,
+ LLVMValueRef j);
#endif /* !LP_BLD_FORMAT_H */
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_format_aos.c b/src/gallium/auxiliary/gallivm/lp_bld_format_aos.c
index bec2a80d767..cc72a31d725 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_format_aos.c
+++ b/src/gallium/auxiliary/gallivm/lp_bld_format_aos.c
@@ -366,6 +366,8 @@ lp_build_pack_rgba_aos(LLVMBuilderRef builder,
}
+
+
/**
* Fetch a pixel into a 4 float AoS.
*
@@ -429,6 +431,26 @@ lp_build_fetch_rgba_aos(LLVMBuilderRef builder,
return lp_build_unpack_rgba_aos(format_desc, &bld, packed);
}
}
+ else if (format_desc->layout == UTIL_FORMAT_LAYOUT_SUBSAMPLED) {
+ LLVMValueRef packed;
+ LLVMValueRef rgba;
+
+ ptr = LLVMBuildBitCast(builder, ptr,
+ LLVMPointerType(LLVMInt32Type(), 0),
+ "packed_ptr");
+
+ packed = LLVMBuildLoad(builder, ptr, "packed");
+
+ rgba = lp_build_unpack_subsampled_to_rgba_aos(builder, format_desc,
+ 1, packed, i, j);
+
+ lp_build_conv(builder,
+ lp_unorm8_vec4_type(),
+ type,
+ &rgba, 1, &rgba, 1);
+
+ return rgba;
+ }
else if (format_desc->fetch_rgba_float) {
/*
* Fallback to calling util_format_description::fetch_rgba_float.
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_format_yuv.c b/src/gallium/auxiliary/gallivm/lp_bld_format_yuv.c
new file mode 100644
index 00000000000..5fe2ab6e3b2
--- /dev/null
+++ b/src/gallium/auxiliary/gallivm/lp_bld_format_yuv.c
@@ -0,0 +1,395 @@
+/**************************************************************************
+ *
+ * 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 pixel format manipulation.
+ *
+ * @author Jose Fonseca <jfonseca@vmware.com>
+ */
+
+
+#include "util/u_format.h"
+#include "util/u_memory.h"
+#include "util/u_math.h"
+#include "util/u_string.h"
+
+#include "lp_bld_arit.h"
+#include "lp_bld_init.h"
+#include "lp_bld_type.h"
+#include "lp_bld_const.h"
+#include "lp_bld_conv.h"
+#include "lp_bld_format.h"
+
+
+/**
+ * Extract Y, U, V channels from packed UYVY.
+ * @param packed is a <n x i32> vector with the packed UYVY blocks
+ * @param i is a <n x i32> vector with the x pixel coordinate (0 or 1)
+ */
+static void
+uyvy_to_yuv_soa(LLVMBuilderRef builder,
+ unsigned n,
+ LLVMValueRef packed,
+ LLVMValueRef i,
+ LLVMValueRef *y,
+ LLVMValueRef *u,
+ LLVMValueRef *v)
+{
+ struct lp_type type;
+ LLVMValueRef shift, mask;
+
+ memset(&type, 0, sizeof type);
+ type.width = 32;
+ type.length = n;
+
+ assert(lp_check_value(type, packed));
+ assert(lp_check_value(type, i));
+
+ /*
+ * y = (uyvy >> 16*i) & 0xff
+ * u = (uyvy ) & 0xff
+ * v = (uyvy >> 16 ) & 0xff
+ */
+
+ shift = LLVMBuildMul(builder, i, lp_build_const_int_vec(type, 16), "");
+ shift = LLVMBuildAdd(builder, shift, lp_build_const_int_vec(type, 8), "");
+ *y = LLVMBuildLShr(builder, packed, shift, "");
+ *u = packed;
+ *v = LLVMBuildLShr(builder, packed, lp_build_const_int_vec(type, 16), "");
+
+ mask = lp_build_const_int_vec(type, 0xff);
+
+ *y = LLVMBuildAnd(builder, *y, mask, "y");
+ *u = LLVMBuildAnd(builder, *u, mask, "u");
+ *v = LLVMBuildAnd(builder, *v, mask, "v");
+}
+
+
+/**
+ * Extract Y, U, V channels from packed YUYV.
+ * @param packed is a <n x i32> vector with the packed YUYV blocks
+ * @param i is a <n x i32> vector with the x pixel coordinate (0 or 1)
+ */
+static void
+yuyv_to_yuv_soa(LLVMBuilderRef builder,
+ unsigned n,
+ LLVMValueRef packed,
+ LLVMValueRef i,
+ LLVMValueRef *y,
+ LLVMValueRef *u,
+ LLVMValueRef *v)
+{
+ struct lp_type type;
+ LLVMValueRef shift, mask;
+
+ memset(&type, 0, sizeof type);
+ type.width = 32;
+ type.length = n;
+
+ assert(lp_check_value(type, packed));
+ assert(lp_check_value(type, i));
+
+ /*
+ * y = (yuyv >> 16*i) & 0xff
+ * u = (yuyv >> 8 ) & 0xff
+ * v = (yuyv >> 24 ) & 0xff
+ */
+
+ shift = LLVMBuildMul(builder, i, lp_build_const_int_vec(type, 16), "");
+ *y = LLVMBuildLShr(builder, packed, shift, "");
+ *u = LLVMBuildLShr(builder, packed, lp_build_const_int_vec(type, 8), "");
+ *v = LLVMBuildLShr(builder, packed, lp_build_const_int_vec(type, 24), "");
+
+ mask = lp_build_const_int_vec(type, 0xff);
+
+ *y = LLVMBuildAnd(builder, *y, mask, "y");
+ *u = LLVMBuildAnd(builder, *u, mask, "u");
+ *v = LLVMBuildAnd(builder, *v, mask, "v");
+}
+
+
+static INLINE void
+yuv_to_rgb_soa(LLVMBuilderRef builder,
+ unsigned n,
+ LLVMValueRef y, LLVMValueRef u, LLVMValueRef v,
+ LLVMValueRef *r, LLVMValueRef *g, LLVMValueRef *b)
+{
+ struct lp_type type;
+ struct lp_build_context bld;
+
+ LLVMValueRef c0;
+ LLVMValueRef c8;
+ LLVMValueRef c16;
+ LLVMValueRef c128;
+ LLVMValueRef c255;
+
+ LLVMValueRef cy;
+ LLVMValueRef cug;
+ LLVMValueRef cub;
+ LLVMValueRef cvr;
+ LLVMValueRef cvg;
+
+ memset(&type, 0, sizeof type);
+ type.sign = TRUE;
+ type.width = 32;
+ type.length = n;
+
+ lp_build_context_init(&bld, builder, type);
+
+ assert(lp_check_value(type, y));
+ assert(lp_check_value(type, u));
+ assert(lp_check_value(type, v));
+
+ /*
+ * Constants
+ */
+
+ c0 = lp_build_const_int_vec(type, 0);
+ c8 = lp_build_const_int_vec(type, 8);
+ c16 = lp_build_const_int_vec(type, 16);
+ c128 = lp_build_const_int_vec(type, 128);
+ c255 = lp_build_const_int_vec(type, 255);
+
+ cy = lp_build_const_int_vec(type, 298);
+ cug = lp_build_const_int_vec(type, -100);
+ cub = lp_build_const_int_vec(type, 516);
+ cvr = lp_build_const_int_vec(type, 409);
+ cvg = lp_build_const_int_vec(type, -208);
+
+ /*
+ * y -= 16;
+ * u -= 128;
+ * v -= 128;
+ */
+
+ y = LLVMBuildSub(builder, y, c16, "");
+ u = LLVMBuildSub(builder, u, c128, "");
+ v = LLVMBuildSub(builder, v, c128, "");
+
+ /*
+ * r = 298 * _y + 409 * _v + 128;
+ * g = 298 * _y - 100 * _u - 208 * _v + 128;
+ * b = 298 * _y + 516 * _u + 128;
+ */
+
+ y = LLVMBuildMul(builder, y, cy, "");
+ y = LLVMBuildAdd(builder, y, c128, "");
+
+ *r = LLVMBuildMul(builder, v, cvr, "");
+ *g = LLVMBuildAdd(builder,
+ LLVMBuildMul(builder, u, cug, ""),
+ LLVMBuildMul(builder, v, cvg, ""),
+ "");
+ *b = LLVMBuildMul(builder, u, cub, "");
+
+ *r = LLVMBuildAdd(builder, *r, y, "");
+ *g = LLVMBuildAdd(builder, *g, y, "");
+ *b = LLVMBuildAdd(builder, *b, y, "");
+
+ /*
+ * r >>= 8;
+ * g >>= 8;
+ * b >>= 8;
+ */
+
+ *r = LLVMBuildAShr(builder, *r, c8, "r");
+ *g = LLVMBuildAShr(builder, *g, c8, "g");
+ *b = LLVMBuildAShr(builder, *b, c8, "b");
+
+ /*
+ * Clamp
+ */
+
+ *r = lp_build_clamp(&bld, *r, c0, c255);
+ *g = lp_build_clamp(&bld, *g, c0, c255);
+ *b = lp_build_clamp(&bld, *b, c0, c255);
+}
+
+
+static LLVMValueRef
+rgb_to_rgba_aos(LLVMBuilderRef builder,
+ unsigned n,
+ LLVMValueRef r, LLVMValueRef g, LLVMValueRef b)
+{
+ struct lp_type type;
+ LLVMValueRef a;
+ LLVMValueRef rgba;
+
+ memset(&type, 0, sizeof type);
+ type.sign = TRUE;
+ type.width = 32;
+ type.length = n;
+
+ assert(lp_check_value(type, r));
+ assert(lp_check_value(type, g));
+ assert(lp_check_value(type, b));
+
+ /*
+ * Make a 4 x unorm8 vector
+ */
+
+ r = r;
+ g = LLVMBuildShl(builder, g, lp_build_const_int_vec(type, 8), "");
+ b = LLVMBuildShl(builder, b, lp_build_const_int_vec(type, 16), "");
+ a = lp_build_const_int_vec(type, 0xff000000);
+
+ rgba = r;
+ rgba = LLVMBuildOr(builder, rgba, g, "");
+ rgba = LLVMBuildOr(builder, rgba, b, "");
+ rgba = LLVMBuildOr(builder, rgba, a, "");
+
+ rgba = LLVMBuildBitCast(builder, rgba,
+ LLVMVectorType(LLVMInt8Type(), 4*n), "");
+
+ return rgba;
+}
+
+
+/**
+ * Convert from <n x i32> packed UYVY to <4n x i8> RGBA AoS
+ */
+static LLVMValueRef
+uyvy_to_rgba_aos(LLVMBuilderRef builder,
+ unsigned n,
+ LLVMValueRef packed,
+ LLVMValueRef i)
+{
+ LLVMValueRef y, u, v;
+ LLVMValueRef r, g, b;
+ LLVMValueRef rgba;
+
+ uyvy_to_yuv_soa(builder, n, packed, i, &y, &u, &v);
+ yuv_to_rgb_soa(builder, n, y, u, v, &r, &g, &b);
+ rgba = rgb_to_rgba_aos(builder, n, r, g, b);
+
+ return rgba;
+}
+
+
+/**
+ * Convert from <n x i32> packed YUYV to <4n x i8> RGBA AoS
+ */
+static LLVMValueRef
+yuyv_to_rgba_aos(LLVMBuilderRef builder,
+ unsigned n,
+ LLVMValueRef packed,
+ LLVMValueRef i)
+{
+ LLVMValueRef y, u, v;
+ LLVMValueRef r, g, b;
+ LLVMValueRef rgba;
+
+ yuyv_to_yuv_soa(builder, n, packed, i, &y, &u, &v);
+ yuv_to_rgb_soa(builder, n, y, u, v, &r, &g, &b);
+ rgba = rgb_to_rgba_aos(builder, n, r, g, b);
+
+ return rgba;
+}
+
+
+/**
+ * Convert from <n x i32> packed RG_BG to <4n x i8> RGBA AoS
+ */
+static LLVMValueRef
+rgbg_to_rgba_aos(LLVMBuilderRef builder,
+ unsigned n,
+ LLVMValueRef packed,
+ LLVMValueRef i)
+{
+ LLVMValueRef r, g, b;
+ LLVMValueRef rgba;
+
+ uyvy_to_yuv_soa(builder, n, packed, i, &g, &r, &b);
+ rgba = rgb_to_rgba_aos(builder, n, r, g, b);
+
+ return rgba;
+}
+
+
+/**
+ * Convert from <n x i32> packed GR_GB to <4n x i8> RGBA AoS
+ */
+static LLVMValueRef
+grgb_to_rgba_aos(LLVMBuilderRef builder,
+ unsigned n,
+ LLVMValueRef packed,
+ LLVMValueRef i)
+{
+ LLVMValueRef r, g, b;
+ LLVMValueRef rgba;
+
+ yuyv_to_yuv_soa(builder, n, packed, i, &g, &r, &b);
+ rgba = rgb_to_rgba_aos(builder, n, r, g, b);
+
+ return rgba;
+}
+
+
+/**
+ * @param n is the number of pixels processed
+ * @param packed is a <n x i32> vector with the packed YUYV blocks
+ * @param i is a <n x i32> vector with the x pixel coordinate (0 or 1)
+ * @return a <4*n x i8> vector with the pixel RGBA values in AoS
+ */
+LLVMValueRef
+lp_build_unpack_subsampled_to_rgba_aos(LLVMBuilderRef builder,
+ const struct util_format_description *format_desc,
+ unsigned n,
+ LLVMValueRef packed,
+ LLVMValueRef i,
+ LLVMValueRef j)
+{
+ LLVMValueRef rgba;
+
+ assert(format_desc->layout == UTIL_FORMAT_LAYOUT_SUBSAMPLED);
+
+ (void)j;
+
+ switch (format_desc->format) {
+ case PIPE_FORMAT_UYVY:
+ rgba = uyvy_to_rgba_aos(builder, n, packed, i);
+ break;
+ case PIPE_FORMAT_YUYV:
+ rgba = yuyv_to_rgba_aos(builder, n, packed, i);
+ break;
+ case PIPE_FORMAT_R8G8_B8G8_UNORM:
+ rgba = rgbg_to_rgba_aos(builder, n, packed, i);
+ break;
+ case PIPE_FORMAT_G8R8_G8B8_UNORM:
+ rgba = grgb_to_rgba_aos(builder, n, packed, i);
+ break;
+ default:
+ assert(0);
+ rgba = LLVMGetUndef(LLVMVectorType(LLVMInt8Type(), 4*n));
+ break;
+ }
+
+ return rgba;
+}
+