Home | History | Annotate | Download | only in tnl_dd
      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 (at) 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 };
    927