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 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 * OTHER DEALINGS IN THE SOFTWARE.
26 * Keith Whitwell <keith@tungstengraphics.com>
32 * Template for render stages which build and emit vertices directly
33 * to fixed-size dma buffers. Useful for rendering strips and other
34 * native primitives where clipping and per-vertex tweaks such as
35 * those in t_dd_tritmp.h are not required.
37 * Produces code for both inline triangles and indexed triangles.
38 * Where various primitive types are unaccelerated by hardware, the
39 * code attempts to fallback to other primitive types (quadstrips to
40 * tristrips, lineloops to linestrips), or to indexed vertices.
43 #if !defined(HAVE_TRIANGLES)
44 #error "must have at least triangles to use render template"
48 #define ELTS_VARS(buf)
49 #define ALLOC_ELTS(nr) 0
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 RELEASE_ELT_VERTS()
57 #define EMIT_INDEXED_VERTS( ctx, start, count )
61 #define EMIT_TWO_ELTS( offset, elt0, elt1 ) \
63 EMIT_ELT( offset, elt0 ); \
64 EMIT_ELT( offset+1, elt1 ); \
69 /**********************************************************************/
70 /* Render whole begin/end objects */
71 /**********************************************************************/
77 static void *TAG(emit_elts
)( struct gl_context
*ctx
, GLuint
*elts
, GLuint nr
,
84 for ( i
= 0 ; i
+1 < nr
; i
+=2, elts
+= 2 ) {
85 EMIT_TWO_ELTS( 0, elts
[0], elts
[1] );
90 EMIT_ELT( 0, elts
[0] );
94 return (void *)ELTPTR
;
98 static __inline
void *TAG(emit_verts
)( struct gl_context
*ctx
, GLuint start
,
99 GLuint count
, void *buf
)
101 return EMIT_VERTS(ctx
, start
, count
, buf
);
104 /***********************************************************************
105 * Render non-indexed primitives.
106 ***********************************************************************/
108 static void TAG(render_points_verts
)( struct gl_context
*ctx
,
115 int dmasz
= GET_SUBSEQUENT_VB_MAX_VERTS();
121 currentsz
= GET_CURRENT_VB_MAX_VERTS();
125 for (j
= start
; j
< count
; j
+= nr
) {
126 nr
= MIN2( currentsz
, count
- j
);
127 TAG(emit_verts
)( ctx
, j
, nr
, ALLOC_VERTS(nr
) );
132 fprintf(stderr
, "%s - cannot draw primitive\n", __FUNCTION__
);
137 static void TAG(render_lines_verts
)( struct gl_context
*ctx
,
144 int dmasz
= GET_SUBSEQUENT_VB_MAX_VERTS();
150 /* Emit whole number of lines in total and in each buffer:
152 count
-= (count
-start
) & 1;
153 currentsz
= GET_CURRENT_VB_MAX_VERTS();
154 currentsz
-= currentsz
& 1;
160 for (j
= start
; j
< count
; j
+= nr
) {
161 nr
= MIN2( currentsz
, count
- j
);
162 TAG(emit_verts
)( ctx
, j
, nr
, ALLOC_VERTS(nr
) );
167 fprintf(stderr
, "%s - cannot draw primitive\n", __FUNCTION__
);
173 static void TAG(render_line_strip_verts
)( struct gl_context
*ctx
,
178 if (HAVE_LINE_STRIPS
) {
180 int dmasz
= GET_SUBSEQUENT_VB_MAX_VERTS();
184 INIT( GL_LINE_STRIP
);
186 currentsz
= GET_CURRENT_VB_MAX_VERTS();
190 for (j
= start
; j
+ 1 < count
; j
+= nr
- 1 ) {
191 nr
= MIN2( currentsz
, count
- j
);
192 TAG(emit_verts
)( ctx
, j
, nr
, ALLOC_VERTS(nr
) );
199 fprintf(stderr
, "%s - cannot draw primitive\n", __FUNCTION__
);
205 static void TAG(render_line_loop_verts
)( struct gl_context
*ctx
,
210 if (HAVE_LINE_STRIPS
) {
212 int dmasz
= GET_SUBSEQUENT_VB_MAX_VERTS();
216 INIT( GL_LINE_STRIP
);
218 if (flags
& PRIM_BEGIN
)
223 /* Ensure last vertex won't wrap buffers:
225 currentsz
= GET_CURRENT_VB_MAX_VERTS();
234 for ( ; j
+ 1 < count
; j
+= nr
- 1 ) {
235 nr
= MIN2( currentsz
, count
- j
);
237 if (j
+ nr
>= count
&&
242 tmp
= ALLOC_VERTS(nr
+1);
243 tmp
= TAG(emit_verts
)( ctx
, j
, nr
, tmp
);
244 tmp
= TAG(emit_verts
)( ctx
, start
, 1, tmp
);
248 TAG(emit_verts
)( ctx
, j
, nr
, ALLOC_VERTS(nr
) );
254 else if (start
+ 1 < count
&& (flags
& PRIM_END
)) {
256 tmp
= ALLOC_VERTS(2);
257 tmp
= TAG(emit_verts
)( ctx
, start
+1, 1, tmp
);
258 tmp
= TAG(emit_verts
)( ctx
, start
, 1, tmp
);
265 fprintf(stderr
, "%s - cannot draw primitive\n", __FUNCTION__
);
271 static void TAG(render_triangles_verts
)( struct gl_context
*ctx
,
277 int dmasz
= (GET_SUBSEQUENT_VB_MAX_VERTS()/3) * 3;
283 currentsz
= (GET_CURRENT_VB_MAX_VERTS()/3) * 3;
285 /* Emit whole number of tris in total. dmasz is already a multiple
288 count
-= (count
-start
)%3;
293 for (j
= start
; j
< count
; j
+= nr
) {
294 nr
= MIN2( currentsz
, count
- j
);
295 TAG(emit_verts
)( ctx
, j
, nr
, ALLOC_VERTS(nr
) );
302 static void TAG(render_tri_strip_verts
)( struct gl_context
*ctx
,
307 if (HAVE_TRI_STRIPS
) {
310 int dmasz
= GET_SUBSEQUENT_VB_MAX_VERTS();
313 INIT(GL_TRIANGLE_STRIP
);
315 currentsz
= GET_CURRENT_VB_MAX_VERTS();
321 /* From here on emit even numbers of tris when wrapping over buffers:
323 dmasz
-= (dmasz
& 1);
324 currentsz
-= (currentsz
& 1);
326 for (j
= start
; j
+ 2 < count
; j
+= nr
- 2 ) {
327 nr
= MIN2( currentsz
, count
- j
);
328 TAG(emit_verts
)( ctx
, j
, nr
, ALLOC_VERTS(nr
) );
335 fprintf(stderr
, "%s - cannot draw primitive\n", __FUNCTION__
);
340 static void TAG(render_tri_fan_verts
)( struct gl_context
*ctx
,
348 int dmasz
= GET_SUBSEQUENT_VB_MAX_VERTS();
351 INIT(GL_TRIANGLE_FAN
);
353 currentsz
= GET_CURRENT_VB_MAX_VERTS();
358 for (j
= start
+ 1 ; j
+ 1 < count
; j
+= nr
- 2 ) {
360 nr
= MIN2( currentsz
, count
- j
+ 1 );
361 tmp
= ALLOC_VERTS( nr
);
362 tmp
= TAG(emit_verts
)( ctx
, start
, 1, tmp
);
363 tmp
= TAG(emit_verts
)( ctx
, j
, nr
- 1, tmp
);
371 /* Could write code to emit these as indexed vertices (for the
372 * g400, for instance).
374 fprintf(stderr
, "%s - cannot draw primitive\n", __FUNCTION__
);
380 static void TAG(render_poly_verts
)( struct gl_context
*ctx
,
388 int dmasz
= GET_SUBSEQUENT_VB_MAX_VERTS();
393 currentsz
= GET_CURRENT_VB_MAX_VERTS();
398 for (j
= start
+ 1 ; j
+ 1 < count
; j
+= nr
- 2 ) {
400 nr
= MIN2( currentsz
, count
- j
+ 1 );
401 tmp
= ALLOC_VERTS( nr
);
402 tmp
= TAG(emit_verts
)( ctx
, start
, 1, tmp
);
403 tmp
= TAG(emit_verts
)( ctx
, j
, nr
- 1, tmp
);
410 else if (HAVE_TRI_FANS
&& ctx
->Light
.ShadeModel
== GL_SMOOTH
) {
411 TAG(render_tri_fan_verts
)( ctx
, start
, count
, flags
);
413 fprintf(stderr
, "%s - cannot draw primitive\n", __FUNCTION__
);
418 static void TAG(render_quad_strip_verts
)( struct gl_context
*ctx
,
425 if (HAVE_QUAD_STRIPS
) {
428 int dmasz
= GET_SUBSEQUENT_VB_MAX_VERTS();
433 currentsz
= GET_CURRENT_VB_MAX_VERTS();
438 dmasz
-= (dmasz
& 2);
439 currentsz
-= (currentsz
& 2);
441 for (j
= start
; j
+ 3 < count
; j
+= nr
- 2 ) {
442 nr
= MIN2( currentsz
, count
- j
);
443 TAG(emit_verts
)( ctx
, j
, nr
, ALLOC_VERTS(nr
) );
449 } else if (HAVE_TRI_STRIPS
&&
450 ctx
->Light
.ShadeModel
== GL_FLAT
&&
451 TNL_CONTEXT(ctx
)->vb
.AttribPtr
[_TNL_ATTRIB_COLOR0
]->stride
) {
454 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS();
458 EMIT_INDEXED_VERTS( ctx
, start
, count
);
460 /* Simulate flat-shaded quadstrips using indexed vertices:
462 ELT_INIT( GL_TRIANGLES
);
464 currentsz
= GET_CURRENT_VB_MAX_ELTS();
466 /* Emit whole number of quads in total, and in each buffer.
469 count
-= (count
-start
) & 1;
470 currentsz
-= currentsz
& 1;
475 currentsz
= currentsz
/6*2;
478 for (j
= start
; j
+ 3 < count
; j
+= nr
- 2 ) {
479 nr
= MIN2( currentsz
, count
- j
);
481 GLint quads
= (nr
/2)-1;
483 ELTS_VARS( ALLOC_ELTS( quads
*6 ) );
485 for ( i
= j
-start
; i
< j
-start
+quads
*2 ; i
+=2 ) {
486 EMIT_TWO_ELTS( 0, (i
+0), (i
+1) );
487 EMIT_TWO_ELTS( 2, (i
+2), (i
+1) );
488 EMIT_TWO_ELTS( 4, (i
+3), (i
+2) );
501 /* Vertices won't fit in a single buffer or elts not
502 * available - should never happen.
504 fprintf(stderr
, "%s - cannot draw primitive\n", __FUNCTION__
);
508 else if (HAVE_TRI_STRIPS
) {
510 int dmasz
= GET_SUBSEQUENT_VB_MAX_VERTS();
513 /* Emit smooth-shaded quadstrips as tristrips:
516 INIT( GL_TRIANGLE_STRIP
);
518 /* Emit whole number of quads in total, and in each buffer.
521 currentsz
= GET_CURRENT_VB_MAX_VERTS();
522 currentsz
-= currentsz
& 1;
523 count
-= (count
-start
) & 1;
529 for (j
= start
; j
+ 3 < count
; j
+= nr
- 2 ) {
530 nr
= MIN2( currentsz
, count
- j
);
531 TAG(emit_verts
)( ctx
, j
, nr
, ALLOC_VERTS(nr
) );
538 fprintf(stderr
, "%s - cannot draw primitive\n", __FUNCTION__
);
544 static void TAG(render_quads_verts
)( struct gl_context
*ctx
,
551 int dmasz
= (GET_SUBSEQUENT_VB_MAX_VERTS()/4) * 4;
557 /* Emit whole number of quads in total. dmasz is already a multiple
560 count
-= (count
-start
)%4;
562 currentsz
= (GET_CURRENT_VB_MAX_VERTS()/4) * 4;
566 for (j
= start
; j
< count
; j
+= nr
) {
567 nr
= MIN2( currentsz
, count
- j
);
568 TAG(emit_verts
)( ctx
, j
, nr
, ALLOC_VERTS(nr
) );
572 else if (HAVE_ELTS
) {
573 /* Hardware doesn't have a quad primitive type -- try to
574 * simulate it using indexed vertices and the triangle
578 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS();
582 EMIT_INDEXED_VERTS( ctx
, start
, count
);
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
);
607 ELTS_VARS( ALLOC_ELTS( quads
*6 ) );
609 for ( i
= j
-start
; i
< j
-start
+quads
*4 ; i
+=4 ) {
610 EMIT_TWO_ELTS( 0, (i
+0), (i
+1) );
611 EMIT_TWO_ELTS( 2, (i
+3), (i
+1) );
612 EMIT_TWO_ELTS( 4, (i
+2), (i
+3) );
623 else if (HAVE_TRIANGLES
) {
624 /* Hardware doesn't have a quad primitive type -- try to
625 * simulate it using triangle primitive. This is a win for
626 * gears, but is it useful in the broader world?
633 for (j
= start
; j
< count
-3; j
+= 4) {
634 void *tmp
= ALLOC_VERTS( 6 );
637 tmp
= EMIT_VERTS(ctx
, j
, 2, tmp
);
638 tmp
= EMIT_VERTS(ctx
, j
+ 3, 1, tmp
);
641 tmp
= EMIT_VERTS(ctx
, j
+ 1, 3, tmp
);
646 /* Vertices won't fit in a single buffer, should never happen.
648 fprintf(stderr
, "%s - cannot draw primitive\n", __FUNCTION__
);
653 static void TAG(render_noop
)( struct gl_context
*ctx
,
663 static tnl_render_func
TAG(render_tab_verts
)[GL_POLYGON
+2] =
665 TAG(render_points_verts
),
666 TAG(render_lines_verts
),
667 TAG(render_line_loop_verts
),
668 TAG(render_line_strip_verts
),
669 TAG(render_triangles_verts
),
670 TAG(render_tri_strip_verts
),
671 TAG(render_tri_fan_verts
),
672 TAG(render_quads_verts
),
673 TAG(render_quad_strip_verts
),
674 TAG(render_poly_verts
),
679 /****************************************************************************
680 * Render elts using hardware indexed verts *
681 ****************************************************************************/
684 static void TAG(render_points_elts
)( struct gl_context
*ctx
,
691 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS();
693 GLuint
*elts
= TNL_CONTEXT(ctx
)->vb
.Elts
;
696 ELT_INIT( GL_POINTS
);
698 currentsz
= GET_CURRENT_VB_MAX_ELTS();
702 for (j
= start
; j
< count
; j
+= nr
) {
703 nr
= MIN2( currentsz
, count
- j
);
704 TAG(emit_elts
)( ctx
, elts
+j
, nr
, ALLOC_ELTS(nr
) );
709 fprintf(stderr
, "%s - cannot draw primitive\n", __FUNCTION__
);
716 static void TAG(render_lines_elts
)( struct gl_context
*ctx
,
723 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS();
725 GLuint
*elts
= TNL_CONTEXT(ctx
)->vb
.Elts
;
728 ELT_INIT( GL_LINES
);
730 /* Emit whole number of lines in total and in each buffer:
732 count
-= (count
-start
) & 1;
733 currentsz
-= currentsz
& 1;
736 currentsz
= GET_CURRENT_VB_MAX_ELTS();
740 for (j
= start
; j
< count
; j
+= nr
) {
741 nr
= MIN2( currentsz
, count
- j
);
742 TAG(emit_elts
)( ctx
, elts
+j
, nr
, ALLOC_ELTS(nr
) );
747 fprintf(stderr
, "%s - cannot draw primitive\n", __FUNCTION__
);
753 static void TAG(render_line_strip_elts
)( struct gl_context
*ctx
,
758 if (HAVE_LINE_STRIPS
) {
760 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS();
762 GLuint
*elts
= TNL_CONTEXT(ctx
)->vb
.Elts
;
765 FLUSH(); /* always a new primitive */
766 ELT_INIT( GL_LINE_STRIP
);
768 currentsz
= GET_CURRENT_VB_MAX_ELTS();
772 for (j
= start
; j
+ 1 < count
; j
+= nr
- 1 ) {
773 nr
= MIN2( currentsz
, count
- j
);
774 TAG(emit_elts
)( ctx
, elts
+j
, nr
, ALLOC_ELTS(nr
) );
779 /* TODO: Try to emit as indexed lines.
781 fprintf(stderr
, "%s - cannot draw primitive\n", __FUNCTION__
);
787 static void TAG(render_line_loop_elts
)( struct gl_context
*ctx
,
792 if (HAVE_LINE_STRIPS
) {
794 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS();
796 GLuint
*elts
= TNL_CONTEXT(ctx
)->vb
.Elts
;
800 ELT_INIT( GL_LINE_STRIP
);
802 if (flags
& PRIM_BEGIN
)
807 currentsz
= GET_CURRENT_VB_MAX_ELTS();
812 /* Ensure last vertex doesn't wrap:
818 for ( ; j
+ 1 < count
; j
+= nr
- 1 ) {
819 nr
= MIN2( currentsz
, count
- j
);
821 if (j
+ nr
>= count
&&
826 tmp
= ALLOC_ELTS(nr
+1);
827 tmp
= TAG(emit_elts
)( ctx
, elts
+j
, nr
, tmp
);
828 tmp
= TAG(emit_elts
)( ctx
, elts
+start
, 1, tmp
);
832 TAG(emit_elts
)( ctx
, elts
+j
, nr
, ALLOC_ELTS(nr
) );
838 else if (start
+ 1 < count
&& (flags
& PRIM_END
)) {
841 tmp
= TAG(emit_elts
)( ctx
, elts
+start
+1, 1, tmp
);
842 tmp
= TAG(emit_elts
)( ctx
, elts
+start
, 1, tmp
);
848 /* TODO: Try to emit as indexed lines */
849 fprintf(stderr
, "%s - cannot draw primitive\n", __FUNCTION__
);
855 /* For verts, we still eliminate the copy from main memory to dma
856 * buffers. For elts, this is probably no better (worse?) than the
859 static void TAG(render_triangles_elts
)( struct gl_context
*ctx
,
865 GLuint
*elts
= TNL_CONTEXT(ctx
)->vb
.Elts
;
866 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS()/3*3;
871 ELT_INIT( GL_TRIANGLES
);
873 currentsz
= GET_CURRENT_VB_MAX_ELTS();
875 /* Emit whole number of tris in total. dmasz is already a multiple
878 count
-= (count
-start
)%3;
879 currentsz
-= currentsz
%3;
883 for (j
= start
; j
< count
; j
+= nr
) {
884 nr
= MIN2( currentsz
, count
- j
);
885 TAG(emit_elts
)( ctx
, elts
+j
, nr
, ALLOC_ELTS(nr
) );
893 static void TAG(render_tri_strip_elts
)( struct gl_context
*ctx
,
898 if (HAVE_TRI_STRIPS
) {
901 GLuint
*elts
= TNL_CONTEXT(ctx
)->vb
.Elts
;
902 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS();
906 ELT_INIT( GL_TRIANGLE_STRIP
);
908 currentsz
= GET_CURRENT_VB_MAX_ELTS();
913 /* Keep the same winding over multiple buffers:
915 dmasz
-= (dmasz
& 1);
916 currentsz
-= (currentsz
& 1);
918 for (j
= start
; j
+ 2 < count
; j
+= nr
- 2 ) {
919 nr
= MIN2( currentsz
, count
- j
);
920 TAG(emit_elts
)( ctx
, elts
+j
, nr
, ALLOC_ELTS(nr
) );
925 /* TODO: try to emit as indexed triangles */
926 fprintf(stderr
, "%s - cannot draw primitive\n", __FUNCTION__
);
931 static void TAG(render_tri_fan_elts
)( struct gl_context
*ctx
,
938 GLuint
*elts
= TNL_CONTEXT(ctx
)->vb
.Elts
;
940 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS();
944 ELT_INIT( GL_TRIANGLE_FAN
);
946 currentsz
= GET_CURRENT_VB_MAX_ELTS();
951 for (j
= start
+ 1 ; j
+ 1 < count
; j
+= nr
- 2 ) {
953 nr
= MIN2( currentsz
, count
- j
+ 1 );
954 tmp
= ALLOC_ELTS( nr
);
955 tmp
= TAG(emit_elts
)( ctx
, elts
+start
, 1, tmp
);
956 tmp
= TAG(emit_elts
)( ctx
, elts
+j
, nr
- 1, tmp
);
962 /* TODO: try to emit as indexed triangles */
963 fprintf(stderr
, "%s - cannot draw primitive\n", __FUNCTION__
);
969 static void TAG(render_poly_elts
)( struct gl_context
*ctx
,
976 GLuint
*elts
= TNL_CONTEXT(ctx
)->vb
.Elts
;
978 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS();
982 ELT_INIT( GL_POLYGON
);
984 currentsz
= GET_CURRENT_VB_MAX_ELTS();
989 for (j
= start
+ 1 ; j
+ 1 < count
; j
+= nr
- 2 ) {
991 nr
= MIN2( currentsz
, count
- j
+ 1 );
992 tmp
= ALLOC_ELTS( nr
);
993 tmp
= TAG(emit_elts
)( ctx
, elts
+start
, 1, tmp
);
994 tmp
= TAG(emit_elts
)( ctx
, elts
+j
, nr
- 1, tmp
);
999 } else if (HAVE_TRI_FANS
&& ctx
->Light
.ShadeModel
== GL_SMOOTH
) {
1000 TAG(render_tri_fan_verts
)( ctx
, start
, count
, flags
);
1002 fprintf(stderr
, "%s - cannot draw primitive\n", __FUNCTION__
);
1007 static void TAG(render_quad_strip_elts
)( struct gl_context
*ctx
,
1012 if (HAVE_QUAD_STRIPS
&& 0) {
1014 else if (HAVE_TRI_STRIPS
) {
1016 GLuint
*elts
= TNL_CONTEXT(ctx
)->vb
.Elts
;
1017 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS();
1022 currentsz
= GET_CURRENT_VB_MAX_ELTS();
1024 /* Emit whole number of quads in total, and in each buffer.
1027 count
-= (count
-start
) & 1;
1028 currentsz
-= currentsz
& 1;
1033 if (ctx
->Light
.ShadeModel
== GL_FLAT
) {
1034 ELT_INIT( GL_TRIANGLES
);
1036 currentsz
= currentsz
/6*2;
1039 for (j
= start
; j
+ 3 < count
; j
+= nr
- 2 ) {
1040 nr
= MIN2( currentsz
, count
- j
);
1045 GLint quads
= (nr
/2)-1;
1046 ELTS_VARS( ALLOC_ELTS( quads
*6 ) );
1048 for ( i
= j
-start
; i
< j
-start
+quads
; i
++, elts
+= 2 ) {
1049 EMIT_TWO_ELTS( 0, elts
[0], elts
[1] );
1050 EMIT_TWO_ELTS( 2, elts
[2], elts
[1] );
1051 EMIT_TWO_ELTS( 4, elts
[3], elts
[2] );
1062 ELT_INIT( GL_TRIANGLE_STRIP
);
1064 for (j
= start
; j
+ 3 < count
; j
+= nr
- 2 ) {
1065 nr
= MIN2( currentsz
, count
- j
);
1066 TAG(emit_elts
)( ctx
, elts
+j
, nr
, ALLOC_ELTS(nr
) );
1075 static void TAG(render_quads_elts
)( struct gl_context
*ctx
,
1082 GLuint
*elts
= TNL_CONTEXT(ctx
)->vb
.Elts
;
1083 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS()/4*4;
1088 ELT_INIT( GL_TRIANGLES
);
1090 currentsz
= GET_CURRENT_VB_MAX_ELTS()/4*4;
1092 count
-= (count
-start
)%4;
1097 for (j
= start
; j
< count
; j
+= nr
) {
1098 nr
= MIN2( currentsz
, count
- j
);
1099 TAG(emit_elts
)( ctx
, elts
+j
, nr
, ALLOC_ELTS(nr
) );
1105 GLuint
*elts
= TNL_CONTEXT(ctx
)->vb
.Elts
;
1106 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS();
1110 ELT_INIT( GL_TRIANGLES
);
1111 currentsz
= GET_CURRENT_VB_MAX_ELTS();
1113 /* Emit whole number of quads in total, and in each buffer.
1116 count
-= (count
-start
) & 3;
1117 currentsz
-= currentsz
& 3;
1119 /* Adjust for rendering as triangles:
1121 currentsz
= currentsz
/6*4;
1127 for (j
= start
; j
+ 3 < count
; j
+= nr
- 2 ) {
1128 nr
= MIN2( currentsz
, count
- j
);
1134 ELTS_VARS( ALLOC_ELTS( quads
* 6 ) );
1136 for ( i
= j
-start
; i
< j
-start
+quads
; i
++, elts
+= 4 ) {
1137 EMIT_TWO_ELTS( 0, elts
[0], elts
[1] );
1138 EMIT_TWO_ELTS( 2, elts
[3], elts
[1] );
1139 EMIT_TWO_ELTS( 4, elts
[2], elts
[3] );
1153 static tnl_render_func
TAG(render_tab_elts
)[GL_POLYGON
+2] =
1155 TAG(render_points_elts
),
1156 TAG(render_lines_elts
),
1157 TAG(render_line_loop_elts
),
1158 TAG(render_line_strip_elts
),
1159 TAG(render_triangles_elts
),
1160 TAG(render_tri_strip_elts
),
1161 TAG(render_tri_fan_elts
),
1162 TAG(render_quads_elts
),
1163 TAG(render_quad_strip_elts
),
1164 TAG(render_poly_elts
),
1174 /* Pre-check the primitives in the VB to prevent the need for
1175 * fallbacks later on.
1177 static GLboolean
TAG(validate_render
)( struct gl_context
*ctx
,
1178 struct vertex_buffer
*VB
)
1182 if (VB
->ClipOrMask
& ~CLIP_CULL_BIT
)
1185 if (VB
->Elts
&& !HAVE_ELTS
)
1188 for (i
= 0 ; i
< VB
->PrimitiveCount
; i
++) {
1189 GLuint prim
= VB
->Primitive
[i
].mode
;
1190 GLuint count
= VB
->Primitive
[i
].count
;
1191 GLboolean ok
= GL_FALSE
;
1196 switch (prim
& PRIM_MODE_MASK
) {
1201 ok
= HAVE_LINES
&& !ctx
->Line
.StippleFlag
;
1204 ok
= HAVE_LINE_STRIPS
&& !ctx
->Line
.StippleFlag
;
1207 ok
= HAVE_LINE_STRIPS
&& !ctx
->Line
.StippleFlag
;
1210 ok
= HAVE_TRIANGLES
;
1212 case GL_TRIANGLE_STRIP
:
1213 ok
= HAVE_TRI_STRIPS
;
1215 case GL_TRIANGLE_FAN
:
1219 if (HAVE_POLYGONS
) {
1223 ok
= (HAVE_TRI_FANS
&& ctx
->Light
.ShadeModel
== GL_SMOOTH
);
1228 ok
= HAVE_TRI_STRIPS
;
1230 else if (HAVE_QUAD_STRIPS
) {
1232 } else if (HAVE_TRI_STRIPS
&&
1233 ctx
->Light
.ShadeModel
== GL_FLAT
&&
1234 VB
->AttribPtr
[_TNL_ATTRIB_COLOR0
]->stride
!= 0) {
1236 ok
= (GLint
) count
< GET_SUBSEQUENT_VB_MAX_ELTS();
1243 ok
= HAVE_TRI_STRIPS
;
1248 } else if (HAVE_ELTS
) {
1249 ok
= (GLint
) count
< GET_SUBSEQUENT_VB_MAX_ELTS();
1252 ok
= HAVE_TRIANGLES
; /* flatshading is ok. */
1260 /* fprintf(stderr, "not ok %s\n", _mesa_lookup_enum_by_nr(prim & PRIM_MODE_MASK)); */