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"
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
)( GLcontext
*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
)( GLcontext
*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
)( GLcontext
*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
)( GLcontext
*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
)( GLcontext
*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
)( GLcontext
*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
);
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
);
263 fprintf(stderr
, "%s - cannot draw primitive\n", __FUNCTION__
);
269 static void TAG(render_triangles_verts
)( GLcontext
*ctx
,
275 int dmasz
= (GET_SUBSEQUENT_VB_MAX_VERTS()/3) * 3;
281 currentsz
= (GET_CURRENT_VB_MAX_VERTS()/3) * 3;
283 /* Emit whole number of tris in total. dmasz is already a multiple
286 count
-= (count
-start
)%3;
291 for (j
= start
; j
< count
; j
+= nr
) {
292 nr
= MIN2( currentsz
, count
- j
);
293 TAG(emit_verts
)( ctx
, j
, nr
, ALLOC_VERTS(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
);
313 currentsz
= GET_CURRENT_VB_MAX_VERTS();
319 /* From here on emit even numbers of tris when wrapping over buffers:
321 dmasz
-= (dmasz
& 1);
322 currentsz
-= (currentsz
& 1);
324 for (j
= start
; j
+ 2 < count
; j
+= nr
- 2 ) {
325 nr
= MIN2( currentsz
, count
- j
);
326 TAG(emit_verts
)( ctx
, j
, nr
, ALLOC_VERTS(nr
) );
333 fprintf(stderr
, "%s - cannot draw primitive\n", __FUNCTION__
);
338 static void TAG(render_tri_fan_verts
)( GLcontext
*ctx
,
346 int dmasz
= GET_SUBSEQUENT_VB_MAX_VERTS();
349 INIT(GL_TRIANGLE_FAN
);
351 currentsz
= GET_CURRENT_VB_MAX_VERTS();
356 for (j
= start
+ 1 ; j
+ 1 < count
; j
+= nr
- 1 ) {
358 nr
= MIN2( currentsz
, count
- j
+ 1 );
359 tmp
= ALLOC_VERTS( nr
);
360 tmp
= TAG(emit_verts
)( ctx
, start
, 1, tmp
);
361 tmp
= TAG(emit_verts
)( ctx
, j
, nr
- 1, tmp
);
368 /* Could write code to emit these as indexed vertices (for the
369 * g400, for instance).
371 fprintf(stderr
, "%s - cannot draw primitive\n", __FUNCTION__
);
377 static void TAG(render_poly_verts
)( GLcontext
*ctx
,
385 int dmasz
= GET_SUBSEQUENT_VB_MAX_VERTS();
390 currentsz
= GET_CURRENT_VB_MAX_VERTS();
395 for (j
= start
+ 1 ; j
+ 1 < count
; j
+= nr
- 1 ) {
397 nr
= MIN2( currentsz
, count
- j
+ 1 );
398 tmp
= ALLOC_VERTS( nr
);
399 tmp
= TAG(emit_verts
)( ctx
, start
, 1, tmp
);
400 tmp
= TAG(emit_verts
)( ctx
, j
, nr
- 1, tmp
);
406 else if (HAVE_TRI_FANS
&& !(ctx
->_TriangleCaps
& DD_FLATSHADE
)) {
407 TAG(render_tri_fan_verts
)( ctx
, start
, count
, flags
);
409 fprintf(stderr
, "%s - cannot draw primitive\n", __FUNCTION__
);
414 static void TAG(render_quad_strip_verts
)( GLcontext
*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
= start
; j
+ 3 < count
; j
+= nr
- 2 ) {
438 nr
= MIN2( currentsz
, count
- j
);
439 TAG(emit_verts
)( ctx
, j
, nr
, ALLOC_VERTS(nr
) );
445 } else if (HAVE_TRI_STRIPS
&& (ctx
->_TriangleCaps
& DD_FLATSHADE
)) {
448 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS();
452 EMIT_INDEXED_VERTS( ctx
, start
, count
);
454 /* Simulate flat-shaded quadstrips using indexed vertices:
456 ELT_INIT( GL_TRIANGLES
);
458 currentsz
= GET_CURRENT_VB_MAX_ELTS();
460 /* Emit whole number of quads in total, and in each buffer.
463 count
-= (count
-start
) & 1;
464 currentsz
-= currentsz
& 1;
469 currentsz
= currentsz
/6*2;
472 for (j
= start
; j
+ 3 < count
; j
+= nr
- 2 ) {
473 nr
= MIN2( currentsz
, count
- j
);
475 GLint quads
= (nr
/2)-1;
477 ELTS_VARS( ALLOC_ELTS( quads
*6 ) );
479 for ( i
= j
-start
; i
< j
-start
+quads
*2 ; i
+=2 ) {
480 EMIT_TWO_ELTS( 0, (i
+0), (i
+1) );
481 EMIT_TWO_ELTS( 2, (i
+2), (i
+1) );
482 EMIT_TWO_ELTS( 4, (i
+3), (i
+2) );
495 /* Vertices won't fit in a single buffer or elts not available,
498 fprintf(stderr
, "%s - cannot draw primitive\n", __FUNCTION__
);
502 else if (HAVE_TRI_STRIPS
) {
504 int dmasz
= GET_SUBSEQUENT_VB_MAX_VERTS();
507 /* Emit smooth-shaded quadstrips as tristrips:
510 INIT( GL_TRIANGLE_STRIP
);
512 /* Emit whole number of quads in total, and in each buffer.
515 currentsz
= GET_CURRENT_VB_MAX_VERTS();
516 currentsz
-= currentsz
& 1;
517 count
-= (count
-start
) & 1;
523 for (j
= start
; j
+ 3 < count
; j
+= nr
- 2 ) {
524 nr
= MIN2( currentsz
, count
- j
);
525 TAG(emit_verts
)( ctx
, j
, nr
, ALLOC_VERTS(nr
) );
532 fprintf(stderr
, "%s - cannot draw primitive\n", __FUNCTION__
);
538 static void TAG(render_quads_verts
)( GLcontext
*ctx
,
545 int dmasz
= (GET_SUBSEQUENT_VB_MAX_VERTS()/4) * 4;
551 /* Emit whole number of quads in total. dmasz is already a multiple
554 count
-= (count
-start
)%4;
556 currentsz
= (GET_CURRENT_VB_MAX_VERTS()/4) * 4;
560 for (j
= start
; j
< count
; j
+= nr
) {
561 nr
= MIN2( currentsz
, count
- j
);
562 TAG(emit_verts
)( ctx
, j
, nr
, ALLOC_VERTS(nr
) );
567 } else if (HAVE_ELTS
) {
568 /* Hardware doesn't have a quad primitive type -- try to
569 * simulate it using indexed vertices and the triangle
573 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS();
577 EMIT_INDEXED_VERTS( ctx
, start
, count
);
580 ELT_INIT( GL_TRIANGLES
);
581 currentsz
= GET_CURRENT_VB_MAX_ELTS();
583 /* Emit whole number of quads in total, and in each buffer.
586 count
-= (count
-start
) & 3;
587 currentsz
-= currentsz
& 3;
589 /* Adjust for rendering as triangles:
591 currentsz
= currentsz
/6*4;
597 for (j
= start
; j
< count
; j
+= nr
) {
598 nr
= MIN2( currentsz
, count
- j
);
602 ELTS_VARS( ALLOC_ELTS( quads
*6 ) );
604 for ( i
= j
-start
; i
< j
-start
+quads
*4 ; i
+=4 ) {
605 EMIT_TWO_ELTS( 0, (i
+0), (i
+1) );
606 EMIT_TWO_ELTS( 2, (i
+3), (i
+1) );
607 EMIT_TWO_ELTS( 4, (i
+2), (i
+3) );
619 /* Vertices won't fit in a single buffer, fallback.
621 fprintf(stderr
, "%s - cannot draw primitive\n", __FUNCTION__
);
626 static void TAG(render_noop
)( GLcontext
*ctx
,
636 static render_func
TAG(render_tab_verts
)[GL_POLYGON
+2] =
638 TAG(render_points_verts
),
639 TAG(render_lines_verts
),
640 TAG(render_line_loop_verts
),
641 TAG(render_line_strip_verts
),
642 TAG(render_triangles_verts
),
643 TAG(render_tri_strip_verts
),
644 TAG(render_tri_fan_verts
),
645 TAG(render_quads_verts
),
646 TAG(render_quad_strip_verts
),
647 TAG(render_poly_verts
),
652 /****************************************************************************
653 * Render elts using hardware indexed verts *
654 ****************************************************************************/
657 static void TAG(render_points_elts
)( GLcontext
*ctx
,
664 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS();
666 GLuint
*elts
= TNL_CONTEXT(ctx
)->vb
.Elts
;
669 ELT_INIT( GL_POINTS
);
671 currentsz
= GET_CURRENT_VB_MAX_ELTS();
675 for (j
= start
; j
< count
; j
+= nr
) {
676 nr
= MIN2( currentsz
, count
- j
);
677 TAG(emit_elts
)( ctx
, elts
+j
, nr
, ALLOC_ELTS(nr
) );
682 fprintf(stderr
, "%s - cannot draw primitive\n", __FUNCTION__
);
689 static void TAG(render_lines_elts
)( GLcontext
*ctx
,
696 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS();
698 GLuint
*elts
= TNL_CONTEXT(ctx
)->vb
.Elts
;
701 ELT_INIT( GL_LINES
);
703 /* Emit whole number of lines in total and in each buffer:
705 count
-= (count
-start
) & 1;
706 currentsz
-= currentsz
& 1;
709 currentsz
= GET_CURRENT_VB_MAX_ELTS();
713 for (j
= start
; j
< count
; j
+= nr
) {
714 nr
= MIN2( currentsz
, count
- j
);
715 TAG(emit_elts
)( ctx
, elts
+j
, nr
, ALLOC_ELTS(nr
) );
720 fprintf(stderr
, "%s - cannot draw primitive\n", __FUNCTION__
);
726 static void TAG(render_line_strip_elts
)( GLcontext
*ctx
,
731 if (HAVE_LINE_STRIPS
) {
733 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS();
735 GLuint
*elts
= TNL_CONTEXT(ctx
)->vb
.Elts
;
738 FLUSH(); /* always a new primitive */
739 ELT_INIT( GL_LINE_STRIP
);
741 currentsz
= GET_CURRENT_VB_MAX_ELTS();
745 for (j
= start
; j
+ 1 < count
; j
+= nr
- 1 ) {
746 nr
= MIN2( currentsz
, count
- j
);
747 TAG(emit_elts
)( ctx
, elts
+j
, nr
, ALLOC_ELTS(nr
) );
752 /* TODO: Try to emit as indexed lines.
754 fprintf(stderr
, "%s - cannot draw primitive\n", __FUNCTION__
);
760 static void TAG(render_line_loop_elts
)( GLcontext
*ctx
,
765 if (HAVE_LINE_STRIPS
) {
767 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS();
769 GLuint
*elts
= TNL_CONTEXT(ctx
)->vb
.Elts
;
773 ELT_INIT( GL_LINE_STRIP
);
775 if (flags
& PRIM_BEGIN
)
780 currentsz
= GET_CURRENT_VB_MAX_ELTS();
785 /* Ensure last vertex doesn't wrap:
791 for ( ; j
+ 1 < count
; j
+= nr
- 1 ) {
792 nr
= MIN2( currentsz
, count
- j
);
794 if (j
+ nr
>= count
&&
799 tmp
= ALLOC_ELTS(nr
+1);
800 tmp
= TAG(emit_elts
)( ctx
, elts
+j
, nr
, tmp
);
801 tmp
= TAG(emit_elts
)( ctx
, elts
+start
, 1, tmp
);
804 TAG(emit_elts
)( ctx
, elts
+j
, nr
, ALLOC_ELTS(nr
) );
810 else if (start
+ 1 < count
&& (flags
& PRIM_END
)) {
813 tmp
= TAG(emit_elts
)( ctx
, elts
+start
+1, 1, tmp
);
814 tmp
= TAG(emit_elts
)( ctx
, elts
+start
, 1, tmp
);
819 /* TODO: Try to emit as indexed lines */
820 fprintf(stderr
, "%s - cannot draw primitive\n", __FUNCTION__
);
826 /* For verts, we still eliminate the copy from main memory to dma
827 * buffers. For elts, this is probably no better (worse?) than the
830 static void TAG(render_triangles_elts
)( GLcontext
*ctx
,
836 GLuint
*elts
= TNL_CONTEXT(ctx
)->vb
.Elts
;
837 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS()/3*3;
842 ELT_INIT( GL_TRIANGLES
);
844 currentsz
= GET_CURRENT_VB_MAX_ELTS();
846 /* Emit whole number of tris in total. dmasz is already a multiple
849 count
-= (count
-start
)%3;
850 currentsz
-= currentsz
%3;
854 for (j
= start
; j
< count
; j
+= nr
) {
855 nr
= MIN2( currentsz
, count
- j
);
856 TAG(emit_elts
)( ctx
, elts
+j
, nr
, ALLOC_ELTS(nr
) );
864 static void TAG(render_tri_strip_elts
)( GLcontext
*ctx
,
869 if (HAVE_TRI_STRIPS
) {
872 GLuint
*elts
= TNL_CONTEXT(ctx
)->vb
.Elts
;
873 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS();
877 ELT_INIT( GL_TRIANGLE_STRIP
);
879 currentsz
= GET_CURRENT_VB_MAX_ELTS();
884 /* Keep the same winding over multiple buffers:
886 dmasz
-= (dmasz
& 1);
887 currentsz
-= (currentsz
& 1);
889 for (j
= start
; j
+ 2 < count
; j
+= nr
- 2 ) {
890 nr
= MIN2( currentsz
, count
- j
);
891 TAG(emit_elts
)( ctx
, elts
+j
, nr
, ALLOC_ELTS(nr
) );
896 /* TODO: try to emit as indexed triangles */
897 fprintf(stderr
, "%s - cannot draw primitive\n", __FUNCTION__
);
902 static void TAG(render_tri_fan_elts
)( GLcontext
*ctx
,
909 GLuint
*elts
= TNL_CONTEXT(ctx
)->vb
.Elts
;
911 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS();
915 ELT_INIT( GL_TRIANGLE_FAN
);
917 currentsz
= GET_CURRENT_VB_MAX_ELTS();
922 for (j
= start
+ 1 ; j
+ 1 < count
; j
+= nr
- 1 ) {
924 nr
= MIN2( currentsz
, count
- j
+ 1 );
925 tmp
= ALLOC_ELTS( nr
);
926 tmp
= TAG(emit_elts
)( ctx
, elts
+start
, 1, tmp
);
927 tmp
= TAG(emit_elts
)( ctx
, elts
+j
, nr
- 1, tmp
);
932 /* TODO: try to emit as indexed triangles */
933 fprintf(stderr
, "%s - cannot draw primitive\n", __FUNCTION__
);
939 static void TAG(render_poly_elts
)( GLcontext
*ctx
,
946 GLuint
*elts
= TNL_CONTEXT(ctx
)->vb
.Elts
;
948 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS();
952 ELT_INIT( GL_POLYGON
);
954 currentsz
= GET_CURRENT_VB_MAX_ELTS();
959 for (j
= start
+ 1 ; j
+ 1 < count
; j
+= nr
- 1 ) {
961 nr
= MIN2( currentsz
, count
- j
+ 1 );
962 tmp
= ALLOC_ELTS( nr
);
963 tmp
= TAG(emit_elts
)( ctx
, elts
+start
, 1, tmp
);
964 tmp
= TAG(emit_elts
)( ctx
, elts
+j
, nr
- 1, tmp
);
968 } else if (HAVE_TRI_FANS
&& !(ctx
->_TriangleCaps
& DD_FLATSHADE
)) {
969 TAG(render_tri_fan_verts
)( ctx
, start
, count
, flags
);
971 fprintf(stderr
, "%s - cannot draw primitive\n", __FUNCTION__
);
976 static void TAG(render_quad_strip_elts
)( GLcontext
*ctx
,
981 if (HAVE_QUAD_STRIPS
&& 0) {
983 else if (HAVE_TRI_STRIPS
) {
985 GLuint
*elts
= TNL_CONTEXT(ctx
)->vb
.Elts
;
986 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS();
991 currentsz
= GET_CURRENT_VB_MAX_ELTS();
993 /* Emit whole number of quads in total, and in each buffer.
996 count
-= (count
-start
) & 1;
997 currentsz
-= currentsz
& 1;
1002 if (ctx
->_TriangleCaps
& DD_FLATSHADE
) {
1003 ELT_INIT( GL_TRIANGLES
);
1005 currentsz
= currentsz
/6*2;
1008 for (j
= start
; j
+ 3 < count
; j
+= nr
- 2 ) {
1009 nr
= MIN2( currentsz
, count
- j
);
1014 GLint quads
= (nr
/2)-1;
1015 void *buf
= ALLOC_ELTS( quads
*6 );
1018 for ( i
= j
-start
; i
< j
-start
+quads
; i
++, elts
+= 2 ) {
1019 EMIT_TWO_ELTS( 0, elts
[0], elts
[1] );
1020 EMIT_TWO_ELTS( 2, elts
[2], elts
[1] );
1021 EMIT_TWO_ELTS( 4, elts
[3], elts
[2] );
1032 ELT_INIT( GL_TRIANGLE_STRIP
);
1034 for (j
= start
; j
+ 3 < count
; j
+= nr
- 2 ) {
1035 nr
= MIN2( currentsz
, count
- j
);
1036 TAG(emit_elts
)( ctx
, elts
+j
, nr
, ALLOC_ELTS(nr
) );
1045 static void TAG(render_quads_elts
)( GLcontext
*ctx
,
1052 GLuint
*elts
= TNL_CONTEXT(ctx
)->vb
.Elts
;
1053 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS()/4*4;
1058 ELT_INIT( GL_TRIANGLES
);
1060 currentsz
= GET_CURRENT_VB_MAX_ELTS()/4*4;
1062 count
-= (count
-start
)%4;
1067 for (j
= start
; j
< count
; j
+= nr
) {
1068 nr
= MIN2( currentsz
, count
- j
);
1069 TAG(emit_elts
)( ctx
, elts
+j
, nr
, ALLOC_ELTS(nr
) );
1075 GLuint
*elts
= TNL_CONTEXT(ctx
)->vb
.Elts
;
1076 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS();
1080 ELT_INIT( GL_TRIANGLES
);
1081 currentsz
= GET_CURRENT_VB_MAX_ELTS();
1083 /* Emit whole number of quads in total, and in each buffer.
1086 count
-= (count
-start
) & 3;
1087 currentsz
-= currentsz
& 3;
1089 /* Adjust for rendering as triangles:
1091 currentsz
= currentsz
/6*4;
1097 for (j
= start
; j
+ 3 < count
; j
+= nr
- 2 ) {
1098 nr
= MIN2( currentsz
, count
- j
);
1104 void *buf
= ALLOC_ELTS( quads
* 6 );
1107 for ( i
= j
-start
; i
< j
-start
+quads
; i
++, elts
+= 4 ) {
1108 EMIT_TWO_ELTS( 0, elts
[0], elts
[1] );
1109 EMIT_TWO_ELTS( 2, elts
[3], elts
[1] );
1110 EMIT_TWO_ELTS( 4, elts
[2], elts
[3] );
1124 static render_func
TAG(render_tab_elts
)[GL_POLYGON
+2] =
1126 TAG(render_points_elts
),
1127 TAG(render_lines_elts
),
1128 TAG(render_line_loop_elts
),
1129 TAG(render_line_strip_elts
),
1130 TAG(render_triangles_elts
),
1131 TAG(render_tri_strip_elts
),
1132 TAG(render_tri_fan_elts
),
1133 TAG(render_quads_elts
),
1134 TAG(render_quad_strip_elts
),
1135 TAG(render_poly_elts
),
1148 /* Prevent fallbacks later on.
1150 static GLboolean
TAG(validate_render
)( GLcontext
*ctx
,
1151 struct vertex_buffer
*VB
)
1158 if (VB
->Elts
&& !HAVE_ELTS
)
1161 for (i
= 0 ; i
< VB
->PrimitiveCount
; i
++) {
1162 GLuint prim
= VB
->Primitive
[i
].mode
;
1163 GLuint count
= VB
->Primitive
[i
].count
;
1164 GLboolean ok
= GL_FALSE
;
1169 switch (prim
& PRIM_MODE_MASK
) {
1174 ok
= HAVE_LINES
&& !ctx
->Line
.StippleFlag
;
1177 ok
= HAVE_LINE_STRIPS
&& !ctx
->Line
.StippleFlag
;
1180 ok
= HAVE_LINE_STRIPS
&& !ctx
->Line
.StippleFlag
;
1183 ok
= HAVE_TRIANGLES
;
1185 case GL_TRIANGLE_STRIP
:
1186 ok
= HAVE_TRI_STRIPS
;
1188 case GL_TRIANGLE_FAN
:
1192 if (HAVE_POLYGONS
) {
1196 ok
= (HAVE_TRI_FANS
&& !(ctx
->_TriangleCaps
& DD_FLATSHADE
));
1200 ok
= HAVE_TRI_STRIPS
;
1202 else if (HAVE_QUAD_STRIPS
) {
1204 } else if (HAVE_TRI_STRIPS
&& (ctx
->_TriangleCaps
& DD_FLATSHADE
)) {
1206 ok
= count
< GET_SUBSEQUENT_VB_MAX_ELTS();
1213 ok
= HAVE_TRI_STRIPS
;
1218 } else if (HAVE_ELTS
) {
1219 ok
= count
< GET_SUBSEQUENT_VB_MAX_ELTS();
1229 if (!ok
) return GL_FALSE
;