8c8a207f1880f9e67ef19827433e4a49b5b2e73e
[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 static void choose_emit_func( GLcontext *ctx, GLuint count, GLubyte *dest);
45
46
47
48
49
50
51 /*
52 * These functions take the NDC coordinates pointed to by 'in', apply the
53 * NDC->Viewport mapping and store the results at 'v'.
54 */
55
56 static INLINE void insert_4f_viewport_4( const struct tnl_clipspace_attr *a, GLubyte *v,
57 const GLfloat *in )
58 {
59 GLfloat *out = (GLfloat *)v;
60 const GLfloat * const vp = a->vp;
61
62 out[0] = vp[0] * in[0] + vp[12];
63 out[1] = vp[5] * in[1] + vp[13];
64 out[2] = vp[10] * in[2] + vp[14];
65 out[3] = in[3];
66 }
67
68 static INLINE void insert_4f_viewport_3( const struct tnl_clipspace_attr *a, GLubyte *v,
69 const GLfloat *in )
70 {
71 GLfloat *out = (GLfloat *)v;
72 const GLfloat * const vp = a->vp;
73
74 out[0] = vp[0] * in[0] + vp[12];
75 out[1] = vp[5] * in[1] + vp[13];
76 out[2] = vp[10] * in[2] + vp[14];
77 out[3] = 1;
78 }
79
80 static INLINE void insert_4f_viewport_2( const struct tnl_clipspace_attr *a, GLubyte *v,
81 const GLfloat *in )
82 {
83 GLfloat *out = (GLfloat *)v;
84 const GLfloat * const vp = a->vp;
85
86 out[0] = vp[0] * in[0] + vp[12];
87 out[1] = vp[5] * in[1] + vp[13];
88 out[2] = vp[14];
89 out[3] = 1;
90 }
91
92 static INLINE void insert_4f_viewport_1( const struct tnl_clipspace_attr *a, GLubyte *v,
93 const GLfloat *in )
94 {
95 GLfloat *out = (GLfloat *)v;
96 const GLfloat * const vp = a->vp;
97
98 out[0] = vp[0] * in[0] + vp[12];
99 out[1] = vp[13];
100 out[2] = vp[14];
101 out[3] = 1;
102 }
103
104 static INLINE void insert_3f_viewport_3( const struct tnl_clipspace_attr *a, GLubyte *v,
105 const GLfloat *in )
106 {
107 GLfloat *out = (GLfloat *)v;
108 const GLfloat * const vp = a->vp;
109
110 out[0] = vp[0] * in[0] + vp[12];
111 out[1] = vp[5] * in[1] + vp[13];
112 out[2] = vp[10] * in[2] + vp[14];
113 }
114
115 static INLINE void insert_3f_viewport_2( const struct tnl_clipspace_attr *a, GLubyte *v,
116 const GLfloat *in )
117 {
118 GLfloat *out = (GLfloat *)v;
119 const GLfloat * const vp = a->vp;
120
121 out[0] = vp[0] * in[0] + vp[12];
122 out[1] = vp[5] * in[1] + vp[13];
123 out[2] = vp[10] * in[2] + vp[14];
124 }
125
126 static INLINE void insert_3f_viewport_1( const struct tnl_clipspace_attr *a, GLubyte *v,
127 const GLfloat *in )
128 {
129 GLfloat *out = (GLfloat *)v;
130 const GLfloat * const vp = a->vp;
131
132 out[0] = vp[0] * in[0] + vp[12];
133 out[1] = vp[13];
134 out[2] = vp[14];
135 }
136
137 static INLINE void insert_2f_viewport_2( const struct tnl_clipspace_attr *a, GLubyte *v,
138 const GLfloat *in )
139 {
140 GLfloat *out = (GLfloat *)v;
141 const GLfloat * const vp = a->vp;
142
143 out[0] = vp[0] * in[0] + vp[12];
144 out[1] = vp[5] * in[1] + vp[13];
145 }
146
147 static INLINE void insert_2f_viewport_1( const struct tnl_clipspace_attr *a, GLubyte *v,
148 const GLfloat *in )
149 {
150 GLfloat *out = (GLfloat *)v;
151 const GLfloat * const vp = a->vp;
152
153 out[0] = vp[0] * in[0] + vp[12];
154 out[1] = vp[13];
155 }
156
157
158 /*
159 * These functions do the same as above, except for the viewport mapping.
160 */
161
162 static INLINE void insert_4f_4( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in )
163 {
164 GLfloat *out = (GLfloat *)(v);
165 (void) a;
166
167 out[0] = in[0];
168 out[1] = in[1];
169 out[2] = in[2];
170 out[3] = in[3];
171 }
172
173 static INLINE void insert_4f_3( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in )
174 {
175 GLfloat *out = (GLfloat *)(v);
176 (void) a;
177
178 out[0] = in[0];
179 out[1] = in[1];
180 out[2] = in[2];
181 out[3] = 1;
182 }
183
184 static INLINE void insert_4f_2( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in )
185 {
186 GLfloat *out = (GLfloat *)(v);
187 (void) a;
188
189 out[0] = in[0];
190 out[1] = in[1];
191 out[2] = 0;
192 out[3] = 1;
193 }
194
195 static INLINE void insert_4f_1( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in )
196 {
197 GLfloat *out = (GLfloat *)(v);
198 (void) a;
199
200 out[0] = in[0];
201 out[1] = 0;
202 out[2] = 0;
203 out[3] = 1;
204 }
205
206 static INLINE void insert_3f_xyw_4( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in )
207 {
208 GLfloat *out = (GLfloat *)(v);
209 (void) a;
210
211 out[0] = in[0];
212 out[1] = in[1];
213 out[2] = in[3];
214 }
215
216 static INLINE void insert_3f_xyw_err( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in )
217 {
218 (void) a; (void) v; (void) in;
219 abort();
220 }
221
222 static INLINE void insert_3f_3( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in )
223 {
224 GLfloat *out = (GLfloat *)(v);
225 (void) a;
226
227 out[0] = in[0];
228 out[1] = in[1];
229 out[2] = in[2];
230 }
231
232 static INLINE void insert_3f_2( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in )
233 {
234 GLfloat *out = (GLfloat *)(v);
235 (void) a;
236
237 out[0] = in[0];
238 out[1] = in[1];
239 out[2] = 0;
240 }
241
242 static INLINE void insert_3f_1( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in )
243 {
244 GLfloat *out = (GLfloat *)(v);
245 (void) a;
246
247 out[0] = in[0];
248 out[1] = 0;
249 out[2] = 0;
250 }
251
252
253 static INLINE void insert_2f_2( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in )
254 {
255 GLfloat *out = (GLfloat *)(v);
256 (void) a;
257
258 out[0] = in[0];
259 out[1] = in[1];
260 }
261
262 static INLINE void insert_2f_1( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in )
263 {
264 GLfloat *out = (GLfloat *)(v);
265 (void) a;
266
267 out[0] = in[0];
268 out[1] = 0;
269 }
270
271 static INLINE void insert_1f_1( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in )
272 {
273 GLfloat *out = (GLfloat *)(v);
274 (void) a;
275
276 out[0] = in[0];
277 }
278
279 static INLINE void insert_4chan_4f_rgba_4( const struct tnl_clipspace_attr *a, GLubyte *v,
280 const GLfloat *in )
281 {
282 GLchan *c = (GLchan *)v;
283 (void) a;
284 UNCLAMPED_FLOAT_TO_CHAN(c[0], in[0]);
285 UNCLAMPED_FLOAT_TO_CHAN(c[1], in[1]);
286 UNCLAMPED_FLOAT_TO_CHAN(c[2], in[2]);
287 UNCLAMPED_FLOAT_TO_CHAN(c[3], in[3]);
288 }
289
290 static INLINE void insert_4chan_4f_rgba_3( const struct tnl_clipspace_attr *a, GLubyte *v,
291 const GLfloat *in )
292 {
293 GLchan *c = (GLchan *)v;
294 (void) a;
295 UNCLAMPED_FLOAT_TO_CHAN(c[0], in[0]);
296 UNCLAMPED_FLOAT_TO_CHAN(c[1], in[1]);
297 UNCLAMPED_FLOAT_TO_CHAN(c[2], in[2]);
298 c[3] = CHAN_MAX;
299 }
300
301 static INLINE void insert_4chan_4f_rgba_2( const struct tnl_clipspace_attr *a, GLubyte *v,
302 const GLfloat *in )
303 {
304 GLchan *c = (GLchan *)v;
305 (void) a;
306 UNCLAMPED_FLOAT_TO_CHAN(c[0], in[0]);
307 UNCLAMPED_FLOAT_TO_CHAN(c[1], in[1]);
308 c[2] = 0;
309 c[3] = CHAN_MAX;
310 }
311
312 static INLINE void insert_4chan_4f_rgba_1( const struct tnl_clipspace_attr *a, GLubyte *v,
313 const GLfloat *in )
314 {
315 GLchan *c = (GLchan *)v;
316 (void) a;
317 UNCLAMPED_FLOAT_TO_CHAN(c[0], in[0]);
318 c[1] = 0;
319 c[2] = 0;
320 c[3] = CHAN_MAX;
321 }
322
323 static INLINE void insert_4ub_4f_rgba_4( const struct tnl_clipspace_attr *a, GLubyte *v,
324 const GLfloat *in )
325 {
326 (void) a;
327 UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]);
328 UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
329 UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[2]);
330 UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[3]);
331 }
332
333 static INLINE void insert_4ub_4f_rgba_3( const struct tnl_clipspace_attr *a, GLubyte *v,
334 const GLfloat *in )
335 {
336 (void) a;
337 UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]);
338 UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
339 UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[2]);
340 v[3] = 0xff;
341 }
342
343 static INLINE void insert_4ub_4f_rgba_2( const struct tnl_clipspace_attr *a, GLubyte *v,
344 const GLfloat *in )
345 {
346 (void) a;
347 UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]);
348 UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
349 v[2] = 0;
350 v[3] = 0xff;
351 }
352
353 static INLINE void insert_4ub_4f_rgba_1( const struct tnl_clipspace_attr *a, GLubyte *v,
354 const GLfloat *in )
355 {
356 (void) a;
357 UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]);
358 v[1] = 0;
359 v[2] = 0;
360 v[3] = 0xff;
361 }
362
363 static INLINE void insert_4ub_4f_bgra_4( const struct tnl_clipspace_attr *a, GLubyte *v,
364 const GLfloat *in )
365 {
366 (void) a;
367 UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[0]);
368 UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
369 UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[2]);
370 UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[3]);
371 }
372
373 static INLINE void insert_4ub_4f_bgra_3( const struct tnl_clipspace_attr *a, GLubyte *v,
374 const GLfloat *in )
375 {
376 (void) a;
377 UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[0]);
378 UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
379 UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[2]);
380 v[3] = 0xff;
381 }
382
383 static INLINE void insert_4ub_4f_bgra_2( const struct tnl_clipspace_attr *a, GLubyte *v,
384 const GLfloat *in )
385 {
386 (void) a;
387 UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[0]);
388 UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
389 v[0] = 0;
390 v[3] = 0xff;
391 }
392
393 static INLINE void insert_4ub_4f_bgra_1( const struct tnl_clipspace_attr *a, GLubyte *v,
394 const GLfloat *in )
395 {
396 (void) a;
397 UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[0]);
398 v[1] = 0;
399 v[0] = 0;
400 v[3] = 0xff;
401 }
402
403 static INLINE void insert_4ub_4f_argb_4( const struct tnl_clipspace_attr *a, GLubyte *v,
404 const GLfloat *in )
405 {
406 (void) a;
407 UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[0]);
408 UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[1]);
409 UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[2]);
410 UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[3]);
411 }
412
413 static INLINE void insert_4ub_4f_argb_3( const struct tnl_clipspace_attr *a, GLubyte *v,
414 const GLfloat *in )
415 {
416 (void) a;
417 UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[0]);
418 UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[1]);
419 UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[2]);
420 v[0] = 0xff;
421 }
422
423 static INLINE void insert_4ub_4f_argb_2( const struct tnl_clipspace_attr *a, GLubyte *v,
424 const GLfloat *in )
425 {
426 (void) a;
427 UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[0]);
428 UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[1]);
429 v[3] = 0x00;
430 v[0] = 0xff;
431 }
432
433 static INLINE void insert_4ub_4f_argb_1( const struct tnl_clipspace_attr *a, GLubyte *v,
434 const GLfloat *in )
435 {
436 (void) a;
437 UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[0]);
438 v[2] = 0x00;
439 v[3] = 0x00;
440 v[0] = 0xff;
441 }
442
443 static INLINE void insert_4ub_4f_abgr_4( const struct tnl_clipspace_attr *a, GLubyte *v,
444 const GLfloat *in )
445 {
446 (void) a;
447 UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[0]);
448 UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[1]);
449 UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[2]);
450 UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[3]);
451 }
452
453 static INLINE void insert_4ub_4f_abgr_3( const struct tnl_clipspace_attr *a, GLubyte *v,
454 const GLfloat *in )
455 {
456 (void) a;
457 UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[0]);
458 UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[1]);
459 UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[2]);
460 v[0] = 0xff;
461 }
462
463 static INLINE void insert_4ub_4f_abgr_2( const struct tnl_clipspace_attr *a, GLubyte *v,
464 const GLfloat *in )
465 {
466 (void) a;
467 UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[0]);
468 UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[1]);
469 v[1] = 0x00;
470 v[0] = 0xff;
471 }
472
473 static INLINE void insert_4ub_4f_abgr_1( const struct tnl_clipspace_attr *a, GLubyte *v,
474 const GLfloat *in )
475 {
476 (void) a;
477 UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[0]);
478 v[2] = 0x00;
479 v[1] = 0x00;
480 v[0] = 0xff;
481 }
482
483 static INLINE void insert_3ub_3f_rgb_3( const struct tnl_clipspace_attr *a, GLubyte *v,
484 const GLfloat *in )
485 {
486 (void) a;
487 UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]);
488 UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
489 UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[2]);
490 }
491
492 static INLINE void insert_3ub_3f_rgb_2( const struct tnl_clipspace_attr *a, GLubyte *v,
493 const GLfloat *in )
494 {
495 (void) a;
496 UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]);
497 UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
498 v[2] = 0;
499 }
500
501 static INLINE void insert_3ub_3f_rgb_1( const struct tnl_clipspace_attr *a, GLubyte *v,
502 const GLfloat *in )
503 {
504 (void) a;
505 UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]);
506 v[1] = 0;
507 v[2] = 0;
508 }
509
510 static INLINE void insert_3ub_3f_bgr_3( const struct tnl_clipspace_attr *a, GLubyte *v,
511 const GLfloat *in )
512 {
513 (void) a;
514 UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[0]);
515 UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
516 UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[2]);
517 }
518
519 static INLINE void insert_3ub_3f_bgr_2( const struct tnl_clipspace_attr *a, GLubyte *v,
520 const GLfloat *in )
521 {
522 (void) a;
523 UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[0]);
524 UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
525 v[0] = 0;
526 }
527
528 static INLINE void insert_3ub_3f_bgr_1( const struct tnl_clipspace_attr *a, GLubyte *v,
529 const GLfloat *in )
530 {
531 (void) a;
532 UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[0]);
533 v[1] = 0;
534 v[0] = 0;
535 }
536
537
538 static INLINE void insert_1ub_1f_1( const struct tnl_clipspace_attr *a, GLubyte *v,
539 const GLfloat *in )
540 {
541 (void) a;
542 UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]);
543 }
544
545
546 /***********************************************************************
547 * Functions to perform the reverse operations to the above, for
548 * swrast translation and clip-interpolation.
549 *
550 * Currently always extracts a full 4 floats.
551 */
552
553 static void extract_4f_viewport( const struct tnl_clipspace_attr *a, GLfloat *out,
554 const GLubyte *v )
555 {
556 const GLfloat *in = (const GLfloat *)v;
557 const GLfloat * const vp = a->vp;
558
559 /* Although included for completeness, the position coordinate is
560 * usually handled differently during clipping.
561 */
562 out[0] = (in[0] - vp[12]) / vp[0];
563 out[1] = (in[1] - vp[13]) / vp[5];
564 out[2] = (in[2] - vp[14]) / vp[10];
565 out[3] = in[3];
566 }
567
568 static void extract_3f_viewport( const struct tnl_clipspace_attr *a, GLfloat *out,
569 const GLubyte *v )
570 {
571 const GLfloat *in = (const GLfloat *)v;
572 const GLfloat * const vp = a->vp;
573
574 out[0] = (in[0] - vp[12]) / vp[0];
575 out[1] = (in[1] - vp[13]) / vp[5];
576 out[2] = (in[2] - vp[14]) / vp[10];
577 out[3] = 1;
578 }
579
580
581 static void extract_2f_viewport( const struct tnl_clipspace_attr *a, GLfloat *out,
582 const GLubyte *v )
583 {
584 const GLfloat *in = (const GLfloat *)v;
585 const GLfloat * const vp = a->vp;
586
587 out[0] = (in[0] - vp[12]) / vp[0];
588 out[1] = (in[1] - vp[13]) / vp[5];
589 out[2] = 0;
590 out[3] = 1;
591 }
592
593
594 static void extract_4f( const struct tnl_clipspace_attr *a, GLfloat *out, const GLubyte *v )
595 {
596 const GLfloat *in = (const GLfloat *)v;
597 (void) a;
598
599 out[0] = in[0];
600 out[1] = in[1];
601 out[2] = in[2];
602 out[3] = in[3];
603 }
604
605 static void extract_3f_xyw( const struct tnl_clipspace_attr *a, GLfloat *out, const GLubyte *v )
606 {
607 const GLfloat *in = (const GLfloat *)v;
608 (void) a;
609
610 out[0] = in[0];
611 out[1] = in[1];
612 out[2] = 0;
613 out[3] = in[2];
614 }
615
616
617 static void extract_3f( const struct tnl_clipspace_attr *a, GLfloat *out, const GLubyte *v )
618 {
619 const GLfloat *in = (const GLfloat *)v;
620 (void) a;
621
622 out[0] = in[0];
623 out[1] = in[1];
624 out[2] = in[2];
625 out[3] = 1;
626 }
627
628
629 static void extract_2f( const struct tnl_clipspace_attr *a, GLfloat *out, const GLubyte *v )
630 {
631 const GLfloat *in = (const GLfloat *)v;
632 (void) a;
633
634 out[0] = in[0];
635 out[1] = in[1];
636 out[2] = 0;
637 out[3] = 1;
638 }
639
640 static void extract_1f( const struct tnl_clipspace_attr *a, GLfloat *out, const GLubyte *v )
641 {
642 const GLfloat *in = (const GLfloat *)v;
643 (void) a;
644
645 out[0] = in[0];
646 out[1] = 0;
647 out[2] = 0;
648 out[3] = 1;
649 }
650
651 static void extract_4chan_4f_rgba( const struct tnl_clipspace_attr *a, GLfloat *out,
652 const GLubyte *v )
653 {
654 GLchan *c = (GLchan *)v;
655 (void) a;
656
657 out[0] = CHAN_TO_FLOAT(c[0]);
658 out[1] = CHAN_TO_FLOAT(c[1]);
659 out[2] = CHAN_TO_FLOAT(c[2]);
660 out[3] = CHAN_TO_FLOAT(c[3]);
661 }
662
663 static void extract_4ub_4f_rgba( const struct tnl_clipspace_attr *a, GLfloat *out,
664 const GLubyte *v )
665 {
666 (void) a;
667 out[0] = UBYTE_TO_FLOAT(v[0]);
668 out[1] = UBYTE_TO_FLOAT(v[1]);
669 out[2] = UBYTE_TO_FLOAT(v[2]);
670 out[3] = UBYTE_TO_FLOAT(v[3]);
671 }
672
673 static void extract_4ub_4f_bgra( const struct tnl_clipspace_attr *a, GLfloat *out,
674 const GLubyte *v )
675 {
676 (void) a;
677 out[2] = UBYTE_TO_FLOAT(v[0]);
678 out[1] = UBYTE_TO_FLOAT(v[1]);
679 out[0] = UBYTE_TO_FLOAT(v[2]);
680 out[3] = UBYTE_TO_FLOAT(v[3]);
681 }
682
683 static void extract_4ub_4f_argb( const struct tnl_clipspace_attr *a, GLfloat *out,
684 const GLubyte *v )
685 {
686 (void) a;
687 out[3] = UBYTE_TO_FLOAT(v[0]);
688 out[0] = UBYTE_TO_FLOAT(v[1]);
689 out[1] = UBYTE_TO_FLOAT(v[2]);
690 out[2] = UBYTE_TO_FLOAT(v[3]);
691 }
692
693 static void extract_4ub_4f_abgr( const struct tnl_clipspace_attr *a, GLfloat *out,
694 const GLubyte *v )
695 {
696 (void) a;
697 out[3] = UBYTE_TO_FLOAT(v[0]);
698 out[2] = UBYTE_TO_FLOAT(v[1]);
699 out[1] = UBYTE_TO_FLOAT(v[2]);
700 out[0] = UBYTE_TO_FLOAT(v[3]);
701 }
702
703 static void extract_3ub_3f_rgb( const struct tnl_clipspace_attr *a, GLfloat *out,
704 const GLubyte *v )
705 {
706 (void) a;
707 out[0] = UBYTE_TO_FLOAT(v[0]);
708 out[1] = UBYTE_TO_FLOAT(v[1]);
709 out[2] = UBYTE_TO_FLOAT(v[2]);
710 out[3] = 1;
711 }
712
713 static void extract_3ub_3f_bgr( const struct tnl_clipspace_attr *a, GLfloat *out,
714 const GLubyte *v )
715 {
716 (void) a;
717 out[2] = UBYTE_TO_FLOAT(v[0]);
718 out[1] = UBYTE_TO_FLOAT(v[1]);
719 out[0] = UBYTE_TO_FLOAT(v[2]);
720 out[3] = 1;
721 }
722
723 static void extract_1ub_1f( const struct tnl_clipspace_attr *a, GLfloat *out, const GLubyte *v )
724 {
725 (void) a;
726 out[0] = UBYTE_TO_FLOAT(v[0]);
727 out[1] = 0;
728 out[2] = 0;
729 out[3] = 1;
730 }
731
732
733 static struct {
734 const char *name;
735 tnl_extract_func extract;
736 tnl_insert_func insert[4];
737 const GLuint attrsize;
738 } format_info[EMIT_MAX] = {
739
740 { "1f",
741 extract_1f,
742 { insert_1f_1, insert_1f_1, insert_1f_1, insert_1f_1 },
743 sizeof(GLfloat) },
744
745 { "2f",
746 extract_2f,
747 { insert_2f_1, insert_2f_2, insert_2f_2, insert_2f_2 },
748 2 * sizeof(GLfloat) },
749
750 { "3f",
751 extract_3f,
752 { insert_3f_1, insert_3f_2, insert_3f_3, insert_3f_3 },
753 3 * sizeof(GLfloat) },
754
755 { "4f",
756 extract_4f,
757 { insert_4f_1, insert_4f_2, insert_4f_3, insert_4f_4 },
758 4 * sizeof(GLfloat) },
759
760 { "2f_viewport",
761 extract_2f_viewport,
762 { insert_2f_viewport_1, insert_2f_viewport_2, insert_2f_viewport_2,
763 insert_2f_viewport_2 },
764 2 * sizeof(GLfloat) },
765
766 { "3f_viewport",
767 extract_3f_viewport,
768 { insert_3f_viewport_1, insert_3f_viewport_2, insert_3f_viewport_3,
769 insert_3f_viewport_3 },
770 3 * sizeof(GLfloat) },
771
772 { "4f_viewport",
773 extract_4f_viewport,
774 { insert_4f_viewport_1, insert_4f_viewport_2, insert_4f_viewport_3,
775 insert_4f_viewport_4 },
776 4 * sizeof(GLfloat) },
777
778 { "3f_xyw",
779 extract_3f_xyw,
780 { insert_3f_xyw_err, insert_3f_xyw_err, insert_3f_xyw_err,
781 insert_3f_xyw_4 },
782 3 * sizeof(GLfloat) },
783
784 { "1ub_1f",
785 extract_1ub_1f,
786 { insert_1ub_1f_1, insert_1ub_1f_1, insert_1ub_1f_1, insert_1ub_1f_1 },
787 sizeof(GLubyte) },
788
789 { "3ub_3f_rgb",
790 extract_3ub_3f_rgb,
791 { insert_3ub_3f_rgb_1, insert_3ub_3f_rgb_2, insert_3ub_3f_rgb_3,
792 insert_3ub_3f_rgb_3 },
793 3 * sizeof(GLubyte) },
794
795 { "3ub_3f_bgr",
796 extract_3ub_3f_bgr,
797 { insert_3ub_3f_bgr_1, insert_3ub_3f_bgr_2, insert_3ub_3f_bgr_3,
798 insert_3ub_3f_bgr_3 },
799 3 * sizeof(GLubyte) },
800
801 { "4ub_4f_rgba",
802 extract_4ub_4f_rgba,
803 { insert_4ub_4f_rgba_1, insert_4ub_4f_rgba_2, insert_4ub_4f_rgba_3,
804 insert_4ub_4f_rgba_4 },
805 4 * sizeof(GLubyte) },
806
807 { "4ub_4f_bgra",
808 extract_4ub_4f_bgra,
809 { insert_4ub_4f_bgra_1, insert_4ub_4f_bgra_2, insert_4ub_4f_bgra_3,
810 insert_4ub_4f_bgra_4 },
811 4 * sizeof(GLubyte) },
812
813 { "4ub_4f_argb",
814 extract_4ub_4f_argb,
815 { insert_4ub_4f_argb_1, insert_4ub_4f_argb_2, insert_4ub_4f_argb_3,
816 insert_4ub_4f_argb_4 },
817 4 * sizeof(GLubyte) },
818
819 { "4ub_4f_abgr",
820 extract_4ub_4f_abgr,
821 { insert_4ub_4f_abgr_1, insert_4ub_4f_abgr_2, insert_4ub_4f_abgr_3,
822 insert_4ub_4f_abgr_4 },
823 4 * sizeof(GLubyte) },
824
825 { "4chan_4f_rgba",
826 extract_4chan_4f_rgba,
827 { insert_4chan_4f_rgba_1, insert_4chan_4f_rgba_2, insert_4chan_4f_rgba_3,
828 insert_4chan_4f_rgba_4 },
829 4 * sizeof(GLchan) },
830
831 { "pad",
832 0,
833 { 0, 0, 0, 0 },
834 0 }
835
836 };
837
838
839
840
841 /***********************************************************************
842 * Hardwired fastpaths for emitting whole vertices or groups of
843 * vertices
844 */
845
846 static void emit_viewport3_rgba4( GLcontext *ctx,
847 GLuint count,
848 GLubyte *v )
849 {
850 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
851 struct tnl_clipspace_attr *a = vtx->attr;
852 GLuint i;
853
854 if (a[0].emit != insert_3f_viewport_3 ||
855 a[1].emit != insert_4ub_4f_rgba_4) {
856 choose_emit_func( ctx, count, v );
857 return;
858 }
859
860 for (i = 0 ; i < count ; i++, v += vtx->vertex_size) {
861 insert_3f_viewport_3( &a[0], v + a[0].vertoffset, (GLfloat *)a[0].inputptr );
862 a[0].inputptr += a[0].inputstride;
863
864 insert_4ub_4f_rgba_4( &a[1], v + a[1].vertoffset, (GLfloat *)a[1].inputptr );
865 a[1].inputptr += a[1].inputstride;
866 }
867 }
868
869
870 static void emit_viewport3_bgra4( GLcontext *ctx,
871 GLuint count,
872 GLubyte *v )
873 {
874 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
875 struct tnl_clipspace_attr *a = vtx->attr;
876 GLuint i;
877
878 if (a[0].emit != insert_3f_viewport_3 ||
879 a[1].emit != insert_4ub_4f_bgra_4) {
880 choose_emit_func( ctx, count, v );
881 return;
882 }
883
884 for (i = 0 ; i < count ; i++, v += vtx->vertex_size) {
885 insert_3f_viewport_3( &a[0], v + a[0].vertoffset, (GLfloat *)a[0].inputptr );
886 a[0].inputptr += a[0].inputstride;
887
888 insert_4ub_4f_bgra_4( &a[1], v + a[1].vertoffset, (GLfloat *)a[1].inputptr );
889 a[1].inputptr += a[1].inputstride;
890 }
891 }
892
893
894 static void emit_viewport4_rgba4_st2( GLcontext *ctx,
895 GLuint count,
896 GLubyte *v )
897 {
898 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
899 struct tnl_clipspace_attr *a = vtx->attr;
900 GLuint i;
901
902 if (a[0].emit != insert_4f_viewport_4 ||
903 a[1].emit != insert_4ub_4f_rgba_4 ||
904 a[2].emit != insert_2f_2) {
905 choose_emit_func( ctx, count, v );
906 return;
907 }
908
909 for (i = 0 ; i < count ; i++, v += vtx->vertex_size) {
910 insert_4f_viewport_4( &a[0], v + a[0].vertoffset, (GLfloat *)a[0].inputptr );
911 a[0].inputptr += a[0].inputstride;
912
913 insert_4ub_4f_rgba_4( &a[1], v + a[1].vertoffset, (GLfloat *)a[1].inputptr );
914 a[1].inputptr += a[1].inputstride;
915
916 insert_2f_2( &a[2], v + a[2].vertoffset, (GLfloat *)a[2].inputptr );
917 a[2].inputptr += a[2].inputstride;
918 }
919 }
920
921
922 static void emit_viewport4_bgra4_st2( GLcontext *ctx,
923 GLuint count,
924 GLubyte *v )
925 {
926 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
927 struct tnl_clipspace_attr *a = vtx->attr;
928 GLuint i;
929
930 if (a[0].emit != insert_4f_viewport_4 ||
931 a[1].emit != insert_4ub_4f_bgra_4 ||
932 a[2].emit != insert_2f_2) {
933 choose_emit_func( ctx, count, v );
934 return;
935 }
936
937 for (i = 0 ; i < count ; i++, v += vtx->vertex_size) {
938 insert_4f_viewport_4( &a[0], v + a[0].vertoffset, (GLfloat *)a[0].inputptr );
939 a[0].inputptr += a[0].inputstride;
940
941 insert_4ub_4f_bgra_4( &a[1], v + a[1].vertoffset, (GLfloat *)a[1].inputptr );
942 a[1].inputptr += a[1].inputstride;
943
944 insert_2f_2( &a[2], v + a[2].vertoffset, (GLfloat *)a[2].inputptr );
945 a[2].inputptr += a[2].inputstride;
946 }
947 }
948
949
950
951 static void emit_viewport4_rgba4_st2_st2( GLcontext *ctx,
952 GLuint count,
953 GLubyte *v )
954 {
955 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
956 struct tnl_clipspace_attr *a = vtx->attr;
957 GLuint i;
958
959 if (a[0].emit != insert_4f_viewport_4 ||
960 a[1].emit != insert_4ub_4f_rgba_4 ||
961 a[2].emit != insert_2f_2 ||
962 a[3].emit != insert_2f_2) {
963 choose_emit_func( ctx, count, v );
964 return;
965 }
966
967 for (i = 0 ; i < count ; i++, v += vtx->vertex_size) {
968 insert_4f_viewport_4( &a[0], v + a[0].vertoffset, (GLfloat *)a[0].inputptr );
969 a[0].inputptr += a[0].inputstride;
970
971 insert_4ub_4f_rgba_4( &a[1], v + a[1].vertoffset, (GLfloat *)a[1].inputptr );
972 a[1].inputptr += a[1].inputstride;
973
974 insert_2f_2( &a[2], v + a[2].vertoffset, (GLfloat *)a[2].inputptr );
975 a[2].inputptr += a[2].inputstride;
976
977 insert_2f_2( &a[3], v + a[3].vertoffset, (GLfloat *)a[3].inputptr );
978 a[3].inputptr += a[3].inputstride;
979 }
980 }
981
982
983
984 static void emit_viewport4_bgra4_st2_st2( GLcontext *ctx,
985 GLuint count,
986 GLubyte *v )
987 {
988 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
989 struct tnl_clipspace_attr *a = vtx->attr;
990 GLuint i;
991
992 if (a[0].emit != insert_4f_viewport_4 ||
993 a[1].emit != insert_4ub_4f_bgra_4 ||
994 a[2].emit != insert_2f_2 ||
995 a[3].emit != insert_2f_2) {
996 choose_emit_func( ctx, count, v );
997 return;
998 }
999
1000 for (i = 0 ; i < count ; i++, v += vtx->vertex_size) {
1001 insert_4f_viewport_4( &a[0], v + a[0].vertoffset, (GLfloat *)a[0].inputptr );
1002 a[0].inputptr += a[0].inputstride;
1003
1004 insert_4ub_4f_bgra_4( &a[1], v + a[1].vertoffset, (GLfloat *)a[1].inputptr );
1005 a[1].inputptr += a[1].inputstride;
1006
1007 insert_2f_2( &a[2], v + a[2].vertoffset, (GLfloat *)a[2].inputptr );
1008 a[2].inputptr += a[2].inputstride;
1009
1010 insert_2f_2( &a[3], v + a[3].vertoffset, (GLfloat *)a[3].inputptr );
1011 a[3].inputptr += a[3].inputstride;
1012 }
1013 }
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023 /***********************************************************************
1024 * Generic (non-codegen) functions for whole vertices or groups of
1025 * vertices
1026 */
1027
1028 static void generic_emit( GLcontext *ctx,
1029 GLuint count,
1030 GLubyte *v )
1031 {
1032 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
1033 struct tnl_clipspace_attr *a = vtx->attr;
1034 const GLuint attr_count = vtx->attr_count;
1035 const GLuint stride = vtx->vertex_size;
1036 GLuint i, j;
1037
1038 for (i = 0 ; i < count ; i++, v += stride) {
1039 for (j = 0; j < attr_count; j++) {
1040 GLfloat *in = (GLfloat *)a[j].inputptr;
1041 a[j].inputptr += a[j].inputstride;
1042 a[j].emit( &a[j], v + a[j].vertoffset, in );
1043 }
1044 }
1045 }
1046
1047
1048 static void generic_interp( GLcontext *ctx,
1049 GLfloat t,
1050 GLuint edst, GLuint eout, GLuint ein,
1051 GLboolean force_boundary )
1052 {
1053 TNLcontext *tnl = TNL_CONTEXT(ctx);
1054 struct vertex_buffer *VB = &tnl->vb;
1055 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
1056 const GLubyte *vin = vtx->vertex_buf + ein * vtx->vertex_size;
1057 const GLubyte *vout = vtx->vertex_buf + eout * vtx->vertex_size;
1058 GLubyte *vdst = vtx->vertex_buf + edst * vtx->vertex_size;
1059 const struct tnl_clipspace_attr *a = vtx->attr;
1060 const GLuint attr_count = vtx->attr_count;
1061 GLuint j;
1062 (void) force_boundary;
1063
1064 if (tnl->NeedNdcCoords) {
1065 const GLfloat *dstclip = VB->ClipPtr->data[edst];
1066 if (dstclip[3] != 0.0) {
1067 const GLfloat w = 1.0f / dstclip[3];
1068 GLfloat pos[4];
1069
1070 pos[0] = dstclip[0] * w;
1071 pos[1] = dstclip[1] * w;
1072 pos[2] = dstclip[2] * w;
1073 pos[3] = w;
1074
1075 a[0].insert[4-1]( &a[0], vdst, pos );
1076 }
1077 }
1078 else {
1079 a[0].insert[4-1]( &a[0], vdst, VB->ClipPtr->data[edst] );
1080 }
1081
1082
1083 for (j = 1; j < attr_count; j++) {
1084 GLfloat fin[4], fout[4], fdst[4];
1085
1086 a[j].extract( &a[j], fin, vin + a[j].vertoffset );
1087 a[j].extract( &a[j], fout, vout + a[j].vertoffset );
1088
1089 INTERP_F( t, fdst[3], fout[3], fin[3] );
1090 INTERP_F( t, fdst[2], fout[2], fin[2] );
1091 INTERP_F( t, fdst[1], fout[1], fin[1] );
1092 INTERP_F( t, fdst[0], fout[0], fin[0] );
1093
1094 a[j].insert[4-1]( &a[j], vdst + a[j].vertoffset, fdst );
1095 }
1096 }
1097
1098
1099 /* Extract color attributes from one vertex and insert them into
1100 * another. (Shortcircuit extract/insert with memcpy).
1101 */
1102 static void generic_copy_pv( GLcontext *ctx, GLuint edst, GLuint esrc )
1103 {
1104 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
1105 GLubyte *vsrc = vtx->vertex_buf + esrc * vtx->vertex_size;
1106 GLubyte *vdst = vtx->vertex_buf + edst * vtx->vertex_size;
1107 const struct tnl_clipspace_attr *a = vtx->attr;
1108 const GLuint attr_count = vtx->attr_count;
1109 GLuint j;
1110
1111 for (j = 0; j < attr_count; j++) {
1112 if (a[j].attrib == VERT_ATTRIB_COLOR0 ||
1113 a[j].attrib == VERT_ATTRIB_COLOR1) {
1114
1115 _mesa_memcpy( vdst + a[j].vertoffset,
1116 vsrc + a[j].vertoffset,
1117 a[j].vertattrsize );
1118 }
1119 }
1120 }
1121
1122
1123 /* Helper functions for hardware which doesn't put back colors and/or
1124 * edgeflags into vertices.
1125 */
1126 static void generic_interp_extras( GLcontext *ctx,
1127 GLfloat t,
1128 GLuint dst, GLuint out, GLuint in,
1129 GLboolean force_boundary )
1130 {
1131 struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
1132
1133 if (VB->ColorPtr[1]) {
1134 assert(VB->ColorPtr[1]->stride == 4 * sizeof(GLfloat));
1135
1136 INTERP_4F( t,
1137 VB->ColorPtr[1]->data[dst],
1138 VB->ColorPtr[1]->data[out],
1139 VB->ColorPtr[1]->data[in] );
1140
1141 if (VB->SecondaryColorPtr[1]) {
1142 INTERP_3F( t,
1143 VB->SecondaryColorPtr[1]->data[dst],
1144 VB->SecondaryColorPtr[1]->data[out],
1145 VB->SecondaryColorPtr[1]->data[in] );
1146 }
1147 }
1148 else if (VB->IndexPtr[1]) {
1149 VB->IndexPtr[1]->data[dst][0] = LINTERP( t,
1150 VB->IndexPtr[1]->data[out][0],
1151 VB->IndexPtr[1]->data[in][0] );
1152 }
1153
1154 if (VB->EdgeFlag) {
1155 VB->EdgeFlag[dst] = VB->EdgeFlag[out] || force_boundary;
1156 }
1157
1158 generic_interp(ctx, t, dst, out, in, force_boundary);
1159 }
1160
1161 static void generic_copy_pv_extras( GLcontext *ctx,
1162 GLuint dst, GLuint src )
1163 {
1164 struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
1165
1166 if (VB->ColorPtr[1]) {
1167 COPY_4FV( VB->ColorPtr[1]->data[dst],
1168 VB->ColorPtr[1]->data[src] );
1169
1170 if (VB->SecondaryColorPtr[1]) {
1171 COPY_4FV( VB->SecondaryColorPtr[1]->data[dst],
1172 VB->SecondaryColorPtr[1]->data[src] );
1173 }
1174 }
1175 else if (VB->IndexPtr[1]) {
1176 VB->IndexPtr[1]->data[dst][0] = VB->IndexPtr[1]->data[src][0];
1177 }
1178
1179 generic_copy_pv(ctx, dst, src);
1180 }
1181
1182
1183
1184
1185 /***********************************************************************
1186 * Build codegen functions or return generic ones:
1187 */
1188
1189
1190 static void choose_emit_func( GLcontext *ctx, GLuint count, GLubyte *dest)
1191 {
1192 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
1193 struct tnl_clipspace_attr *a = vtx->attr;
1194 const GLuint attr_count = vtx->attr_count;
1195
1196 vtx->emit = 0;
1197
1198 if (0)
1199 vtx->emit = _tnl_codegen_emit(ctx);
1200
1201 /* Does it fit a hardwired fastpath?
1202 */
1203 switch (attr_count) {
1204 case 2:
1205 if (a[0].emit == insert_3f_viewport_3) {
1206 if (a[1].emit == insert_4ub_4f_bgra_4)
1207 vtx->emit = emit_viewport3_bgra4;
1208 else if (a[1].emit == insert_4ub_4f_rgba_4)
1209 vtx->emit = emit_viewport3_rgba4;
1210 }
1211 break;
1212 case 3:
1213 if (a[0].emit == insert_4f_viewport_4 &&
1214 a[2].emit == insert_2f_2) {
1215 if (a[1].emit == insert_4ub_4f_bgra_4)
1216 vtx->emit = emit_viewport4_bgra4_st2;
1217 else if (a[1].emit == insert_4ub_4f_rgba_4)
1218 vtx->emit = emit_viewport4_rgba4_st2;
1219 }
1220 break;
1221 case 4:
1222 if (a[0].emit == insert_4f_viewport_4 &&
1223 a[2].emit == insert_2f_2 &&
1224 a[3].emit == insert_2f_2) {
1225 if (a[1].emit == insert_4ub_4f_bgra_4)
1226 vtx->emit = emit_viewport4_bgra4_st2_st2;
1227 else if (a[1].emit == insert_4ub_4f_rgba_4)
1228 vtx->emit = emit_viewport4_rgba4_st2_st2;
1229 }
1230 }
1231
1232 /* Otherwise use the generic version:
1233 */
1234 if (!vtx->emit)
1235 vtx->emit = generic_emit;
1236
1237 vtx->emit( ctx, count, dest );
1238 }
1239
1240
1241
1242 static void choose_interp_func( GLcontext *ctx,
1243 GLfloat t,
1244 GLuint edst, GLuint eout, GLuint ein,
1245 GLboolean force_boundary )
1246 {
1247 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
1248
1249 if (vtx->need_extras &&
1250 (ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED))) {
1251 vtx->interp = generic_interp_extras;
1252 } else {
1253 vtx->interp = generic_interp;
1254 }
1255
1256 vtx->interp( ctx, t, edst, eout, ein, force_boundary );
1257 }
1258
1259
1260 static void choose_copy_pv_func( GLcontext *ctx, GLuint edst, GLuint esrc )
1261 {
1262 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
1263
1264 if (vtx->need_extras &&
1265 (ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED))) {
1266 vtx->copy_pv = generic_copy_pv_extras;
1267 } else {
1268 vtx->copy_pv = generic_copy_pv;
1269 }
1270
1271 vtx->copy_pv( ctx, edst, esrc );
1272 }
1273
1274
1275 /***********************************************************************
1276 * Public entrypoints, mostly dispatch to the above:
1277 */
1278
1279
1280 /* Interpolate between two vertices to produce a third:
1281 */
1282 void _tnl_interp( GLcontext *ctx,
1283 GLfloat t,
1284 GLuint edst, GLuint eout, GLuint ein,
1285 GLboolean force_boundary )
1286 {
1287 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
1288 vtx->interp( ctx, t, edst, eout, ein, force_boundary );
1289 }
1290
1291 /* Copy colors from one vertex to another:
1292 */
1293 void _tnl_copy_pv( GLcontext *ctx, GLuint edst, GLuint esrc )
1294 {
1295 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
1296 vtx->copy_pv( ctx, edst, esrc );
1297 }
1298
1299
1300 /* Extract a named attribute from a hardware vertex. Will have to
1301 * reverse any viewport transformation, swizzling or other conversions
1302 * which may have been applied:
1303 */
1304 void _tnl_get_attr( GLcontext *ctx, const void *vin,
1305 GLenum attr, GLfloat *dest )
1306 {
1307 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
1308 const struct tnl_clipspace_attr *a = vtx->attr;
1309 const GLuint attr_count = vtx->attr_count;
1310 GLuint j;
1311
1312 for (j = 0; j < attr_count; j++) {
1313 if (a[j].attrib == attr) {
1314 a[j].extract( &a[j], dest, (GLubyte *)vin + a[j].vertoffset );
1315 return;
1316 }
1317 }
1318
1319 /* Else return the value from ctx->Current -- dangerous???
1320 */
1321 _mesa_memcpy( dest, ctx->Current.Attrib[attr], 4*sizeof(GLfloat));
1322 }
1323
1324
1325 /* Complementary operation to the above.
1326 */
1327 void _tnl_set_attr( GLcontext *ctx, void *vout,
1328 GLenum attr, const GLfloat *src )
1329 {
1330 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
1331 const struct tnl_clipspace_attr *a = vtx->attr;
1332 const GLuint attr_count = vtx->attr_count;
1333 GLuint j;
1334
1335 for (j = 0; j < attr_count; j++) {
1336 if (a[j].attrib == attr) {
1337 a[j].insert[4-1]( &a[j], (GLubyte *)vout + a[j].vertoffset, src );
1338 return;
1339 }
1340 }
1341 }
1342
1343
1344 void *_tnl_get_vertex( GLcontext *ctx, GLuint nr )
1345 {
1346 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
1347
1348 return vtx->vertex_buf + nr * vtx->vertex_size;
1349 }
1350
1351 void _tnl_invalidate_vertex_state( GLcontext *ctx, GLuint new_state )
1352 {
1353 if (new_state & (_DD_NEW_TRI_LIGHT_TWOSIDE|_DD_NEW_TRI_UNFILLED) ) {
1354 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
1355 vtx->new_inputs = ~0;
1356 vtx->interp = choose_interp_func;
1357 vtx->copy_pv = choose_copy_pv_func;
1358 }
1359 }
1360
1361
1362 GLuint _tnl_install_attrs( GLcontext *ctx, const struct tnl_attr_map *map,
1363 GLuint nr, const GLfloat *vp,
1364 GLuint unpacked_size )
1365 {
1366 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
1367 GLuint offset = 0;
1368 GLuint i, j;
1369
1370 assert(nr < _TNL_ATTRIB_MAX);
1371 assert(nr == 0 || map[0].attrib == VERT_ATTRIB_POS);
1372
1373 vtx->emit = choose_emit_func;
1374 vtx->interp = choose_interp_func;
1375 vtx->copy_pv = choose_copy_pv_func;
1376 vtx->new_inputs = ~0;
1377
1378 for (j = 0, i = 0; i < nr; i++) {
1379 const GLuint format = map[i].format;
1380 if (format == EMIT_PAD) {
1381 /*
1382 fprintf(stderr, "%d: pad %d, offset %d\n", i,
1383 map[i].offset, offset);
1384 */
1385 offset += map[i].offset;
1386
1387 }
1388 else {
1389 vtx->attr[j].attrib = map[i].attrib;
1390 vtx->attr[j].format = format;
1391 vtx->attr[j].vp = vp;
1392 vtx->attr[j].insert = format_info[format].insert;
1393 vtx->attr[j].extract = format_info[format].extract;
1394 vtx->attr[j].vertattrsize = format_info[format].attrsize;
1395
1396 if (unpacked_size)
1397 vtx->attr[j].vertoffset = map[i].offset;
1398 else
1399 vtx->attr[j].vertoffset = offset;
1400
1401 /*
1402 fprintf(stderr, "%d: %s, vp %p, offset %d\n", i,
1403 format_info[format].name, (void *)vp,
1404 vtx->attr[j].vertoffset);
1405 */
1406 offset += format_info[format].attrsize;
1407 j++;
1408 }
1409 }
1410
1411 vtx->attr_count = j;
1412
1413 if (unpacked_size)
1414 vtx->vertex_size = unpacked_size;
1415 else
1416 vtx->vertex_size = offset;
1417
1418 assert(vtx->vertex_size <= vtx->max_vertex_size);
1419
1420 return vtx->vertex_size;
1421 }
1422
1423
1424
1425 void _tnl_invalidate_vertices( GLcontext *ctx, GLuint newinputs )
1426 {
1427 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
1428 vtx->new_inputs |= newinputs;
1429 }
1430
1431
1432 void _tnl_build_vertices( GLcontext *ctx,
1433 GLuint start,
1434 GLuint end,
1435 GLuint newinputs )
1436 {
1437 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
1438
1439 newinputs |= vtx->new_inputs;
1440 vtx->new_inputs = 0;
1441
1442 if (newinputs) {
1443 struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
1444 struct tnl_clipspace_attr *a = vtx->attr;
1445 const GLuint stride = vtx->vertex_size;
1446 const GLuint count = vtx->attr_count;
1447 GLuint j;
1448
1449 for (j = 0; j < count; j++) {
1450 GLvector4f *vptr = VB->AttribPtr[a[j].attrib];
1451 a[j].inputstride = vptr->stride;
1452 a[j].inputptr = ((GLubyte *)vptr->data) + start * vptr->stride;
1453 a[j].emit = a[j].insert[vptr->size - 1];
1454 }
1455
1456 vtx->emit( ctx, end - start,
1457 (GLubyte *)vtx->vertex_buf + start * stride );
1458 }
1459 }
1460
1461
1462 void *_tnl_emit_vertices_to_buffer( GLcontext *ctx,
1463 GLuint start,
1464 GLuint end,
1465 void *dest )
1466 {
1467 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
1468 struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
1469 struct tnl_clipspace_attr *a = vtx->attr;
1470 const GLuint count = vtx->attr_count;
1471 GLuint j;
1472
1473 for (j = 0; j < count; j++) {
1474 GLvector4f *vptr = VB->AttribPtr[a[j].attrib];
1475 a[j].inputstride = vptr->stride;
1476 a[j].inputptr = ((GLubyte *)vptr->data) + start * vptr->stride;
1477 a[j].emit = a[j].insert[vptr->size - 1];
1478 }
1479
1480 /* Note: dest should not be adjusted for non-zero 'start' values:
1481 */
1482 vtx->emit( ctx, end - start, dest );
1483
1484 return (void *)((GLubyte *)dest + vtx->vertex_size * (end - start));
1485 }
1486
1487
1488 void _tnl_init_vertices( GLcontext *ctx,
1489 GLuint vb_size,
1490 GLuint max_vertex_size )
1491 {
1492 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
1493
1494 _tnl_install_attrs( ctx, 0, 0, 0, 0 );
1495
1496 vtx->need_extras = GL_TRUE;
1497 if (max_vertex_size > vtx->max_vertex_size) {
1498 _tnl_free_vertices( ctx );
1499 vtx->max_vertex_size = max_vertex_size;
1500 vtx->vertex_buf = (GLubyte *)ALIGN_CALLOC(vb_size * max_vertex_size, 32 );
1501 }
1502
1503 _tnl_init_c_codegen( &vtx->codegen );
1504 }
1505
1506
1507 void _tnl_free_vertices( GLcontext *ctx )
1508 {
1509 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
1510 if (vtx->vertex_buf) {
1511 ALIGN_FREE(vtx->vertex_buf);
1512 vtx->vertex_buf = 0;
1513 }
1514 }