Add infrastructure for t_vertex.c codegen. Add an example driver
[mesa.git] / src / mesa / tnl / t_vertex.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
36 /* Build and manage clipspace/ndc/window vertices.
37 *
38 * Another new mechanism designed and crying out for codegen. Before
39 * that, it would be very interesting to investigate the merger of
40 * these vertices and those built in t_vtx_*.
41 */
42
43
44
45
46
47
48 /*
49 * These functions take the NDC coordinates pointed to by 'in', apply the
50 * NDC->Viewport mapping and store the results at 'v'.
51 */
52
53 static void
54 insert_4f_viewport_4( const struct tnl_clipspace_attr *a, GLubyte *v,
55 const GLfloat *in )
56 {
57 GLfloat *out = (GLfloat *)v;
58 const GLfloat * const vp = a->vp;
59
60 out[0] = vp[0] * in[0] + vp[12];
61 out[1] = vp[5] * in[1] + vp[13];
62 out[2] = vp[10] * in[2] + vp[14];
63 out[3] = in[3];
64 }
65
66 static void insert_4f_viewport_3( const struct tnl_clipspace_attr *a, GLubyte *v,
67 const GLfloat *in )
68 {
69 GLfloat *out = (GLfloat *)v;
70 const GLfloat * const vp = a->vp;
71
72 out[0] = vp[0] * in[0] + vp[12];
73 out[1] = vp[5] * in[1] + vp[13];
74 out[2] = vp[10] * in[2] + vp[14];
75 out[3] = 1;
76 }
77
78 static void insert_4f_viewport_2( const struct tnl_clipspace_attr *a, GLubyte *v,
79 const GLfloat *in )
80 {
81 GLfloat *out = (GLfloat *)v;
82 const GLfloat * const vp = a->vp;
83
84 out[0] = vp[0] * in[0] + vp[12];
85 out[1] = vp[5] * in[1] + vp[13];
86 out[2] = vp[14];
87 out[3] = 1;
88 }
89
90 static void insert_4f_viewport_1( const struct tnl_clipspace_attr *a, GLubyte *v,
91 const GLfloat *in )
92 {
93 GLfloat *out = (GLfloat *)v;
94 const GLfloat * const vp = a->vp;
95
96 out[0] = vp[0] * in[0] + vp[12];
97 out[1] = vp[13];
98 out[2] = vp[14];
99 out[3] = 1;
100 }
101
102 static void insert_3f_viewport_3( const struct tnl_clipspace_attr *a, GLubyte *v,
103 const GLfloat *in )
104 {
105 GLfloat *out = (GLfloat *)v;
106 const GLfloat * const vp = a->vp;
107
108 out[0] = vp[0] * in[0] + vp[12];
109 out[1] = vp[5] * in[1] + vp[13];
110 out[2] = vp[10] * in[2] + vp[14];
111 }
112
113 static void insert_3f_viewport_2( const struct tnl_clipspace_attr *a, GLubyte *v,
114 const GLfloat *in )
115 {
116 GLfloat *out = (GLfloat *)v;
117 const GLfloat * const vp = a->vp;
118
119 out[0] = vp[0] * in[0] + vp[12];
120 out[1] = vp[5] * in[1] + vp[13];
121 out[2] = vp[10] * in[2] + vp[14];
122 }
123
124 static void insert_3f_viewport_1( const struct tnl_clipspace_attr *a, GLubyte *v,
125 const GLfloat *in )
126 {
127 GLfloat *out = (GLfloat *)v;
128 const GLfloat * const vp = a->vp;
129
130 out[0] = vp[0] * in[0] + vp[12];
131 out[1] = vp[13];
132 out[2] = vp[14];
133 }
134
135 static void insert_2f_viewport_2( const struct tnl_clipspace_attr *a, GLubyte *v,
136 const GLfloat *in )
137 {
138 GLfloat *out = (GLfloat *)v;
139 const GLfloat * const vp = a->vp;
140
141 out[0] = vp[0] * in[0] + vp[12];
142 out[1] = vp[5] * in[1] + vp[13];
143 }
144
145 static void insert_2f_viewport_1( const struct tnl_clipspace_attr *a, GLubyte *v,
146 const GLfloat *in )
147 {
148 GLfloat *out = (GLfloat *)v;
149 const GLfloat * const vp = a->vp;
150
151 out[0] = vp[0] * in[0] + vp[12];
152 out[1] = vp[13];
153 }
154
155
156 /*
157 * These functions do the same as above, except for the viewport mapping.
158 */
159
160 static void insert_4f_4( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in )
161 {
162 GLfloat *out = (GLfloat *)(v);
163
164 out[0] = in[0];
165 out[1] = in[1];
166 out[2] = in[2];
167 out[3] = in[3];
168 }
169
170 static void insert_4f_3( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in )
171 {
172 GLfloat *out = (GLfloat *)(v);
173
174 out[0] = in[0];
175 out[1] = in[1];
176 out[2] = in[2];
177 out[3] = 1;
178 }
179
180 static void insert_4f_2( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in )
181 {
182 GLfloat *out = (GLfloat *)(v);
183
184 out[0] = in[0];
185 out[1] = in[1];
186 out[2] = 0;
187 out[3] = 1;
188 }
189
190 static void insert_4f_1( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in )
191 {
192 GLfloat *out = (GLfloat *)(v);
193
194 out[0] = in[0];
195 out[1] = 0;
196 out[2] = 0;
197 out[3] = 1;
198 }
199
200 static void insert_3f_xyw_4( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in )
201 {
202 GLfloat *out = (GLfloat *)(v);
203
204 out[0] = in[0];
205 out[1] = in[1];
206 out[2] = in[3];
207 }
208
209 static void insert_3f_xyw_err( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in )
210 {
211 abort();
212 }
213
214 static void insert_3f_3( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in )
215 {
216 GLfloat *out = (GLfloat *)(v);
217
218 out[0] = in[0];
219 out[1] = in[1];
220 out[2] = in[2];
221 }
222
223 static void insert_3f_2( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in )
224 {
225 GLfloat *out = (GLfloat *)(v);
226
227 out[0] = in[0];
228 out[1] = in[1];
229 out[2] = 0;
230 }
231
232 static void insert_3f_1( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in )
233 {
234 GLfloat *out = (GLfloat *)(v);
235
236 out[0] = in[0];
237 out[1] = 0;
238 out[2] = 0;
239 }
240
241
242 static void insert_2f_2( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in )
243 {
244 GLfloat *out = (GLfloat *)(v);
245
246 out[0] = in[0];
247 out[1] = in[1];
248 }
249
250 static void insert_2f_1( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in )
251 {
252 GLfloat *out = (GLfloat *)(v);
253
254 out[0] = in[0];
255 out[1] = 0;
256 }
257
258 static void insert_1f_1( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in )
259 {
260 GLfloat *out = (GLfloat *)(v);
261
262 out[0] = in[0];
263 }
264
265 static void insert_4chan_4f_rgba_4( const struct tnl_clipspace_attr *a, GLubyte *v,
266 const GLfloat *in )
267 {
268 GLchan *c = (GLchan *)v;
269 UNCLAMPED_FLOAT_TO_CHAN(c[0], in[0]);
270 UNCLAMPED_FLOAT_TO_CHAN(c[1], in[1]);
271 UNCLAMPED_FLOAT_TO_CHAN(c[2], in[2]);
272 UNCLAMPED_FLOAT_TO_CHAN(c[3], in[3]);
273 }
274
275 static void insert_4chan_4f_rgba_3( const struct tnl_clipspace_attr *a, GLubyte *v,
276 const GLfloat *in )
277 {
278 GLchan *c = (GLchan *)v;
279 UNCLAMPED_FLOAT_TO_CHAN(c[0], in[0]);
280 UNCLAMPED_FLOAT_TO_CHAN(c[1], in[1]);
281 UNCLAMPED_FLOAT_TO_CHAN(c[2], in[2]);
282 c[3] = CHAN_MAX;
283 }
284
285 static void insert_4chan_4f_rgba_2( const struct tnl_clipspace_attr *a, GLubyte *v,
286 const GLfloat *in )
287 {
288 GLchan *c = (GLchan *)v;
289 UNCLAMPED_FLOAT_TO_CHAN(c[0], in[0]);
290 UNCLAMPED_FLOAT_TO_CHAN(c[1], in[1]);
291 c[2] = 0;
292 c[3] = CHAN_MAX;
293 }
294
295 static void insert_4chan_4f_rgba_1( const struct tnl_clipspace_attr *a, GLubyte *v,
296 const GLfloat *in )
297 {
298 GLchan *c = (GLchan *)v;
299 UNCLAMPED_FLOAT_TO_CHAN(c[0], in[0]);
300 c[1] = 0;
301 c[2] = 0;
302 c[3] = CHAN_MAX;
303 }
304
305 static void insert_4ub_4f_rgba_4( const struct tnl_clipspace_attr *a, GLubyte *v,
306 const GLfloat *in )
307 {
308 UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]);
309 UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
310 UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[2]);
311 UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[3]);
312 }
313
314 static void insert_4ub_4f_rgba_3( const struct tnl_clipspace_attr *a, GLubyte *v,
315 const GLfloat *in )
316 {
317 UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]);
318 UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
319 UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[2]);
320 v[3] = 0xff;
321 }
322
323 static void insert_4ub_4f_rgba_2( const struct tnl_clipspace_attr *a, GLubyte *v,
324 const GLfloat *in )
325 {
326 UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]);
327 UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
328 v[2] = 0;
329 v[3] = 0xff;
330 }
331
332 static void insert_4ub_4f_rgba_1( const struct tnl_clipspace_attr *a, GLubyte *v,
333 const GLfloat *in )
334 {
335 UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]);
336 v[1] = 0;
337 v[2] = 0;
338 v[3] = 0xff;
339 }
340
341 static void insert_4ub_4f_bgra_4( const struct tnl_clipspace_attr *a, GLubyte *v,
342 const GLfloat *in )
343 {
344 UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[0]);
345 UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
346 UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[2]);
347 UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[3]);
348 }
349
350 static void insert_4ub_4f_bgra_3( const struct tnl_clipspace_attr *a, GLubyte *v,
351 const GLfloat *in )
352 {
353 UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[0]);
354 UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
355 UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[2]);
356 v[3] = 0xff;
357 }
358
359 static void insert_4ub_4f_bgra_2( const struct tnl_clipspace_attr *a, GLubyte *v,
360 const GLfloat *in )
361 {
362 UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[0]);
363 UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
364 v[0] = 0;
365 v[3] = 0xff;
366 }
367
368 static void insert_4ub_4f_bgra_1( const struct tnl_clipspace_attr *a, GLubyte *v,
369 const GLfloat *in )
370 {
371 UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[0]);
372 v[1] = 0;
373 v[0] = 0;
374 v[3] = 0xff;
375 }
376
377 static void insert_3ub_3f_rgb_3( const struct tnl_clipspace_attr *a, GLubyte *v,
378 const GLfloat *in )
379 {
380 UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]);
381 UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
382 UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[2]);
383 }
384
385 static void insert_3ub_3f_rgb_2( const struct tnl_clipspace_attr *a, GLubyte *v,
386 const GLfloat *in )
387 {
388 UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]);
389 UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
390 v[2] = 0;
391 }
392
393 static void insert_3ub_3f_rgb_1( const struct tnl_clipspace_attr *a, GLubyte *v,
394 const GLfloat *in )
395 {
396 UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]);
397 v[1] = 0;
398 v[2] = 0;
399 }
400
401 static void insert_3ub_3f_bgr_3( const struct tnl_clipspace_attr *a, GLubyte *v,
402 const GLfloat *in )
403 {
404 UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[0]);
405 UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
406 UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[2]);
407 }
408
409 static void insert_3ub_3f_bgr_2( const struct tnl_clipspace_attr *a, GLubyte *v,
410 const GLfloat *in )
411 {
412 UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[0]);
413 UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
414 v[0] = 0;
415 }
416
417 static void insert_3ub_3f_bgr_1( const struct tnl_clipspace_attr *a, GLubyte *v,
418 const GLfloat *in )
419 {
420 UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[0]);
421 v[1] = 0;
422 v[0] = 0;
423 }
424
425
426 static void insert_1ub_1f_1( const struct tnl_clipspace_attr *a, GLubyte *v,
427 const GLfloat *in )
428 {
429 UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]);
430 }
431
432
433 /***********************************************************************
434 * Functions to perform the reverse operations to the above, for
435 * swrast translation and clip-interpolation.
436 *
437 * Currently always extracts a full 4 floats.
438 */
439
440 static void extract_4f_viewport( const struct tnl_clipspace_attr *a, GLfloat *out,
441 const GLubyte *v )
442 {
443 const GLfloat *in = (const GLfloat *)v;
444 const GLfloat * const vp = a->vp;
445
446 /* Although included for completeness, the position coordinate is
447 * usually handled differently during clipping.
448 */
449 out[0] = (in[0] - vp[12]) / vp[0];
450 out[1] = (in[1] - vp[13]) / vp[5];
451 out[2] = (in[2] - vp[14]) / vp[10];
452 out[3] = in[3];
453 }
454
455 static void extract_3f_viewport( const struct tnl_clipspace_attr *a, GLfloat *out,
456 const GLubyte *v )
457 {
458 const GLfloat *in = (const GLfloat *)v;
459 const GLfloat * const vp = a->vp;
460
461 out[0] = (in[0] - vp[12]) / vp[0];
462 out[1] = (in[1] - vp[13]) / vp[5];
463 out[2] = (in[2] - vp[14]) / vp[10];
464 out[3] = 1;
465 }
466
467
468 static void extract_2f_viewport( const struct tnl_clipspace_attr *a, GLfloat *out,
469 const GLubyte *v )
470 {
471 const GLfloat *in = (const GLfloat *)v;
472 const GLfloat * const vp = a->vp;
473
474 out[0] = (in[0] - vp[12]) / vp[0];
475 out[1] = (in[1] - vp[13]) / vp[5];
476 out[2] = 0;
477 out[3] = 1;
478 }
479
480
481 static void extract_4f( const struct tnl_clipspace_attr *a, GLfloat *out, const GLubyte *v )
482 {
483 const GLfloat *in = (const GLfloat *)v;
484
485 out[0] = in[0];
486 out[1] = in[1];
487 out[2] = in[2];
488 out[3] = in[3];
489 }
490
491 static void extract_3f_xyw( const struct tnl_clipspace_attr *a, GLfloat *out, const GLubyte *v )
492 {
493 const GLfloat *in = (const GLfloat *)v;
494
495 out[0] = in[0];
496 out[1] = in[1];
497 out[2] = 0;
498 out[3] = in[2];
499 }
500
501
502 static void extract_3f( const struct tnl_clipspace_attr *a, GLfloat *out, const GLubyte *v )
503 {
504 const GLfloat *in = (const GLfloat *)v;
505
506 out[0] = in[0];
507 out[1] = in[1];
508 out[2] = in[2];
509 out[3] = 1;
510 }
511
512
513 static void extract_2f( const struct tnl_clipspace_attr *a, GLfloat *out, const GLubyte *v )
514 {
515 const GLfloat *in = (const GLfloat *)v;
516
517 out[0] = in[0];
518 out[1] = in[1];
519 out[2] = 0;
520 out[3] = 1;
521 }
522
523 static void extract_1f( const struct tnl_clipspace_attr *a, GLfloat *out, const GLubyte *v )
524 {
525 const GLfloat *in = (const GLfloat *)v;
526
527 out[0] = in[0];
528 out[1] = 0;
529 out[2] = 0;
530 out[3] = 1;
531 }
532
533 static void extract_4chan_4f_rgba( const struct tnl_clipspace_attr *a, GLfloat *out,
534 const GLubyte *v )
535 {
536 GLchan *c = (GLchan *)v;
537
538 out[0] = CHAN_TO_FLOAT(c[0]);
539 out[1] = CHAN_TO_FLOAT(c[1]);
540 out[2] = CHAN_TO_FLOAT(c[2]);
541 out[3] = CHAN_TO_FLOAT(c[3]);
542 }
543
544 static void extract_4ub_4f_rgba( const struct tnl_clipspace_attr *a, GLfloat *out,
545 const GLubyte *v )
546 {
547 out[0] = UBYTE_TO_FLOAT(v[0]);
548 out[1] = UBYTE_TO_FLOAT(v[1]);
549 out[2] = UBYTE_TO_FLOAT(v[2]);
550 out[3] = UBYTE_TO_FLOAT(v[3]);
551 }
552
553 static void extract_4ub_4f_bgra( const struct tnl_clipspace_attr *a, GLfloat *out,
554 const GLubyte *v )
555 {
556 out[2] = UBYTE_TO_FLOAT(v[0]);
557 out[1] = UBYTE_TO_FLOAT(v[1]);
558 out[0] = UBYTE_TO_FLOAT(v[2]);
559 out[3] = UBYTE_TO_FLOAT(v[3]);
560 }
561
562 static void extract_3ub_3f_rgb( const struct tnl_clipspace_attr *a, GLfloat *out,
563 const GLubyte *v )
564 {
565 out[0] = UBYTE_TO_FLOAT(v[0]);
566 out[1] = UBYTE_TO_FLOAT(v[1]);
567 out[2] = UBYTE_TO_FLOAT(v[2]);
568 out[3] = 1;
569 }
570
571 static void extract_3ub_3f_bgr( const struct tnl_clipspace_attr *a, GLfloat *out,
572 const GLubyte *v )
573 {
574 out[2] = UBYTE_TO_FLOAT(v[0]);
575 out[1] = UBYTE_TO_FLOAT(v[1]);
576 out[0] = UBYTE_TO_FLOAT(v[2]);
577 out[3] = 1;
578 }
579
580 static void extract_1ub_1f( const struct tnl_clipspace_attr *a, GLfloat *out, const GLubyte *v )
581 {
582 out[0] = UBYTE_TO_FLOAT(v[0]);
583 out[1] = 0;
584 out[2] = 0;
585 out[3] = 1;
586 }
587
588
589 static struct {
590 const char *name;
591 extract_func extract;
592 insert_func insert[4];
593 const GLuint attrsize;
594 } format_info[EMIT_MAX] = {
595
596 { "1f",
597 extract_1f,
598 { insert_1f_1, insert_1f_1, insert_1f_1, insert_1f_1 },
599 sizeof(GLfloat) },
600
601 { "2f",
602 extract_2f,
603 { insert_2f_1, insert_2f_2, insert_2f_2, insert_2f_2 },
604 2 * sizeof(GLfloat) },
605
606 { "3f",
607 extract_3f,
608 { insert_3f_1, insert_3f_2, insert_3f_3, insert_3f_3 },
609 3 * sizeof(GLfloat) },
610
611 { "4f",
612 extract_4f,
613 { insert_4f_1, insert_4f_2, insert_4f_3, insert_4f_4 },
614 4 * sizeof(GLfloat) },
615
616 { "2f_viewport",
617 extract_2f_viewport,
618 { insert_2f_viewport_1, insert_2f_viewport_2, insert_2f_viewport_2,
619 insert_2f_viewport_2 },
620 2 * sizeof(GLfloat) },
621
622 { "3f_viewport",
623 extract_3f_viewport,
624 { insert_3f_viewport_1, insert_3f_viewport_2, insert_3f_viewport_3,
625 insert_3f_viewport_3 },
626 3 * sizeof(GLfloat) },
627
628 { "4f_viewport",
629 extract_4f_viewport,
630 { insert_4f_viewport_1, insert_4f_viewport_2, insert_4f_viewport_3,
631 insert_4f_viewport_4 },
632 4 * sizeof(GLfloat) },
633
634 { "3f_xyw",
635 extract_3f_xyw,
636 { insert_3f_xyw_err, insert_3f_xyw_err, insert_3f_xyw_err,
637 insert_3f_xyw_4 },
638 3 * sizeof(GLfloat) },
639
640 { "1ub_1f",
641 extract_1ub_1f,
642 { insert_1ub_1f_1, insert_1ub_1f_1, insert_1ub_1f_1, insert_1ub_1f_1 },
643 sizeof(GLubyte) },
644
645 { "3ub_3f_rgb",
646 extract_3ub_3f_rgb,
647 { insert_3ub_3f_rgb_1, insert_3ub_3f_rgb_2, insert_3ub_3f_rgb_3,
648 insert_3ub_3f_rgb_3 },
649 3 * sizeof(GLubyte) },
650
651 { "3ub_3f_bgr",
652 extract_3ub_3f_bgr,
653 { insert_3ub_3f_bgr_1, insert_3ub_3f_bgr_2, insert_3ub_3f_bgr_3,
654 insert_3ub_3f_bgr_3 },
655 3 * sizeof(GLubyte) },
656
657 { "4ub_4f_rgba",
658 extract_4ub_4f_rgba,
659 { insert_4ub_4f_rgba_1, insert_4ub_4f_rgba_2, insert_4ub_4f_rgba_3,
660 insert_4ub_4f_rgba_4 },
661 4 * sizeof(GLubyte) },
662
663 { "4ub_4f_bgra",
664 extract_4ub_4f_bgra,
665 { insert_4ub_4f_bgra_1, insert_4ub_4f_bgra_2, insert_4ub_4f_bgra_3,
666 insert_4ub_4f_bgra_4 },
667 4 * sizeof(GLubyte) },
668
669 { "4chan_4f_rgba",
670 extract_4chan_4f_rgba,
671 { insert_4chan_4f_rgba_1, insert_4chan_4f_rgba_2, insert_4chan_4f_rgba_3,
672 insert_4chan_4f_rgba_4 },
673 4 * sizeof(GLchan) },
674
675 { "pad",
676 0,
677 { 0, 0, 0, 0 },
678 0 }
679
680 };
681
682
683 /***********************************************************************
684 * Generic (non-codegen) functions for whole vertices or groups of
685 * vertices
686 */
687
688 static void generic_emit( GLcontext *ctx,
689 GLuint start, GLuint end,
690 void *dest )
691 {
692 struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
693 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
694 struct tnl_clipspace_attr *a = vtx->attr;
695 GLubyte *v = (GLubyte *)dest;
696 GLuint i, j;
697 const GLuint count = vtx->attr_count;
698 GLuint stride;
699
700 for (j = 0; j < count; j++) {
701 GLvector4f *vptr = VB->AttribPtr[a[j].attrib];
702 a[j].inputstride = vptr->stride;
703 a[j].inputptr = ((GLubyte *)vptr->data) + start * vptr->stride;
704 a[j].emit = a[j].insert[vptr->size - 1];
705 }
706
707 end -= start;
708 stride = vtx->vertex_size;
709
710 for (i = 0 ; i < end ; i++, v += stride) {
711 for (j = 0; j < count; j++) {
712 GLfloat *in = (GLfloat *)a[j].inputptr;
713 a[j].inputptr += a[j].inputstride;
714 a[j].emit( &a[j], v + a[j].vertoffset, in );
715 }
716 }
717 }
718
719
720 static void generic_interp( GLcontext *ctx,
721 GLfloat t,
722 GLuint edst, GLuint eout, GLuint ein,
723 GLboolean force_boundary )
724 {
725 TNLcontext *tnl = TNL_CONTEXT(ctx);
726 struct vertex_buffer *VB = &tnl->vb;
727 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
728 const GLubyte *vin = vtx->vertex_buf + ein * vtx->vertex_size;
729 const GLubyte *vout = vtx->vertex_buf + eout * vtx->vertex_size;
730 GLubyte *vdst = vtx->vertex_buf + edst * vtx->vertex_size;
731 const struct tnl_clipspace_attr *a = vtx->attr;
732 const GLuint attr_count = vtx->attr_count;
733 GLuint j;
734
735 if (tnl->NeedNdcCoords) {
736 const GLfloat *dstclip = VB->ClipPtr->data[edst];
737 if (dstclip[3] != 0.0) {
738 const GLfloat w = 1.0f / dstclip[3];
739 GLfloat pos[4];
740
741 pos[0] = dstclip[0] * w;
742 pos[1] = dstclip[1] * w;
743 pos[2] = dstclip[2] * w;
744 pos[3] = w;
745
746 a[0].insert[4-1]( &a[0], vdst, pos );
747 }
748 }
749 else {
750 a[0].insert[4-1]( &a[0], vdst, VB->ClipPtr->data[edst] );
751 }
752
753
754 for (j = 1; j < attr_count; j++) {
755 GLfloat fin[4], fout[4], fdst[4];
756
757 a[j].extract( &a[j], fin, vin + a[j].vertoffset );
758 a[j].extract( &a[j], fout, vout + a[j].vertoffset );
759
760 INTERP_F( t, fdst[3], fout[3], fin[3] );
761 INTERP_F( t, fdst[2], fout[2], fin[2] );
762 INTERP_F( t, fdst[1], fout[1], fin[1] );
763 INTERP_F( t, fdst[0], fout[0], fin[0] );
764
765 a[j].insert[4-1]( &a[j], vdst + a[j].vertoffset, fdst );
766 }
767 }
768
769
770 /* Extract color attributes from one vertex and insert them into
771 * another. (Shortcircuit extract/insert with memcpy).
772 */
773 static void generic_copy_pv( GLcontext *ctx, GLuint edst, GLuint esrc )
774 {
775 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
776 GLubyte *vsrc = vtx->vertex_buf + esrc * vtx->vertex_size;
777 GLubyte *vdst = vtx->vertex_buf + edst * vtx->vertex_size;
778 const struct tnl_clipspace_attr *a = vtx->attr;
779 const GLuint attr_count = vtx->attr_count;
780 GLuint j;
781
782 for (j = 0; j < attr_count; j++) {
783 if (a[j].attrib == VERT_ATTRIB_COLOR0 ||
784 a[j].attrib == VERT_ATTRIB_COLOR1) {
785
786 _mesa_memcpy( vdst + a[j].vertoffset,
787 vsrc + a[j].vertoffset,
788 a[j].vertattrsize );
789 }
790 }
791 }
792
793
794 /* Helper functions for hardware which doesn't put back colors and/or
795 * edgeflags into vertices.
796 */
797 static void generic_interp_extras( GLcontext *ctx,
798 GLfloat t,
799 GLuint dst, GLuint out, GLuint in,
800 GLboolean force_boundary )
801 {
802 struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
803
804 if (VB->ColorPtr[1]) {
805 assert(VB->ColorPtr[1]->stride == 4 * sizeof(GLfloat));
806
807 INTERP_4F( t,
808 VB->ColorPtr[1]->data[dst],
809 VB->ColorPtr[1]->data[out],
810 VB->ColorPtr[1]->data[in] );
811
812 if (VB->SecondaryColorPtr[1]) {
813 INTERP_3F( t,
814 VB->SecondaryColorPtr[1]->data[dst],
815 VB->SecondaryColorPtr[1]->data[out],
816 VB->SecondaryColorPtr[1]->data[in] );
817 }
818 }
819 else if (VB->IndexPtr[1]) {
820 VB->IndexPtr[1]->data[dst][0] = LINTERP( t,
821 VB->IndexPtr[1]->data[out][0],
822 VB->IndexPtr[1]->data[in][0] );
823 }
824
825 if (VB->EdgeFlag) {
826 VB->EdgeFlag[dst] = VB->EdgeFlag[out] || force_boundary;
827 }
828
829 generic_interp(ctx, t, dst, out, in, force_boundary);
830 }
831
832 static void generic_copy_pv_extras( GLcontext *ctx,
833 GLuint dst, GLuint src )
834 {
835 struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
836
837 if (VB->ColorPtr[1]) {
838 COPY_4FV( VB->ColorPtr[1]->data[dst],
839 VB->ColorPtr[1]->data[src] );
840
841 if (VB->SecondaryColorPtr[1]) {
842 COPY_4FV( VB->SecondaryColorPtr[1]->data[dst],
843 VB->SecondaryColorPtr[1]->data[src] );
844 }
845 }
846 else if (VB->IndexPtr[1]) {
847 VB->IndexPtr[1]->data[dst][0] = VB->IndexPtr[1]->data[src][0];
848 }
849
850 generic_copy_pv(ctx, dst, src);
851 }
852
853
854
855
856 /***********************************************************************
857 * Build codegen functions or return generic ones:
858 */
859
860
861 static void do_emit( GLcontext *ctx, GLuint start, GLuint end,
862 void *dest)
863 {
864 TNLcontext *tnl = TNL_CONTEXT(ctx);
865 struct vertex_buffer *VB = &tnl->vb;
866 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
867 struct tnl_clipspace_attr *a = vtx->attr;
868 const GLuint count = vtx->attr_count;
869 GLuint j;
870
871 for (j = 0; j < count; j++) {
872 GLvector4f *vptr = VB->AttribPtr[a[j].attrib];
873 a[j].inputstride = vptr->stride;
874 a[j].inputptr = ((GLubyte *)vptr->data) + start * vptr->stride;
875 a[j].emit = a[j].insert[vptr->size - 1];
876 }
877
878 vtx->emit = 0;
879
880 if (0)
881 vtx->emit = _tnl_codegen_emit(ctx);
882
883 if (!vtx->emit)
884 vtx->emit = generic_emit;
885
886 vtx->emit( ctx, start, end, dest );
887 }
888
889
890
891 static void choose_interp_func( GLcontext *ctx,
892 GLfloat t,
893 GLuint edst, GLuint eout, GLuint ein,
894 GLboolean force_boundary )
895 {
896 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
897
898 if (vtx->need_extras &&
899 (ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED))) {
900 vtx->interp = generic_interp_extras;
901 } else {
902 vtx->interp = generic_interp;
903 }
904
905 vtx->interp( ctx, t, edst, eout, ein, force_boundary );
906 }
907
908
909 static void choose_copy_pv_func( GLcontext *ctx, GLuint edst, GLuint esrc )
910 {
911 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
912
913 if (vtx->need_extras &&
914 (ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED))) {
915 vtx->copy_pv = generic_copy_pv_extras;
916 } else {
917 vtx->copy_pv = generic_copy_pv;
918 }
919
920 vtx->copy_pv( ctx, edst, esrc );
921 }
922
923
924 /***********************************************************************
925 * Public entrypoints, mostly dispatch to the above:
926 */
927
928
929 /* Interpolate between two vertices to produce a third:
930 */
931 void _tnl_interp( GLcontext *ctx,
932 GLfloat t,
933 GLuint edst, GLuint eout, GLuint ein,
934 GLboolean force_boundary )
935 {
936 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
937 vtx->interp( ctx, t, edst, eout, ein, force_boundary );
938 }
939
940 /* Copy colors from one vertex to another:
941 */
942 void _tnl_copy_pv( GLcontext *ctx, GLuint edst, GLuint esrc )
943 {
944 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
945 vtx->copy_pv( ctx, edst, esrc );
946 }
947
948
949 /* Extract a named attribute from a hardware vertex. Will have to
950 * reverse any viewport transformation, swizzling or other conversions
951 * which may have been applied:
952 */
953 void _tnl_get_attr( GLcontext *ctx, const void *vin,
954 GLenum attr, GLfloat *dest )
955 {
956 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
957 const struct tnl_clipspace_attr *a = vtx->attr;
958 const GLuint attr_count = vtx->attr_count;
959 GLuint j;
960
961 for (j = 0; j < attr_count; j++) {
962 if (a[j].attrib == attr) {
963 a[j].extract( &a[j], dest, (GLubyte *)vin + a[j].vertoffset );
964 return;
965 }
966 }
967
968 /* Else return the value from ctx->Current -- dangerous???
969 */
970 _mesa_memcpy( dest, ctx->Current.Attrib[attr], 4*sizeof(GLfloat));
971 }
972
973
974 /* Complementary operation to the above.
975 */
976 void _tnl_set_attr( GLcontext *ctx, void *vout,
977 GLenum attr, const GLfloat *src )
978 {
979 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
980 const struct tnl_clipspace_attr *a = vtx->attr;
981 const GLuint attr_count = vtx->attr_count;
982 GLuint j;
983
984 for (j = 0; j < attr_count; j++) {
985 if (a[j].attrib == attr) {
986 a[j].insert[4-1]( &a[j], (GLubyte *)vout + a[j].vertoffset, src );
987 return;
988 }
989 }
990 }
991
992
993 void *_tnl_get_vertex( GLcontext *ctx, GLuint nr )
994 {
995 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
996
997 return vtx->vertex_buf + nr * vtx->vertex_size;
998 }
999
1000 void _tnl_invalidate_vertex_state( GLcontext *ctx, GLuint new_state )
1001 {
1002 if (new_state & (_DD_NEW_TRI_LIGHT_TWOSIDE|_DD_NEW_TRI_UNFILLED) ) {
1003 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
1004 vtx->new_inputs = ~0;
1005 vtx->interp = choose_interp_func;
1006 vtx->copy_pv = choose_copy_pv_func;
1007 }
1008 }
1009
1010
1011 GLuint _tnl_install_attrs( GLcontext *ctx, const struct tnl_attr_map *map,
1012 GLuint nr, const GLfloat *vp,
1013 GLuint unpacked_size )
1014 {
1015 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
1016 GLuint offset = 0;
1017 GLuint i, j;
1018
1019 assert(nr < _TNL_ATTRIB_MAX);
1020 assert(nr == 0 || map[0].attrib == VERT_ATTRIB_POS);
1021
1022 vtx->emit = 0;
1023 vtx->interp = choose_interp_func;
1024 vtx->copy_pv = choose_copy_pv_func;
1025 vtx->new_inputs = ~0;
1026
1027 for (j = 0, i = 0; i < nr; i++) {
1028 const GLuint format = map[i].format;
1029 if (format == EMIT_PAD) {
1030 fprintf(stderr, "%d: pad %d, offset %d\n", i,
1031 map[i].offset, offset);
1032
1033 offset += map[i].offset;
1034
1035 }
1036 else {
1037 vtx->attr[j].attrib = map[i].attrib;
1038 vtx->attr[j].format = format;
1039 vtx->attr[j].vp = vp;
1040 vtx->attr[j].insert = format_info[format].insert;
1041 vtx->attr[j].extract = format_info[format].extract;
1042 vtx->attr[j].vertattrsize = format_info[format].attrsize;
1043
1044 if (unpacked_size)
1045 vtx->attr[j].vertoffset = map[i].offset;
1046 else
1047 vtx->attr[j].vertoffset = offset;
1048
1049 fprintf(stderr, "%d: %s, vp %p, offset %d\n", i,
1050 format_info[format].name, (void *)vp,
1051 vtx->attr[j].vertoffset);
1052
1053 offset += format_info[format].attrsize;
1054 j++;
1055 }
1056 }
1057
1058 vtx->attr_count = j;
1059
1060 if (unpacked_size)
1061 vtx->vertex_size = unpacked_size;
1062 else
1063 vtx->vertex_size = offset;
1064
1065 assert(vtx->vertex_size <= vtx->max_vertex_size);
1066
1067 return vtx->vertex_size;
1068 }
1069
1070
1071
1072 void _tnl_invalidate_vertices( GLcontext *ctx, GLuint newinputs )
1073 {
1074 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
1075 vtx->new_inputs |= newinputs;
1076 }
1077
1078
1079 void _tnl_build_vertices( GLcontext *ctx,
1080 GLuint start,
1081 GLuint end,
1082 GLuint newinputs )
1083 {
1084 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
1085 const GLuint stride = vtx->vertex_size;
1086 GLubyte *vDest = ((GLubyte *)vtx->vertex_buf + (start*stride));
1087
1088 newinputs |= vtx->new_inputs;
1089 vtx->new_inputs = 0;
1090
1091 if (newinputs)
1092 do_emit( ctx, start, end, vDest );
1093 }
1094
1095
1096 void *_tnl_emit_vertices_to_buffer( GLcontext *ctx,
1097 GLuint start,
1098 GLuint end,
1099 void *dest )
1100 {
1101 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
1102 do_emit( ctx, start, end, dest );
1103 return (void *)((GLubyte *)dest + vtx->vertex_size * (end - start));
1104 }
1105
1106
1107 void _tnl_init_vertices( GLcontext *ctx,
1108 GLuint vb_size,
1109 GLuint max_vertex_size )
1110 {
1111 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
1112
1113 _tnl_install_attrs( ctx, 0, 0, 0, 0 );
1114
1115 vtx->need_extras = GL_TRUE;
1116 if (max_vertex_size > vtx->max_vertex_size) {
1117 _tnl_free_vertices( ctx );
1118 vtx->max_vertex_size = max_vertex_size;
1119 vtx->vertex_buf = (GLubyte *)ALIGN_CALLOC(vb_size * max_vertex_size, 32 );
1120 }
1121
1122 _tnl_init_c_codegen( &vtx->codegen );
1123 }
1124
1125
1126 void _tnl_free_vertices( GLcontext *ctx )
1127 {
1128 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
1129 if (vtx->vertex_buf) {
1130 ALIGN_FREE(vtx->vertex_buf);
1131 vtx->vertex_buf = 0;
1132 }
1133 }