2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2006 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>
31 * Template for render stages which build and emit vertices directly
32 * to fixed-size dma buffers. Useful for rendering strips and other
33 * native primitives where clipping and per-vertex tweaks such as
34 * those in t_dd_tritmp.h are not required.
36 * Produces code for both inline triangles and indexed triangles.
37 * Where various primitive types are unaccelerated by hardware, the
38 * code attempts to fallback to other primitive types (quadstrips to
39 * tristrips, lineloops to linestrips), or to indexed vertices.
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
);
247 TAG(emit_verts
)( ctx
, j
, nr
, ALLOC_VERTS(nr
) );
253 else if (start
+ 1 < count
&& (flags
& PRIM_END
)) {
255 tmp
= ALLOC_VERTS(2);
256 tmp
= TAG(emit_verts
)( ctx
, start
+1, 1, tmp
);
257 tmp
= TAG(emit_verts
)( ctx
, start
, 1, tmp
);
264 fprintf(stderr
, "%s - cannot draw primitive\n", __FUNCTION__
);
270 static void TAG(render_triangles_verts
)( GLcontext
*ctx
,
276 int dmasz
= (GET_SUBSEQUENT_VB_MAX_VERTS()/3) * 3;
282 currentsz
= (GET_CURRENT_VB_MAX_VERTS()/3) * 3;
284 /* Emit whole number of tris in total. dmasz is already a multiple
287 count
-= (count
-start
)%3;
292 for (j
= start
; j
< count
; j
+= nr
) {
293 nr
= MIN2( currentsz
, count
- j
);
294 TAG(emit_verts
)( ctx
, j
, nr
, ALLOC_VERTS(nr
) );
301 static void TAG(render_tri_strip_verts
)( GLcontext
*ctx
,
306 if (HAVE_TRI_STRIPS
) {
309 int dmasz
= GET_SUBSEQUENT_VB_MAX_VERTS();
312 INIT(GL_TRIANGLE_STRIP
);
314 currentsz
= GET_CURRENT_VB_MAX_VERTS();
320 /* From here on emit even numbers of tris when wrapping over buffers:
322 dmasz
-= (dmasz
& 1);
323 currentsz
-= (currentsz
& 1);
325 for (j
= start
; j
+ 2 < count
; j
+= nr
- 2 ) {
326 nr
= MIN2( currentsz
, count
- j
);
327 TAG(emit_verts
)( ctx
, j
, nr
, ALLOC_VERTS(nr
) );
334 fprintf(stderr
, "%s - cannot draw primitive\n", __FUNCTION__
);
339 static void TAG(render_tri_fan_verts
)( GLcontext
*ctx
,
347 int dmasz
= GET_SUBSEQUENT_VB_MAX_VERTS();
350 INIT(GL_TRIANGLE_FAN
);
352 currentsz
= GET_CURRENT_VB_MAX_VERTS();
357 for (j
= start
+ 1 ; j
+ 1 < count
; j
+= nr
- 2 ) {
359 nr
= MIN2( currentsz
, count
- j
+ 1 );
360 tmp
= ALLOC_VERTS( nr
);
361 tmp
= TAG(emit_verts
)( ctx
, start
, 1, tmp
);
362 tmp
= TAG(emit_verts
)( ctx
, j
, nr
- 1, tmp
);
370 /* Could write code to emit these as indexed vertices (for the
371 * g400, for instance).
373 fprintf(stderr
, "%s - cannot draw primitive\n", __FUNCTION__
);
379 static void TAG(render_poly_verts
)( GLcontext
*ctx
,
387 int dmasz
= GET_SUBSEQUENT_VB_MAX_VERTS();
392 currentsz
= GET_CURRENT_VB_MAX_VERTS();
397 for (j
= start
+ 1 ; j
+ 1 < count
; j
+= nr
- 2 ) {
399 nr
= MIN2( currentsz
, count
- j
+ 1 );
400 tmp
= ALLOC_VERTS( nr
);
401 tmp
= TAG(emit_verts
)( ctx
, start
, 1, tmp
);
402 tmp
= TAG(emit_verts
)( ctx
, j
, nr
- 1, tmp
);
409 else if (HAVE_TRI_FANS
&& ctx
->Light
.ShadeModel
== GL_SMOOTH
) {
410 TAG(render_tri_fan_verts
)( ctx
, start
, count
, flags
);
412 fprintf(stderr
, "%s - cannot draw primitive\n", __FUNCTION__
);
417 static void TAG(render_quad_strip_verts
)( GLcontext
*ctx
,
424 if (HAVE_QUAD_STRIPS
) {
427 int dmasz
= GET_SUBSEQUENT_VB_MAX_VERTS();
432 currentsz
= GET_CURRENT_VB_MAX_VERTS();
437 dmasz
-= (dmasz
& 2);
438 currentsz
-= (currentsz
& 2);
440 for (j
= start
; j
+ 3 < count
; j
+= nr
- 2 ) {
441 nr
= MIN2( currentsz
, count
- j
);
442 TAG(emit_verts
)( ctx
, j
, nr
, ALLOC_VERTS(nr
) );
448 } else if (HAVE_TRI_STRIPS
&&
449 ctx
->Light
.ShadeModel
== GL_FLAT
&&
450 TNL_CONTEXT(ctx
)->vb
.AttribPtr
[_TNL_ATTRIB_COLOR0
]->stride
) {
453 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS();
457 EMIT_INDEXED_VERTS( ctx
, start
, count
);
459 /* Simulate flat-shaded quadstrips using indexed vertices:
461 ELT_INIT( GL_TRIANGLES
);
463 currentsz
= GET_CURRENT_VB_MAX_ELTS();
465 /* Emit whole number of quads in total, and in each buffer.
468 count
-= (count
-start
) & 1;
469 currentsz
-= currentsz
& 1;
474 currentsz
= currentsz
/6*2;
477 for (j
= start
; j
+ 3 < count
; j
+= nr
- 2 ) {
478 nr
= MIN2( currentsz
, count
- j
);
480 GLint quads
= (nr
/2)-1;
482 ELTS_VARS( ALLOC_ELTS( quads
*6 ) );
484 for ( i
= j
-start
; i
< j
-start
+quads
*2 ; i
+=2 ) {
485 EMIT_TWO_ELTS( 0, (i
+0), (i
+1) );
486 EMIT_TWO_ELTS( 2, (i
+2), (i
+1) );
487 EMIT_TWO_ELTS( 4, (i
+3), (i
+2) );
500 /* Vertices won't fit in a single buffer or elts not
501 * available - should never happen.
503 fprintf(stderr
, "%s - cannot draw primitive\n", __FUNCTION__
);
507 else if (HAVE_TRI_STRIPS
) {
509 int dmasz
= GET_SUBSEQUENT_VB_MAX_VERTS();
512 /* Emit smooth-shaded quadstrips as tristrips:
515 INIT( GL_TRIANGLE_STRIP
);
517 /* Emit whole number of quads in total, and in each buffer.
520 currentsz
= GET_CURRENT_VB_MAX_VERTS();
521 currentsz
-= currentsz
& 1;
522 count
-= (count
-start
) & 1;
528 for (j
= start
; j
+ 3 < count
; j
+= nr
- 2 ) {
529 nr
= MIN2( currentsz
, count
- j
);
530 TAG(emit_verts
)( ctx
, j
, nr
, ALLOC_VERTS(nr
) );
537 fprintf(stderr
, "%s - cannot draw primitive\n", __FUNCTION__
);
543 static void TAG(render_quads_verts
)( GLcontext
*ctx
,
550 int dmasz
= (GET_SUBSEQUENT_VB_MAX_VERTS()/4) * 4;
556 /* Emit whole number of quads in total. dmasz is already a multiple
559 count
-= (count
-start
)%4;
561 currentsz
= (GET_CURRENT_VB_MAX_VERTS()/4) * 4;
565 for (j
= start
; j
< count
; j
+= nr
) {
566 nr
= MIN2( currentsz
, count
- j
);
567 TAG(emit_verts
)( ctx
, j
, nr
, ALLOC_VERTS(nr
) );
571 else if (HAVE_ELTS
) {
572 /* Hardware doesn't have a quad primitive type -- try to
573 * simulate it using indexed vertices and the triangle
577 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS();
581 EMIT_INDEXED_VERTS( ctx
, start
, count
);
584 ELT_INIT( GL_TRIANGLES
);
585 currentsz
= GET_CURRENT_VB_MAX_ELTS();
587 /* Emit whole number of quads in total, and in each buffer.
590 count
-= (count
-start
) & 3;
591 currentsz
-= currentsz
& 3;
593 /* Adjust for rendering as triangles:
595 currentsz
= currentsz
/6*4;
601 for (j
= start
; j
< count
; j
+= nr
) {
602 nr
= MIN2( currentsz
, count
- j
);
606 ELTS_VARS( ALLOC_ELTS( quads
*6 ) );
608 for ( i
= j
-start
; i
< j
-start
+quads
*4 ; i
+=4 ) {
609 EMIT_TWO_ELTS( 0, (i
+0), (i
+1) );
610 EMIT_TWO_ELTS( 2, (i
+3), (i
+1) );
611 EMIT_TWO_ELTS( 4, (i
+2), (i
+3) );
622 else if (HAVE_TRIANGLES
) {
623 /* Hardware doesn't have a quad primitive type -- try to
624 * simulate it using triangle primitive. This is a win for
625 * gears, but is it useful in the broader world?
632 for (j
= start
; j
< count
-3; j
+= 4) {
633 void *tmp
= ALLOC_VERTS( 6 );
636 tmp
= EMIT_VERTS(ctx
, j
, 2, tmp
);
637 tmp
= EMIT_VERTS(ctx
, j
+ 3, 1, tmp
);
640 tmp
= EMIT_VERTS(ctx
, j
+ 1, 3, tmp
);
645 /* Vertices won't fit in a single buffer, should never happen.
647 fprintf(stderr
, "%s - cannot draw primitive\n", __FUNCTION__
);
652 static void TAG(render_noop
)( GLcontext
*ctx
,
662 static tnl_render_func
TAG(render_tab_verts
)[GL_POLYGON
+2] =
664 TAG(render_points_verts
),
665 TAG(render_lines_verts
),
666 TAG(render_line_loop_verts
),
667 TAG(render_line_strip_verts
),
668 TAG(render_triangles_verts
),
669 TAG(render_tri_strip_verts
),
670 TAG(render_tri_fan_verts
),
671 TAG(render_quads_verts
),
672 TAG(render_quad_strip_verts
),
673 TAG(render_poly_verts
),
678 /****************************************************************************
679 * Render elts using hardware indexed verts *
680 ****************************************************************************/
683 static void TAG(render_points_elts
)( GLcontext
*ctx
,
690 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS();
692 GLuint
*elts
= TNL_CONTEXT(ctx
)->vb
.Elts
;
695 ELT_INIT( GL_POINTS
);
697 currentsz
= GET_CURRENT_VB_MAX_ELTS();
701 for (j
= start
; j
< count
; j
+= nr
) {
702 nr
= MIN2( currentsz
, count
- j
);
703 TAG(emit_elts
)( ctx
, elts
+j
, nr
, ALLOC_ELTS(nr
) );
708 fprintf(stderr
, "%s - cannot draw primitive\n", __FUNCTION__
);
715 static void TAG(render_lines_elts
)( GLcontext
*ctx
,
722 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS();
724 GLuint
*elts
= TNL_CONTEXT(ctx
)->vb
.Elts
;
727 ELT_INIT( GL_LINES
);
729 /* Emit whole number of lines in total and in each buffer:
731 count
-= (count
-start
) & 1;
732 currentsz
-= currentsz
& 1;
735 currentsz
= GET_CURRENT_VB_MAX_ELTS();
739 for (j
= start
; j
< count
; j
+= nr
) {
740 nr
= MIN2( currentsz
, count
- j
);
741 TAG(emit_elts
)( ctx
, elts
+j
, nr
, ALLOC_ELTS(nr
) );
746 fprintf(stderr
, "%s - cannot draw primitive\n", __FUNCTION__
);
752 static void TAG(render_line_strip_elts
)( GLcontext
*ctx
,
757 if (HAVE_LINE_STRIPS
) {
759 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS();
761 GLuint
*elts
= TNL_CONTEXT(ctx
)->vb
.Elts
;
764 FLUSH(); /* always a new primitive */
765 ELT_INIT( GL_LINE_STRIP
);
767 currentsz
= GET_CURRENT_VB_MAX_ELTS();
771 for (j
= start
; j
+ 1 < count
; j
+= nr
- 1 ) {
772 nr
= MIN2( currentsz
, count
- j
);
773 TAG(emit_elts
)( ctx
, elts
+j
, nr
, ALLOC_ELTS(nr
) );
778 /* TODO: Try to emit as indexed lines.
780 fprintf(stderr
, "%s - cannot draw primitive\n", __FUNCTION__
);
786 static void TAG(render_line_loop_elts
)( GLcontext
*ctx
,
791 if (HAVE_LINE_STRIPS
) {
793 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS();
795 GLuint
*elts
= TNL_CONTEXT(ctx
)->vb
.Elts
;
799 ELT_INIT( GL_LINE_STRIP
);
801 if (flags
& PRIM_BEGIN
)
806 currentsz
= GET_CURRENT_VB_MAX_ELTS();
811 /* Ensure last vertex doesn't wrap:
817 for ( ; j
+ 1 < count
; j
+= nr
- 1 ) {
818 nr
= MIN2( currentsz
, count
- j
);
820 if (j
+ nr
>= count
&&
825 tmp
= ALLOC_ELTS(nr
+1);
826 tmp
= TAG(emit_elts
)( ctx
, elts
+j
, nr
, tmp
);
827 tmp
= TAG(emit_elts
)( ctx
, elts
+start
, 1, tmp
);
831 TAG(emit_elts
)( ctx
, elts
+j
, nr
, ALLOC_ELTS(nr
) );
837 else if (start
+ 1 < count
&& (flags
& PRIM_END
)) {
840 tmp
= TAG(emit_elts
)( ctx
, elts
+start
+1, 1, tmp
);
841 tmp
= TAG(emit_elts
)( ctx
, elts
+start
, 1, tmp
);
847 /* TODO: Try to emit as indexed lines */
848 fprintf(stderr
, "%s - cannot draw primitive\n", __FUNCTION__
);
854 /* For verts, we still eliminate the copy from main memory to dma
855 * buffers. For elts, this is probably no better (worse?) than the
858 static void TAG(render_triangles_elts
)( GLcontext
*ctx
,
864 GLuint
*elts
= TNL_CONTEXT(ctx
)->vb
.Elts
;
865 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS()/3*3;
870 ELT_INIT( GL_TRIANGLES
);
872 currentsz
= GET_CURRENT_VB_MAX_ELTS();
874 /* Emit whole number of tris in total. dmasz is already a multiple
877 count
-= (count
-start
)%3;
878 currentsz
-= currentsz
%3;
882 for (j
= start
; j
< count
; j
+= nr
) {
883 nr
= MIN2( currentsz
, count
- j
);
884 TAG(emit_elts
)( ctx
, elts
+j
, nr
, ALLOC_ELTS(nr
) );
892 static void TAG(render_tri_strip_elts
)( GLcontext
*ctx
,
897 if (HAVE_TRI_STRIPS
) {
900 GLuint
*elts
= TNL_CONTEXT(ctx
)->vb
.Elts
;
901 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS();
905 ELT_INIT( GL_TRIANGLE_STRIP
);
907 currentsz
= GET_CURRENT_VB_MAX_ELTS();
912 /* Keep the same winding over multiple buffers:
914 dmasz
-= (dmasz
& 1);
915 currentsz
-= (currentsz
& 1);
917 for (j
= start
; j
+ 2 < count
; j
+= nr
- 2 ) {
918 nr
= MIN2( currentsz
, count
- j
);
919 TAG(emit_elts
)( ctx
, elts
+j
, nr
, ALLOC_ELTS(nr
) );
924 /* TODO: try to emit as indexed triangles */
925 fprintf(stderr
, "%s - cannot draw primitive\n", __FUNCTION__
);
930 static void TAG(render_tri_fan_elts
)( GLcontext
*ctx
,
937 GLuint
*elts
= TNL_CONTEXT(ctx
)->vb
.Elts
;
939 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS();
943 ELT_INIT( GL_TRIANGLE_FAN
);
945 currentsz
= GET_CURRENT_VB_MAX_ELTS();
950 for (j
= start
+ 1 ; j
+ 1 < count
; j
+= nr
- 2 ) {
952 nr
= MIN2( currentsz
, count
- j
+ 1 );
953 tmp
= ALLOC_ELTS( nr
);
954 tmp
= TAG(emit_elts
)( ctx
, elts
+start
, 1, tmp
);
955 tmp
= TAG(emit_elts
)( ctx
, elts
+j
, nr
- 1, tmp
);
961 /* TODO: try to emit as indexed triangles */
962 fprintf(stderr
, "%s - cannot draw primitive\n", __FUNCTION__
);
968 static void TAG(render_poly_elts
)( GLcontext
*ctx
,
975 GLuint
*elts
= TNL_CONTEXT(ctx
)->vb
.Elts
;
977 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS();
981 ELT_INIT( GL_POLYGON
);
983 currentsz
= GET_CURRENT_VB_MAX_ELTS();
988 for (j
= start
+ 1 ; j
+ 1 < count
; j
+= nr
- 2 ) {
990 nr
= MIN2( currentsz
, count
- j
+ 1 );
991 tmp
= ALLOC_ELTS( nr
);
992 tmp
= TAG(emit_elts
)( ctx
, elts
+start
, 1, tmp
);
993 tmp
= TAG(emit_elts
)( ctx
, elts
+j
, nr
- 1, tmp
);
998 } else if (HAVE_TRI_FANS
&& ctx
->Light
.ShadeModel
== GL_SMOOTH
) {
999 TAG(render_tri_fan_verts
)( ctx
, start
, count
, flags
);
1001 fprintf(stderr
, "%s - cannot draw primitive\n", __FUNCTION__
);
1006 static void TAG(render_quad_strip_elts
)( GLcontext
*ctx
,
1011 if (HAVE_QUAD_STRIPS
&& 0) {
1013 else if (HAVE_TRI_STRIPS
) {
1015 GLuint
*elts
= TNL_CONTEXT(ctx
)->vb
.Elts
;
1016 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS();
1021 currentsz
= GET_CURRENT_VB_MAX_ELTS();
1023 /* Emit whole number of quads in total, and in each buffer.
1026 count
-= (count
-start
) & 1;
1027 currentsz
-= currentsz
& 1;
1032 if (ctx
->Light
.ShadeModel
== GL_FLAT
) {
1033 ELT_INIT( GL_TRIANGLES
);
1035 currentsz
= currentsz
/6*2;
1038 for (j
= start
; j
+ 3 < count
; j
+= nr
- 2 ) {
1039 nr
= MIN2( currentsz
, count
- j
);
1044 GLint quads
= (nr
/2)-1;
1045 ELTS_VARS( ALLOC_ELTS( quads
*6 ) );
1047 for ( i
= j
-start
; i
< j
-start
+quads
; i
++, elts
+= 2 ) {
1048 EMIT_TWO_ELTS( 0, elts
[0], elts
[1] );
1049 EMIT_TWO_ELTS( 2, elts
[2], elts
[1] );
1050 EMIT_TWO_ELTS( 4, elts
[3], elts
[2] );
1061 ELT_INIT( GL_TRIANGLE_STRIP
);
1063 for (j
= start
; j
+ 3 < count
; j
+= nr
- 2 ) {
1064 nr
= MIN2( currentsz
, count
- j
);
1065 TAG(emit_elts
)( ctx
, elts
+j
, nr
, ALLOC_ELTS(nr
) );
1074 static void TAG(render_quads_elts
)( GLcontext
*ctx
,
1081 GLuint
*elts
= TNL_CONTEXT(ctx
)->vb
.Elts
;
1082 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS()/4*4;
1087 ELT_INIT( GL_TRIANGLES
);
1089 currentsz
= GET_CURRENT_VB_MAX_ELTS()/4*4;
1091 count
-= (count
-start
)%4;
1096 for (j
= start
; j
< count
; j
+= nr
) {
1097 nr
= MIN2( currentsz
, count
- j
);
1098 TAG(emit_elts
)( ctx
, elts
+j
, nr
, ALLOC_ELTS(nr
) );
1104 GLuint
*elts
= TNL_CONTEXT(ctx
)->vb
.Elts
;
1105 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS();
1109 ELT_INIT( GL_TRIANGLES
);
1110 currentsz
= GET_CURRENT_VB_MAX_ELTS();
1112 /* Emit whole number of quads in total, and in each buffer.
1115 count
-= (count
-start
) & 3;
1116 currentsz
-= currentsz
& 3;
1118 /* Adjust for rendering as triangles:
1120 currentsz
= currentsz
/6*4;
1126 for (j
= start
; j
+ 3 < count
; j
+= nr
- 2 ) {
1127 nr
= MIN2( currentsz
, count
- j
);
1133 ELTS_VARS( ALLOC_ELTS( quads
* 6 ) );
1135 for ( i
= j
-start
; i
< j
-start
+quads
; i
++, elts
+= 4 ) {
1136 EMIT_TWO_ELTS( 0, elts
[0], elts
[1] );
1137 EMIT_TWO_ELTS( 2, elts
[3], elts
[1] );
1138 EMIT_TWO_ELTS( 4, elts
[2], elts
[3] );
1152 static tnl_render_func
TAG(render_tab_elts
)[GL_POLYGON
+2] =
1154 TAG(render_points_elts
),
1155 TAG(render_lines_elts
),
1156 TAG(render_line_loop_elts
),
1157 TAG(render_line_strip_elts
),
1158 TAG(render_triangles_elts
),
1159 TAG(render_tri_strip_elts
),
1160 TAG(render_tri_fan_elts
),
1161 TAG(render_quads_elts
),
1162 TAG(render_quad_strip_elts
),
1163 TAG(render_poly_elts
),
1173 /* Pre-check the primitives in the VB to prevent the need for
1174 * fallbacks later on.
1176 static GLboolean
TAG(validate_render
)( GLcontext
*ctx
,
1177 struct vertex_buffer
*VB
)
1181 if (VB
->ClipOrMask
& ~CLIP_CULL_BIT
)
1184 if (VB
->Elts
&& !HAVE_ELTS
)
1187 for (i
= 0 ; i
< VB
->PrimitiveCount
; i
++) {
1188 GLuint prim
= VB
->Primitive
[i
].mode
;
1189 GLuint count
= VB
->Primitive
[i
].count
;
1190 GLboolean ok
= GL_FALSE
;
1195 switch (prim
& PRIM_MODE_MASK
) {
1200 ok
= HAVE_LINES
&& !ctx
->Line
.StippleFlag
;
1203 ok
= HAVE_LINE_STRIPS
&& !ctx
->Line
.StippleFlag
;
1206 ok
= HAVE_LINE_STRIPS
&& !ctx
->Line
.StippleFlag
;
1209 ok
= HAVE_TRIANGLES
;
1211 case GL_TRIANGLE_STRIP
:
1212 ok
= HAVE_TRI_STRIPS
;
1214 case GL_TRIANGLE_FAN
:
1218 if (HAVE_POLYGONS
) {
1222 ok
= (HAVE_TRI_FANS
&& ctx
->Light
.ShadeModel
== GL_SMOOTH
);
1227 ok
= HAVE_TRI_STRIPS
;
1229 else if (HAVE_QUAD_STRIPS
) {
1231 } else if (HAVE_TRI_STRIPS
&&
1232 ctx
->Light
.ShadeModel
== GL_FLAT
&&
1233 VB
->AttribPtr
[_TNL_ATTRIB_COLOR0
]->stride
!= 0) {
1235 ok
= (GLint
) count
< GET_SUBSEQUENT_VB_MAX_ELTS();
1242 ok
= HAVE_TRI_STRIPS
;
1247 } else if (HAVE_ELTS
) {
1248 ok
= (GLint
) count
< GET_SUBSEQUENT_VB_MAX_ELTS();
1251 ok
= HAVE_TRIANGLES
; /* flatshading is ok. */
1259 /* fprintf(stderr, "not ok %s\n", _mesa_lookup_enum_by_nr(prim & PRIM_MODE_MASK)); */