2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2004 Brian Paul All Rights Reserved.
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 * Keith Whitwell <keith@tungstengraphics.com>
29 /* Template for render stages which build and emit vertices directly
30 * to fixed-size dma buffers. Useful for rendering strips and other
31 * native primitives where clipping and per-vertex tweaks such as
32 * those in t_dd_tritmp.h are not required.
34 * Produces code for both inline triangles and indexed triangles.
35 * Where various primitive types are unaccelerated by hardware, the
36 * code attempts to fallback to other primitive types (quadstrips to
37 * tristrips, lineloops to linestrips), or to indexed vertices.
38 * Ultimately, a FALLBACK() macro is invoked if there is no way to
39 * render the primitive natively.
42 #if !defined(HAVE_TRIANGLES)
43 #error "must have at least triangles to use render template"
47 #define ELTS_VARS(buf)
48 #define ALLOC_ELTS(nr) 0
49 #define EMIT_ELT( offset, elt )
50 #define EMIT_TWO_ELTS( offset, elt0, elt1 )
51 #define INCR_ELTS( nr )
52 #define ELT_INIT(prim)
53 #define GET_CURRENT_VB_MAX_ELTS() 0
54 #define GET_SUBSEQUENT_VB_MAX_ELTS() 0
55 #define RELEASE_ELT_VERTS()
56 #define EMIT_INDEXED_VERTS( ctx, start, count )
60 #define EMIT_TWO_ELTS( offset, elt0, elt1 ) \
62 EMIT_ELT( offset, elt0 ); \
63 EMIT_ELT( offset+1, elt1 ); \
68 /**********************************************************************/
69 /* Render whole begin/end objects */
70 /**********************************************************************/
76 static void *TAG(emit_elts
)( GLcontext
*ctx
, GLuint
*elts
, GLuint nr
,
83 for ( i
= 0 ; i
+1 < nr
; i
+=2, elts
+= 2 ) {
84 EMIT_TWO_ELTS( 0, elts
[0], elts
[1] );
89 EMIT_ELT( 0, elts
[0] );
93 return (void *)ELTPTR
;
97 static __inline
void *TAG(emit_verts
)( GLcontext
*ctx
, GLuint start
,
98 GLuint count
, void *buf
)
100 return EMIT_VERTS(ctx
, start
, count
, buf
);
103 /***********************************************************************
104 * Render non-indexed primitives.
105 ***********************************************************************/
107 static void TAG(render_points_verts
)( GLcontext
*ctx
,
114 int dmasz
= GET_SUBSEQUENT_VB_MAX_VERTS();
120 currentsz
= GET_CURRENT_VB_MAX_VERTS();
124 for (j
= start
; j
< count
; j
+= nr
) {
125 nr
= MIN2( currentsz
, count
- j
);
126 TAG(emit_verts
)( ctx
, j
, nr
, ALLOC_VERTS(nr
) );
131 fprintf(stderr
, "%s - cannot draw primitive\n", __FUNCTION__
);
136 static void TAG(render_lines_verts
)( GLcontext
*ctx
,
143 int dmasz
= GET_SUBSEQUENT_VB_MAX_VERTS();
149 /* Emit whole number of lines in total and in each buffer:
151 count
-= (count
-start
) & 1;
152 currentsz
= GET_CURRENT_VB_MAX_VERTS();
153 currentsz
-= currentsz
& 1;
159 for (j
= start
; j
< count
; j
+= nr
) {
160 nr
= MIN2( currentsz
, count
- j
);
161 TAG(emit_verts
)( ctx
, j
, nr
, ALLOC_VERTS(nr
) );
166 fprintf(stderr
, "%s - cannot draw primitive\n", __FUNCTION__
);
172 static void TAG(render_line_strip_verts
)( GLcontext
*ctx
,
177 if (HAVE_LINE_STRIPS
) {
179 int dmasz
= GET_SUBSEQUENT_VB_MAX_VERTS();
183 INIT( GL_LINE_STRIP
);
185 currentsz
= GET_CURRENT_VB_MAX_VERTS();
189 for (j
= start
; j
+ 1 < count
; j
+= nr
- 1 ) {
190 nr
= MIN2( currentsz
, count
- j
);
191 TAG(emit_verts
)( ctx
, j
, nr
, ALLOC_VERTS(nr
) );
198 fprintf(stderr
, "%s - cannot draw primitive\n", __FUNCTION__
);
204 static void TAG(render_line_loop_verts
)( GLcontext
*ctx
,
209 if (HAVE_LINE_STRIPS
) {
211 int dmasz
= GET_SUBSEQUENT_VB_MAX_VERTS();
215 INIT( GL_LINE_STRIP
);
217 if (flags
& PRIM_BEGIN
)
222 /* Ensure last vertex won't wrap buffers:
224 currentsz
= GET_CURRENT_VB_MAX_VERTS();
233 for ( ; j
+ 1 < count
; j
+= nr
- 1 ) {
234 nr
= MIN2( currentsz
, count
- j
);
236 if (j
+ nr
>= count
&&
241 tmp
= ALLOC_VERTS(nr
+1);
242 tmp
= TAG(emit_verts
)( ctx
, j
, nr
, tmp
);
243 tmp
= TAG(emit_verts
)( ctx
, start
, 1, tmp
);
246 TAG(emit_verts
)( ctx
, j
, nr
, ALLOC_VERTS(nr
) );
252 else if (start
+ 1 < count
&& (flags
& PRIM_END
)) {
254 tmp
= ALLOC_VERTS(2);
255 tmp
= TAG(emit_verts
)( ctx
, start
+1, 1, tmp
);
256 tmp
= TAG(emit_verts
)( ctx
, start
, 1, tmp
);
262 fprintf(stderr
, "%s - cannot draw primitive\n", __FUNCTION__
);
268 static void TAG(render_triangles_verts
)( GLcontext
*ctx
,
274 int dmasz
= (GET_SUBSEQUENT_VB_MAX_VERTS()/3) * 3;
280 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 TAG(emit_verts
)( ctx
, j
, nr
, ALLOC_VERTS(nr
) );
299 static void TAG(render_tri_strip_verts
)( GLcontext
*ctx
,
304 if (HAVE_TRI_STRIPS
) {
307 int dmasz
= GET_SUBSEQUENT_VB_MAX_VERTS();
310 INIT(GL_TRIANGLE_STRIP
);
312 currentsz
= GET_CURRENT_VB_MAX_VERTS();
318 /* From here on emit even numbers of tris when wrapping over buffers:
320 dmasz
-= (dmasz
& 1);
321 currentsz
-= (currentsz
& 1);
323 for (j
= start
; j
+ 2 < count
; j
+= nr
- 2 ) {
324 nr
= MIN2( currentsz
, count
- j
);
325 TAG(emit_verts
)( ctx
, j
, nr
, ALLOC_VERTS(nr
) );
332 fprintf(stderr
, "%s - cannot draw primitive\n", __FUNCTION__
);
337 static void TAG(render_tri_fan_verts
)( GLcontext
*ctx
,
345 int dmasz
= GET_SUBSEQUENT_VB_MAX_VERTS();
348 INIT(GL_TRIANGLE_FAN
);
350 currentsz
= GET_CURRENT_VB_MAX_VERTS();
355 for (j
= start
+ 1 ; j
+ 1 < count
; j
+= nr
- 2 ) {
357 nr
= MIN2( currentsz
, count
- j
+ 1 );
358 tmp
= ALLOC_VERTS( nr
);
359 tmp
= TAG(emit_verts
)( ctx
, start
, 1, tmp
);
360 tmp
= TAG(emit_verts
)( ctx
, j
, nr
- 1, tmp
);
367 /* Could write code to emit these as indexed vertices (for the
368 * g400, for instance).
370 fprintf(stderr
, "%s - cannot draw primitive\n", __FUNCTION__
);
376 static void TAG(render_poly_verts
)( GLcontext
*ctx
,
384 int dmasz
= GET_SUBSEQUENT_VB_MAX_VERTS();
389 currentsz
= GET_CURRENT_VB_MAX_VERTS();
394 for (j
= start
+ 1 ; j
+ 1 < count
; j
+= nr
- 2 ) {
396 nr
= MIN2( currentsz
, count
- j
+ 1 );
397 tmp
= ALLOC_VERTS( nr
);
398 tmp
= TAG(emit_verts
)( ctx
, start
, 1, tmp
);
399 tmp
= TAG(emit_verts
)( ctx
, j
, nr
- 1, tmp
);
405 else if (HAVE_TRI_FANS
&& !(ctx
->_TriangleCaps
& DD_FLATSHADE
)) {
406 TAG(render_tri_fan_verts
)( ctx
, start
, count
, flags
);
408 fprintf(stderr
, "%s - cannot draw primitive\n", __FUNCTION__
);
413 static void TAG(render_quad_strip_verts
)( GLcontext
*ctx
,
420 if (HAVE_QUAD_STRIPS
) {
423 int dmasz
= GET_SUBSEQUENT_VB_MAX_VERTS();
428 currentsz
= GET_CURRENT_VB_MAX_VERTS();
433 dmasz
-= (dmasz
& 2);
434 currentsz
-= (currentsz
& 2);
436 for (j
= start
; j
+ 3 < count
; j
+= nr
- 2 ) {
437 nr
= MIN2( currentsz
, count
- j
);
438 TAG(emit_verts
)( ctx
, j
, nr
, ALLOC_VERTS(nr
) );
444 } else if (HAVE_TRI_STRIPS
&& (ctx
->_TriangleCaps
& DD_FLATSHADE
)) {
447 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS();
451 EMIT_INDEXED_VERTS( ctx
, start
, count
);
453 /* Simulate flat-shaded quadstrips using indexed vertices:
455 ELT_INIT( GL_TRIANGLES
);
457 currentsz
= GET_CURRENT_VB_MAX_ELTS();
459 /* Emit whole number of quads in total, and in each buffer.
462 count
-= (count
-start
) & 1;
463 currentsz
-= currentsz
& 1;
468 currentsz
= currentsz
/6*2;
471 for (j
= start
; j
+ 3 < count
; j
+= nr
- 2 ) {
472 nr
= MIN2( currentsz
, count
- j
);
474 GLint quads
= (nr
/2)-1;
476 ELTS_VARS( ALLOC_ELTS( quads
*6 ) );
478 for ( i
= j
-start
; i
< j
-start
+quads
*2 ; i
+=2 ) {
479 EMIT_TWO_ELTS( 0, (i
+0), (i
+1) );
480 EMIT_TWO_ELTS( 2, (i
+2), (i
+1) );
481 EMIT_TWO_ELTS( 4, (i
+3), (i
+2) );
494 /* Vertices won't fit in a single buffer or elts not available,
497 fprintf(stderr
, "%s - cannot draw primitive\n", __FUNCTION__
);
501 else if (HAVE_TRI_STRIPS
) {
503 int dmasz
= GET_SUBSEQUENT_VB_MAX_VERTS();
506 /* Emit smooth-shaded quadstrips as tristrips:
509 INIT( GL_TRIANGLE_STRIP
);
511 /* Emit whole number of quads in total, and in each buffer.
514 currentsz
= GET_CURRENT_VB_MAX_VERTS();
515 currentsz
-= currentsz
& 1;
516 count
-= (count
-start
) & 1;
522 for (j
= start
; j
+ 3 < count
; j
+= nr
- 2 ) {
523 nr
= MIN2( currentsz
, count
- j
);
524 TAG(emit_verts
)( ctx
, j
, nr
, ALLOC_VERTS(nr
) );
531 fprintf(stderr
, "%s - cannot draw primitive\n", __FUNCTION__
);
537 static void TAG(render_quads_verts
)( GLcontext
*ctx
,
544 int dmasz
= (GET_SUBSEQUENT_VB_MAX_VERTS()/4) * 4;
550 /* Emit whole number of quads in total. dmasz is already a multiple
553 count
-= (count
-start
)%4;
555 currentsz
= (GET_CURRENT_VB_MAX_VERTS()/4) * 4;
559 for (j
= start
; j
< count
; j
+= nr
) {
560 nr
= MIN2( currentsz
, count
- j
);
561 TAG(emit_verts
)( ctx
, j
, nr
, ALLOC_VERTS(nr
) );
566 } else if (HAVE_ELTS
) {
567 /* Hardware doesn't have a quad primitive type -- try to
568 * simulate it using indexed vertices and the triangle
572 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS();
576 EMIT_INDEXED_VERTS( ctx
, start
, count
);
579 ELT_INIT( GL_TRIANGLES
);
580 currentsz
= GET_CURRENT_VB_MAX_ELTS();
582 /* Emit whole number of quads in total, and in each buffer.
585 count
-= (count
-start
) & 3;
586 currentsz
-= currentsz
& 3;
588 /* Adjust for rendering as triangles:
590 currentsz
= currentsz
/6*4;
596 for (j
= start
; j
< count
; j
+= nr
) {
597 nr
= MIN2( currentsz
, count
- j
);
601 ELTS_VARS( ALLOC_ELTS( quads
*6 ) );
603 for ( i
= j
-start
; i
< j
-start
+quads
*4 ; i
+=4 ) {
604 EMIT_TWO_ELTS( 0, (i
+0), (i
+1) );
605 EMIT_TWO_ELTS( 2, (i
+3), (i
+1) );
606 EMIT_TWO_ELTS( 4, (i
+2), (i
+3) );
618 /* Vertices won't fit in a single buffer, fallback.
620 fprintf(stderr
, "%s - cannot draw primitive\n", __FUNCTION__
);
625 static void TAG(render_noop
)( GLcontext
*ctx
,
635 static tnl_render_func
TAG(render_tab_verts
)[GL_POLYGON
+2] =
637 TAG(render_points_verts
),
638 TAG(render_lines_verts
),
639 TAG(render_line_loop_verts
),
640 TAG(render_line_strip_verts
),
641 TAG(render_triangles_verts
),
642 TAG(render_tri_strip_verts
),
643 TAG(render_tri_fan_verts
),
644 TAG(render_quads_verts
),
645 TAG(render_quad_strip_verts
),
646 TAG(render_poly_verts
),
651 /****************************************************************************
652 * Render elts using hardware indexed verts *
653 ****************************************************************************/
656 static void TAG(render_points_elts
)( GLcontext
*ctx
,
663 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS();
665 GLuint
*elts
= TNL_CONTEXT(ctx
)->vb
.Elts
;
668 ELT_INIT( GL_POINTS
);
670 currentsz
= GET_CURRENT_VB_MAX_ELTS();
674 for (j
= start
; j
< count
; j
+= nr
) {
675 nr
= MIN2( currentsz
, count
- j
);
676 TAG(emit_elts
)( ctx
, elts
+j
, nr
, ALLOC_ELTS(nr
) );
681 fprintf(stderr
, "%s - cannot draw primitive\n", __FUNCTION__
);
688 static void TAG(render_lines_elts
)( GLcontext
*ctx
,
695 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS();
697 GLuint
*elts
= TNL_CONTEXT(ctx
)->vb
.Elts
;
700 ELT_INIT( GL_LINES
);
702 /* Emit whole number of lines in total and in each buffer:
704 count
-= (count
-start
) & 1;
705 currentsz
-= currentsz
& 1;
708 currentsz
= GET_CURRENT_VB_MAX_ELTS();
712 for (j
= start
; j
< count
; j
+= nr
) {
713 nr
= MIN2( currentsz
, count
- j
);
714 TAG(emit_elts
)( ctx
, elts
+j
, nr
, ALLOC_ELTS(nr
) );
719 fprintf(stderr
, "%s - cannot draw primitive\n", __FUNCTION__
);
725 static void TAG(render_line_strip_elts
)( GLcontext
*ctx
,
730 if (HAVE_LINE_STRIPS
) {
732 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS();
734 GLuint
*elts
= TNL_CONTEXT(ctx
)->vb
.Elts
;
737 FLUSH(); /* always a new primitive */
738 ELT_INIT( GL_LINE_STRIP
);
740 currentsz
= GET_CURRENT_VB_MAX_ELTS();
744 for (j
= start
; j
+ 1 < count
; j
+= nr
- 1 ) {
745 nr
= MIN2( currentsz
, count
- j
);
746 TAG(emit_elts
)( ctx
, elts
+j
, nr
, ALLOC_ELTS(nr
) );
751 /* TODO: Try to emit as indexed lines.
753 fprintf(stderr
, "%s - cannot draw primitive\n", __FUNCTION__
);
759 static void TAG(render_line_loop_elts
)( GLcontext
*ctx
,
764 if (HAVE_LINE_STRIPS
) {
766 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS();
768 GLuint
*elts
= TNL_CONTEXT(ctx
)->vb
.Elts
;
772 ELT_INIT( GL_LINE_STRIP
);
774 if (flags
& PRIM_BEGIN
)
779 currentsz
= GET_CURRENT_VB_MAX_ELTS();
784 /* Ensure last vertex doesn't wrap:
790 for ( ; j
+ 1 < count
; j
+= nr
- 1 ) {
791 nr
= MIN2( currentsz
, count
- j
);
793 if (j
+ nr
>= count
&&
798 tmp
= ALLOC_ELTS(nr
+1);
799 tmp
= TAG(emit_elts
)( ctx
, elts
+j
, nr
, tmp
);
800 tmp
= TAG(emit_elts
)( ctx
, elts
+start
, 1, tmp
);
803 TAG(emit_elts
)( ctx
, elts
+j
, nr
, ALLOC_ELTS(nr
) );
809 else if (start
+ 1 < count
&& (flags
& PRIM_END
)) {
812 tmp
= TAG(emit_elts
)( ctx
, elts
+start
+1, 1, tmp
);
813 tmp
= TAG(emit_elts
)( ctx
, elts
+start
, 1, tmp
);
818 /* TODO: Try to emit as indexed lines */
819 fprintf(stderr
, "%s - cannot draw primitive\n", __FUNCTION__
);
825 /* For verts, we still eliminate the copy from main memory to dma
826 * buffers. For elts, this is probably no better (worse?) than the
829 static void TAG(render_triangles_elts
)( GLcontext
*ctx
,
835 GLuint
*elts
= TNL_CONTEXT(ctx
)->vb
.Elts
;
836 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS()/3*3;
841 ELT_INIT( GL_TRIANGLES
);
843 currentsz
= GET_CURRENT_VB_MAX_ELTS();
845 /* Emit whole number of tris in total. dmasz is already a multiple
848 count
-= (count
-start
)%3;
849 currentsz
-= currentsz
%3;
853 for (j
= start
; j
< count
; j
+= nr
) {
854 nr
= MIN2( currentsz
, count
- j
);
855 TAG(emit_elts
)( ctx
, elts
+j
, nr
, ALLOC_ELTS(nr
) );
863 static void TAG(render_tri_strip_elts
)( GLcontext
*ctx
,
868 if (HAVE_TRI_STRIPS
) {
871 GLuint
*elts
= TNL_CONTEXT(ctx
)->vb
.Elts
;
872 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS();
876 ELT_INIT( GL_TRIANGLE_STRIP
);
878 currentsz
= GET_CURRENT_VB_MAX_ELTS();
883 /* Keep the same winding over multiple buffers:
885 dmasz
-= (dmasz
& 1);
886 currentsz
-= (currentsz
& 1);
888 for (j
= start
; j
+ 2 < count
; j
+= nr
- 2 ) {
889 nr
= MIN2( currentsz
, count
- j
);
890 TAG(emit_elts
)( ctx
, elts
+j
, nr
, ALLOC_ELTS(nr
) );
895 /* TODO: try to emit as indexed triangles */
896 fprintf(stderr
, "%s - cannot draw primitive\n", __FUNCTION__
);
901 static void TAG(render_tri_fan_elts
)( GLcontext
*ctx
,
908 GLuint
*elts
= TNL_CONTEXT(ctx
)->vb
.Elts
;
910 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS();
914 ELT_INIT( GL_TRIANGLE_FAN
);
916 currentsz
= GET_CURRENT_VB_MAX_ELTS();
921 for (j
= start
+ 1 ; j
+ 1 < count
; j
+= nr
- 2 ) {
923 nr
= MIN2( currentsz
, count
- j
+ 1 );
924 tmp
= ALLOC_ELTS( nr
);
925 tmp
= TAG(emit_elts
)( ctx
, elts
+start
, 1, tmp
);
926 tmp
= TAG(emit_elts
)( ctx
, elts
+j
, nr
- 1, tmp
);
931 /* TODO: try to emit as indexed triangles */
932 fprintf(stderr
, "%s - cannot draw primitive\n", __FUNCTION__
);
938 static void TAG(render_poly_elts
)( GLcontext
*ctx
,
945 GLuint
*elts
= TNL_CONTEXT(ctx
)->vb
.Elts
;
947 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS();
951 ELT_INIT( GL_POLYGON
);
953 currentsz
= GET_CURRENT_VB_MAX_ELTS();
958 for (j
= start
+ 1 ; j
+ 1 < count
; j
+= nr
- 2 ) {
960 nr
= MIN2( currentsz
, count
- j
+ 1 );
961 tmp
= ALLOC_ELTS( nr
);
962 tmp
= TAG(emit_elts
)( ctx
, elts
+start
, 1, tmp
);
963 tmp
= TAG(emit_elts
)( ctx
, elts
+j
, nr
- 1, tmp
);
967 } else if (HAVE_TRI_FANS
&& !(ctx
->_TriangleCaps
& DD_FLATSHADE
)) {
968 TAG(render_tri_fan_verts
)( ctx
, start
, count
, flags
);
970 fprintf(stderr
, "%s - cannot draw primitive\n", __FUNCTION__
);
975 static void TAG(render_quad_strip_elts
)( GLcontext
*ctx
,
980 if (HAVE_QUAD_STRIPS
&& 0) {
982 else if (HAVE_TRI_STRIPS
) {
984 GLuint
*elts
= TNL_CONTEXT(ctx
)->vb
.Elts
;
985 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS();
990 currentsz
= GET_CURRENT_VB_MAX_ELTS();
992 /* Emit whole number of quads in total, and in each buffer.
995 count
-= (count
-start
) & 1;
996 currentsz
-= currentsz
& 1;
1001 if (ctx
->_TriangleCaps
& DD_FLATSHADE
) {
1002 ELT_INIT( GL_TRIANGLES
);
1004 currentsz
= currentsz
/6*2;
1007 for (j
= start
; j
+ 3 < count
; j
+= nr
- 2 ) {
1008 nr
= MIN2( currentsz
, count
- j
);
1013 GLint quads
= (nr
/2)-1;
1014 void *buf
= ALLOC_ELTS( quads
*6 );
1017 for ( i
= j
-start
; i
< j
-start
+quads
; i
++, elts
+= 2 ) {
1018 EMIT_TWO_ELTS( 0, elts
[0], elts
[1] );
1019 EMIT_TWO_ELTS( 2, elts
[2], elts
[1] );
1020 EMIT_TWO_ELTS( 4, elts
[3], elts
[2] );
1031 ELT_INIT( GL_TRIANGLE_STRIP
);
1033 for (j
= start
; j
+ 3 < count
; j
+= nr
- 2 ) {
1034 nr
= MIN2( currentsz
, count
- j
);
1035 TAG(emit_elts
)( ctx
, elts
+j
, nr
, ALLOC_ELTS(nr
) );
1044 static void TAG(render_quads_elts
)( GLcontext
*ctx
,
1051 GLuint
*elts
= TNL_CONTEXT(ctx
)->vb
.Elts
;
1052 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS()/4*4;
1057 ELT_INIT( GL_TRIANGLES
);
1059 currentsz
= GET_CURRENT_VB_MAX_ELTS()/4*4;
1061 count
-= (count
-start
)%4;
1066 for (j
= start
; j
< count
; j
+= nr
) {
1067 nr
= MIN2( currentsz
, count
- j
);
1068 TAG(emit_elts
)( ctx
, elts
+j
, nr
, ALLOC_ELTS(nr
) );
1074 GLuint
*elts
= TNL_CONTEXT(ctx
)->vb
.Elts
;
1075 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS();
1079 ELT_INIT( GL_TRIANGLES
);
1080 currentsz
= GET_CURRENT_VB_MAX_ELTS();
1082 /* Emit whole number of quads in total, and in each buffer.
1085 count
-= (count
-start
) & 3;
1086 currentsz
-= currentsz
& 3;
1088 /* Adjust for rendering as triangles:
1090 currentsz
= currentsz
/6*4;
1096 for (j
= start
; j
+ 3 < count
; j
+= nr
- 2 ) {
1097 nr
= MIN2( currentsz
, count
- j
);
1103 void *buf
= ALLOC_ELTS( quads
* 6 );
1106 for ( i
= j
-start
; i
< j
-start
+quads
; i
++, elts
+= 4 ) {
1107 EMIT_TWO_ELTS( 0, elts
[0], elts
[1] );
1108 EMIT_TWO_ELTS( 2, elts
[3], elts
[1] );
1109 EMIT_TWO_ELTS( 4, elts
[2], elts
[3] );
1123 static tnl_render_func
TAG(render_tab_elts
)[GL_POLYGON
+2] =
1125 TAG(render_points_elts
),
1126 TAG(render_lines_elts
),
1127 TAG(render_line_loop_elts
),
1128 TAG(render_line_strip_elts
),
1129 TAG(render_triangles_elts
),
1130 TAG(render_tri_strip_elts
),
1131 TAG(render_tri_fan_elts
),
1132 TAG(render_quads_elts
),
1133 TAG(render_quad_strip_elts
),
1134 TAG(render_poly_elts
),
1147 /* Prevent fallbacks later on.
1149 static GLboolean
TAG(validate_render
)( GLcontext
*ctx
,
1150 struct vertex_buffer
*VB
)
1154 if (VB
->ClipOrMask
& ~CLIP_CULL_BIT
)
1157 if (VB
->Elts
&& !HAVE_ELTS
)
1160 for (i
= 0 ; i
< VB
->PrimitiveCount
; i
++) {
1161 GLuint prim
= VB
->Primitive
[i
].mode
;
1162 GLuint count
= VB
->Primitive
[i
].count
;
1163 GLboolean ok
= GL_FALSE
;
1168 switch (prim
& PRIM_MODE_MASK
) {
1173 ok
= HAVE_LINES
&& !ctx
->Line
.StippleFlag
;
1176 ok
= HAVE_LINE_STRIPS
&& !ctx
->Line
.StippleFlag
;
1179 ok
= HAVE_LINE_STRIPS
&& !ctx
->Line
.StippleFlag
;
1182 ok
= HAVE_TRIANGLES
;
1184 case GL_TRIANGLE_STRIP
:
1185 ok
= HAVE_TRI_STRIPS
;
1187 case GL_TRIANGLE_FAN
:
1191 if (HAVE_POLYGONS
) {
1195 ok
= (HAVE_TRI_FANS
&& !(ctx
->_TriangleCaps
& DD_FLATSHADE
));
1199 ok
= HAVE_TRI_STRIPS
;
1201 else if (HAVE_QUAD_STRIPS
) {
1203 } else if (HAVE_TRI_STRIPS
&& (ctx
->_TriangleCaps
& DD_FLATSHADE
)) {
1205 ok
= (GLint
) count
< GET_SUBSEQUENT_VB_MAX_ELTS();
1212 ok
= HAVE_TRI_STRIPS
;
1217 } else if (HAVE_ELTS
) {
1218 ok
= (GLint
) count
< GET_SUBSEQUENT_VB_MAX_ELTS();
1228 if (!ok
) return GL_FALSE
;