Re-commit t_vertex.[ch] changes to fd.o server.
[mesa.git] / src / mesa / tnl / t_vertex.c
1 /*
2 * Copyright 2003 Tungsten Graphics, inc.
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * on the rights to use, copy, modify, merge, publish, distribute, sub
9 * license, and/or sell copies of the Software, and to permit persons to whom
10 * the Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
14 * Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19 * TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
20 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
21 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
22 * USE OR OTHER DEALINGS IN THE SOFTWARE.
23 *
24 * Authors:
25 * Keith Whitwell <keithw@tungstengraphics.com>
26 */
27
28 #include "glheader.h"
29 #include "context.h"
30 #include "colormac.h"
31
32 #include "t_context.h"
33 #include "t_vertex.h"
34
35
36 /* Build and manage clipspace/ndc/window vertices.
37 *
38 * Another new mechanism designed and crying out for codegen. Before
39 * that, it would be very interesting to investigate the merger of
40 * these vertices and those built in t_vtx_*.
41 */
42
43
44
45 #define GET_VERTEX_STATE(ctx) &(TNL_CONTEXT(ctx)->clipspace)
46
47 static void insert_4f_viewport( const struct tnl_clipspace_attr *a, char *v,
48 const GLfloat *in )
49 {
50 GLfloat *out = (GLfloat *)v;
51 const GLfloat * const vp = a->vp;
52
53 out[0] = vp[0] * in[0] + vp[12];
54 out[1] = vp[5] * in[1] + vp[13];
55 out[2] = vp[10] * in[2] + vp[14];
56 out[3] = in[3];
57 }
58
59 static void insert_3f_viewport( const struct tnl_clipspace_attr *a, char *v,
60 const GLfloat *in )
61 {
62 GLfloat *out = (GLfloat *)v;
63 const GLfloat * const vp = a->vp;
64
65 out[0] = vp[0] * in[0] + vp[12];
66 out[1] = vp[5] * in[1] + vp[13];
67 out[2] = vp[10] * in[2] + vp[14];
68 }
69
70 static void insert_2f_viewport( const struct tnl_clipspace_attr *a, char *v,
71 const GLfloat *in )
72 {
73 GLfloat *out = (GLfloat *)v;
74 const GLfloat * const vp = a->vp;
75
76 out[0] = vp[0] * in[0] + vp[12];
77 out[1] = vp[5] * in[1] + vp[13];
78 }
79
80
81 static void insert_4f( const struct tnl_clipspace_attr *a, char *v, const GLfloat *in )
82 {
83 GLfloat *out = (GLfloat *)(v);
84
85 out[0] = in[0];
86 out[1] = in[1];
87 out[2] = in[2];
88 out[3] = in[3];
89 }
90
91 static void insert_3f_xyw( const struct tnl_clipspace_attr *a, char *v, const GLfloat *in )
92 {
93 GLfloat *out = (GLfloat *)(v);
94
95 out[0] = in[0];
96 out[1] = in[1];
97 out[2] = in[3];
98 }
99
100
101 static void insert_3f( const struct tnl_clipspace_attr *a, char *v, const GLfloat *in )
102 {
103 GLfloat *out = (GLfloat *)(v);
104
105 out[0] = in[0];
106 out[1] = in[1];
107 out[2] = in[2];
108 }
109
110
111 static void insert_2f( const struct tnl_clipspace_attr *a, char *v, const GLfloat *in )
112 {
113 GLfloat *out = (GLfloat *)(v);
114
115 out[0] = in[0];
116 out[1] = in[1];
117 }
118
119 static void insert_1f( const struct tnl_clipspace_attr *a, char *v, const GLfloat *in )
120 {
121 GLfloat *out = (GLfloat *)(v);
122
123 out[0] = in[0];
124 }
125
126 static void insert_3f_pad( const struct tnl_clipspace_attr *a, char *v, const GLfloat *in )
127 {
128 GLfloat *out = (GLfloat *)(v);
129
130 out[0] = in[0];
131 out[1] = in[1];
132 out[2] = in[2];
133 out[3] = 1;
134 }
135
136
137 static void insert_2f_pad( const struct tnl_clipspace_attr *a, char *v, const GLfloat *in )
138 {
139 GLfloat *out = (GLfloat *)(v);
140
141 out[0] = in[0];
142 out[1] = in[1];
143 out[2] = 0;
144 out[3] = 1;
145 }
146
147 static void insert_1f_pad( const struct tnl_clipspace_attr *a, char *v, const GLfloat *in )
148 {
149 GLfloat *out = (GLfloat *)(v);
150
151 out[0] = in[0];
152 out[1] = 0;
153 out[2] = 0;
154 out[3] = 1;
155 }
156
157 static void insert_4chan_4f_rgba( const struct tnl_clipspace_attr *a, char *v,
158 const GLfloat *in )
159 {
160 GLchan *c = (GLchan *)v;
161 UNCLAMPED_FLOAT_TO_CHAN(c[0], in[0]);
162 UNCLAMPED_FLOAT_TO_CHAN(c[1], in[1]);
163 UNCLAMPED_FLOAT_TO_CHAN(c[2], in[2]);
164 UNCLAMPED_FLOAT_TO_CHAN(c[3], in[3]);
165 }
166
167 static void insert_4ub_4f_rgba( const struct tnl_clipspace_attr *a, char *v,
168 const GLfloat *in )
169 {
170 UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]);
171 UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
172 UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[2]);
173 UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[3]);
174 }
175
176 static void insert_4ub_4f_bgra( const struct tnl_clipspace_attr *a, char *v,
177 const GLfloat *in )
178 {
179 UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[0]);
180 UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
181 UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[2]);
182 UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[3]);
183 }
184
185 static void insert_3ub_3f_rgb( const struct tnl_clipspace_attr *a, char *v,
186 const GLfloat *in )
187 {
188 UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]);
189 UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
190 UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[2]);
191 }
192
193 static void insert_3ub_3f_bgr( const struct tnl_clipspace_attr *a, char *v,
194 const GLfloat *in )
195 {
196 UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[0]);
197 UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
198 UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[2]);
199 }
200
201 static void insert_1ub_1f( const struct tnl_clipspace_attr *a, char *v,
202 const GLfloat *in )
203 {
204 UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]);
205 }
206
207
208 /***********************************************************************
209 * Functions to perform the reverse operations to the above, for
210 * swrast translation and clip-interpolation.
211 *
212 * Currently always extracts a full 4 floats.
213 */
214
215 static void extract_4f_viewport( const struct tnl_clipspace_attr *a, GLfloat *out,
216 const char *v )
217 {
218 const GLfloat *in = (const GLfloat *)v;
219 const GLfloat * const vp = a->vp;
220
221 out[0] = (in[0] - vp[12]) / vp[0];
222 out[1] = (in[1] - vp[13]) / vp[5];
223 out[2] = (in[2] - vp[14]) / vp[10];
224 out[3] = in[3];
225 }
226
227 static void extract_3f_viewport( const struct tnl_clipspace_attr *a, GLfloat *out,
228 const char *v )
229 {
230 const GLfloat *in = (const GLfloat *)v;
231 const GLfloat * const vp = a->vp;
232
233 out[0] = (in[0] - vp[12]) / vp[0];
234 out[1] = (in[1] - vp[13]) / vp[5];
235 out[2] = (in[2] - vp[14]) / vp[10];
236 out[3] = 1;
237 }
238
239
240 static void extract_2f_viewport( const struct tnl_clipspace_attr *a, GLfloat *out,
241 const char *v )
242 {
243 const GLfloat *in = (const GLfloat *)v;
244 const GLfloat * const vp = a->vp;
245
246 out[0] = (in[0] - vp[12]) / vp[0];
247 out[1] = (in[1] - vp[13]) / vp[5];
248 out[2] = 0;
249 out[3] = 1;
250 }
251
252
253 static void extract_4f( const struct tnl_clipspace_attr *a, GLfloat *out, const char *v )
254 {
255 const GLfloat *in = (const GLfloat *)v;
256
257 out[0] = in[0];
258 out[1] = in[1];
259 out[2] = in[2];
260 out[3] = in[3];
261 }
262
263 static void extract_3f_xyw( const struct tnl_clipspace_attr *a, GLfloat *out, const char *v )
264 {
265 const GLfloat *in = (const GLfloat *)v;
266
267 out[0] = in[0];
268 out[1] = in[1];
269 out[2] = in[3];
270 out[3] = 1;
271 }
272
273
274 static void extract_3f( const struct tnl_clipspace_attr *a, GLfloat *out, const char *v )
275 {
276 const GLfloat *in = (const GLfloat *)v;
277
278 out[0] = in[0];
279 out[1] = in[1];
280 out[2] = in[2];
281 out[3] = 1;
282 }
283
284
285 static void extract_2f( const struct tnl_clipspace_attr *a, GLfloat *out, const char *v )
286 {
287 const GLfloat *in = (const GLfloat *)v;
288
289 out[0] = in[0];
290 out[1] = in[1];
291 out[2] = 0;
292 out[3] = 1;
293 }
294
295 static void extract_1f( const struct tnl_clipspace_attr *a, GLfloat *out, const char *v )
296 {
297 const GLfloat *in = (const GLfloat *)v;
298
299 out[0] = in[0];
300 out[1] = 0;
301 out[2] = 0;
302 out[3] = 1;
303 }
304
305 static void extract_4chan_4f_rgba( const struct tnl_clipspace_attr *a, GLfloat *out,
306 const char *v )
307 {
308 GLchan *c = (GLchan *)v;
309
310 out[0] = CHAN_TO_FLOAT(c[0]);
311 out[1] = CHAN_TO_FLOAT(c[1]);
312 out[2] = CHAN_TO_FLOAT(c[2]);
313 out[3] = CHAN_TO_FLOAT(c[3]);
314 }
315
316 static void extract_4ub_4f_rgba( const struct tnl_clipspace_attr *a, GLfloat *out,
317 const char *v )
318 {
319 out[0] = UBYTE_TO_FLOAT(v[0]);
320 out[1] = UBYTE_TO_FLOAT(v[1]);
321 out[2] = UBYTE_TO_FLOAT(v[2]);
322 out[3] = UBYTE_TO_FLOAT(v[3]);
323 }
324
325 static void extract_4ub_4f_bgra( const struct tnl_clipspace_attr *a, GLfloat *out,
326 const char *v )
327 {
328 out[2] = UBYTE_TO_FLOAT(v[0]);
329 out[1] = UBYTE_TO_FLOAT(v[1]);
330 out[0] = UBYTE_TO_FLOAT(v[2]);
331 out[3] = UBYTE_TO_FLOAT(v[3]);
332 }
333
334 static void extract_3ub_3f_rgb( const struct tnl_clipspace_attr *a, GLfloat *out,
335 const char *v )
336 {
337 out[0] = UBYTE_TO_FLOAT(v[0]);
338 out[1] = UBYTE_TO_FLOAT(v[1]);
339 out[2] = UBYTE_TO_FLOAT(v[2]);
340 out[3] = 1;
341 }
342
343 static void extract_3ub_3f_bgr( const struct tnl_clipspace_attr *a, GLfloat *out,
344 const char *v )
345 {
346 out[2] = UBYTE_TO_FLOAT(v[0]);
347 out[1] = UBYTE_TO_FLOAT(v[1]);
348 out[0] = UBYTE_TO_FLOAT(v[2]);
349 out[3] = 1;
350 }
351
352 static void extract_1ub_1f( const struct tnl_clipspace_attr *a, GLfloat *out, const char *v )
353 {
354 out[0] = UBYTE_TO_FLOAT(v[0]);
355 out[1] = 0;
356 out[2] = 0;
357 out[3] = 1;
358 }
359
360
361 typedef void (*extract_func)( const struct tnl_clipspace_attr *a, GLfloat *out,
362 const char *v );
363
364 typedef void (*insert_func)( const struct tnl_clipspace_attr *a, char *v, const GLfloat *in );
365
366
367 struct {
368 extract_func extract;
369 insert_func insert;
370 GLuint attrsize;
371 } format_info[EMIT_MAX] = {
372
373 { extract_1f,
374 insert_1f,
375 sizeof(GLfloat) },
376
377 { extract_2f,
378 insert_2f,
379 2 * sizeof(GLfloat) },
380
381 { extract_3f,
382 insert_3f,
383 3 * sizeof(GLfloat) },
384
385 { extract_4f,
386 insert_4f,
387 4 * sizeof(GLfloat) },
388
389 { extract_2f_viewport,
390 insert_2f_viewport,
391 2 * sizeof(GLfloat) },
392
393 { extract_3f_viewport,
394 insert_3f_viewport,
395 3 * sizeof(GLfloat) },
396
397 { extract_4f_viewport,
398 insert_4f_viewport,
399 4 * sizeof(GLfloat) },
400
401 { extract_3f_xyw,
402 insert_3f_xyw,
403 3 * sizeof(GLfloat) },
404
405 { extract_1ub_1f,
406 insert_1ub_1f,
407 sizeof(GLubyte) },
408
409 { extract_3ub_3f_rgb,
410 insert_3ub_3f_rgb,
411 3 * sizeof(GLubyte) },
412
413 { extract_3ub_3f_bgr,
414 insert_3ub_3f_bgr,
415 3 * sizeof(GLubyte) },
416
417 { extract_4ub_4f_rgba,
418 insert_4ub_4f_rgba,
419 4 * sizeof(GLubyte) },
420
421 { extract_4ub_4f_bgra,
422 insert_4ub_4f_bgra,
423 4 * sizeof(GLubyte) },
424
425 { extract_4chan_4f_rgba,
426 insert_4chan_4f_rgba,
427 4 * sizeof(GLchan) },
428
429 { extract_1f,
430 insert_1f_pad,
431 4 * sizeof(GLfloat) },
432
433 { extract_2f,
434 insert_2f_pad,
435 4 * sizeof(GLfloat) },
436
437 { extract_3f,
438 insert_3f_pad,
439 4 * sizeof(GLfloat) },
440
441
442 };
443
444
445 /***********************************************************************
446 * Generic (non-codegen) functions for whole vertices or groups of
447 * vertices
448 */
449
450 static void generic_emit( GLcontext *ctx,
451 GLuint start, GLuint end,
452 void *dest )
453 {
454 struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
455 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
456 struct tnl_clipspace_attr *a = vtx->attr;
457 char *v = (char *)dest;
458 int i, j;
459 GLuint count = vtx->attr_count;
460 GLuint stride;
461
462 for (j = 0; j < count; j++) {
463 GLvector4f *vptr = VB->AttribPtr[a[j].attrib];
464 a[j].inputstride = vptr->stride;
465 a[j].inputptr = (GLfloat *)STRIDE_4F(vptr->data, start * vptr->stride);
466 }
467
468 end -= start;
469 stride = vtx->vertex_size;
470
471 for (i = 0 ; i < end ; i++, v += stride) {
472 for (j = 0; j < count; j++) {
473 GLfloat *in = a[j].inputptr;
474 (char *)a[j].inputptr += a[j].inputstride;
475 a[j].insert( &a[j], v + a[j].vertoffset, in );
476 }
477 }
478 }
479
480
481 static void generic_interp( GLcontext *ctx,
482 GLfloat t,
483 GLuint edst, GLuint eout, GLuint ein,
484 GLboolean force_boundary )
485 {
486 TNLcontext *tnl = TNL_CONTEXT(ctx);
487 struct vertex_buffer *VB = &tnl->vb;
488 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
489 char *vin = vtx->vertex_buf + ein * vtx->vertex_size;
490 char *vout = vtx->vertex_buf + eout * vtx->vertex_size;
491 char *vdst = vtx->vertex_buf + edst * vtx->vertex_size;
492 const struct tnl_clipspace_attr *a = vtx->attr;
493 int attr_count = vtx->attr_count;
494 int j;
495
496 if (tnl->NeedNdcCoords) {
497 const GLfloat *dstclip = VB->ClipPtr->data[edst];
498 const GLfloat w = 1.0 / dstclip[3];
499 GLfloat pos[4];
500
501 pos[0] = dstclip[0] * w;
502 pos[1] = dstclip[1] * w;
503 pos[2] = dstclip[2] * w;
504 pos[3] = w;
505
506 a[0].insert( &a[0], vdst, pos );
507 }
508 else {
509 a[0].insert( &a[0], vdst, VB->ClipPtr->data[edst] );
510 }
511
512
513 for (j = 1; j < attr_count; j++) {
514 GLfloat fin[4], fout[4], fdst[4];
515
516 a[j].extract( &a[j], fin, vin + a[j].vertoffset );
517 a[j].extract( &a[j], fout, vout + a[j].vertoffset );
518
519 INTERP_F( t, fdst[3], fout[3], fin[3] );
520 INTERP_F( t, fdst[2], fout[2], fin[2] );
521 INTERP_F( t, fdst[1], fout[1], fin[1] );
522 INTERP_F( t, fdst[0], fout[0], fin[0] );
523
524 a[j].insert( &a[j], vdst + a[j].vertoffset, fdst );
525 }
526 }
527
528
529 /* Extract color attributes from one vertex and insert them into
530 * another. (Shortcircuit extract/insert with memcpy).
531 */
532 static void generic_copy_pv( GLcontext *ctx, GLuint edst, GLuint esrc )
533 {
534 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
535 char *vsrc = vtx->vertex_buf + esrc * vtx->vertex_size;
536 char *vdst = vtx->vertex_buf + edst * vtx->vertex_size;
537 const struct tnl_clipspace_attr *a = vtx->attr;
538 int attr_count = vtx->attr_count;
539 int j;
540
541 for (j = 0; j < attr_count; j++) {
542 if (a[j].attrib == VERT_ATTRIB_COLOR0 ||
543 a[j].attrib == VERT_ATTRIB_COLOR1) {
544
545 memcpy( vdst + a[j].vertoffset,
546 vsrc + a[j].vertoffset,
547 a[j].vertattrsize );
548 }
549 }
550 }
551
552
553 /* Helper functions for hardware which doesn't put back colors and/or
554 * edgeflags into vertices.
555 */
556 static void generic_interp_extras( GLcontext *ctx,
557 GLfloat t,
558 GLuint dst, GLuint out, GLuint in,
559 GLboolean force_boundary )
560 {
561 struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
562
563 if (VB->ColorPtr[1]) {
564 assert(VB->ColorPtr[1]->stride == 4 * sizeof(GLfloat));
565
566 INTERP_4F( t,
567 VB->ColorPtr[1]->data[dst],
568 VB->ColorPtr[1]->data[out],
569 VB->ColorPtr[1]->data[in] );
570
571 if (VB->SecondaryColorPtr[1]) {
572 INTERP_3F( t,
573 VB->SecondaryColorPtr[1]->data[dst],
574 VB->SecondaryColorPtr[1]->data[out],
575 VB->SecondaryColorPtr[1]->data[in] );
576 }
577 }
578
579 if (VB->EdgeFlag) {
580 VB->EdgeFlag[dst] = VB->EdgeFlag[out] || force_boundary;
581 }
582
583 generic_interp(ctx, t, dst, out, in, force_boundary);
584 }
585
586 static void generic_copy_pv_extras( GLcontext *ctx,
587 GLuint dst, GLuint src )
588 {
589 struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
590
591 if (VB->ColorPtr[1]) {
592 COPY_4FV( VB->ColorPtr[1]->data[dst],
593 VB->ColorPtr[1]->data[src] );
594
595 if (VB->SecondaryColorPtr[1]) {
596 COPY_4FV( VB->SecondaryColorPtr[1]->data[dst],
597 VB->SecondaryColorPtr[1]->data[src] );
598 }
599 }
600
601 _tnl_copy_pv(ctx, dst, src);
602 }
603
604
605
606
607
608
609 /***********************************************************************
610 * Build codegen functions or return generic ones:
611 */
612
613
614 static void choose_emit_func( GLcontext *ctx,
615 GLuint start, GLuint end,
616 void *dest )
617 {
618 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
619 vtx->emit = generic_emit;
620 vtx->emit( ctx, start, end, dest );
621 }
622
623
624 static void choose_interp_func( GLcontext *ctx,
625 GLfloat t,
626 GLuint edst, GLuint eout, GLuint ein,
627 GLboolean force_boundary )
628 {
629 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
630
631 if (vtx->need_extras &&
632 (ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED))) {
633 vtx->interp = generic_interp_extras;
634 } else {
635 vtx->interp = generic_interp;
636 }
637
638 vtx->interp( ctx, t, edst, eout, ein, force_boundary );
639 }
640
641
642 static void choose_copy_pv_func( GLcontext *ctx, GLuint edst, GLuint esrc )
643 {
644 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
645
646 if (vtx->need_extras &&
647 (ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED))) {
648 vtx->copy_pv = generic_copy_pv_extras;
649 } else {
650 vtx->copy_pv = generic_copy_pv;
651 }
652
653 vtx->copy_pv( ctx, edst, esrc );
654 }
655
656
657 /***********************************************************************
658 * Public entrypoints, mostly dispatch to the above:
659 */
660
661
662 /* Interpolate between two vertices to produce a third:
663 */
664 void _tnl_interp( GLcontext *ctx,
665 GLfloat t,
666 GLuint edst, GLuint eout, GLuint ein,
667 GLboolean force_boundary )
668 {
669 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
670 vtx->interp( ctx, t, edst, eout, ein, force_boundary );
671 }
672
673 /* Copy colors from one vertex to another:
674 */
675 void _tnl_copy_pv( GLcontext *ctx, GLuint edst, GLuint esrc )
676 {
677 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
678 vtx->copy_pv( ctx, edst, esrc );
679 }
680
681
682 /* Extract a named attribute from a hardware vertex. Will have to
683 * reverse any viewport transformation, swizzling or other conversions
684 * which may have been applied:
685 */
686 void _tnl_get_attr( GLcontext *ctx, const void *vin,
687 GLenum attr, GLfloat *dest )
688 {
689 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
690 const struct tnl_clipspace_attr *a = vtx->attr;
691 int attr_count = vtx->attr_count;
692 int j;
693
694 for (j = 0; j < attr_count; j++) {
695 if (a[j].attrib == attr) {
696 a[j].extract( &a[j], dest, vin );
697 return;
698 }
699 }
700
701 /* Else return the value from ctx->Current
702 */
703 memcpy( dest, ctx->Current.Attrib[attr], 4*sizeof(GLfloat));
704 }
705
706 void *_tnl_get_vertex( GLcontext *ctx, GLuint nr )
707 {
708 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
709
710 return vtx->vertex_buf + nr * vtx->vertex_size;
711 }
712
713 void _tnl_invalidate_vertex_state( GLcontext *ctx, GLuint new_state )
714 {
715 if (new_state & (_DD_NEW_TRI_LIGHT_TWOSIDE|_DD_NEW_TRI_UNFILLED) ) {
716 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
717 vtx->new_inputs = ~0;
718 vtx->interp = choose_interp_func;
719 vtx->copy_pv = choose_copy_pv_func;
720 }
721 }
722
723
724 GLuint _tnl_install_attrs( GLcontext *ctx, const struct tnl_attr_map *map,
725 GLuint nr, const GLfloat *vp )
726 {
727 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
728 int offset = 0;
729 int i;
730
731 assert(nr < _TNL_ATTRIB_MAX);
732 assert(nr == 0 || map[0].attrib == VERT_ATTRIB_POS);
733
734 vtx->attr_count = nr;
735 vtx->emit = choose_emit_func;
736 vtx->interp = choose_interp_func;
737 vtx->copy_pv = choose_copy_pv_func;
738 vtx->new_inputs = ~0;
739
740 for (i = 0; i < nr; i++) {
741 GLuint format = map[i].format;
742 vtx->attr[i].attrib = map[i].attrib;
743 /* vtx->attr[i].format = map[i].format; */
744 vtx->attr[i].vp = vp;
745 vtx->attr[i].insert = format_info[format].insert;
746 vtx->attr[i].extract = format_info[format].extract;
747 vtx->attr[i].vertattrsize = format_info[format].attrsize;
748 vtx->attr[i].vertoffset = offset;
749 offset += format_info[format].attrsize;
750 }
751
752 assert(offset <= vtx->max_vertex_size);
753
754 vtx->vertex_size = offset;
755
756 return vtx->vertex_size;
757 }
758
759
760
761 void _tnl_invalidate_vertices( GLcontext *ctx, GLuint newinputs )
762 {
763 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
764 vtx->new_inputs |= newinputs;
765 }
766
767
768
769 void _tnl_build_vertices( GLcontext *ctx,
770 GLuint start,
771 GLuint count,
772 GLuint newinputs )
773 {
774 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
775 GLuint stride = vtx->vertex_size;
776 GLubyte *v = ((GLubyte *)vtx->vertex_buf + (start*stride));
777
778 newinputs |= vtx->new_inputs;
779 vtx->new_inputs = 0;
780
781 if (newinputs)
782 vtx->emit( ctx, start, count, v );
783 }
784
785
786 void *_tnl_emit_vertices_to_buffer( GLcontext *ctx,
787 GLuint start,
788 GLuint count,
789 void *dest )
790 {
791 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
792 vtx->emit( ctx, start, count, dest );
793 return (void *)((char *)dest + vtx->vertex_size * (count - start));
794 }
795
796
797 void _tnl_init_vertices( GLcontext *ctx,
798 GLuint vb_size,
799 GLuint max_vertex_size )
800 {
801 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
802
803 _tnl_install_attrs( ctx, 0, 0, 0 );
804
805 vtx->need_extras = GL_TRUE;
806 vtx->max_vertex_size = max_vertex_size;
807 vtx->vertex_buf = (char *)ALIGN_MALLOC(vb_size * 4 * 18, max_vertex_size);
808 }
809
810
811 void _tnl_free_vertices( GLcontext *ctx )
812 {
813 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
814 if (vtx->vertex_buf) {
815 ALIGN_FREE(vtx->vertex_buf);
816 vtx->vertex_buf = 0;
817 }
818 }