OSDN Git Service

llvmpipe: Factor out and optimize the input interpolation.
[android-x86/external-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 #include "util/u_format.h"
30
31 #include "lp_bld_format.h"
32
33
34 LLVMValueRef
35 lp_build_unpack_rgba(LLVMBuilderRef builder,
36                      enum pipe_format format,
37                      LLVMValueRef packed)
38 {
39    const struct util_format_description *desc;
40    LLVMTypeRef type;
41    LLVMValueRef shifted, casted, scaled, masked;
42    LLVMValueRef shifts[4];
43    LLVMValueRef masks[4];
44    LLVMValueRef scales[4];
45    LLVMValueRef swizzles[4];
46    LLVMValueRef aux[4];
47    bool normalized;
48    int empty_channel;
49    unsigned shift;
50    unsigned i;
51
52    desc = util_format_description(format);
53
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);
59
60    type = LLVMIntType(desc->block.bits);
61
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(), "");
66
67    /* Broadcast the packed value to all four channels */
68    packed = LLVMBuildInsertElement(builder,
69                                    LLVMGetUndef(LLVMVectorType(LLVMInt32Type(), 4)),
70                                    packed,
71                                    LLVMConstNull(LLVMInt32Type()),
72                                    "");
73    packed = LLVMBuildShuffleVector(builder,
74                                    packed,
75                                    LLVMGetUndef(LLVMVectorType(LLVMInt32Type(), 4)),
76                                    LLVMConstNull(LLVMVectorType(LLVMInt32Type(), 4)),
77                                    "");
78
79    /* Initialize vector constants */
80    normalized = FALSE;
81    empty_channel = -1;
82    shift = 0;
83    for (i = 0; i < 4; ++i) {
84       unsigned bits = desc->channel[i].size;
85
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());
90          empty_channel = i;
91       }
92       else {
93          unsigned mask = (1 << bits) - 1;
94
95          assert(desc->channel[i].type == UTIL_FORMAT_TYPE_UNSIGNED);
96          assert(bits < 32);
97
98          shifts[i] = LLVMConstInt(LLVMInt32Type(), shift, 0);
99          masks[i] = LLVMConstInt(LLVMInt32Type(), mask, 0);
100
101          if (desc->channel[i].normalized) {
102             scales[i] = LLVMConstReal(LLVMFloatType(), 1.0/mask);
103             normalized = TRUE;
104          }
105          else
106             scales[i] =  LLVMConstReal(LLVMFloatType(), 1.0);
107       }
108
109       shift += bits;
110    }
111
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), "");
116
117    if (normalized)
118       scaled = LLVMBuildMul(builder, casted, LLVMConstVector(scales, 4), "");
119    else
120       scaled = casted;
121
122    for (i = 0; i < 4; ++i)
123       aux[i] = LLVMGetUndef(LLVMFloatType());
124
125    for (i = 0; i < 4; ++i) {
126       enum util_format_swizzle swizzle = desc->swizzle[i];
127
128       switch (swizzle) {
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);
134          break;
135       case UTIL_FORMAT_SWIZZLE_0:
136          assert(empty_channel >= 0);
137          swizzles[i] = LLVMConstInt(LLVMInt32Type(), empty_channel, 0);
138          break;
139       case UTIL_FORMAT_SWIZZLE_1:
140          swizzles[i] = LLVMConstInt(LLVMInt32Type(), 4, 0);
141          aux[0] = LLVMConstReal(LLVMFloatType(), 1.0);
142          break;
143       case UTIL_FORMAT_SWIZZLE_NONE:
144          swizzles[i] = LLVMGetUndef(LLVMFloatType());
145          assert(0);
146          break;
147       }
148    }
149
150    return LLVMBuildShuffleVector(builder, scaled, LLVMConstVector(aux, 4), LLVMConstVector(swizzles, 4), "");
151 }
152
153
154 LLVMValueRef
155 lp_build_pack_rgba(LLVMBuilderRef builder,
156                    enum pipe_format format,
157                    LLVMValueRef rgba)
158 {
159    const struct util_format_description *desc;
160    LLVMTypeRef type;
161    LLVMValueRef packed = NULL;
162    LLVMValueRef swizzles[4];
163    LLVMValueRef shifted, casted, scaled, unswizzled;
164    LLVMValueRef shifts[4];
165    LLVMValueRef scales[4];
166    bool normalized;
167    unsigned shift;
168    unsigned i, j;
169
170    desc = util_format_description(format);
171
172    assert(desc->layout == UTIL_FORMAT_LAYOUT_ARITH);
173    assert(desc->block.width == 1);
174    assert(desc->block.height == 1);
175
176    type = LLVMIntType(desc->block.bits);
177
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)
182             break;
183       }
184       if (j < 4)
185          swizzles[i] = LLVMConstInt(LLVMInt32Type(), j, 0);
186       else
187          swizzles[i] = LLVMGetUndef(LLVMInt32Type());
188    }
189
190    unswizzled = LLVMBuildShuffleVector(builder, rgba,
191                                        LLVMGetUndef(LLVMVectorType(LLVMFloatType(), 4)),
192                                        LLVMConstVector(swizzles, 4), "");
193
194    normalized = FALSE;
195    shift = 0;
196    for (i = 0; i < 4; ++i) {
197       unsigned bits = desc->channel[i].size;
198
199       if (desc->channel[i].type == UTIL_FORMAT_TYPE_VOID) {
200          shifts[i] = LLVMGetUndef(LLVMInt32Type());
201          scales[i] =  LLVMGetUndef(LLVMFloatType());
202       }
203       else {
204          unsigned mask = (1 << bits) - 1;
205
206          assert(desc->channel[i].type == UTIL_FORMAT_TYPE_UNSIGNED);
207          assert(bits < 32);
208
209          shifts[i] = LLVMConstInt(LLVMInt32Type(), shift, 0);
210
211          if (desc->channel[i].normalized) {
212             scales[i] = LLVMConstReal(LLVMFloatType(), mask);
213             normalized = TRUE;
214          }
215          else
216             scales[i] =  LLVMConstReal(LLVMFloatType(), 1.0);
217       }
218
219       shift += bits;
220    }
221
222    if (normalized)
223       scaled = LLVMBuildMul(builder, unswizzled, LLVMConstVector(scales, 4), "");
224    else
225       scaled = unswizzled;
226
227    casted = LLVMBuildFPToSI(builder, scaled, LLVMVectorType(LLVMInt32Type(), 4), "");
228
229    shifted = LLVMBuildShl(builder, casted, LLVMConstVector(shifts, 4), "");
230    
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), "");
235          if (packed)
236             packed = LLVMBuildOr(builder, packed, component, "");
237          else
238             packed = component;
239       }
240    }
241
242    if (!packed)
243       packed = LLVMGetUndef(LLVMInt32Type());
244
245    if (desc->block.bits < 32)
246       packed = LLVMBuildTrunc(builder, packed, type, "");
247
248    return packed;
249 }
250
251
252 LLVMValueRef
253 lp_build_load_rgba(LLVMBuilderRef builder,
254                    enum pipe_format format,
255                    LLVMValueRef ptr)
256 {
257    const struct util_format_description *desc;
258    LLVMTypeRef type;
259    LLVMValueRef packed;
260
261    desc = util_format_description(format);
262
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);
268
269    type = LLVMIntType(desc->block.bits);
270
271    ptr = LLVMBuildBitCast(builder, ptr, LLVMPointerType(type, 0), "");
272
273    packed = LLVMBuildLoad(builder, ptr, "");
274
275    return lp_build_unpack_rgba(builder, format, packed);
276 }
277
278
279 void
280 lp_build_store_rgba(LLVMBuilderRef builder,
281                     enum pipe_format format,
282                     LLVMValueRef ptr,
283                     LLVMValueRef rgba)
284 {
285    const struct util_format_description *desc;
286    LLVMTypeRef type;
287    LLVMValueRef packed;
288
289    desc = util_format_description(format);
290
291    assert(desc->layout == UTIL_FORMAT_LAYOUT_ARITH);
292    assert(desc->block.width == 1);
293    assert(desc->block.height == 1);
294
295    type = LLVMIntType(desc->block.bits);
296
297    packed = lp_build_pack_rgba(builder, format, rgba);
298
299    ptr = LLVMBuildBitCast(builder, ptr, LLVMPointerType(type, 0), "");
300
301    LLVMBuildStore(builder, packed, ptr);
302 }
303