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@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
TAG(triangle)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
TAG(quadr)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
TAG(quadr)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
TAG(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
TAG(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 
TAG(init)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