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_*.
45 #define GET_VERTEX_STATE(ctx) &(TNL_CONTEXT(ctx)->clipspace)
47 static void insert_4f_viewport_4( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
50 GLfloat
*out
= (GLfloat
*)v
;
51 const GLfloat
* const vp
= a
->vp
;
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];
59 static void insert_4f_viewport_3( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
62 GLfloat
*out
= (GLfloat
*)v
;
63 const GLfloat
* const vp
= a
->vp
;
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];
71 static void insert_4f_viewport_2( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
74 GLfloat
*out
= (GLfloat
*)v
;
75 const GLfloat
* const vp
= a
->vp
;
77 out
[0] = vp
[0] * in
[0] + vp
[12];
78 out
[1] = vp
[5] * in
[1] + vp
[13];
83 static void insert_4f_viewport_1( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
86 GLfloat
*out
= (GLfloat
*)v
;
87 const GLfloat
* const vp
= a
->vp
;
89 out
[0] = vp
[0] * in
[0] + vp
[12];
95 static void insert_3f_viewport_3( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
98 GLfloat
*out
= (GLfloat
*)v
;
99 const GLfloat
* const vp
= a
->vp
;
101 out
[0] = vp
[0] * in
[0] + vp
[12];
102 out
[1] = vp
[5] * in
[1] + vp
[13];
103 out
[2] = vp
[10] * in
[2] + vp
[14];
106 static void insert_3f_viewport_2( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
109 GLfloat
*out
= (GLfloat
*)v
;
110 const GLfloat
* const vp
= a
->vp
;
112 out
[0] = vp
[0] * in
[0] + vp
[12];
113 out
[1] = vp
[5] * in
[1] + vp
[13];
114 out
[2] = vp
[10] * in
[2] + vp
[14];
117 static void insert_3f_viewport_1( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
120 GLfloat
*out
= (GLfloat
*)v
;
121 const GLfloat
* const vp
= a
->vp
;
123 out
[0] = vp
[0] * in
[0] + vp
[12];
128 static void insert_2f_viewport_2( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
131 GLfloat
*out
= (GLfloat
*)v
;
132 const GLfloat
* const vp
= a
->vp
;
134 out
[0] = vp
[0] * in
[0] + vp
[12];
135 out
[1] = vp
[5] * in
[1] + vp
[13];
138 static void insert_2f_viewport_1( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
141 GLfloat
*out
= (GLfloat
*)v
;
142 const GLfloat
* const vp
= a
->vp
;
144 out
[0] = vp
[0] * in
[0] + vp
[12];
149 static void insert_4f_4( const struct tnl_clipspace_attr
*a
, GLubyte
*v
, const GLfloat
*in
)
151 GLfloat
*out
= (GLfloat
*)(v
);
159 static void insert_4f_3( const struct tnl_clipspace_attr
*a
, GLubyte
*v
, const GLfloat
*in
)
161 GLfloat
*out
= (GLfloat
*)(v
);
169 static void insert_4f_2( const struct tnl_clipspace_attr
*a
, GLubyte
*v
, const GLfloat
*in
)
171 GLfloat
*out
= (GLfloat
*)(v
);
179 static void insert_4f_1( const struct tnl_clipspace_attr
*a
, GLubyte
*v
, const GLfloat
*in
)
181 GLfloat
*out
= (GLfloat
*)(v
);
189 static void insert_3f_xyw_4( const struct tnl_clipspace_attr
*a
, GLubyte
*v
, const GLfloat
*in
)
191 GLfloat
*out
= (GLfloat
*)(v
);
198 static void insert_3f_xyw_err( const struct tnl_clipspace_attr
*a
, GLubyte
*v
, const GLfloat
*in
)
203 static void insert_3f_3( const struct tnl_clipspace_attr
*a
, GLubyte
*v
, const GLfloat
*in
)
205 GLfloat
*out
= (GLfloat
*)(v
);
212 static void insert_3f_2( const struct tnl_clipspace_attr
*a
, GLubyte
*v
, const GLfloat
*in
)
214 GLfloat
*out
= (GLfloat
*)(v
);
221 static void insert_3f_1( const struct tnl_clipspace_attr
*a
, GLubyte
*v
, const GLfloat
*in
)
223 GLfloat
*out
= (GLfloat
*)(v
);
231 static void insert_2f_2( const struct tnl_clipspace_attr
*a
, GLubyte
*v
, const GLfloat
*in
)
233 GLfloat
*out
= (GLfloat
*)(v
);
239 static void insert_2f_1( const struct tnl_clipspace_attr
*a
, GLubyte
*v
, const GLfloat
*in
)
241 GLfloat
*out
= (GLfloat
*)(v
);
247 static void insert_1f_1( const struct tnl_clipspace_attr
*a
, GLubyte
*v
, const GLfloat
*in
)
249 GLfloat
*out
= (GLfloat
*)(v
);
254 static void insert_4chan_4f_rgba_4( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
257 GLchan
*c
= (GLchan
*)v
;
258 UNCLAMPED_FLOAT_TO_CHAN(c
[0], in
[0]);
259 UNCLAMPED_FLOAT_TO_CHAN(c
[1], in
[1]);
260 UNCLAMPED_FLOAT_TO_CHAN(c
[2], in
[2]);
261 UNCLAMPED_FLOAT_TO_CHAN(c
[3], in
[3]);
264 static void insert_4chan_4f_rgba_3( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
267 GLchan
*c
= (GLchan
*)v
;
268 UNCLAMPED_FLOAT_TO_CHAN(c
[0], in
[0]);
269 UNCLAMPED_FLOAT_TO_CHAN(c
[1], in
[1]);
270 UNCLAMPED_FLOAT_TO_CHAN(c
[2], in
[2]);
274 static void insert_4chan_4f_rgba_2( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
277 GLchan
*c
= (GLchan
*)v
;
278 UNCLAMPED_FLOAT_TO_CHAN(c
[0], in
[0]);
279 UNCLAMPED_FLOAT_TO_CHAN(c
[1], in
[1]);
284 static void insert_4chan_4f_rgba_1( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
287 GLchan
*c
= (GLchan
*)v
;
288 UNCLAMPED_FLOAT_TO_CHAN(c
[0], in
[0]);
294 static void insert_4ub_4f_rgba_4( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
297 UNCLAMPED_FLOAT_TO_UBYTE(v
[0], in
[0]);
298 UNCLAMPED_FLOAT_TO_UBYTE(v
[1], in
[1]);
299 UNCLAMPED_FLOAT_TO_UBYTE(v
[2], in
[2]);
300 UNCLAMPED_FLOAT_TO_UBYTE(v
[3], in
[3]);
303 static void insert_4ub_4f_rgba_3( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
306 UNCLAMPED_FLOAT_TO_UBYTE(v
[0], in
[0]);
307 UNCLAMPED_FLOAT_TO_UBYTE(v
[1], in
[1]);
308 UNCLAMPED_FLOAT_TO_UBYTE(v
[2], in
[2]);
312 static void insert_4ub_4f_rgba_2( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
315 UNCLAMPED_FLOAT_TO_UBYTE(v
[0], in
[0]);
316 UNCLAMPED_FLOAT_TO_UBYTE(v
[1], in
[1]);
321 static void insert_4ub_4f_rgba_1( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
324 UNCLAMPED_FLOAT_TO_UBYTE(v
[0], in
[0]);
330 static void insert_4ub_4f_bgra_4( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
333 UNCLAMPED_FLOAT_TO_UBYTE(v
[2], in
[0]);
334 UNCLAMPED_FLOAT_TO_UBYTE(v
[1], in
[1]);
335 UNCLAMPED_FLOAT_TO_UBYTE(v
[0], in
[2]);
336 UNCLAMPED_FLOAT_TO_UBYTE(v
[3], in
[3]);
339 static void insert_4ub_4f_bgra_3( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
342 UNCLAMPED_FLOAT_TO_UBYTE(v
[2], in
[0]);
343 UNCLAMPED_FLOAT_TO_UBYTE(v
[1], in
[1]);
344 UNCLAMPED_FLOAT_TO_UBYTE(v
[0], in
[2]);
348 static void insert_4ub_4f_bgra_2( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
351 UNCLAMPED_FLOAT_TO_UBYTE(v
[2], in
[0]);
352 UNCLAMPED_FLOAT_TO_UBYTE(v
[1], in
[1]);
357 static void insert_4ub_4f_bgra_1( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
360 UNCLAMPED_FLOAT_TO_UBYTE(v
[2], in
[0]);
366 static void insert_3ub_3f_rgb_3( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
369 UNCLAMPED_FLOAT_TO_UBYTE(v
[0], in
[0]);
370 UNCLAMPED_FLOAT_TO_UBYTE(v
[1], in
[1]);
371 UNCLAMPED_FLOAT_TO_UBYTE(v
[2], in
[2]);
374 static void insert_3ub_3f_rgb_2( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
377 UNCLAMPED_FLOAT_TO_UBYTE(v
[0], in
[0]);
378 UNCLAMPED_FLOAT_TO_UBYTE(v
[1], in
[1]);
382 static void insert_3ub_3f_rgb_1( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
385 UNCLAMPED_FLOAT_TO_UBYTE(v
[0], in
[0]);
390 static void insert_3ub_3f_bgr_3( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
393 UNCLAMPED_FLOAT_TO_UBYTE(v
[2], in
[0]);
394 UNCLAMPED_FLOAT_TO_UBYTE(v
[1], in
[1]);
395 UNCLAMPED_FLOAT_TO_UBYTE(v
[0], in
[2]);
398 static void insert_3ub_3f_bgr_2( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
401 UNCLAMPED_FLOAT_TO_UBYTE(v
[2], in
[0]);
402 UNCLAMPED_FLOAT_TO_UBYTE(v
[1], in
[1]);
406 static void insert_3ub_3f_bgr_1( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
409 UNCLAMPED_FLOAT_TO_UBYTE(v
[2], in
[0]);
415 static void insert_1ub_1f_1( const struct tnl_clipspace_attr
*a
, GLubyte
*v
,
418 UNCLAMPED_FLOAT_TO_UBYTE(v
[0], in
[0]);
422 /***********************************************************************
423 * Functions to perform the reverse operations to the above, for
424 * swrast translation and clip-interpolation.
426 * Currently always extracts a full 4 floats.
429 static void extract_4f_viewport( const struct tnl_clipspace_attr
*a
, GLfloat
*out
,
432 const GLfloat
*in
= (const GLfloat
*)v
;
433 const GLfloat
* const vp
= a
->vp
;
435 out
[0] = (in
[0] - vp
[12]) / vp
[0];
436 out
[1] = (in
[1] - vp
[13]) / vp
[5];
437 out
[2] = (in
[2] - vp
[14]) / vp
[10];
441 static void extract_3f_viewport( const struct tnl_clipspace_attr
*a
, GLfloat
*out
,
444 const GLfloat
*in
= (const GLfloat
*)v
;
445 const GLfloat
* const vp
= a
->vp
;
447 out
[0] = (in
[0] - vp
[12]) / vp
[0];
448 out
[1] = (in
[1] - vp
[13]) / vp
[5];
449 out
[2] = (in
[2] - vp
[14]) / vp
[10];
454 static void extract_2f_viewport( const struct tnl_clipspace_attr
*a
, GLfloat
*out
,
457 const GLfloat
*in
= (const GLfloat
*)v
;
458 const GLfloat
* const vp
= a
->vp
;
460 out
[0] = (in
[0] - vp
[12]) / vp
[0];
461 out
[1] = (in
[1] - vp
[13]) / vp
[5];
467 static void extract_4f( const struct tnl_clipspace_attr
*a
, GLfloat
*out
, const GLubyte
*v
)
469 const GLfloat
*in
= (const GLfloat
*)v
;
477 static void extract_3f_xyw( const struct tnl_clipspace_attr
*a
, GLfloat
*out
, const GLubyte
*v
)
479 const GLfloat
*in
= (const GLfloat
*)v
;
488 static void extract_3f( const struct tnl_clipspace_attr
*a
, GLfloat
*out
, const GLubyte
*v
)
490 const GLfloat
*in
= (const GLfloat
*)v
;
499 static void extract_2f( const struct tnl_clipspace_attr
*a
, GLfloat
*out
, const GLubyte
*v
)
501 const GLfloat
*in
= (const GLfloat
*)v
;
509 static void extract_1f( const struct tnl_clipspace_attr
*a
, GLfloat
*out
, const GLubyte
*v
)
511 const GLfloat
*in
= (const GLfloat
*)v
;
519 static void extract_4chan_4f_rgba( const struct tnl_clipspace_attr
*a
, GLfloat
*out
,
522 GLchan
*c
= (GLchan
*)v
;
524 out
[0] = CHAN_TO_FLOAT(c
[0]);
525 out
[1] = CHAN_TO_FLOAT(c
[1]);
526 out
[2] = CHAN_TO_FLOAT(c
[2]);
527 out
[3] = CHAN_TO_FLOAT(c
[3]);
530 static void extract_4ub_4f_rgba( const struct tnl_clipspace_attr
*a
, GLfloat
*out
,
533 out
[0] = UBYTE_TO_FLOAT(v
[0]);
534 out
[1] = UBYTE_TO_FLOAT(v
[1]);
535 out
[2] = UBYTE_TO_FLOAT(v
[2]);
536 out
[3] = UBYTE_TO_FLOAT(v
[3]);
539 static void extract_4ub_4f_bgra( const struct tnl_clipspace_attr
*a
, GLfloat
*out
,
542 out
[2] = UBYTE_TO_FLOAT(v
[0]);
543 out
[1] = UBYTE_TO_FLOAT(v
[1]);
544 out
[0] = UBYTE_TO_FLOAT(v
[2]);
545 out
[3] = UBYTE_TO_FLOAT(v
[3]);
548 static void extract_3ub_3f_rgb( const struct tnl_clipspace_attr
*a
, GLfloat
*out
,
551 out
[0] = UBYTE_TO_FLOAT(v
[0]);
552 out
[1] = UBYTE_TO_FLOAT(v
[1]);
553 out
[2] = UBYTE_TO_FLOAT(v
[2]);
557 static void extract_3ub_3f_bgr( const struct tnl_clipspace_attr
*a
, GLfloat
*out
,
560 out
[2] = UBYTE_TO_FLOAT(v
[0]);
561 out
[1] = UBYTE_TO_FLOAT(v
[1]);
562 out
[0] = UBYTE_TO_FLOAT(v
[2]);
566 static void extract_1ub_1f( const struct tnl_clipspace_attr
*a
, GLfloat
*out
, const GLubyte
*v
)
568 out
[0] = UBYTE_TO_FLOAT(v
[0]);
577 extract_func extract
;
578 insert_func insert
[4];
580 } format_info
[EMIT_MAX
] = {
584 { insert_1f_1
, insert_1f_1
, insert_1f_1
, insert_1f_1
},
589 { insert_2f_1
, insert_2f_2
, insert_2f_2
, insert_2f_2
},
590 2 * sizeof(GLfloat
) },
594 { insert_3f_1
, insert_3f_2
, insert_3f_3
, insert_3f_3
},
595 3 * sizeof(GLfloat
) },
599 { insert_4f_1
, insert_4f_2
, insert_4f_3
, insert_4f_4
},
600 4 * sizeof(GLfloat
) },
604 { insert_2f_viewport_1
, insert_2f_viewport_2
, insert_2f_viewport_2
,
605 insert_2f_viewport_2
},
606 2 * sizeof(GLfloat
) },
610 { insert_3f_viewport_1
, insert_3f_viewport_2
, insert_3f_viewport_3
,
611 insert_3f_viewport_3
},
612 3 * sizeof(GLfloat
) },
616 { insert_4f_viewport_1
, insert_4f_viewport_2
, insert_4f_viewport_3
,
617 insert_4f_viewport_4
},
618 4 * sizeof(GLfloat
) },
622 { insert_3f_xyw_err
, insert_3f_xyw_err
, insert_3f_xyw_err
,
624 3 * sizeof(GLfloat
) },
628 { insert_1ub_1f_1
, insert_1ub_1f_1
, insert_1ub_1f_1
, insert_1ub_1f_1
},
633 { insert_3ub_3f_rgb_1
, insert_3ub_3f_rgb_2
, insert_3ub_3f_rgb_3
,
634 insert_3ub_3f_rgb_3
},
635 3 * sizeof(GLubyte
) },
639 { insert_3ub_3f_bgr_1
, insert_3ub_3f_bgr_2
, insert_3ub_3f_bgr_3
,
640 insert_3ub_3f_bgr_3
},
641 3 * sizeof(GLubyte
) },
645 { insert_4ub_4f_rgba_1
, insert_4ub_4f_rgba_2
, insert_4ub_4f_rgba_3
,
646 insert_4ub_4f_rgba_4
},
647 4 * sizeof(GLubyte
) },
651 { insert_4ub_4f_bgra_1
, insert_4ub_4f_bgra_2
, insert_4ub_4f_bgra_3
,
652 insert_4ub_4f_bgra_4
},
653 4 * sizeof(GLubyte
) },
656 extract_4chan_4f_rgba
,
657 { insert_4chan_4f_rgba_1
, insert_4chan_4f_rgba_2
, insert_4chan_4f_rgba_3
,
658 insert_4chan_4f_rgba_4
},
664 /***********************************************************************
665 * Generic (non-codegen) functions for whole vertices or groups of
669 static void generic_emit( GLcontext
*ctx
,
670 GLuint start
, GLuint end
,
673 struct vertex_buffer
*VB
= &TNL_CONTEXT(ctx
)->vb
;
674 struct tnl_clipspace
*vtx
= GET_VERTEX_STATE(ctx
);
675 struct tnl_clipspace_attr
*a
= vtx
->attr
;
676 GLubyte
*v
= (GLubyte
*)dest
;
678 GLuint count
= vtx
->attr_count
;
681 for (j
= 0; j
< count
; j
++) {
682 GLvector4f
*vptr
= VB
->AttribPtr
[a
[j
].attrib
];
683 a
[j
].inputstride
= vptr
->stride
;
684 a
[j
].inputptr
= ((GLubyte
*)vptr
->data
) + start
* vptr
->stride
;
685 a
[j
].emit
= a
[j
].insert
[vptr
->size
- 1];
689 stride
= vtx
->vertex_size
;
691 for (i
= 0 ; i
< end
; i
++, v
+= stride
) {
692 for (j
= 0; j
< count
; j
++) {
693 GLfloat
*in
= (GLfloat
*)a
[j
].inputptr
;
694 a
[j
].inputptr
+= a
[j
].inputstride
;
695 a
[j
].emit( &a
[j
], v
+ a
[j
].vertoffset
, in
);
701 static void generic_interp( GLcontext
*ctx
,
703 GLuint edst
, GLuint eout
, GLuint ein
,
704 GLboolean force_boundary
)
706 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
707 struct vertex_buffer
*VB
= &tnl
->vb
;
708 struct tnl_clipspace
*vtx
= GET_VERTEX_STATE(ctx
);
709 GLubyte
*vin
= vtx
->vertex_buf
+ ein
* vtx
->vertex_size
;
710 GLubyte
*vout
= vtx
->vertex_buf
+ eout
* vtx
->vertex_size
;
711 GLubyte
*vdst
= vtx
->vertex_buf
+ edst
* vtx
->vertex_size
;
712 const struct tnl_clipspace_attr
*a
= vtx
->attr
;
713 int attr_count
= vtx
->attr_count
;
716 if (tnl
->NeedNdcCoords
) {
717 const GLfloat
*dstclip
= VB
->ClipPtr
->data
[edst
];
718 const GLfloat w
= 1.0 / dstclip
[3];
721 pos
[0] = dstclip
[0] * w
;
722 pos
[1] = dstclip
[1] * w
;
723 pos
[2] = dstclip
[2] * w
;
726 a
[0].insert
[4-1]( &a
[0], vdst
, pos
);
729 a
[0].insert
[4-1]( &a
[0], vdst
, VB
->ClipPtr
->data
[edst
] );
733 for (j
= 1; j
< attr_count
; j
++) {
734 GLfloat fin
[4], fout
[4], fdst
[4];
736 a
[j
].extract( &a
[j
], fin
, vin
+ a
[j
].vertoffset
);
737 a
[j
].extract( &a
[j
], fout
, vout
+ a
[j
].vertoffset
);
739 INTERP_F( t
, fdst
[3], fout
[3], fin
[3] );
740 INTERP_F( t
, fdst
[2], fout
[2], fin
[2] );
741 INTERP_F( t
, fdst
[1], fout
[1], fin
[1] );
742 INTERP_F( t
, fdst
[0], fout
[0], fin
[0] );
744 a
[j
].insert
[4-1]( &a
[j
], vdst
+ a
[j
].vertoffset
, fdst
);
749 /* Extract color attributes from one vertex and insert them into
750 * another. (Shortcircuit extract/insert with memcpy).
752 static void generic_copy_pv( GLcontext
*ctx
, GLuint edst
, GLuint esrc
)
754 struct tnl_clipspace
*vtx
= GET_VERTEX_STATE(ctx
);
755 GLubyte
*vsrc
= vtx
->vertex_buf
+ esrc
* vtx
->vertex_size
;
756 GLubyte
*vdst
= vtx
->vertex_buf
+ edst
* vtx
->vertex_size
;
757 const struct tnl_clipspace_attr
*a
= vtx
->attr
;
758 int attr_count
= vtx
->attr_count
;
761 for (j
= 0; j
< attr_count
; j
++) {
762 if (a
[j
].attrib
== VERT_ATTRIB_COLOR0
||
763 a
[j
].attrib
== VERT_ATTRIB_COLOR1
) {
765 memcpy( vdst
+ a
[j
].vertoffset
,
766 vsrc
+ a
[j
].vertoffset
,
773 /* Helper functions for hardware which doesn't put back colors and/or
774 * edgeflags into vertices.
776 static void generic_interp_extras( GLcontext
*ctx
,
778 GLuint dst
, GLuint out
, GLuint in
,
779 GLboolean force_boundary
)
781 struct vertex_buffer
*VB
= &TNL_CONTEXT(ctx
)->vb
;
783 if (VB
->ColorPtr
[1]) {
784 assert(VB
->ColorPtr
[1]->stride
== 4 * sizeof(GLfloat
));
787 VB
->ColorPtr
[1]->data
[dst
],
788 VB
->ColorPtr
[1]->data
[out
],
789 VB
->ColorPtr
[1]->data
[in
] );
791 if (VB
->SecondaryColorPtr
[1]) {
793 VB
->SecondaryColorPtr
[1]->data
[dst
],
794 VB
->SecondaryColorPtr
[1]->data
[out
],
795 VB
->SecondaryColorPtr
[1]->data
[in
] );
798 else if (VB
->IndexPtr
[1]) {
799 VB
->IndexPtr
[1]->data
[dst
][0] = LINTERP( t
,
800 VB
->IndexPtr
[1]->data
[out
][0],
801 VB
->IndexPtr
[1]->data
[in
][0] );
805 VB
->EdgeFlag
[dst
] = VB
->EdgeFlag
[out
] || force_boundary
;
808 generic_interp(ctx
, t
, dst
, out
, in
, force_boundary
);
811 static void generic_copy_pv_extras( GLcontext
*ctx
,
812 GLuint dst
, GLuint src
)
814 struct vertex_buffer
*VB
= &TNL_CONTEXT(ctx
)->vb
;
816 if (VB
->ColorPtr
[1]) {
817 COPY_4FV( VB
->ColorPtr
[1]->data
[dst
],
818 VB
->ColorPtr
[1]->data
[src
] );
820 if (VB
->SecondaryColorPtr
[1]) {
821 COPY_4FV( VB
->SecondaryColorPtr
[1]->data
[dst
],
822 VB
->SecondaryColorPtr
[1]->data
[src
] );
825 else if (VB
->IndexPtr
[1]) {
826 VB
->IndexPtr
[1]->data
[dst
][0] = VB
->IndexPtr
[1]->data
[src
][0];
829 _tnl_copy_pv(ctx
, dst
, src
);
837 /***********************************************************************
838 * Build codegen functions or return generic ones:
842 static void choose_emit_func( GLcontext
*ctx
,
843 GLuint start
, GLuint end
,
846 struct tnl_clipspace
*vtx
= GET_VERTEX_STATE(ctx
);
847 vtx
->emit
= generic_emit
;
848 vtx
->emit( ctx
, start
, end
, dest
);
852 static void choose_interp_func( GLcontext
*ctx
,
854 GLuint edst
, GLuint eout
, GLuint ein
,
855 GLboolean force_boundary
)
857 struct tnl_clipspace
*vtx
= GET_VERTEX_STATE(ctx
);
859 if (vtx
->need_extras
&&
860 (ctx
->_TriangleCaps
& (DD_TRI_LIGHT_TWOSIDE
|DD_TRI_UNFILLED
))) {
861 vtx
->interp
= generic_interp_extras
;
863 vtx
->interp
= generic_interp
;
866 vtx
->interp( ctx
, t
, edst
, eout
, ein
, force_boundary
);
870 static void choose_copy_pv_func( GLcontext
*ctx
, GLuint edst
, GLuint esrc
)
872 struct tnl_clipspace
*vtx
= GET_VERTEX_STATE(ctx
);
874 if (vtx
->need_extras
&&
875 (ctx
->_TriangleCaps
& (DD_TRI_LIGHT_TWOSIDE
|DD_TRI_UNFILLED
))) {
876 vtx
->copy_pv
= generic_copy_pv_extras
;
878 vtx
->copy_pv
= generic_copy_pv
;
881 vtx
->copy_pv( ctx
, edst
, esrc
);
885 /***********************************************************************
886 * Public entrypoints, mostly dispatch to the above:
890 /* Interpolate between two vertices to produce a third:
892 void _tnl_interp( GLcontext
*ctx
,
894 GLuint edst
, GLuint eout
, GLuint ein
,
895 GLboolean force_boundary
)
897 struct tnl_clipspace
*vtx
= GET_VERTEX_STATE(ctx
);
898 vtx
->interp( ctx
, t
, edst
, eout
, ein
, force_boundary
);
901 /* Copy colors from one vertex to another:
903 void _tnl_copy_pv( GLcontext
*ctx
, GLuint edst
, GLuint esrc
)
905 struct tnl_clipspace
*vtx
= GET_VERTEX_STATE(ctx
);
906 vtx
->copy_pv( ctx
, edst
, esrc
);
910 /* Extract a named attribute from a hardware vertex. Will have to
911 * reverse any viewport transformation, swizzling or other conversions
912 * which may have been applied:
914 void _tnl_get_attr( GLcontext
*ctx
, const void *vin
,
915 GLenum attr
, GLfloat
*dest
)
917 struct tnl_clipspace
*vtx
= GET_VERTEX_STATE(ctx
);
918 const struct tnl_clipspace_attr
*a
= vtx
->attr
;
919 int attr_count
= vtx
->attr_count
;
922 for (j
= 0; j
< attr_count
; j
++) {
923 if (a
[j
].attrib
== attr
) {
924 a
[j
].extract( &a
[j
], dest
, (GLubyte
*)vin
+ a
[j
].vertoffset
);
929 /* Else return the value from ctx->Current
931 memcpy( dest
, ctx
->Current
.Attrib
[attr
], 4*sizeof(GLfloat
));
934 void *_tnl_get_vertex( GLcontext
*ctx
, GLuint nr
)
936 struct tnl_clipspace
*vtx
= GET_VERTEX_STATE(ctx
);
938 return vtx
->vertex_buf
+ nr
* vtx
->vertex_size
;
941 void _tnl_invalidate_vertex_state( GLcontext
*ctx
, GLuint new_state
)
943 if (new_state
& (_DD_NEW_TRI_LIGHT_TWOSIDE
|_DD_NEW_TRI_UNFILLED
) ) {
944 struct tnl_clipspace
*vtx
= GET_VERTEX_STATE(ctx
);
945 vtx
->new_inputs
= ~0;
946 vtx
->interp
= choose_interp_func
;
947 vtx
->copy_pv
= choose_copy_pv_func
;
952 GLuint
_tnl_install_attrs( GLcontext
*ctx
, const struct tnl_attr_map
*map
,
953 GLuint nr
, const GLfloat
*vp
,
954 GLuint unpacked_size
)
956 struct tnl_clipspace
*vtx
= GET_VERTEX_STATE(ctx
);
960 assert(nr
< _TNL_ATTRIB_MAX
);
961 assert(nr
== 0 || map
[0].attrib
== VERT_ATTRIB_POS
);
963 vtx
->attr_count
= nr
;
964 vtx
->emit
= choose_emit_func
;
965 vtx
->interp
= choose_interp_func
;
966 vtx
->copy_pv
= choose_copy_pv_func
;
967 vtx
->new_inputs
= ~0;
969 for (i
= 0; i
< nr
; i
++) {
970 GLuint format
= map
[i
].format
;
971 vtx
->attr
[i
].attrib
= map
[i
].attrib
;
972 vtx
->attr
[i
].vp
= vp
;
973 vtx
->attr
[i
].insert
= format_info
[format
].insert
;
974 vtx
->attr
[i
].extract
= format_info
[format
].extract
;
975 vtx
->attr
[i
].vertattrsize
= format_info
[format
].attrsize
;
978 vtx
->attr
[i
].vertoffset
= map
[i
].offset
;
980 vtx
->attr
[i
].vertoffset
= offset
;
982 /* fprintf(stderr, "%d: %s offset %d\n", i, */
983 /* format_info[format].name, vtx->attr[i].vertoffset); */
985 offset
+= format_info
[format
].attrsize
;
989 vtx
->vertex_size
= unpacked_size
;
991 vtx
->vertex_size
= offset
;
993 assert(vtx
->vertex_size
<= vtx
->max_vertex_size
);
995 return vtx
->vertex_size
;
1000 void _tnl_invalidate_vertices( GLcontext
*ctx
, GLuint newinputs
)
1002 struct tnl_clipspace
*vtx
= GET_VERTEX_STATE(ctx
);
1003 vtx
->new_inputs
|= newinputs
;
1008 void _tnl_build_vertices( GLcontext
*ctx
,
1013 struct tnl_clipspace
*vtx
= GET_VERTEX_STATE(ctx
);
1014 GLuint stride
= vtx
->vertex_size
;
1015 GLubyte
*v
= ((GLubyte
*)vtx
->vertex_buf
+ (start
*stride
));
1017 newinputs
|= vtx
->new_inputs
;
1018 vtx
->new_inputs
= 0;
1021 vtx
->emit( ctx
, start
, count
, v
);
1025 void *_tnl_emit_vertices_to_buffer( GLcontext
*ctx
,
1030 struct tnl_clipspace
*vtx
= GET_VERTEX_STATE(ctx
);
1031 vtx
->emit( ctx
, start
, count
, dest
);
1032 return (void *)((GLubyte
*)dest
+ vtx
->vertex_size
* (count
- start
));
1036 void _tnl_init_vertices( GLcontext
*ctx
,
1038 GLuint max_vertex_size
)
1040 struct tnl_clipspace
*vtx
= GET_VERTEX_STATE(ctx
);
1042 _tnl_install_attrs( ctx
, 0, 0, 0, 0 );
1044 vtx
->need_extras
= GL_TRUE
;
1045 if (max_vertex_size
> vtx
->max_vertex_size
) {
1046 _tnl_free_vertices( ctx
);
1047 vtx
->max_vertex_size
= max_vertex_size
;
1048 vtx
->vertex_buf
= (GLubyte
*)ALIGN_MALLOC(vb_size
* max_vertex_size
, 32 );
1053 void _tnl_free_vertices( GLcontext
*ctx
)
1055 struct tnl_clipspace
*vtx
= GET_VERTEX_STATE(ctx
);
1056 if (vtx
->vertex_buf
) {
1057 ALIGN_FREE(vtx
->vertex_buf
);
1058 vtx
->vertex_buf
= 0;