gallivm: Move gather functions to its own module.
[mesa.git] / src / gallium / auxiliary / gallivm / lp_bld_format_yuv.c
1 /**************************************************************************
2 *
3 * Copyright 2010 VMware, Inc.
4 * All Rights Reserved.
5 *
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:
13 *
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.
21 *
22 * The above copyright notice and this permission notice (including the
23 * next paragraph) shall be included in all copies or substantial portions
24 * of the Software.
25 *
26 **************************************************************************/
27
28
29 /**
30 * @file
31 * YUV pixel format manipulation.
32 *
33 * @author Jose Fonseca <jfonseca@vmware.com>
34 */
35
36
37 #include "util/u_format.h"
38 #include "util/u_memory.h"
39 #include "util/u_math.h"
40 #include "util/u_string.h"
41
42 #include "lp_bld_arit.h"
43 #include "lp_bld_init.h"
44 #include "lp_bld_type.h"
45 #include "lp_bld_const.h"
46 #include "lp_bld_conv.h"
47 #include "lp_bld_gather.h"
48 #include "lp_bld_format.h"
49
50
51 /**
52 * Extract Y, U, V channels from packed UYVY.
53 * @param packed is a <n x i32> vector with the packed UYVY blocks
54 * @param i is a <n x i32> vector with the x pixel coordinate (0 or 1)
55 */
56 static void
57 uyvy_to_yuv_soa(LLVMBuilderRef builder,
58 unsigned n,
59 LLVMValueRef packed,
60 LLVMValueRef i,
61 LLVMValueRef *y,
62 LLVMValueRef *u,
63 LLVMValueRef *v)
64 {
65 struct lp_type type;
66 LLVMValueRef shift, mask;
67
68 memset(&type, 0, sizeof type);
69 type.width = 32;
70 type.length = n;
71
72 assert(lp_check_value(type, packed));
73 assert(lp_check_value(type, i));
74
75 /*
76 * y = (uyvy >> 16*i) & 0xff
77 * u = (uyvy ) & 0xff
78 * v = (uyvy >> 16 ) & 0xff
79 */
80
81 shift = LLVMBuildMul(builder, i, lp_build_const_int_vec(type, 16), "");
82 shift = LLVMBuildAdd(builder, shift, lp_build_const_int_vec(type, 8), "");
83 *y = LLVMBuildLShr(builder, packed, shift, "");
84 *u = packed;
85 *v = LLVMBuildLShr(builder, packed, lp_build_const_int_vec(type, 16), "");
86
87 mask = lp_build_const_int_vec(type, 0xff);
88
89 *y = LLVMBuildAnd(builder, *y, mask, "y");
90 *u = LLVMBuildAnd(builder, *u, mask, "u");
91 *v = LLVMBuildAnd(builder, *v, mask, "v");
92 }
93
94
95 /**
96 * Extract Y, U, V channels from packed YUYV.
97 * @param packed is a <n x i32> vector with the packed YUYV blocks
98 * @param i is a <n x i32> vector with the x pixel coordinate (0 or 1)
99 */
100 static void
101 yuyv_to_yuv_soa(LLVMBuilderRef builder,
102 unsigned n,
103 LLVMValueRef packed,
104 LLVMValueRef i,
105 LLVMValueRef *y,
106 LLVMValueRef *u,
107 LLVMValueRef *v)
108 {
109 struct lp_type type;
110 LLVMValueRef shift, mask;
111
112 memset(&type, 0, sizeof type);
113 type.width = 32;
114 type.length = n;
115
116 assert(lp_check_value(type, packed));
117 assert(lp_check_value(type, i));
118
119 /*
120 * y = (yuyv >> 16*i) & 0xff
121 * u = (yuyv >> 8 ) & 0xff
122 * v = (yuyv >> 24 ) & 0xff
123 */
124
125 shift = LLVMBuildMul(builder, i, lp_build_const_int_vec(type, 16), "");
126 *y = LLVMBuildLShr(builder, packed, shift, "");
127 *u = LLVMBuildLShr(builder, packed, lp_build_const_int_vec(type, 8), "");
128 *v = LLVMBuildLShr(builder, packed, lp_build_const_int_vec(type, 24), "");
129
130 mask = lp_build_const_int_vec(type, 0xff);
131
132 *y = LLVMBuildAnd(builder, *y, mask, "y");
133 *u = LLVMBuildAnd(builder, *u, mask, "u");
134 *v = LLVMBuildAnd(builder, *v, mask, "v");
135 }
136
137
138 static INLINE void
139 yuv_to_rgb_soa(LLVMBuilderRef builder,
140 unsigned n,
141 LLVMValueRef y, LLVMValueRef u, LLVMValueRef v,
142 LLVMValueRef *r, LLVMValueRef *g, LLVMValueRef *b)
143 {
144 struct lp_type type;
145 struct lp_build_context bld;
146
147 LLVMValueRef c0;
148 LLVMValueRef c8;
149 LLVMValueRef c16;
150 LLVMValueRef c128;
151 LLVMValueRef c255;
152
153 LLVMValueRef cy;
154 LLVMValueRef cug;
155 LLVMValueRef cub;
156 LLVMValueRef cvr;
157 LLVMValueRef cvg;
158
159 memset(&type, 0, sizeof type);
160 type.sign = TRUE;
161 type.width = 32;
162 type.length = n;
163
164 lp_build_context_init(&bld, builder, type);
165
166 assert(lp_check_value(type, y));
167 assert(lp_check_value(type, u));
168 assert(lp_check_value(type, v));
169
170 /*
171 * Constants
172 */
173
174 c0 = lp_build_const_int_vec(type, 0);
175 c8 = lp_build_const_int_vec(type, 8);
176 c16 = lp_build_const_int_vec(type, 16);
177 c128 = lp_build_const_int_vec(type, 128);
178 c255 = lp_build_const_int_vec(type, 255);
179
180 cy = lp_build_const_int_vec(type, 298);
181 cug = lp_build_const_int_vec(type, -100);
182 cub = lp_build_const_int_vec(type, 516);
183 cvr = lp_build_const_int_vec(type, 409);
184 cvg = lp_build_const_int_vec(type, -208);
185
186 /*
187 * y -= 16;
188 * u -= 128;
189 * v -= 128;
190 */
191
192 y = LLVMBuildSub(builder, y, c16, "");
193 u = LLVMBuildSub(builder, u, c128, "");
194 v = LLVMBuildSub(builder, v, c128, "");
195
196 /*
197 * r = 298 * _y + 409 * _v + 128;
198 * g = 298 * _y - 100 * _u - 208 * _v + 128;
199 * b = 298 * _y + 516 * _u + 128;
200 */
201
202 y = LLVMBuildMul(builder, y, cy, "");
203 y = LLVMBuildAdd(builder, y, c128, "");
204
205 *r = LLVMBuildMul(builder, v, cvr, "");
206 *g = LLVMBuildAdd(builder,
207 LLVMBuildMul(builder, u, cug, ""),
208 LLVMBuildMul(builder, v, cvg, ""),
209 "");
210 *b = LLVMBuildMul(builder, u, cub, "");
211
212 *r = LLVMBuildAdd(builder, *r, y, "");
213 *g = LLVMBuildAdd(builder, *g, y, "");
214 *b = LLVMBuildAdd(builder, *b, y, "");
215
216 /*
217 * r >>= 8;
218 * g >>= 8;
219 * b >>= 8;
220 */
221
222 *r = LLVMBuildAShr(builder, *r, c8, "r");
223 *g = LLVMBuildAShr(builder, *g, c8, "g");
224 *b = LLVMBuildAShr(builder, *b, c8, "b");
225
226 /*
227 * Clamp
228 */
229
230 *r = lp_build_clamp(&bld, *r, c0, c255);
231 *g = lp_build_clamp(&bld, *g, c0, c255);
232 *b = lp_build_clamp(&bld, *b, c0, c255);
233 }
234
235
236 static LLVMValueRef
237 rgb_to_rgba_aos(LLVMBuilderRef builder,
238 unsigned n,
239 LLVMValueRef r, LLVMValueRef g, LLVMValueRef b)
240 {
241 struct lp_type type;
242 LLVMValueRef a;
243 LLVMValueRef rgba;
244
245 memset(&type, 0, sizeof type);
246 type.sign = TRUE;
247 type.width = 32;
248 type.length = n;
249
250 assert(lp_check_value(type, r));
251 assert(lp_check_value(type, g));
252 assert(lp_check_value(type, b));
253
254 /*
255 * Make a 4 x unorm8 vector
256 */
257
258 r = r;
259 g = LLVMBuildShl(builder, g, lp_build_const_int_vec(type, 8), "");
260 b = LLVMBuildShl(builder, b, lp_build_const_int_vec(type, 16), "");
261 a = lp_build_const_int_vec(type, 0xff000000);
262
263 rgba = r;
264 rgba = LLVMBuildOr(builder, rgba, g, "");
265 rgba = LLVMBuildOr(builder, rgba, b, "");
266 rgba = LLVMBuildOr(builder, rgba, a, "");
267
268 rgba = LLVMBuildBitCast(builder, rgba,
269 LLVMVectorType(LLVMInt8Type(), 4*n), "");
270
271 return rgba;
272 }
273
274
275 /**
276 * Convert from <n x i32> packed UYVY to <4n x i8> RGBA AoS
277 */
278 static LLVMValueRef
279 uyvy_to_rgba_aos(LLVMBuilderRef builder,
280 unsigned n,
281 LLVMValueRef packed,
282 LLVMValueRef i)
283 {
284 LLVMValueRef y, u, v;
285 LLVMValueRef r, g, b;
286 LLVMValueRef rgba;
287
288 uyvy_to_yuv_soa(builder, n, packed, i, &y, &u, &v);
289 yuv_to_rgb_soa(builder, n, y, u, v, &r, &g, &b);
290 rgba = rgb_to_rgba_aos(builder, n, r, g, b);
291
292 return rgba;
293 }
294
295
296 /**
297 * Convert from <n x i32> packed YUYV to <4n x i8> RGBA AoS
298 */
299 static LLVMValueRef
300 yuyv_to_rgba_aos(LLVMBuilderRef builder,
301 unsigned n,
302 LLVMValueRef packed,
303 LLVMValueRef i)
304 {
305 LLVMValueRef y, u, v;
306 LLVMValueRef r, g, b;
307 LLVMValueRef rgba;
308
309 yuyv_to_yuv_soa(builder, n, packed, i, &y, &u, &v);
310 yuv_to_rgb_soa(builder, n, y, u, v, &r, &g, &b);
311 rgba = rgb_to_rgba_aos(builder, n, r, g, b);
312
313 return rgba;
314 }
315
316
317 /**
318 * Convert from <n x i32> packed RG_BG to <4n x i8> RGBA AoS
319 */
320 static LLVMValueRef
321 rgbg_to_rgba_aos(LLVMBuilderRef builder,
322 unsigned n,
323 LLVMValueRef packed,
324 LLVMValueRef i)
325 {
326 LLVMValueRef r, g, b;
327 LLVMValueRef rgba;
328
329 uyvy_to_yuv_soa(builder, n, packed, i, &g, &r, &b);
330 rgba = rgb_to_rgba_aos(builder, n, r, g, b);
331
332 return rgba;
333 }
334
335
336 /**
337 * Convert from <n x i32> packed GR_GB to <4n x i8> RGBA AoS
338 */
339 static LLVMValueRef
340 grgb_to_rgba_aos(LLVMBuilderRef builder,
341 unsigned n,
342 LLVMValueRef packed,
343 LLVMValueRef i)
344 {
345 LLVMValueRef r, g, b;
346 LLVMValueRef rgba;
347
348 yuyv_to_yuv_soa(builder, n, packed, i, &g, &r, &b);
349 rgba = rgb_to_rgba_aos(builder, n, r, g, b);
350
351 return rgba;
352 }
353
354
355 /**
356 * @param n is the number of pixels processed
357 * @param packed is a <n x i32> vector with the packed YUYV blocks
358 * @param i is a <n x i32> vector with the x pixel coordinate (0 or 1)
359 * @return a <4*n x i8> vector with the pixel RGBA values in AoS
360 */
361 LLVMValueRef
362 lp_build_unpack_subsampled_to_rgba_aos(LLVMBuilderRef builder,
363 const struct util_format_description *format_desc,
364 unsigned n,
365 LLVMValueRef packed,
366 LLVMValueRef i,
367 LLVMValueRef j)
368 {
369 LLVMValueRef rgba;
370
371 assert(format_desc->layout == UTIL_FORMAT_LAYOUT_SUBSAMPLED);
372
373 (void)j;
374
375 switch (format_desc->format) {
376 case PIPE_FORMAT_UYVY:
377 rgba = uyvy_to_rgba_aos(builder, n, packed, i);
378 break;
379 case PIPE_FORMAT_YUYV:
380 rgba = yuyv_to_rgba_aos(builder, n, packed, i);
381 break;
382 case PIPE_FORMAT_R8G8_B8G8_UNORM:
383 rgba = rgbg_to_rgba_aos(builder, n, packed, i);
384 break;
385 case PIPE_FORMAT_G8R8_G8B8_UNORM:
386 rgba = grgb_to_rgba_aos(builder, n, packed, i);
387 break;
388 default:
389 assert(0);
390 rgba = LLVMGetUndef(LLVMVectorType(LLVMInt8Type(), 4*n));
391 break;
392 }
393
394 return rgba;
395 }
396