1 /**************************************************************************
3 * Copyright 2010 VMware, Inc.
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
18 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20 * USE OR OTHER DEALINGS IN THE SOFTWARE.
22 * The above copyright notice and this permission notice (including the
23 * next paragraph) shall be included in all copies or substantial portions
26 **************************************************************************/
31 * YUV pixel format manipulation.
33 * @author Jose Fonseca <jfonseca@vmware.com>
37 #include "util/u_format.h"
39 #include "lp_bld_arit.h"
40 #include "lp_bld_type.h"
41 #include "lp_bld_const.h"
42 #include "lp_bld_conv.h"
43 #include "lp_bld_gather.h"
44 #include "lp_bld_format.h"
48 * Extract Y, U, V channels from packed UYVY.
49 * @param packed is a <n x i32> vector with the packed UYVY blocks
50 * @param i is a <n x i32> vector with the x pixel coordinate (0 or 1)
53 uyvy_to_yuv_soa(LLVMBuilderRef builder
,
62 LLVMValueRef shift
, mask
;
64 memset(&type
, 0, sizeof type
);
68 assert(lp_check_value(type
, packed
));
69 assert(lp_check_value(type
, i
));
72 * y = (uyvy >> 16*i) & 0xff
74 * v = (uyvy >> 16 ) & 0xff
77 shift
= LLVMBuildMul(builder
, i
, lp_build_const_int_vec(type
, 16), "");
78 shift
= LLVMBuildAdd(builder
, shift
, lp_build_const_int_vec(type
, 8), "");
79 *y
= LLVMBuildLShr(builder
, packed
, shift
, "");
81 *v
= LLVMBuildLShr(builder
, packed
, lp_build_const_int_vec(type
, 16), "");
83 mask
= lp_build_const_int_vec(type
, 0xff);
85 *y
= LLVMBuildAnd(builder
, *y
, mask
, "y");
86 *u
= LLVMBuildAnd(builder
, *u
, mask
, "u");
87 *v
= LLVMBuildAnd(builder
, *v
, mask
, "v");
92 * Extract Y, U, V channels from packed YUYV.
93 * @param packed is a <n x i32> vector with the packed YUYV blocks
94 * @param i is a <n x i32> vector with the x pixel coordinate (0 or 1)
97 yuyv_to_yuv_soa(LLVMBuilderRef builder
,
106 LLVMValueRef shift
, mask
;
108 memset(&type
, 0, sizeof type
);
112 assert(lp_check_value(type
, packed
));
113 assert(lp_check_value(type
, i
));
116 * y = (yuyv >> 16*i) & 0xff
117 * u = (yuyv >> 8 ) & 0xff
118 * v = (yuyv >> 24 ) & 0xff
121 shift
= LLVMBuildMul(builder
, i
, lp_build_const_int_vec(type
, 16), "");
122 *y
= LLVMBuildLShr(builder
, packed
, shift
, "");
123 *u
= LLVMBuildLShr(builder
, packed
, lp_build_const_int_vec(type
, 8), "");
124 *v
= LLVMBuildLShr(builder
, packed
, lp_build_const_int_vec(type
, 24), "");
126 mask
= lp_build_const_int_vec(type
, 0xff);
128 *y
= LLVMBuildAnd(builder
, *y
, mask
, "y");
129 *u
= LLVMBuildAnd(builder
, *u
, mask
, "u");
130 *v
= LLVMBuildAnd(builder
, *v
, mask
, "v");
135 yuv_to_rgb_soa(LLVMBuilderRef builder
,
137 LLVMValueRef y
, LLVMValueRef u
, LLVMValueRef v
,
138 LLVMValueRef
*r
, LLVMValueRef
*g
, LLVMValueRef
*b
)
141 struct lp_build_context bld
;
155 memset(&type
, 0, sizeof type
);
160 lp_build_context_init(&bld
, builder
, type
);
162 assert(lp_check_value(type
, y
));
163 assert(lp_check_value(type
, u
));
164 assert(lp_check_value(type
, v
));
170 c0
= lp_build_const_int_vec(type
, 0);
171 c8
= lp_build_const_int_vec(type
, 8);
172 c16
= lp_build_const_int_vec(type
, 16);
173 c128
= lp_build_const_int_vec(type
, 128);
174 c255
= lp_build_const_int_vec(type
, 255);
176 cy
= lp_build_const_int_vec(type
, 298);
177 cug
= lp_build_const_int_vec(type
, -100);
178 cub
= lp_build_const_int_vec(type
, 516);
179 cvr
= lp_build_const_int_vec(type
, 409);
180 cvg
= lp_build_const_int_vec(type
, -208);
188 y
= LLVMBuildSub(builder
, y
, c16
, "");
189 u
= LLVMBuildSub(builder
, u
, c128
, "");
190 v
= LLVMBuildSub(builder
, v
, c128
, "");
193 * r = 298 * _y + 409 * _v + 128;
194 * g = 298 * _y - 100 * _u - 208 * _v + 128;
195 * b = 298 * _y + 516 * _u + 128;
198 y
= LLVMBuildMul(builder
, y
, cy
, "");
199 y
= LLVMBuildAdd(builder
, y
, c128
, "");
201 *r
= LLVMBuildMul(builder
, v
, cvr
, "");
202 *g
= LLVMBuildAdd(builder
,
203 LLVMBuildMul(builder
, u
, cug
, ""),
204 LLVMBuildMul(builder
, v
, cvg
, ""),
206 *b
= LLVMBuildMul(builder
, u
, cub
, "");
208 *r
= LLVMBuildAdd(builder
, *r
, y
, "");
209 *g
= LLVMBuildAdd(builder
, *g
, y
, "");
210 *b
= LLVMBuildAdd(builder
, *b
, y
, "");
218 *r
= LLVMBuildAShr(builder
, *r
, c8
, "r");
219 *g
= LLVMBuildAShr(builder
, *g
, c8
, "g");
220 *b
= LLVMBuildAShr(builder
, *b
, c8
, "b");
226 *r
= lp_build_clamp(&bld
, *r
, c0
, c255
);
227 *g
= lp_build_clamp(&bld
, *g
, c0
, c255
);
228 *b
= lp_build_clamp(&bld
, *b
, c0
, c255
);
233 rgb_to_rgba_aos(LLVMBuilderRef builder
,
235 LLVMValueRef r
, LLVMValueRef g
, LLVMValueRef b
)
241 memset(&type
, 0, sizeof type
);
246 assert(lp_check_value(type
, r
));
247 assert(lp_check_value(type
, g
));
248 assert(lp_check_value(type
, b
));
251 * Make a 4 x unorm8 vector
255 g
= LLVMBuildShl(builder
, g
, lp_build_const_int_vec(type
, 8), "");
256 b
= LLVMBuildShl(builder
, b
, lp_build_const_int_vec(type
, 16), "");
257 a
= lp_build_const_int_vec(type
, 0xff000000);
260 rgba
= LLVMBuildOr(builder
, rgba
, g
, "");
261 rgba
= LLVMBuildOr(builder
, rgba
, b
, "");
262 rgba
= LLVMBuildOr(builder
, rgba
, a
, "");
264 rgba
= LLVMBuildBitCast(builder
, rgba
,
265 LLVMVectorType(LLVMInt8Type(), 4*n
), "");
272 * Convert from <n x i32> packed UYVY to <4n x i8> RGBA AoS
275 uyvy_to_rgba_aos(LLVMBuilderRef builder
,
280 LLVMValueRef y
, u
, v
;
281 LLVMValueRef r
, g
, b
;
284 uyvy_to_yuv_soa(builder
, n
, packed
, i
, &y
, &u
, &v
);
285 yuv_to_rgb_soa(builder
, n
, y
, u
, v
, &r
, &g
, &b
);
286 rgba
= rgb_to_rgba_aos(builder
, n
, r
, g
, b
);
293 * Convert from <n x i32> packed YUYV to <4n x i8> RGBA AoS
296 yuyv_to_rgba_aos(LLVMBuilderRef builder
,
301 LLVMValueRef y
, u
, v
;
302 LLVMValueRef r
, g
, b
;
305 yuyv_to_yuv_soa(builder
, n
, packed
, i
, &y
, &u
, &v
);
306 yuv_to_rgb_soa(builder
, n
, y
, u
, v
, &r
, &g
, &b
);
307 rgba
= rgb_to_rgba_aos(builder
, n
, r
, g
, b
);
314 * Convert from <n x i32> packed RG_BG to <4n x i8> RGBA AoS
317 rgbg_to_rgba_aos(LLVMBuilderRef builder
,
322 LLVMValueRef r
, g
, b
;
325 uyvy_to_yuv_soa(builder
, n
, packed
, i
, &g
, &r
, &b
);
326 rgba
= rgb_to_rgba_aos(builder
, n
, r
, g
, b
);
333 * Convert from <n x i32> packed GR_GB to <4n x i8> RGBA AoS
336 grgb_to_rgba_aos(LLVMBuilderRef builder
,
341 LLVMValueRef r
, g
, b
;
344 yuyv_to_yuv_soa(builder
, n
, packed
, i
, &g
, &r
, &b
);
345 rgba
= rgb_to_rgba_aos(builder
, n
, r
, g
, b
);
352 * @param n is the number of pixels processed
353 * @param packed is a <n x i32> vector with the packed YUYV blocks
354 * @param i is a <n x i32> vector with the x pixel coordinate (0 or 1)
355 * @return a <4*n x i8> vector with the pixel RGBA values in AoS
358 lp_build_fetch_subsampled_rgba_aos(LLVMBuilderRef builder
,
359 const struct util_format_description
*format_desc
,
361 LLVMValueRef base_ptr
,
369 assert(format_desc
->layout
== UTIL_FORMAT_LAYOUT_SUBSAMPLED
);
370 assert(format_desc
->block
.bits
== 32);
371 assert(format_desc
->block
.width
== 2);
372 assert(format_desc
->block
.height
== 1);
374 packed
= lp_build_gather(builder
, n
, 32, 32, base_ptr
, offset
);
378 switch (format_desc
->format
) {
379 case PIPE_FORMAT_UYVY
:
380 rgba
= uyvy_to_rgba_aos(builder
, n
, packed
, i
);
382 case PIPE_FORMAT_YUYV
:
383 rgba
= yuyv_to_rgba_aos(builder
, n
, packed
, i
);
385 case PIPE_FORMAT_R8G8_B8G8_UNORM
:
386 rgba
= rgbg_to_rgba_aos(builder
, n
, packed
, i
);
388 case PIPE_FORMAT_G8R8_G8B8_UNORM
:
389 rgba
= grgb_to_rgba_aos(builder
, n
, packed
, i
);
393 rgba
= LLVMGetUndef(LLVMVectorType(LLVMInt8Type(), 4*n
));