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