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_aos(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_aos(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_aos(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_aos(builder
, format
, packed
);
280 lp_build_store_rgba_aos(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_aos(builder
, format
, rgba
);
299 ptr
= LLVMBuildBitCast(builder
, ptr
, LLVMPointerType(type
, 0), "");
301 LLVMBuildStore(builder
, packed
, ptr
);