1 /*
2  * Mesa 3-D graphics library
3  *
4  * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
5  *
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:
12  *
13  * The above copyright notice and this permission notice shall be included
14  * in all copies or substantial portions of the Software.
15  *
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.
23  *
24  * Authors:
25  *    Keith Whitwell <keithw@vmware.com>
26  */
27 
28 
29 /**
30  * \file t_dd_dmatmp2.h
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.
35  *
36  */
37 
38 #if !HAVE_TRIANGLES || !HAVE_POINTS || !HAVE_LINES
39 #error "must have points, lines & triangles to use render template"
40 #endif
41 
42 #if !HAVE_TRI_STRIPS || !HAVE_TRI_FANS
43 #error "must have tri strip and fans to use render template"
44 #endif
45 
46 #if !HAVE_LINE_STRIPS
47 #error "must have line strips to use render template"
48 #endif
49 
50 #if !HAVE_POLYGONS
51 #error "must have polygons to use render template"
52 #endif
53 
54 #if !HAVE_ELTS
55 #error "must have elts to use render template"
56 #endif
57 
58 
59 #ifndef EMIT_TWO_ELTS
60 #define EMIT_TWO_ELTS( dest, offset, elt0, elt1 )	\
61 do { 						\
62    (dest)[offset] = (elt0); 			\
63    (dest)[offset+1] = (elt1); 			\
64 } while (0)
65 #endif
66 
67 
68 /**********************************************************************/
69 /*                  Render whole begin/end objects                    */
70 /**********************************************************************/
71 
72 
TAG(emit_elts)73 static ELT_TYPE *TAG(emit_elts)( struct gl_context *ctx,
74 			    ELT_TYPE *dest,
75 			    GLuint *elts, GLuint nr )
76 {
77    GLint i;
78    LOCAL_VARS;
79 
80    for ( i = 0 ; i+1 < nr ; i+=2, elts += 2 ) {
81       EMIT_TWO_ELTS( dest, 0, elts[0], elts[1] );
82       dest += 2;
83    }
84    if (i < nr) {
85       EMIT_ELT( dest, 0, elts[0] );
86       dest += 1;
87    }
88 
89    return dest;
90 }
91 
TAG(emit_consecutive_elts)92 static ELT_TYPE *TAG(emit_consecutive_elts)( struct gl_context *ctx,
93 					ELT_TYPE *dest,
94 					GLuint start, GLuint nr )
95 {
96    GLint i;
97    LOCAL_VARS;
98 
99    for ( i = 0 ; i+1 < nr ; i+=2, start += 2 ) {
100       EMIT_TWO_ELTS( dest, 0, start, start+1 );
101       dest += 2;
102    }
103    if (i < nr) {
104       EMIT_ELT( dest, 0, start );
105       dest += 1;
106    }
107 
108    return dest;
109 }
110 
111 /***********************************************************************
112  *                    Render non-indexed primitives.
113  ***********************************************************************/
114 
115 
116 
TAG(render_points_verts)117 static void TAG(render_points_verts)( struct gl_context *ctx,
118 				      GLuint start,
119 				      GLuint count,
120 				      GLuint flags )
121 {
122    if (start < count) {
123       LOCAL_VARS;
124       if (0) fprintf(stderr, "%s\n", __func__);
125       EMIT_PRIM( ctx, GL_POINTS, HW_POINTS, start, count );
126    }
127 }
128 
TAG(render_lines_verts)129 static void TAG(render_lines_verts)( struct gl_context *ctx,
130 				     GLuint start,
131 				     GLuint count,
132 				     GLuint flags )
133 {
134    LOCAL_VARS;
135    if (0) fprintf(stderr, "%s\n", __func__);
136    count -= (count-start) & 1;
137 
138    if (start+1 >= count)
139       return;
140 
141    if ((flags & PRIM_BEGIN) && ctx->Line.StippleFlag) {
142       RESET_STIPPLE();
143       AUTO_STIPPLE( GL_TRUE );
144    }
145 
146    EMIT_PRIM( ctx, GL_LINES, HW_LINES, start, count );
147 
148    if ((flags & PRIM_END) && ctx->Line.StippleFlag)
149       AUTO_STIPPLE( GL_FALSE );
150 }
151 
152 
TAG(render_line_strip_verts)153 static void TAG(render_line_strip_verts)( struct gl_context *ctx,
154 					  GLuint start,
155 					  GLuint count,
156 					  GLuint flags )
157 {
158    LOCAL_VARS;
159    if (0) fprintf(stderr, "%s\n", __func__);
160 
161    if (start+1 >= count)
162       return;
163 
164    if ((flags & PRIM_BEGIN) && ctx->Line.StippleFlag)
165       RESET_STIPPLE();
166 
167 
168    if (PREFER_DISCRETE_ELT_PRIM( count-start, HW_LINES ))
169    {
170       int dmasz = GET_MAX_HW_ELTS();
171       GLuint j, nr;
172 
173       ELT_INIT( GL_LINES, HW_LINES );
174 
175       /* Emit whole number of lines in each full buffer.
176        */
177       dmasz = dmasz/2;
178 
179 
180       for (j = start; j + 1 < count; j += nr - 1 ) {
181 	 ELT_TYPE *dest;
182 	 GLint i;
183 
184 	 nr = MIN2( dmasz, count - j );
185 	 dest = ALLOC_ELTS( (nr-1)*2 );
186 
187 	 for ( i = j ; i+1 < j+nr ; i+=1 ) {
188 	    EMIT_TWO_ELTS( dest, 0, (i+0), (i+1) );
189 	    dest += 2;
190 	 }
191 
192 	 CLOSE_ELTS();
193       }
194    }
195    else
196       EMIT_PRIM( ctx, GL_LINE_STRIP, HW_LINE_STRIP, start, count );
197 }
198 
199 
TAG(render_line_loop_verts)200 static void TAG(render_line_loop_verts)( struct gl_context *ctx,
201 					 GLuint start,
202 					 GLuint count,
203 					 GLuint flags )
204 {
205    LOCAL_VARS;
206    GLuint j, nr;
207    if (0) fprintf(stderr, "%s\n", __func__);
208 
209    if (flags & PRIM_BEGIN) {
210       j = start;
211       if (ctx->Line.StippleFlag)
212 	 RESET_STIPPLE( );
213    }
214    else
215       j = start + 1;
216 
217    if (flags & PRIM_END) {
218 
219       if (start+1 >= count)
220 	 return;
221 
222       if (PREFER_DISCRETE_ELT_PRIM( count-start, HW_LINES )) {
223 	 int dmasz = GET_MAX_HW_ELTS();
224 
225 	 ELT_INIT( GL_LINES, HW_LINES );
226 
227 	 /* Emit whole number of lines in each full buffer.
228 	  */
229 	 dmasz = dmasz/2;
230 
231 	 /* Ensure last vertex doesn't wrap:
232 	  */
233 	 dmasz--;
234 
235 	 for (; j + 1 < count;  ) {
236 	    GLint i;
237 	    ELT_TYPE *dest;
238 
239 	    nr = MIN2( dmasz, count - j );
240 	    dest = ALLOC_ELTS( nr*2 );	/* allocs room for 1 more line */
241 
242 	    for ( i = 0 ; i < nr - 1 ; i+=1 ) {
243 	       EMIT_TWO_ELTS( dest, 0, (j+i), (j+i+1) );
244 	       dest += 2;
245 	    }
246 
247 	    j += nr - 1;
248 
249 	    /* Emit 1 more line into space alloced above */
250 	    if (j + 1 >= count) {
251  	       EMIT_TWO_ELTS( dest, 0, (j), (start) );
252  	       dest += 2;
253  	    }
254 
255 	    CLOSE_ELTS();
256 	 }
257       }
258       else
259       {
260 	 int dmasz = GET_MAX_HW_ELTS() - 1;
261 
262 	 ELT_INIT( GL_LINE_STRIP, HW_LINE_STRIP );
263 
264 	 for ( ; j + 1 < count;  ) {
265 	    nr = MIN2( dmasz, count - j );
266 	    if (j + nr < count) {
267 	       ELT_TYPE *dest = ALLOC_ELTS( nr );
268 	       dest = TAG(emit_consecutive_elts)( ctx, dest, j, nr );
269 	       (void) dest;
270 	       j += nr - 1;
271 	       CLOSE_ELTS();
272 	    }
273 	    else if (nr) {
274 	       ELT_TYPE *dest = ALLOC_ELTS( nr + 1 );
275 	       dest = TAG(emit_consecutive_elts)( ctx, dest, j, nr );
276 	       dest = TAG(emit_consecutive_elts)( ctx, dest, start, 1 );
277 	       (void) dest;
278 	       j += nr;
279 	       CLOSE_ELTS();
280 	    }
281 	 }
282       }
283    } else {
284       TAG(render_line_strip_verts)( ctx, j, count, flags );
285    }
286 }
287 
288 
TAG(render_triangles_verts)289 static void TAG(render_triangles_verts)( struct gl_context *ctx,
290 					 GLuint start,
291 					 GLuint count,
292 					 GLuint flags )
293 {
294    LOCAL_VARS;
295    if (0) fprintf(stderr, "%s\n", __func__);
296 
297    count -= (count-start)%3;
298 
299    if (start+2 >= count) {
300       return;
301    }
302 
303    /* need a PREFER_DISCRETE_ELT_PRIM here too..
304     */
305    EMIT_PRIM( ctx, GL_TRIANGLES, HW_TRIANGLES, start, count );
306 }
307 
308 
309 
TAG(render_tri_strip_verts)310 static void TAG(render_tri_strip_verts)( struct gl_context *ctx,
311 					 GLuint start,
312 					 GLuint count,
313 					 GLuint flags )
314 {
315    LOCAL_VARS;
316    if (0) fprintf(stderr, "%s\n", __func__);
317 
318    if (start + 2 >= count)
319       return;
320 
321    if (PREFER_DISCRETE_ELT_PRIM( count-start, HW_TRIANGLES ))
322    {
323       int dmasz = GET_MAX_HW_ELTS();
324       int parity = 0;
325       GLuint j, nr;
326 
327       ELT_INIT( GL_TRIANGLES, HW_TRIANGLES );
328 
329       /* Emit even number of tris in each full buffer.
330        */
331       dmasz = dmasz/3;
332       dmasz -= dmasz & 1;
333 
334       for (j = start; j + 2 < count; j += nr - 2 ) {
335 	 ELT_TYPE *dest;
336 	 GLint i;
337 
338 	 nr = MIN2( dmasz, count - j );
339 	 dest = ALLOC_ELTS( (nr-2)*3 );
340 
341 	 for ( i = j ; i+2 < j+nr ; i++, parity^=1 ) {
342 	    EMIT_ELT( dest, 0, (i+0+parity) );
343 	    EMIT_ELT( dest, 1, (i+1-parity) );
344 	    EMIT_ELT( dest, 2, (i+2) );
345 	    dest += 3;
346 	 }
347 
348 	 CLOSE_ELTS();
349       }
350    }
351    else
352       EMIT_PRIM( ctx, GL_TRIANGLE_STRIP, HW_TRIANGLE_STRIP_0, start, count );
353 }
354 
TAG(render_tri_fan_verts)355 static void TAG(render_tri_fan_verts)( struct gl_context *ctx,
356 				       GLuint start,
357 				       GLuint count,
358 				       GLuint flags )
359 {
360    LOCAL_VARS;
361    if (0) fprintf(stderr, "%s\n", __func__);
362 
363    if (start+2 >= count)
364       return;
365 
366    if (PREFER_DISCRETE_ELT_PRIM( count-start, HW_TRIANGLES ))
367    {
368       int dmasz = GET_MAX_HW_ELTS();
369       GLuint j, nr;
370 
371       ELT_INIT( GL_TRIANGLES, HW_TRIANGLES );
372 
373       dmasz = dmasz/3;
374 
375       for (j = start + 1; j + 1 < count; j += nr - 1 ) {
376 	 ELT_TYPE *dest;
377 	 GLint i;
378 
379 	 nr = MIN2( dmasz, count - j );
380 	 dest = ALLOC_ELTS( (nr-1)*3 );
381 
382 	 for ( i = j ; i+1 < j+nr ; i++ ) {
383 	    EMIT_ELT( dest, 0, (start) );
384 	    EMIT_ELT( dest, 1, (i) );
385 	    EMIT_ELT( dest, 2, (i+1) );
386 	    dest += 3;
387 	 }
388 
389 	 CLOSE_ELTS();
390       }
391    }
392    else {
393       EMIT_PRIM( ctx, GL_TRIANGLE_FAN, HW_TRIANGLE_FAN, start, count );
394    }
395 }
396 
397 
TAG(render_poly_verts)398 static void TAG(render_poly_verts)( struct gl_context *ctx,
399 				    GLuint start,
400 				    GLuint count,
401 				    GLuint flags )
402 {
403    LOCAL_VARS;
404    if (0) fprintf(stderr, "%s\n", __func__);
405 
406    if (start+2 >= count)
407       return;
408 
409    EMIT_PRIM( ctx, GL_POLYGON, HW_POLYGON, start, count );
410 }
411 
TAG(render_quad_strip_verts)412 static void TAG(render_quad_strip_verts)( struct gl_context *ctx,
413 					  GLuint start,
414 					  GLuint count,
415 					  GLuint flags )
416 {
417    LOCAL_VARS;
418    if (0) fprintf(stderr, "%s\n", __func__);
419 
420    count -= (count-start) & 1;
421 
422    if (start+3 >= count)
423       return;
424 
425    if (HAVE_QUAD_STRIPS) {
426       EMIT_PRIM( ctx, GL_QUAD_STRIP, HW_QUAD_STRIP, start, count );
427    }
428    else if (ctx->Light.ShadeModel == GL_FLAT) {
429       LOCAL_VARS;
430       int dmasz = GET_MAX_HW_ELTS();
431       GLuint j, nr;
432 
433       ELT_INIT( GL_TRIANGLES, HW_TRIANGLES );
434 
435       /* Emit whole number of quads in total, and in each buffer.
436        */
437       dmasz = (dmasz/6)*2;
438 
439       for (j = start; j + 3 < count; j += nr - 2 ) {
440 	 ELT_TYPE *dest;
441 	 GLint quads, i;
442 
443 	 nr = MIN2( dmasz, count - j );
444 	 quads = (nr/2)-1;
445 	 dest = ALLOC_ELTS( quads*6 );
446 
447 	 for ( i = j ; i < j+quads*2 ; i+=2 ) {
448 	    EMIT_TWO_ELTS( dest, 0, (i+0), (i+1) );
449 	    EMIT_TWO_ELTS( dest, 2, (i+2), (i+1) );
450 	    EMIT_TWO_ELTS( dest, 4, (i+3), (i+2) );
451 	    dest += 6;
452 	 }
453 
454 	 CLOSE_ELTS();
455       }
456    }
457    else {
458       EMIT_PRIM( ctx, GL_TRIANGLE_STRIP, HW_TRIANGLE_STRIP_0, start, count );
459    }
460 }
461 
462 
TAG(render_quads_verts)463 static void TAG(render_quads_verts)( struct gl_context *ctx,
464 				     GLuint start,
465 				     GLuint count,
466 				     GLuint flags )
467 {
468    LOCAL_VARS;
469    if (0) fprintf(stderr, "%s\n", __func__);
470    count -= (count-start)%4;
471 
472    if (start+3 >= count)
473       return;
474 
475    if (HAVE_QUADS) {
476       EMIT_PRIM( ctx, GL_QUADS, HW_QUADS, start, count );
477    }
478    else {
479       /* Hardware doesn't have a quad primitive type -- simulate it
480        * using indexed vertices and the triangle primitive:
481        */
482       LOCAL_VARS;
483       int dmasz = GET_MAX_HW_ELTS();
484       GLuint j, nr;
485 
486       ELT_INIT( GL_TRIANGLES, HW_TRIANGLES );
487 
488       /* Adjust for rendering as triangles:
489        */
490       dmasz = (dmasz/6)*4;
491 
492       for (j = start; j < count; j += nr ) {
493 	 ELT_TYPE *dest;
494 	 GLint quads, i;
495 
496 	 nr = MIN2( dmasz, count - j );
497 	 quads = nr/4;
498 	 dest = ALLOC_ELTS( quads*6 );
499 
500 	 for ( i = j ; i < j+quads*4 ; i+=4 ) {
501 	    EMIT_TWO_ELTS( dest, 0, (i+0), (i+1) );
502 	    EMIT_TWO_ELTS( dest, 2, (i+3), (i+1) );
503 	    EMIT_TWO_ELTS( dest, 4, (i+2), (i+3) );
504 	    dest += 6;
505 	 }
506 
507 	 CLOSE_ELTS();
508       }
509    }
510 }
511 
TAG(render_noop)512 static void TAG(render_noop)( struct gl_context *ctx,
513 			      GLuint start,
514 			      GLuint count,
515 			      GLuint flags )
516 {
517 }
518 
519 
520 
521 
522 static tnl_render_func TAG(render_tab_verts)[GL_POLYGON+2] =
523 {
524    TAG(render_points_verts),
525    TAG(render_lines_verts),
526    TAG(render_line_loop_verts),
527    TAG(render_line_strip_verts),
528    TAG(render_triangles_verts),
529    TAG(render_tri_strip_verts),
530    TAG(render_tri_fan_verts),
531    TAG(render_quads_verts),
532    TAG(render_quad_strip_verts),
533    TAG(render_poly_verts),
534    TAG(render_noop),
535 };
536 
537 
538 /****************************************************************************
539  *                 Render elts using hardware indexed verts                 *
540  ****************************************************************************/
541 
TAG(render_points_elts)542 static void TAG(render_points_elts)( struct gl_context *ctx,
543 				     GLuint start,
544 				     GLuint count,
545 				     GLuint flags )
546 {
547    LOCAL_VARS;
548    int dmasz = GET_MAX_HW_ELTS();
549    GLuint *elts = GET_MESA_ELTS();
550    GLuint j, nr;
551    ELT_TYPE *dest;
552 
553    ELT_INIT( GL_POINTS, HW_POINTS );
554 
555    for (j = start; j < count; j += nr ) {
556       nr = MIN2( dmasz, count - j );
557       dest = ALLOC_ELTS( nr );
558       dest = TAG(emit_elts)( ctx, dest, elts+j, nr );
559       (void) dest;
560       CLOSE_ELTS();
561    }
562 }
563 
564 
565 
TAG(render_lines_elts)566 static void TAG(render_lines_elts)( struct gl_context *ctx,
567 				    GLuint start,
568 				    GLuint count,
569 				    GLuint flags )
570 {
571    LOCAL_VARS;
572    int dmasz = GET_MAX_HW_ELTS();
573    GLuint *elts = GET_MESA_ELTS();
574    GLuint j, nr;
575    ELT_TYPE *dest;
576 
577    if (start+1 >= count)
578       return;
579 
580    if ((flags & PRIM_BEGIN) && ctx->Line.StippleFlag) {
581       RESET_STIPPLE();
582       AUTO_STIPPLE( GL_TRUE );
583    }
584 
585    ELT_INIT( GL_LINES, HW_LINES );
586 
587    /* Emit whole number of lines in total and in each buffer:
588     */
589    count -= (count-start) & 1;
590    dmasz -= dmasz & 1;
591 
592    for (j = start; j < count; j += nr ) {
593       nr = MIN2( dmasz, count - j );
594       dest = ALLOC_ELTS( nr );
595       dest = TAG(emit_elts)( ctx, dest, elts+j, nr );
596       (void) dest;
597       CLOSE_ELTS();
598    }
599 
600    if ((flags & PRIM_END) && ctx->Line.StippleFlag)
601       AUTO_STIPPLE( GL_FALSE );
602 }
603 
604 
TAG(render_line_strip_elts)605 static void TAG(render_line_strip_elts)( struct gl_context *ctx,
606 					 GLuint start,
607 					 GLuint count,
608 					 GLuint flags )
609 {
610    LOCAL_VARS;
611    int dmasz = GET_MAX_HW_ELTS();
612    GLuint *elts = GET_MESA_ELTS();
613    GLuint j, nr;
614    ELT_TYPE *dest;
615 
616    if (start+1 >= count)
617       return;
618 
619    ELT_INIT( GL_LINE_STRIP, HW_LINE_STRIP );
620 
621    if ((flags & PRIM_BEGIN) && ctx->Line.StippleFlag)
622       RESET_STIPPLE();
623 
624    for (j = start; j + 1 < count; j += nr - 1 ) {
625       nr = MIN2( dmasz, count - j );
626       dest = ALLOC_ELTS( nr );
627       dest = TAG(emit_elts)( ctx, dest, elts+j, nr );
628       (void) dest;
629       CLOSE_ELTS();
630    }
631 }
632 
633 
TAG(render_line_loop_elts)634 static void TAG(render_line_loop_elts)( struct gl_context *ctx,
635 					GLuint start,
636 					GLuint count,
637 					GLuint flags )
638 {
639    LOCAL_VARS;
640    int dmasz = GET_MAX_HW_ELTS();
641    GLuint *elts = GET_MESA_ELTS();
642    GLuint j, nr;
643    ELT_TYPE *dest;
644 
645    if (0) fprintf(stderr, "%s\n", __func__);
646 
647    if (flags & PRIM_BEGIN)
648       j = start;
649    else
650       j = start + 1;
651 
652 
653    if (flags & PRIM_END) {
654       if (start+1 >= count)
655 	 return;
656    }
657    else {
658       if (j+1 >= count)
659 	 return;
660    }
661 
662    ELT_INIT( GL_LINE_STRIP, HW_LINE_STRIP );
663 
664    if ((flags & PRIM_BEGIN) && ctx->Line.StippleFlag)
665       RESET_STIPPLE();
666 
667 
668    /* Ensure last vertex doesn't wrap:
669     */
670    dmasz--;
671 
672    for ( ; j + 1 < count; ) {
673       nr = MIN2( dmasz, count - j );
674       dest = ALLOC_ELTS( nr+1 );	/* Reserve possible space for last elt */
675       dest = TAG(emit_elts)( ctx, dest, elts+j, nr );
676       j += nr - 1;
677       if (j + 1 >= count && (flags & PRIM_END)) {
678 	 dest = TAG(emit_elts)( ctx, dest, elts+start, 1 );
679 	 (void) dest;
680       }
681       CLOSE_ELTS();
682    }
683 }
684 
685 
TAG(render_triangles_elts)686 static void TAG(render_triangles_elts)( struct gl_context *ctx,
687 					GLuint start,
688 					GLuint count,
689 					GLuint flags )
690 {
691    LOCAL_VARS;
692    GLuint *elts = GET_MESA_ELTS();
693    int dmasz = GET_MAX_HW_ELTS()/3*3;
694    GLuint j, nr;
695    ELT_TYPE *dest;
696 
697    if (start+2 >= count)
698       return;
699 
700    ELT_INIT( GL_TRIANGLES, HW_TRIANGLES );
701 
702 
703    /* Emit whole number of tris in total.  dmasz is already a multiple
704     * of 3.
705     */
706    count -= (count-start)%3;
707 
708    for (j = start; j < count; j += nr) {
709       nr = MIN2( dmasz, count - j );
710       dest = ALLOC_ELTS( nr );
711       dest = TAG(emit_elts)( ctx, dest, elts+j, nr );
712       (void) dest;
713       CLOSE_ELTS();
714    }
715 }
716 
717 
718 
TAG(render_tri_strip_elts)719 static void TAG(render_tri_strip_elts)( struct gl_context *ctx,
720 					GLuint start,
721 					GLuint count,
722 					GLuint flags )
723 {
724    LOCAL_VARS;
725    GLuint j, nr;
726    GLuint *elts = GET_MESA_ELTS();
727    int dmasz = GET_MAX_HW_ELTS();
728    ELT_TYPE *dest;
729 
730    if (start+2 >= count)
731       return;
732 
733    ELT_INIT( GL_TRIANGLE_STRIP, HW_TRIANGLE_STRIP_0 );
734 
735    /* Keep the same winding over multiple buffers:
736     */
737    dmasz -= (dmasz & 1);
738 
739    for (j = start ; j + 2 < count; j += nr - 2 ) {
740       nr = MIN2( dmasz, count - j );
741 
742       dest = ALLOC_ELTS( nr );
743       dest = TAG(emit_elts)( ctx, dest, elts+j, nr );
744       (void) dest;
745       CLOSE_ELTS();
746    }
747 }
748 
TAG(render_tri_fan_elts)749 static void TAG(render_tri_fan_elts)( struct gl_context *ctx,
750 				      GLuint start,
751 				      GLuint count,
752 				      GLuint flags )
753 {
754    LOCAL_VARS;
755    GLuint *elts = GET_MESA_ELTS();
756    GLuint j, nr;
757    int dmasz = GET_MAX_HW_ELTS();
758    ELT_TYPE *dest;
759 
760    if (start+2 >= count)
761       return;
762 
763    ELT_INIT( GL_TRIANGLE_FAN, HW_TRIANGLE_FAN );
764 
765    for (j = start + 1 ; j + 1 < count; j += nr - 1 ) {
766       nr = MIN2( dmasz, count - j + 1 );
767       dest = ALLOC_ELTS( nr );
768       dest = TAG(emit_elts)( ctx, dest, elts+start, 1 );
769       dest = TAG(emit_elts)( ctx, dest, elts+j, nr - 1 );
770       (void) dest;
771       CLOSE_ELTS();
772    }
773 }
774 
775 
TAG(render_poly_elts)776 static void TAG(render_poly_elts)( struct gl_context *ctx,
777 				   GLuint start,
778 				   GLuint count,
779 				   GLuint flags )
780 {
781    LOCAL_VARS;
782    GLuint *elts = GET_MESA_ELTS();
783    GLuint j, nr;
784    int dmasz = GET_MAX_HW_ELTS();
785    ELT_TYPE *dest;
786 
787    if (start+2 >= count)
788       return;
789 
790    ELT_INIT( GL_POLYGON, HW_POLYGON );
791 
792    for (j = start + 1 ; j + 1 < count ; j += nr - 1 ) {
793       nr = MIN2( dmasz, count - j + 1 );
794       dest = ALLOC_ELTS( nr );
795       dest = TAG(emit_elts)( ctx, dest, elts+start, 1 );
796       dest = TAG(emit_elts)( ctx, dest, elts+j, nr - 1 );
797       (void) dest;
798       CLOSE_ELTS();
799    }
800 }
801 
TAG(render_quad_strip_elts)802 static void TAG(render_quad_strip_elts)( struct gl_context *ctx,
803 					 GLuint start,
804 					 GLuint count,
805 					 GLuint flags )
806 {
807    if (start+3 >= count)
808       return;
809 
810    if (HAVE_QUAD_STRIPS && 0) {
811    }
812    else {
813       LOCAL_VARS;
814       GLuint *elts = GET_MESA_ELTS();
815       int dmasz = GET_MAX_HW_ELTS();
816       GLuint j, nr;
817       ELT_TYPE *dest;
818 
819       /* Emit whole number of quads in total, and in each buffer.
820        */
821       dmasz -= dmasz & 1;
822       count -= (count-start) & 1;
823 
824       if (ctx->Light.ShadeModel == GL_FLAT) {
825 	 ELT_INIT( GL_TRIANGLES, HW_TRIANGLES );
826 
827 	 dmasz = dmasz/6*2;
828 
829 	 for (j = start; j + 3 < count; j += nr - 2 ) {
830 	    nr = MIN2( dmasz, count - j );
831 
832 	    if (nr >= 4)
833 	    {
834 	       GLint quads = (nr/2)-1;
835 	       ELT_TYPE *dest = ALLOC_ELTS( quads*6 );
836 	       GLint i;
837 
838 	       for ( i = j-start ; i < j-start+quads ; i++, elts += 2 ) {
839 		  EMIT_TWO_ELTS( dest, 0, elts[0], elts[1] );
840 		  EMIT_TWO_ELTS( dest, 2, elts[2], elts[1] );
841 		  EMIT_TWO_ELTS( dest, 4, elts[3], elts[2] );
842 		  dest += 6;
843 	       }
844 
845 	       CLOSE_ELTS();
846 	    }
847 	 }
848       }
849       else {
850 	 ELT_INIT( GL_TRIANGLE_STRIP, HW_TRIANGLE_STRIP_0 );
851 
852 	 for (j = start; j + 3 < count; j += nr - 2 ) {
853 	    nr = MIN2( dmasz, count - j );
854 	    dest = ALLOC_ELTS( nr );
855 	    dest = TAG(emit_elts)( ctx, dest, elts+j, nr );
856 	    (void) dest;
857 	    CLOSE_ELTS();
858 	 }
859       }
860    }
861 }
862 
863 
TAG(render_quads_elts)864 static void TAG(render_quads_elts)( struct gl_context *ctx,
865 				    GLuint start,
866 				    GLuint count,
867 				    GLuint flags )
868 {
869    if (start+3 >= count)
870       return;
871 
872    if (HAVE_QUADS && 0) {
873    } else {
874       LOCAL_VARS;
875       GLuint *elts = GET_MESA_ELTS();
876       int dmasz = GET_MAX_HW_ELTS();
877       GLuint j, nr;
878 
879       ELT_INIT( GL_TRIANGLES, HW_TRIANGLES );
880 
881       /* Emit whole number of quads in total, and in each buffer.
882        */
883       dmasz -= dmasz & 3;
884       count -= (count-start) & 3;
885 
886       /* Adjust for rendering as triangles:
887        */
888       dmasz = dmasz/6*4;
889 
890       for (j = start; j + 3 < count; j += nr ) {
891 	 nr = MIN2( dmasz, count - j );
892 
893 	 {
894 	    GLint quads = nr/4;
895 	    ELT_TYPE *dest = ALLOC_ELTS( quads * 6 );
896 	    GLint i;
897 
898 	    for ( i = j-start ; i < j-start+quads ; i++, elts += 4 ) {
899 	       EMIT_TWO_ELTS( dest, 0, elts[0], elts[1] );
900 	       EMIT_TWO_ELTS( dest, 2, elts[3], elts[1] );
901 	       EMIT_TWO_ELTS( dest, 4, elts[2], elts[3] );
902 	       dest += 6;
903 	    }
904 
905 	    CLOSE_ELTS();
906 	 }
907       }
908    }
909 }
910 
911 
912 
913 static tnl_render_func TAG(render_tab_elts)[GL_POLYGON+2] =
914 {
915    TAG(render_points_elts),
916    TAG(render_lines_elts),
917    TAG(render_line_loop_elts),
918    TAG(render_line_strip_elts),
919    TAG(render_triangles_elts),
920    TAG(render_tri_strip_elts),
921    TAG(render_tri_fan_elts),
922    TAG(render_quads_elts),
923    TAG(render_quad_strip_elts),
924    TAG(render_poly_elts),
925    TAG(render_noop),
926 };
927