2 * Copyright 2003 Tungsten Graphics, inc.
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:
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
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.
25 * Keith Whitwell <keithw@tungstengraphics.com>
32 #include "t_context.h"
36 /* Build and manage clipspace/ndc/window vertices.
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_*.
49 * These functions take the NDC coordinates pointed to by 'in', apply the
50 * NDC->Viewport mapping and store the results at 'v'.
54 insert_4f_viewport_4( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
57 GLfloat
*out
= (GLfloat
*)v
;
58 const GLfloat
* const vp
= a
->vp
;
60 out
[0] = vp
[0] * in
[0] + vp
[12];
61 out
[1] = vp
[5] * in
[1] + vp
[13];
62 out
[2] = vp
[10] * in
[2] + vp
[14];
66 static void insert_4f_viewport_3( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
69 GLfloat
*out
= (GLfloat
*)v
;
70 const GLfloat
* const vp
= a
->vp
;
72 out
[0] = vp
[0] * in
[0] + vp
[12];
73 out
[1] = vp
[5] * in
[1] + vp
[13];
74 out
[2] = vp
[10] * in
[2] + vp
[14];
78 static void insert_4f_viewport_2( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
81 GLfloat
*out
= (GLfloat
*)v
;
82 const GLfloat
* const vp
= a
->vp
;
84 out
[0] = vp
[0] * in
[0] + vp
[12];
85 out
[1] = vp
[5] * in
[1] + vp
[13];
90 static void insert_4f_viewport_1( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
93 GLfloat
*out
= (GLfloat
*)v
;
94 const GLfloat
* const vp
= a
->vp
;
96 out
[0] = vp
[0] * in
[0] + vp
[12];
102 static void insert_3f_viewport_3( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
105 GLfloat
*out
= (GLfloat
*)v
;
106 const GLfloat
* const vp
= a
->vp
;
108 out
[0] = vp
[0] * in
[0] + vp
[12];
109 out
[1] = vp
[5] * in
[1] + vp
[13];
110 out
[2] = vp
[10] * in
[2] + vp
[14];
113 static void insert_3f_viewport_2( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
116 GLfloat
*out
= (GLfloat
*)v
;
117 const GLfloat
* const vp
= a
->vp
;
119 out
[0] = vp
[0] * in
[0] + vp
[12];
120 out
[1] = vp
[5] * in
[1] + vp
[13];
121 out
[2] = vp
[10] * in
[2] + vp
[14];
124 static void insert_3f_viewport_1( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
127 GLfloat
*out
= (GLfloat
*)v
;
128 const GLfloat
* const vp
= a
->vp
;
130 out
[0] = vp
[0] * in
[0] + vp
[12];
135 static void insert_2f_viewport_2( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
138 GLfloat
*out
= (GLfloat
*)v
;
139 const GLfloat
* const vp
= a
->vp
;
141 out
[0] = vp
[0] * in
[0] + vp
[12];
142 out
[1] = vp
[5] * in
[1] + vp
[13];
145 static void insert_2f_viewport_1( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
148 GLfloat
*out
= (GLfloat
*)v
;
149 const GLfloat
* const vp
= a
->vp
;
151 out
[0] = vp
[0] * in
[0] + vp
[12];
157 * These functions do the same as above, except for the viewport mapping.
160 static void insert_4f_4( const struct tnl_clipspace_attr
*a
, GLubyte
*v
, const GLfloat
*in
)
162 GLfloat
*out
= (GLfloat
*)(v
);
170 static void insert_4f_3( const struct tnl_clipspace_attr
*a
, GLubyte
*v
, const GLfloat
*in
)
172 GLfloat
*out
= (GLfloat
*)(v
);
180 static void insert_4f_2( const struct tnl_clipspace_attr
*a
, GLubyte
*v
, const GLfloat
*in
)
182 GLfloat
*out
= (GLfloat
*)(v
);
190 static void insert_4f_1( const struct tnl_clipspace_attr
*a
, GLubyte
*v
, const GLfloat
*in
)
192 GLfloat
*out
= (GLfloat
*)(v
);
200 static void insert_3f_xyw_4( const struct tnl_clipspace_attr
*a
, GLubyte
*v
, const GLfloat
*in
)
202 GLfloat
*out
= (GLfloat
*)(v
);
209 static void insert_3f_xyw_err( const struct tnl_clipspace_attr
*a
, GLubyte
*v
, const GLfloat
*in
)
214 static void insert_3f_3( const struct tnl_clipspace_attr
*a
, GLubyte
*v
, const GLfloat
*in
)
216 GLfloat
*out
= (GLfloat
*)(v
);
223 static void insert_3f_2( const struct tnl_clipspace_attr
*a
, GLubyte
*v
, const GLfloat
*in
)
225 GLfloat
*out
= (GLfloat
*)(v
);
232 static void insert_3f_1( const struct tnl_clipspace_attr
*a
, GLubyte
*v
, const GLfloat
*in
)
234 GLfloat
*out
= (GLfloat
*)(v
);
242 static void insert_2f_2( const struct tnl_clipspace_attr
*a
, GLubyte
*v
, const GLfloat
*in
)
244 GLfloat
*out
= (GLfloat
*)(v
);
250 static void insert_2f_1( const struct tnl_clipspace_attr
*a
, GLubyte
*v
, const GLfloat
*in
)
252 GLfloat
*out
= (GLfloat
*)(v
);
258 static void insert_1f_1( const struct tnl_clipspace_attr
*a
, GLubyte
*v
, const GLfloat
*in
)
260 GLfloat
*out
= (GLfloat
*)(v
);
265 static void insert_4chan_4f_rgba_4( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
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 UNCLAMPED_FLOAT_TO_CHAN(c
[3], in
[3]);
275 static void insert_4chan_4f_rgba_3( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
278 GLchan
*c
= (GLchan
*)v
;
279 UNCLAMPED_FLOAT_TO_CHAN(c
[0], in
[0]);
280 UNCLAMPED_FLOAT_TO_CHAN(c
[1], in
[1]);
281 UNCLAMPED_FLOAT_TO_CHAN(c
[2], in
[2]);
285 static void insert_4chan_4f_rgba_2( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
288 GLchan
*c
= (GLchan
*)v
;
289 UNCLAMPED_FLOAT_TO_CHAN(c
[0], in
[0]);
290 UNCLAMPED_FLOAT_TO_CHAN(c
[1], in
[1]);
295 static void insert_4chan_4f_rgba_1( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
298 GLchan
*c
= (GLchan
*)v
;
299 UNCLAMPED_FLOAT_TO_CHAN(c
[0], in
[0]);
305 static void insert_4ub_4f_rgba_4( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
308 UNCLAMPED_FLOAT_TO_UBYTE(v
[0], in
[0]);
309 UNCLAMPED_FLOAT_TO_UBYTE(v
[1], in
[1]);
310 UNCLAMPED_FLOAT_TO_UBYTE(v
[2], in
[2]);
311 UNCLAMPED_FLOAT_TO_UBYTE(v
[3], in
[3]);
314 static void insert_4ub_4f_rgba_3( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
317 UNCLAMPED_FLOAT_TO_UBYTE(v
[0], in
[0]);
318 UNCLAMPED_FLOAT_TO_UBYTE(v
[1], in
[1]);
319 UNCLAMPED_FLOAT_TO_UBYTE(v
[2], in
[2]);
323 static void insert_4ub_4f_rgba_2( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
326 UNCLAMPED_FLOAT_TO_UBYTE(v
[0], in
[0]);
327 UNCLAMPED_FLOAT_TO_UBYTE(v
[1], in
[1]);
332 static void insert_4ub_4f_rgba_1( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
335 UNCLAMPED_FLOAT_TO_UBYTE(v
[0], in
[0]);
341 static void insert_4ub_4f_bgra_4( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
344 UNCLAMPED_FLOAT_TO_UBYTE(v
[2], in
[0]);
345 UNCLAMPED_FLOAT_TO_UBYTE(v
[1], in
[1]);
346 UNCLAMPED_FLOAT_TO_UBYTE(v
[0], in
[2]);
347 UNCLAMPED_FLOAT_TO_UBYTE(v
[3], in
[3]);
350 static void insert_4ub_4f_bgra_3( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
353 UNCLAMPED_FLOAT_TO_UBYTE(v
[2], in
[0]);
354 UNCLAMPED_FLOAT_TO_UBYTE(v
[1], in
[1]);
355 UNCLAMPED_FLOAT_TO_UBYTE(v
[0], in
[2]);
359 static void insert_4ub_4f_bgra_2( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
362 UNCLAMPED_FLOAT_TO_UBYTE(v
[2], in
[0]);
363 UNCLAMPED_FLOAT_TO_UBYTE(v
[1], in
[1]);
368 static void insert_4ub_4f_bgra_1( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
371 UNCLAMPED_FLOAT_TO_UBYTE(v
[2], in
[0]);
377 static void insert_3ub_3f_rgb_3( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
380 UNCLAMPED_FLOAT_TO_UBYTE(v
[0], in
[0]);
381 UNCLAMPED_FLOAT_TO_UBYTE(v
[1], in
[1]);
382 UNCLAMPED_FLOAT_TO_UBYTE(v
[2], in
[2]);
385 static void insert_3ub_3f_rgb_2( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
388 UNCLAMPED_FLOAT_TO_UBYTE(v
[0], in
[0]);
389 UNCLAMPED_FLOAT_TO_UBYTE(v
[1], in
[1]);
393 static void insert_3ub_3f_rgb_1( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
396 UNCLAMPED_FLOAT_TO_UBYTE(v
[0], in
[0]);
401 static void insert_3ub_3f_bgr_3( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
404 UNCLAMPED_FLOAT_TO_UBYTE(v
[2], in
[0]);
405 UNCLAMPED_FLOAT_TO_UBYTE(v
[1], in
[1]);
406 UNCLAMPED_FLOAT_TO_UBYTE(v
[0], in
[2]);
409 static void insert_3ub_3f_bgr_2( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
412 UNCLAMPED_FLOAT_TO_UBYTE(v
[2], in
[0]);
413 UNCLAMPED_FLOAT_TO_UBYTE(v
[1], in
[1]);
417 static void insert_3ub_3f_bgr_1( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
420 UNCLAMPED_FLOAT_TO_UBYTE(v
[2], in
[0]);
426 static void insert_1ub_1f_1( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
429 UNCLAMPED_FLOAT_TO_UBYTE(v
[0], in
[0]);
433 /***********************************************************************
434 * Functions to perform the reverse operations to the above, for
435 * swrast translation and clip-interpolation.
437 * Currently always extracts a full 4 floats.
440 static void extract_4f_viewport( const struct tnl_clipspace_attr
*a
, GLfloat
*out
,
443 const GLfloat
*in
= (const GLfloat
*)v
;
444 const GLfloat
* const vp
= a
->vp
;
446 /* Although included for completeness, the position coordinate is
447 * usually handled differently during clipping.
449 out
[0] = (in
[0] - vp
[12]) / vp
[0];
450 out
[1] = (in
[1] - vp
[13]) / vp
[5];
451 out
[2] = (in
[2] - vp
[14]) / vp
[10];
455 static void extract_3f_viewport( const struct tnl_clipspace_attr
*a
, GLfloat
*out
,
458 const GLfloat
*in
= (const GLfloat
*)v
;
459 const GLfloat
* const vp
= a
->vp
;
461 out
[0] = (in
[0] - vp
[12]) / vp
[0];
462 out
[1] = (in
[1] - vp
[13]) / vp
[5];
463 out
[2] = (in
[2] - vp
[14]) / vp
[10];
468 static void extract_2f_viewport( const struct tnl_clipspace_attr
*a
, GLfloat
*out
,
471 const GLfloat
*in
= (const GLfloat
*)v
;
472 const GLfloat
* const vp
= a
->vp
;
474 out
[0] = (in
[0] - vp
[12]) / vp
[0];
475 out
[1] = (in
[1] - vp
[13]) / vp
[5];
481 static void extract_4f( const struct tnl_clipspace_attr
*a
, GLfloat
*out
, const GLubyte
*v
)
483 const GLfloat
*in
= (const GLfloat
*)v
;
491 static void extract_3f_xyw( const struct tnl_clipspace_attr
*a
, GLfloat
*out
, const GLubyte
*v
)
493 const GLfloat
*in
= (const GLfloat
*)v
;
502 static void extract_3f( const struct tnl_clipspace_attr
*a
, GLfloat
*out
, const GLubyte
*v
)
504 const GLfloat
*in
= (const GLfloat
*)v
;
513 static void extract_2f( const struct tnl_clipspace_attr
*a
, GLfloat
*out
, const GLubyte
*v
)
515 const GLfloat
*in
= (const GLfloat
*)v
;
523 static void extract_1f( const struct tnl_clipspace_attr
*a
, GLfloat
*out
, const GLubyte
*v
)
525 const GLfloat
*in
= (const GLfloat
*)v
;
533 static void extract_4chan_4f_rgba( const struct tnl_clipspace_attr
*a
, GLfloat
*out
,
536 GLchan
*c
= (GLchan
*)v
;
538 out
[0] = CHAN_TO_FLOAT(c
[0]);
539 out
[1] = CHAN_TO_FLOAT(c
[1]);
540 out
[2] = CHAN_TO_FLOAT(c
[2]);
541 out
[3] = CHAN_TO_FLOAT(c
[3]);
544 static void extract_4ub_4f_rgba( const struct tnl_clipspace_attr
*a
, GLfloat
*out
,
547 out
[0] = UBYTE_TO_FLOAT(v
[0]);
548 out
[1] = UBYTE_TO_FLOAT(v
[1]);
549 out
[2] = UBYTE_TO_FLOAT(v
[2]);
550 out
[3] = UBYTE_TO_FLOAT(v
[3]);
553 static void extract_4ub_4f_bgra( const struct tnl_clipspace_attr
*a
, GLfloat
*out
,
556 out
[2] = UBYTE_TO_FLOAT(v
[0]);
557 out
[1] = UBYTE_TO_FLOAT(v
[1]);
558 out
[0] = UBYTE_TO_FLOAT(v
[2]);
559 out
[3] = UBYTE_TO_FLOAT(v
[3]);
562 static void extract_3ub_3f_rgb( const struct tnl_clipspace_attr
*a
, GLfloat
*out
,
565 out
[0] = UBYTE_TO_FLOAT(v
[0]);
566 out
[1] = UBYTE_TO_FLOAT(v
[1]);
567 out
[2] = UBYTE_TO_FLOAT(v
[2]);
571 static void extract_3ub_3f_bgr( const struct tnl_clipspace_attr
*a
, GLfloat
*out
,
574 out
[2] = UBYTE_TO_FLOAT(v
[0]);
575 out
[1] = UBYTE_TO_FLOAT(v
[1]);
576 out
[0] = UBYTE_TO_FLOAT(v
[2]);
580 static void extract_1ub_1f( const struct tnl_clipspace_attr
*a
, GLfloat
*out
, const GLubyte
*v
)
582 out
[0] = UBYTE_TO_FLOAT(v
[0]);
591 extract_func extract
;
592 insert_func insert
[4];
593 const GLuint attrsize
;
594 } format_info
[EMIT_MAX
] = {
598 { insert_1f_1
, insert_1f_1
, insert_1f_1
, insert_1f_1
},
603 { insert_2f_1
, insert_2f_2
, insert_2f_2
, insert_2f_2
},
604 2 * sizeof(GLfloat
) },
608 { insert_3f_1
, insert_3f_2
, insert_3f_3
, insert_3f_3
},
609 3 * sizeof(GLfloat
) },
613 { insert_4f_1
, insert_4f_2
, insert_4f_3
, insert_4f_4
},
614 4 * sizeof(GLfloat
) },
618 { insert_2f_viewport_1
, insert_2f_viewport_2
, insert_2f_viewport_2
,
619 insert_2f_viewport_2
},
620 2 * sizeof(GLfloat
) },
624 { insert_3f_viewport_1
, insert_3f_viewport_2
, insert_3f_viewport_3
,
625 insert_3f_viewport_3
},
626 3 * sizeof(GLfloat
) },
630 { insert_4f_viewport_1
, insert_4f_viewport_2
, insert_4f_viewport_3
,
631 insert_4f_viewport_4
},
632 4 * sizeof(GLfloat
) },
636 { insert_3f_xyw_err
, insert_3f_xyw_err
, insert_3f_xyw_err
,
638 3 * sizeof(GLfloat
) },
642 { insert_1ub_1f_1
, insert_1ub_1f_1
, insert_1ub_1f_1
, insert_1ub_1f_1
},
647 { insert_3ub_3f_rgb_1
, insert_3ub_3f_rgb_2
, insert_3ub_3f_rgb_3
,
648 insert_3ub_3f_rgb_3
},
649 3 * sizeof(GLubyte
) },
653 { insert_3ub_3f_bgr_1
, insert_3ub_3f_bgr_2
, insert_3ub_3f_bgr_3
,
654 insert_3ub_3f_bgr_3
},
655 3 * sizeof(GLubyte
) },
659 { insert_4ub_4f_rgba_1
, insert_4ub_4f_rgba_2
, insert_4ub_4f_rgba_3
,
660 insert_4ub_4f_rgba_4
},
661 4 * sizeof(GLubyte
) },
665 { insert_4ub_4f_bgra_1
, insert_4ub_4f_bgra_2
, insert_4ub_4f_bgra_3
,
666 insert_4ub_4f_bgra_4
},
667 4 * sizeof(GLubyte
) },
670 extract_4chan_4f_rgba
,
671 { insert_4chan_4f_rgba_1
, insert_4chan_4f_rgba_2
, insert_4chan_4f_rgba_3
,
672 insert_4chan_4f_rgba_4
},
673 4 * sizeof(GLchan
) },
683 /***********************************************************************
684 * Generic (non-codegen) functions for whole vertices or groups of
688 static void generic_emit( GLcontext
*ctx
,
689 GLuint start
, GLuint end
,
692 struct vertex_buffer
*VB
= &TNL_CONTEXT(ctx
)->vb
;
693 struct tnl_clipspace
*vtx
= GET_VERTEX_STATE(ctx
);
694 struct tnl_clipspace_attr
*a
= vtx
->attr
;
695 GLubyte
*v
= (GLubyte
*)dest
;
697 const GLuint count
= vtx
->attr_count
;
700 for (j
= 0; j
< count
; j
++) {
701 GLvector4f
*vptr
= VB
->AttribPtr
[a
[j
].attrib
];
702 a
[j
].inputstride
= vptr
->stride
;
703 a
[j
].inputptr
= ((GLubyte
*)vptr
->data
) + start
* vptr
->stride
;
704 a
[j
].emit
= a
[j
].insert
[vptr
->size
- 1];
708 stride
= vtx
->vertex_size
;
710 for (i
= 0 ; i
< end
; i
++, v
+= stride
) {
711 for (j
= 0; j
< count
; j
++) {
712 GLfloat
*in
= (GLfloat
*)a
[j
].inputptr
;
713 a
[j
].inputptr
+= a
[j
].inputstride
;
714 a
[j
].emit( &a
[j
], v
+ a
[j
].vertoffset
, in
);
720 static void generic_interp( GLcontext
*ctx
,
722 GLuint edst
, GLuint eout
, GLuint ein
,
723 GLboolean force_boundary
)
725 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
726 struct vertex_buffer
*VB
= &tnl
->vb
;
727 struct tnl_clipspace
*vtx
= GET_VERTEX_STATE(ctx
);
728 const GLubyte
*vin
= vtx
->vertex_buf
+ ein
* vtx
->vertex_size
;
729 const GLubyte
*vout
= vtx
->vertex_buf
+ eout
* vtx
->vertex_size
;
730 GLubyte
*vdst
= vtx
->vertex_buf
+ edst
* vtx
->vertex_size
;
731 const struct tnl_clipspace_attr
*a
= vtx
->attr
;
732 const GLuint attr_count
= vtx
->attr_count
;
735 if (tnl
->NeedNdcCoords
) {
736 const GLfloat
*dstclip
= VB
->ClipPtr
->data
[edst
];
737 if (dstclip
[3] != 0.0) {
738 const GLfloat w
= 1.0f
/ dstclip
[3];
741 pos
[0] = dstclip
[0] * w
;
742 pos
[1] = dstclip
[1] * w
;
743 pos
[2] = dstclip
[2] * w
;
746 a
[0].insert
[4-1]( &a
[0], vdst
, pos
);
750 a
[0].insert
[4-1]( &a
[0], vdst
, VB
->ClipPtr
->data
[edst
] );
754 for (j
= 1; j
< attr_count
; j
++) {
755 GLfloat fin
[4], fout
[4], fdst
[4];
757 a
[j
].extract( &a
[j
], fin
, vin
+ a
[j
].vertoffset
);
758 a
[j
].extract( &a
[j
], fout
, vout
+ a
[j
].vertoffset
);
760 INTERP_F( t
, fdst
[3], fout
[3], fin
[3] );
761 INTERP_F( t
, fdst
[2], fout
[2], fin
[2] );
762 INTERP_F( t
, fdst
[1], fout
[1], fin
[1] );
763 INTERP_F( t
, fdst
[0], fout
[0], fin
[0] );
765 a
[j
].insert
[4-1]( &a
[j
], vdst
+ a
[j
].vertoffset
, fdst
);
770 /* Extract color attributes from one vertex and insert them into
771 * another. (Shortcircuit extract/insert with memcpy).
773 static void generic_copy_pv( GLcontext
*ctx
, GLuint edst
, GLuint esrc
)
775 struct tnl_clipspace
*vtx
= GET_VERTEX_STATE(ctx
);
776 GLubyte
*vsrc
= vtx
->vertex_buf
+ esrc
* vtx
->vertex_size
;
777 GLubyte
*vdst
= vtx
->vertex_buf
+ edst
* vtx
->vertex_size
;
778 const struct tnl_clipspace_attr
*a
= vtx
->attr
;
779 const GLuint attr_count
= vtx
->attr_count
;
782 for (j
= 0; j
< attr_count
; j
++) {
783 if (a
[j
].attrib
== VERT_ATTRIB_COLOR0
||
784 a
[j
].attrib
== VERT_ATTRIB_COLOR1
) {
786 _mesa_memcpy( vdst
+ a
[j
].vertoffset
,
787 vsrc
+ a
[j
].vertoffset
,
794 /* Helper functions for hardware which doesn't put back colors and/or
795 * edgeflags into vertices.
797 static void generic_interp_extras( GLcontext
*ctx
,
799 GLuint dst
, GLuint out
, GLuint in
,
800 GLboolean force_boundary
)
802 struct vertex_buffer
*VB
= &TNL_CONTEXT(ctx
)->vb
;
804 if (VB
->ColorPtr
[1]) {
805 assert(VB
->ColorPtr
[1]->stride
== 4 * sizeof(GLfloat
));
808 VB
->ColorPtr
[1]->data
[dst
],
809 VB
->ColorPtr
[1]->data
[out
],
810 VB
->ColorPtr
[1]->data
[in
] );
812 if (VB
->SecondaryColorPtr
[1]) {
814 VB
->SecondaryColorPtr
[1]->data
[dst
],
815 VB
->SecondaryColorPtr
[1]->data
[out
],
816 VB
->SecondaryColorPtr
[1]->data
[in
] );
819 else if (VB
->IndexPtr
[1]) {
820 VB
->IndexPtr
[1]->data
[dst
][0] = LINTERP( t
,
821 VB
->IndexPtr
[1]->data
[out
][0],
822 VB
->IndexPtr
[1]->data
[in
][0] );
826 VB
->EdgeFlag
[dst
] = VB
->EdgeFlag
[out
] || force_boundary
;
829 generic_interp(ctx
, t
, dst
, out
, in
, force_boundary
);
832 static void generic_copy_pv_extras( GLcontext
*ctx
,
833 GLuint dst
, GLuint src
)
835 struct vertex_buffer
*VB
= &TNL_CONTEXT(ctx
)->vb
;
837 if (VB
->ColorPtr
[1]) {
838 COPY_4FV( VB
->ColorPtr
[1]->data
[dst
],
839 VB
->ColorPtr
[1]->data
[src
] );
841 if (VB
->SecondaryColorPtr
[1]) {
842 COPY_4FV( VB
->SecondaryColorPtr
[1]->data
[dst
],
843 VB
->SecondaryColorPtr
[1]->data
[src
] );
846 else if (VB
->IndexPtr
[1]) {
847 VB
->IndexPtr
[1]->data
[dst
][0] = VB
->IndexPtr
[1]->data
[src
][0];
850 generic_copy_pv(ctx
, dst
, src
);
856 /***********************************************************************
857 * Build codegen functions or return generic ones:
861 static void do_emit( GLcontext
*ctx
, GLuint start
, GLuint end
,
864 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
865 struct vertex_buffer
*VB
= &tnl
->vb
;
866 struct tnl_clipspace
*vtx
= GET_VERTEX_STATE(ctx
);
867 struct tnl_clipspace_attr
*a
= vtx
->attr
;
868 const GLuint count
= vtx
->attr_count
;
871 for (j
= 0; j
< count
; j
++) {
872 GLvector4f
*vptr
= VB
->AttribPtr
[a
[j
].attrib
];
873 a
[j
].inputstride
= vptr
->stride
;
874 a
[j
].inputptr
= ((GLubyte
*)vptr
->data
) + start
* vptr
->stride
;
875 a
[j
].emit
= a
[j
].insert
[vptr
->size
- 1];
881 vtx
->emit
= _tnl_codegen_emit(ctx
);
884 vtx
->emit
= generic_emit
;
886 vtx
->emit( ctx
, start
, end
, dest
);
891 static void choose_interp_func( GLcontext
*ctx
,
893 GLuint edst
, GLuint eout
, GLuint ein
,
894 GLboolean force_boundary
)
896 struct tnl_clipspace
*vtx
= GET_VERTEX_STATE(ctx
);
898 if (vtx
->need_extras
&&
899 (ctx
->_TriangleCaps
& (DD_TRI_LIGHT_TWOSIDE
|DD_TRI_UNFILLED
))) {
900 vtx
->interp
= generic_interp_extras
;
902 vtx
->interp
= generic_interp
;
905 vtx
->interp( ctx
, t
, edst
, eout
, ein
, force_boundary
);
909 static void choose_copy_pv_func( GLcontext
*ctx
, GLuint edst
, GLuint esrc
)
911 struct tnl_clipspace
*vtx
= GET_VERTEX_STATE(ctx
);
913 if (vtx
->need_extras
&&
914 (ctx
->_TriangleCaps
& (DD_TRI_LIGHT_TWOSIDE
|DD_TRI_UNFILLED
))) {
915 vtx
->copy_pv
= generic_copy_pv_extras
;
917 vtx
->copy_pv
= generic_copy_pv
;
920 vtx
->copy_pv( ctx
, edst
, esrc
);
924 /***********************************************************************
925 * Public entrypoints, mostly dispatch to the above:
929 /* Interpolate between two vertices to produce a third:
931 void _tnl_interp( GLcontext
*ctx
,
933 GLuint edst
, GLuint eout
, GLuint ein
,
934 GLboolean force_boundary
)
936 struct tnl_clipspace
*vtx
= GET_VERTEX_STATE(ctx
);
937 vtx
->interp( ctx
, t
, edst
, eout
, ein
, force_boundary
);
940 /* Copy colors from one vertex to another:
942 void _tnl_copy_pv( GLcontext
*ctx
, GLuint edst
, GLuint esrc
)
944 struct tnl_clipspace
*vtx
= GET_VERTEX_STATE(ctx
);
945 vtx
->copy_pv( ctx
, edst
, esrc
);
949 /* Extract a named attribute from a hardware vertex. Will have to
950 * reverse any viewport transformation, swizzling or other conversions
951 * which may have been applied:
953 void _tnl_get_attr( GLcontext
*ctx
, const void *vin
,
954 GLenum attr
, GLfloat
*dest
)
956 struct tnl_clipspace
*vtx
= GET_VERTEX_STATE(ctx
);
957 const struct tnl_clipspace_attr
*a
= vtx
->attr
;
958 const GLuint attr_count
= vtx
->attr_count
;
961 for (j
= 0; j
< attr_count
; j
++) {
962 if (a
[j
].attrib
== attr
) {
963 a
[j
].extract( &a
[j
], dest
, (GLubyte
*)vin
+ a
[j
].vertoffset
);
968 /* Else return the value from ctx->Current -- dangerous???
970 _mesa_memcpy( dest
, ctx
->Current
.Attrib
[attr
], 4*sizeof(GLfloat
));
974 /* Complementary operation to the above.
976 void _tnl_set_attr( GLcontext
*ctx
, void *vout
,
977 GLenum attr
, const GLfloat
*src
)
979 struct tnl_clipspace
*vtx
= GET_VERTEX_STATE(ctx
);
980 const struct tnl_clipspace_attr
*a
= vtx
->attr
;
981 const GLuint attr_count
= vtx
->attr_count
;
984 for (j
= 0; j
< attr_count
; j
++) {
985 if (a
[j
].attrib
== attr
) {
986 a
[j
].insert
[4-1]( &a
[j
], (GLubyte
*)vout
+ a
[j
].vertoffset
, src
);
993 void *_tnl_get_vertex( GLcontext
*ctx
, GLuint nr
)
995 struct tnl_clipspace
*vtx
= GET_VERTEX_STATE(ctx
);
997 return vtx
->vertex_buf
+ nr
* vtx
->vertex_size
;
1000 void _tnl_invalidate_vertex_state( GLcontext
*ctx
, GLuint new_state
)
1002 if (new_state
& (_DD_NEW_TRI_LIGHT_TWOSIDE
|_DD_NEW_TRI_UNFILLED
) ) {
1003 struct tnl_clipspace
*vtx
= GET_VERTEX_STATE(ctx
);
1004 vtx
->new_inputs
= ~0;
1005 vtx
->interp
= choose_interp_func
;
1006 vtx
->copy_pv
= choose_copy_pv_func
;
1011 GLuint
_tnl_install_attrs( GLcontext
*ctx
, const struct tnl_attr_map
*map
,
1012 GLuint nr
, const GLfloat
*vp
,
1013 GLuint unpacked_size
)
1015 struct tnl_clipspace
*vtx
= GET_VERTEX_STATE(ctx
);
1019 assert(nr
< _TNL_ATTRIB_MAX
);
1020 assert(nr
== 0 || map
[0].attrib
== VERT_ATTRIB_POS
);
1023 vtx
->interp
= choose_interp_func
;
1024 vtx
->copy_pv
= choose_copy_pv_func
;
1025 vtx
->new_inputs
= ~0;
1027 for (j
= 0, i
= 0; i
< nr
; i
++) {
1028 const GLuint format
= map
[i
].format
;
1029 if (format
== EMIT_PAD
) {
1030 fprintf(stderr
, "%d: pad %d, offset %d\n", i
,
1031 map
[i
].offset
, offset
);
1033 offset
+= map
[i
].offset
;
1037 vtx
->attr
[j
].attrib
= map
[i
].attrib
;
1038 vtx
->attr
[j
].format
= format
;
1039 vtx
->attr
[j
].vp
= vp
;
1040 vtx
->attr
[j
].insert
= format_info
[format
].insert
;
1041 vtx
->attr
[j
].extract
= format_info
[format
].extract
;
1042 vtx
->attr
[j
].vertattrsize
= format_info
[format
].attrsize
;
1045 vtx
->attr
[j
].vertoffset
= map
[i
].offset
;
1047 vtx
->attr
[j
].vertoffset
= offset
;
1049 fprintf(stderr
, "%d: %s, vp %p, offset %d\n", i
,
1050 format_info
[format
].name
, (void *)vp
,
1051 vtx
->attr
[j
].vertoffset
);
1053 offset
+= format_info
[format
].attrsize
;
1058 vtx
->attr_count
= j
;
1061 vtx
->vertex_size
= unpacked_size
;
1063 vtx
->vertex_size
= offset
;
1065 assert(vtx
->vertex_size
<= vtx
->max_vertex_size
);
1067 return vtx
->vertex_size
;
1072 void _tnl_invalidate_vertices( GLcontext
*ctx
, GLuint newinputs
)
1074 struct tnl_clipspace
*vtx
= GET_VERTEX_STATE(ctx
);
1075 vtx
->new_inputs
|= newinputs
;
1079 void _tnl_build_vertices( GLcontext
*ctx
,
1084 struct tnl_clipspace
*vtx
= GET_VERTEX_STATE(ctx
);
1085 const GLuint stride
= vtx
->vertex_size
;
1086 GLubyte
*vDest
= ((GLubyte
*)vtx
->vertex_buf
+ (start
*stride
));
1088 newinputs
|= vtx
->new_inputs
;
1089 vtx
->new_inputs
= 0;
1092 do_emit( ctx
, start
, end
, vDest
);
1096 void *_tnl_emit_vertices_to_buffer( GLcontext
*ctx
,
1101 struct tnl_clipspace
*vtx
= GET_VERTEX_STATE(ctx
);
1102 do_emit( ctx
, start
, end
, dest
);
1103 return (void *)((GLubyte
*)dest
+ vtx
->vertex_size
* (end
- start
));
1107 void _tnl_init_vertices( GLcontext
*ctx
,
1109 GLuint max_vertex_size
)
1111 struct tnl_clipspace
*vtx
= GET_VERTEX_STATE(ctx
);
1113 _tnl_install_attrs( ctx
, 0, 0, 0, 0 );
1115 vtx
->need_extras
= GL_TRUE
;
1116 if (max_vertex_size
> vtx
->max_vertex_size
) {
1117 _tnl_free_vertices( ctx
);
1118 vtx
->max_vertex_size
= max_vertex_size
;
1119 vtx
->vertex_buf
= (GLubyte
*)ALIGN_CALLOC(vb_size
* max_vertex_size
, 32 );
1122 _tnl_init_c_codegen( &vtx
->codegen
);
1126 void _tnl_free_vertices( GLcontext
*ctx
)
1128 struct tnl_clipspace
*vtx
= GET_VERTEX_STATE(ctx
);
1129 if (vtx
->vertex_buf
) {
1130 ALIGN_FREE(vtx
->vertex_buf
);
1131 vtx
->vertex_buf
= 0;