Home | History | Annotate | Download | only in tnl
      1 /*
      2  * Mesa 3-D graphics library
      3  * Version:  6.5
      4  *
      5  * Copyright (C) 1999-2005  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 #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    (void) flags;
    128 
    129    INIT(GL_LINE_LOOP);
    130 
    131    if (start+1 < count) {
    132       if (TEST_PRIM_BEGIN(flags)) {
    133 	 RESET_STIPPLE;
    134          if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT)
    135             RENDER_LINE( ELT(start), ELT(start+1) );
    136          else
    137             RENDER_LINE( ELT(start+1), ELT(start) );
    138       }
    139 
    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          if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT)
    149             RENDER_LINE( ELT(count-1), ELT(start) );
    150          else
    151             RENDER_LINE( ELT(start), ELT(count-1) );
    152       }
    153    }
    154 
    155    POSTFIX;
    156 }
    157 
    158 
    159 static void TAG(render_triangles)( struct gl_context *ctx,
    160 				   GLuint start,
    161 				   GLuint count,
    162 				   GLuint flags )
    163 {
    164    GLuint j;
    165    LOCAL_VARS;
    166    (void) flags;
    167 
    168    INIT(GL_TRIANGLES);
    169    if (NEED_EDGEFLAG_SETUP) {
    170       for (j=start+2; j<count; j+=3) {
    171 	 /* Leave the edgeflags as supplied by the user.
    172 	  */
    173 	 RESET_STIPPLE;
    174          if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT)
    175             RENDER_TRI( ELT(j-2), ELT(j-1), ELT(j) );
    176          else
    177             RENDER_TRI( ELT(j-1), ELT(j), ELT(j-2) );
    178       }
    179    } else {
    180       for (j=start+2; j<count; j+=3) {
    181          if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT)
    182             RENDER_TRI( ELT(j-2), ELT(j-1), ELT(j) );
    183          else
    184             RENDER_TRI( ELT(j-1), ELT(j), ELT(j-2) );
    185       }
    186    }
    187    POSTFIX;
    188 }
    189 
    190 
    191 
    192 static void TAG(render_tri_strip)( struct gl_context *ctx,
    193 				   GLuint start,
    194 				   GLuint count,
    195 				   GLuint flags )
    196 {
    197    GLuint j;
    198    GLuint parity = 0;
    199    LOCAL_VARS;
    200 
    201    INIT(GL_TRIANGLE_STRIP);
    202    if (NEED_EDGEFLAG_SETUP) {
    203       for (j=start+2;j<count;j++,parity^=1) {
    204          GLuint ej2, ej1, ej;
    205          GLboolean ef2, ef1, ef;
    206          if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT) {
    207             ej2 = ELT(j-2+parity);
    208             ej1 = ELT(j-1-parity);
    209             ej = ELT(j);
    210          }
    211          else {
    212             ej2 = ELT(j-1+parity);
    213             ej1 = ELT(j-parity);
    214             ej = ELT(j-2);
    215          }
    216 	 ef2 = EDGEFLAG_GET( ej2 );
    217 	 ef1 = EDGEFLAG_GET( ej1 );
    218 	 ef = EDGEFLAG_GET( ej );
    219 	 if (TEST_PRIM_BEGIN(flags)) {
    220 	    RESET_STIPPLE;
    221 	 }
    222 	 EDGEFLAG_SET( ej2, GL_TRUE );
    223 	 EDGEFLAG_SET( ej1, GL_TRUE );
    224 	 EDGEFLAG_SET( ej, GL_TRUE );
    225          RENDER_TRI( ej2, ej1, ej );
    226 	 EDGEFLAG_SET( ej2, ef2 );
    227 	 EDGEFLAG_SET( ej1, ef1 );
    228 	 EDGEFLAG_SET( ej, ef );
    229       }
    230    } else {
    231       for (j=start+2; j<count ; j++, parity^=1) {
    232          if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT)
    233             RENDER_TRI( ELT(j-2+parity), ELT(j-1-parity), ELT(j) );
    234          else
    235             RENDER_TRI( ELT(j-1+parity), ELT(j-parity), ELT(j-2) );
    236       }
    237    }
    238    POSTFIX;
    239 }
    240 
    241 
    242 static void TAG(render_tri_fan)( struct gl_context *ctx,
    243 				 GLuint start,
    244 				 GLuint count,
    245 				 GLuint flags )
    246 {
    247    GLuint j;
    248    LOCAL_VARS;
    249    (void) flags;
    250 
    251    INIT(GL_TRIANGLE_FAN);
    252    if (NEED_EDGEFLAG_SETUP) {
    253       for (j=start+2;j<count;j++) {
    254 	 /* For trifans, all edges are boundary.
    255 	  */
    256 	 GLuint ejs = ELT(start);
    257 	 GLuint ej1 = ELT(j-1);
    258 	 GLuint ej = ELT(j);
    259 	 GLboolean efs = EDGEFLAG_GET( ejs );
    260 	 GLboolean ef1 = EDGEFLAG_GET( ej1 );
    261 	 GLboolean ef = EDGEFLAG_GET( ej );
    262 	 if (TEST_PRIM_BEGIN(flags)) {
    263 	    RESET_STIPPLE;
    264 	 }
    265 	 EDGEFLAG_SET( ejs, GL_TRUE );
    266 	 EDGEFLAG_SET( ej1, GL_TRUE );
    267 	 EDGEFLAG_SET( ej, GL_TRUE );
    268          if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT)
    269             RENDER_TRI( ejs, ej1, ej);
    270          else
    271             RENDER_TRI( ej, ejs, ej1);
    272 	 EDGEFLAG_SET( ejs, efs );
    273 	 EDGEFLAG_SET( ej1, ef1 );
    274 	 EDGEFLAG_SET( ej, ef );
    275       }
    276    } else {
    277       for (j=start+2;j<count;j++) {
    278          if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT)
    279             RENDER_TRI( ELT(start), ELT(j-1), ELT(j) );
    280          else
    281             RENDER_TRI( ELT(j), ELT(start), ELT(j-1) );
    282       }
    283    }
    284 
    285    POSTFIX;
    286 }
    287 
    288 
    289 static void TAG(render_poly)( struct gl_context *ctx,
    290 			      GLuint start,
    291 			      GLuint count,
    292 			      GLuint flags )
    293 {
    294    GLuint j = start+2;
    295    LOCAL_VARS;
    296    (void) flags;
    297 
    298    INIT(GL_POLYGON);
    299    if (NEED_EDGEFLAG_SETUP) {
    300       GLboolean efstart = EDGEFLAG_GET( ELT(start) );
    301       GLboolean efcount = EDGEFLAG_GET( ELT(count-1) );
    302 
    303       /* If the primitive does not begin here, the first edge
    304        * is non-boundary.
    305        */
    306       if (!TEST_PRIM_BEGIN(flags))
    307 	 EDGEFLAG_SET( ELT(start), GL_FALSE );
    308       else {
    309 	 RESET_STIPPLE;
    310       }
    311 
    312       /* If the primitive does not end here, the final edge is
    313        * non-boundary.
    314        */
    315       if (!TEST_PRIM_END(flags))
    316 	 EDGEFLAG_SET( ELT(count-1), GL_FALSE );
    317 
    318       /* Draw the first triangles (possibly zero)
    319        */
    320       if (j+1<count) {
    321 	 GLboolean ef = EDGEFLAG_GET( ELT(j) );
    322 	 EDGEFLAG_SET( ELT(j), GL_FALSE );
    323 	 RENDER_TRI( ELT(j-1), ELT(j), ELT(start) );
    324 	 EDGEFLAG_SET( ELT(j), ef );
    325 	 j++;
    326 
    327 	 /* Don't render the first edge again:
    328 	  */
    329 	 EDGEFLAG_SET( ELT(start), GL_FALSE );
    330 
    331 	 for (;j+1<count;j++) {
    332 	    GLboolean efj = EDGEFLAG_GET( ELT(j) );
    333 	    EDGEFLAG_SET( ELT(j), GL_FALSE );
    334 	    RENDER_TRI( ELT(j-1), ELT(j), ELT(start) );
    335 	    EDGEFLAG_SET( ELT(j), efj );
    336 	 }
    337       }
    338 
    339       /* Draw the last or only triangle
    340        */
    341       if (j < count)
    342 	 RENDER_TRI( ELT(j-1), ELT(j), ELT(start) );
    343 
    344       /* Restore the first and last edgeflags:
    345        */
    346       EDGEFLAG_SET( ELT(count-1), efcount );
    347       EDGEFLAG_SET( ELT(start), efstart );
    348 
    349    }
    350    else {
    351       for (j=start+2;j<count;j++) {
    352 	 RENDER_TRI( ELT(j-1), ELT(j), ELT(start) );
    353       }
    354    }
    355    POSTFIX;
    356 }
    357 
    358 static void TAG(render_quads)( struct gl_context *ctx,
    359 			       GLuint start,
    360 			       GLuint count,
    361 			       GLuint flags )
    362 {
    363    GLuint j;
    364    LOCAL_VARS;
    365    (void) flags;
    366 
    367    INIT(GL_QUADS);
    368    if (NEED_EDGEFLAG_SETUP) {
    369       for (j=start+3; j<count; j+=4) {
    370 	 /* Use user-specified edgeflags for quads.
    371 	  */
    372 	 RESET_STIPPLE;
    373          if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT ||
    374              !ctx->Const.QuadsFollowProvokingVertexConvention)
    375             RENDER_QUAD( ELT(j-3), ELT(j-2), ELT(j-1), ELT(j) );
    376          else
    377             RENDER_QUAD( ELT(j-2), ELT(j-1), ELT(j), ELT(j-3) );
    378       }
    379    } else {
    380       for (j=start+3; j<count; j+=4) {
    381          if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT ||
    382              !ctx->Const.QuadsFollowProvokingVertexConvention)
    383             RENDER_QUAD( ELT(j-3), ELT(j-2), ELT(j-1), ELT(j) );
    384          else
    385             RENDER_QUAD( ELT(j-2), ELT(j-1), ELT(j), ELT(j-3) );
    386       }
    387    }
    388    POSTFIX;
    389 }
    390 
    391 static void TAG(render_quad_strip)( struct gl_context *ctx,
    392 				    GLuint start,
    393 				    GLuint count,
    394 				    GLuint flags )
    395 {
    396    GLuint j;
    397    LOCAL_VARS;
    398    (void) flags;
    399 
    400    INIT(GL_QUAD_STRIP);
    401    if (NEED_EDGEFLAG_SETUP) {
    402       for (j=start+3;j<count;j+=2) {
    403 	 /* All edges are boundary.  Set edgeflags to 1, draw the
    404 	  * quad, and restore them to the original values.
    405 	  */
    406 	 GLboolean ef3 = EDGEFLAG_GET( ELT(j-3) );
    407 	 GLboolean ef2 = EDGEFLAG_GET( ELT(j-2) );
    408 	 GLboolean ef1 = EDGEFLAG_GET( ELT(j-1) );
    409 	 GLboolean ef = EDGEFLAG_GET( ELT(j) );
    410 	 if (TEST_PRIM_BEGIN(flags)) {
    411 	    RESET_STIPPLE;
    412 	 }
    413 	 EDGEFLAG_SET( ELT(j-3), GL_TRUE );
    414 	 EDGEFLAG_SET( ELT(j-2), GL_TRUE );
    415 	 EDGEFLAG_SET( ELT(j-1), GL_TRUE );
    416 	 EDGEFLAG_SET( ELT(j), GL_TRUE );
    417          if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT ||
    418              !ctx->Const.QuadsFollowProvokingVertexConvention)
    419             RENDER_QUAD( ELT(j-1), ELT(j-3), ELT(j-2), ELT(j) );
    420          else
    421             RENDER_QUAD( ELT(j-2), ELT(j), ELT(j-1), ELT(j-3) );
    422 	 EDGEFLAG_SET( ELT(j-3), ef3 );
    423 	 EDGEFLAG_SET( ELT(j-2), ef2 );
    424 	 EDGEFLAG_SET( ELT(j-1), ef1 );
    425 	 EDGEFLAG_SET( ELT(j), ef );
    426       }
    427    } else {
    428       for (j=start+3;j<count;j+=2) {
    429          if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT ||
    430              !ctx->Const.QuadsFollowProvokingVertexConvention)
    431             RENDER_QUAD( ELT(j-1), ELT(j-3), ELT(j-2), ELT(j) );
    432          else
    433             RENDER_QUAD( ELT(j-2), ELT(j), ELT(j-1), ELT(j-3) );
    434       }
    435    }
    436    POSTFIX;
    437 }
    438 
    439 static void TAG(render_noop)( struct gl_context *ctx,
    440 			      GLuint start,
    441 			      GLuint count,
    442 			      GLuint flags )
    443 {
    444    (void)(ctx && start && count && flags);
    445 }
    446 
    447 RENDER_TAB_QUALIFIER void (*TAG(render_tab)[GL_POLYGON+2])(struct gl_context *,
    448 							   GLuint,
    449 							   GLuint,
    450 							   GLuint) =
    451 {
    452    TAG(render_points),
    453    TAG(render_lines),
    454    TAG(render_line_loop),
    455    TAG(render_line_strip),
    456    TAG(render_triangles),
    457    TAG(render_tri_strip),
    458    TAG(render_tri_fan),
    459    TAG(render_quads),
    460    TAG(render_quad_strip),
    461    TAG(render_poly),
    462    TAG(render_noop),
    463 };
    464 
    465 
    466 
    467 #ifndef PRESERVE_VB_DEFS
    468 #undef RENDER_TRI
    469 #undef RENDER_QUAD
    470 #undef RENDER_LINE
    471 #undef RENDER_POINTS
    472 #undef LOCAL_VARS
    473 #undef INIT
    474 #undef POSTFIX
    475 #undef RESET_STIPPLE
    476 #undef DBG
    477 #undef ELT
    478 #undef RENDER_TAB_QUALIFIER
    479 #endif
    480 
    481 #ifndef PRESERVE_TAG
    482 #undef TAG
    483 #endif
    484 
    485 #undef PRESERVE_VB_DEFS
    486 #undef PRESERVE_TAG
    487