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