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