Home | History | Annotate | Download | only in tnl
      1 /*
      2  * Mesa 3-D graphics library
      3  *
      4  * Copyright (C) 1999-2005  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 (at) vmware.com>
     26  */
     27 
     28 
     29 #ifndef POSTFIX
     30 #define POSTFIX
     31 #endif
     32 
     33 #ifndef INIT
     34 #define INIT(x)
     35 #endif
     36 
     37 #ifndef NEED_EDGEFLAG_SETUP
     38 #define NEED_EDGEFLAG_SETUP 0
     39 #define EDGEFLAG_GET(a) 0
     40 #define EDGEFLAG_SET(a,b) (void)b
     41 #endif
     42 
     43 #ifndef RESET_STIPPLE
     44 #define RESET_STIPPLE
     45 #endif
     46 
     47 #ifndef TEST_PRIM_END
     48 #define TEST_PRIM_END(prim) (flags & PRIM_END)
     49 #define TEST_PRIM_BEGIN(prim) (flags & PRIM_BEGIN)
     50 #endif
     51 
     52 #ifndef ELT
     53 #define ELT(x) x
     54 #endif
     55 
     56 #ifndef RENDER_TAB_QUALIFIER
     57 #define RENDER_TAB_QUALIFIER static
     58 #endif
     59 
     60 static void TAG(render_points)( struct gl_context *ctx,
     61 				GLuint start,
     62 				GLuint count,
     63 				GLuint flags )
     64 {
     65    LOCAL_VARS;
     66    (void) flags;
     67 
     68    INIT(GL_POINTS);
     69    RENDER_POINTS( start, count );
     70    POSTFIX;
     71 }
     72 
     73 static void TAG(render_lines)( struct gl_context *ctx,
     74 			       GLuint start,
     75 			       GLuint count,
     76 			       GLuint flags )
     77 {
     78    GLuint j;
     79    LOCAL_VARS;
     80    (void) flags;
     81 
     82    INIT(GL_LINES);
     83    for (j=start+1; j<count; j+=2 ) {
     84       RESET_STIPPLE;
     85       if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT)
     86          RENDER_LINE( ELT(j-1), ELT(j) );
     87       else
     88          RENDER_LINE( ELT(j), ELT(j-1) );
     89    }
     90    POSTFIX;
     91 }
     92 
     93 
     94 static void TAG(render_line_strip)( struct gl_context *ctx,
     95 				    GLuint start,
     96 				    GLuint count,
     97 				    GLuint flags )
     98 {
     99    GLuint j;
    100    LOCAL_VARS;
    101    (void) flags;
    102 
    103    INIT(GL_LINE_STRIP);
    104 
    105    if (TEST_PRIM_BEGIN(flags)) {
    106       RESET_STIPPLE;
    107    }
    108 
    109    for (j=start+1; j<count; j++ ) {
    110       if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT)
    111          RENDER_LINE( ELT(j-1), ELT(j) );
    112       else
    113          RENDER_LINE( ELT(j), ELT(j-1) );
    114    }
    115    POSTFIX;
    116 }
    117 
    118 
    119 static void TAG(render_line_loop)( struct gl_context *ctx,
    120 				   GLuint start,
    121 				   GLuint count,
    122 				   GLuint flags )
    123 {
    124    GLuint i;
    125    LOCAL_VARS;
    126 
    127    INIT(GL_LINE_LOOP);
    128 
    129    if (start+1 < count) {
    130       if (TEST_PRIM_BEGIN(flags)) {
    131 	 RESET_STIPPLE;
    132          /* draw the first line from v[0] to v[1] */
    133          if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT)
    134             RENDER_LINE( ELT(start), ELT(start+1) );
    135          else
    136             RENDER_LINE( ELT(start+1), ELT(start) );
    137       }
    138 
    139       /* draw lines from v[1] to v[n-1] */
    140       for ( i = start+2 ; i < count ; i++) {
    141          if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT)
    142             RENDER_LINE( ELT(i-1), ELT(i) );
    143          else
    144             RENDER_LINE( ELT(i), ELT(i-1) );
    145       }
    146 
    147       if ( TEST_PRIM_END(flags)) {
    148          /* draw final line from v[n-1] to v[0] (the very first vertex) */
    149          if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT)
    150             RENDER_LINE( ELT(count-1), ELT(start) );
    151          else
    152             RENDER_LINE( ELT(start), ELT(count-1) );
    153       }
    154    }
    155 
    156    POSTFIX;
    157 }
    158 
    159 
    160 static void TAG(render_triangles)( struct gl_context *ctx,
    161 				   GLuint start,
    162 				   GLuint count,
    163 				   GLuint flags )
    164 {
    165    GLuint j;
    166    LOCAL_VARS;
    167    (void) flags;
    168 
    169    INIT(GL_TRIANGLES);
    170    if (NEED_EDGEFLAG_SETUP) {
    171       for (j=start+2; j<count; j+=3) {
    172 	 /* Leave the edgeflags as supplied by the user.
    173 	  */
    174 	 RESET_STIPPLE;
    175          if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT)
    176             RENDER_TRI( ELT(j-2), ELT(j-1), ELT(j) );
    177          else
    178             RENDER_TRI( ELT(j-1), ELT(j), ELT(j-2) );
    179       }
    180    } else {
    181       for (j=start+2; j<count; j+=3) {
    182          if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT)
    183             RENDER_TRI( ELT(j-2), ELT(j-1), ELT(j) );
    184          else
    185             RENDER_TRI( ELT(j-1), ELT(j), ELT(j-2) );
    186       }
    187    }
    188    POSTFIX;
    189 }
    190 
    191 
    192 
    193 static void TAG(render_tri_strip)( struct gl_context *ctx,
    194 				   GLuint start,
    195 				   GLuint count,
    196 				   GLuint flags )
    197 {
    198    GLuint j;
    199    GLuint parity = 0;
    200    LOCAL_VARS;
    201 
    202    INIT(GL_TRIANGLE_STRIP);
    203    if (NEED_EDGEFLAG_SETUP) {
    204       for (j=start+2;j<count;j++,parity^=1) {
    205          GLuint ej2, ej1, ej;
    206          GLboolean ef2, ef1, ef;
    207          if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT) {
    208             ej2 = ELT(j-2+parity);
    209             ej1 = ELT(j-1-parity);
    210             ej = ELT(j);
    211          }
    212          else {
    213             ej2 = ELT(j-1+parity);
    214             ej1 = ELT(j-parity);
    215             ej = ELT(j-2);
    216          }
    217 	 ef2 = EDGEFLAG_GET( ej2 );
    218 	 ef1 = EDGEFLAG_GET( ej1 );
    219 	 ef = EDGEFLAG_GET( ej );
    220 	 if (TEST_PRIM_BEGIN(flags)) {
    221 	    RESET_STIPPLE;
    222 	 }
    223 	 EDGEFLAG_SET( ej2, GL_TRUE );
    224 	 EDGEFLAG_SET( ej1, GL_TRUE );
    225 	 EDGEFLAG_SET( ej, GL_TRUE );
    226          RENDER_TRI( ej2, ej1, ej );
    227 	 EDGEFLAG_SET( ej2, ef2 );
    228 	 EDGEFLAG_SET( ej1, ef1 );
    229 	 EDGEFLAG_SET( ej, ef );
    230       }
    231    } else {
    232       for (j=start+2; j<count ; j++, parity^=1) {
    233          if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT)
    234             RENDER_TRI( ELT(j-2+parity), ELT(j-1-parity), ELT(j) );
    235          else
    236             RENDER_TRI( ELT(j-1+parity), ELT(j-parity), ELT(j-2) );
    237       }
    238    }
    239    POSTFIX;
    240 }
    241 
    242 
    243 static void TAG(render_tri_fan)( struct gl_context *ctx,
    244 				 GLuint start,
    245 				 GLuint count,
    246 				 GLuint flags )
    247 {
    248    GLuint j;
    249    LOCAL_VARS;
    250    (void) flags;
    251 
    252    INIT(GL_TRIANGLE_FAN);
    253    if (NEED_EDGEFLAG_SETUP) {
    254       for (j=start+2;j<count;j++) {
    255 	 /* For trifans, all edges are boundary.
    256 	  */
    257 	 GLuint ejs = ELT(start);
    258 	 GLuint ej1 = ELT(j-1);
    259 	 GLuint ej = ELT(j);
    260 	 GLboolean efs = EDGEFLAG_GET( ejs );
    261 	 GLboolean ef1 = EDGEFLAG_GET( ej1 );
    262 	 GLboolean ef = EDGEFLAG_GET( ej );
    263 	 if (TEST_PRIM_BEGIN(flags)) {
    264 	    RESET_STIPPLE;
    265 	 }
    266 	 EDGEFLAG_SET( ejs, GL_TRUE );
    267 	 EDGEFLAG_SET( ej1, GL_TRUE );
    268 	 EDGEFLAG_SET( ej, GL_TRUE );
    269          if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT)
    270             RENDER_TRI( ejs, ej1, ej);
    271          else
    272             RENDER_TRI( ej, ejs, ej1);
    273 	 EDGEFLAG_SET( ejs, efs );
    274 	 EDGEFLAG_SET( ej1, ef1 );
    275 	 EDGEFLAG_SET( ej, ef );
    276       }
    277    } else {
    278       for (j=start+2;j<count;j++) {
    279          if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT)
    280             RENDER_TRI( ELT(start), ELT(j-1), ELT(j) );
    281          else
    282             RENDER_TRI( ELT(j), ELT(start), ELT(j-1) );
    283       }
    284    }
    285 
    286    POSTFIX;
    287 }
    288 
    289 
    290 static void TAG(render_poly)( struct gl_context *ctx,
    291 			      GLuint start,
    292 			      GLuint count,
    293 			      GLuint flags )
    294 {
    295    GLuint j = start+2;
    296    LOCAL_VARS;
    297    (void) flags;
    298 
    299    INIT(GL_POLYGON);
    300    if (NEED_EDGEFLAG_SETUP) {
    301       GLboolean efstart = EDGEFLAG_GET( ELT(start) );
    302       GLboolean efcount = EDGEFLAG_GET( ELT(count-1) );
    303 
    304       /* If the primitive does not begin here, the first edge
    305        * is non-boundary.
    306        */
    307       if (!TEST_PRIM_BEGIN(flags))
    308 	 EDGEFLAG_SET( ELT(start), GL_FALSE );
    309       else {
    310 	 RESET_STIPPLE;
    311       }
    312 
    313       /* If the primitive does not end here, the final edge is
    314        * non-boundary.
    315        */
    316       if (!TEST_PRIM_END(flags))
    317 	 EDGEFLAG_SET( ELT(count-1), GL_FALSE );
    318 
    319       /* Draw the first triangles (possibly zero)
    320        */
    321       if (j+1<count) {
    322 	 GLboolean ef = EDGEFLAG_GET( ELT(j) );
    323 	 EDGEFLAG_SET( ELT(j), GL_FALSE );
    324 	 RENDER_TRI( ELT(j-1), ELT(j), ELT(start) );
    325 	 EDGEFLAG_SET( ELT(j), ef );
    326 	 j++;
    327 
    328 	 /* Don't render the first edge again:
    329 	  */
    330 	 EDGEFLAG_SET( ELT(start), GL_FALSE );
    331 
    332 	 for (;j+1<count;j++) {
    333 	    GLboolean efj = EDGEFLAG_GET( ELT(j) );
    334 	    EDGEFLAG_SET( ELT(j), GL_FALSE );
    335 	    RENDER_TRI( ELT(j-1), ELT(j), ELT(start) );
    336 	    EDGEFLAG_SET( ELT(j), efj );
    337 	 }
    338       }
    339 
    340       /* Draw the last or only triangle
    341        */
    342       if (j < count)
    343 	 RENDER_TRI( ELT(j-1), ELT(j), ELT(start) );
    344 
    345       /* Restore the first and last edgeflags:
    346        */
    347       EDGEFLAG_SET( ELT(count-1), efcount );
    348       EDGEFLAG_SET( ELT(start), efstart );
    349 
    350    }
    351    else {
    352       for (j=start+2;j<count;j++) {
    353 	 RENDER_TRI( ELT(j-1), ELT(j), ELT(start) );
    354       }
    355    }
    356    POSTFIX;
    357 }
    358 
    359 static void TAG(render_quads)( struct gl_context *ctx,
    360 			       GLuint start,
    361 			       GLuint count,
    362 			       GLuint flags )
    363 {
    364    GLuint j;
    365    LOCAL_VARS;
    366    (void) flags;
    367 
    368    INIT(GL_QUADS);
    369    if (NEED_EDGEFLAG_SETUP) {
    370       for (j=start+3; j<count; j+=4) {
    371 	 /* Use user-specified edgeflags for quads.
    372 	  */
    373 	 RESET_STIPPLE;
    374          if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT ||
    375              !ctx->Const.QuadsFollowProvokingVertexConvention)
    376             RENDER_QUAD( ELT(j-3), ELT(j-2), ELT(j-1), ELT(j) );
    377          else
    378             RENDER_QUAD( ELT(j-2), ELT(j-1), ELT(j), ELT(j-3) );
    379       }
    380    } else {
    381       for (j=start+3; j<count; j+=4) {
    382          if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT ||
    383              !ctx->Const.QuadsFollowProvokingVertexConvention)
    384             RENDER_QUAD( ELT(j-3), ELT(j-2), ELT(j-1), ELT(j) );
    385          else
    386             RENDER_QUAD( ELT(j-2), ELT(j-1), ELT(j), ELT(j-3) );
    387       }
    388    }
    389    POSTFIX;
    390 }
    391 
    392 static void TAG(render_quad_strip)( struct gl_context *ctx,
    393 				    GLuint start,
    394 				    GLuint count,
    395 				    GLuint flags )
    396 {
    397    GLuint j;
    398    LOCAL_VARS;
    399    (void) flags;
    400 
    401    INIT(GL_QUAD_STRIP);
    402    if (NEED_EDGEFLAG_SETUP) {
    403       for (j=start+3;j<count;j+=2) {
    404 	 /* All edges are boundary.  Set edgeflags to 1, draw the
    405 	  * quad, and restore them to the original values.
    406 	  */
    407 	 GLboolean ef3 = EDGEFLAG_GET( ELT(j-3) );
    408 	 GLboolean ef2 = EDGEFLAG_GET( ELT(j-2) );
    409 	 GLboolean ef1 = EDGEFLAG_GET( ELT(j-1) );
    410 	 GLboolean ef = EDGEFLAG_GET( ELT(j) );
    411 	 if (TEST_PRIM_BEGIN(flags)) {
    412 	    RESET_STIPPLE;
    413 	 }
    414 	 EDGEFLAG_SET( ELT(j-3), GL_TRUE );
    415 	 EDGEFLAG_SET( ELT(j-2), GL_TRUE );
    416 	 EDGEFLAG_SET( ELT(j-1), GL_TRUE );
    417 	 EDGEFLAG_SET( ELT(j), GL_TRUE );
    418          if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT ||
    419              !ctx->Const.QuadsFollowProvokingVertexConvention)
    420             RENDER_QUAD( ELT(j-1), ELT(j-3), ELT(j-2), ELT(j) );
    421          else
    422             RENDER_QUAD( ELT(j-2), ELT(j), ELT(j-1), ELT(j-3) );
    423 	 EDGEFLAG_SET( ELT(j-3), ef3 );
    424 	 EDGEFLAG_SET( ELT(j-2), ef2 );
    425 	 EDGEFLAG_SET( ELT(j-1), ef1 );
    426 	 EDGEFLAG_SET( ELT(j), ef );
    427       }
    428    } else {
    429       for (j=start+3;j<count;j+=2) {
    430          if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT ||
    431              !ctx->Const.QuadsFollowProvokingVertexConvention)
    432             RENDER_QUAD( ELT(j-1), ELT(j-3), ELT(j-2), ELT(j) );
    433          else
    434             RENDER_QUAD( ELT(j-2), ELT(j), ELT(j-1), ELT(j-3) );
    435       }
    436    }
    437    POSTFIX;
    438 }
    439 
    440 static void TAG(render_noop)( struct gl_context *ctx,
    441 			      GLuint start,
    442 			      GLuint count,
    443 			      GLuint flags )
    444 {
    445    (void)(ctx && start && count && flags);
    446 }
    447 
    448 RENDER_TAB_QUALIFIER void (*TAG(render_tab)[GL_POLYGON+2])(struct gl_context *,
    449 							   GLuint,
    450 							   GLuint,
    451 							   GLuint) =
    452 {
    453    TAG(render_points),
    454    TAG(render_lines),
    455    TAG(render_line_loop),
    456    TAG(render_line_strip),
    457    TAG(render_triangles),
    458    TAG(render_tri_strip),
    459    TAG(render_tri_fan),
    460    TAG(render_quads),
    461    TAG(render_quad_strip),
    462    TAG(render_poly),
    463    TAG(render_noop),
    464 };
    465 
    466 
    467 
    468 #ifndef PRESERVE_VB_DEFS
    469 #undef RENDER_TRI
    470 #undef RENDER_QUAD
    471 #undef RENDER_LINE
    472 #undef RENDER_POINTS
    473 #undef LOCAL_VARS
    474 #undef INIT
    475 #undef POSTFIX
    476 #undef RESET_STIPPLE
    477 #undef DBG
    478 #undef ELT
    479 #undef RENDER_TAB_QUALIFIER
    480 #endif
    481 
    482 #ifndef PRESERVE_TAG
    483 #undef TAG
    484 #endif
    485 
    486 #undef PRESERVE_VB_DEFS
    487 #undef PRESERVE_TAG
    488