3 * Mesa 3-D graphics library
6 * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 * Keith Whitwell <keith@tungstengraphics.com>
30 /* Template for render stages which build and emit vertices directly
31 * to fixed-size dma buffers. Useful for rendering strips and other
32 * native primitives where clipping and per-vertex tweaks such as
33 * those in t_dd_tritmp.h are not required.
35 * Produces code for both inline triangles and indexed triangles.
36 * Where various primitive types are unaccelerated by hardware, the
37 * code attempts to fallback to other primitive types (quadstrips to
38 * tristrips, lineloops to linestrips), or to indexed vertices.
39 * Ultimately, a FALLBACK() macro is invoked if there is no way to
40 * render the primitive natively.
43 #if !defined(HAVE_TRIANGLES)
44 #error "must have at least triangles to use render template"
49 #define ALLOC_ELTS( nr )
50 #define EMIT_ELT( offset, elt )
51 #define EMIT_TWO_ELTS( offset, elt0, elt1 )
52 #define INCR_ELTS( nr )
53 #define ELT_INIT(prim)
54 #define GET_CURRENT_VB_MAX_ELTS() 0
55 #define GET_SUBSEQUENT_VB_MAX_ELTS() 0
56 #define ALLOC_ELTS_NEW_PRIMITIVE(nr)
57 #define RELEASE_ELT_VERTS()
58 #define EMIT_INDEXED_VERTS( ctx, start, count )
62 #define EMIT_TWO_ELTS( offset, elt0, elt1 ) \
64 EMIT_ELT( offset, elt0 ); \
65 EMIT_ELT( offset+1, elt1 ); \
73 /**********************************************************************/
74 /* Render whole begin/end objects */
75 /**********************************************************************/
79 static GLboolean
TAG(emit_elt_verts
)( GLcontext
*ctx
,
80 GLuint start
, GLuint count
)
84 GLuint nr
= count
- start
;
86 if ( nr
>= GET_SUBSEQUENT_VB_MAX_VERTS() ) /* assumes same packing for
87 * indexed and regualar verts
91 NEW_PRIMITIVE(); /* finish last prim */
92 EMIT_INDEXED_VERTS( ctx
, start
, count
);
100 static void TAG(emit_elts
)( GLcontext
*ctx
, GLuint
*elts
, GLuint nr
)
108 for ( i
= 0 ; i
< nr
; i
+=2, elts
+= 2 ) {
109 EMIT_TWO_ELTS( 0, elts
[0], elts
[1] );
116 /***********************************************************************
117 * Render non-indexed primitives.
118 ***********************************************************************/
122 static void TAG(render_points_verts
)( GLcontext
*ctx
,
129 int dmasz
= GET_SUBSEQUENT_VB_MAX_VERTS();
130 int currentsz
= GET_CURRENT_VB_MAX_VERTS();
138 for (j
= start
; j
< count
; j
+= nr
) {
139 nr
= MIN2( currentsz
, count
- j
);
140 EMIT_VERTS( ctx
, j
, nr
);
147 VERT_FALLBACK( ctx
, start
, count
, flags
);
151 static void TAG(render_lines_verts
)( GLcontext
*ctx
,
158 int dmasz
= GET_SUBSEQUENT_VB_MAX_VERTS();
159 int currentsz
= GET_CURRENT_VB_MAX_VERTS();
164 /* Emit whole number of lines in total and in each buffer:
166 count
-= (count
-start
) & 1;
167 currentsz
-= currentsz
& 1;
173 for (j
= start
; j
< count
; j
+= nr
) {
174 nr
= MIN2( currentsz
, count
- j
);
175 EMIT_VERTS( ctx
, j
, nr
);
182 VERT_FALLBACK( ctx
, start
, count
, flags
);
187 static void TAG(render_line_strip_verts
)( GLcontext
*ctx
,
192 if (HAVE_LINE_STRIPS
) {
194 int dmasz
= GET_SUBSEQUENT_VB_MAX_VERTS();
195 int currentsz
= GET_CURRENT_VB_MAX_VERTS();
198 NEW_PRIMITIVE(); /* always a new primitive */
199 INIT( GL_LINE_STRIP
);
204 for (j
= start
; j
+ 1 < count
; j
+= nr
- 1 ) {
205 nr
= MIN2( currentsz
, count
- j
);
206 EMIT_VERTS( ctx
, j
, nr
);
213 VERT_FALLBACK( ctx
, start
, count
, flags
);
218 static void TAG(render_line_loop_verts
)( GLcontext
*ctx
,
223 if (HAVE_LINE_STRIPS
) {
225 int dmasz
= GET_SUBSEQUENT_VB_MAX_VERTS();
226 int currentsz
= GET_CURRENT_VB_MAX_VERTS();
230 INIT( GL_LINE_STRIP
);
232 if (flags
& PRIM_BEGIN
)
237 /* Ensure last vertex won't wrap buffers:
248 for ( ; j
+ 1 < count
; j
+= nr
- 1 ) {
249 nr
= MIN2( currentsz
, count
- j
);
250 EMIT_VERTS( ctx
, j
, nr
);
254 if (start
< count
- 1 && (flags
& PRIM_END
))
255 EMIT_VERTS( ctx
, start
, 1 );
257 else if (start
+ 1 < count
&& (flags
& PRIM_END
)) {
258 EMIT_VERTS( ctx
, start
+1, 1 );
259 EMIT_VERTS( ctx
, start
, 1 );
265 VERT_FALLBACK( ctx
, start
, count
, flags
);
270 static void TAG(render_triangles_verts
)( GLcontext
*ctx
,
276 int dmasz
= (GET_SUBSEQUENT_VB_MAX_VERTS()/3) * 3;
277 int currentsz
= (GET_CURRENT_VB_MAX_VERTS()/3) * 3;
282 /* Emit whole number of tris in total. dmasz is already a multiple
285 count
-= (count
-start
)%3;
290 for (j
= start
; j
< count
; j
+= nr
) {
291 nr
= MIN2( currentsz
, count
- j
);
292 EMIT_VERTS( ctx
, j
, nr
);
300 static void TAG(render_tri_strip_verts
)( GLcontext
*ctx
,
305 if (HAVE_TRI_STRIPS
) {
308 int dmasz
= GET_SUBSEQUENT_VB_MAX_VERTS();
311 INIT(GL_TRIANGLE_STRIP
);
314 currentsz
= GET_CURRENT_VB_MAX_VERTS();
321 if ((flags
& PRIM_PARITY
) && count
- start
> 2) {
322 if (HAVE_TRI_STRIP_1
&& 0) {
324 EMIT_VERTS( ctx
, start
, 1 );
329 /* From here on emit even numbers of tris when wrapping over buffers:
331 dmasz
-= (dmasz
& 1);
332 currentsz
-= (currentsz
& 1);
334 for (j
= start
; j
+ 2 < count
; j
+= nr
- 2 ) {
335 nr
= MIN2( currentsz
, count
- j
);
336 EMIT_VERTS( ctx
, j
, nr
);
343 VERT_FALLBACK( ctx
, start
, count
, flags
);
347 static void TAG(render_tri_fan_verts
)( GLcontext
*ctx
,
355 int dmasz
= GET_SUBSEQUENT_VB_MAX_VERTS();
356 int currentsz
= GET_CURRENT_VB_MAX_VERTS();
359 INIT(GL_TRIANGLE_FAN
);
366 for (j
= start
+ 1 ; j
+ 1 < count
; j
+= nr
- 1 ) {
367 nr
= MIN2( currentsz
, count
- j
+ 1 );
368 EMIT_VERTS( ctx
, start
, 1 );
369 EMIT_VERTS( ctx
, j
, nr
- 1 );
377 /* Could write code to emit these as indexed vertices (for the
378 * g400, for instance).
380 VERT_FALLBACK( ctx
, start
, count
, flags
);
385 static void TAG(render_poly_verts
)( GLcontext
*ctx
,
393 int dmasz
= GET_SUBSEQUENT_VB_MAX_VERTS();
394 int currentsz
= GET_CURRENT_VB_MAX_VERTS();
404 for (j
= start
+ 1 ; j
+ 1 < count
; j
+= nr
- 1 ) {
405 nr
= MIN2( currentsz
, count
- j
+ 1 );
406 EMIT_VERTS( ctx
, start
, 1 );
407 EMIT_VERTS( ctx
, j
, nr
- 1 );
414 else if (HAVE_TRI_FANS
&& !(ctx
->_TriangleCaps
& DD_FLATSHADE
)) {
415 TAG(render_tri_fan_verts
)( ctx
, start
, count
, flags
);
417 VERT_FALLBACK( ctx
, start
, count
, flags
);
421 static void TAG(render_quad_strip_verts
)( GLcontext
*ctx
,
428 if (HAVE_QUAD_STRIPS
) {
431 int dmasz
= GET_SUBSEQUENT_VB_MAX_VERTS();
437 currentsz
= GET_CURRENT_VB_MAX_VERTS();
444 dmasz
-= (dmasz
& 2);
445 currentsz
-= (currentsz
& 2);
447 for (j
= start
; j
+ 3 < count
; j
+= nr
- 2 ) {
448 nr
= MIN2( currentsz
, count
- j
);
449 EMIT_VERTS( ctx
, j
, nr
);
455 } else if (HAVE_TRI_STRIPS
&& (ctx
->_TriangleCaps
& DD_FLATSHADE
)) {
456 if (TAG(emit_elt_verts
)( ctx
, start
, count
)) {
458 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS();
462 /* Simulate flat-shaded quadstrips using indexed vertices:
465 ELT_INIT( GL_TRIANGLES
);
467 currentsz
= GET_CURRENT_VB_MAX_ELTS();
469 /* Emit whole number of quads in total, and in each buffer.
472 count
-= (count
-start
) & 1;
473 currentsz
-= currentsz
& 1;
478 currentsz
= currentsz
/6*2;
481 for (j
= start
; j
+ 3 < count
; j
+= nr
- 2 ) {
482 nr
= MIN2( currentsz
, count
- j
);
484 GLint quads
= (nr
/2)-1;
489 ALLOC_ELTS_NEW_PRIMITIVE( quads
*6 );
491 for ( i
= j
-start
; i
< j
-start
+quads
*2 ; i
+=2 ) {
492 EMIT_TWO_ELTS( 0, (i
+0), (i
+1) );
493 EMIT_TWO_ELTS( 2, (i
+2), (i
+1) );
494 EMIT_TWO_ELTS( 4, (i
+3), (i
+2) );
506 /* Vertices won't fit in a single buffer or elts not available,
509 VERT_FALLBACK( ctx
, start
, count
, flags
);
512 else if (HAVE_TRI_STRIPS
) {
514 int dmasz
= GET_SUBSEQUENT_VB_MAX_VERTS();
515 int currentsz
= GET_CURRENT_VB_MAX_VERTS();
517 /* Emit smooth-shaded quadstrips as tristrips:
520 INIT( GL_TRIANGLE_STRIP
);
522 /* Emit whole number of quads in total, and in each buffer.
525 currentsz
-= currentsz
& 1;
526 count
-= (count
-start
) & 1;
533 for (j
= start
; j
+ 3 < count
; j
+= nr
- 2 ) {
534 nr
= MIN2( currentsz
, count
- j
);
535 EMIT_VERTS( ctx
, j
, nr
);
542 VERT_FALLBACK( ctx
, start
, count
, flags
);
547 static void TAG(render_quads_verts
)( GLcontext
*ctx
,
554 int dmasz
= (GET_SUBSEQUENT_VB_MAX_VERTS()/4) * 4;
555 int currentsz
= (GET_CURRENT_VB_MAX_VERTS()/4) * 4;
560 /* Emit whole number of quads in total. dmasz is already a multiple
563 count
-= (count
-start
)%4;
568 for (j
= start
; j
< count
; j
+= nr
) {
569 nr
= MIN2( currentsz
, count
- j
);
570 EMIT_VERTS( ctx
, j
, nr
);
574 } else if (TAG(emit_elt_verts
)( ctx
, start
, count
)) {
575 /* Hardware doesn't have a quad primitive type -- try to
576 * simulate it using indexed vertices and the triangle
580 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS();
585 ELT_INIT( GL_TRIANGLES
);
586 currentsz
= GET_CURRENT_VB_MAX_ELTS();
588 /* Emit whole number of quads in total, and in each buffer.
591 count
-= (count
-start
) & 3;
592 currentsz
-= currentsz
& 3;
594 /* Adjust for rendering as triangles:
596 currentsz
= currentsz
/6*4;
602 for (j
= start
; j
< count
; j
+= nr
) {
603 nr
= MIN2( currentsz
, count
- j
);
610 ALLOC_ELTS_NEW_PRIMITIVE( quads
*6 );
612 for ( i
= j
-start
; i
< j
-start
+quads
*4 ; i
+=4 ) {
613 EMIT_TWO_ELTS( 0, (i
+0), (i
+1) );
614 EMIT_TWO_ELTS( 2, (i
+3), (i
+1) );
615 EMIT_TWO_ELTS( 4, (i
+2), (i
+3) );
627 /* Vertices won't fit in a single buffer, fallback.
629 VERT_FALLBACK( ctx
, start
, count
, flags
);
633 static void TAG(render_noop
)( GLcontext
*ctx
,
643 static render_func
TAG(render_tab_verts
)[GL_POLYGON
+2] =
645 TAG(render_points_verts
),
646 TAG(render_lines_verts
),
647 TAG(render_line_loop_verts
),
648 TAG(render_line_strip_verts
),
649 TAG(render_triangles_verts
),
650 TAG(render_tri_strip_verts
),
651 TAG(render_tri_fan_verts
),
652 TAG(render_quads_verts
),
653 TAG(render_quad_strip_verts
),
654 TAG(render_poly_verts
),
659 /****************************************************************************
660 * Render elts using hardware indexed verts *
661 ****************************************************************************/
664 static void TAG(render_points_elts
)( GLcontext
*ctx
,
671 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS();
673 GLuint
*elts
= TNL_CONTEXT(ctx
)->vb
.Elts
;
676 ELT_INIT( GL_POINTS
);
678 currentsz
= GET_CURRENT_VB_MAX_ELTS();
682 for (j
= start
; j
< count
; j
+= nr
) {
683 nr
= MIN2( currentsz
, count
- j
);
684 TAG(emit_elts
)( ctx
, elts
+j
, nr
);
689 ELT_FALLBACK( ctx
, start
, count
, flags
);
695 static void TAG(render_lines_elts
)( GLcontext
*ctx
,
702 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS();
704 GLuint
*elts
= TNL_CONTEXT(ctx
)->vb
.Elts
;
707 ELT_INIT( GL_LINES
);
709 /* Emit whole number of lines in total and in each buffer:
711 count
-= (count
-start
) & 1;
712 currentsz
-= currentsz
& 1;
715 currentsz
= GET_CURRENT_VB_MAX_ELTS();
719 for (j
= start
; j
< count
; j
+= nr
) {
720 nr
= MIN2( currentsz
, count
- j
);
721 TAG(emit_elts
)( ctx
, elts
+j
, nr
);
726 ELT_FALLBACK( ctx
, start
, count
, flags
);
731 static void TAG(render_line_strip_elts
)( GLcontext
*ctx
,
736 if (HAVE_LINE_STRIPS
) {
738 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS();
740 GLuint
*elts
= TNL_CONTEXT(ctx
)->vb
.Elts
;
743 NEW_PRIMITIVE(); /* always a new primitive */
744 ELT_INIT( GL_LINE_STRIP
);
746 currentsz
= GET_CURRENT_VB_MAX_ELTS();
750 for (j
= start
; j
+ 1 < count
; j
+= nr
- 1 ) {
751 nr
= MIN2( currentsz
, count
- j
);
752 TAG(emit_elts
)( ctx
, elts
+j
, nr
);
757 /* TODO: Try to emit as indexed lines.
759 ELT_FALLBACK( ctx
, start
, count
, flags
);
764 static void TAG(render_line_loop_elts
)( GLcontext
*ctx
,
769 if (HAVE_LINE_STRIPS
) {
771 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS();
773 GLuint
*elts
= TNL_CONTEXT(ctx
)->vb
.Elts
;
777 ELT_INIT( GL_LINE_STRIP
);
779 if (flags
& PRIM_BEGIN
)
784 currentsz
= GET_CURRENT_VB_MAX_ELTS();
790 /* Ensure last vertex doesn't wrap:
795 for ( ; j
+ 1 < count
; j
+= nr
- 1 ) {
796 nr
= MIN2( currentsz
, count
- j
);
797 /* NEW_PRIMITIVE(); */
798 TAG(emit_elts
)( ctx
, elts
+j
, nr
);
802 if (flags
& PRIM_END
)
803 TAG(emit_elts
)( ctx
, elts
+start
, 1 );
807 /* TODO: Try to emit as indexed lines */
808 ELT_FALLBACK( ctx
, start
, count
, flags
);
813 /* For verts, we still eliminate the copy from main memory to dma
814 * buffers. For elts, this is probably no better (worse?) than the
817 static void TAG(render_triangles_elts
)( GLcontext
*ctx
,
823 GLuint
*elts
= TNL_CONTEXT(ctx
)->vb
.Elts
;
824 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS()/3*3;
829 ELT_INIT( GL_TRIANGLES
);
831 currentsz
= GET_CURRENT_VB_MAX_ELTS();
833 /* Emit whole number of tris in total. dmasz is already a multiple
836 count
-= (count
-start
)%3;
837 currentsz
-= currentsz
%3;
841 for (j
= start
; j
< count
; j
+= nr
) {
842 nr
= MIN2( currentsz
, count
- j
);
843 TAG(emit_elts
)( ctx
, elts
+j
, nr
);
851 static void TAG(render_tri_strip_elts
)( GLcontext
*ctx
,
856 if (HAVE_TRI_STRIPS
) {
859 GLuint
*elts
= TNL_CONTEXT(ctx
)->vb
.Elts
;
860 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS();
864 ELT_INIT( GL_TRIANGLE_STRIP
);
866 currentsz
= GET_CURRENT_VB_MAX_ELTS();
872 if ((flags
& PRIM_PARITY
) && count
- start
> 2) {
873 TAG(emit_elts
)( ctx
, elts
+start
, 1 );
876 /* Keep the same winding over multiple buffers:
878 dmasz
-= (dmasz
& 1);
879 currentsz
-= (currentsz
& 1);
881 for (j
= start
; j
+ 2 < count
; j
+= nr
- 2 ) {
882 nr
= MIN2( currentsz
, count
- j
);
883 TAG(emit_elts
)( ctx
, elts
+j
, nr
);
888 /* TODO: try to emit as indexed triangles */
889 ELT_FALLBACK( ctx
, start
, count
, flags
);
893 static void TAG(render_tri_fan_elts
)( GLcontext
*ctx
,
900 GLuint
*elts
= TNL_CONTEXT(ctx
)->vb
.Elts
;
902 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS();
906 ELT_INIT( GL_TRIANGLE_FAN
);
908 currentsz
= GET_CURRENT_VB_MAX_ELTS();
914 for (j
= start
+ 1 ; j
+ 1 < count
; j
+= nr
- 1 ) {
915 nr
= MIN2( currentsz
, count
- j
+ 1 );
916 TAG(emit_elts
)( ctx
, elts
+start
, 1 );
917 TAG(emit_elts
)( ctx
, elts
+j
, nr
- 1 );
922 /* TODO: try to emit as indexed triangles */
923 ELT_FALLBACK( ctx
, start
, count
, flags
);
928 static void TAG(render_poly_elts
)( GLcontext
*ctx
,
933 if (HAVE_POLYGONS
&& 0) {
934 } else if (HAVE_TRI_FANS
&& !(ctx
->_TriangleCaps
& DD_FLATSHADE
)) {
936 GLuint
*elts
= TNL_CONTEXT(ctx
)->vb
.Elts
;
938 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS();
942 ELT_INIT( GL_TRIANGLE_FAN
);
944 currentsz
= GET_CURRENT_VB_MAX_ELTS();
950 for (j
= start
+ 1 ; j
+ 1 < count
; j
+= nr
- 1 ) {
951 nr
= MIN2( currentsz
, count
- j
+ 1 );
952 TAG(emit_elts
)( ctx
, elts
+start
, 1 );
953 TAG(emit_elts
)( ctx
, elts
+j
, nr
- 1 );
958 ELT_FALLBACK( ctx
, start
, count
, flags
);
962 static void TAG(render_quad_strip_elts
)( GLcontext
*ctx
,
967 if (HAVE_QUAD_STRIPS
&& 0) {
969 else if (HAVE_TRI_STRIPS
) {
971 GLuint
*elts
= TNL_CONTEXT(ctx
)->vb
.Elts
;
972 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS();
977 currentsz
= GET_CURRENT_VB_MAX_ELTS();
979 /* Emit whole number of quads in total, and in each buffer.
982 count
-= (count
-start
) & 1;
983 currentsz
-= currentsz
& 1;
988 if (ctx
->_TriangleCaps
& DD_FLATSHADE
) {
989 ELT_INIT( GL_TRIANGLES
);
991 currentsz
= currentsz
/6*2;
994 for (j
= start
; j
+ 3 < count
; j
+= nr
- 2 ) {
995 nr
= MIN2( currentsz
, count
- j
);
1000 GLint quads
= (nr
/2)-1;
1005 ALLOC_ELTS_NEW_PRIMITIVE( quads
*6 );
1007 for ( i
= j
-start
; i
< j
-start
+quads
; i
++, elts
+= 2 ) {
1008 EMIT_TWO_ELTS( 0, elts
[0], elts
[1] );
1009 EMIT_TWO_ELTS( 2, elts
[2], elts
[1] );
1010 EMIT_TWO_ELTS( 4, elts
[3], elts
[2] );
1021 ELT_INIT( GL_TRIANGLE_STRIP
);
1023 for (j
= start
; j
+ 3 < count
; j
+= nr
- 2 ) {
1024 nr
= MIN2( currentsz
, count
- j
);
1025 TAG(emit_elts
)( ctx
, elts
+j
, nr
);
1034 static void TAG(render_quads_elts
)( GLcontext
*ctx
,
1039 if (HAVE_QUADS
&& 0) {
1042 GLuint
*elts
= TNL_CONTEXT(ctx
)->vb
.Elts
;
1043 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS();
1047 ELT_INIT( GL_TRIANGLES
);
1048 currentsz
= GET_CURRENT_VB_MAX_ELTS();
1050 /* Emit whole number of quads in total, and in each buffer.
1053 count
-= (count
-start
) & 3;
1054 currentsz
-= currentsz
& 3;
1056 /* Adjust for rendering as triangles:
1058 currentsz
= currentsz
/6*4;
1064 for (j
= start
; j
+ 3 < count
; j
+= nr
- 2 ) {
1065 nr
= MIN2( currentsz
, count
- j
);
1073 ALLOC_ELTS_NEW_PRIMITIVE( quads
* 6 );
1075 for ( i
= j
-start
; i
< j
-start
+quads
; i
++, elts
+= 4 ) {
1076 EMIT_TWO_ELTS( 0, elts
[0], elts
[1] );
1077 EMIT_TWO_ELTS( 2, elts
[3], elts
[1] );
1078 EMIT_TWO_ELTS( 4, elts
[2], elts
[3] );
1091 static render_func
TAG(render_tab_elts
)[GL_POLYGON
+2] =
1093 TAG(render_points_elts
),
1094 TAG(render_lines_elts
),
1095 TAG(render_line_loop_elts
),
1096 TAG(render_line_strip_elts
),
1097 TAG(render_triangles_elts
),
1098 TAG(render_tri_strip_elts
),
1099 TAG(render_tri_fan_elts
),
1100 TAG(render_quads_elts
),
1101 TAG(render_quad_strip_elts
),
1102 TAG(render_poly_elts
),