2 * Mesa 3-D graphics library
4 * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
25 * Keith Whitwell <keithw@vmware.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
)( struct gl_context
*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
)( struct gl_context
*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
)( struct gl_context
*ctx
,
114 int dmasz
= GET_SUBSEQUENT_VB_MAX_VERTS();
120 currentsz
= GET_CURRENT_VB_MAX_VERTS();
124 for (j
= 0; j
< count
; j
+= nr
) {
125 nr
= MIN2( currentsz
, count
- j
);
126 TAG(emit_verts
)(ctx
, start
+ j
, nr
, ALLOC_VERTS(nr
));
131 fprintf(stderr
, "%s - cannot draw primitive\n", __func__
);
136 static void TAG(render_lines_verts
)( struct gl_context
*ctx
,
143 int dmasz
= GET_SUBSEQUENT_VB_MAX_VERTS();
149 /* Emit whole number of lines in total and in each buffer:
152 currentsz
= GET_CURRENT_VB_MAX_VERTS();
153 currentsz
-= currentsz
& 1;
159 for (j
= 0; j
< count
; j
+= nr
) {
160 nr
= MIN2( currentsz
, count
- j
);
161 TAG(emit_verts
)(ctx
, start
+ j
, nr
, ALLOC_VERTS(nr
));
166 fprintf(stderr
, "%s - cannot draw primitive\n", __func__
);
172 static void TAG(render_line_strip_verts
)( struct gl_context
*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
= 0; j
+ 1 < count
; j
+= nr
- 1 ) {
190 nr
= MIN2( currentsz
, count
- j
);
191 TAG(emit_verts
)(ctx
, start
+ j
, nr
, ALLOC_VERTS(nr
));
198 fprintf(stderr
, "%s - cannot draw primitive\n", __func__
);
204 static void TAG(render_line_loop_verts
)( struct gl_context
*ctx
,
209 if (HAVE_LINE_STRIPS
) {
211 int dmasz
= GET_SUBSEQUENT_VB_MAX_VERTS();
215 INIT( GL_LINE_STRIP
);
217 j
= (flags
& PRIM_BEGIN
) ? 0 : 1;
219 /* Ensure last vertex won't wrap buffers:
221 currentsz
= GET_CURRENT_VB_MAX_VERTS();
230 for ( ; j
+ 1 < count
; j
+= nr
- 1 ) {
231 nr
= MIN2( currentsz
, count
- j
);
233 if (j
+ nr
>= count
&&
238 tmp
= ALLOC_VERTS(nr
+1);
239 tmp
= TAG(emit_verts
)(ctx
, start
+ j
, nr
, tmp
);
240 tmp
= TAG(emit_verts
)( ctx
, start
, 1, tmp
);
244 TAG(emit_verts
)(ctx
, start
+ j
, nr
, ALLOC_VERTS(nr
));
250 else if (count
> 1 && (flags
& PRIM_END
)) {
252 tmp
= ALLOC_VERTS(2);
253 tmp
= TAG(emit_verts
)( ctx
, start
+1, 1, tmp
);
254 tmp
= TAG(emit_verts
)( ctx
, start
, 1, tmp
);
261 fprintf(stderr
, "%s - cannot draw primitive\n", __func__
);
267 static void TAG(render_triangles_verts
)( struct gl_context
*ctx
,
273 int dmasz
= (GET_SUBSEQUENT_VB_MAX_VERTS()/3) * 3;
279 currentsz
= (GET_CURRENT_VB_MAX_VERTS()/3) * 3;
281 /* Emit whole number of tris in total. dmasz is already a multiple
289 for (j
= 0; j
< count
; j
+= nr
) {
290 nr
= MIN2( currentsz
, count
- j
);
291 TAG(emit_verts
)(ctx
, start
+ j
, nr
, ALLOC_VERTS(nr
));
298 static void TAG(render_tri_strip_verts
)( struct gl_context
*ctx
,
303 if (HAVE_TRI_STRIPS
) {
306 int dmasz
= GET_SUBSEQUENT_VB_MAX_VERTS();
309 INIT(GL_TRIANGLE_STRIP
);
311 currentsz
= GET_CURRENT_VB_MAX_VERTS();
317 /* From here on emit even numbers of tris when wrapping over buffers:
319 dmasz
-= (dmasz
& 1);
320 currentsz
-= (currentsz
& 1);
322 for (j
= 0; j
+ 2 < count
; j
+= nr
- 2) {
323 nr
= MIN2( currentsz
, count
- j
);
324 TAG(emit_verts
)(ctx
, start
+ j
, nr
, ALLOC_VERTS(nr
));
331 fprintf(stderr
, "%s - cannot draw primitive\n", __func__
);
336 static void TAG(render_tri_fan_verts
)( struct gl_context
*ctx
,
344 int dmasz
= GET_SUBSEQUENT_VB_MAX_VERTS();
347 INIT(GL_TRIANGLE_FAN
);
349 currentsz
= GET_CURRENT_VB_MAX_VERTS();
354 for (j
= 1; j
+ 1 < count
; j
+= nr
- 2) {
356 nr
= MIN2( currentsz
, count
- j
+ 1 );
357 tmp
= ALLOC_VERTS( nr
);
358 tmp
= TAG(emit_verts
)( ctx
, start
, 1, tmp
);
359 tmp
= TAG(emit_verts
)( ctx
, start
+ 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", __func__
);
376 static void TAG(render_poly_verts
)( struct gl_context
*ctx
,
384 int dmasz
= GET_SUBSEQUENT_VB_MAX_VERTS();
389 currentsz
= GET_CURRENT_VB_MAX_VERTS();
394 for (j
= 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
, start
+ j
, nr
- 1, tmp
);
406 else if (HAVE_TRI_FANS
&& ctx
->Light
.ShadeModel
== GL_SMOOTH
) {
407 TAG(render_tri_fan_verts
)( ctx
, start
, count
, flags
);
409 fprintf(stderr
, "%s - cannot draw primitive\n", __func__
);
414 static void TAG(render_quad_strip_verts
)( struct gl_context
*ctx
,
421 if (HAVE_QUAD_STRIPS
) {
424 int dmasz
= GET_SUBSEQUENT_VB_MAX_VERTS();
429 currentsz
= GET_CURRENT_VB_MAX_VERTS();
434 dmasz
-= (dmasz
& 2);
435 currentsz
-= (currentsz
& 2);
437 for (j
= 0; j
+ 3 < count
; j
+= nr
- 2 ) {
438 nr
= MIN2( currentsz
, count
- j
);
439 TAG(emit_verts
)(ctx
, start
+ j
, nr
, ALLOC_VERTS(nr
));
445 } else if (HAVE_TRI_STRIPS
&&
446 ctx
->Light
.ShadeModel
== GL_FLAT
&&
447 TNL_CONTEXT(ctx
)->vb
.AttribPtr
[_TNL_ATTRIB_COLOR0
]->stride
) {
450 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS();
454 EMIT_INDEXED_VERTS( ctx
, start
, count
);
456 /* Simulate flat-shaded quadstrips using indexed vertices:
458 ELT_INIT( GL_TRIANGLES
);
460 currentsz
= GET_CURRENT_VB_MAX_ELTS();
462 /* Emit whole number of quads in total, and in each buffer.
466 currentsz
-= currentsz
& 1;
471 currentsz
= currentsz
/6*2;
474 for (j
= 0; j
+ 3 < count
; j
+= nr
- 2) {
475 nr
= MIN2( currentsz
, count
- j
);
477 GLint quads
= (nr
/2)-1;
479 ELTS_VARS( ALLOC_ELTS( quads
*6 ) );
481 for (i
= j
; i
< j
+ quads
* 2; i
+= 2) {
482 EMIT_TWO_ELTS( 0, (i
+0), (i
+1) );
483 EMIT_TWO_ELTS( 2, (i
+2), (i
+1) );
484 EMIT_TWO_ELTS( 4, (i
+3), (i
+2) );
497 /* Vertices won't fit in a single buffer or elts not
498 * available - should never happen.
500 fprintf(stderr
, "%s - cannot draw primitive\n", __func__
);
504 else if (HAVE_TRI_STRIPS
) {
506 int dmasz
= GET_SUBSEQUENT_VB_MAX_VERTS();
509 /* Emit smooth-shaded quadstrips as tristrips:
512 INIT( GL_TRIANGLE_STRIP
);
514 /* Emit whole number of quads in total, and in each buffer.
517 currentsz
= GET_CURRENT_VB_MAX_VERTS();
518 currentsz
-= currentsz
& 1;
525 for (j
= 0; j
+ 3 < count
; j
+= nr
- 2) {
526 nr
= MIN2( currentsz
, count
- j
);
527 TAG(emit_verts
)(ctx
, start
+ j
, nr
, ALLOC_VERTS(nr
));
534 fprintf(stderr
, "%s - cannot draw primitive\n", __func__
);
540 static void TAG(render_quads_verts
)( struct gl_context
*ctx
,
545 /* Emit whole number of quads in total. */
550 int dmasz
= (GET_SUBSEQUENT_VB_MAX_VERTS()/4) * 4;
556 currentsz
= (GET_CURRENT_VB_MAX_VERTS()/4) * 4;
560 for (j
= 0; j
< count
; j
+= nr
) {
561 nr
= MIN2( currentsz
, count
- j
);
562 TAG(emit_verts
)(ctx
, start
+ 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 currentsz
-= currentsz
& 3;
587 /* Adjust for rendering as triangles:
589 currentsz
= currentsz
/6*4;
595 for (j
= 0; j
< count
; j
+= nr
) {
596 nr
= MIN2( currentsz
, count
- j
);
600 ELTS_VARS( ALLOC_ELTS( quads
*6 ) );
602 for (i
= j
; i
< j
+ quads
* 4; i
+= 4) {
603 EMIT_TWO_ELTS( 0, (i
+0), (i
+1) );
604 EMIT_TWO_ELTS( 2, (i
+3), (i
+1) );
605 EMIT_TWO_ELTS( 4, (i
+2), (i
+3) );
616 else if (HAVE_TRIANGLES
) {
617 /* Hardware doesn't have a quad primitive type -- try to
618 * simulate it using triangle primitive. This is a win for
619 * gears, but is it useful in the broader world?
626 for (j
= 0; j
< count
-3; j
+= 4) {
627 void *tmp
= ALLOC_VERTS( 6 );
630 tmp
= EMIT_VERTS(ctx
, start
+ j
, 2, tmp
);
631 tmp
= EMIT_VERTS(ctx
, start
+ j
+ 3, 1, tmp
);
634 tmp
= EMIT_VERTS(ctx
, start
+ j
+ 1, 3, tmp
);
639 /* Vertices won't fit in a single buffer, should never happen.
641 fprintf(stderr
, "%s - cannot draw primitive\n", __func__
);
646 static void TAG(render_noop
)( struct gl_context
*ctx
,
656 static tnl_render_func
TAG(render_tab_verts
)[GL_POLYGON
+2] =
658 TAG(render_points_verts
),
659 TAG(render_lines_verts
),
660 TAG(render_line_loop_verts
),
661 TAG(render_line_strip_verts
),
662 TAG(render_triangles_verts
),
663 TAG(render_tri_strip_verts
),
664 TAG(render_tri_fan_verts
),
665 TAG(render_quads_verts
),
666 TAG(render_quad_strip_verts
),
667 TAG(render_poly_verts
),
672 /****************************************************************************
673 * Render elts using hardware indexed verts *
674 ****************************************************************************/
677 static void TAG(render_points_elts
)( struct gl_context
*ctx
,
684 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS();
686 GLuint
*elts
= TNL_CONTEXT(ctx
)->vb
.Elts
;
689 ELT_INIT( GL_POINTS
);
691 currentsz
= GET_CURRENT_VB_MAX_ELTS();
695 for (j
= 0; j
< count
; j
+= nr
) {
696 nr
= MIN2( currentsz
, count
- j
);
697 TAG(emit_elts
)(ctx
, elts
+ start
+ j
, nr
, ALLOC_ELTS(nr
));
702 fprintf(stderr
, "%s - cannot draw primitive\n", __func__
);
709 static void TAG(render_lines_elts
)( struct gl_context
*ctx
,
716 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS();
718 GLuint
*elts
= TNL_CONTEXT(ctx
)->vb
.Elts
;
721 ELT_INIT( GL_LINES
);
723 /* Emit whole number of lines in total and in each buffer:
726 currentsz
-= currentsz
& 1;
729 currentsz
= GET_CURRENT_VB_MAX_ELTS();
733 for (j
= 0; j
< count
; j
+= nr
) {
734 nr
= MIN2( currentsz
, count
- j
);
735 TAG(emit_elts
)(ctx
, elts
+ start
+ j
, nr
, ALLOC_ELTS(nr
));
740 fprintf(stderr
, "%s - cannot draw primitive\n", __func__
);
746 static void TAG(render_line_strip_elts
)( struct gl_context
*ctx
,
751 if (HAVE_LINE_STRIPS
) {
753 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS();
755 GLuint
*elts
= TNL_CONTEXT(ctx
)->vb
.Elts
;
758 FLUSH(); /* always a new primitive */
759 ELT_INIT( GL_LINE_STRIP
);
761 currentsz
= GET_CURRENT_VB_MAX_ELTS();
765 for (j
= 0; j
+ 1 < count
; j
+= nr
- 1) {
766 nr
= MIN2( currentsz
, count
- j
);
767 TAG(emit_elts
)( ctx
, elts
+ start
+ j
, nr
, ALLOC_ELTS(nr
));
772 /* TODO: Try to emit as indexed lines.
774 fprintf(stderr
, "%s - cannot draw primitive\n", __func__
);
780 static void TAG(render_line_loop_elts
)( struct gl_context
*ctx
,
785 if (HAVE_LINE_STRIPS
) {
787 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS();
789 GLuint
*elts
= TNL_CONTEXT(ctx
)->vb
.Elts
;
793 ELT_INIT( GL_LINE_STRIP
);
795 j
= (flags
& PRIM_BEGIN
) ? 0 : 1;
797 currentsz
= GET_CURRENT_VB_MAX_ELTS();
802 /* Ensure last vertex doesn't wrap:
808 for ( ; j
+ 1 < count
; j
+= nr
- 1 ) {
809 nr
= MIN2( currentsz
, count
- j
);
811 if (j
+ nr
>= count
&&
816 tmp
= ALLOC_ELTS(nr
+1);
817 tmp
= TAG(emit_elts
)(ctx
, elts
+ start
+ j
, nr
, tmp
);
818 tmp
= TAG(emit_elts
)( ctx
, elts
+start
, 1, tmp
);
822 TAG(emit_elts
)(ctx
, elts
+ start
+ j
, nr
, ALLOC_ELTS(nr
));
828 else if (count
> 1 && (flags
& PRIM_END
)) {
831 tmp
= TAG(emit_elts
)( ctx
, elts
+start
+1, 1, tmp
);
832 tmp
= TAG(emit_elts
)( ctx
, elts
+start
, 1, tmp
);
838 /* TODO: Try to emit as indexed lines */
839 fprintf(stderr
, "%s - cannot draw primitive\n", __func__
);
845 /* For verts, we still eliminate the copy from main memory to dma
846 * buffers. For elts, this is probably no better (worse?) than the
849 static void TAG(render_triangles_elts
)( struct gl_context
*ctx
,
855 GLuint
*elts
= TNL_CONTEXT(ctx
)->vb
.Elts
;
856 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS()/3*3;
861 ELT_INIT( GL_TRIANGLES
);
863 currentsz
= GET_CURRENT_VB_MAX_ELTS();
865 /* Emit whole number of tris in total. dmasz is already a multiple
869 currentsz
-= currentsz
%3;
873 for (j
= 0; j
< count
; j
+= nr
) {
874 nr
= MIN2( currentsz
, count
- j
);
875 TAG(emit_elts
)(ctx
, elts
+ start
+ j
, nr
, ALLOC_ELTS(nr
));
883 static void TAG(render_tri_strip_elts
)( struct gl_context
*ctx
,
888 if (HAVE_TRI_STRIPS
) {
891 GLuint
*elts
= TNL_CONTEXT(ctx
)->vb
.Elts
;
892 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS();
896 ELT_INIT( GL_TRIANGLE_STRIP
);
898 currentsz
= GET_CURRENT_VB_MAX_ELTS();
903 /* Keep the same winding over multiple buffers:
905 dmasz
-= (dmasz
& 1);
906 currentsz
-= (currentsz
& 1);
908 for (j
= 0; j
+ 2 < count
; j
+= nr
- 2) {
909 nr
= MIN2( currentsz
, count
- j
);
910 TAG(emit_elts
)( ctx
, elts
+ start
+ j
, nr
, ALLOC_ELTS(nr
) );
915 /* TODO: try to emit as indexed triangles */
916 fprintf(stderr
, "%s - cannot draw primitive\n", __func__
);
921 static void TAG(render_tri_fan_elts
)( struct gl_context
*ctx
,
928 GLuint
*elts
= TNL_CONTEXT(ctx
)->vb
.Elts
;
930 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS();
934 ELT_INIT( GL_TRIANGLE_FAN
);
936 currentsz
= GET_CURRENT_VB_MAX_ELTS();
941 for (j
= 1; j
+ 1 < count
; j
+= nr
- 2) {
943 nr
= MIN2( currentsz
, count
- j
+ 1 );
944 tmp
= ALLOC_ELTS( nr
);
945 tmp
= TAG(emit_elts
)( ctx
, elts
+start
, 1, tmp
);
946 tmp
= TAG(emit_elts
)(ctx
, elts
+ start
+ j
, nr
- 1, tmp
);
952 /* TODO: try to emit as indexed triangles */
953 fprintf(stderr
, "%s - cannot draw primitive\n", __func__
);
959 static void TAG(render_poly_elts
)( struct gl_context
*ctx
,
966 GLuint
*elts
= TNL_CONTEXT(ctx
)->vb
.Elts
;
968 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS();
972 ELT_INIT( GL_POLYGON
);
974 currentsz
= GET_CURRENT_VB_MAX_ELTS();
979 for (j
= 1 ; j
+ 1 < count
; j
+= nr
- 2) {
981 nr
= MIN2( currentsz
, count
- j
+ 1 );
982 tmp
= ALLOC_ELTS( nr
);
983 tmp
= TAG(emit_elts
)( ctx
, elts
+start
, 1, tmp
);
984 tmp
= TAG(emit_elts
)(ctx
, elts
+ start
+ j
, nr
- 1, tmp
);
989 } else if (HAVE_TRI_FANS
&& ctx
->Light
.ShadeModel
== GL_SMOOTH
) {
990 TAG(render_tri_fan_verts
)( ctx
, start
, count
, flags
);
992 fprintf(stderr
, "%s - cannot draw primitive\n", __func__
);
997 static void TAG(render_quad_strip_elts
)( struct gl_context
*ctx
,
1002 if (HAVE_QUAD_STRIPS
&& 0) {
1004 else if (HAVE_TRI_STRIPS
) {
1006 GLuint
*elts
= TNL_CONTEXT(ctx
)->vb
.Elts
;
1007 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS();
1012 currentsz
= GET_CURRENT_VB_MAX_ELTS();
1014 /* Emit whole number of quads in total, and in each buffer.
1018 currentsz
-= currentsz
& 1;
1023 if (ctx
->Light
.ShadeModel
== GL_FLAT
) {
1024 ELT_INIT( GL_TRIANGLES
);
1026 currentsz
= currentsz
/6*2;
1029 for (j
= 0; j
+ 3 < count
; j
+= nr
- 2) {
1030 nr
= MIN2( currentsz
, count
- j
);
1035 GLint quads
= (nr
/2)-1;
1036 ELTS_VARS( ALLOC_ELTS( quads
*6 ) );
1038 for (i
= j
; i
< j
+ quads
; i
++, elts
+= 2) {
1039 EMIT_TWO_ELTS( 0, elts
[0], elts
[1] );
1040 EMIT_TWO_ELTS( 2, elts
[2], elts
[1] );
1041 EMIT_TWO_ELTS( 4, elts
[3], elts
[2] );
1052 ELT_INIT( GL_TRIANGLE_STRIP
);
1054 for (j
= 0; j
+ 3 < count
; j
+= nr
- 2) {
1055 nr
= MIN2( currentsz
, count
- j
);
1056 TAG(emit_elts
)(ctx
, elts
+ start
+ j
, nr
, ALLOC_ELTS(nr
));
1065 static void TAG(render_quads_elts
)( struct gl_context
*ctx
,
1070 /* Emit whole number of quads in total. */
1075 GLuint
*elts
= TNL_CONTEXT(ctx
)->vb
.Elts
;
1076 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS()/4*4;
1081 ELT_INIT( GL_TRIANGLES
);
1083 currentsz
= GET_CURRENT_VB_MAX_ELTS()/4*4;
1088 for (j
= 0; j
< count
; j
+= nr
) {
1089 nr
= MIN2( currentsz
, count
- j
);
1090 TAG(emit_elts
)(ctx
, elts
+ start
+ j
, nr
, ALLOC_ELTS(nr
));
1096 GLuint
*elts
= TNL_CONTEXT(ctx
)->vb
.Elts
;
1097 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS();
1101 ELT_INIT( GL_TRIANGLES
);
1102 currentsz
= GET_CURRENT_VB_MAX_ELTS();
1104 /* Emit whole number of quads in total, and in each buffer.
1107 currentsz
-= currentsz
& 3;
1109 /* Adjust for rendering as triangles:
1111 currentsz
= currentsz
/6*4;
1117 for (j
= 0; j
+ 3 < count
; j
+= nr
- 2) {
1118 nr
= MIN2( currentsz
, count
- j
);
1124 ELTS_VARS( ALLOC_ELTS( quads
* 6 ) );
1126 for (i
= j
; i
< j
+ quads
; i
++, elts
+= 4) {
1127 EMIT_TWO_ELTS( 0, elts
[0], elts
[1] );
1128 EMIT_TWO_ELTS( 2, elts
[3], elts
[1] );
1129 EMIT_TWO_ELTS( 4, elts
[2], elts
[3] );
1143 static tnl_render_func
TAG(render_tab_elts
)[GL_POLYGON
+2] =
1145 TAG(render_points_elts
),
1146 TAG(render_lines_elts
),
1147 TAG(render_line_loop_elts
),
1148 TAG(render_line_strip_elts
),
1149 TAG(render_triangles_elts
),
1150 TAG(render_tri_strip_elts
),
1151 TAG(render_tri_fan_elts
),
1152 TAG(render_quads_elts
),
1153 TAG(render_quad_strip_elts
),
1154 TAG(render_poly_elts
),
1164 /* Pre-check the primitives in the VB to prevent the need for
1165 * fallbacks later on.
1167 static GLboolean
TAG(validate_render
)( struct gl_context
*ctx
,
1168 struct vertex_buffer
*VB
)
1172 if (VB
->ClipOrMask
& ~CLIP_CULL_BIT
)
1175 if (VB
->Elts
&& !HAVE_ELTS
)
1178 for (i
= 0 ; i
< VB
->PrimitiveCount
; i
++) {
1179 GLuint prim
= VB
->Primitive
[i
].mode
;
1180 GLuint count
= VB
->Primitive
[i
].count
;
1181 GLboolean ok
= GL_FALSE
;
1186 switch (prim
& PRIM_MODE_MASK
) {
1191 ok
= HAVE_LINES
&& !ctx
->Line
.StippleFlag
;
1194 ok
= HAVE_LINE_STRIPS
&& !ctx
->Line
.StippleFlag
;
1197 ok
= HAVE_LINE_STRIPS
&& !ctx
->Line
.StippleFlag
;
1200 ok
= HAVE_TRIANGLES
;
1202 case GL_TRIANGLE_STRIP
:
1203 ok
= HAVE_TRI_STRIPS
;
1205 case GL_TRIANGLE_FAN
:
1209 if (HAVE_POLYGONS
) {
1213 ok
= (HAVE_TRI_FANS
&& ctx
->Light
.ShadeModel
== GL_SMOOTH
);
1218 ok
= HAVE_TRI_STRIPS
;
1220 else if (HAVE_QUAD_STRIPS
) {
1222 } else if (HAVE_TRI_STRIPS
&&
1223 ctx
->Light
.ShadeModel
== GL_FLAT
&&
1224 VB
->AttribPtr
[_TNL_ATTRIB_COLOR0
]->stride
!= 0) {
1226 ok
= (GLint
) count
< GET_SUBSEQUENT_VB_MAX_ELTS();
1233 ok
= HAVE_TRI_STRIPS
;
1238 } else if (HAVE_ELTS
) {
1239 ok
= (GLint
) count
< GET_SUBSEQUENT_VB_MAX_ELTS();
1242 ok
= HAVE_TRIANGLES
; /* flatshading is ok. */
1250 /* fprintf(stderr, "not ok %s\n", _mesa_enum_to_string(prim & PRIM_MODE_MASK)); */