s_tritemp.h revision 9ab512ad8cf3a12f4f7f8494fa99bc9389f217db
1/*
2 * Mesa 3-D graphics library
3 * Version:  6.5
4 *
5 * Copyright (C) 1999-2006  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
25/*
26 * Triangle Rasterizer Template
27 *
28 * This file is #include'd to generate custom triangle rasterizers.
29 *
30 * The following macros may be defined to indicate what auxillary information
31 * must be interpolated across the triangle:
32 *    INTERP_Z        - if defined, interpolate vertex Z values
33 *    INTERP_W        - if defined, interpolate vertex W values
34 *    INTERP_FOG      - if defined, interpolate fog values
35 *    INTERP_RGB      - if defined, interpolate RGB values
36 *    INTERP_ALPHA    - if defined, interpolate Alpha values (req's INTERP_RGB)
37 *    INTERP_SPEC     - if defined, interpolate specular RGB values
38 *    INTERP_INDEX    - if defined, interpolate color index values
39 *    INTERP_INT_TEX  - if defined, interpolate integer ST texcoords
40 *                         (fast, simple 2-D texture mapping)
41 *    INTERP_TEX      - if defined, interpolate set 0 float STRQ texcoords
42 *                         NOTE:  OpenGL STRQ = Mesa STUV (R was taken for red)
43 *    INTERP_MULTITEX - if defined, interpolate N units of STRQ texcoords
44 *    INTERP_VARYING  - if defined, interpolate M GLSL varyings
45 *
46 * When one can directly address pixels in the color buffer the following
47 * macros can be defined and used to compute pixel addresses during
48 * rasterization (see pRow):
49 *    PIXEL_TYPE          - the datatype of a pixel (GLubyte, GLushort, GLuint)
50 *    BYTES_PER_ROW       - number of bytes per row in the color buffer
51 *    PIXEL_ADDRESS(X,Y)  - returns the address of pixel at (X,Y) where
52 *                          Y==0 at bottom of screen and increases upward.
53 *
54 * Similarly, for direct depth buffer access, this type is used for depth
55 * buffer addressing:
56 *    DEPTH_TYPE          - either GLushort or GLuint
57 *
58 * Optionally, one may provide one-time setup code per triangle:
59 *    SETUP_CODE    - code which is to be executed once per triangle
60 *    CLEANUP_CODE    - code to execute at end of triangle
61 *
62 * The following macro MUST be defined:
63 *    RENDER_SPAN(span) - code to write a span of pixels.
64 *
65 * This code was designed for the origin to be in the lower-left corner.
66 *
67 * Inspired by triangle rasterizer code written by Allen Akin.  Thanks Allen!
68 *
69 *
70 * Some notes on rasterization accuracy:
71 *
72 * This code uses fixed point arithmetic (the GLfixed type) to iterate
73 * over the triangle edges and interpolate ancillary data (such as Z,
74 * color, secondary color, etc).  The number of fractional bits in
75 * GLfixed and the value of SUB_PIXEL_BITS has a direct bearing on the
76 * accuracy of rasterization.
77 *
78 * If SUB_PIXEL_BITS=4 then we'll snap the vertices to the nearest
79 * 1/16 of a pixel.  If we're walking up a long, nearly vertical edge
80 * (dx=1/16, dy=1024) we'll need 4 + 10 = 14 fractional bits in
81 * GLfixed to walk the edge without error.  If the maximum viewport
82 * height is 4K pixels, then we'll need 4 + 12 = 16 fractional bits.
83 *
84 * Historically, Mesa has used 11 fractional bits in GLfixed, snaps
85 * vertices to 1/16 pixel and allowed a maximum viewport height of 2K
86 * pixels.  11 fractional bits is actually insufficient for accurately
87 * rasterizing some triangles.  More recently, the maximum viewport
88 * height was increased to 4K pixels.  Thus, Mesa should be using 16
89 * fractional bits in GLfixed.  Unfortunately, there may be some issues
90 * with setting FIXED_FRAC_BITS=16, such as multiplication overflow.
91 * This will have to be examined in some detail...
92 *
93 * For now, if you find rasterization errors, particularly with tall,
94 * sliver triangles, try increasing FIXED_FRAC_BITS and/or decreasing
95 * SUB_PIXEL_BITS.
96 */
97
98/*
99 * ColorTemp is used for intermediate color values.
100 */
101#if CHAN_TYPE == GL_FLOAT
102#define ColorTemp GLfloat
103#else
104#define ColorTemp GLint  /* same as GLfixed */
105#endif
106
107
108/*
109 * Walk triangle edges with GLfixed or GLdouble
110 */
111#if TRIANGLE_WALK_DOUBLE
112#define GLinterp        GLdouble
113#define InterpToInt(X)  ((GLint) (X))
114#define INTERP_ONE      1.0
115#else
116#define GLinterp        GLfixed
117#define InterpToInt(X)  FixedToInt(X)
118#define INTERP_ONE      FIXED_ONE
119#endif
120
121
122/*
123 * Either loop over all texture units, or just use unit zero.
124 */
125#ifdef INTERP_MULTITEX
126#define TEX_UNIT_LOOP(CODE)					\
127   {								\
128      GLuint u;							\
129      for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {	\
130         if (ctx->Texture._EnabledCoordUnits & (1 << u)) {	\
131            const GLuint attr = FRAG_ATTRIB_TEX0 + u;		\
132            (void) attr;                                        \
133            CODE						\
134         }							\
135      }								\
136   }
137#define INTERP_TEX
138#elif defined(INTERP_TEX)
139#define TEX_UNIT_LOOP(CODE)					\
140   {								\
141      const GLuint u = 0;					\
142      const GLuint attr = FRAG_ATTRIB_TEX0 + u;			\
143      (void) attr;                                              \
144      CODE							\
145   }
146#endif
147
148
149
150#ifdef INTERP_VARYING
151
152#define VARYING_LOOP(CODE)                       \
153   {                                             \
154      GLuint iv, ic;                             \
155      for (iv = 0; iv < MAX_VARYING; iv++) {     \
156         if (inputsUsed & FRAG_BIT_VAR(iv)) {    \
157            GLuint attr = FRAG_ATTRIB_VAR0 + iv; \
158            (void) attr;                         \
159            for (ic = 0; ic < 4; ic++) {         \
160               CODE                              \
161            }                                    \
162         }                                       \
163      }                                          \
164   }
165#endif
166
167
168
169/*
170 * Some code we unfortunately need to prevent negative interpolated colors.
171 */
172#ifndef CLAMP_INTERPOLANT
173#define CLAMP_INTERPOLANT(CHANNEL, CHANNELSTEP, LEN)		\
174do {								\
175   GLfixed endVal = span.CHANNEL + (LEN) * span.CHANNELSTEP;	\
176   if (endVal < 0) {						\
177      span.CHANNEL -= endVal;					\
178   }								\
179   if (span.CHANNEL < 0) {					\
180      span.CHANNEL = 0;						\
181   }								\
182} while (0)
183#endif
184
185
186static void NAME(GLcontext *ctx, const SWvertex *v0,
187                                 const SWvertex *v1,
188                                 const SWvertex *v2 )
189{
190   typedef struct {
191      const SWvertex *v0, *v1;   /* Y(v0) < Y(v1) */
192#if TRIANGLE_WALK_DOUBLE
193      GLdouble dx;	/* X(v1) - X(v0) */
194      GLdouble dy;	/* Y(v1) - Y(v0) */
195      GLdouble dxdy;	/* dx/dy */
196      GLdouble adjy;	/* adjust from v[0]->fy to fsy, scaled */
197      GLdouble fsx;	/* first sample point x coord */
198      GLdouble fsy;
199      GLdouble fx0;	/*X of lower endpoint */
200#else
201      GLfloat dx;	/* X(v1) - X(v0) */
202      GLfloat dy;	/* Y(v1) - Y(v0) */
203      GLfloat dxdy;	/* dx/dy */
204      GLfixed fdxdy;	/* dx/dy in fixed-point */
205      GLfloat adjy;	/* adjust from v[0]->fy to fsy, scaled */
206      GLfixed fsx;	/* first sample point x coord */
207      GLfixed fsy;
208      GLfixed fx0;	/* fixed pt X of lower endpoint */
209#endif
210      GLint lines;	/* number of lines to be sampled on this edge */
211   } EdgeT;
212
213#ifdef INTERP_Z
214   const GLint depthBits = ctx->DrawBuffer->Visual.depthBits;
215   const GLint fixedToDepthShift = depthBits <= 16 ? FIXED_SHIFT : 0;
216   const GLfloat maxDepth = ctx->DrawBuffer->_DepthMaxF;
217#define FixedToDepth(F)  ((F) >> fixedToDepthShift)
218#endif
219   EdgeT eMaj, eTop, eBot;
220   GLfloat oneOverArea;
221   const SWvertex *vMin, *vMid, *vMax;  /* Y(vMin)<=Y(vMid)<=Y(vMax) */
222   GLfloat bf = SWRAST_CONTEXT(ctx)->_BackfaceSign;
223#if !TRIANGLE_WALK_DOUBLE
224   const GLint snapMask = ~((FIXED_ONE / (1 << SUB_PIXEL_BITS)) - 1); /* for x/y coord snapping */
225#endif
226   GLinterp vMin_fx, vMin_fy, vMid_fx, vMid_fy, vMax_fx, vMax_fy;
227#ifdef INTERP_VARYING
228   const GLbitfield inputsUsed = ctx->FragmentProgram._Current ?
229      ctx->FragmentProgram._Current->Base.InputsRead : 0x0;
230#endif
231
232   SWspan span;
233
234   INIT_SPAN(span, GL_POLYGON, 0, 0, 0);
235
236#ifdef INTERP_Z
237   (void) fixedToDepthShift;
238#endif
239
240   /*
241   printf("%s()\n", __FUNCTION__);
242   printf("  %g, %g, %g\n", v0->win[0], v0->win[1], v0->win[2]);
243   printf("  %g, %g, %g\n", v1->win[0], v1->win[1], v1->win[2]);
244   printf("  %g, %g, %g\n", v2->win[0], v2->win[1], v2->win[2]);
245   */
246   /*
247   ASSERT(v0->win[2] >= 0.0);
248   ASSERT(v1->win[2] >= 0.0);
249   ASSERT(v2->win[2] >= 0.0);
250   */
251   /* Compute fixed point x,y coords w/ half-pixel offsets and snapping.
252    * And find the order of the 3 vertices along the Y axis.
253    */
254   {
255#if TRIANGLE_WALK_DOUBLE
256      const GLdouble fy0 = v0->win[1] - 0.5;
257      const GLdouble fy1 = v1->win[1] - 0.5;
258      const GLdouble fy2 = v2->win[1] - 0.5;
259#else
260      const GLfixed fy0 = FloatToFixed(v0->win[1] - 0.5F) & snapMask;
261      const GLfixed fy1 = FloatToFixed(v1->win[1] - 0.5F) & snapMask;
262      const GLfixed fy2 = FloatToFixed(v2->win[1] - 0.5F) & snapMask;
263#endif
264      if (fy0 <= fy1) {
265         if (fy1 <= fy2) {
266            /* y0 <= y1 <= y2 */
267            vMin = v0;   vMid = v1;   vMax = v2;
268            vMin_fy = fy0;  vMid_fy = fy1;  vMax_fy = fy2;
269         }
270         else if (fy2 <= fy0) {
271            /* y2 <= y0 <= y1 */
272            vMin = v2;   vMid = v0;   vMax = v1;
273            vMin_fy = fy2;  vMid_fy = fy0;  vMax_fy = fy1;
274         }
275         else {
276            /* y0 <= y2 <= y1 */
277            vMin = v0;   vMid = v2;   vMax = v1;
278            vMin_fy = fy0;  vMid_fy = fy2;  vMax_fy = fy1;
279            bf = -bf;
280         }
281      }
282      else {
283         if (fy0 <= fy2) {
284            /* y1 <= y0 <= y2 */
285            vMin = v1;   vMid = v0;   vMax = v2;
286            vMin_fy = fy1;  vMid_fy = fy0;  vMax_fy = fy2;
287            bf = -bf;
288         }
289         else if (fy2 <= fy1) {
290            /* y2 <= y1 <= y0 */
291            vMin = v2;   vMid = v1;   vMax = v0;
292            vMin_fy = fy2;  vMid_fy = fy1;  vMax_fy = fy0;
293            bf = -bf;
294         }
295         else {
296            /* y1 <= y2 <= y0 */
297            vMin = v1;   vMid = v2;   vMax = v0;
298            vMin_fy = fy1;  vMid_fy = fy2;  vMax_fy = fy0;
299         }
300      }
301
302      /* fixed point X coords */
303#if TRIANGLE_WALK_DOUBLE
304      vMin_fx = vMin->win[0] + 0.5;
305      vMid_fx = vMid->win[0] + 0.5;
306      vMax_fx = vMax->win[0] + 0.5;
307#else
308      vMin_fx = FloatToFixed(vMin->win[0] + 0.5F) & snapMask;
309      vMid_fx = FloatToFixed(vMid->win[0] + 0.5F) & snapMask;
310      vMax_fx = FloatToFixed(vMax->win[0] + 0.5F) & snapMask;
311#endif
312   }
313
314   /* vertex/edge relationship */
315   eMaj.v0 = vMin;   eMaj.v1 = vMax;   /*TODO: .v1's not needed */
316   eTop.v0 = vMid;   eTop.v1 = vMax;
317   eBot.v0 = vMin;   eBot.v1 = vMid;
318
319   /* compute deltas for each edge:  vertex[upper] - vertex[lower] */
320#if TRIANGLE_WALK_DOUBLE
321   eMaj.dx = vMax_fx - vMin_fx;
322   eMaj.dy = vMax_fy - vMin_fy;
323   eTop.dx = vMax_fx - vMid_fx;
324   eTop.dy = vMax_fy - vMid_fy;
325   eBot.dx = vMid_fx - vMin_fx;
326   eBot.dy = vMid_fy - vMin_fy;
327#else
328   eMaj.dx = FixedToFloat(vMax_fx - vMin_fx);
329   eMaj.dy = FixedToFloat(vMax_fy - vMin_fy);
330   eTop.dx = FixedToFloat(vMax_fx - vMid_fx);
331   eTop.dy = FixedToFloat(vMax_fy - vMid_fy);
332   eBot.dx = FixedToFloat(vMid_fx - vMin_fx);
333   eBot.dy = FixedToFloat(vMid_fy - vMin_fy);
334#endif
335
336   /* compute area, oneOverArea and perform backface culling */
337   {
338#if TRIANGLE_WALK_DOUBLE
339      const GLdouble area = eMaj.dx * eBot.dy - eBot.dx * eMaj.dy;
340#else
341      const GLfloat area = eMaj.dx * eBot.dy - eBot.dx * eMaj.dy;
342#endif
343      /* Do backface culling */
344      if (area * bf < 0.0)
345         return;
346
347      if (IS_INF_OR_NAN(area) || area == 0.0F)
348         return;
349
350      oneOverArea = 1.0F / area;
351   }
352
353
354   span.facing = ctx->_Facing; /* for 2-sided stencil test */
355
356   /* Edge setup.  For a triangle strip these could be reused... */
357   {
358#if TRIANGLE_WALK_DOUBLE
359      eMaj.fsy = CEILF(vMin_fy);
360      eMaj.lines = (GLint) CEILF(vMax_fy - eMaj.fsy);
361#else
362      eMaj.fsy = FixedCeil(vMin_fy);
363      eMaj.lines = FixedToInt(FixedCeil(vMax_fy - eMaj.fsy));
364#endif
365      if (eMaj.lines > 0) {
366         eMaj.dxdy = eMaj.dx / eMaj.dy;
367#if TRIANGLE_WALK_DOUBLE
368         eMaj.adjy = (eMaj.fsy - vMin_fy) * FIXED_SCALE;  /* SCALED! */
369         eMaj.fx0 = vMin_fx;
370         eMaj.fsx = eMaj.fx0 + (eMaj.adjy * eMaj.dxdy) / (GLdouble) FIXED_SCALE;
371#else
372         eMaj.fdxdy = SignedFloatToFixed(eMaj.dxdy);
373         eMaj.adjy = (GLfloat) (eMaj.fsy - vMin_fy);  /* SCALED! */
374         eMaj.fx0 = vMin_fx;
375         eMaj.fsx = eMaj.fx0 + (GLfixed) (eMaj.adjy * eMaj.dxdy);
376#endif
377      }
378      else {
379         return;  /*CULLED*/
380      }
381
382#if TRIANGLE_WALK_DOUBLE
383      eTop.fsy = CEILF(vMid_fy);
384      eTop.lines = (GLint) CEILF(vMax_fy - eTop.fsy);
385#else
386      eTop.fsy = FixedCeil(vMid_fy);
387      eTop.lines = FixedToInt(FixedCeil(vMax_fy - eTop.fsy));
388#endif
389      if (eTop.lines > 0) {
390         eTop.dxdy = eTop.dx / eTop.dy;
391#if TRIANGLE_WALK_DOUBLE
392         eTop.adjy = (eTop.fsy - vMid_fy) * FIXED_SCALE; /* SCALED! */
393         eTop.fx0 = vMid_fx;
394         eTop.fsx = eTop.fx0 + (eTop.adjy * eTop.dxdy) / (GLdouble) FIXED_SCALE;
395#else
396         eTop.fdxdy = SignedFloatToFixed(eTop.dxdy);
397         eTop.adjy = (GLfloat) (eTop.fsy - vMid_fy); /* SCALED! */
398         eTop.fx0 = vMid_fx;
399         eTop.fsx = eTop.fx0 + (GLfixed) (eTop.adjy * eTop.dxdy);
400#endif
401      }
402
403#if TRIANGLE_WALK_DOUBLE
404      eBot.fsy = CEILF(vMin_fy);
405      eBot.lines = (GLint) CEILF(vMid_fy - eBot.fsy);
406#else
407      eBot.fsy = FixedCeil(vMin_fy);
408      eBot.lines = FixedToInt(FixedCeil(vMid_fy - eBot.fsy));
409#endif
410      if (eBot.lines > 0) {
411         eBot.dxdy = eBot.dx / eBot.dy;
412#if TRIANGLE_WALK_DOUBLE
413         eBot.adjy = (eBot.fsy - vMin_fy) * FIXED_SCALE;  /* SCALED! */
414         eBot.fx0 = vMin_fx;
415         eBot.fsx = eBot.fx0 + (eBot.adjy * eBot.dxdy) / (GLdouble) FIXED_SCALE;
416#else
417         eBot.fdxdy = SignedFloatToFixed(eBot.dxdy);
418         eBot.adjy = (GLfloat) (eBot.fsy - vMin_fy);  /* SCALED! */
419         eBot.fx0 = vMin_fx;
420         eBot.fsx = eBot.fx0 + (GLfixed) (eBot.adjy * eBot.dxdy);
421#endif
422      }
423   }
424
425   /*
426    * Conceptually, we view a triangle as two subtriangles
427    * separated by a perfectly horizontal line.  The edge that is
428    * intersected by this line is one with maximal absolute dy; we
429    * call it a ``major'' edge.  The other two edges are the
430    * ``top'' edge (for the upper subtriangle) and the ``bottom''
431    * edge (for the lower subtriangle).  If either of these two
432    * edges is horizontal or very close to horizontal, the
433    * corresponding subtriangle might cover zero sample points;
434    * we take care to handle such cases, for performance as well
435    * as correctness.
436    *
437    * By stepping rasterization parameters along the major edge,
438    * we can avoid recomputing them at the discontinuity where
439    * the top and bottom edges meet.  However, this forces us to
440    * be able to scan both left-to-right and right-to-left.
441    * Also, we must determine whether the major edge is at the
442    * left or right side of the triangle.  We do this by
443    * computing the magnitude of the cross-product of the major
444    * and top edges.  Since this magnitude depends on the sine of
445    * the angle between the two edges, its sign tells us whether
446    * we turn to the left or to the right when travelling along
447    * the major edge to the top edge, and from this we infer
448    * whether the major edge is on the left or the right.
449    *
450    * Serendipitously, this cross-product magnitude is also a
451    * value we need to compute the iteration parameter
452    * derivatives for the triangle, and it can be used to perform
453    * backface culling because its sign tells us whether the
454    * triangle is clockwise or counterclockwise.  In this code we
455    * refer to it as ``area'' because it's also proportional to
456    * the pixel area of the triangle.
457    */
458
459   {
460      GLint scan_from_left_to_right;  /* true if scanning left-to-right */
461#ifdef INTERP_INDEX
462      GLfloat didx, didy;
463#endif
464
465      /*
466       * Execute user-supplied setup code
467       */
468#ifdef SETUP_CODE
469      SETUP_CODE
470#endif
471
472      scan_from_left_to_right = (oneOverArea < 0.0F);
473
474
475      /* compute d?/dx and d?/dy derivatives */
476#ifdef INTERP_Z
477      span.interpMask |= SPAN_Z;
478      {
479         GLfloat eMaj_dz = vMax->win[2] - vMin->win[2];
480         GLfloat eBot_dz = vMid->win[2] - vMin->win[2];
481         span.attrStepX[FRAG_ATTRIB_WPOS][2] = oneOverArea * (eMaj_dz * eBot.dy - eMaj.dy * eBot_dz);
482         if (span.attrStepX[FRAG_ATTRIB_WPOS][2] > maxDepth || span.attrStepX[FRAG_ATTRIB_WPOS][2] < -maxDepth) {
483            /* probably a sliver triangle */
484            span.attrStepX[FRAG_ATTRIB_WPOS][2] = 0.0;
485            span.attrStepY[FRAG_ATTRIB_WPOS][2] = 0.0;
486         }
487         else {
488            span.attrStepY[FRAG_ATTRIB_WPOS][2] = oneOverArea * (eMaj.dx * eBot_dz - eMaj_dz * eBot.dx);
489         }
490         if (depthBits <= 16)
491            span.zStep = SignedFloatToFixed(span.attrStepX[FRAG_ATTRIB_WPOS][2]);
492         else
493            span.zStep = (GLint) span.attrStepX[FRAG_ATTRIB_WPOS][2];
494      }
495#endif
496#ifdef INTERP_W
497      span.interpMask |= SPAN_W;
498      {
499         const GLfloat eMaj_dw = vMax->win[3] - vMin->win[3];
500         const GLfloat eBot_dw = vMid->win[3] - vMin->win[3];
501         span.attrStepX[FRAG_ATTRIB_WPOS][3] = oneOverArea * (eMaj_dw * eBot.dy - eMaj.dy * eBot_dw);
502         span.attrStepY[FRAG_ATTRIB_WPOS][3] = oneOverArea * (eMaj.dx * eBot_dw - eMaj_dw * eBot.dx);
503      }
504#endif
505#ifdef INTERP_FOG
506      span.interpMask |= SPAN_FOG;
507      {
508#  ifdef INTERP_W
509         const GLfloat wMax = vMax->win[3], wMin = vMin->win[3], wMid = vMid->win[3];
510         const GLfloat eMaj_dfog = vMax->fog * wMax - vMin->fog * wMin;
511         const GLfloat eBot_dfog = vMid->fog * wMid - vMin->fog * wMin;
512#  else
513         const GLfloat eMaj_dfog = vMax->fog - vMin->fog;
514         const GLfloat eBot_dfog = vMid->fog - vMin->fog;
515#  endif
516         span.attrStepX[FRAG_ATTRIB_FOGC][0] = oneOverArea * (eMaj_dfog * eBot.dy - eMaj.dy * eBot_dfog);
517         span.attrStepY[FRAG_ATTRIB_FOGC][0] = oneOverArea * (eMaj.dx * eBot_dfog - eMaj_dfog * eBot.dx);
518      }
519#endif
520#ifdef INTERP_RGB
521      span.interpMask |= SPAN_RGBA;
522      if (ctx->Light.ShadeModel == GL_SMOOTH) {
523         GLfloat eMaj_dr = (GLfloat) ((ColorTemp) vMax->color[RCOMP] - (ColorTemp) vMin->color[RCOMP]);
524         GLfloat eBot_dr = (GLfloat) ((ColorTemp) vMid->color[RCOMP] - (ColorTemp) vMin->color[RCOMP]);
525         GLfloat eMaj_dg = (GLfloat) ((ColorTemp) vMax->color[GCOMP] - (ColorTemp) vMin->color[GCOMP]);
526         GLfloat eBot_dg = (GLfloat) ((ColorTemp) vMid->color[GCOMP] - (ColorTemp) vMin->color[GCOMP]);
527         GLfloat eMaj_db = (GLfloat) ((ColorTemp) vMax->color[BCOMP] - (ColorTemp) vMin->color[BCOMP]);
528         GLfloat eBot_db = (GLfloat) ((ColorTemp) vMid->color[BCOMP] - (ColorTemp) vMin->color[BCOMP]);
529#  ifdef INTERP_ALPHA
530         GLfloat eMaj_da = (GLfloat) ((ColorTemp) vMax->color[ACOMP] - (ColorTemp) vMin->color[ACOMP]);
531         GLfloat eBot_da = (GLfloat) ((ColorTemp) vMid->color[ACOMP] - (ColorTemp) vMin->color[ACOMP]);
532#  endif
533         span.attrStepX[FRAG_ATTRIB_COL0][0] = oneOverArea * (eMaj_dr * eBot.dy - eMaj.dy * eBot_dr);
534         span.attrStepY[FRAG_ATTRIB_COL0][0] = oneOverArea * (eMaj.dx * eBot_dr - eMaj_dr * eBot.dx);
535         span.attrStepX[FRAG_ATTRIB_COL0][1] = oneOverArea * (eMaj_dg * eBot.dy - eMaj.dy * eBot_dg);
536         span.attrStepY[FRAG_ATTRIB_COL0][1] = oneOverArea * (eMaj.dx * eBot_dg - eMaj_dg * eBot.dx);
537         span.attrStepX[FRAG_ATTRIB_COL0][2] = oneOverArea * (eMaj_db * eBot.dy - eMaj.dy * eBot_db);
538         span.attrStepY[FRAG_ATTRIB_COL0][2] = oneOverArea * (eMaj.dx * eBot_db - eMaj_db * eBot.dx);
539#  if CHAN_TYPE == GL_FLOAT
540         span.redStep   = span.attrStepX[FRAG_ATTRIB_COL0][0];
541         span.greenStep = span.attrStepX[FRAG_ATTRIB_COL0][1];
542         span.blueStep  = span.attrStepX[FRAG_ATTRIB_COL0][2];
543#  else
544         span.redStep   = SignedFloatToFixed(span.attrStepX[FRAG_ATTRIB_COL0][0]);
545         span.greenStep = SignedFloatToFixed(span.attrStepX[FRAG_ATTRIB_COL0][1]);
546         span.blueStep  = SignedFloatToFixed(span.attrStepX[FRAG_ATTRIB_COL0][2]);
547#  endif /* GL_FLOAT */
548#  ifdef INTERP_ALPHA
549         span.attrStepX[FRAG_ATTRIB_COL0][3] = oneOverArea * (eMaj_da * eBot.dy - eMaj.dy * eBot_da);
550         span.attrStepX[FRAG_ATTRIB_COL0][3] = oneOverArea * (eMaj.dx * eBot_da - eMaj_da * eBot.dx);
551#    if CHAN_TYPE == GL_FLOAT
552         span.alphaStep = span.attrStepX[FRAG_ATTRIB_COL0][3];
553#    else
554         span.alphaStep = SignedFloatToFixed(span.attrStepX[FRAG_ATTRIB_COL0][3]);
555#    endif /* GL_FLOAT */
556#  endif /* INTERP_ALPHA */
557      }
558      else {
559         ASSERT(ctx->Light.ShadeModel == GL_FLAT);
560         span.interpMask |= SPAN_FLAT;
561         span.attrStepX[FRAG_ATTRIB_COL0][0] = span.attrStepY[FRAG_ATTRIB_COL0][0] = 0.0F;
562         span.attrStepX[FRAG_ATTRIB_COL0][1] = span.attrStepY[FRAG_ATTRIB_COL0][1] = 0.0F;
563         span.attrStepX[FRAG_ATTRIB_COL0][2] = span.attrStepY[FRAG_ATTRIB_COL0][2] = 0.0F;
564#    if CHAN_TYPE == GL_FLOAT
565	 span.redStep   = 0.0F;
566	 span.greenStep = 0.0F;
567	 span.blueStep  = 0.0F;
568#    else
569	 span.redStep   = 0;
570	 span.greenStep = 0;
571	 span.blueStep  = 0;
572#    endif /* GL_FLOAT */
573#  ifdef INTERP_ALPHA
574         span.attrStepX[FRAG_ATTRIB_COL0][3] = span.attrStepX[FRAG_ATTRIB_COL0][3] = 0.0F;
575#    if CHAN_TYPE == GL_FLOAT
576	 span.alphaStep = 0.0F;
577#    else
578	 span.alphaStep = 0;
579#    endif /* GL_FLOAT */
580#  endif
581      }
582#endif /* INTERP_RGB */
583#ifdef INTERP_SPEC
584      span.interpMask |= SPAN_SPEC;
585      if (ctx->Light.ShadeModel == GL_SMOOTH) {
586         GLfloat eMaj_dsr = (GLfloat) ((ColorTemp) vMax->specular[RCOMP] - (ColorTemp) vMin->specular[RCOMP]);
587         GLfloat eBot_dsr = (GLfloat) ((ColorTemp) vMid->specular[RCOMP] - (ColorTemp) vMin->specular[RCOMP]);
588         GLfloat eMaj_dsg = (GLfloat) ((ColorTemp) vMax->specular[GCOMP] - (ColorTemp) vMin->specular[GCOMP]);
589         GLfloat eBot_dsg = (GLfloat) ((ColorTemp) vMid->specular[GCOMP] - (ColorTemp) vMin->specular[GCOMP]);
590         GLfloat eMaj_dsb = (GLfloat) ((ColorTemp) vMax->specular[BCOMP] - (ColorTemp) vMin->specular[BCOMP]);
591         GLfloat eBot_dsb = (GLfloat) ((ColorTemp) vMid->specular[BCOMP] - (ColorTemp) vMin->specular[BCOMP]);
592         span.attrStepX[FRAG_ATTRIB_COL1][0] = oneOverArea * (eMaj_dsr * eBot.dy - eMaj.dy * eBot_dsr);
593         span.attrStepY[FRAG_ATTRIB_COL1][0] = oneOverArea * (eMaj.dx * eBot_dsr - eMaj_dsr * eBot.dx);
594         span.attrStepX[FRAG_ATTRIB_COL1][1] = oneOverArea * (eMaj_dsg * eBot.dy - eMaj.dy * eBot_dsg);
595         span.attrStepY[FRAG_ATTRIB_COL1][1] = oneOverArea * (eMaj.dx * eBot_dsg - eMaj_dsg * eBot.dx);
596         span.attrStepX[FRAG_ATTRIB_COL1][2] = oneOverArea * (eMaj_dsb * eBot.dy - eMaj.dy * eBot_dsb);
597         span.attrStepY[FRAG_ATTRIB_COL1][2] = oneOverArea * (eMaj.dx * eBot_dsb - eMaj_dsb * eBot.dx);
598#  if CHAN_TYPE == GL_FLOAT
599         span.specRedStep   = span.attrStep[FRAG_ATTRIB_COL1][0];
600         span.specGreenStep = span.dsgdx;
601         span.specBlueStep  = span.dsbdx;
602#  else
603         span.specRedStep   = SignedFloatToFixed(span.attrStepX[FRAG_ATTRIB_COL1][0]);
604         span.specGreenStep = SignedFloatToFixed(span.attrStepX[FRAG_ATTRIB_COL1][1]);
605         span.specBlueStep  = SignedFloatToFixed(span.attrStepX[FRAG_ATTRIB_COL1][2]);
606#  endif
607      }
608      else {
609         span.attrStepX[FRAG_ATTRIB_COL1][0] = span.attrStepY[FRAG_ATTRIB_COL1][0] = 0.0F;
610         span.attrStepX[FRAG_ATTRIB_COL1][1] = span.attrStepY[FRAG_ATTRIB_COL1][1] = 0.0F;
611         span.attrStepX[FRAG_ATTRIB_COL1][2] = span.attrStepY[FRAG_ATTRIB_COL1][2] = 0.0F;
612#  if CHAN_TYPE == GL_FLOAT
613	 span.specRedStep   = 0.0F;
614	 span.specGreenStep = 0.0F;
615	 span.specBlueStep  = 0.0F;
616#  else
617	 span.specRedStep   = 0;
618	 span.specGreenStep = 0;
619	 span.specBlueStep  = 0;
620#  endif
621      }
622#endif /* INTERP_SPEC */
623#ifdef INTERP_INDEX
624      span.interpMask |= SPAN_INDEX;
625      if (ctx->Light.ShadeModel == GL_SMOOTH) {
626         GLfloat eMaj_di = vMax->index - vMin->index;
627         GLfloat eBot_di = vMid->index - vMin->index;
628         didx = oneOverArea * (eMaj_di * eBot.dy - eMaj.dy * eBot_di);
629         didy = oneOverArea * (eMaj.dx * eBot_di - eMaj_di * eBot.dx);
630         span.indexStep = SignedFloatToFixed(didx);
631      }
632      else {
633         span.interpMask |= SPAN_FLAT;
634         didx = didy = 0.0F;
635         span.indexStep = 0;
636      }
637#endif
638#ifdef INTERP_INT_TEX
639      span.interpMask |= SPAN_INT_TEXTURE;
640      {
641         GLfloat eMaj_ds = (vMax->texcoord[0][0] - vMin->texcoord[0][0]) * S_SCALE;
642         GLfloat eBot_ds = (vMid->texcoord[0][0] - vMin->texcoord[0][0]) * S_SCALE;
643         GLfloat eMaj_dt = (vMax->texcoord[0][1] - vMin->texcoord[0][1]) * T_SCALE;
644         GLfloat eBot_dt = (vMid->texcoord[0][1] - vMin->texcoord[0][1]) * T_SCALE;
645         span.attrStepX[FRAG_ATTRIB_TEX0][0] = oneOverArea * (eMaj_ds * eBot.dy - eMaj.dy * eBot_ds);
646         span.attrStepY[FRAG_ATTRIB_TEX0][0] = oneOverArea * (eMaj.dx * eBot_ds - eMaj_ds * eBot.dx);
647         span.attrStepX[FRAG_ATTRIB_TEX0][1] = oneOverArea * (eMaj_dt * eBot.dy - eMaj.dy * eBot_dt);
648         span.attrStepY[FRAG_ATTRIB_TEX0][1] = oneOverArea * (eMaj.dx * eBot_dt - eMaj_dt * eBot.dx);
649         span.intTexStep[0] = SignedFloatToFixed(span.attrStepX[FRAG_ATTRIB_TEX0][0]);
650         span.intTexStep[1] = SignedFloatToFixed(span.attrStepX[FRAG_ATTRIB_TEX0][1]);
651      }
652#endif
653#ifdef INTERP_TEX
654      span.interpMask |= SPAN_TEXTURE;
655      {
656         /* win[3] is 1/W */
657         const GLfloat wMax = vMax->win[3], wMin = vMin->win[3], wMid = vMid->win[3];
658         TEX_UNIT_LOOP(
659            GLfloat eMaj_ds = vMax->texcoord[u][0] * wMax - vMin->texcoord[u][0] * wMin;
660            GLfloat eBot_ds = vMid->texcoord[u][0] * wMid - vMin->texcoord[u][0] * wMin;
661            GLfloat eMaj_dt = vMax->texcoord[u][1] * wMax - vMin->texcoord[u][1] * wMin;
662            GLfloat eBot_dt = vMid->texcoord[u][1] * wMid - vMin->texcoord[u][1] * wMin;
663            GLfloat eMaj_du = vMax->texcoord[u][2] * wMax - vMin->texcoord[u][2] * wMin;
664            GLfloat eBot_du = vMid->texcoord[u][2] * wMid - vMin->texcoord[u][2] * wMin;
665            GLfloat eMaj_dv = vMax->texcoord[u][3] * wMax - vMin->texcoord[u][3] * wMin;
666            GLfloat eBot_dv = vMid->texcoord[u][3] * wMid - vMin->texcoord[u][3] * wMin;
667            span.attrStepX[attr][0] = oneOverArea * (eMaj_ds * eBot.dy - eMaj.dy * eBot_ds);
668            span.attrStepY[attr][0] = oneOverArea * (eMaj.dx * eBot_ds - eMaj_ds * eBot.dx);
669            span.attrStepX[attr][1] = oneOverArea * (eMaj_dt * eBot.dy - eMaj.dy * eBot_dt);
670            span.attrStepY[attr][1] = oneOverArea * (eMaj.dx * eBot_dt - eMaj_dt * eBot.dx);
671            span.attrStepX[attr][2] = oneOverArea * (eMaj_du * eBot.dy - eMaj.dy * eBot_du);
672            span.attrStepY[attr][2] = oneOverArea * (eMaj.dx * eBot_du - eMaj_du * eBot.dx);
673            span.attrStepX[attr][3] = oneOverArea * (eMaj_dv * eBot.dy - eMaj.dy * eBot_dv);
674            span.attrStepY[attr][3] = oneOverArea * (eMaj.dx * eBot_dv - eMaj_dv * eBot.dx);
675         )
676      }
677#endif
678#ifdef INTERP_VARYING
679      span.interpMask |= SPAN_VARYING;
680      {
681         /* win[3] is 1/W */
682         const GLfloat wMax = vMax->win[3], wMin = vMin->win[3], wMid = vMid->win[3];
683         VARYING_LOOP(
684            GLfloat eMaj_dvar = vMax->varying[iv][ic] * wMax - vMin->varying[iv][ic] * wMin;
685            GLfloat eBot_dvar = vMid->varying[iv][ic] * wMid - vMin->varying[iv][ic] * wMin;
686            span.attrStepX[attr][ic] = oneOverArea * (eMaj_dvar * eBot.dy - eMaj.dy * eBot_dvar);
687            span.attrStepY[attr][ic] = oneOverArea * (eMaj.dx * eBot_dvar - eMaj_dvar * eBot.dx);
688         )
689      }
690#endif
691
692      /*
693       * We always sample at pixel centers.  However, we avoid
694       * explicit half-pixel offsets in this code by incorporating
695       * the proper offset in each of x and y during the
696       * transformation to window coordinates.
697       *
698       * We also apply the usual rasterization rules to prevent
699       * cracks and overlaps.  A pixel is considered inside a
700       * subtriangle if it meets all of four conditions: it is on or
701       * to the right of the left edge, strictly to the left of the
702       * right edge, on or below the top edge, and strictly above
703       * the bottom edge.  (Some edges may be degenerate.)
704       *
705       * The following discussion assumes left-to-right scanning
706       * (that is, the major edge is on the left); the right-to-left
707       * case is a straightforward variation.
708       *
709       * We start by finding the half-integral y coordinate that is
710       * at or below the top of the triangle.  This gives us the
711       * first scan line that could possibly contain pixels that are
712       * inside the triangle.
713       *
714       * Next we creep down the major edge until we reach that y,
715       * and compute the corresponding x coordinate on the edge.
716       * Then we find the half-integral x that lies on or just
717       * inside the edge.  This is the first pixel that might lie in
718       * the interior of the triangle.  (We won't know for sure
719       * until we check the other edges.)
720       *
721       * As we rasterize the triangle, we'll step down the major
722       * edge.  For each step in y, we'll move an integer number
723       * of steps in x.  There are two possible x step sizes, which
724       * we'll call the ``inner'' step (guaranteed to land on the
725       * edge or inside it) and the ``outer'' step (guaranteed to
726       * land on the edge or outside it).  The inner and outer steps
727       * differ by one.  During rasterization we maintain an error
728       * term that indicates our distance from the true edge, and
729       * select either the inner step or the outer step, whichever
730       * gets us to the first pixel that falls inside the triangle.
731       *
732       * All parameters (z, red, etc.) as well as the buffer
733       * addresses for color and z have inner and outer step values,
734       * so that we can increment them appropriately.  This method
735       * eliminates the need to adjust parameters by creeping a
736       * sub-pixel amount into the triangle at each scanline.
737       */
738
739      {
740         GLint subTriangle;
741         GLinterp fxLeftEdge = 0, fxRightEdge = 0;
742         GLinterp fdxLeftEdge = 0, fdxRightEdge = 0;
743         GLinterp fError = 0, fdError = 0;
744#ifdef PIXEL_ADDRESS
745         PIXEL_TYPE *pRow = NULL;
746         GLint dPRowOuter = 0, dPRowInner;  /* offset in bytes */
747#endif
748#ifdef INTERP_Z
749#  ifdef DEPTH_TYPE
750         struct gl_renderbuffer *zrb
751            = ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
752         DEPTH_TYPE *zRow = NULL;
753         GLint dZRowOuter = 0, dZRowInner;  /* offset in bytes */
754#  endif
755         GLuint zLeft = 0;
756         GLfixed fdzOuter = 0, fdzInner;
757#endif
758#ifdef INTERP_W
759         GLfloat wLeft = 0, dwOuter = 0, dwInner;
760#endif
761#ifdef INTERP_FOG
762         GLfloat fogLeft = 0, dfogOuter = 0, dfogInner;
763#endif
764#ifdef INTERP_RGB
765         ColorTemp rLeft = 0, fdrOuter = 0, fdrInner;
766         ColorTemp gLeft = 0, fdgOuter = 0, fdgInner;
767         ColorTemp bLeft = 0, fdbOuter = 0, fdbInner;
768#endif
769#ifdef INTERP_ALPHA
770         ColorTemp aLeft = 0, fdaOuter = 0, fdaInner;
771#endif
772#ifdef INTERP_SPEC
773         ColorTemp srLeft=0, dsrOuter=0, dsrInner;
774         ColorTemp sgLeft=0, dsgOuter=0, dsgInner;
775         ColorTemp sbLeft=0, dsbOuter=0, dsbInner;
776#endif
777#ifdef INTERP_INDEX
778         GLfixed iLeft=0, diOuter=0, diInner;
779#endif
780#ifdef INTERP_INT_TEX
781         GLfixed sLeft=0, dsOuter=0, dsInner;
782         GLfixed tLeft=0, dtOuter=0, dtInner;
783#endif
784#ifdef INTERP_TEX
785         GLfloat sLeft[MAX_TEXTURE_COORD_UNITS];
786         GLfloat tLeft[MAX_TEXTURE_COORD_UNITS];
787         GLfloat uLeft[MAX_TEXTURE_COORD_UNITS];
788         GLfloat vLeft[MAX_TEXTURE_COORD_UNITS];
789         GLfloat dsOuter[MAX_TEXTURE_COORD_UNITS], dsInner[MAX_TEXTURE_COORD_UNITS];
790         GLfloat dtOuter[MAX_TEXTURE_COORD_UNITS], dtInner[MAX_TEXTURE_COORD_UNITS];
791         GLfloat duOuter[MAX_TEXTURE_COORD_UNITS], duInner[MAX_TEXTURE_COORD_UNITS];
792         GLfloat dvOuter[MAX_TEXTURE_COORD_UNITS], dvInner[MAX_TEXTURE_COORD_UNITS];
793#endif
794#ifdef INTERP_VARYING
795         GLfloat varLeft[MAX_VARYING][4];
796         GLfloat dvarOuter[MAX_VARYING][4];
797         GLfloat dvarInner[MAX_VARYING][4];
798#endif
799
800         for (subTriangle=0; subTriangle<=1; subTriangle++) {
801            EdgeT *eLeft, *eRight;
802            int setupLeft, setupRight;
803            int lines;
804
805            if (subTriangle==0) {
806               /* bottom half */
807               if (scan_from_left_to_right) {
808                  eLeft = &eMaj;
809                  eRight = &eBot;
810                  lines = eRight->lines;
811                  setupLeft = 1;
812                  setupRight = 1;
813               }
814               else {
815                  eLeft = &eBot;
816                  eRight = &eMaj;
817                  lines = eLeft->lines;
818                  setupLeft = 1;
819                  setupRight = 1;
820               }
821            }
822            else {
823               /* top half */
824               if (scan_from_left_to_right) {
825                  eLeft = &eMaj;
826                  eRight = &eTop;
827                  lines = eRight->lines;
828                  setupLeft = 0;
829                  setupRight = 1;
830               }
831               else {
832                  eLeft = &eTop;
833                  eRight = &eMaj;
834                  lines = eLeft->lines;
835                  setupLeft = 1;
836                  setupRight = 0;
837               }
838               if (lines == 0)
839                  return;
840            }
841
842            if (setupLeft && eLeft->lines > 0) {
843               const SWvertex *vLower = eLeft->v0;
844#if TRIANGLE_WALK_DOUBLE
845               const GLdouble fsy = eLeft->fsy;
846               const GLdouble fsx = eLeft->fsx;
847               const GLdouble fx = CEILF(fsx);
848               const GLdouble adjx = (fx - eLeft->fx0) * FIXED_SCALE;  /* SCALED! */
849#else
850               const GLfixed fsy = eLeft->fsy;
851               const GLfixed fsx = eLeft->fsx;  /* no fractional part */
852               const GLfixed fx = FixedCeil(fsx);  /* no fractional part */
853               const GLfixed adjx = (GLinterp) (fx - eLeft->fx0); /* SCALED! */
854#endif
855               const GLinterp adjy = (GLinterp) eLeft->adjy;      /* SCALED! */
856               GLint idxOuter;
857#if TRIANGLE_WALK_DOUBLE
858               GLdouble dxOuter;
859
860               fError = fx - fsx - 1.0;
861               fxLeftEdge = fsx;
862               fdxLeftEdge = eLeft->dxdy;
863               dxOuter = FLOORF(fdxLeftEdge);
864               fdError = dxOuter - fdxLeftEdge + 1.0;
865               idxOuter = (GLint) dxOuter;
866               span.y = (GLint) fsy;
867#else
868               GLfloat dxOuter;
869               GLfixed fdxOuter;
870
871               fError = fx - fsx - FIXED_ONE;
872               fxLeftEdge = fsx - FIXED_EPSILON;
873               fdxLeftEdge = eLeft->fdxdy;
874               fdxOuter = FixedFloor(fdxLeftEdge - FIXED_EPSILON);
875               fdError = fdxOuter - fdxLeftEdge + FIXED_ONE;
876               idxOuter = FixedToInt(fdxOuter);
877               dxOuter = (GLfloat) idxOuter;
878               span.y = FixedToInt(fsy);
879#endif
880
881               /* silence warnings on some compilers */
882               (void) dxOuter;
883               (void) adjx;
884               (void) adjy;
885               (void) vLower;
886
887#ifdef PIXEL_ADDRESS
888               {
889                  pRow = (PIXEL_TYPE *) PIXEL_ADDRESS(InterpToInt(fxLeftEdge), span.y);
890                  dPRowOuter = -((int)BYTES_PER_ROW) + idxOuter * sizeof(PIXEL_TYPE);
891                  /* negative because Y=0 at bottom and increases upward */
892               }
893#endif
894               /*
895                * Now we need the set of parameter (z, color, etc.) values at
896                * the point (fx, fsy).  This gives us properly-sampled parameter
897                * values that we can step from pixel to pixel.  Furthermore,
898                * although we might have intermediate results that overflow
899                * the normal parameter range when we step temporarily outside
900                * the triangle, we shouldn't overflow or underflow for any
901                * pixel that's actually inside the triangle.
902                */
903
904#ifdef INTERP_Z
905               {
906                  GLfloat z0 = vLower->win[2];
907                  if (depthBits <= 16) {
908                     /* interpolate fixed-pt values */
909                     GLfloat tmp = (z0 * FIXED_SCALE
910                                    + span.attrStepX[FRAG_ATTRIB_WPOS][2] * adjx
911                                    + span.attrStepY[FRAG_ATTRIB_WPOS][2] * adjy) + FIXED_HALF;
912                     if (tmp < MAX_GLUINT / 2)
913                        zLeft = (GLfixed) tmp;
914                     else
915                        zLeft = MAX_GLUINT / 2;
916                     fdzOuter = SignedFloatToFixed(span.attrStepY[FRAG_ATTRIB_WPOS][2] + dxOuter * span.attrStepX[FRAG_ATTRIB_WPOS][2]);
917                  }
918                  else {
919                     /* interpolate depth values w/out scaling */
920                     zLeft = (GLuint) (z0 + span.attrStepX[FRAG_ATTRIB_WPOS][2] * FixedToFloat(adjx)
921                                          + span.attrStepY[FRAG_ATTRIB_WPOS][2] * FixedToFloat(adjy));
922                     fdzOuter = (GLint) (span.attrStepY[FRAG_ATTRIB_WPOS][2] + dxOuter * span.attrStepX[FRAG_ATTRIB_WPOS][2]);
923                  }
924#  ifdef DEPTH_TYPE
925                  zRow = (DEPTH_TYPE *)
926                    zrb->GetPointer(ctx, zrb, InterpToInt(fxLeftEdge), span.y);
927                  dZRowOuter = (ctx->DrawBuffer->Width + idxOuter) * sizeof(DEPTH_TYPE);
928#  endif
929               }
930#endif
931#ifdef INTERP_W
932               wLeft = vLower->win[3] + (span.attrStepX[FRAG_ATTRIB_WPOS][3] * adjx + span.attrStepY[FRAG_ATTRIB_WPOS][3] * adjy) * (1.0F/FIXED_SCALE);
933               dwOuter = span.attrStepY[FRAG_ATTRIB_WPOS][3] + dxOuter * span.attrStepX[FRAG_ATTRIB_WPOS][3];
934#endif
935#ifdef INTERP_FOG
936#  ifdef INTERP_W
937               fogLeft = vLower->fog * vLower->win[3] + (span.attrStepX[FRAG_ATTRIB_FOGC][0] * adjx + span.attrStepY[FRAG_ATTRIB_FOGC][0] * adjy) * (1.0F/FIXED_SCALE);
938#  else
939               fogLeft = vLower->fog + (span.attrStepX[FRAG_ATTRIB_FOGC][0] * adjx + span.attrStepY[FRAG_ATTRIB_FOGC][0] * adjy) * (1.0F/FIXED_SCALE);
940#  endif
941               dfogOuter = span.attrStepY[FRAG_ATTRIB_FOGC][0] + dxOuter * span.attrStepX[FRAG_ATTRIB_FOGC][0];
942#endif
943#ifdef INTERP_RGB
944               if (ctx->Light.ShadeModel == GL_SMOOTH) {
945#  if CHAN_TYPE == GL_FLOAT
946                  rLeft = vLower->color[RCOMP] + (span.attrStepX[FRAG_ATTRIB_COL0][0] * adjx + span.attrStepY[FRAG_ATTRIB_COL0][0] * adjy) * (1.0F / FIXED_SCALE);
947                  gLeft = vLower->color[GCOMP] + (span.attrStepX[FRAG_ATTRIB_COL0][1] * adjx + span.attrStepY[FRAG_ATTRIB_COL0][1] * adjy) * (1.0F / FIXED_SCALE);
948                  bLeft = vLower->color[BCOMP] + (span.attrStepX[FRAG_ATTRIB_COL0][2] * adjx + span.attrStepY[FRAG_ATTRIB_COL0][2] * adjy) * (1.0F / FIXED_SCALE);
949                  fdrOuter = span.attrStepY[FRAG_ATTRIB_COL0][0] + dxOuter * span.attrStepX[FRAG_ATTRIB_COL0][0];
950                  fdgOuter = span.attrStepY[FRAG_ATTRIB_COL0][1] + dxOuter * span.attrStepX[FRAG_ATTRIB_COL0][1];
951                  fdbOuter = span.attrStepY[FRAG_ATTRIB_COL0][2] + dxOuter * span.attrStepX[FRAG_ATTRIB_COL0][2];
952#  else
953                  rLeft = (GLint)(ChanToFixed(vLower->color[RCOMP]) + span.attrStepX[FRAG_ATTRIB_COL0][0] * adjx + span.attrStepY[FRAG_ATTRIB_COL0][0] * adjy) + FIXED_HALF;
954                  gLeft = (GLint)(ChanToFixed(vLower->color[GCOMP]) + span.attrStepX[FRAG_ATTRIB_COL0][1] * adjx + span.attrStepY[FRAG_ATTRIB_COL0][1] * adjy) + FIXED_HALF;
955                  bLeft = (GLint)(ChanToFixed(vLower->color[BCOMP]) + span.attrStepX[FRAG_ATTRIB_COL0][2] * adjx + span.attrStepY[FRAG_ATTRIB_COL0][2] * adjy) + FIXED_HALF;
956                  fdrOuter = SignedFloatToFixed(span.attrStepY[FRAG_ATTRIB_COL0][0] + dxOuter * span.attrStepX[FRAG_ATTRIB_COL0][0]);
957                  fdgOuter = SignedFloatToFixed(span.attrStepY[FRAG_ATTRIB_COL0][1] + dxOuter * span.attrStepX[FRAG_ATTRIB_COL0][1]);
958                  fdbOuter = SignedFloatToFixed(span.attrStepY[FRAG_ATTRIB_COL0][2] + dxOuter * span.attrStepX[FRAG_ATTRIB_COL0][2]);
959#  endif
960#  ifdef INTERP_ALPHA
961#    if CHAN_TYPE == GL_FLOAT
962                  aLeft = vLower->color[ACOMP] + (span.attrStepX[FRAG_ATTRIB_COL0][3] * adjx + span.attrStepX[FRAG_ATTRIB_COL0][3] * adjy) * (1.0F / FIXED_SCALE);
963                  fdaOuter = span.attrStepX[FRAG_ATTRIB_COL0][3] + dxOuter * span.attrStepX[FRAG_ATTRIB_COL0][3];
964#    else
965                  aLeft = (GLint)(ChanToFixed(vLower->color[ACOMP]) + span.attrStepX[FRAG_ATTRIB_COL0][3] * adjx + span.attrStepX[FRAG_ATTRIB_COL0][3] * adjy) + FIXED_HALF;
966                  fdaOuter = SignedFloatToFixed(span.attrStepX[FRAG_ATTRIB_COL0][3] + dxOuter * span.attrStepX[FRAG_ATTRIB_COL0][3]);
967#    endif
968#  endif
969               }
970               else {
971                  ASSERT(ctx->Light.ShadeModel == GL_FLAT);
972#  if CHAN_TYPE == GL_FLOAT
973                  rLeft = v2->color[RCOMP];
974                  gLeft = v2->color[GCOMP];
975                  bLeft = v2->color[BCOMP];
976                  fdrOuter = fdgOuter = fdbOuter = 0.0F;
977#  else
978                  rLeft = ChanToFixed(v2->color[RCOMP]);
979                  gLeft = ChanToFixed(v2->color[GCOMP]);
980                  bLeft = ChanToFixed(v2->color[BCOMP]);
981                  fdrOuter = fdgOuter = fdbOuter = 0;
982#  endif
983#  ifdef INTERP_ALPHA
984#    if CHAN_TYPE == GL_FLOAT
985                  aLeft = v2->color[ACOMP];
986                  fdaOuter = 0.0F;
987#    else
988                  aLeft = ChanToFixed(v2->color[ACOMP]);
989                  fdaOuter = 0;
990#    endif
991#  endif
992               }
993#endif /* INTERP_RGB */
994
995
996#ifdef INTERP_SPEC
997               if (ctx->Light.ShadeModel == GL_SMOOTH) {
998#  if CHAN_TYPE == GL_FLOAT
999                  srLeft = vLower->specular[RCOMP] + (span.attrStepX[FRAG_ATTRIB_COL1][0] * adjx + span.attrStepY[FRAG_ATTRIB_COL1][0] * adjy) * (1.0F / FIXED_SCALE);
1000                  sgLeft = vLower->specular[GCOMP] + (span.attrStepX[FRAG_ATTRIB_COL1][1] * adjx + span.attrStepY[FRAG_ATTRIB_COL1][1] * adjy) * (1.0F / FIXED_SCALE);
1001                  sbLeft = vLower->specular[BCOMP] + (span.attrStepX[FRAG_ATTRIB_COL1][2] * adjx + span.attrStepY[FRAG_ATTRIB_COL1][2] * adjy) * (1.0F / FIXED_SCALE);
1002                  dsrOuter = span.attrStepY[FRAG_ATTRIB_COL1][0] + dxOuter * span.attrStepX[FRAG_ATTRIB_COL1][0];
1003                  dsgOuter = span.attrStepY[FRAG_ATTRIB_COL1][1] + dxOuter * span.attrStepX[FRAG_ATTRIB_COL1][1];
1004                  dsbOuter = span.attrStepY[FRAG_ATTRIB_COL1][2] + dxOuter * span.attrStepX[FRAG_ATTRIB_COL1][2];
1005#  else
1006                  srLeft = (GLfixed) (ChanToFixed(vLower->specular[RCOMP]) + span.attrStepX[FRAG_ATTRIB_COL1][0] * adjx + span.attrStepY[FRAG_ATTRIB_COL1][0] * adjy) + FIXED_HALF;
1007                  sgLeft = (GLfixed) (ChanToFixed(vLower->specular[GCOMP]) + span.attrStepX[FRAG_ATTRIB_COL1][1] * adjx + span.attrStepY[FRAG_ATTRIB_COL1][1] * adjy) + FIXED_HALF;
1008                  sbLeft = (GLfixed) (ChanToFixed(vLower->specular[BCOMP]) + span.attrStepX[FRAG_ATTRIB_COL1][2] * adjx + span.attrStepY[FRAG_ATTRIB_COL1][2] * adjy) + FIXED_HALF;
1009                  dsrOuter = SignedFloatToFixed(span.attrStepY[FRAG_ATTRIB_COL1][0] + dxOuter * span.attrStepX[FRAG_ATTRIB_COL1][0]);
1010                  dsgOuter = SignedFloatToFixed(span.attrStepY[FRAG_ATTRIB_COL1][1] + dxOuter * span.attrStepX[FRAG_ATTRIB_COL1][1]);
1011                  dsbOuter = SignedFloatToFixed(span.attrStepY[FRAG_ATTRIB_COL1][2] + dxOuter * span.attrStepX[FRAG_ATTRIB_COL1][2]);
1012#  endif
1013               }
1014               else {
1015                  ASSERT(ctx->Light.ShadeModel == GL_FLAT);
1016#if  CHAN_TYPE == GL_FLOAT
1017                  srLeft = v2->specular[RCOMP];
1018                  sgLeft = v2->specular[GCOMP];
1019                  sbLeft = v2->specular[BCOMP];
1020                  dsrOuter = dsgOuter = dsbOuter = 0.0F;
1021#  else
1022                  srLeft = ChanToFixed(v2->specular[RCOMP]);
1023                  sgLeft = ChanToFixed(v2->specular[GCOMP]);
1024                  sbLeft = ChanToFixed(v2->specular[BCOMP]);
1025                  dsrOuter = dsgOuter = dsbOuter = 0;
1026#  endif
1027               }
1028#endif
1029
1030#ifdef INTERP_INDEX
1031               if (ctx->Light.ShadeModel == GL_SMOOTH) {
1032                  iLeft = (GLfixed)(vLower->index * FIXED_SCALE
1033                                 + didx * adjx + didy * adjy) + FIXED_HALF;
1034                  diOuter = SignedFloatToFixed(didy + dxOuter * didx);
1035               }
1036               else {
1037                  ASSERT(ctx->Light.ShadeModel == GL_FLAT);
1038                  iLeft = FloatToFixed(v2->index);
1039                  diOuter = 0;
1040               }
1041#endif
1042#ifdef INTERP_INT_TEX
1043               {
1044                  GLfloat s0, t0;
1045                  s0 = vLower->texcoord[0][0] * S_SCALE;
1046                  sLeft = (GLfixed)(s0 * FIXED_SCALE + span.attrStepX[FRAG_ATTRIB_TEX0][0] * adjx
1047                                 + span.attrStepY[FRAG_ATTRIB_TEX0][0] * adjy) + FIXED_HALF;
1048                  dsOuter = SignedFloatToFixed(span.attrStepY[FRAG_ATTRIB_TEX0][0] + dxOuter * span.attrStepX[FRAG_ATTRIB_TEX0][0]);
1049
1050                  t0 = vLower->texcoord[0][1] * T_SCALE;
1051                  tLeft = (GLfixed)(t0 * FIXED_SCALE + span.attrStepX[FRAG_ATTRIB_TEX0][1] * adjx
1052                                 + span.attrStepY[FRAG_ATTRIB_TEX0][1] * adjy) + FIXED_HALF;
1053                  dtOuter = SignedFloatToFixed(span.attrStepY[FRAG_ATTRIB_TEX0][1] + dxOuter * span.attrStepX[FRAG_ATTRIB_TEX0][1]);
1054               }
1055#endif
1056#ifdef INTERP_TEX
1057               TEX_UNIT_LOOP(
1058                  const GLfloat invW = vLower->win[3];
1059                  const GLfloat s0 = vLower->texcoord[u][0] * invW;
1060                  const GLfloat t0 = vLower->texcoord[u][1] * invW;
1061                  const GLfloat u0 = vLower->texcoord[u][2] * invW;
1062                  const GLfloat v0 = vLower->texcoord[u][3] * invW;
1063                  sLeft[u] = s0 + (span.attrStepX[attr][0] * adjx + span.attrStepY[attr][0] * adjy) * (1.0F/FIXED_SCALE);
1064                  tLeft[u] = t0 + (span.attrStepX[attr][1] * adjx + span.attrStepY[attr][1] * adjy) * (1.0F/FIXED_SCALE);
1065                  uLeft[u] = u0 + (span.attrStepX[attr][2] * adjx + span.attrStepY[attr][2] * adjy) * (1.0F/FIXED_SCALE);
1066                  vLeft[u] = v0 + (span.attrStepX[attr][3] * adjx + span.attrStepY[attr][3] * adjy) * (1.0F/FIXED_SCALE);
1067                  dsOuter[u] = span.attrStepY[attr][0] + dxOuter * span.attrStepX[attr][0];
1068                  dtOuter[u] = span.attrStepY[attr][1] + dxOuter * span.attrStepX[attr][1];
1069                  duOuter[u] = span.attrStepY[attr][2] + dxOuter * span.attrStepX[attr][2];
1070                  dvOuter[u] = span.attrStepY[attr][3] + dxOuter * span.attrStepX[attr][3];
1071               )
1072#endif
1073#ifdef INTERP_VARYING
1074               VARYING_LOOP(
1075                  const GLfloat invW = vLower->win[3];
1076                  const GLfloat var0 = vLower->varying[iv][ic] * invW;
1077                  varLeft[iv][ic] = var0 + (span.attrStepX[attr][ic] * adjx +
1078                     span.attrStepY[attr][ic] * adjy) * (1.0f / FIXED_SCALE);
1079                  dvarOuter[iv][ic] = span.attrStepY[attr][ic] + dxOuter * span.attrStepX[attr][ic];
1080               )
1081#endif
1082            } /*if setupLeft*/
1083
1084
1085            if (setupRight && eRight->lines>0) {
1086#if TRIANGLE_WALK_DOUBLE
1087               fxRightEdge = eRight->fsx;
1088               fdxRightEdge = eRight->dxdy;
1089#else
1090               fxRightEdge = eRight->fsx - FIXED_EPSILON;
1091               fdxRightEdge = eRight->fdxdy;
1092#endif
1093            }
1094
1095            if (lines==0) {
1096               continue;
1097            }
1098
1099
1100            /* Rasterize setup */
1101#ifdef PIXEL_ADDRESS
1102            dPRowInner = dPRowOuter + sizeof(PIXEL_TYPE);
1103#endif
1104#ifdef INTERP_Z
1105#  ifdef DEPTH_TYPE
1106            dZRowInner = dZRowOuter + sizeof(DEPTH_TYPE);
1107#  endif
1108            fdzInner = fdzOuter + span.zStep;
1109#endif
1110#ifdef INTERP_W
1111            dwInner = dwOuter + span.attrStepX[FRAG_ATTRIB_WPOS][3];
1112#endif
1113#ifdef INTERP_FOG
1114            dfogInner = dfogOuter + span.attrStepX[FRAG_ATTRIB_FOGC][0];
1115#endif
1116#ifdef INTERP_RGB
1117            fdrInner = fdrOuter + span.redStep;
1118            fdgInner = fdgOuter + span.greenStep;
1119            fdbInner = fdbOuter + span.blueStep;
1120#endif
1121#ifdef INTERP_ALPHA
1122            fdaInner = fdaOuter + span.alphaStep;
1123#endif
1124#ifdef INTERP_SPEC
1125            dsrInner = dsrOuter + span.specRedStep;
1126            dsgInner = dsgOuter + span.specGreenStep;
1127            dsbInner = dsbOuter + span.specBlueStep;
1128#endif
1129#ifdef INTERP_INDEX
1130            diInner = diOuter + span.indexStep;
1131#endif
1132#ifdef INTERP_INT_TEX
1133            dsInner = dsOuter + span.intTexStep[0];
1134            dtInner = dtOuter + span.intTexStep[1];
1135#endif
1136#ifdef INTERP_TEX
1137            TEX_UNIT_LOOP(
1138               dsInner[u] = dsOuter[u] + span.attrStepX[attr][0];
1139               dtInner[u] = dtOuter[u] + span.attrStepX[attr][1];
1140               duInner[u] = duOuter[u] + span.attrStepX[attr][2];
1141               dvInner[u] = dvOuter[u] + span.attrStepX[attr][3];
1142            )
1143#endif
1144#ifdef INTERP_VARYING
1145            VARYING_LOOP(
1146               dvarInner[iv][ic] = dvarOuter[iv][ic] + span.attrStepX[attr][ic];
1147            )
1148#endif
1149
1150            while (lines > 0) {
1151               /* initialize the span interpolants to the leftmost value */
1152               /* ff = fixed-pt fragment */
1153               const GLint right = InterpToInt(fxRightEdge);
1154               span.x = InterpToInt(fxLeftEdge);
1155               if (right <= span.x)
1156                  span.end = 0;
1157               else
1158                  span.end = right - span.x;
1159
1160#ifdef INTERP_Z
1161               span.z = zLeft;
1162#endif
1163#ifdef INTERP_W
1164               span.attrStart[FRAG_ATTRIB_WPOS][3] = wLeft;
1165#endif
1166#ifdef INTERP_FOG
1167               span.attrStart[FRAG_ATTRIB_FOGC][0] = fogLeft;
1168#endif
1169#ifdef INTERP_RGB
1170               span.red = rLeft;
1171               span.green = gLeft;
1172               span.blue = bLeft;
1173#endif
1174#ifdef INTERP_ALPHA
1175               span.alpha = aLeft;
1176#endif
1177#ifdef INTERP_SPEC
1178               span.specRed = srLeft;
1179               span.specGreen = sgLeft;
1180               span.specBlue = sbLeft;
1181#endif
1182#ifdef INTERP_INDEX
1183               span.index = iLeft;
1184#endif
1185#ifdef INTERP_INT_TEX
1186               span.intTex[0] = sLeft;
1187               span.intTex[1] = tLeft;
1188#endif
1189
1190#ifdef INTERP_TEX
1191               TEX_UNIT_LOOP(
1192                  span.attrStart[attr][0] = sLeft[u];
1193                  span.attrStart[attr][1] = tLeft[u];
1194                  span.attrStart[attr][2] = uLeft[u];
1195                  span.attrStart[attr][3] = vLeft[u];
1196               )
1197#endif
1198#ifdef INTERP_VARYING
1199               VARYING_LOOP(
1200                  span.attrStart[attr][ic] = varLeft[iv][ic];
1201               )
1202#endif
1203
1204               /* This is where we actually generate fragments */
1205               /* XXX the test for span.y > 0 _shouldn't_ be needed but
1206                * it fixes a problem on 64-bit Opterons (bug 4842).
1207                */
1208               if (span.end > 0 && span.y >= 0) {
1209                  const GLint len = span.end - 1;
1210                  (void) len;
1211#ifdef INTERP_RGB
1212                  CLAMP_INTERPOLANT(red, redStep, len);
1213                  CLAMP_INTERPOLANT(green, greenStep, len);
1214                  CLAMP_INTERPOLANT(blue, blueStep, len);
1215#endif
1216#ifdef INTERP_ALPHA
1217                  CLAMP_INTERPOLANT(alpha, alphaStep, len);
1218#endif
1219#ifdef INTERP_SPEC
1220                  CLAMP_INTERPOLANT(specRed, specRedStep, len);
1221                  CLAMP_INTERPOLANT(specGreen, specGreenStep, len);
1222                  CLAMP_INTERPOLANT(specBlue, specBlueStep, len);
1223#endif
1224#ifdef INTERP_INDEX
1225                  CLAMP_INTERPOLANT(index, indexStep, len);
1226#endif
1227                  {
1228                     RENDER_SPAN( span );
1229                  }
1230               }
1231
1232               /*
1233                * Advance to the next scan line.  Compute the
1234                * new edge coordinates, and adjust the
1235                * pixel-center x coordinate so that it stays
1236                * on or inside the major edge.
1237                */
1238               span.y++;
1239               lines--;
1240
1241               fxLeftEdge += fdxLeftEdge;
1242               fxRightEdge += fdxRightEdge;
1243
1244               fError += fdError;
1245               if (fError >= 0) {
1246                  fError -= INTERP_ONE;
1247
1248#ifdef PIXEL_ADDRESS
1249                  pRow = (PIXEL_TYPE *) ((GLubyte *) pRow + dPRowOuter);
1250#endif
1251#ifdef INTERP_Z
1252#  ifdef DEPTH_TYPE
1253                  zRow = (DEPTH_TYPE *) ((GLubyte *) zRow + dZRowOuter);
1254#  endif
1255                  zLeft += fdzOuter;
1256#endif
1257#ifdef INTERP_W
1258                  wLeft += dwOuter;
1259#endif
1260#ifdef INTERP_FOG
1261                  fogLeft += dfogOuter;
1262#endif
1263#ifdef INTERP_RGB
1264                  rLeft += fdrOuter;
1265                  gLeft += fdgOuter;
1266                  bLeft += fdbOuter;
1267#endif
1268#ifdef INTERP_ALPHA
1269                  aLeft += fdaOuter;
1270#endif
1271#ifdef INTERP_SPEC
1272                  srLeft += dsrOuter;
1273                  sgLeft += dsgOuter;
1274                  sbLeft += dsbOuter;
1275#endif
1276#ifdef INTERP_INDEX
1277                  iLeft += diOuter;
1278#endif
1279#ifdef INTERP_INT_TEX
1280                  sLeft += dsOuter;
1281                  tLeft += dtOuter;
1282#endif
1283#ifdef INTERP_TEX
1284                  TEX_UNIT_LOOP(
1285                     sLeft[u] += dsOuter[u];
1286                     tLeft[u] += dtOuter[u];
1287                     uLeft[u] += duOuter[u];
1288                     vLeft[u] += dvOuter[u];
1289                  )
1290#endif
1291#ifdef INTERP_VARYING
1292                  VARYING_LOOP(
1293                     varLeft[iv][ic] += dvarOuter[iv][ic];
1294                  )
1295#endif
1296               }
1297               else {
1298#ifdef PIXEL_ADDRESS
1299                  pRow = (PIXEL_TYPE *) ((GLubyte *) pRow + dPRowInner);
1300#endif
1301#ifdef INTERP_Z
1302#  ifdef DEPTH_TYPE
1303                  zRow = (DEPTH_TYPE *) ((GLubyte *) zRow + dZRowInner);
1304#  endif
1305                  zLeft += fdzInner;
1306#endif
1307#ifdef INTERP_W
1308                  wLeft += dwInner;
1309#endif
1310#ifdef INTERP_FOG
1311                  fogLeft += dfogInner;
1312#endif
1313#ifdef INTERP_RGB
1314                  rLeft += fdrInner;
1315                  gLeft += fdgInner;
1316                  bLeft += fdbInner;
1317#endif
1318#ifdef INTERP_ALPHA
1319                  aLeft += fdaInner;
1320#endif
1321#ifdef INTERP_SPEC
1322                  srLeft += dsrInner;
1323                  sgLeft += dsgInner;
1324                  sbLeft += dsbInner;
1325#endif
1326#ifdef INTERP_INDEX
1327                  iLeft += diInner;
1328#endif
1329#ifdef INTERP_INT_TEX
1330                  sLeft += dsInner;
1331                  tLeft += dtInner;
1332#endif
1333#ifdef INTERP_TEX
1334                  TEX_UNIT_LOOP(
1335                     sLeft[u] += dsInner[u];
1336                     tLeft[u] += dtInner[u];
1337                     uLeft[u] += duInner[u];
1338                     vLeft[u] += dvInner[u];
1339                  )
1340#endif
1341#ifdef INTERP_VARYING
1342                  VARYING_LOOP(
1343                     varLeft[iv][ic] += dvarInner[iv][ic];
1344                  )
1345#endif
1346               }
1347            } /*while lines>0*/
1348
1349         } /* for subTriangle */
1350
1351      }
1352#ifdef CLEANUP_CODE
1353      CLEANUP_CODE
1354#endif
1355   }
1356}
1357
1358#undef SETUP_CODE
1359#undef CLEANUP_CODE
1360#undef RENDER_SPAN
1361
1362#undef PIXEL_TYPE
1363#undef BYTES_PER_ROW
1364#undef PIXEL_ADDRESS
1365#undef DEPTH_TYPE
1366
1367#undef INTERP_Z
1368#undef INTERP_W
1369#undef INTERP_FOG
1370#undef INTERP_RGB
1371#undef INTERP_ALPHA
1372#undef INTERP_SPEC
1373#undef INTERP_INDEX
1374#undef INTERP_INT_TEX
1375#undef INTERP_TEX
1376#undef INTERP_MULTITEX
1377#undef INTERP_VARYING
1378#undef TEX_UNIT_LOOP
1379#undef VARYING_LOOP
1380
1381#undef S_SCALE
1382#undef T_SCALE
1383
1384#undef FixedToDepth
1385#undef ColorTemp
1386#undef GLinterp
1387#undef InterpToInt
1388#undef INTERP_ONE
1389
1390#undef NAME
1391