1 /**************************************************************************
3 * Copyright 2009 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 above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
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.
26 **************************************************************************/
29 #include "util/u_format.h"
31 #include "lp_bld_format.h"
35 lp_build_unpack_rgba(LLVMBuilderRef builder,
36 enum pipe_format format,
39 const struct util_format_description *desc;
41 LLVMValueRef shifted, casted, scaled, masked;
42 LLVMValueRef shifts[4];
43 LLVMValueRef masks[4];
44 LLVMValueRef scales[4];
45 LLVMValueRef swizzles[4];
52 desc = util_format_description(format);
54 /* FIXME: Support more formats */
55 assert(desc->layout == UTIL_FORMAT_LAYOUT_ARITH);
56 assert(desc->block.width == 1);
57 assert(desc->block.height == 1);
58 assert(desc->block.bits <= 32);
60 type = LLVMIntType(desc->block.bits);
62 /* Do the intermediate integer computations with 32bit integers since it
63 * matches floating point size */
64 if (desc->block.bits < 32)
65 packed = LLVMBuildZExt(builder, packed, LLVMInt32Type(), "");
67 /* Broadcast the packed value to all four channels */
68 packed = LLVMBuildInsertElement(builder,
69 LLVMGetUndef(LLVMVectorType(LLVMInt32Type(), 4)),
71 LLVMConstNull(LLVMInt32Type()),
73 packed = LLVMBuildShuffleVector(builder,
75 LLVMGetUndef(LLVMVectorType(LLVMInt32Type(), 4)),
76 LLVMConstNull(LLVMVectorType(LLVMInt32Type(), 4)),
79 /* Initialize vector constants */
83 for (i = 0; i < 4; ++i) {
84 unsigned bits = desc->channel[i].size;
86 if (desc->channel[i].type == UTIL_FORMAT_TYPE_VOID) {
87 shifts[i] = LLVMGetUndef(LLVMInt32Type());
88 masks[i] = LLVMConstNull(LLVMInt32Type());
89 scales[i] = LLVMConstNull(LLVMFloatType());
93 unsigned mask = (1 << bits) - 1;
95 assert(desc->channel[i].type == UTIL_FORMAT_TYPE_UNSIGNED);
98 shifts[i] = LLVMConstInt(LLVMInt32Type(), shift, 0);
99 masks[i] = LLVMConstInt(LLVMInt32Type(), mask, 0);
101 if (desc->channel[i].normalized) {
102 scales[i] = LLVMConstReal(LLVMFloatType(), 1.0/mask);
106 scales[i] = LLVMConstReal(LLVMFloatType(), 1.0);
112 shifted = LLVMBuildLShr(builder, packed, LLVMConstVector(shifts, 4), "");
113 masked = LLVMBuildAnd(builder, shifted, LLVMConstVector(masks, 4), "");
114 // UIToFP can't be expressed in SSE2
115 casted = LLVMBuildSIToFP(builder, masked, LLVMVectorType(LLVMFloatType(), 4), "");
118 scaled = LLVMBuildMul(builder, casted, LLVMConstVector(scales, 4), "");
122 for (i = 0; i < 4; ++i)
123 aux[i] = LLVMGetUndef(LLVMFloatType());
125 for (i = 0; i < 4; ++i) {
126 enum util_format_swizzle swizzle = desc->swizzle[i];
129 case UTIL_FORMAT_SWIZZLE_X:
130 case UTIL_FORMAT_SWIZZLE_Y:
131 case UTIL_FORMAT_SWIZZLE_Z:
132 case UTIL_FORMAT_SWIZZLE_W:
133 swizzles[i] = LLVMConstInt(LLVMInt32Type(), swizzle, 0);
135 case UTIL_FORMAT_SWIZZLE_0:
136 assert(empty_channel >= 0);
137 swizzles[i] = LLVMConstInt(LLVMInt32Type(), empty_channel, 0);
139 case UTIL_FORMAT_SWIZZLE_1:
140 swizzles[i] = LLVMConstInt(LLVMInt32Type(), 4, 0);
141 aux[0] = LLVMConstReal(LLVMFloatType(), 1.0);
143 case UTIL_FORMAT_SWIZZLE_NONE:
144 swizzles[i] = LLVMGetUndef(LLVMFloatType());
150 return LLVMBuildShuffleVector(builder, scaled, LLVMConstVector(aux, 4), LLVMConstVector(swizzles, 4), "");
155 lp_build_pack_rgba(LLVMBuilderRef builder,
156 enum pipe_format format,
159 const struct util_format_description *desc;
161 LLVMValueRef packed = NULL;
162 LLVMValueRef swizzles[4];
163 LLVMValueRef shifted, casted, scaled, unswizzled;
164 LLVMValueRef shifts[4];
165 LLVMValueRef scales[4];
170 desc = util_format_description(format);
172 assert(desc->layout == UTIL_FORMAT_LAYOUT_ARITH);
173 assert(desc->block.width == 1);
174 assert(desc->block.height == 1);
176 type = LLVMIntType(desc->block.bits);
178 /* Unswizzle the color components into the source vector. */
179 for (i = 0; i < 4; ++i) {
180 for (j = 0; j < 4; ++j) {
181 if (desc->swizzle[j] == i)
185 swizzles[i] = LLVMConstInt(LLVMInt32Type(), j, 0);
187 swizzles[i] = LLVMGetUndef(LLVMInt32Type());
190 unswizzled = LLVMBuildShuffleVector(builder, rgba,
191 LLVMGetUndef(LLVMVectorType(LLVMFloatType(), 4)),
192 LLVMConstVector(swizzles, 4), "");
196 for (i = 0; i < 4; ++i) {
197 unsigned bits = desc->channel[i].size;
199 if (desc->channel[i].type == UTIL_FORMAT_TYPE_VOID) {
200 shifts[i] = LLVMGetUndef(LLVMInt32Type());
201 scales[i] = LLVMGetUndef(LLVMFloatType());
204 unsigned mask = (1 << bits) - 1;
206 assert(desc->channel[i].type == UTIL_FORMAT_TYPE_UNSIGNED);
209 shifts[i] = LLVMConstInt(LLVMInt32Type(), shift, 0);
211 if (desc->channel[i].normalized) {
212 scales[i] = LLVMConstReal(LLVMFloatType(), mask);
216 scales[i] = LLVMConstReal(LLVMFloatType(), 1.0);
223 scaled = LLVMBuildMul(builder, unswizzled, LLVMConstVector(scales, 4), "");
227 casted = LLVMBuildFPToSI(builder, scaled, LLVMVectorType(LLVMInt32Type(), 4), "");
229 shifted = LLVMBuildShl(builder, casted, LLVMConstVector(shifts, 4), "");
231 /* Bitwise or all components */
232 for (i = 0; i < 4; ++i) {
233 if (desc->channel[i].type == UTIL_FORMAT_TYPE_UNSIGNED) {
234 LLVMValueRef component = LLVMBuildExtractElement(builder, shifted, LLVMConstInt(LLVMInt32Type(), i, 0), "");
236 packed = LLVMBuildOr(builder, packed, component, "");
243 packed = LLVMGetUndef(LLVMInt32Type());
245 if (desc->block.bits < 32)
246 packed = LLVMBuildTrunc(builder, packed, type, "");
253 lp_build_load_rgba(LLVMBuilderRef builder,
254 enum pipe_format format,
257 const struct util_format_description *desc;
261 desc = util_format_description(format);
263 /* FIXME: Support more formats */
264 assert(desc->layout == UTIL_FORMAT_LAYOUT_ARITH);
265 assert(desc->block.width == 1);
266 assert(desc->block.height == 1);
267 assert(desc->block.bits <= 32);
269 type = LLVMIntType(desc->block.bits);
271 ptr = LLVMBuildBitCast(builder, ptr, LLVMPointerType(type, 0), "");
273 packed = LLVMBuildLoad(builder, ptr, "");
275 return lp_build_unpack_rgba(builder, format, packed);
280 lp_build_store_rgba(LLVMBuilderRef builder,
281 enum pipe_format format,
285 const struct util_format_description *desc;
289 desc = util_format_description(format);
291 assert(desc->layout == UTIL_FORMAT_LAYOUT_ARITH);
292 assert(desc->block.width == 1);
293 assert(desc->block.height == 1);
295 type = LLVMIntType(desc->block.bits);
297 packed = lp_build_pack_rgba(builder, format, rgba);
299 ptr = LLVMBuildBitCast(builder, ptr, LLVMPointerType(type, 0), "");
301 LLVMBuildStore(builder, packed, ptr);