Home | History | Annotate | Download | only in tnl_dd
      1 /*
      2  * Mesa 3-D graphics library
      3  * Version:  6.3
      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 /* Template for building functions to plug into the driver interface
     30  * of t_vb_render.c:
     31  *     ctx->Driver.QuadFunc
     32  *     ctx->Driver.TriangleFunc
     33  *     ctx->Driver.LineFunc
     34  *     ctx->Driver.PointsFunc
     35  *
     36  * DO_TWOSIDE:   Plug back-color values from the VB into backfacing triangles,
     37  *               and restore vertices afterwards.
     38  * DO_OFFSET:    Calculate offset for triangles and adjust vertices.  Restore
     39  *               vertices after rendering.
     40  * DO_FLAT:      For hardware without native flatshading, copy provoking colors
     41  *               into the other vertices.  Restore after rendering.
     42  * DO_UNFILLED:  Decompose triangles to lines and points where appropriate.
     43  * DO_TWOSTENCIL:Gross hack for two-sided stencil.
     44  *
     45  * HAVE_SPEC: Vertices have secondary rgba values.
     46  *
     47  * VERT_X(v): Alias for vertex x value.
     48  * VERT_Y(v): Alias for vertex y value.
     49  * VERT_Z(v): Alias for vertex z value.
     50  * DEPTH_SCALE: Scale for constant offset.
     51  * REVERSE_DEPTH: Viewport depth range reversed.
     52  *
     53  * VERTEX: Hardware vertex type.
     54  * GET_VERTEX(n): Retreive vertex with index n.
     55  * AREA_IS_CCW(a): Return true if triangle with signed area a is ccw.
     56  *
     57  * VERT_SET_RGBA: Assign vertex rgba from VB color.
     58  * VERT_COPY_RGBA: Copy vertex rgba another vertex.
     59  * VERT_SAVE_RGBA: Save vertex rgba to a local variable.
     60  * VERT_RESTORE_RGBA: Restore vertex rgba from a local variable.
     61  *   --> Similar for SPEC.
     62  *
     63  * LOCAL_VARS(n): (At least) define local vars for save/restore rgba.
     64  *
     65  */
     66 
     67 #if HAVE_BACK_COLORS
     68 #define VERT_SET_RGBA( v, c )
     69 #endif
     70 
     71 #if !HAVE_SPEC
     72 #define VERT_SET_SPEC( v, c ) (void) c
     73 #define VERT_COPY_SPEC( v0, v1 )
     74 #define VERT_SAVE_SPEC( idx )
     75 #define VERT_RESTORE_SPEC( idx )
     76 #if HAVE_BACK_COLORS
     77 #define VERT_COPY_SPEC1( v )
     78 #endif
     79 #else
     80 #if HAVE_BACK_COLORS
     81 #define VERT_SET_SPEC( v, c )
     82 #endif
     83 #endif
     84 
     85 #if !HAVE_BACK_COLORS
     86 #define VERT_COPY_SPEC1( v )
     87 #define VERT_COPY_RGBA1( v )
     88 #endif
     89 
     90 #ifndef INSANE_VERTICES
     91 #define VERT_SET_Z(v,val) VERT_Z(v) = val
     92 #define VERT_Z_ADD(v,val) VERT_Z(v) += val
     93 #endif
     94 
     95 #ifndef REVERSE_DEPTH
     96 #define REVERSE_DEPTH 0
     97 #endif
     98 
     99 /* disable twostencil for un-aware drivers */
    100 #ifndef HAVE_STENCIL_TWOSIDE
    101 #define HAVE_STENCIL_TWOSIDE 0
    102 #endif
    103 #ifndef DO_TWOSTENCIL
    104 #define DO_TWOSTENCIL 0
    105 #endif
    106 #ifndef SETUP_STENCIL
    107 #define SETUP_STENCIL(f)
    108 #endif
    109 #ifndef UNSET_STENCIL
    110 #define UNSET_STENCIL(f)
    111 #endif
    112 
    113 #if DO_TRI
    114 static void TAG(triangle)( struct gl_context *ctx, GLuint e0, GLuint e1, GLuint e2 )
    115 {
    116    struct vertex_buffer *VB = &TNL_CONTEXT( ctx )->vb;
    117    VERTEX *v[3];
    118    GLfloat offset = 0;
    119    GLfloat z[3] = { 0 };
    120    GLenum mode = GL_FILL;
    121    GLuint facing = 0;
    122    LOCAL_VARS(3);
    123 
    124 /*     fprintf(stderr, "%s\n", __FUNCTION__); */
    125 
    126    v[0] = (VERTEX *)GET_VERTEX(e0);
    127    v[1] = (VERTEX *)GET_VERTEX(e1);
    128    v[2] = (VERTEX *)GET_VERTEX(e2);
    129 
    130    if (DO_TWOSIDE || DO_OFFSET || DO_UNFILLED || DO_TWOSTENCIL)
    131    {
    132       GLfloat ex = VERT_X(v[0]) - VERT_X(v[2]);
    133       GLfloat ey = VERT_Y(v[0]) - VERT_Y(v[2]);
    134       GLfloat fx = VERT_X(v[1]) - VERT_X(v[2]);
    135       GLfloat fy = VERT_Y(v[1]) - VERT_Y(v[2]);
    136       GLfloat cc = ex*fy - ey*fx;
    137 
    138       if (DO_TWOSIDE || DO_UNFILLED || DO_TWOSTENCIL)
    139       {
    140 	 facing = AREA_IS_CCW( cc ) ^ ctx->Polygon._FrontBit;
    141 
    142 	 if (DO_UNFILLED) {
    143 	    if (facing) {
    144 	       mode = ctx->Polygon.BackMode;
    145 	       if (ctx->Polygon.CullFlag &&
    146 		   ctx->Polygon.CullFaceMode != GL_FRONT) {
    147 		  return;
    148 	       }
    149 	    } else {
    150 	       mode = ctx->Polygon.FrontMode;
    151 	       if (ctx->Polygon.CullFlag &&
    152 		   ctx->Polygon.CullFaceMode != GL_BACK) {
    153 		  return;
    154 	       }
    155 	    }
    156 	 }
    157 
    158 	 if (DO_TWOSIDE && facing == 1) {
    159 	    if (HAVE_BACK_COLORS) {
    160 	       if (!DO_FLAT) {
    161 		  VERT_SAVE_RGBA( 0 );
    162 		  VERT_SAVE_RGBA( 1 );
    163 		  VERT_COPY_RGBA1( v[0] );
    164 		  VERT_COPY_RGBA1( v[1] );
    165 	       }
    166 	       VERT_SAVE_RGBA( 2 );
    167 	       VERT_COPY_RGBA1( v[2] );
    168 	       if (HAVE_SPEC) {
    169 		  if (!DO_FLAT) {
    170 		     VERT_SAVE_SPEC( 0 );
    171 		     VERT_SAVE_SPEC( 1 );
    172 		     VERT_COPY_SPEC1( v[0] );
    173 		     VERT_COPY_SPEC1( v[1] );
    174 		  }
    175 		  VERT_SAVE_SPEC( 2 );
    176 		  VERT_COPY_SPEC1( v[2] );
    177 	       }
    178 	    }
    179 	    else {
    180 	       GLfloat (*vbcolor)[4] = VB->BackfaceColorPtr->data;
    181 	       (void) vbcolor;
    182 
    183 	       if (!DO_FLAT) {
    184 		  VERT_SAVE_RGBA( 0 );
    185 		  VERT_SAVE_RGBA( 1 );
    186 	       }
    187 	       VERT_SAVE_RGBA( 2 );
    188 
    189 	       if (VB->BackfaceColorPtr->stride) {
    190 		  ASSERT(VB->BackfaceColorPtr->stride == 4*sizeof(GLfloat));
    191 
    192 		  if (!DO_FLAT) {
    193 		     VERT_SET_RGBA( v[0], vbcolor[e0] );
    194 		     VERT_SET_RGBA( v[1], vbcolor[e1] );
    195 		  }
    196 		  VERT_SET_RGBA( v[2], vbcolor[e2] );
    197 	       }
    198 	       else {
    199 		  if (!DO_FLAT) {
    200 		     VERT_SET_RGBA( v[0], vbcolor[0] );
    201 		     VERT_SET_RGBA( v[1], vbcolor[0] );
    202 		  }
    203 		  VERT_SET_RGBA( v[2], vbcolor[0] );
    204 	       }
    205 
    206 	       if (HAVE_SPEC && VB->BackfaceSecondaryColorPtr) {
    207 		  GLfloat (*vbspec)[4] = VB->BackfaceSecondaryColorPtr->data;
    208 		  ASSERT(VB->BackfaceSecondaryColorPtr->stride == 4*sizeof(GLfloat));
    209 
    210 		  if (!DO_FLAT) {
    211 		     VERT_SAVE_SPEC( 0 );
    212 		     VERT_SAVE_SPEC( 1 );
    213 		     VERT_SET_SPEC( v[0], vbspec[e0] );
    214 		     VERT_SET_SPEC( v[1], vbspec[e1] );
    215 		  }
    216 		  VERT_SAVE_SPEC( 2 );
    217 		  VERT_SET_SPEC( v[2], vbspec[e2] );
    218 	       }
    219 	    }
    220 	 }
    221       }
    222 
    223 
    224       if (DO_OFFSET)
    225       {
    226 	 offset = ctx->Polygon.OffsetUnits * DEPTH_SCALE;
    227 	 z[0] = VERT_Z(v[0]);
    228 	 z[1] = VERT_Z(v[1]);
    229 	 z[2] = VERT_Z(v[2]);
    230 	 if (cc * cc > 1e-16) {
    231 	    GLfloat ic	= 1.0 / cc;
    232 	    GLfloat ez	= z[0] - z[2];
    233 	    GLfloat fz	= z[1] - z[2];
    234 	    GLfloat a	= ey*fz - ez*fy;
    235 	    GLfloat b	= ez*fx - ex*fz;
    236 	    GLfloat ac	= a * ic;
    237 	    GLfloat bc	= b * ic;
    238 	    if ( ac < 0.0f ) ac = -ac;
    239 	    if ( bc < 0.0f ) bc = -bc;
    240 	    offset += MAX2( ac, bc ) * ctx->Polygon.OffsetFactor / ctx->DrawBuffer->_MRD;
    241 	 }
    242 	 offset *= ctx->DrawBuffer->_MRD * (REVERSE_DEPTH ? -1.0 : 1.0);
    243       }
    244    }
    245 
    246    if (DO_FLAT) {
    247       VERT_SAVE_RGBA( 0 );
    248       VERT_SAVE_RGBA( 1 );
    249       VERT_COPY_RGBA( v[0], v[2] );
    250       VERT_COPY_RGBA( v[1], v[2] );
    251       if (HAVE_SPEC && VB->AttribPtr[_TNL_ATTRIB_COLOR1]) {
    252 	 VERT_SAVE_SPEC( 0 );
    253 	 VERT_SAVE_SPEC( 1 );
    254 	 VERT_COPY_SPEC( v[0], v[2] );
    255 	 VERT_COPY_SPEC( v[1], v[2] );
    256       }
    257    }
    258 
    259    if (mode == GL_POINT) {
    260       if (DO_OFFSET && ctx->Polygon.OffsetPoint) {
    261 	 VERT_Z_ADD(v[0], offset);
    262 	 VERT_Z_ADD(v[1], offset);
    263 	 VERT_Z_ADD(v[2], offset);
    264       }
    265       if (DO_TWOSTENCIL && !HAVE_STENCIL_TWOSIDE && ctx->Stencil.TestTwoSide) {
    266          SETUP_STENCIL(facing);
    267          UNFILLED_TRI( ctx, GL_POINT, e0, e1, e2 );
    268          UNSET_STENCIL(facing);
    269       } else {
    270          UNFILLED_TRI( ctx, GL_POINT, e0, e1, e2 );
    271       }
    272    } else if (mode == GL_LINE) {
    273       if (DO_OFFSET && ctx->Polygon.OffsetLine) {
    274 	 VERT_Z_ADD(v[0], offset);
    275 	 VERT_Z_ADD(v[1], offset);
    276 	 VERT_Z_ADD(v[2], offset);
    277       }
    278       if (DO_TWOSTENCIL && !HAVE_STENCIL_TWOSIDE && ctx->Stencil.TestTwoSide) {
    279          SETUP_STENCIL(facing);
    280          UNFILLED_TRI( ctx, GL_LINE, e0, e1, e2 );
    281          UNSET_STENCIL(facing);
    282       } else {
    283          UNFILLED_TRI( ctx, GL_LINE, e0, e1, e2 );
    284       }
    285    } else {
    286       if (DO_OFFSET && ctx->Polygon.OffsetFill) {
    287 	 VERT_Z_ADD(v[0], offset);
    288 	 VERT_Z_ADD(v[1], offset);
    289 	 VERT_Z_ADD(v[2], offset);
    290       }
    291       if (DO_UNFILLED) {
    292 	 RASTERIZE( GL_TRIANGLES );
    293       }
    294       if (DO_TWOSTENCIL && !HAVE_STENCIL_TWOSIDE && ctx->Stencil.TestTwoSide) {
    295          SETUP_STENCIL(facing);
    296          TRI( v[0], v[1], v[2] );
    297          UNSET_STENCIL(facing);
    298       } else {
    299          TRI( v[0], v[1], v[2] );
    300       }
    301    }
    302 
    303    if (DO_OFFSET)
    304    {
    305       VERT_SET_Z(v[0], z[0]);
    306       VERT_SET_Z(v[1], z[1]);
    307       VERT_SET_Z(v[2], z[2]);
    308    }
    309 
    310    if (DO_TWOSIDE && facing == 1) {
    311       if (!DO_FLAT) {
    312 	 VERT_RESTORE_RGBA( 0 );
    313 	 VERT_RESTORE_RGBA( 1 );
    314       }
    315       VERT_RESTORE_RGBA( 2 );
    316       if (HAVE_SPEC) {
    317 	 if (!DO_FLAT) {
    318 	    VERT_RESTORE_SPEC( 0 );
    319 	    VERT_RESTORE_SPEC( 1 );
    320 	 }
    321 	 VERT_RESTORE_SPEC( 2 );
    322       }
    323    }
    324 
    325 
    326    if (DO_FLAT) {
    327 	 VERT_RESTORE_RGBA( 0 );
    328 	 VERT_RESTORE_RGBA( 1 );
    329 	 if (HAVE_SPEC && VB->AttribPtr[_TNL_ATTRIB_COLOR1]) {
    330 	    VERT_RESTORE_SPEC( 0 );
    331 	    VERT_RESTORE_SPEC( 1 );
    332 	 }
    333    }
    334 }
    335 #endif
    336 
    337 #if DO_QUAD
    338 #if DO_FULL_QUAD
    339 static void TAG(quadr)( struct gl_context *ctx,
    340 		       GLuint e0, GLuint e1, GLuint e2, GLuint e3 )
    341 {
    342    struct vertex_buffer *VB = &TNL_CONTEXT( ctx )->vb;
    343    VERTEX *v[4];
    344    GLfloat offset = 0;
    345    GLfloat z[4] = { 0 };
    346    GLenum mode = GL_FILL;
    347    GLuint facing = 0;
    348    LOCAL_VARS(4);
    349 
    350    v[0] = (VERTEX *)GET_VERTEX(e0);
    351    v[1] = (VERTEX *)GET_VERTEX(e1);
    352    v[2] = (VERTEX *)GET_VERTEX(e2);
    353    v[3] = (VERTEX *)GET_VERTEX(e3);
    354 
    355    if (DO_TWOSIDE || DO_OFFSET || DO_UNFILLED || DO_TWOSTENCIL)
    356    {
    357       GLfloat ex = VERT_X(v[2]) - VERT_X(v[0]);
    358       GLfloat ey = VERT_Y(v[2]) - VERT_Y(v[0]);
    359       GLfloat fx = VERT_X(v[3]) - VERT_X(v[1]);
    360       GLfloat fy = VERT_Y(v[3]) - VERT_Y(v[1]);
    361       GLfloat cc = ex*fy - ey*fx;
    362 
    363       if (DO_TWOSIDE || DO_UNFILLED || DO_TWOSTENCIL)
    364       {
    365 	 facing = AREA_IS_CCW( cc ) ^ ctx->Polygon._FrontBit;
    366 
    367 	 if (DO_UNFILLED) {
    368 	    if (facing) {
    369 	       mode = ctx->Polygon.BackMode;
    370 	       if (ctx->Polygon.CullFlag &&
    371 		   ctx->Polygon.CullFaceMode != GL_FRONT) {
    372 		  return;
    373 	       }
    374 	    } else {
    375 	       mode = ctx->Polygon.FrontMode;
    376 	       if (ctx->Polygon.CullFlag &&
    377 		   ctx->Polygon.CullFaceMode != GL_BACK) {
    378 		  return;
    379 	       }
    380 	    }
    381 	 }
    382 
    383 	 if (DO_TWOSIDE && facing == 1) {
    384 	    GLfloat (*vbcolor)[4] = VB->BackfaceColorPtr->data;
    385 	    (void)vbcolor;
    386 
    387 	    if (HAVE_BACK_COLORS) {
    388 	       if (!DO_FLAT) {
    389 		  VERT_SAVE_RGBA( 0 );
    390 		  VERT_SAVE_RGBA( 1 );
    391 		  VERT_SAVE_RGBA( 2 );
    392 		  VERT_COPY_RGBA1( v[0] );
    393 		  VERT_COPY_RGBA1( v[1] );
    394 		  VERT_COPY_RGBA1( v[2] );
    395 	       }
    396 	       VERT_SAVE_RGBA( 3 );
    397 	       VERT_COPY_RGBA1( v[3] );
    398 	       if (HAVE_SPEC) {
    399 		  if (!DO_FLAT) {
    400 		     VERT_SAVE_SPEC( 0 );
    401 		     VERT_SAVE_SPEC( 1 );
    402 		     VERT_SAVE_SPEC( 2 );
    403 		     VERT_COPY_SPEC1( v[0] );
    404 		     VERT_COPY_SPEC1( v[1] );
    405 		     VERT_COPY_SPEC1( v[2] );
    406 		  }
    407 		  VERT_SAVE_SPEC( 3 );
    408 		  VERT_COPY_SPEC1( v[3] );
    409 	       }
    410 	    }
    411 	    else {
    412 	       if (!DO_FLAT) {
    413 		  VERT_SAVE_RGBA( 0 );
    414 		  VERT_SAVE_RGBA( 1 );
    415 		  VERT_SAVE_RGBA( 2 );
    416 	       }
    417 	       VERT_SAVE_RGBA( 3 );
    418 
    419 	       if (VB->BackfaceColorPtr->stride) {
    420 		  if (!DO_FLAT) {
    421 		     VERT_SET_RGBA( v[0], vbcolor[e0] );
    422 		     VERT_SET_RGBA( v[1], vbcolor[e1] );
    423 		     VERT_SET_RGBA( v[2], vbcolor[e2] );
    424 		  }
    425 		  VERT_SET_RGBA( v[3], vbcolor[e3] );
    426 	       }
    427 	       else {
    428 		  if (!DO_FLAT) {
    429 		     VERT_SET_RGBA( v[0], vbcolor[0] );
    430 		     VERT_SET_RGBA( v[1], vbcolor[0] );
    431 		     VERT_SET_RGBA( v[2], vbcolor[0] );
    432 		  }
    433 		  VERT_SET_RGBA( v[3], vbcolor[0] );
    434 	       }
    435 
    436 	       if (HAVE_SPEC && VB->BackfaceSecondaryColorPtr) {
    437 		  GLfloat (*vbspec)[4] = VB->BackfaceSecondaryColorPtr->data;
    438 		  ASSERT(VB->BackfaceSecondaryColorPtr->stride==4*sizeof(GLfloat));
    439 
    440 		  if (!DO_FLAT) {
    441 		     VERT_SAVE_SPEC( 0 );
    442 		     VERT_SAVE_SPEC( 1 );
    443 		     VERT_SAVE_SPEC( 2 );
    444 		     VERT_SET_SPEC( v[0], vbspec[e0] );
    445 		     VERT_SET_SPEC( v[1], vbspec[e1] );
    446 		     VERT_SET_SPEC( v[2], vbspec[e2] );
    447 		  }
    448 		  VERT_SAVE_SPEC( 3 );
    449 		  VERT_SET_SPEC( v[3], vbspec[e3] );
    450 	       }
    451 	    }
    452 	 }
    453       }
    454 
    455 
    456       if (DO_OFFSET)
    457       {
    458 	 offset = ctx->Polygon.OffsetUnits * DEPTH_SCALE;
    459 	 z[0] = VERT_Z(v[0]);
    460 	 z[1] = VERT_Z(v[1]);
    461 	 z[2] = VERT_Z(v[2]);
    462 	 z[3] = VERT_Z(v[3]);
    463 	 if (cc * cc > 1e-16) {
    464 	    GLfloat ez = z[2] - z[0];
    465 	    GLfloat fz = z[3] - z[1];
    466 	    GLfloat a	= ey*fz - ez*fy;
    467 	    GLfloat b	= ez*fx - ex*fz;
    468 	    GLfloat ic	= 1.0 / cc;
    469 	    GLfloat ac	= a * ic;
    470 	    GLfloat bc	= b * ic;
    471 	    if ( ac < 0.0f ) ac = -ac;
    472 	    if ( bc < 0.0f ) bc = -bc;
    473 	    offset += MAX2( ac, bc ) * ctx->Polygon.OffsetFactor / ctx->DrawBuffer->_MRD;
    474 	 }
    475 	 offset *= ctx->DrawBuffer->_MRD * (REVERSE_DEPTH ? -1.0 : 1.0);
    476       }
    477    }
    478 
    479    if (DO_FLAT) {
    480 	 VERT_SAVE_RGBA( 0 );
    481 	 VERT_SAVE_RGBA( 1 );
    482 	 VERT_SAVE_RGBA( 2 );
    483 	 VERT_COPY_RGBA( v[0], v[3] );
    484 	 VERT_COPY_RGBA( v[1], v[3] );
    485 	 VERT_COPY_RGBA( v[2], v[3] );
    486 	 if (HAVE_SPEC && VB->AttribPtr[_TNL_ATTRIB_COLOR1]) {
    487 	    VERT_SAVE_SPEC( 0 );
    488 	    VERT_SAVE_SPEC( 1 );
    489 	    VERT_SAVE_SPEC( 2 );
    490 	    VERT_COPY_SPEC( v[0], v[3] );
    491 	    VERT_COPY_SPEC( v[1], v[3] );
    492 	    VERT_COPY_SPEC( v[2], v[3] );
    493 	 }
    494    }
    495 
    496    if (mode == GL_POINT) {
    497       if (( DO_OFFSET) && ctx->Polygon.OffsetPoint) {
    498 	 VERT_Z_ADD(v[0], offset);
    499 	 VERT_Z_ADD(v[1], offset);
    500 	 VERT_Z_ADD(v[2], offset);
    501 	 VERT_Z_ADD(v[3], offset);
    502       }
    503       if (DO_TWOSTENCIL && !HAVE_STENCIL_TWOSIDE && ctx->Stencil.TestTwoSide) {
    504          SETUP_STENCIL(facing);
    505          UNFILLED_QUAD( ctx, GL_POINT, e0, e1, e2, e3 );
    506          UNSET_STENCIL(facing);
    507       } else {
    508          UNFILLED_QUAD( ctx, GL_POINT, e0, e1, e2, e3 );
    509       }
    510    } else if (mode == GL_LINE) {
    511       if (DO_OFFSET && ctx->Polygon.OffsetLine) {
    512 	 VERT_Z_ADD(v[0], offset);
    513 	 VERT_Z_ADD(v[1], offset);
    514 	 VERT_Z_ADD(v[2], offset);
    515 	 VERT_Z_ADD(v[3], offset);
    516       }
    517       if (DO_TWOSTENCIL && !HAVE_STENCIL_TWOSIDE && ctx->Stencil.TestTwoSide) {
    518          SETUP_STENCIL(facing);
    519          UNFILLED_QUAD( ctx, GL_LINE, e0, e1, e2, e3 );
    520          UNSET_STENCIL(facing);
    521       } else {
    522          UNFILLED_QUAD( ctx, GL_LINE, e0, e1, e2, e3 );
    523       }
    524    } else {
    525       if (DO_OFFSET && ctx->Polygon.OffsetFill) {
    526 	 VERT_Z_ADD(v[0], offset);
    527 	 VERT_Z_ADD(v[1], offset);
    528 	 VERT_Z_ADD(v[2], offset);
    529 	 VERT_Z_ADD(v[3], offset);
    530       }
    531       RASTERIZE( GL_QUADS );
    532       if (DO_TWOSTENCIL && !HAVE_STENCIL_TWOSIDE && ctx->Stencil.TestTwoSide) {
    533          SETUP_STENCIL(facing);
    534          QUAD( (v[0]), (v[1]), (v[2]), (v[3]) );
    535          UNSET_STENCIL(facing);
    536       } else {
    537          QUAD( (v[0]), (v[1]), (v[2]), (v[3]) );
    538       }
    539    }
    540 
    541    if (DO_OFFSET)
    542    {
    543       VERT_SET_Z(v[0], z[0]);
    544       VERT_SET_Z(v[1], z[1]);
    545       VERT_SET_Z(v[2], z[2]);
    546       VERT_SET_Z(v[3], z[3]);
    547    }
    548 
    549    if (DO_TWOSIDE && facing == 1) {
    550       if (!DO_FLAT) {
    551 	 VERT_RESTORE_RGBA( 0 );
    552 	 VERT_RESTORE_RGBA( 1 );
    553 	 VERT_RESTORE_RGBA( 2 );
    554       }
    555       VERT_RESTORE_RGBA( 3 );
    556       if (HAVE_SPEC) {
    557 	 if (!DO_FLAT) {
    558 	    VERT_RESTORE_SPEC( 0 );
    559 	    VERT_RESTORE_SPEC( 1 );
    560 	    VERT_RESTORE_SPEC( 2 );
    561 	 }
    562 	 VERT_RESTORE_SPEC( 3 );
    563       }
    564    }
    565 
    566 
    567    if (DO_FLAT) {
    568 	 VERT_RESTORE_RGBA( 0 );
    569 	 VERT_RESTORE_RGBA( 1 );
    570 	 VERT_RESTORE_RGBA( 2 );
    571 	 if (HAVE_SPEC && VB->AttribPtr[_TNL_ATTRIB_COLOR1]) {
    572 	    VERT_RESTORE_SPEC( 0 );
    573 	    VERT_RESTORE_SPEC( 1 );
    574 	    VERT_RESTORE_SPEC( 2 );
    575 	 }
    576    }
    577 }
    578 #else
    579 static void TAG(quadr)( struct gl_context *ctx, GLuint e0,
    580 		       GLuint e1, GLuint e2, GLuint e3 )
    581 {
    582    if (DO_UNFILLED) {
    583       struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
    584       GLubyte ef1 = VB->EdgeFlag[e1];
    585       GLubyte ef3 = VB->EdgeFlag[e3];
    586       VB->EdgeFlag[e1] = 0;
    587       TAG(triangle)( ctx, e0, e1, e3 );
    588       VB->EdgeFlag[e1] = ef1;
    589       VB->EdgeFlag[e3] = 0;
    590       TAG(triangle)( ctx, e1, e2, e3 );
    591       VB->EdgeFlag[e3] = ef3;
    592    } else {
    593       TAG(triangle)( ctx, e0, e1, e3 );
    594       TAG(triangle)( ctx, e1, e2, e3 );
    595    }
    596 }
    597 #endif
    598 #endif
    599 
    600 #if DO_LINE
    601 static void TAG(line)( struct gl_context *ctx, GLuint e0, GLuint e1 )
    602 {
    603    struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
    604    VERTEX *v[2];
    605    LOCAL_VARS(2);
    606 
    607    v[0] = (VERTEX *)GET_VERTEX(e0);
    608    v[1] = (VERTEX *)GET_VERTEX(e1);
    609 
    610    if (DO_FLAT) {
    611 	 VERT_SAVE_RGBA( 0 );
    612 	 VERT_COPY_RGBA( v[0], v[1] );
    613 	 if (HAVE_SPEC && VB->AttribPtr[_TNL_ATTRIB_COLOR1]) {
    614 	    VERT_SAVE_SPEC( 0 );
    615 	    VERT_COPY_SPEC( v[0], v[1] );
    616 	 }
    617    }
    618 
    619    LINE( v[0], v[1] );
    620 
    621    if (DO_FLAT) {
    622 	 VERT_RESTORE_RGBA( 0 );
    623 
    624 	 if (HAVE_SPEC && VB->AttribPtr[_TNL_ATTRIB_COLOR1]) {
    625 	    VERT_RESTORE_SPEC( 0 );
    626 	 }
    627    }
    628 }
    629 #endif
    630 
    631 #if DO_POINTS
    632 static void TAG(points)( struct gl_context *ctx, GLuint first, GLuint last )
    633 {
    634    struct vertex_buffer *VB = &TNL_CONTEXT( ctx )->vb;
    635    GLuint i;
    636    LOCAL_VARS(1);
    637 
    638    if (VB->Elts == 0) {
    639       for ( i = first ; i < last ; i++ ) {
    640 	 if ( VB->ClipMask[i] == 0 ) {
    641 	    VERTEX *v = (VERTEX *)GET_VERTEX(i);
    642 	    POINT( v );
    643 	 }
    644       }
    645    } else {
    646       for ( i = first ; i < last ; i++ ) {
    647 	 GLuint e = VB->Elts[i];
    648 	 if ( VB->ClipMask[e] == 0 ) {
    649 	    VERTEX *v = (VERTEX *)GET_VERTEX(e);
    650 	    POINT( v );
    651 	 }
    652       }
    653    }
    654 }
    655 #endif
    656 
    657 static void TAG(init)( void )
    658 {
    659 #if DO_QUAD
    660    TAB[IND].quad = TAG(quadr);
    661 #endif
    662 #if DO_TRI
    663    TAB[IND].triangle = TAG(triangle);
    664 #endif
    665 #if DO_LINE
    666    TAB[IND].line = TAG(line);
    667 #endif
    668 #if DO_POINTS
    669    TAB[IND].points = TAG(points);
    670 #endif
    671 }
    672 
    673 #undef IND
    674 #undef TAG
    675 
    676 #if HAVE_BACK_COLORS
    677 #undef VERT_SET_RGBA
    678 #endif
    679 
    680 #if !HAVE_SPEC
    681 #undef VERT_SET_SPEC
    682 #undef VERT_COPY_SPEC
    683 #undef VERT_SAVE_SPEC
    684 #undef VERT_RESTORE_SPEC
    685 #if HAVE_BACK_COLORS
    686 #undef VERT_COPY_SPEC1
    687 #endif
    688 #else
    689 #if HAVE_BACK_COLORS
    690 #undef VERT_SET_SPEC
    691 #endif
    692 #endif
    693 
    694 #if !HAVE_BACK_COLORS
    695 #undef VERT_COPY_SPEC1
    696 #undef VERT_COPY_RGBA1
    697 #endif
    698 
    699 #ifndef INSANE_VERTICES
    700 #undef VERT_SET_Z
    701 #undef VERT_Z_ADD
    702 #endif
    703