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_*.
46 #define GET_VERTEX_STATE(ctx) &(TNL_CONTEXT(ctx)->clipspace)
50 * These functions take the NDC coordinates pointed to by 'in', apply the
51 * NDC->Viewport mapping and store the results at 'v'.
55 insert_4f_viewport_4( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
58 GLfloat
*out
= (GLfloat
*)v
;
59 const GLfloat
* const vp
= a
->vp
;
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];
67 static void insert_4f_viewport_3( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
70 GLfloat
*out
= (GLfloat
*)v
;
71 const GLfloat
* const vp
= a
->vp
;
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];
79 static void insert_4f_viewport_2( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
82 GLfloat
*out
= (GLfloat
*)v
;
83 const GLfloat
* const vp
= a
->vp
;
85 out
[0] = vp
[0] * in
[0] + vp
[12];
86 out
[1] = vp
[5] * in
[1] + vp
[13];
91 static void insert_4f_viewport_1( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
94 GLfloat
*out
= (GLfloat
*)v
;
95 const GLfloat
* const vp
= a
->vp
;
97 out
[0] = vp
[0] * in
[0] + vp
[12];
103 static void insert_3f_viewport_3( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
106 GLfloat
*out
= (GLfloat
*)v
;
107 const GLfloat
* const vp
= a
->vp
;
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];
114 static void insert_3f_viewport_2( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
117 GLfloat
*out
= (GLfloat
*)v
;
118 const GLfloat
* const vp
= a
->vp
;
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];
125 static void insert_3f_viewport_1( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
128 GLfloat
*out
= (GLfloat
*)v
;
129 const GLfloat
* const vp
= a
->vp
;
131 out
[0] = vp
[0] * in
[0] + vp
[12];
136 static void insert_2f_viewport_2( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
139 GLfloat
*out
= (GLfloat
*)v
;
140 const GLfloat
* const vp
= a
->vp
;
142 out
[0] = vp
[0] * in
[0] + vp
[12];
143 out
[1] = vp
[5] * in
[1] + vp
[13];
146 static void insert_2f_viewport_1( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
149 GLfloat
*out
= (GLfloat
*)v
;
150 const GLfloat
* const vp
= a
->vp
;
152 out
[0] = vp
[0] * in
[0] + vp
[12];
158 * These functions do the same as above, except for the viewport mapping.
161 static void insert_4f_4( const struct tnl_clipspace_attr
*a
, GLubyte
*v
, const GLfloat
*in
)
163 GLfloat
*out
= (GLfloat
*)(v
);
171 static void insert_4f_3( const struct tnl_clipspace_attr
*a
, GLubyte
*v
, const GLfloat
*in
)
173 GLfloat
*out
= (GLfloat
*)(v
);
181 static void insert_4f_2( const struct tnl_clipspace_attr
*a
, GLubyte
*v
, const GLfloat
*in
)
183 GLfloat
*out
= (GLfloat
*)(v
);
191 static void insert_4f_1( const struct tnl_clipspace_attr
*a
, GLubyte
*v
, const GLfloat
*in
)
193 GLfloat
*out
= (GLfloat
*)(v
);
201 static void insert_3f_xyw_4( const struct tnl_clipspace_attr
*a
, GLubyte
*v
, const GLfloat
*in
)
203 GLfloat
*out
= (GLfloat
*)(v
);
210 static void insert_3f_xyw_err( const struct tnl_clipspace_attr
*a
, GLubyte
*v
, const GLfloat
*in
)
215 static void insert_3f_3( const struct tnl_clipspace_attr
*a
, GLubyte
*v
, const GLfloat
*in
)
217 GLfloat
*out
= (GLfloat
*)(v
);
224 static void insert_3f_2( const struct tnl_clipspace_attr
*a
, GLubyte
*v
, const GLfloat
*in
)
226 GLfloat
*out
= (GLfloat
*)(v
);
233 static void insert_3f_1( const struct tnl_clipspace_attr
*a
, GLubyte
*v
, const GLfloat
*in
)
235 GLfloat
*out
= (GLfloat
*)(v
);
243 static void insert_2f_2( const struct tnl_clipspace_attr
*a
, GLubyte
*v
, const GLfloat
*in
)
245 GLfloat
*out
= (GLfloat
*)(v
);
251 static void insert_2f_1( const struct tnl_clipspace_attr
*a
, GLubyte
*v
, const GLfloat
*in
)
253 GLfloat
*out
= (GLfloat
*)(v
);
259 static void insert_1f_1( const struct tnl_clipspace_attr
*a
, GLubyte
*v
, const GLfloat
*in
)
261 GLfloat
*out
= (GLfloat
*)(v
);
266 static void insert_4chan_4f_rgba_4( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
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]);
276 static void insert_4chan_4f_rgba_3( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
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]);
286 static void insert_4chan_4f_rgba_2( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
289 GLchan
*c
= (GLchan
*)v
;
290 UNCLAMPED_FLOAT_TO_CHAN(c
[0], in
[0]);
291 UNCLAMPED_FLOAT_TO_CHAN(c
[1], in
[1]);
296 static void insert_4chan_4f_rgba_1( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
299 GLchan
*c
= (GLchan
*)v
;
300 UNCLAMPED_FLOAT_TO_CHAN(c
[0], in
[0]);
306 static void insert_4ub_4f_rgba_4( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
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]);
315 static void insert_4ub_4f_rgba_3( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
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]);
324 static void insert_4ub_4f_rgba_2( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
327 UNCLAMPED_FLOAT_TO_UBYTE(v
[0], in
[0]);
328 UNCLAMPED_FLOAT_TO_UBYTE(v
[1], in
[1]);
333 static void insert_4ub_4f_rgba_1( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
336 UNCLAMPED_FLOAT_TO_UBYTE(v
[0], in
[0]);
342 static void insert_4ub_4f_bgra_4( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
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]);
351 static void insert_4ub_4f_bgra_3( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
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]);
360 static void insert_4ub_4f_bgra_2( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
363 UNCLAMPED_FLOAT_TO_UBYTE(v
[2], in
[0]);
364 UNCLAMPED_FLOAT_TO_UBYTE(v
[1], in
[1]);
369 static void insert_4ub_4f_bgra_1( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
372 UNCLAMPED_FLOAT_TO_UBYTE(v
[2], in
[0]);
378 static void insert_3ub_3f_rgb_3( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
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]);
386 static void insert_3ub_3f_rgb_2( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
389 UNCLAMPED_FLOAT_TO_UBYTE(v
[0], in
[0]);
390 UNCLAMPED_FLOAT_TO_UBYTE(v
[1], in
[1]);
394 static void insert_3ub_3f_rgb_1( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
397 UNCLAMPED_FLOAT_TO_UBYTE(v
[0], in
[0]);
402 static void insert_3ub_3f_bgr_3( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
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]);
410 static void insert_3ub_3f_bgr_2( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
413 UNCLAMPED_FLOAT_TO_UBYTE(v
[2], in
[0]);
414 UNCLAMPED_FLOAT_TO_UBYTE(v
[1], in
[1]);
418 static void insert_3ub_3f_bgr_1( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
421 UNCLAMPED_FLOAT_TO_UBYTE(v
[2], in
[0]);
427 static void insert_1ub_1f_1( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
430 UNCLAMPED_FLOAT_TO_UBYTE(v
[0], in
[0]);
434 /***********************************************************************
435 * Functions to perform the reverse operations to the above, for
436 * swrast translation and clip-interpolation.
438 * Currently always extracts a full 4 floats.
441 static void extract_4f_viewport( const struct tnl_clipspace_attr
*a
, GLfloat
*out
,
444 const GLfloat
*in
= (const GLfloat
*)v
;
445 const GLfloat
* const vp
= a
->vp
;
447 /* Although included for completeness, the position coordinate is
448 * usually handled differently during clipping.
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];
456 static void extract_3f_viewport( const struct tnl_clipspace_attr
*a
, GLfloat
*out
,
459 const GLfloat
*in
= (const GLfloat
*)v
;
460 const GLfloat
* const vp
= a
->vp
;
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];
469 static void extract_2f_viewport( const struct tnl_clipspace_attr
*a
, GLfloat
*out
,
472 const GLfloat
*in
= (const GLfloat
*)v
;
473 const GLfloat
* const vp
= a
->vp
;
475 out
[0] = (in
[0] - vp
[12]) / vp
[0];
476 out
[1] = (in
[1] - vp
[13]) / vp
[5];
482 static void extract_4f( const struct tnl_clipspace_attr
*a
, GLfloat
*out
, const GLubyte
*v
)
484 const GLfloat
*in
= (const GLfloat
*)v
;
492 static void extract_3f_xyw( const struct tnl_clipspace_attr
*a
, GLfloat
*out
, const GLubyte
*v
)
494 const GLfloat
*in
= (const GLfloat
*)v
;
503 static void extract_3f( const struct tnl_clipspace_attr
*a
, GLfloat
*out
, const GLubyte
*v
)
505 const GLfloat
*in
= (const GLfloat
*)v
;
514 static void extract_2f( const struct tnl_clipspace_attr
*a
, GLfloat
*out
, const GLubyte
*v
)
516 const GLfloat
*in
= (const GLfloat
*)v
;
524 static void extract_1f( const struct tnl_clipspace_attr
*a
, GLfloat
*out
, const GLubyte
*v
)
526 const GLfloat
*in
= (const GLfloat
*)v
;
534 static void extract_4chan_4f_rgba( const struct tnl_clipspace_attr
*a
, GLfloat
*out
,
537 GLchan
*c
= (GLchan
*)v
;
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]);
545 static void extract_4ub_4f_rgba( const struct tnl_clipspace_attr
*a
, GLfloat
*out
,
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]);
554 static void extract_4ub_4f_bgra( const struct tnl_clipspace_attr
*a
, GLfloat
*out
,
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]);
563 static void extract_3ub_3f_rgb( const struct tnl_clipspace_attr
*a
, GLfloat
*out
,
566 out
[0] = UBYTE_TO_FLOAT(v
[0]);
567 out
[1] = UBYTE_TO_FLOAT(v
[1]);
568 out
[2] = UBYTE_TO_FLOAT(v
[2]);
572 static void extract_3ub_3f_bgr( const struct tnl_clipspace_attr
*a
, GLfloat
*out
,
575 out
[2] = UBYTE_TO_FLOAT(v
[0]);
576 out
[1] = UBYTE_TO_FLOAT(v
[1]);
577 out
[0] = UBYTE_TO_FLOAT(v
[2]);
581 static void extract_1ub_1f( const struct tnl_clipspace_attr
*a
, GLfloat
*out
, const GLubyte
*v
)
583 out
[0] = UBYTE_TO_FLOAT(v
[0]);
592 extract_func extract
;
593 insert_func insert
[4];
594 const GLuint attrsize
;
595 } format_info
[EMIT_MAX
] = {
599 { insert_1f_1
, insert_1f_1
, insert_1f_1
, insert_1f_1
},
604 { insert_2f_1
, insert_2f_2
, insert_2f_2
, insert_2f_2
},
605 2 * sizeof(GLfloat
) },
609 { insert_3f_1
, insert_3f_2
, insert_3f_3
, insert_3f_3
},
610 3 * sizeof(GLfloat
) },
614 { insert_4f_1
, insert_4f_2
, insert_4f_3
, insert_4f_4
},
615 4 * sizeof(GLfloat
) },
619 { insert_2f_viewport_1
, insert_2f_viewport_2
, insert_2f_viewport_2
,
620 insert_2f_viewport_2
},
621 2 * sizeof(GLfloat
) },
625 { insert_3f_viewport_1
, insert_3f_viewport_2
, insert_3f_viewport_3
,
626 insert_3f_viewport_3
},
627 3 * sizeof(GLfloat
) },
631 { insert_4f_viewport_1
, insert_4f_viewport_2
, insert_4f_viewport_3
,
632 insert_4f_viewport_4
},
633 4 * sizeof(GLfloat
) },
637 { insert_3f_xyw_err
, insert_3f_xyw_err
, insert_3f_xyw_err
,
639 3 * sizeof(GLfloat
) },
643 { insert_1ub_1f_1
, insert_1ub_1f_1
, insert_1ub_1f_1
, insert_1ub_1f_1
},
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
) },
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
) },
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
) },
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
) },
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
) },
684 /***********************************************************************
685 * Generic (non-codegen) functions for whole vertices or groups of
689 static void generic_emit( GLcontext
*ctx
,
690 GLuint start
, GLuint end
,
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
;
698 const GLuint count
= vtx
->attr_count
;
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];
709 stride
= vtx
->vertex_size
;
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
);
721 static void generic_interp( GLcontext
*ctx
,
723 GLuint edst
, GLuint eout
, GLuint ein
,
724 GLboolean force_boundary
)
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
;
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];
742 pos
[0] = dstclip
[0] * w
;
743 pos
[1] = dstclip
[1] * w
;
744 pos
[2] = dstclip
[2] * w
;
747 a
[0].insert
[4-1]( &a
[0], vdst
, pos
);
751 a
[0].insert
[4-1]( &a
[0], vdst
, VB
->ClipPtr
->data
[edst
] );
755 for (j
= 1; j
< attr_count
; j
++) {
756 GLfloat fin
[4], fout
[4], fdst
[4];
758 a
[j
].extract( &a
[j
], fin
, vin
+ a
[j
].vertoffset
);
759 a
[j
].extract( &a
[j
], fout
, vout
+ a
[j
].vertoffset
);
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] );
766 a
[j
].insert
[4-1]( &a
[j
], vdst
+ a
[j
].vertoffset
, fdst
);
771 /* Extract color attributes from one vertex and insert them into
772 * another. (Shortcircuit extract/insert with memcpy).
774 static void generic_copy_pv( GLcontext
*ctx
, GLuint edst
, GLuint esrc
)
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
;
783 for (j
= 0; j
< attr_count
; j
++) {
784 if (a
[j
].attrib
== VERT_ATTRIB_COLOR0
||
785 a
[j
].attrib
== VERT_ATTRIB_COLOR1
) {
787 _mesa_memcpy( vdst
+ a
[j
].vertoffset
,
788 vsrc
+ a
[j
].vertoffset
,
795 /* Helper functions for hardware which doesn't put back colors and/or
796 * edgeflags into vertices.
798 static void generic_interp_extras( GLcontext
*ctx
,
800 GLuint dst
, GLuint out
, GLuint in
,
801 GLboolean force_boundary
)
803 struct vertex_buffer
*VB
= &TNL_CONTEXT(ctx
)->vb
;
805 if (VB
->ColorPtr
[1]) {
806 assert(VB
->ColorPtr
[1]->stride
== 4 * sizeof(GLfloat
));
809 VB
->ColorPtr
[1]->data
[dst
],
810 VB
->ColorPtr
[1]->data
[out
],
811 VB
->ColorPtr
[1]->data
[in
] );
813 if (VB
->SecondaryColorPtr
[1]) {
815 VB
->SecondaryColorPtr
[1]->data
[dst
],
816 VB
->SecondaryColorPtr
[1]->data
[out
],
817 VB
->SecondaryColorPtr
[1]->data
[in
] );
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] );
827 VB
->EdgeFlag
[dst
] = VB
->EdgeFlag
[out
] || force_boundary
;
830 generic_interp(ctx
, t
, dst
, out
, in
, force_boundary
);
833 static void generic_copy_pv_extras( GLcontext
*ctx
,
834 GLuint dst
, GLuint src
)
836 struct vertex_buffer
*VB
= &TNL_CONTEXT(ctx
)->vb
;
838 if (VB
->ColorPtr
[1]) {
839 COPY_4FV( VB
->ColorPtr
[1]->data
[dst
],
840 VB
->ColorPtr
[1]->data
[src
] );
842 if (VB
->SecondaryColorPtr
[1]) {
843 COPY_4FV( VB
->SecondaryColorPtr
[1]->data
[dst
],
844 VB
->SecondaryColorPtr
[1]->data
[src
] );
847 else if (VB
->IndexPtr
[1]) {
848 VB
->IndexPtr
[1]->data
[dst
][0] = VB
->IndexPtr
[1]->data
[src
][0];
851 generic_copy_pv(ctx
, dst
, src
);
857 /***********************************************************************
858 * Build codegen functions or return generic ones:
862 static void choose_emit_func( GLcontext
*ctx
,
863 GLuint start
, GLuint end
,
866 struct tnl_clipspace
*vtx
= GET_VERTEX_STATE(ctx
);
867 vtx
->emit
= generic_emit
;
868 vtx
->emit( ctx
, start
, end
, dest
);
872 static void choose_interp_func( GLcontext
*ctx
,
874 GLuint edst
, GLuint eout
, GLuint ein
,
875 GLboolean force_boundary
)
877 struct tnl_clipspace
*vtx
= GET_VERTEX_STATE(ctx
);
879 if (vtx
->need_extras
&&
880 (ctx
->_TriangleCaps
& (DD_TRI_LIGHT_TWOSIDE
|DD_TRI_UNFILLED
))) {
881 vtx
->interp
= generic_interp_extras
;
883 vtx
->interp
= generic_interp
;
886 vtx
->interp( ctx
, t
, edst
, eout
, ein
, force_boundary
);
890 static void choose_copy_pv_func( GLcontext
*ctx
, GLuint edst
, GLuint esrc
)
892 struct tnl_clipspace
*vtx
= GET_VERTEX_STATE(ctx
);
894 if (vtx
->need_extras
&&
895 (ctx
->_TriangleCaps
& (DD_TRI_LIGHT_TWOSIDE
|DD_TRI_UNFILLED
))) {
896 vtx
->copy_pv
= generic_copy_pv_extras
;
898 vtx
->copy_pv
= generic_copy_pv
;
901 vtx
->copy_pv( ctx
, edst
, esrc
);
905 /***********************************************************************
906 * Public entrypoints, mostly dispatch to the above:
910 /* Interpolate between two vertices to produce a third:
912 void _tnl_interp( GLcontext
*ctx
,
914 GLuint edst
, GLuint eout
, GLuint ein
,
915 GLboolean force_boundary
)
917 struct tnl_clipspace
*vtx
= GET_VERTEX_STATE(ctx
);
918 vtx
->interp( ctx
, t
, edst
, eout
, ein
, force_boundary
);
921 /* Copy colors from one vertex to another:
923 void _tnl_copy_pv( GLcontext
*ctx
, GLuint edst
, GLuint esrc
)
925 struct tnl_clipspace
*vtx
= GET_VERTEX_STATE(ctx
);
926 vtx
->copy_pv( ctx
, edst
, esrc
);
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:
934 void _tnl_get_attr( GLcontext
*ctx
, const void *vin
,
935 GLenum attr
, GLfloat
*dest
)
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
;
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
);
949 /* Else return the value from ctx->Current -- dangerous???
951 _mesa_memcpy( dest
, ctx
->Current
.Attrib
[attr
], 4*sizeof(GLfloat
));
955 /* Complementary operation to the above.
957 void _tnl_set_attr( GLcontext
*ctx
, void *vout
,
958 GLenum attr
, const GLfloat
*src
)
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
;
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
);
974 void *_tnl_get_vertex( GLcontext
*ctx
, GLuint nr
)
976 struct tnl_clipspace
*vtx
= GET_VERTEX_STATE(ctx
);
978 return vtx
->vertex_buf
+ nr
* vtx
->vertex_size
;
981 void _tnl_invalidate_vertex_state( GLcontext
*ctx
, GLuint new_state
)
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
;
992 GLuint
_tnl_install_attrs( GLcontext
*ctx
, const struct tnl_attr_map
*map
,
993 GLuint nr
, const GLfloat
*vp
,
994 GLuint unpacked_size
)
996 struct tnl_clipspace
*vtx
= GET_VERTEX_STATE(ctx
);
1000 assert(nr
< _TNL_ATTRIB_MAX
);
1001 assert(nr
== 0 || map
[0].attrib
== VERT_ATTRIB_POS
);
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;
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
;
1013 /* fprintf(stderr, "%d: pad %d, offset now %d\n", i, */
1014 /* map[i].offset, offset); */
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
;
1025 vtx
->attr
[j
].vertoffset
= map
[i
].offset
;
1027 vtx
->attr
[j
].vertoffset
= offset
;
1029 /* fprintf(stderr, "%d: %s offset %d\n", i, */
1030 /* format_info[format].name, vtx->attr[j].vertoffset); */
1032 offset
+= format_info
[format
].attrsize
;
1037 vtx
->attr_count
= j
;
1040 vtx
->vertex_size
= unpacked_size
;
1042 vtx
->vertex_size
= offset
;
1044 assert(vtx
->vertex_size
<= vtx
->max_vertex_size
);
1046 return vtx
->vertex_size
;
1051 void _tnl_invalidate_vertices( GLcontext
*ctx
, GLuint newinputs
)
1053 struct tnl_clipspace
*vtx
= GET_VERTEX_STATE(ctx
);
1054 vtx
->new_inputs
|= newinputs
;
1059 void _tnl_build_vertices( GLcontext
*ctx
,
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
));
1068 newinputs
|= vtx
->new_inputs
;
1069 vtx
->new_inputs
= 0;
1072 vtx
->emit( ctx
, start
, end
, vDest
);
1076 void *_tnl_emit_vertices_to_buffer( GLcontext
*ctx
,
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
));
1087 void _tnl_init_vertices( GLcontext
*ctx
,
1089 GLuint max_vertex_size
)
1091 struct tnl_clipspace
*vtx
= GET_VERTEX_STATE(ctx
);
1093 _tnl_install_attrs( ctx
, 0, 0, 0, 0 );
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 );
1104 void _tnl_free_vertices( GLcontext
*ctx
)
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;