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