mesa: remove a line of dead code
[mesa.git] / src / gallium / drivers / llvmpipe / lp_bld_format_aos.c
1 /**************************************************************************
2 *
3 * Copyright 2009 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 above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28 /**
29 * @file
30 * AoS pixel format manipulation.
31 *
32 * @author Jose Fonseca <jfonseca@vmware.com>
33 */
34
35
36 #include "util/u_cpu_detect.h"
37 #include "util/u_format.h"
38
39 #include "lp_bld_type.h"
40 #include "lp_bld_const.h"
41 #include "lp_bld_logic.h"
42 #include "lp_bld_swizzle.h"
43 #include "lp_bld_format.h"
44
45
46 /**
47 * Unpack a single pixel into its RGBA components.
48 *
49 * @param packed integer.
50 *
51 * @return RGBA in a 4 floats vector.
52 *
53 * XXX: This is mostly for reference and testing -- operating a single pixel at
54 * a time is rarely if ever needed.
55 */
56 LLVMValueRef
57 lp_build_unpack_rgba_aos(LLVMBuilderRef builder,
58 const struct util_format_description *desc,
59 LLVMValueRef packed)
60 {
61 LLVMTypeRef type;
62 LLVMValueRef shifted, casted, scaled, masked;
63 LLVMValueRef shifts[4];
64 LLVMValueRef masks[4];
65 LLVMValueRef scales[4];
66 LLVMValueRef swizzles[4];
67 LLVMValueRef aux[4];
68 bool normalized;
69 int empty_channel;
70 unsigned shift;
71 unsigned i;
72
73 /* FIXME: Support more formats */
74 assert(desc->layout == UTIL_FORMAT_LAYOUT_ARITH);
75 assert(desc->block.width == 1);
76 assert(desc->block.height == 1);
77 assert(desc->block.bits <= 32);
78
79 type = LLVMIntType(desc->block.bits);
80
81 /* Do the intermediate integer computations with 32bit integers since it
82 * matches floating point size */
83 if (desc->block.bits < 32)
84 packed = LLVMBuildZExt(builder, packed, LLVMInt32Type(), "");
85
86 /* Broadcast the packed value to all four channels */
87 packed = LLVMBuildInsertElement(builder,
88 LLVMGetUndef(LLVMVectorType(LLVMInt32Type(), 4)),
89 packed,
90 LLVMConstNull(LLVMInt32Type()),
91 "");
92 packed = LLVMBuildShuffleVector(builder,
93 packed,
94 LLVMGetUndef(LLVMVectorType(LLVMInt32Type(), 4)),
95 LLVMConstNull(LLVMVectorType(LLVMInt32Type(), 4)),
96 "");
97
98 /* Initialize vector constants */
99 normalized = FALSE;
100 empty_channel = -1;
101 shift = 0;
102 for (i = 0; i < 4; ++i) {
103 unsigned bits = desc->channel[i].size;
104
105 if (desc->channel[i].type == UTIL_FORMAT_TYPE_VOID) {
106 shifts[i] = LLVMGetUndef(LLVMInt32Type());
107 masks[i] = LLVMConstNull(LLVMInt32Type());
108 scales[i] = LLVMConstNull(LLVMFloatType());
109 empty_channel = i;
110 }
111 else {
112 unsigned mask = (1 << bits) - 1;
113
114 assert(desc->channel[i].type == UTIL_FORMAT_TYPE_UNSIGNED);
115 assert(bits < 32);
116
117 shifts[i] = LLVMConstInt(LLVMInt32Type(), shift, 0);
118 masks[i] = LLVMConstInt(LLVMInt32Type(), mask, 0);
119
120 if (desc->channel[i].normalized) {
121 scales[i] = LLVMConstReal(LLVMFloatType(), 1.0/mask);
122 normalized = TRUE;
123 }
124 else
125 scales[i] = LLVMConstReal(LLVMFloatType(), 1.0);
126 }
127
128 shift += bits;
129 }
130
131 shifted = LLVMBuildLShr(builder, packed, LLVMConstVector(shifts, 4), "");
132 masked = LLVMBuildAnd(builder, shifted, LLVMConstVector(masks, 4), "");
133 // UIToFP can't be expressed in SSE2
134 casted = LLVMBuildSIToFP(builder, masked, LLVMVectorType(LLVMFloatType(), 4), "");
135
136 if (normalized)
137 scaled = LLVMBuildMul(builder, casted, LLVMConstVector(scales, 4), "");
138 else
139 scaled = casted;
140
141 for (i = 0; i < 4; ++i)
142 aux[i] = LLVMGetUndef(LLVMFloatType());
143
144 for (i = 0; i < 4; ++i) {
145 enum util_format_swizzle swizzle = desc->swizzle[i];
146
147 switch (swizzle) {
148 case UTIL_FORMAT_SWIZZLE_X:
149 case UTIL_FORMAT_SWIZZLE_Y:
150 case UTIL_FORMAT_SWIZZLE_Z:
151 case UTIL_FORMAT_SWIZZLE_W:
152 swizzles[i] = LLVMConstInt(LLVMInt32Type(), swizzle, 0);
153 break;
154 case UTIL_FORMAT_SWIZZLE_0:
155 assert(empty_channel >= 0);
156 swizzles[i] = LLVMConstInt(LLVMInt32Type(), empty_channel, 0);
157 break;
158 case UTIL_FORMAT_SWIZZLE_1:
159 swizzles[i] = LLVMConstInt(LLVMInt32Type(), 4, 0);
160 aux[0] = LLVMConstReal(LLVMFloatType(), 1.0);
161 break;
162 case UTIL_FORMAT_SWIZZLE_NONE:
163 swizzles[i] = LLVMGetUndef(LLVMFloatType());
164 assert(0);
165 break;
166 }
167 }
168
169 return LLVMBuildShuffleVector(builder, scaled, LLVMConstVector(aux, 4), LLVMConstVector(swizzles, 4), "");
170 }
171
172
173 /**
174 * Take a vector with packed pixels and unpack into a rgba8 vector.
175 *
176 * Formats with bit depth smaller than 32bits are accepted, but they must be
177 * padded to 32bits.
178 */
179 LLVMValueRef
180 lp_build_unpack_rgba8_aos(LLVMBuilderRef builder,
181 const struct util_format_description *desc,
182 struct lp_type type,
183 LLVMValueRef packed)
184 {
185 struct lp_build_context bld;
186 bool rgba8;
187 LLVMValueRef res;
188 unsigned i;
189
190 lp_build_context_init(&bld, builder, type);
191
192 /* FIXME: Support more formats */
193 assert(desc->layout == UTIL_FORMAT_LAYOUT_ARITH);
194 assert(desc->block.width == 1);
195 assert(desc->block.height == 1);
196 assert(desc->block.bits <= 32);
197
198 assert(!type.floating);
199 assert(!type.fixed);
200 assert(type.norm);
201 assert(type.width == 8);
202 assert(type.length % 4 == 0);
203
204 rgba8 = TRUE;
205 for(i = 0; i < 4; ++i) {
206 assert(desc->channel[i].type == UTIL_FORMAT_TYPE_UNSIGNED ||
207 desc->channel[i].type == UTIL_FORMAT_TYPE_VOID);
208 if(desc->channel[0].size != 8)
209 rgba8 = FALSE;
210 }
211
212 if(rgba8) {
213 /*
214 * The pixel is already in a rgba8 format variant. All it is necessary
215 * is to swizzle the channels.
216 */
217
218 unsigned char swizzles[4];
219 boolean zeros[4]; /* bitwise AND mask */
220 boolean ones[4]; /* bitwise OR mask */
221 boolean swizzles_needed = FALSE;
222 boolean zeros_needed = FALSE;
223 boolean ones_needed = FALSE;
224
225 for(i = 0; i < 4; ++i) {
226 enum util_format_swizzle swizzle = desc->swizzle[i];
227
228 /* Initialize with the no-op case */
229 swizzles[i] = util_cpu_caps.little_endian ? 3 - i : i;
230 zeros[i] = TRUE;
231 ones[i] = FALSE;
232
233 switch (swizzle) {
234 case UTIL_FORMAT_SWIZZLE_X:
235 case UTIL_FORMAT_SWIZZLE_Y:
236 case UTIL_FORMAT_SWIZZLE_Z:
237 case UTIL_FORMAT_SWIZZLE_W:
238 if(swizzle != swizzles[i]) {
239 swizzles[i] = swizzle;
240 swizzles_needed = TRUE;
241 }
242 break;
243 case UTIL_FORMAT_SWIZZLE_0:
244 zeros[i] = FALSE;
245 zeros_needed = TRUE;
246 break;
247 case UTIL_FORMAT_SWIZZLE_1:
248 ones[i] = TRUE;
249 ones_needed = TRUE;
250 break;
251 case UTIL_FORMAT_SWIZZLE_NONE:
252 assert(0);
253 break;
254 }
255 }
256
257 res = packed;
258
259 if(swizzles_needed)
260 res = lp_build_swizzle1_aos(&bld, res, swizzles);
261
262 if(zeros_needed) {
263 /* Mask out zero channels */
264 LLVMValueRef mask = lp_build_const_mask_aos(type, zeros);
265 res = LLVMBuildAnd(builder, res, mask, "");
266 }
267
268 if(ones_needed) {
269 /* Or one channels */
270 LLVMValueRef mask = lp_build_const_mask_aos(type, ones);
271 res = LLVMBuildOr(builder, res, mask, "");
272 }
273 }
274 else {
275 /* FIXME */
276 assert(0);
277 res = lp_build_undef(type);
278 }
279
280 return res;
281 }
282
283
284 /**
285 * Pack a single pixel.
286 *
287 * @param rgba 4 float vector with the unpacked components.
288 *
289 * XXX: This is mostly for reference and testing -- operating a single pixel at
290 * a time is rarely if ever needed.
291 */
292 LLVMValueRef
293 lp_build_pack_rgba_aos(LLVMBuilderRef builder,
294 const struct util_format_description *desc,
295 LLVMValueRef rgba)
296 {
297 LLVMTypeRef type;
298 LLVMValueRef packed = NULL;
299 LLVMValueRef swizzles[4];
300 LLVMValueRef shifted, casted, scaled, unswizzled;
301 LLVMValueRef shifts[4];
302 LLVMValueRef scales[4];
303 bool normalized;
304 unsigned shift;
305 unsigned i, j;
306
307 assert(desc->layout == UTIL_FORMAT_LAYOUT_ARITH);
308 assert(desc->block.width == 1);
309 assert(desc->block.height == 1);
310
311 type = LLVMIntType(desc->block.bits);
312
313 /* Unswizzle the color components into the source vector. */
314 for (i = 0; i < 4; ++i) {
315 for (j = 0; j < 4; ++j) {
316 if (desc->swizzle[j] == i)
317 break;
318 }
319 if (j < 4)
320 swizzles[i] = LLVMConstInt(LLVMInt32Type(), j, 0);
321 else
322 swizzles[i] = LLVMGetUndef(LLVMInt32Type());
323 }
324
325 unswizzled = LLVMBuildShuffleVector(builder, rgba,
326 LLVMGetUndef(LLVMVectorType(LLVMFloatType(), 4)),
327 LLVMConstVector(swizzles, 4), "");
328
329 normalized = FALSE;
330 shift = 0;
331 for (i = 0; i < 4; ++i) {
332 unsigned bits = desc->channel[i].size;
333
334 if (desc->channel[i].type == UTIL_FORMAT_TYPE_VOID) {
335 shifts[i] = LLVMGetUndef(LLVMInt32Type());
336 scales[i] = LLVMGetUndef(LLVMFloatType());
337 }
338 else {
339 unsigned mask = (1 << bits) - 1;
340
341 assert(desc->channel[i].type == UTIL_FORMAT_TYPE_UNSIGNED);
342 assert(bits < 32);
343
344 shifts[i] = LLVMConstInt(LLVMInt32Type(), shift, 0);
345
346 if (desc->channel[i].normalized) {
347 scales[i] = LLVMConstReal(LLVMFloatType(), mask);
348 normalized = TRUE;
349 }
350 else
351 scales[i] = LLVMConstReal(LLVMFloatType(), 1.0);
352 }
353
354 shift += bits;
355 }
356
357 if (normalized)
358 scaled = LLVMBuildMul(builder, unswizzled, LLVMConstVector(scales, 4), "");
359 else
360 scaled = unswizzled;
361
362 casted = LLVMBuildFPToSI(builder, scaled, LLVMVectorType(LLVMInt32Type(), 4), "");
363
364 shifted = LLVMBuildShl(builder, casted, LLVMConstVector(shifts, 4), "");
365
366 /* Bitwise or all components */
367 for (i = 0; i < 4; ++i) {
368 if (desc->channel[i].type == UTIL_FORMAT_TYPE_UNSIGNED) {
369 LLVMValueRef component = LLVMBuildExtractElement(builder, shifted, LLVMConstInt(LLVMInt32Type(), i, 0), "");
370 if (packed)
371 packed = LLVMBuildOr(builder, packed, component, "");
372 else
373 packed = component;
374 }
375 }
376
377 if (!packed)
378 packed = LLVMGetUndef(LLVMInt32Type());
379
380 if (desc->block.bits < 32)
381 packed = LLVMBuildTrunc(builder, packed, type, "");
382
383 return packed;
384 }