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
114static 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
339static 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
579static 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
601static 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
632static 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
657static 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