Merge branch 'gallium-polygon-stipple'
[mesa.git] / src / gallium / auxiliary / gallivm / lp_bld_const.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 /**
30 * @file
31 * Helper functions for constant building.
32 *
33 * @author Jose Fonseca <jfonseca@vmware.com>
34 */
35
36 #include <float.h>
37
38 #include "util/u_debug.h"
39
40 #include "lp_bld_type.h"
41 #include "lp_bld_const.h"
42 #include "lp_bld_init.h"
43
44
45 unsigned
46 lp_mantissa(struct lp_type type)
47 {
48 assert(type.floating);
49
50 if(type.floating) {
51 switch(type.width) {
52 case 32:
53 return 23;
54 case 64:
55 return 53;
56 default:
57 assert(0);
58 return 0;
59 }
60 }
61 else {
62 if(type.sign)
63 return type.width - 1;
64 else
65 return type.width;
66 }
67 }
68
69
70 /**
71 * Shift of the unity.
72 *
73 * Same as lp_const_scale(), but in terms of shifts.
74 */
75 unsigned
76 lp_const_shift(struct lp_type type)
77 {
78 if(type.floating)
79 return 0;
80 else if(type.fixed)
81 return type.width/2;
82 else if(type.norm)
83 return type.sign ? type.width - 1 : type.width;
84 else
85 return 0;
86 }
87
88
89 unsigned
90 lp_const_offset(struct lp_type type)
91 {
92 if(type.floating || type.fixed)
93 return 0;
94 else if(type.norm)
95 return 1;
96 else
97 return 0;
98 }
99
100
101 /**
102 * Scaling factor between the LLVM native value and its interpretation.
103 *
104 * This is 1.0 for all floating types and unnormalized integers, and something
105 * else for the fixed points types and normalized integers.
106 */
107 double
108 lp_const_scale(struct lp_type type)
109 {
110 unsigned long long llscale;
111 double dscale;
112
113 llscale = (unsigned long long)1 << lp_const_shift(type);
114 llscale -= lp_const_offset(type);
115 dscale = (double)llscale;
116 assert((unsigned long long)dscale == llscale);
117
118 return dscale;
119 }
120
121
122 /**
123 * Minimum value representable by the type.
124 */
125 double
126 lp_const_min(struct lp_type type)
127 {
128 unsigned bits;
129
130 if(!type.sign)
131 return 0.0;
132
133 if(type.norm)
134 return -1.0;
135
136 if (type.floating) {
137 switch(type.width) {
138 case 32:
139 return -FLT_MAX;
140 case 64:
141 return -DBL_MAX;
142 default:
143 assert(0);
144 return 0.0;
145 }
146 }
147
148 if(type.fixed)
149 /* FIXME: consider the fractional bits? */
150 bits = type.width / 2 - 1;
151 else
152 bits = type.width - 1;
153
154 return (double)-((long long)1 << bits);
155 }
156
157
158 /**
159 * Maximum value representable by the type.
160 */
161 double
162 lp_const_max(struct lp_type type)
163 {
164 unsigned bits;
165
166 if(type.norm)
167 return 1.0;
168
169 if (type.floating) {
170 switch(type.width) {
171 case 32:
172 return FLT_MAX;
173 case 64:
174 return DBL_MAX;
175 default:
176 assert(0);
177 return 0.0;
178 }
179 }
180
181 if(type.fixed)
182 bits = type.width / 2;
183 else
184 bits = type.width;
185
186 if(type.sign)
187 bits -= 1;
188
189 return (double)(((unsigned long long)1 << bits) - 1);
190 }
191
192
193 double
194 lp_const_eps(struct lp_type type)
195 {
196 if (type.floating) {
197 switch(type.width) {
198 case 32:
199 return FLT_EPSILON;
200 case 64:
201 return DBL_EPSILON;
202 default:
203 assert(0);
204 return 0.0;
205 }
206 }
207 else {
208 double scale = lp_const_scale(type);
209 return 1.0/scale;
210 }
211 }
212
213
214 LLVMValueRef
215 lp_build_undef(struct gallivm_state *gallivm, struct lp_type type)
216 {
217 LLVMTypeRef vec_type = lp_build_vec_type(gallivm, type);
218 return LLVMGetUndef(vec_type);
219 }
220
221
222 LLVMValueRef
223 lp_build_zero(struct gallivm_state *gallivm, struct lp_type type)
224 {
225 if (type.length == 1) {
226 if (type.floating)
227 return lp_build_const_float(gallivm, 0.0);
228 else
229 return LLVMConstInt(LLVMIntTypeInContext(gallivm->context, type.width), 0, 0);
230 }
231 else {
232 LLVMTypeRef vec_type = lp_build_vec_type(gallivm, type);
233 return LLVMConstNull(vec_type);
234 }
235 }
236
237
238 LLVMValueRef
239 lp_build_one(struct gallivm_state *gallivm, struct lp_type type)
240 {
241 LLVMTypeRef elem_type;
242 LLVMValueRef elems[LP_MAX_VECTOR_LENGTH];
243 unsigned i;
244
245 assert(type.length <= LP_MAX_VECTOR_LENGTH);
246
247 elem_type = lp_build_elem_type(gallivm, type);
248
249 if(type.floating)
250 elems[0] = LLVMConstReal(elem_type, 1.0);
251 else if(type.fixed)
252 elems[0] = LLVMConstInt(elem_type, 1LL << (type.width/2), 0);
253 else if(!type.norm)
254 elems[0] = LLVMConstInt(elem_type, 1, 0);
255 else if(type.sign)
256 elems[0] = LLVMConstInt(elem_type, (1LL << (type.width - 1)) - 1, 0);
257 else {
258 /* special case' -- 1.0 for normalized types is more easily attained if
259 * we start with a vector consisting of all bits set */
260 LLVMTypeRef vec_type = LLVMVectorType(elem_type, type.length);
261 LLVMValueRef vec = LLVMConstAllOnes(vec_type);
262
263 #if 0
264 if(type.sign)
265 /* TODO: Unfortunately this caused "Tried to create a shift operation
266 * on a non-integer type!" */
267 vec = LLVMConstLShr(vec, lp_build_const_int_vec(type, 1));
268 #endif
269
270 return vec;
271 }
272
273 for(i = 1; i < type.length; ++i)
274 elems[i] = elems[0];
275
276 if (type.length == 1)
277 return elems[0];
278 else
279 return LLVMConstVector(elems, type.length);
280 }
281
282
283 /**
284 * Build constant-valued element from a scalar value.
285 */
286 LLVMValueRef
287 lp_build_const_elem(struct gallivm_state *gallivm,
288 struct lp_type type,
289 double val)
290 {
291 LLVMTypeRef elem_type = lp_build_elem_type(gallivm, type);
292 LLVMValueRef elem;
293
294 if(type.floating) {
295 elem = LLVMConstReal(elem_type, val);
296 }
297 else {
298 double dscale = lp_const_scale(type);
299
300 elem = LLVMConstInt(elem_type, val*dscale + 0.5, 0);
301 }
302
303 return elem;
304 }
305
306
307 /**
308 * Build constant-valued vector from a scalar value.
309 */
310 LLVMValueRef
311 lp_build_const_vec(struct gallivm_state *gallivm, struct lp_type type,
312 double val)
313 {
314 if (type.length == 1) {
315 return lp_build_const_elem(gallivm, type, val);
316 } else {
317 LLVMValueRef elems[LP_MAX_VECTOR_LENGTH];
318 unsigned i;
319 elems[0] = lp_build_const_elem(gallivm, type, val);
320 for(i = 1; i < type.length; ++i)
321 elems[i] = elems[0];
322 return LLVMConstVector(elems, type.length);
323 }
324 }
325
326
327 LLVMValueRef
328 lp_build_const_int_vec(struct gallivm_state *gallivm, struct lp_type type,
329 long long val)
330 {
331 LLVMTypeRef elem_type = lp_build_int_elem_type(gallivm, type);
332 LLVMValueRef elems[LP_MAX_VECTOR_LENGTH];
333 unsigned i;
334
335 assert(type.length <= LP_MAX_VECTOR_LENGTH);
336
337 for(i = 0; i < type.length; ++i)
338 elems[i] = LLVMConstInt(elem_type, val, type.sign ? 1 : 0);
339
340 if (type.length == 1)
341 return elems[0];
342
343 return LLVMConstVector(elems, type.length);
344 }
345
346
347 LLVMValueRef
348 lp_build_const_aos(struct gallivm_state *gallivm,
349 struct lp_type type,
350 double r, double g, double b, double a,
351 const unsigned char *swizzle)
352 {
353 const unsigned char default_swizzle[4] = {0, 1, 2, 3};
354 LLVMTypeRef elem_type;
355 LLVMValueRef elems[LP_MAX_VECTOR_LENGTH];
356 unsigned i;
357
358 assert(type.length % 4 == 0);
359 assert(type.length <= LP_MAX_VECTOR_LENGTH);
360
361 elem_type = lp_build_elem_type(gallivm, type);
362
363 if(swizzle == NULL)
364 swizzle = default_swizzle;
365
366 if(type.floating) {
367 elems[swizzle[0]] = LLVMConstReal(elem_type, r);
368 elems[swizzle[1]] = LLVMConstReal(elem_type, g);
369 elems[swizzle[2]] = LLVMConstReal(elem_type, b);
370 elems[swizzle[3]] = LLVMConstReal(elem_type, a);
371 }
372 else {
373 double dscale = lp_const_scale(type);
374
375 elems[swizzle[0]] = LLVMConstInt(elem_type, r*dscale + 0.5, 0);
376 elems[swizzle[1]] = LLVMConstInt(elem_type, g*dscale + 0.5, 0);
377 elems[swizzle[2]] = LLVMConstInt(elem_type, b*dscale + 0.5, 0);
378 elems[swizzle[3]] = LLVMConstInt(elem_type, a*dscale + 0.5, 0);
379 }
380
381 for(i = 4; i < type.length; ++i)
382 elems[i] = elems[i % 4];
383
384 return LLVMConstVector(elems, type.length);
385 }
386
387
388 /**
389 * @param mask TGSI_WRITEMASK_xxx
390 */
391 LLVMValueRef
392 lp_build_const_mask_aos(struct gallivm_state *gallivm,
393 struct lp_type type,
394 unsigned mask)
395 {
396 LLVMTypeRef elem_type = LLVMIntTypeInContext(gallivm->context, type.width);
397 LLVMValueRef masks[LP_MAX_VECTOR_LENGTH];
398 unsigned i, j;
399
400 assert(type.length <= LP_MAX_VECTOR_LENGTH);
401
402 for (j = 0; j < type.length; j += 4) {
403 for( i = 0; i < 4; ++i) {
404 masks[j + i] = LLVMConstInt(elem_type,
405 mask & (1 << i) ? ~0ULL : 0,
406 1);
407 }
408 }
409
410 return LLVMConstVector(masks, type.length);
411 }