Rename the various function types in t_context.h to include a tnl_ prefix.
[mesa.git] / src / mesa / tnl / t_vertex_codegen.c
1 /*
2 * Copyright 2003 Tungsten Graphics, inc.
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * on the rights to use, copy, modify, merge, publish, distribute, sub
9 * license, and/or sell copies of the Software, and to permit persons to whom
10 * the Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
14 * Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19 * TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
20 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
21 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
22 * USE OR OTHER DEALINGS IN THE SOFTWARE.
23 *
24 * Authors:
25 * Keith Whitwell <keithw@tungstengraphics.com>
26 */
27
28 #include "glheader.h"
29 #include "context.h"
30 #include "colormac.h"
31
32 #include "t_context.h"
33 #include "t_vertex.h"
34
35 #include "simple_list.h"
36
37 /* Another codegen scheme, hopefully portable to a few different
38 * architectures without too much work.
39 */
40
41
42
43
44 static GLboolean emit_4f_viewport_4( struct tnl_clipspace_codegen *p )
45 {
46 return
47 p->emit_mad(p, out(0), vp(0), in(0), vp(12)) &&
48 p->emit_mad(p, out(1), vp(5), in(1), vp(13)) &&
49 p->emit_mad(p, out(2), vp(10), in(2), vp(14)) &&
50 p->emit_mov(p, out(3), in(3));
51 }
52
53 static GLboolean emit_4f_viewport_3( struct tnl_clipspace_codegen *p )
54 {
55 return
56 p->emit_mad(p, out(0), vp(0), in(0), vp(12)) &&
57 p->emit_mad(p, out(1), vp(5), in(1), vp(13)) &&
58 p->emit_mad(p, out(2), vp(10), in(2), vp(14)) &&
59 p->emit_const(p, out(3), 1.0);
60 }
61
62 static GLboolean emit_4f_viewport_2( struct tnl_clipspace_codegen *p )
63 {
64 return
65 p->emit_mad(p, out(0), vp(0), in(0), vp(12)) &&
66 p->emit_mad(p, out(1), vp(5), in(1), vp(13)) &&
67 p->emit_mov(p, out(2), vp(14)) &&
68 p->emit_const(p, out(3), 1.0);
69 }
70
71 static GLboolean emit_4f_viewport_1( struct tnl_clipspace_codegen *p )
72 {
73 return
74 p->emit_mad(p, out(0), vp(0), in(0), vp(12)) &&
75 p->emit_mov(p, out(1), vp(13)) &&
76 p->emit_mov(p, out(2), vp(14)) &&
77 p->emit_const(p, out(3), 1.0);
78 }
79
80 static GLboolean emit_3f_viewport_3( struct tnl_clipspace_codegen *p )
81 {
82 return
83 p->emit_mad(p, out(0), vp(0), in(0), vp(12)) &&
84 p->emit_mad(p, out(1), vp(5), in(1), vp(13)) &&
85 p->emit_mad(p, out(2), vp(10), in(2), vp(14));
86 }
87
88 static GLboolean emit_3f_viewport_2( struct tnl_clipspace_codegen *p )
89 {
90 return
91 p->emit_mad(p, out(0), vp(0), in(0), vp(12)) &&
92 p->emit_mad(p, out(1), vp(5), in(1), vp(13)) &&
93 p->emit_mov(p, out(2), vp(14));
94 }
95
96 static GLboolean emit_3f_viewport_1( struct tnl_clipspace_codegen *p )
97 {
98 return
99 p->emit_mad(p, out(0), vp(0), in(0), vp(12)) &&
100 p->emit_mov(p, out(1), vp(13)) &&
101 p->emit_mov(p, out(2), vp(14));
102 }
103
104 static GLboolean emit_2f_viewport_2( struct tnl_clipspace_codegen *p )
105 {
106 return
107 p->emit_mad(p, out(0), vp(0), in(0), vp(12)) &&
108 p->emit_mad(p, out(1), vp(5), in(1), vp(13));
109 }
110
111 static GLboolean emit_2f_viewport_1( struct tnl_clipspace_codegen *p )
112 {
113 return
114 p->emit_mad(p, out(0), vp(0), in(0), vp(12));
115 }
116
117
118 static GLboolean emit_4f_4( struct tnl_clipspace_codegen *p )
119 {
120 return
121 p->emit_mov(p, out(0), in(0)) &&
122 p->emit_mov(p, out(1), in(1)) &&
123 p->emit_mov(p, out(2), in(2)) &&
124 p->emit_mov(p, out(3), in(3));
125 }
126
127 static GLboolean emit_4f_3( struct tnl_clipspace_codegen *p )
128 {
129 return
130 p->emit_mov(p, out(0), in(0)) &&
131 p->emit_mov(p, out(1), in(1)) &&
132 p->emit_mov(p, out(2), in(2)) &&
133 p->emit_const(p, out(3), 1.0);
134 }
135
136 static GLboolean emit_4f_2( struct tnl_clipspace_codegen *p )
137 {
138 return
139 p->emit_mov(p, out(0), in(0)) &&
140 p->emit_mov(p, out(1), in(1)) &&
141 p->emit_const(p, out(2), 0.0) &&
142 p->emit_const(p, out(3), 1.0);
143 }
144
145 static GLboolean emit_4f_1( struct tnl_clipspace_codegen *p )
146 {
147 return
148 p->emit_mov(p, out(0), in(0)) &&
149 p->emit_const(p, out(1), 0.0) &&
150 p->emit_const(p, out(2), 0.0) &&
151 p->emit_const(p, out(3), 1.0);
152 }
153
154 static GLboolean emit_3f_xyw_4( struct tnl_clipspace_codegen *p )
155 {
156 return
157 p->emit_mov(p, out(0), in(0)) &&
158 p->emit_mov(p, out(1), in(1)) &&
159 p->emit_mov(p, out(2), in(3));
160 }
161
162 static GLboolean emit_3f_xyw_err( struct tnl_clipspace_codegen *p )
163 {
164 assert(0);
165 return GL_FALSE;
166 }
167
168 static GLboolean emit_3f_3( struct tnl_clipspace_codegen *p )
169 {
170 return
171 p->emit_mov(p, out(0), in(0)) &&
172 p->emit_mov(p, out(1), in(1)) &&
173 p->emit_mov(p, out(2), in(2));
174 }
175
176 static GLboolean emit_3f_2( struct tnl_clipspace_codegen *p )
177 {
178 return
179 p->emit_mov(p, out(0), in(0)) &&
180 p->emit_mov(p, out(1), in(1)) &&
181 p->emit_const(p, out(2), 0.0);
182 }
183
184 static GLboolean emit_3f_1( struct tnl_clipspace_codegen *p )
185 {
186 return
187 p->emit_mov(p, out(0), in(0)) &&
188 p->emit_const(p, out(1), 0.0) &&
189 p->emit_const(p, out(2), 0.0);
190 }
191
192
193 static GLboolean emit_2f_2( struct tnl_clipspace_codegen *p )
194 {
195 return
196 p->emit_mov(p, out(0), in(0)) &&
197 p->emit_mov(p, out(1), in(1));
198 }
199
200 static GLboolean emit_2f_1( struct tnl_clipspace_codegen *p )
201 {
202 return
203 p->emit_mov(p, out(0), in(0)) &&
204 p->emit_const(p, out(1), 0.0);
205 }
206
207 static GLboolean emit_1f_1( struct tnl_clipspace_codegen *p )
208 {
209 return
210 p->emit_mov(p, out(0), in(0));
211 }
212
213 static GLboolean emit_4chan_4f_rgba_4( struct tnl_clipspace_codegen *p )
214 {
215 return
216 p->emit_float_to_chan(p, out(0), in(0)) &&
217 p->emit_float_to_chan(p, out(1), in(1)) &&
218 p->emit_float_to_chan(p, out(2), in(2)) &&
219 p->emit_float_to_chan(p, out(3), in(3));
220 }
221
222 static GLboolean emit_4chan_4f_rgba_3( struct tnl_clipspace_codegen *p )
223 {
224 return
225 p->emit_float_to_chan(p, out(0), in(0)) &&
226 p->emit_float_to_chan(p, out(1), in(1)) &&
227 p->emit_float_to_chan(p, out(2), in(2)) &&
228 p->emit_const_chan(p, out(3), CHAN_MAX);
229 }
230
231 static GLboolean emit_4chan_4f_rgba_2( struct tnl_clipspace_codegen *p )
232 {
233 return
234 p->emit_float_to_chan(p, out(0), in(0)) &&
235 p->emit_float_to_chan(p, out(1), in(1)) &&
236 p->emit_const_chan(p, out(2), 0) &&
237 p->emit_const_chan(p, out(3), CHAN_MAX);
238 }
239
240 static GLboolean emit_4chan_4f_rgba_1( struct tnl_clipspace_codegen *p )
241 {
242 return
243 p->emit_float_to_chan(p, out(0), in(0)) &&
244 p->emit_const_chan(p, out(1), 0) &&
245 p->emit_const_chan(p, out(2), 0) &&
246 p->emit_const_chan(p, out(3), CHAN_MAX);
247 }
248
249 static GLboolean emit_4ub_4f_rgba_4( struct tnl_clipspace_codegen *p )
250 {
251 return
252 p->emit_float_to_ubyte(p, out(0), in(0)) &&
253 p->emit_float_to_ubyte(p, out(1), in(1)) &&
254 p->emit_float_to_ubyte(p, out(2), in(2)) &&
255 p->emit_float_to_ubyte(p, out(3), in(3));
256 }
257
258 static GLboolean emit_4ub_4f_rgba_3( struct tnl_clipspace_codegen *p )
259 {
260 return
261 p->emit_float_to_ubyte(p, out(0), in(0)) &&
262 p->emit_float_to_ubyte(p, out(1), in(1)) &&
263 p->emit_float_to_ubyte(p, out(2), in(2)) &&
264 p->emit_const_ubyte(p, out(3), 0xff);
265 }
266
267 static GLboolean emit_4ub_4f_rgba_2( struct tnl_clipspace_codegen *p )
268 {
269 return
270 p->emit_float_to_ubyte(p, out(0), in(0)) &&
271 p->emit_float_to_ubyte(p, out(1), in(1)) &&
272 p->emit_const_ubyte(p, out(2), 0) &&
273 p->emit_const_ubyte(p, out(3), 0xff);
274 }
275
276 static GLboolean emit_4ub_4f_rgba_1( struct tnl_clipspace_codegen *p )
277 {
278 return
279 p->emit_float_to_ubyte(p, out(0), in(0)) &&
280 p->emit_const_ubyte(p, out(1), 0) &&
281 p->emit_const_ubyte(p, out(2), 0) &&
282 p->emit_const_ubyte(p, out(3), 0xff);
283 }
284
285 static GLboolean emit_4ub_4f_bgra_4( struct tnl_clipspace_codegen *p )
286 {
287 return
288 p->emit_float_to_ubyte(p, out(2), in(0)) &&
289 p->emit_float_to_ubyte(p, out(1), in(1)) &&
290 p->emit_float_to_ubyte(p, out(0), in(2)) &&
291 p->emit_float_to_ubyte(p, out(3), in(3));
292 }
293
294 static GLboolean emit_4ub_4f_bgra_3( struct tnl_clipspace_codegen *p )
295 {
296 return
297 p->emit_float_to_ubyte(p, out(2), in(0)) &&
298 p->emit_float_to_ubyte(p, out(1), in(1)) &&
299 p->emit_float_to_ubyte(p, out(0), in(2)) &&
300 p->emit_const_ubyte(p, out(3), 0xff);
301 }
302
303 static GLboolean emit_4ub_4f_bgra_2( struct tnl_clipspace_codegen *p )
304 {
305 return
306 p->emit_float_to_ubyte(p, out(2), in(0)) &&
307 p->emit_float_to_ubyte(p, out(1), in(1)) &&
308 p->emit_const_ubyte(p, out(0), 0) &&
309 p->emit_const_ubyte(p, out(3), 0xff);
310 }
311
312 static GLboolean emit_4ub_4f_bgra_1( struct tnl_clipspace_codegen *p )
313 {
314 return
315 p->emit_float_to_ubyte(p, out(2), in(0)) &&
316 p->emit_const_ubyte(p, out(1), 0) &&
317 p->emit_const_ubyte(p, out(0), 0) &&
318 p->emit_const_ubyte(p, out(3), 0xff);
319 }
320
321 static GLboolean emit_3ub_3f_rgb_3( struct tnl_clipspace_codegen *p )
322 {
323 return
324 p->emit_float_to_ubyte(p, out(0), in(0)) &&
325 p->emit_float_to_ubyte(p, out(1), in(1)) &&
326 p->emit_float_to_ubyte(p, out(2), in(2));
327 }
328
329 static GLboolean emit_3ub_3f_rgb_2( struct tnl_clipspace_codegen *p )
330 {
331 return
332 p->emit_float_to_ubyte(p, out(0), in(0)) &&
333 p->emit_float_to_ubyte(p, out(1), in(1)) &&
334 p->emit_const_ubyte(p, out(2), 0);
335 }
336
337 static GLboolean emit_3ub_3f_rgb_1( struct tnl_clipspace_codegen *p )
338 {
339 return
340 p->emit_float_to_ubyte(p, out(0), in(0)) &&
341 p->emit_const_ubyte(p, out(1), 0) &&
342 p->emit_const_ubyte(p, out(2), 0);
343 }
344
345 static GLboolean emit_3ub_3f_bgr_3( struct tnl_clipspace_codegen *p )
346 {
347 return
348 p->emit_float_to_ubyte(p, out(2), in(0)) &&
349 p->emit_float_to_ubyte(p, out(1), in(1)) &&
350 p->emit_float_to_ubyte(p, out(0), in(2));
351 }
352
353 static GLboolean emit_3ub_3f_bgr_2( struct tnl_clipspace_codegen *p )
354 {
355 return
356 p->emit_float_to_ubyte(p, out(2), in(0)) &&
357 p->emit_float_to_ubyte(p, out(1), in(1)) &&
358 p->emit_const_ubyte(p, out(0), 0);
359 }
360
361 static GLboolean emit_3ub_3f_bgr_1( struct tnl_clipspace_codegen *p )
362 {
363 return
364 p->emit_float_to_ubyte(p, out(2), in(0)) &&
365 p->emit_const_ubyte(p, out(1), 0) &&
366 p->emit_const_ubyte(p, out(0), 0);
367 }
368
369
370 static GLboolean emit_1ub_1f_1( struct tnl_clipspace_codegen *p )
371 {
372 return
373 p->emit_float_to_ubyte(p, out(0), in(0));
374 }
375
376
377
378
379 static struct {
380 const char *name;
381 GLenum out_type;
382 GLboolean need_vp;
383 GLboolean (*emit[4])( struct tnl_clipspace_codegen * );
384 } emit_info[EMIT_MAX] = {
385
386 { "1f", GL_FLOAT, GL_FALSE,
387 { emit_1f_1, emit_1f_1, emit_1f_1, emit_1f_1 } },
388
389 { "2f", GL_FLOAT, GL_FALSE,
390 { emit_2f_1, emit_2f_2, emit_2f_2, emit_2f_2 } },
391
392 { "3f", GL_FLOAT, GL_FALSE,
393 { emit_3f_1, emit_3f_2, emit_3f_3, emit_3f_3 } },
394
395 { "4f", GL_FLOAT, GL_FALSE,
396 { emit_4f_1, emit_4f_2, emit_4f_3, emit_4f_4 } },
397
398 { "2f_viewport", GL_FLOAT, GL_TRUE,
399 { emit_2f_viewport_1, emit_2f_viewport_2, emit_2f_viewport_2,
400 emit_2f_viewport_2 } },
401
402 { "3f_viewport", GL_FLOAT, GL_TRUE,
403 { emit_3f_viewport_1, emit_3f_viewport_2, emit_3f_viewport_3,
404 emit_3f_viewport_3 } },
405
406 { "4f_viewport", GL_FLOAT, GL_TRUE,
407 { emit_4f_viewport_1, emit_4f_viewport_2, emit_4f_viewport_3,
408 emit_4f_viewport_4 } },
409
410 { "3f_xyw", GL_FLOAT, GL_FALSE,
411 { emit_3f_xyw_err, emit_3f_xyw_err, emit_3f_xyw_err,
412 emit_3f_xyw_4 } },
413
414 { "1ub_1f", GL_UNSIGNED_BYTE, GL_FALSE,
415 { emit_1ub_1f_1, emit_1ub_1f_1, emit_1ub_1f_1, emit_1ub_1f_1 } },
416
417 { "3ub_3f_rgb", GL_UNSIGNED_BYTE, GL_FALSE,
418 { emit_3ub_3f_rgb_1, emit_3ub_3f_rgb_2, emit_3ub_3f_rgb_3,
419 emit_3ub_3f_rgb_3 } },
420
421 { "3ub_3f_bgr", GL_UNSIGNED_BYTE, GL_FALSE,
422 { emit_3ub_3f_bgr_1, emit_3ub_3f_bgr_2, emit_3ub_3f_bgr_3,
423 emit_3ub_3f_bgr_3 } },
424
425 { "4ub_4f_rgba", GL_UNSIGNED_BYTE, GL_FALSE,
426 { emit_4ub_4f_rgba_1, emit_4ub_4f_rgba_2, emit_4ub_4f_rgba_3,
427 emit_4ub_4f_rgba_4 } },
428
429 { "4ub_4f_bgra", GL_UNSIGNED_BYTE, GL_FALSE,
430 { emit_4ub_4f_bgra_1, emit_4ub_4f_bgra_2, emit_4ub_4f_bgra_3,
431 emit_4ub_4f_bgra_4 } },
432
433 { "4chan_4f_rgba", CHAN_TYPE, GL_FALSE,
434 { emit_4chan_4f_rgba_1, emit_4chan_4f_rgba_2, emit_4chan_4f_rgba_3,
435 emit_4chan_4f_rgba_4 } },
436
437 { "pad", 0, 0,
438 { 0, 0, 0, 0 } }
439
440 };
441
442
443 /***********************************************************************
444 * list(attrib, size) --> function
445 *
446 * Because of the dependence of size, this all has to take place after
447 * the pipeline has been run.
448 */
449
450 tnl_emit_func _tnl_codegen_emit( GLcontext *ctx )
451 {
452 struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
453 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
454 struct tnl_clipspace_attr *a = vtx->attr;
455 struct tnl_clipspace_codegen *p = &vtx->codegen;
456 const GLuint count = vtx->attr_count;
457 GLuint j;
458
459 /* Need a faster lookup, or is this linear scan of an MRU list good
460 * enough? MRU chosen based on the guess that consecutive VB's are
461 * likely to be of the same format. A hash of attributes and sizes
462 * might be a better technique.
463 *
464 * With the vtx code now in place, it should be possible to track
465 * changes to the sizes of input arrays (and state, of course) and
466 * only invalidate this function when those sizes have changed.
467 */
468 #if 0
469 foreach (l, p->codegen_list) {
470 if (l->attr_count != count)
471 continue;
472
473 /* Assumptions:
474 * a[j].vp will not change for a given attrib
475 * a[j].vertex_offset will not change nothing else has changed.
476 */
477 for (j = 0; j < count; j++)
478 if (a[j].attrib != l->a[j].attrib ||
479 a[j].sz != l->a[j].sz)
480 break;
481
482 if (j == count) {
483 move_to_head(l, p->codegen_list);
484 return l->func;
485 }
486 }
487 #endif
488
489 p->emit_header( p, vtx );
490
491 for (j = 0; j < count; j++) {
492 GLuint sz = VB->AttribPtr[a[j].attrib]->size - 1;
493 p->emit_attr_header( p, a, j,
494 emit_info[a[j].format].out_type,
495 emit_info[a[j].format].need_vp );
496
497 if (!emit_info[a[j].format].emit[sz]( p )) {
498 fprintf(stderr, "codegen failed\n");
499 return 0;
500 }
501
502 p->emit_attr_footer( p );
503 }
504
505 p->emit_footer( p );
506
507 return p->emit_store_func( p );
508 }
509