Merge remote branch 'origin/master' into pipe-video
[mesa.git] / src / gallium / auxiliary / draw / draw_vs_aos_machine.c
1 /**************************************************************************
2 *
3 * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
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 TUNGSTEN GRAPHICS 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 "pipe/p_config.h"
30
31
32 #include "pipe/p_shader_tokens.h"
33 #include "util/u_math.h"
34 #include "util/u_memory.h"
35 #include "tgsi/tgsi_parse.h"
36 #include "tgsi/tgsi_util.h"
37 #include "tgsi/tgsi_exec.h"
38 #include "draw_vs.h"
39 #include "draw_vs_aos.h"
40 #include "draw_vertex.h"
41
42 #ifdef PIPE_ARCH_X86
43
44 #include "rtasm/rtasm_x86sse.h"
45
46
47 #define X87_CW_EXCEPTION_INV_OP (1<<0)
48 #define X87_CW_EXCEPTION_DENORM_OP (1<<1)
49 #define X87_CW_EXCEPTION_ZERO_DIVIDE (1<<2)
50 #define X87_CW_EXCEPTION_OVERFLOW (1<<3)
51 #define X87_CW_EXCEPTION_UNDERFLOW (1<<4)
52 #define X87_CW_EXCEPTION_PRECISION (1<<5)
53 #define X87_CW_PRECISION_SINGLE (0<<8)
54 #define X87_CW_PRECISION_RESERVED (1<<8)
55 #define X87_CW_PRECISION_DOUBLE (2<<8)
56 #define X87_CW_PRECISION_DOUBLE_EXT (3<<8)
57 #define X87_CW_PRECISION_MASK (3<<8)
58 #define X87_CW_ROUND_NEAREST (0<<10)
59 #define X87_CW_ROUND_DOWN (1<<10)
60 #define X87_CW_ROUND_UP (2<<10)
61 #define X87_CW_ROUND_ZERO (3<<10)
62 #define X87_CW_ROUND_MASK (3<<10)
63 #define X87_CW_INFINITY (1<<12)
64
65
66 void PIPE_CDECL aos_do_lit( struct aos_machine *machine,
67 float *result,
68 const float *in,
69 unsigned count )
70 {
71 if (in[0] > 0)
72 {
73 if (in[1] <= 0.0)
74 {
75 result[0] = 1.0F;
76 result[1] = in[0];
77 result[2] = 0.0F;
78 result[3] = 1.0F;
79 }
80 else
81 {
82 const float epsilon = 1.0F / 256.0F;
83 float exponent = CLAMP(in[3], -(128.0F - epsilon), (128.0F - epsilon));
84 result[0] = 1.0F;
85 result[1] = in[0];
86 result[2] = powf(in[1], exponent);
87 result[3] = 1.0;
88 }
89 }
90 else
91 {
92 result[0] = 1.0F;
93 result[1] = 0.0;
94 result[2] = 0.0;
95 result[3] = 1.0F;
96 }
97 }
98
99
100 static void PIPE_CDECL do_lit_lut( struct aos_machine *machine,
101 float *result,
102 const float *in,
103 unsigned count )
104 {
105 if (in[0] > 0)
106 {
107 if (in[1] <= 0.0)
108 {
109 result[0] = 1.0F;
110 result[1] = in[0];
111 result[2] = 0.0F;
112 result[3] = 1.0F;
113 return;
114 }
115
116 if (machine->lit_info[count].shine_tab->exponent != in[3]) {
117 machine->lit_info[count].func = aos_do_lit;
118 goto no_luck;
119 }
120
121 if (in[1] <= 1.0)
122 {
123 const float *tab = machine->lit_info[count].shine_tab->values;
124 float f = in[1] * 256;
125 int k = (int)f;
126 float frac = f - (float)k;
127
128 result[0] = 1.0F;
129 result[1] = in[0];
130 result[2] = tab[k] + frac*(tab[k+1]-tab[k]);
131 result[3] = 1.0;
132 return;
133 }
134
135 no_luck:
136 {
137 const float epsilon = 1.0F / 256.0F;
138 float exponent = CLAMP(in[3], -(128.0F - epsilon), (128.0F - epsilon));
139 result[0] = 1.0F;
140 result[1] = in[0];
141 result[2] = powf(in[1], exponent);
142 result[3] = 1.0;
143 }
144 }
145 else
146 {
147 result[0] = 1.0F;
148 result[1] = 0.0;
149 result[2] = 0.0;
150 result[3] = 1.0F;
151 }
152 }
153
154
155 static void do_populate_lut( struct shine_tab *tab,
156 float unclamped_exponent )
157 {
158 const float epsilon = 1.0F / 256.0F;
159 float exponent = CLAMP(unclamped_exponent, -(128.0F - epsilon), (128.0F - epsilon));
160 unsigned i;
161
162 tab->exponent = unclamped_exponent; /* for later comparison */
163
164 tab->values[0] = 0;
165 if (exponent == 0) {
166 for (i = 1; i < 258; i++) {
167 tab->values[i] = 1.0;
168 }
169 }
170 else {
171 for (i = 1; i < 258; i++) {
172 tab->values[i] = powf((float)i * epsilon, exponent);
173 }
174 }
175 }
176
177
178
179
180 static void PIPE_CDECL populate_lut( struct aos_machine *machine,
181 float *result,
182 const float *in,
183 unsigned count )
184 {
185 unsigned i, tab;
186
187 /* Search for an existing table for this value. Note that without
188 * static analysis we don't really know if in[3] will be constant,
189 * but it usually is...
190 */
191 for (tab = 0; tab < 4; tab++) {
192 if (machine->shine_tab[tab].exponent == in[3]) {
193 goto found;
194 }
195 }
196
197 for (tab = 0, i = 1; i < 4; i++) {
198 if (machine->shine_tab[i].last_used < machine->shine_tab[tab].last_used)
199 tab = i;
200 }
201
202 if (machine->shine_tab[tab].last_used == machine->now) {
203 /* No unused tables (this is not a ffvertex program...). Just
204 * call pow each time:
205 */
206 machine->lit_info[count].func = aos_do_lit;
207 machine->lit_info[count].func( machine, result, in, count );
208 return;
209 }
210 else {
211 do_populate_lut( &machine->shine_tab[tab], in[3] );
212 }
213
214 found:
215 machine->shine_tab[tab].last_used = machine->now;
216 machine->lit_info[count].shine_tab = &machine->shine_tab[tab];
217 machine->lit_info[count].func = do_lit_lut;
218 machine->lit_info[count].func( machine, result, in, count );
219 }
220
221
222 void
223 draw_vs_aos_machine_constants(struct aos_machine *machine,
224 unsigned slot,
225 const void *constants)
226 {
227 machine->constants[slot] = constants;
228
229 {
230 unsigned i;
231 for (i = 0; i < MAX_LIT_INFO; i++) {
232 machine->lit_info[i].func = populate_lut;
233 machine->now++;
234 }
235 }
236 }
237
238
239 void draw_vs_aos_machine_viewport( struct aos_machine *machine,
240 const struct pipe_viewport_state *viewport )
241 {
242 memcpy(machine->scale, viewport->scale, 4 * sizeof(float));
243 memcpy(machine->translate, viewport->translate, 4 * sizeof(float));
244 }
245
246
247
248 void draw_vs_aos_machine_destroy( struct aos_machine *machine )
249 {
250 align_free(machine);
251 }
252
253 struct aos_machine *draw_vs_aos_machine( void )
254 {
255 struct aos_machine *machine;
256 unsigned i;
257 float inv = 1.0f/255.0f;
258 float f255 = 255.0f;
259
260 machine = align_malloc(sizeof(struct aos_machine), 16);
261 if (!machine)
262 return NULL;
263
264 memset(machine, 0, sizeof(*machine));
265
266 ASSIGN_4V(machine->internal[IMM_SWZ], 1.0f, -1.0f, 0.0f, 1.0f);
267 *(unsigned *)&machine->internal[IMM_SWZ][3] = 0xffffffff;
268
269 ASSIGN_4V(machine->internal[IMM_ONES], 1.0f, 1.0f, 1.0f, 1.0f);
270 ASSIGN_4V(machine->internal[IMM_NEGS], -1.0f, -1.0f, -1.0f, -1.0f);
271 ASSIGN_4V(machine->internal[IMM_IDENTITY], 0.0f, 0.0f, 0.0f, 1.0f);
272 ASSIGN_4V(machine->internal[IMM_INV_255], inv, inv, inv, inv);
273 ASSIGN_4V(machine->internal[IMM_255], f255, f255, f255, f255);
274 ASSIGN_4V(machine->internal[IMM_RSQ], -.5f, 1.5f, 0.0f, 0.0f);
275
276
277 machine->fpu_rnd_nearest = (X87_CW_EXCEPTION_INV_OP |
278 X87_CW_EXCEPTION_DENORM_OP |
279 X87_CW_EXCEPTION_ZERO_DIVIDE |
280 X87_CW_EXCEPTION_OVERFLOW |
281 X87_CW_EXCEPTION_UNDERFLOW |
282 X87_CW_EXCEPTION_PRECISION |
283 (1<<6) |
284 X87_CW_ROUND_NEAREST |
285 X87_CW_PRECISION_DOUBLE_EXT);
286
287 assert(machine->fpu_rnd_nearest == 0x37f);
288
289 machine->fpu_rnd_neg_inf = (X87_CW_EXCEPTION_INV_OP |
290 X87_CW_EXCEPTION_DENORM_OP |
291 X87_CW_EXCEPTION_ZERO_DIVIDE |
292 X87_CW_EXCEPTION_OVERFLOW |
293 X87_CW_EXCEPTION_UNDERFLOW |
294 X87_CW_EXCEPTION_PRECISION |
295 (1<<6) |
296 X87_CW_ROUND_DOWN |
297 X87_CW_PRECISION_DOUBLE_EXT);
298
299 for (i = 0; i < MAX_SHINE_TAB; i++)
300 do_populate_lut( &machine->shine_tab[i], 1.0f );
301
302 return machine;
303 }
304
305 #else
306
307 void draw_vs_aos_machine_viewport( struct aos_machine *machine,
308 const struct pipe_viewport_state *viewport )
309 {
310 }
311
312 void
313 draw_vs_aos_machine_constants(struct aos_machine *machine,
314 unsigned slot,
315 const void *constants)
316 {
317 }
318
319 void draw_vs_aos_machine_destroy( struct aos_machine *machine )
320 {
321 }
322
323 struct aos_machine *draw_vs_aos_machine( void )
324 {
325 return NULL;
326 }
327 #endif
328