Tizen 2.0 Release
[profile/ivi/osmesa.git] / src / mesa / tnl_dd / t_dd_dmatmp2.h
1 /*
2  * Mesa 3-D graphics library
3  * Version:  6.5.1
4  *
5  * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
6  *
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:
13  *
14  * The above copyright notice and this permission notice shall be included
15  * in all copies or substantial portions of the Software.
16  *
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.
23  *
24  * Authors:
25  *    Keith Whitwell <keith@tungstengraphics.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
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
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
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", __FUNCTION__);
125       EMIT_PRIM( ctx, GL_POINTS, HW_POINTS, start, count );
126    }
127 }
128
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", __FUNCTION__);
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
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", __FUNCTION__);
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
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", __FUNCTION__);
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
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", __FUNCTION__);
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
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", __FUNCTION__);
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
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", __FUNCTION__);
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
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", __FUNCTION__);
405
406    if (start+2 >= count) 
407       return;
408
409    EMIT_PRIM( ctx, GL_POLYGON, HW_POLYGON, start, count );
410 }
411
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", __FUNCTION__);
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
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", __FUNCTION__);
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
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
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
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
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
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", __FUNCTION__);
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
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
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
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
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
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
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 };