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.
40 #if !defined(HAVE_TRIANGLES)
41 #error "must have at least triangles to use render template"
45 #define ELTS_VARS(buf)
46 #define ALLOC_ELTS(nr) 0
47 #define EMIT_ELT( offset, elt )
48 #define EMIT_TWO_ELTS( offset, elt0, elt1 )
49 #define INCR_ELTS( nr )
50 #define ELT_INIT(prim)
51 #define GET_CURRENT_VB_MAX_ELTS() 0
52 #define GET_SUBSEQUENT_VB_MAX_ELTS() 0
53 #define RELEASE_ELT_VERTS()
54 #define EMIT_INDEXED_VERTS( ctx, start, count )
58 #define EMIT_TWO_ELTS( offset, elt0, elt1 ) \
60 EMIT_ELT( offset, elt0 ); \
61 EMIT_ELT( offset+1, elt1 ); \
66 /**********************************************************************/
67 /* Render whole begin/end objects */
68 /**********************************************************************/
74 static void *TAG(emit_elts
)( GLcontext
*ctx
, GLuint
*elts
, GLuint nr
,
81 for ( i
= 0 ; i
+1 < nr
; i
+=2, elts
+= 2 ) {
82 EMIT_TWO_ELTS( 0, elts
[0], elts
[1] );
87 EMIT_ELT( 0, elts
[0] );
91 return (void *)ELTPTR
;
95 static __inline
void *TAG(emit_verts
)( GLcontext
*ctx
, GLuint start
,
96 GLuint count
, void *buf
)
98 return EMIT_VERTS(ctx
, start
, count
, buf
);
101 /***********************************************************************
102 * Render non-indexed primitives.
103 ***********************************************************************/
105 static void TAG(render_points_verts
)( GLcontext
*ctx
,
112 int dmasz
= GET_SUBSEQUENT_VB_MAX_VERTS();
118 currentsz
= GET_CURRENT_VB_MAX_VERTS();
122 for (j
= start
; j
< count
; j
+= nr
) {
123 nr
= MIN2( currentsz
, count
- j
);
124 TAG(emit_verts
)( ctx
, j
, nr
, ALLOC_VERTS(nr
) );
129 fprintf(stderr
, "%s - cannot draw primitive\n", __FUNCTION__
);
134 static void TAG(render_lines_verts
)( GLcontext
*ctx
,
141 int dmasz
= GET_SUBSEQUENT_VB_MAX_VERTS();
147 /* Emit whole number of lines in total and in each buffer:
149 count
-= (count
-start
) & 1;
150 currentsz
= GET_CURRENT_VB_MAX_VERTS();
151 currentsz
-= currentsz
& 1;
157 for (j
= start
; j
< count
; j
+= nr
) {
158 nr
= MIN2( currentsz
, count
- j
);
159 TAG(emit_verts
)( ctx
, j
, nr
, ALLOC_VERTS(nr
) );
164 fprintf(stderr
, "%s - cannot draw primitive\n", __FUNCTION__
);
170 static void TAG(render_line_strip_verts
)( GLcontext
*ctx
,
175 if (HAVE_LINE_STRIPS
) {
177 int dmasz
= GET_SUBSEQUENT_VB_MAX_VERTS();
181 INIT( GL_LINE_STRIP
);
183 currentsz
= GET_CURRENT_VB_MAX_VERTS();
187 for (j
= start
; j
+ 1 < count
; j
+= nr
- 1 ) {
188 nr
= MIN2( currentsz
, count
- j
);
189 TAG(emit_verts
)( ctx
, j
, nr
, ALLOC_VERTS(nr
) );
196 fprintf(stderr
, "%s - cannot draw primitive\n", __FUNCTION__
);
202 static void TAG(render_line_loop_verts
)( GLcontext
*ctx
,
207 if (HAVE_LINE_STRIPS
) {
209 int dmasz
= GET_SUBSEQUENT_VB_MAX_VERTS();
213 INIT( GL_LINE_STRIP
);
215 if (flags
& PRIM_BEGIN
)
220 /* Ensure last vertex won't wrap buffers:
222 currentsz
= GET_CURRENT_VB_MAX_VERTS();
231 for ( ; j
+ 1 < count
; j
+= nr
- 1 ) {
232 nr
= MIN2( currentsz
, count
- j
);
234 if (j
+ nr
>= count
&&
239 tmp
= ALLOC_VERTS(nr
+1);
240 tmp
= TAG(emit_verts
)( ctx
, j
, nr
, tmp
);
241 tmp
= TAG(emit_verts
)( ctx
, start
, 1, tmp
);
244 TAG(emit_verts
)( ctx
, j
, nr
, ALLOC_VERTS(nr
) );
250 else if (start
+ 1 < count
&& (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
);
260 fprintf(stderr
, "%s - cannot draw primitive\n", __FUNCTION__
);
266 static void TAG(render_triangles_verts
)( GLcontext
*ctx
,
272 int dmasz
= (GET_SUBSEQUENT_VB_MAX_VERTS()/3) * 3;
278 currentsz
= (GET_CURRENT_VB_MAX_VERTS()/3) * 3;
280 /* Emit whole number of tris in total. dmasz is already a multiple
283 count
-= (count
-start
)%3;
288 for (j
= start
; j
< count
; j
+= nr
) {
289 nr
= MIN2( currentsz
, count
- j
);
290 TAG(emit_verts
)( ctx
, j
, nr
, ALLOC_VERTS(nr
) );
297 static void TAG(render_tri_strip_verts
)( GLcontext
*ctx
,
302 if (HAVE_TRI_STRIPS
) {
305 int dmasz
= GET_SUBSEQUENT_VB_MAX_VERTS();
308 INIT(GL_TRIANGLE_STRIP
);
310 currentsz
= GET_CURRENT_VB_MAX_VERTS();
316 /* From here on emit even numbers of tris when wrapping over buffers:
318 dmasz
-= (dmasz
& 1);
319 currentsz
-= (currentsz
& 1);
321 for (j
= start
; j
+ 2 < count
; j
+= nr
- 2 ) {
322 nr
= MIN2( currentsz
, count
- j
);
323 TAG(emit_verts
)( ctx
, j
, nr
, ALLOC_VERTS(nr
) );
330 fprintf(stderr
, "%s - cannot draw primitive\n", __FUNCTION__
);
335 static void TAG(render_tri_fan_verts
)( GLcontext
*ctx
,
343 int dmasz
= GET_SUBSEQUENT_VB_MAX_VERTS();
346 INIT(GL_TRIANGLE_FAN
);
348 currentsz
= GET_CURRENT_VB_MAX_VERTS();
353 for (j
= start
+ 1 ; j
+ 1 < count
; j
+= nr
- 2 ) {
355 nr
= MIN2( currentsz
, count
- j
+ 1 );
356 tmp
= ALLOC_VERTS( nr
);
357 tmp
= TAG(emit_verts
)( ctx
, start
, 1, tmp
);
358 tmp
= TAG(emit_verts
)( ctx
, j
, nr
- 1, tmp
);
365 /* Could write code to emit these as indexed vertices (for the
366 * g400, for instance).
368 fprintf(stderr
, "%s - cannot draw primitive\n", __FUNCTION__
);
374 static void TAG(render_poly_verts
)( GLcontext
*ctx
,
382 int dmasz
= GET_SUBSEQUENT_VB_MAX_VERTS();
387 currentsz
= GET_CURRENT_VB_MAX_VERTS();
392 for (j
= start
+ 1 ; j
+ 1 < count
; j
+= nr
- 2 ) {
394 nr
= MIN2( currentsz
, count
- j
+ 1 );
395 tmp
= ALLOC_VERTS( nr
);
396 tmp
= TAG(emit_verts
)( ctx
, start
, 1, tmp
);
397 tmp
= TAG(emit_verts
)( ctx
, j
, nr
- 1, tmp
);
403 else if (HAVE_TRI_FANS
&& !(ctx
->_TriangleCaps
& DD_FLATSHADE
)) {
404 TAG(render_tri_fan_verts
)( ctx
, start
, count
, flags
);
406 fprintf(stderr
, "%s - cannot draw primitive\n", __FUNCTION__
);
411 static void TAG(render_quad_strip_verts
)( GLcontext
*ctx
,
418 if (HAVE_QUAD_STRIPS
) {
421 int dmasz
= GET_SUBSEQUENT_VB_MAX_VERTS();
426 currentsz
= GET_CURRENT_VB_MAX_VERTS();
431 dmasz
-= (dmasz
& 2);
432 currentsz
-= (currentsz
& 2);
434 for (j
= start
; j
+ 3 < count
; j
+= nr
- 2 ) {
435 nr
= MIN2( currentsz
, count
- j
);
436 TAG(emit_verts
)( ctx
, j
, nr
, ALLOC_VERTS(nr
) );
442 } else if (HAVE_TRI_STRIPS
&&
443 (ctx
->_TriangleCaps
& DD_FLATSHADE
) &&
444 TNL_CONTEXT(ctx
)->vb
.ColorPtr
[0]->stride
) {
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
495 * available - should never happen.
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
) );
565 else if (HAVE_ELTS
) {
566 /* Hardware doesn't have a quad primitive type -- try to
567 * simulate it using indexed vertices and the triangle
571 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS();
575 EMIT_INDEXED_VERTS( ctx
, start
, count
);
578 ELT_INIT( GL_TRIANGLES
);
579 currentsz
= GET_CURRENT_VB_MAX_ELTS();
581 /* Emit whole number of quads in total, and in each buffer.
584 count
-= (count
-start
) & 3;
585 currentsz
-= currentsz
& 3;
587 /* Adjust for rendering as triangles:
589 currentsz
= currentsz
/6*4;
595 for (j
= start
; j
< count
; j
+= nr
) {
596 nr
= MIN2( currentsz
, count
- j
);
600 ELTS_VARS( ALLOC_ELTS( quads
*6 ) );
602 for ( i
= j
-start
; i
< j
-start
+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
= start
; j
< count
-3; j
+= 4) {
627 void *tmp
= ALLOC_VERTS( 6 );
630 tmp
= EMIT_VERTS(ctx
, j
, 2, tmp
);
631 tmp
= EMIT_VERTS(ctx
, j
+ 3, 1, tmp
);
634 tmp
= EMIT_VERTS(ctx
, j
+ 1, 3, tmp
);
638 /* Vertices won't fit in a single buffer, should never happen.
640 fprintf(stderr
, "%s - cannot draw primitive\n", __FUNCTION__
);
645 static void TAG(render_noop
)( GLcontext
*ctx
,
655 static tnl_render_func
TAG(render_tab_verts
)[GL_POLYGON
+2] =
657 TAG(render_points_verts
),
658 TAG(render_lines_verts
),
659 TAG(render_line_loop_verts
),
660 TAG(render_line_strip_verts
),
661 TAG(render_triangles_verts
),
662 TAG(render_tri_strip_verts
),
663 TAG(render_tri_fan_verts
),
664 TAG(render_quads_verts
),
665 TAG(render_quad_strip_verts
),
666 TAG(render_poly_verts
),
671 /****************************************************************************
672 * Render elts using hardware indexed verts *
673 ****************************************************************************/
676 static void TAG(render_points_elts
)( GLcontext
*ctx
,
683 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS();
685 GLuint
*elts
= TNL_CONTEXT(ctx
)->vb
.Elts
;
688 ELT_INIT( GL_POINTS
);
690 currentsz
= GET_CURRENT_VB_MAX_ELTS();
694 for (j
= start
; j
< count
; j
+= nr
) {
695 nr
= MIN2( currentsz
, count
- j
);
696 TAG(emit_elts
)( ctx
, elts
+j
, nr
, ALLOC_ELTS(nr
) );
701 fprintf(stderr
, "%s - cannot draw primitive\n", __FUNCTION__
);
708 static void TAG(render_lines_elts
)( GLcontext
*ctx
,
715 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS();
717 GLuint
*elts
= TNL_CONTEXT(ctx
)->vb
.Elts
;
720 ELT_INIT( GL_LINES
);
722 /* Emit whole number of lines in total and in each buffer:
724 count
-= (count
-start
) & 1;
725 currentsz
-= currentsz
& 1;
728 currentsz
= GET_CURRENT_VB_MAX_ELTS();
732 for (j
= start
; j
< count
; j
+= nr
) {
733 nr
= MIN2( currentsz
, count
- j
);
734 TAG(emit_elts
)( ctx
, elts
+j
, nr
, ALLOC_ELTS(nr
) );
739 fprintf(stderr
, "%s - cannot draw primitive\n", __FUNCTION__
);
745 static void TAG(render_line_strip_elts
)( GLcontext
*ctx
,
750 if (HAVE_LINE_STRIPS
) {
752 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS();
754 GLuint
*elts
= TNL_CONTEXT(ctx
)->vb
.Elts
;
757 FLUSH(); /* always a new primitive */
758 ELT_INIT( GL_LINE_STRIP
);
760 currentsz
= GET_CURRENT_VB_MAX_ELTS();
764 for (j
= start
; j
+ 1 < count
; j
+= nr
- 1 ) {
765 nr
= MIN2( currentsz
, count
- j
);
766 TAG(emit_elts
)( ctx
, elts
+j
, nr
, ALLOC_ELTS(nr
) );
771 /* TODO: Try to emit as indexed lines.
773 fprintf(stderr
, "%s - cannot draw primitive\n", __FUNCTION__
);
779 static void TAG(render_line_loop_elts
)( GLcontext
*ctx
,
784 if (HAVE_LINE_STRIPS
) {
786 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS();
788 GLuint
*elts
= TNL_CONTEXT(ctx
)->vb
.Elts
;
792 ELT_INIT( GL_LINE_STRIP
);
794 if (flags
& PRIM_BEGIN
)
799 currentsz
= GET_CURRENT_VB_MAX_ELTS();
804 /* Ensure last vertex doesn't wrap:
810 for ( ; j
+ 1 < count
; j
+= nr
- 1 ) {
811 nr
= MIN2( currentsz
, count
- j
);
813 if (j
+ nr
>= count
&&
818 tmp
= ALLOC_ELTS(nr
+1);
819 tmp
= TAG(emit_elts
)( ctx
, elts
+j
, nr
, tmp
);
820 tmp
= TAG(emit_elts
)( ctx
, elts
+start
, 1, tmp
);
823 TAG(emit_elts
)( ctx
, elts
+j
, nr
, ALLOC_ELTS(nr
) );
829 else if (start
+ 1 < count
&& (flags
& PRIM_END
)) {
832 tmp
= TAG(emit_elts
)( ctx
, elts
+start
+1, 1, tmp
);
833 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", __FUNCTION__
);
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
)( GLcontext
*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
868 count
-= (count
-start
)%3;
869 currentsz
-= currentsz
%3;
873 for (j
= start
; j
< count
; j
+= nr
) {
874 nr
= MIN2( currentsz
, count
- j
);
875 TAG(emit_elts
)( ctx
, elts
+j
, nr
, ALLOC_ELTS(nr
) );
883 static void TAG(render_tri_strip_elts
)( GLcontext
*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
= start
; j
+ 2 < count
; j
+= nr
- 2 ) {
909 nr
= MIN2( currentsz
, count
- j
);
910 TAG(emit_elts
)( ctx
, elts
+j
, nr
, ALLOC_ELTS(nr
) );
915 /* TODO: try to emit as indexed triangles */
916 fprintf(stderr
, "%s - cannot draw primitive\n", __FUNCTION__
);
921 static void TAG(render_tri_fan_elts
)( GLcontext
*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
= start
+ 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
+j
, nr
- 1, tmp
);
951 /* TODO: try to emit as indexed triangles */
952 fprintf(stderr
, "%s - cannot draw primitive\n", __FUNCTION__
);
958 static void TAG(render_poly_elts
)( GLcontext
*ctx
,
965 GLuint
*elts
= TNL_CONTEXT(ctx
)->vb
.Elts
;
967 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS();
971 ELT_INIT( GL_POLYGON
);
973 currentsz
= GET_CURRENT_VB_MAX_ELTS();
978 for (j
= start
+ 1 ; j
+ 1 < count
; j
+= nr
- 2 ) {
980 nr
= MIN2( currentsz
, count
- j
+ 1 );
981 tmp
= ALLOC_ELTS( nr
);
982 tmp
= TAG(emit_elts
)( ctx
, elts
+start
, 1, tmp
);
983 tmp
= TAG(emit_elts
)( ctx
, elts
+j
, nr
- 1, tmp
);
987 } else if (HAVE_TRI_FANS
&& !(ctx
->_TriangleCaps
& DD_FLATSHADE
)) {
988 TAG(render_tri_fan_verts
)( ctx
, start
, count
, flags
);
990 fprintf(stderr
, "%s - cannot draw primitive\n", __FUNCTION__
);
995 static void TAG(render_quad_strip_elts
)( GLcontext
*ctx
,
1000 if (HAVE_QUAD_STRIPS
&& 0) {
1002 else if (HAVE_TRI_STRIPS
) {
1004 GLuint
*elts
= TNL_CONTEXT(ctx
)->vb
.Elts
;
1005 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS();
1010 currentsz
= GET_CURRENT_VB_MAX_ELTS();
1012 /* Emit whole number of quads in total, and in each buffer.
1015 count
-= (count
-start
) & 1;
1016 currentsz
-= currentsz
& 1;
1021 if (ctx
->_TriangleCaps
& DD_FLATSHADE
) {
1022 ELT_INIT( GL_TRIANGLES
);
1024 currentsz
= currentsz
/6*2;
1027 for (j
= start
; j
+ 3 < count
; j
+= nr
- 2 ) {
1028 nr
= MIN2( currentsz
, count
- j
);
1033 GLint quads
= (nr
/2)-1;
1034 ELTS_VARS( ALLOC_ELTS( quads
*6 ) );
1036 for ( i
= j
-start
; i
< j
-start
+quads
; i
++, elts
+= 2 ) {
1037 EMIT_TWO_ELTS( 0, elts
[0], elts
[1] );
1038 EMIT_TWO_ELTS( 2, elts
[2], elts
[1] );
1039 EMIT_TWO_ELTS( 4, elts
[3], elts
[2] );
1050 ELT_INIT( GL_TRIANGLE_STRIP
);
1052 for (j
= start
; j
+ 3 < count
; j
+= nr
- 2 ) {
1053 nr
= MIN2( currentsz
, count
- j
);
1054 TAG(emit_elts
)( ctx
, elts
+j
, nr
, ALLOC_ELTS(nr
) );
1063 static void TAG(render_quads_elts
)( GLcontext
*ctx
,
1070 GLuint
*elts
= TNL_CONTEXT(ctx
)->vb
.Elts
;
1071 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS()/4*4;
1076 ELT_INIT( GL_TRIANGLES
);
1078 currentsz
= GET_CURRENT_VB_MAX_ELTS()/4*4;
1080 count
-= (count
-start
)%4;
1085 for (j
= start
; j
< count
; j
+= nr
) {
1086 nr
= MIN2( currentsz
, count
- j
);
1087 TAG(emit_elts
)( ctx
, elts
+j
, nr
, ALLOC_ELTS(nr
) );
1093 GLuint
*elts
= TNL_CONTEXT(ctx
)->vb
.Elts
;
1094 int dmasz
= GET_SUBSEQUENT_VB_MAX_ELTS();
1098 ELT_INIT( GL_TRIANGLES
);
1099 currentsz
= GET_CURRENT_VB_MAX_ELTS();
1101 /* Emit whole number of quads in total, and in each buffer.
1104 count
-= (count
-start
) & 3;
1105 currentsz
-= currentsz
& 3;
1107 /* Adjust for rendering as triangles:
1109 currentsz
= currentsz
/6*4;
1115 for (j
= start
; j
+ 3 < count
; j
+= nr
- 2 ) {
1116 nr
= MIN2( currentsz
, count
- j
);
1122 ELTS_VARS( ALLOC_ELTS( quads
* 6 ) );
1124 for ( i
= j
-start
; i
< j
-start
+quads
; i
++, elts
+= 4 ) {
1125 EMIT_TWO_ELTS( 0, elts
[0], elts
[1] );
1126 EMIT_TWO_ELTS( 2, elts
[3], elts
[1] );
1127 EMIT_TWO_ELTS( 4, elts
[2], elts
[3] );
1141 static tnl_render_func
TAG(render_tab_elts
)[GL_POLYGON
+2] =
1143 TAG(render_points_elts
),
1144 TAG(render_lines_elts
),
1145 TAG(render_line_loop_elts
),
1146 TAG(render_line_strip_elts
),
1147 TAG(render_triangles_elts
),
1148 TAG(render_tri_strip_elts
),
1149 TAG(render_tri_fan_elts
),
1150 TAG(render_quads_elts
),
1151 TAG(render_quad_strip_elts
),
1152 TAG(render_poly_elts
),
1162 /* Pre-check the primitives in the VB to prevent the need for
1163 * fallbacks later on.
1165 static GLboolean
TAG(validate_render
)( GLcontext
*ctx
,
1166 struct vertex_buffer
*VB
)
1170 if (VB
->ClipOrMask
& ~CLIP_CULL_BIT
)
1173 if (VB
->Elts
&& !HAVE_ELTS
)
1176 for (i
= 0 ; i
< VB
->PrimitiveCount
; i
++) {
1177 GLuint prim
= VB
->Primitive
[i
].mode
;
1178 GLuint count
= VB
->Primitive
[i
].count
;
1179 GLboolean ok
= GL_FALSE
;
1184 switch (prim
& PRIM_MODE_MASK
) {
1189 ok
= HAVE_LINES
&& !ctx
->Line
.StippleFlag
;
1192 ok
= HAVE_LINE_STRIPS
&& !ctx
->Line
.StippleFlag
;
1195 ok
= HAVE_LINE_STRIPS
&& !ctx
->Line
.StippleFlag
;
1198 ok
= HAVE_TRIANGLES
;
1200 case GL_TRIANGLE_STRIP
:
1201 ok
= HAVE_TRI_STRIPS
;
1203 case GL_TRIANGLE_FAN
:
1207 if (HAVE_POLYGONS
) {
1211 ok
= (HAVE_TRI_FANS
&& !(ctx
->_TriangleCaps
& DD_FLATSHADE
));
1215 ok
= HAVE_TRI_STRIPS
;
1217 else if (HAVE_QUAD_STRIPS
) {
1219 } else if (HAVE_TRI_STRIPS
&&
1220 (ctx
->_TriangleCaps
& DD_FLATSHADE
) &&
1221 VB
->ColorPtr
[0]->stride
!= 0) {
1223 ok
= (GLint
) count
< GET_SUBSEQUENT_VB_MAX_ELTS();
1230 ok
= HAVE_TRI_STRIPS
;
1235 } else if (HAVE_ELTS
) {
1236 ok
= (GLint
) count
< GET_SUBSEQUENT_VB_MAX_ELTS();
1239 ok
= HAVE_TRIANGLES
; /* flatshading is ok. */
1247 /* fprintf(stderr, "not ok %s\n", _mesa_lookup_enum_by_nr(prim & PRIM_MODE_MASK)); */