s_tritemp.h revision dec3ed69e21baa1113938132e344761f39320f5f
1/* $Id: s_tritemp.h,v 1.45 2003/03/16 18:42:13 brianp Exp $ */
2
3/*
4 * Mesa 3-D graphics library
5 * Version:  5.1
6 *
7 * Copyright (C) 1999-2003  Brian Paul   All Rights Reserved.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 */
26/* $XFree86: xc/extras/Mesa/src/swrast/s_tritemp.h,v 1.2 2002/02/27 21:07:54 tsi Exp $ */
27
28/*
29 * Triangle Rasterizer Template
30 *
31 * This file is #include'd to generate custom triangle rasterizers.
32 *
33 * The following macros may be defined to indicate what auxillary information
34 * must be interplated across the triangle:
35 *    INTERP_Z        - if defined, interpolate Z values
36 *    INTERP_FOG      - if defined, interpolate fog values
37 *    INTERP_RGB      - if defined, interpolate RGB values
38 *    INTERP_ALPHA    - if defined, interpolate Alpha values (req's INTERP_RGB)
39 *    INTERP_SPEC     - if defined, interpolate specular RGB values
40 *    INTERP_INDEX    - if defined, interpolate color index values
41 *    INTERP_INT_TEX  - if defined, interpolate integer ST texcoords
42 *                         (fast, simple 2-D texture mapping)
43 *    INTERP_TEX      - if defined, interpolate set 0 float STRQ texcoords
44 *                         NOTE:  OpenGL STRQ = Mesa STUV (R was taken for red)
45 *    INTERP_MULTITEX - if defined, interpolate N units of STRQ texcoords
46 *
47 * When one can directly address pixels in the color buffer the following
48 * macros can be defined and used to compute pixel addresses during
49 * rasterization (see pRow):
50 *    PIXEL_TYPE          - the datatype of a pixel (GLubyte, GLushort, GLuint)
51 *    BYTES_PER_ROW       - number of bytes per row in the color buffer
52 *    PIXEL_ADDRESS(X,Y)  - returns the address of pixel at (X,Y) where
53 *                          Y==0 at bottom of screen and increases upward.
54 *
55 * Similarly, for direct depth buffer access, this type is used for depth
56 * buffer addressing:
57 *    DEPTH_TYPE          - either GLushort or GLuint
58 *
59 * Optionally, one may provide one-time setup code per triangle:
60 *    SETUP_CODE    - code which is to be executed once per triangle
61 *    CLEANUP_CODE    - code to execute at end of triangle
62 *
63 * The following macro MUST be defined:
64 *    RENDER_SPAN(span) - code to write a span of pixels.
65 *
66 * This code was designed for the origin to be in the lower-left corner.
67 *
68 * Inspired by triangle rasterizer code written by Allen Akin.  Thanks Allen!
69 */
70
71
72/*
73 * ColorTemp is used for intermediate color values.
74 */
75#if CHAN_TYPE == GL_FLOAT
76#define ColorTemp GLfloat
77#else
78#define ColorTemp GLint  /* same as GLfixed */
79#endif
80
81
82
83static void NAME(GLcontext *ctx, const SWvertex *v0,
84                                 const SWvertex *v1,
85                                 const SWvertex *v2 )
86{
87   typedef struct {
88        const SWvertex *v0, *v1;   /* Y(v0) < Y(v1) */
89        GLfloat dx;	/* X(v1) - X(v0) */
90        GLfloat dy;	/* Y(v1) - Y(v0) */
91        GLfixed fdxdy;	/* dx/dy in fixed-point */
92        GLfixed fsx;	/* first sample point x coord */
93        GLfixed fsy;
94        GLfloat adjy;	/* adjust from v[0]->fy to fsy, scaled */
95        GLint lines;	/* number of lines to be sampled on this edge */
96        GLfixed fx0;	/* fixed pt X of lower endpoint */
97   } EdgeT;
98
99#ifdef INTERP_Z
100   const GLint depthBits = ctx->Visual.depthBits;
101   const GLint fixedToDepthShift = depthBits <= 16 ? FIXED_SHIFT : 0;
102   const GLfloat maxDepth = ctx->DepthMaxF;
103#define FixedToDepth(F)  ((F) >> fixedToDepthShift)
104#endif
105   EdgeT eMaj, eTop, eBot;
106   GLfloat oneOverArea;
107   const SWvertex *vMin, *vMid, *vMax;  /* Y(vMin)<=Y(vMid)<=Y(vMax) */
108   float bf = SWRAST_CONTEXT(ctx)->_backface_sign;
109   const GLint snapMask = ~((FIXED_ONE / (1 << SUB_PIXEL_BITS)) - 1); /* for x/y coord snapping */
110   GLfixed vMin_fx, vMin_fy, vMid_fx, vMid_fy, vMax_fx, vMax_fy;
111
112   struct sw_span span;
113
114   INIT_SPAN(span, GL_POLYGON, 0, 0, 0);
115
116#ifdef INTERP_Z
117   (void) fixedToDepthShift;
118#endif
119
120   /*
121   printf("%s()\n", __FUNCTION__);
122   printf("  %g, %g, %g\n", v0->win[0], v0->win[1], v0->win[2]);
123   printf("  %g, %g, %g\n", v1->win[0], v1->win[1], v1->win[2]);
124   printf("  %g, %g, %g\n", v2->win[0], v2->win[1], v2->win[2]);
125   */
126
127   /* Compute fixed point x,y coords w/ half-pixel offsets and snapping.
128    * And find the order of the 3 vertices along the Y axis.
129    */
130   {
131      const GLfixed fy0 = FloatToFixed(v0->win[1] - 0.5F) & snapMask;
132      const GLfixed fy1 = FloatToFixed(v1->win[1] - 0.5F) & snapMask;
133      const GLfixed fy2 = FloatToFixed(v2->win[1] - 0.5F) & snapMask;
134
135      if (fy0 <= fy1) {
136         if (fy1 <= fy2) {
137            /* y0 <= y1 <= y2 */
138            vMin = v0;   vMid = v1;   vMax = v2;
139            vMin_fy = fy0;  vMid_fy = fy1;  vMax_fy = fy2;
140         }
141         else if (fy2 <= fy0) {
142            /* y2 <= y0 <= y1 */
143            vMin = v2;   vMid = v0;   vMax = v1;
144            vMin_fy = fy2;  vMid_fy = fy0;  vMax_fy = fy1;
145         }
146         else {
147            /* y0 <= y2 <= y1 */
148            vMin = v0;   vMid = v2;   vMax = v1;
149            vMin_fy = fy0;  vMid_fy = fy2;  vMax_fy = fy1;
150            bf = -bf;
151         }
152      }
153      else {
154         if (fy0 <= fy2) {
155            /* y1 <= y0 <= y2 */
156            vMin = v1;   vMid = v0;   vMax = v2;
157            vMin_fy = fy1;  vMid_fy = fy0;  vMax_fy = fy2;
158            bf = -bf;
159         }
160         else if (fy2 <= fy1) {
161            /* y2 <= y1 <= y0 */
162            vMin = v2;   vMid = v1;   vMax = v0;
163            vMin_fy = fy2;  vMid_fy = fy1;  vMax_fy = fy0;
164            bf = -bf;
165         }
166         else {
167            /* y1 <= y2 <= y0 */
168            vMin = v1;   vMid = v2;   vMax = v0;
169            vMin_fy = fy1;  vMid_fy = fy2;  vMax_fy = fy0;
170         }
171      }
172
173      /* fixed point X coords */
174      vMin_fx = FloatToFixed(vMin->win[0] + 0.5F) & snapMask;
175      vMid_fx = FloatToFixed(vMid->win[0] + 0.5F) & snapMask;
176      vMax_fx = FloatToFixed(vMax->win[0] + 0.5F) & snapMask;
177   }
178
179   /* vertex/edge relationship */
180   eMaj.v0 = vMin;   eMaj.v1 = vMax;   /*TODO: .v1's not needed */
181   eTop.v0 = vMid;   eTop.v1 = vMax;
182   eBot.v0 = vMin;   eBot.v1 = vMid;
183
184   /* compute deltas for each edge:  vertex[upper] - vertex[lower] */
185   eMaj.dx = FixedToFloat(vMax_fx - vMin_fx);
186   eMaj.dy = FixedToFloat(vMax_fy - vMin_fy);
187   eTop.dx = FixedToFloat(vMax_fx - vMid_fx);
188   eTop.dy = FixedToFloat(vMax_fy - vMid_fy);
189   eBot.dx = FixedToFloat(vMid_fx - vMin_fx);
190   eBot.dy = FixedToFloat(vMid_fy - vMin_fy);
191
192   /* compute area, oneOverArea and perform backface culling */
193   {
194      const GLfloat area = eMaj.dx * eBot.dy - eBot.dx * eMaj.dy;
195
196      /* Do backface culling */
197      if (area * bf < 0.0)
198         return;
199
200      if (IS_INF_OR_NAN(area) || area == 0.0F)
201         return;
202
203      oneOverArea = 1.0F / area;
204   }
205
206#ifndef DO_OCCLUSION_TEST
207   ctx->OcclusionResult = GL_TRUE;
208#endif
209   span.facing = ctx->_Facing; /* for 2-sided stencil test */
210
211   /* Edge setup.  For a triangle strip these could be reused... */
212   {
213      eMaj.fsy = FixedCeil(vMin_fy);
214      eMaj.lines = FixedToInt(FixedCeil(vMax_fy - eMaj.fsy));
215      if (eMaj.lines > 0) {
216         GLfloat dxdy = eMaj.dx / eMaj.dy;
217         eMaj.fdxdy = SignedFloatToFixed(dxdy);
218         eMaj.adjy = (GLfloat) (eMaj.fsy - vMin_fy);  /* SCALED! */
219         eMaj.fx0 = vMin_fx;
220         eMaj.fsx = eMaj.fx0 + (GLfixed) (eMaj.adjy * dxdy);
221      }
222      else {
223         return;  /*CULLED*/
224      }
225
226      eTop.fsy = FixedCeil(vMid_fy);
227      eTop.lines = FixedToInt(FixedCeil(vMax_fy - eTop.fsy));
228      if (eTop.lines > 0) {
229         GLfloat dxdy = eTop.dx / eTop.dy;
230         eTop.fdxdy = SignedFloatToFixed(dxdy);
231         eTop.adjy = (GLfloat) (eTop.fsy - vMid_fy); /* SCALED! */
232         eTop.fx0 = vMid_fx;
233         eTop.fsx = eTop.fx0 + (GLfixed) (eTop.adjy * dxdy);
234      }
235
236      eBot.fsy = FixedCeil(vMin_fy);
237      eBot.lines = FixedToInt(FixedCeil(vMid_fy - eBot.fsy));
238      if (eBot.lines > 0) {
239         GLfloat dxdy = eBot.dx / eBot.dy;
240         eBot.fdxdy = SignedFloatToFixed(dxdy);
241         eBot.adjy = (GLfloat) (eBot.fsy - vMin_fy);  /* SCALED! */
242         eBot.fx0 = vMin_fx;
243         eBot.fsx = eBot.fx0 + (GLfixed) (eBot.adjy * dxdy);
244      }
245   }
246
247   /*
248    * Conceptually, we view a triangle as two subtriangles
249    * separated by a perfectly horizontal line.  The edge that is
250    * intersected by this line is one with maximal absolute dy; we
251    * call it a ``major'' edge.  The other two edges are the
252    * ``top'' edge (for the upper subtriangle) and the ``bottom''
253    * edge (for the lower subtriangle).  If either of these two
254    * edges is horizontal or very close to horizontal, the
255    * corresponding subtriangle might cover zero sample points;
256    * we take care to handle such cases, for performance as well
257    * as correctness.
258    *
259    * By stepping rasterization parameters along the major edge,
260    * we can avoid recomputing them at the discontinuity where
261    * the top and bottom edges meet.  However, this forces us to
262    * be able to scan both left-to-right and right-to-left.
263    * Also, we must determine whether the major edge is at the
264    * left or right side of the triangle.  We do this by
265    * computing the magnitude of the cross-product of the major
266    * and top edges.  Since this magnitude depends on the sine of
267    * the angle between the two edges, its sign tells us whether
268    * we turn to the left or to the right when travelling along
269    * the major edge to the top edge, and from this we infer
270    * whether the major edge is on the left or the right.
271    *
272    * Serendipitously, this cross-product magnitude is also a
273    * value we need to compute the iteration parameter
274    * derivatives for the triangle, and it can be used to perform
275    * backface culling because its sign tells us whether the
276    * triangle is clockwise or counterclockwise.  In this code we
277    * refer to it as ``area'' because it's also proportional to
278    * the pixel area of the triangle.
279    */
280
281   {
282      GLint scan_from_left_to_right;  /* true if scanning left-to-right */
283#ifdef INTERP_Z
284      GLfloat dzdx, dzdy;
285#endif
286#ifdef INTERP_FOG
287      GLfloat dfogdy;
288#endif
289#if defined(INTERP_RGB)
290      GLfloat drdx, drdy;
291      GLfloat dgdx, dgdy;
292      GLfloat dbdx, dbdy;
293#endif
294#if defined(INTERP_ALPHA)
295      GLfloat dadx, dady;
296#endif
297#if defined(INTERP_SPEC)
298      GLfloat dsrdx, dsrdy;
299      GLfloat dsgdx, dsgdy;
300      GLfloat dsbdx, dsbdy;
301#endif
302#ifdef INTERP_INDEX
303      GLfloat didx, didy;
304#endif
305
306      /*
307       * Execute user-supplied setup code
308       */
309#ifdef SETUP_CODE
310      SETUP_CODE
311#endif
312
313      scan_from_left_to_right = (oneOverArea < 0.0F);
314
315
316      /* compute d?/dx and d?/dy derivatives */
317#ifdef INTERP_Z
318      span.interpMask |= SPAN_Z;
319      {
320         GLfloat eMaj_dz, eBot_dz;
321         eMaj_dz = vMax->win[2] - vMin->win[2];
322         eBot_dz = vMid->win[2] - vMin->win[2];
323         dzdx = oneOverArea * (eMaj_dz * eBot.dy - eMaj.dy * eBot_dz);
324         if (dzdx > maxDepth || dzdx < -maxDepth) {
325            /* probably a sliver triangle */
326            dzdx = 0.0;
327            dzdy = 0.0;
328         }
329         else {
330            dzdy = oneOverArea * (eMaj.dx * eBot_dz - eMaj_dz * eBot.dx);
331         }
332         if (depthBits <= 16)
333            span.zStep = SignedFloatToFixed(dzdx);
334         else
335            span.zStep = (GLint) dzdx;
336      }
337#endif
338#ifdef INTERP_FOG
339      span.interpMask |= SPAN_FOG;
340      {
341         const GLfloat eMaj_dfog = vMax->fog - vMin->fog;
342         const GLfloat eBot_dfog = vMid->fog - vMin->fog;
343         span.fogStep = oneOverArea * (eMaj_dfog * eBot.dy - eMaj.dy * eBot_dfog);
344         dfogdy = oneOverArea * (eMaj.dx * eBot_dfog - eMaj_dfog * eBot.dx);
345      }
346#endif
347#ifdef INTERP_RGB
348      span.interpMask |= SPAN_RGBA;
349      if (ctx->Light.ShadeModel == GL_SMOOTH) {
350         GLfloat eMaj_dr = (GLfloat) ((ColorTemp) vMax->color[RCOMP] - vMin->color[RCOMP]);
351         GLfloat eBot_dr = (GLfloat) ((ColorTemp) vMid->color[RCOMP] - vMin->color[RCOMP]);
352         GLfloat eMaj_dg = (GLfloat) ((ColorTemp) vMax->color[GCOMP] - vMin->color[GCOMP]);
353         GLfloat eBot_dg = (GLfloat) ((ColorTemp) vMid->color[GCOMP] - vMin->color[GCOMP]);
354         GLfloat eMaj_db = (GLfloat) ((ColorTemp) vMax->color[BCOMP] - vMin->color[BCOMP]);
355         GLfloat eBot_db = (GLfloat) ((ColorTemp) vMid->color[BCOMP] - vMin->color[BCOMP]);
356#  ifdef INTERP_ALPHA
357         GLfloat eMaj_da = (GLfloat) ((ColorTemp) vMax->color[ACOMP] - vMin->color[ACOMP]);
358         GLfloat eBot_da = (GLfloat) ((ColorTemp) vMid->color[ACOMP] - vMin->color[ACOMP]);
359#  endif
360         drdx = oneOverArea * (eMaj_dr * eBot.dy - eMaj.dy * eBot_dr);
361         drdy = oneOverArea * (eMaj.dx * eBot_dr - eMaj_dr * eBot.dx);
362         dgdx = oneOverArea * (eMaj_dg * eBot.dy - eMaj.dy * eBot_dg);
363         dgdy = oneOverArea * (eMaj.dx * eBot_dg - eMaj_dg * eBot.dx);
364         dbdx = oneOverArea * (eMaj_db * eBot.dy - eMaj.dy * eBot_db);
365         dbdy = oneOverArea * (eMaj.dx * eBot_db - eMaj_db * eBot.dx);
366#  if CHAN_TYPE == GL_FLOAT
367         span.redStep   = drdx;
368         span.greenStep = dgdx;
369         span.blueStep  = dbdx;
370#  else
371         span.redStep   = SignedFloatToFixed(drdx);
372         span.greenStep = SignedFloatToFixed(dgdx);
373         span.blueStep  = SignedFloatToFixed(dbdx);
374#  endif /* GL_FLOAT */
375#  ifdef INTERP_ALPHA
376         dadx = oneOverArea * (eMaj_da * eBot.dy - eMaj.dy * eBot_da);
377         dady = oneOverArea * (eMaj.dx * eBot_da - eMaj_da * eBot.dx);
378#    if CHAN_TYPE == GL_FLOAT
379         span.alphaStep = dadx;
380#    else
381         span.alphaStep = SignedFloatToFixed(dadx);
382#    endif /* GL_FLOAT */
383#  endif /* INTERP_ALPHA */
384      }
385      else {
386         ASSERT (ctx->Light.ShadeModel == GL_FLAT);
387         span.interpMask |= SPAN_FLAT;
388         drdx = drdy = span.redStep   = 0;
389         dgdx = dgdy = span.greenStep = 0;
390         dbdx = dbdy = span.blueStep  = 0;
391#  ifdef INTERP_ALPHA
392         dadx = dady = span.alphaStep = 0;
393#  endif
394      }
395#endif /* INTERP_RGB */
396#ifdef INTERP_SPEC
397      span.interpMask |= SPAN_SPEC;
398      if (ctx->Light.ShadeModel == GL_SMOOTH) {
399         GLfloat eMaj_dsr = (GLfloat) ((ColorTemp) vMax->specular[RCOMP] - vMin->specular[RCOMP]);
400         GLfloat eBot_dsr = (GLfloat) ((ColorTemp) vMid->specular[RCOMP] - vMin->specular[RCOMP]);
401         GLfloat eMaj_dsg = (GLfloat) ((ColorTemp) vMax->specular[GCOMP] - vMin->specular[GCOMP]);
402         GLfloat eBot_dsg = (GLfloat) ((ColorTemp) vMid->specular[GCOMP] - vMin->specular[GCOMP]);
403         GLfloat eMaj_dsb = (GLfloat) ((ColorTemp) vMax->specular[BCOMP] - vMin->specular[BCOMP]);
404         GLfloat eBot_dsb = (GLfloat) ((ColorTemp) vMid->specular[BCOMP] - vMin->specular[BCOMP]);
405         dsrdx = oneOverArea * (eMaj_dsr * eBot.dy - eMaj.dy * eBot_dsr);
406         dsrdy = oneOverArea * (eMaj.dx * eBot_dsr - eMaj_dsr * eBot.dx);
407         dsgdx = oneOverArea * (eMaj_dsg * eBot.dy - eMaj.dy * eBot_dsg);
408         dsgdy = oneOverArea * (eMaj.dx * eBot_dsg - eMaj_dsg * eBot.dx);
409         dsbdx = oneOverArea * (eMaj_dsb * eBot.dy - eMaj.dy * eBot_dsb);
410         dsbdy = oneOverArea * (eMaj.dx * eBot_dsb - eMaj_dsb * eBot.dx);
411#  if CHAN_TYPE == GL_FLOAT
412         span.specRedStep   = dsrdx;
413         span.specGreenStep = dsgdx;
414         span.specBlueStep  = dsbdx;
415#  else
416         span.specRedStep   = SignedFloatToFixed(dsrdx);
417         span.specGreenStep = SignedFloatToFixed(dsgdx);
418         span.specBlueStep  = SignedFloatToFixed(dsbdx);
419#  endif
420      }
421      else {
422         dsrdx = dsrdy = span.specRedStep   = 0;
423         dsgdx = dsgdy = span.specGreenStep = 0;
424         dsbdx = dsbdy = span.specBlueStep  = 0;
425      }
426#endif /* INTERP_SPEC */
427#ifdef INTERP_INDEX
428      span.interpMask |= SPAN_INDEX;
429      if (ctx->Light.ShadeModel == GL_SMOOTH) {
430         GLfloat eMaj_di = (GLfloat) ((GLint) vMax->index - (GLint) vMin->index);
431         GLfloat eBot_di = (GLfloat) ((GLint) vMid->index - (GLint) vMin->index);
432         didx = oneOverArea * (eMaj_di * eBot.dy - eMaj.dy * eBot_di);
433         didy = oneOverArea * (eMaj.dx * eBot_di - eMaj_di * eBot.dx);
434         span.indexStep = SignedFloatToFixed(didx);
435      }
436      else {
437         span.interpMask |= SPAN_FLAT;
438         didx = didy = 0.0F;
439         span.indexStep = 0;
440      }
441#endif
442#ifdef INTERP_INT_TEX
443      span.interpMask |= SPAN_INT_TEXTURE;
444      {
445         GLfloat eMaj_ds = (vMax->texcoord[0][0] - vMin->texcoord[0][0]) * S_SCALE;
446         GLfloat eBot_ds = (vMid->texcoord[0][0] - vMin->texcoord[0][0]) * S_SCALE;
447         GLfloat eMaj_dt = (vMax->texcoord[0][1] - vMin->texcoord[0][1]) * T_SCALE;
448         GLfloat eBot_dt = (vMid->texcoord[0][1] - vMin->texcoord[0][1]) * T_SCALE;
449         span.texStepX[0][0] = oneOverArea * (eMaj_ds * eBot.dy - eMaj.dy * eBot_ds);
450         span.texStepY[0][0] = oneOverArea * (eMaj.dx * eBot_ds - eMaj_ds * eBot.dx);
451         span.texStepX[0][1] = oneOverArea * (eMaj_dt * eBot.dy - eMaj.dy * eBot_dt);
452         span.texStepY[0][1] = oneOverArea * (eMaj.dx * eBot_dt - eMaj_dt * eBot.dx);
453         span.intTexStep[0] = SignedFloatToFixed(span.texStepX[0][0]);
454         span.intTexStep[1] = SignedFloatToFixed(span.texStepX[0][1]);
455      }
456#endif
457#ifdef INTERP_TEX
458      span.interpMask |= SPAN_TEXTURE;
459      {
460         const GLfloat wMax = vMax->win[3], wMin = vMin->win[3], wMid = vMid->win[3];
461         GLfloat eMaj_ds = vMax->texcoord[0][0] * wMax - vMin->texcoord[0][0] * wMin;
462         GLfloat eBot_ds = vMid->texcoord[0][0] * wMid - vMin->texcoord[0][0] * wMin;
463         GLfloat eMaj_dt = vMax->texcoord[0][1] * wMax - vMin->texcoord[0][1] * wMin;
464         GLfloat eBot_dt = vMid->texcoord[0][1] * wMid - vMin->texcoord[0][1] * wMin;
465         GLfloat eMaj_du = vMax->texcoord[0][2] * wMax - vMin->texcoord[0][2] * wMin;
466         GLfloat eBot_du = vMid->texcoord[0][2] * wMid - vMin->texcoord[0][2] * wMin;
467         GLfloat eMaj_dv = vMax->texcoord[0][3] * wMax - vMin->texcoord[0][3] * wMin;
468         GLfloat eBot_dv = vMid->texcoord[0][3] * wMid - vMin->texcoord[0][3] * wMin;
469         span.texStepX[0][0] = oneOverArea * (eMaj_ds * eBot.dy - eMaj.dy * eBot_ds);
470         span.texStepY[0][0] = oneOverArea * (eMaj.dx * eBot_ds - eMaj_ds * eBot.dx);
471         span.texStepX[0][1] = oneOverArea * (eMaj_dt * eBot.dy - eMaj.dy * eBot_dt);
472         span.texStepY[0][1] = oneOverArea * (eMaj.dx * eBot_dt - eMaj_dt * eBot.dx);
473         span.texStepX[0][2] = oneOverArea * (eMaj_du * eBot.dy - eMaj.dy * eBot_du);
474         span.texStepY[0][2] = oneOverArea * (eMaj.dx * eBot_du - eMaj_du * eBot.dx);
475         span.texStepX[0][3] = oneOverArea * (eMaj_dv * eBot.dy - eMaj.dy * eBot_dv);
476         span.texStepY[0][3] = oneOverArea * (eMaj.dx * eBot_dv - eMaj_dv * eBot.dx);
477      }
478#endif
479#ifdef INTERP_MULTITEX
480      span.interpMask |= SPAN_TEXTURE;
481      {
482         const GLfloat wMax = vMax->win[3], wMin = vMin->win[3], wMid = vMid->win[3];
483         GLuint u;
484         for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
485            if (ctx->Texture.Unit[u]._ReallyEnabled) {
486               GLfloat eMaj_ds = vMax->texcoord[u][0] * wMax - vMin->texcoord[u][0] * wMin;
487               GLfloat eBot_ds = vMid->texcoord[u][0] * wMid - vMin->texcoord[u][0] * wMin;
488               GLfloat eMaj_dt = vMax->texcoord[u][1] * wMax - vMin->texcoord[u][1] * wMin;
489               GLfloat eBot_dt = vMid->texcoord[u][1] * wMid - vMin->texcoord[u][1] * wMin;
490               GLfloat eMaj_du = vMax->texcoord[u][2] * wMax - vMin->texcoord[u][2] * wMin;
491               GLfloat eBot_du = vMid->texcoord[u][2] * wMid - vMin->texcoord[u][2] * wMin;
492               GLfloat eMaj_dv = vMax->texcoord[u][3] * wMax - vMin->texcoord[u][3] * wMin;
493               GLfloat eBot_dv = vMid->texcoord[u][3] * wMid - vMin->texcoord[u][3] * wMin;
494               span.texStepX[u][0] = oneOverArea * (eMaj_ds * eBot.dy - eMaj.dy * eBot_ds);
495               span.texStepY[u][0] = oneOverArea * (eMaj.dx * eBot_ds - eMaj_ds * eBot.dx);
496               span.texStepX[u][1] = oneOverArea * (eMaj_dt * eBot.dy - eMaj.dy * eBot_dt);
497               span.texStepY[u][1] = oneOverArea * (eMaj.dx * eBot_dt - eMaj_dt * eBot.dx);
498               span.texStepX[u][2] = oneOverArea * (eMaj_du * eBot.dy - eMaj.dy * eBot_du);
499               span.texStepY[u][2] = oneOverArea * (eMaj.dx * eBot_du - eMaj_du * eBot.dx);
500               span.texStepX[u][3] = oneOverArea * (eMaj_dv * eBot.dy - eMaj.dy * eBot_dv);
501               span.texStepY[u][3] = oneOverArea * (eMaj.dx * eBot_dv - eMaj_dv * eBot.dx);
502            }
503         }
504      }
505#endif
506
507      /*
508       * We always sample at pixel centers.  However, we avoid
509       * explicit half-pixel offsets in this code by incorporating
510       * the proper offset in each of x and y during the
511       * transformation to window coordinates.
512       *
513       * We also apply the usual rasterization rules to prevent
514       * cracks and overlaps.  A pixel is considered inside a
515       * subtriangle if it meets all of four conditions: it is on or
516       * to the right of the left edge, strictly to the left of the
517       * right edge, on or below the top edge, and strictly above
518       * the bottom edge.  (Some edges may be degenerate.)
519       *
520       * The following discussion assumes left-to-right scanning
521       * (that is, the major edge is on the left); the right-to-left
522       * case is a straightforward variation.
523       *
524       * We start by finding the half-integral y coordinate that is
525       * at or below the top of the triangle.  This gives us the
526       * first scan line that could possibly contain pixels that are
527       * inside the triangle.
528       *
529       * Next we creep down the major edge until we reach that y,
530       * and compute the corresponding x coordinate on the edge.
531       * Then we find the half-integral x that lies on or just
532       * inside the edge.  This is the first pixel that might lie in
533       * the interior of the triangle.  (We won't know for sure
534       * until we check the other edges.)
535       *
536       * As we rasterize the triangle, we'll step down the major
537       * edge.  For each step in y, we'll move an integer number
538       * of steps in x.  There are two possible x step sizes, which
539       * we'll call the ``inner'' step (guaranteed to land on the
540       * edge or inside it) and the ``outer'' step (guaranteed to
541       * land on the edge or outside it).  The inner and outer steps
542       * differ by one.  During rasterization we maintain an error
543       * term that indicates our distance from the true edge, and
544       * select either the inner step or the outer step, whichever
545       * gets us to the first pixel that falls inside the triangle.
546       *
547       * All parameters (z, red, etc.) as well as the buffer
548       * addresses for color and z have inner and outer step values,
549       * so that we can increment them appropriately.  This method
550       * eliminates the need to adjust parameters by creeping a
551       * sub-pixel amount into the triangle at each scanline.
552       */
553
554      {
555         int subTriangle;
556         GLfixed fx;
557         GLfixed fxLeftEdge = 0, fxRightEdge = 0;
558         GLfixed fdxLeftEdge = 0, fdxRightEdge = 0;
559         GLfixed fdxOuter;
560         int idxOuter;
561         float dxOuter;
562         GLfixed fError = 0, fdError = 0;
563         float adjx, adjy;
564         GLfixed fy;
565#ifdef PIXEL_ADDRESS
566         PIXEL_TYPE *pRow = NULL;
567         int dPRowOuter = 0, dPRowInner;  /* offset in bytes */
568#endif
569#ifdef INTERP_Z
570#  ifdef DEPTH_TYPE
571         DEPTH_TYPE *zRow = NULL;
572         int dZRowOuter = 0, dZRowInner;  /* offset in bytes */
573#  endif
574         GLfixed fz = 0, fdzOuter = 0, fdzInner;
575#endif
576#ifdef INTERP_FOG
577         GLfloat fogLeft = 0, dfogOuter = 0, dfogInner;
578#endif
579#ifdef INTERP_RGB
580         ColorTemp fr = 0, fdrOuter = 0, fdrInner;
581         ColorTemp fg = 0, fdgOuter = 0, fdgInner;
582         ColorTemp fb = 0, fdbOuter = 0, fdbInner;
583#endif
584#ifdef INTERP_ALPHA
585         ColorTemp fa = 0, fdaOuter = 0, fdaInner;
586#endif
587#ifdef INTERP_SPEC
588         ColorTemp fsr=0, fdsrOuter=0, fdsrInner;
589         ColorTemp fsg=0, fdsgOuter=0, fdsgInner;
590         ColorTemp fsb=0, fdsbOuter=0, fdsbInner;
591#endif
592#ifdef INTERP_INDEX
593         GLfixed fi=0, fdiOuter=0, fdiInner;
594#endif
595#ifdef INTERP_INT_TEX
596         GLfixed fs=0, fdsOuter=0, fdsInner;
597         GLfixed ft=0, fdtOuter=0, fdtInner;
598#endif
599#ifdef INTERP_TEX
600         GLfloat sLeft=0, dsOuter=0, dsInner;
601         GLfloat tLeft=0, dtOuter=0, dtInner;
602         GLfloat uLeft=0, duOuter=0, duInner;
603         GLfloat vLeft=0, dvOuter=0, dvInner;
604#endif
605#ifdef INTERP_MULTITEX
606         GLfloat sLeft[MAX_TEXTURE_COORD_UNITS];
607         GLfloat tLeft[MAX_TEXTURE_COORD_UNITS];
608         GLfloat uLeft[MAX_TEXTURE_COORD_UNITS];
609         GLfloat vLeft[MAX_TEXTURE_COORD_UNITS];
610         GLfloat dsOuter[MAX_TEXTURE_COORD_UNITS], dsInner[MAX_TEXTURE_COORD_UNITS];
611         GLfloat dtOuter[MAX_TEXTURE_COORD_UNITS], dtInner[MAX_TEXTURE_COORD_UNITS];
612         GLfloat duOuter[MAX_TEXTURE_COORD_UNITS], duInner[MAX_TEXTURE_COORD_UNITS];
613         GLfloat dvOuter[MAX_TEXTURE_COORD_UNITS], dvInner[MAX_TEXTURE_COORD_UNITS];
614#endif
615
616         for (subTriangle=0; subTriangle<=1; subTriangle++) {
617            EdgeT *eLeft, *eRight;
618            int setupLeft, setupRight;
619            int lines;
620
621            if (subTriangle==0) {
622               /* bottom half */
623               if (scan_from_left_to_right) {
624                  eLeft = &eMaj;
625                  eRight = &eBot;
626                  lines = eRight->lines;
627                  setupLeft = 1;
628                  setupRight = 1;
629               }
630               else {
631                  eLeft = &eBot;
632                  eRight = &eMaj;
633                  lines = eLeft->lines;
634                  setupLeft = 1;
635                  setupRight = 1;
636               }
637            }
638            else {
639               /* top half */
640               if (scan_from_left_to_right) {
641                  eLeft = &eMaj;
642                  eRight = &eTop;
643                  lines = eRight->lines;
644                  setupLeft = 0;
645                  setupRight = 1;
646               }
647               else {
648                  eLeft = &eTop;
649                  eRight = &eMaj;
650                  lines = eLeft->lines;
651                  setupLeft = 1;
652                  setupRight = 0;
653               }
654               if (lines == 0)
655                  return;
656            }
657
658            if (setupLeft && eLeft->lines > 0) {
659               const SWvertex *vLower;
660               GLfixed fsx = eLeft->fsx;
661               fx = FixedCeil(fsx);
662               fError = fx - fsx - FIXED_ONE;
663               fxLeftEdge = fsx - FIXED_EPSILON;
664               fdxLeftEdge = eLeft->fdxdy;
665               fdxOuter = FixedFloor(fdxLeftEdge - FIXED_EPSILON);
666               fdError = fdxOuter - fdxLeftEdge + FIXED_ONE;
667               idxOuter = FixedToInt(fdxOuter);
668               dxOuter = (float) idxOuter;
669               (void) dxOuter;
670
671               fy = eLeft->fsy;
672               span.y = FixedToInt(fy);
673
674               adjx = (float)(fx - eLeft->fx0);  /* SCALED! */
675               adjy = eLeft->adjy;		 /* SCALED! */
676#ifndef __IBMCPP__
677               (void) adjx;  /* silence compiler warnings */
678               (void) adjy;  /* silence compiler warnings */
679#endif
680               vLower = eLeft->v0;
681#ifndef __IBMCPP__
682               (void) vLower;  /* silence compiler warnings */
683#endif
684
685#ifdef PIXEL_ADDRESS
686               {
687                  pRow = (PIXEL_TYPE *) PIXEL_ADDRESS(FixedToInt(fxLeftEdge), span.y);
688                  dPRowOuter = -((int)BYTES_PER_ROW) + idxOuter * sizeof(PIXEL_TYPE);
689                  /* negative because Y=0 at bottom and increases upward */
690               }
691#endif
692               /*
693                * Now we need the set of parameter (z, color, etc.) values at
694                * the point (fx, fy).  This gives us properly-sampled parameter
695                * values that we can step from pixel to pixel.  Furthermore,
696                * although we might have intermediate results that overflow
697                * the normal parameter range when we step temporarily outside
698                * the triangle, we shouldn't overflow or underflow for any
699                * pixel that's actually inside the triangle.
700                */
701
702#ifdef INTERP_Z
703               {
704                  GLfloat z0 = vLower->win[2];
705                  if (depthBits <= 16) {
706                     /* interpolate fixed-pt values */
707                     GLfloat tmp = (z0 * FIXED_SCALE + dzdx * adjx + dzdy * adjy) + FIXED_HALF;
708                     if (tmp < MAX_GLUINT / 2)
709                        fz = (GLfixed) tmp;
710                     else
711                        fz = MAX_GLUINT / 2;
712                     fdzOuter = SignedFloatToFixed(dzdy + dxOuter * dzdx);
713                  }
714                  else {
715                     /* interpolate depth values exactly */
716                     fz = (GLint) (z0 + dzdx * FixedToFloat(adjx) + dzdy * FixedToFloat(adjy));
717                     fdzOuter = (GLint) (dzdy + dxOuter * dzdx);
718                  }
719#  ifdef DEPTH_TYPE
720                  zRow = (DEPTH_TYPE *)
721                    _mesa_zbuffer_address(ctx, FixedToInt(fxLeftEdge), span.y);
722                  dZRowOuter = (ctx->DrawBuffer->Width + idxOuter) * sizeof(DEPTH_TYPE);
723#  endif
724               }
725#endif
726#ifdef INTERP_FOG
727               fogLeft = vLower->fog + (span.fogStep * adjx + dfogdy * adjy)
728                                       * (1.0F/FIXED_SCALE);
729               dfogOuter = dfogdy + dxOuter * span.fogStep;
730#endif
731#ifdef INTERP_RGB
732               if (ctx->Light.ShadeModel == GL_SMOOTH) {
733#  if CHAN_TYPE == GL_FLOAT
734                  fr = vLower->color[RCOMP] + (drdx * adjx + drdy * adjy) * (1.0F / FIXED_SCALE);
735                  fg = vLower->color[GCOMP] + (dgdx * adjx + dgdy * adjy) * (1.0F / FIXED_SCALE);
736                  fb = vLower->color[BCOMP] + (dbdx * adjx + dbdy * adjy) * (1.0F / FIXED_SCALE);
737                  fdrOuter = drdy + dxOuter * drdx;
738                  fdgOuter = dgdy + dxOuter * dgdx;
739                  fdbOuter = dbdy + dxOuter * dbdx;
740#  else
741                  fr = (ChanToFixed(vLower->color[RCOMP]) + drdx * adjx + drdy * adjy) + FIXED_HALF;
742                  fg = (ChanToFixed(vLower->color[GCOMP]) + dgdx * adjx + dgdy * adjy) + FIXED_HALF;
743                  fb = (ChanToFixed(vLower->color[BCOMP]) + dbdx * adjx + dbdy * adjy) + FIXED_HALF;
744                  fdrOuter = SignedFloatToFixed(drdy + dxOuter * drdx);
745                  fdgOuter = SignedFloatToFixed(dgdy + dxOuter * dgdx);
746                  fdbOuter = SignedFloatToFixed(dbdy + dxOuter * dbdx);
747#  endif
748#  ifdef INTERP_ALPHA
749#    if CHAN_TYPE == GL_FLOAT
750                  fa = vLower->color[ACOMP] + (dadx * adjx + dady * adjy) * (1.0F / FIXED_SCALE);
751                  fdaOuter = dady + dxOuter * dadx;
752#    else
753                  fa = (ChanToFixed(vLower->color[ACOMP]) + dadx * adjx + dady * adjy) + FIXED_HALF;
754                  fdaOuter = SignedFloatToFixed(dady + dxOuter * dadx);
755#    endif
756#  endif
757               }
758               else {
759                  ASSERT (ctx->Light.ShadeModel == GL_FLAT);
760#  if CHAN_TYPE == GL_FLOAT
761                  fr = v2->color[RCOMP];
762                  fg = v2->color[GCOMP];
763                  fb = v2->color[BCOMP];
764                  fdrOuter = fdgOuter = fdbOuter = 0.0F;
765#  else
766                  fr = ChanToFixed(v2->color[RCOMP]);
767                  fg = ChanToFixed(v2->color[GCOMP]);
768                  fb = ChanToFixed(v2->color[BCOMP]);
769                  fdrOuter = fdgOuter = fdbOuter = 0;
770#  endif
771#  ifdef INTERP_ALPHA
772#    if CHAN_TYPE == GL_FLOAT
773                  fa = v2->color[ACOMP];
774                  fdaOuter = 0.0F;
775#    else
776                  fa = ChanToFixed(v2->color[ACOMP]);
777                  fdaOuter = 0;
778#    endif
779#  endif
780               }
781#endif
782
783#ifdef INTERP_SPEC
784               if (ctx->Light.ShadeModel == GL_SMOOTH) {
785#  if CHAN_TYPE == GL_FLOAT
786                  fsr = vLower->specular[RCOMP] + (dsrdx * adjx + dsrdy * adjy) * (1.0F / FIXED_SCALE);
787                  fsg = vLower->specular[GCOMP] + (dsgdx * adjx + dsgdy * adjy) * (1.0F / FIXED_SCALE);
788                  fsb = vLower->specular[BCOMP] + (dsbdx * adjx + dsbdy * adjy) * (1.0F / FIXED_SCALE);
789                  fdsrOuter = dsrdy + dxOuter * dsrdx;
790                  fdsgOuter = dsgdy + dxOuter * dsgdx;
791                  fdsbOuter = dsbdy + dxOuter * dsbdx;
792#  else
793                  fsr = (GLfixed) (ChanToFixed(vLower->specular[RCOMP]) + dsrdx * adjx + dsrdy * adjy) + FIXED_HALF;
794                  fsg = (GLfixed) (ChanToFixed(vLower->specular[GCOMP]) + dsgdx * adjx + dsgdy * adjy) + FIXED_HALF;
795                  fsb = (GLfixed) (ChanToFixed(vLower->specular[BCOMP]) + dsbdx * adjx + dsbdy * adjy) + FIXED_HALF;
796                  fdsrOuter = SignedFloatToFixed(dsrdy + dxOuter * dsrdx);
797                  fdsgOuter = SignedFloatToFixed(dsgdy + dxOuter * dsgdx);
798                  fdsbOuter = SignedFloatToFixed(dsbdy + dxOuter * dsbdx);
799#  endif
800               }
801               else {
802#if  CHAN_TYPE == GL_FLOAT
803                  fsr = v2->specular[RCOMP];
804                  fsg = v2->specular[GCOMP];
805                  fsb = v2->specular[BCOMP];
806                  fdsrOuter = fdsgOuter = fdsbOuter = 0.0F;
807#  else
808                  fsr = ChanToFixed(v2->specular[RCOMP]);
809                  fsg = ChanToFixed(v2->specular[GCOMP]);
810                  fsb = ChanToFixed(v2->specular[BCOMP]);
811                  fdsrOuter = fdsgOuter = fdsbOuter = 0;
812#  endif
813               }
814#endif
815
816#ifdef INTERP_INDEX
817               if (ctx->Light.ShadeModel == GL_SMOOTH) {
818                  fi = (GLfixed)(vLower->index * FIXED_SCALE
819                                 + didx * adjx + didy * adjy) + FIXED_HALF;
820                  fdiOuter = SignedFloatToFixed(didy + dxOuter * didx);
821               }
822               else {
823                  fi = (GLfixed) (v2->index * FIXED_SCALE);
824                  fdiOuter = 0;
825               }
826#endif
827#ifdef INTERP_INT_TEX
828               {
829                  GLfloat s0, t0;
830                  s0 = vLower->texcoord[0][0] * S_SCALE;
831                  fs = (GLfixed)(s0 * FIXED_SCALE + span.texStepX[0][0] * adjx
832                                 + span.texStepY[0][0] * adjy) + FIXED_HALF;
833                  fdsOuter = SignedFloatToFixed(span.texStepY[0][0] + dxOuter * span.texStepX[0][0]);
834
835                  t0 = vLower->texcoord[0][1] * T_SCALE;
836                  ft = (GLfixed)(t0 * FIXED_SCALE + span.texStepX[0][1] * adjx
837                                 + span.texStepY[0][1] * adjy) + FIXED_HALF;
838                  fdtOuter = SignedFloatToFixed(span.texStepY[0][1] + dxOuter * span.texStepX[0][1]);
839               }
840#endif
841#ifdef INTERP_TEX
842               {
843                  const GLfloat invW = vLower->win[3];
844                  const GLfloat s0 = vLower->texcoord[0][0] * invW;
845                  const GLfloat t0 = vLower->texcoord[0][1] * invW;
846                  const GLfloat u0 = vLower->texcoord[0][2] * invW;
847                  const GLfloat v0 = vLower->texcoord[0][3] * invW;
848                  sLeft = s0 + (span.texStepX[0][0] * adjx + span.texStepY[0][0] * adjy) * (1.0F/FIXED_SCALE);
849                  tLeft = t0 + (span.texStepX[0][1] * adjx + span.texStepY[0][1] * adjy) * (1.0F/FIXED_SCALE);
850                  uLeft = u0 + (span.texStepX[0][2] * adjx + span.texStepY[0][2] * adjy) * (1.0F/FIXED_SCALE);
851                  vLeft = v0 + (span.texStepX[0][3] * adjx + span.texStepY[0][3] * adjy) * (1.0F/FIXED_SCALE);
852                  dsOuter = span.texStepY[0][0] + dxOuter * span.texStepX[0][0];
853                  dtOuter = span.texStepY[0][1] + dxOuter * span.texStepX[0][1];
854                  duOuter = span.texStepY[0][2] + dxOuter * span.texStepX[0][2];
855                  dvOuter = span.texStepY[0][3] + dxOuter * span.texStepX[0][3];
856               }
857#endif
858#ifdef INTERP_MULTITEX
859               {
860                  GLuint u;
861                  for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
862                     if (ctx->Texture.Unit[u]._ReallyEnabled) {
863                        const GLfloat invW = vLower->win[3];
864                        const GLfloat s0 = vLower->texcoord[u][0] * invW;
865                        const GLfloat t0 = vLower->texcoord[u][1] * invW;
866                        const GLfloat u0 = vLower->texcoord[u][2] * invW;
867                        const GLfloat v0 = vLower->texcoord[u][3] * invW;
868                        sLeft[u] = s0 + (span.texStepX[u][0] * adjx + span.texStepY[u][0] * adjy) * (1.0F/FIXED_SCALE);
869                        tLeft[u] = t0 + (span.texStepX[u][1] * adjx + span.texStepY[u][1] * adjy) * (1.0F/FIXED_SCALE);
870                        uLeft[u] = u0 + (span.texStepX[u][2] * adjx + span.texStepY[u][2] * adjy) * (1.0F/FIXED_SCALE);
871                        vLeft[u] = v0 + (span.texStepX[u][3] * adjx + span.texStepY[u][3] * adjy) * (1.0F/FIXED_SCALE);
872                        dsOuter[u] = span.texStepY[u][0] + dxOuter * span.texStepX[u][0];
873                        dtOuter[u] = span.texStepY[u][1] + dxOuter * span.texStepX[u][1];
874                        duOuter[u] = span.texStepY[u][2] + dxOuter * span.texStepX[u][2];
875                        dvOuter[u] = span.texStepY[u][3] + dxOuter * span.texStepX[u][3];
876                     }
877                  }
878               }
879#endif
880
881            } /*if setupLeft*/
882
883
884            if (setupRight && eRight->lines>0) {
885               fxRightEdge = eRight->fsx - FIXED_EPSILON;
886               fdxRightEdge = eRight->fdxdy;
887            }
888
889            if (lines==0) {
890               continue;
891            }
892
893
894            /* Rasterize setup */
895#ifdef PIXEL_ADDRESS
896            dPRowInner = dPRowOuter + sizeof(PIXEL_TYPE);
897#endif
898#ifdef INTERP_Z
899#  ifdef DEPTH_TYPE
900            dZRowInner = dZRowOuter + sizeof(DEPTH_TYPE);
901#  endif
902            fdzInner = fdzOuter + span.zStep;
903#endif
904#ifdef INTERP_FOG
905            dfogInner = dfogOuter + span.fogStep;
906#endif
907#if defined(INTERP_RGB)
908            fdrInner = fdrOuter + span.redStep;
909            fdgInner = fdgOuter + span.greenStep;
910            fdbInner = fdbOuter + span.blueStep;
911#endif
912#if defined(INTERP_ALPHA)
913            fdaInner = fdaOuter + span.alphaStep;
914#endif
915#if defined(INTERP_SPEC)
916            fdsrInner = fdsrOuter + span.specRedStep;
917            fdsgInner = fdsgOuter + span.specGreenStep;
918            fdsbInner = fdsbOuter + span.specBlueStep;
919#endif
920#ifdef INTERP_INDEX
921            fdiInner = fdiOuter + span.indexStep;
922#endif
923#ifdef INTERP_INT_TEX
924            fdsInner = fdsOuter + span.intTexStep[0];
925            fdtInner = fdtOuter + span.intTexStep[1];
926#endif
927#ifdef INTERP_TEX
928            dsInner = dsOuter + span.texStepX[0][0];
929            dtInner = dtOuter + span.texStepX[0][1];
930            duInner = duOuter + span.texStepX[0][2];
931            dvInner = dvOuter + span.texStepX[0][3];
932#endif
933#ifdef INTERP_MULTITEX
934            {
935               GLuint u;
936               for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
937                  if (ctx->Texture.Unit[u]._ReallyEnabled) {
938                     dsInner[u] = dsOuter[u] + span.texStepX[u][0];
939                     dtInner[u] = dtOuter[u] + span.texStepX[u][1];
940                     duInner[u] = duOuter[u] + span.texStepX[u][2];
941                     dvInner[u] = dvOuter[u] + span.texStepX[u][3];
942                  }
943               }
944            }
945#endif
946
947            while (lines > 0) {
948               /* initialize the span interpolants to the leftmost value */
949               /* ff = fixed-pt fragment */
950               const GLint right = FixedToInt(fxRightEdge);
951
952               span.x = FixedToInt(fxLeftEdge);
953
954               if (right <= span.x)
955                  span.end = 0;
956               else
957                  span.end = right - span.x;
958
959#ifdef INTERP_Z
960               span.z = fz;
961#endif
962#ifdef INTERP_FOG
963               span.fog = fogLeft;
964#endif
965#if defined(INTERP_RGB)
966               span.red = fr;
967               span.green = fg;
968               span.blue = fb;
969#endif
970#if defined(INTERP_ALPHA)
971               span.alpha = fa;
972#endif
973#if defined(INTERP_SPEC)
974               span.specRed = fsr;
975               span.specGreen = fsg;
976               span.specBlue = fsb;
977#endif
978#ifdef INTERP_INDEX
979               span.index = fi;
980#endif
981#ifdef INTERP_INT_TEX
982               span.intTex[0] = fs;
983               span.intTex[1] = ft;
984#endif
985
986#ifdef INTERP_TEX
987               span.tex[0][0] = sLeft;
988               span.tex[0][1] = tLeft;
989               span.tex[0][2] = uLeft;
990               span.tex[0][3] = vLeft;
991#endif
992
993#ifdef INTERP_MULTITEX
994               {
995                  GLuint u;
996                  for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
997                     if (ctx->Texture.Unit[u]._ReallyEnabled) {
998                        span.tex[u][0] = sLeft[u];
999                        span.tex[u][1] = tLeft[u];
1000                        span.tex[u][2] = uLeft[u];
1001                        span.tex[u][3] = vLeft[u];
1002                     }
1003                  }
1004               }
1005#endif
1006
1007#ifdef INTERP_RGB
1008               {
1009                  /* need this to accomodate round-off errors */
1010                  const GLint len = right - span.x - 1;
1011                  GLfixed ffrend = span.red + len * span.redStep;
1012                  GLfixed ffgend = span.green + len * span.greenStep;
1013                  GLfixed ffbend = span.blue + len * span.blueStep;
1014                  if (ffrend < 0) {
1015                     span.red -= ffrend;
1016                     if (span.red < 0)
1017                        span.red = 0;
1018                  }
1019                  if (ffgend < 0) {
1020                     span.green -= ffgend;
1021                     if (span.green < 0)
1022                        span.green = 0;
1023                  }
1024                  if (ffbend < 0) {
1025                     span.blue -= ffbend;
1026                     if (span.blue < 0)
1027                        span.blue = 0;
1028                  }
1029               }
1030#endif
1031#ifdef INTERP_ALPHA
1032               {
1033                  const GLint len = right - span.x - 1;
1034                  GLfixed ffaend = span.alpha + len * span.alphaStep;
1035                  if (ffaend < 0) {
1036                     span.alpha -= ffaend;
1037                     if (span.alpha < 0)
1038                        span.alpha = 0;
1039                  }
1040               }
1041#endif
1042#ifdef INTERP_SPEC
1043               {
1044                  /* need this to accomodate round-off errors */
1045                  const GLint len = right - span.x - 1;
1046                  GLfixed ffsrend = span.specRed + len * span.specRedStep;
1047                  GLfixed ffsgend = span.specGreen + len * span.specGreenStep;
1048                  GLfixed ffsbend = span.specBlue + len * span.specBlueStep;
1049                  if (ffsrend < 0) {
1050                     span.specRed -= ffsrend;
1051                     if (span.specRed < 0)
1052                        span.specRed = 0;
1053                  }
1054                  if (ffsgend < 0) {
1055                     span.specGreen -= ffsgend;
1056                     if (span.specGreen < 0)
1057                        span.specGreen = 0;
1058                  }
1059                  if (ffsbend < 0) {
1060                     span.specBlue -= ffsbend;
1061                     if (span.specBlue < 0)
1062                        span.specBlue = 0;
1063                  }
1064               }
1065#endif
1066#ifdef INTERP_INDEX
1067               if (span.index < 0)  span.index = 0;
1068#endif
1069
1070               /* This is where we actually generate fragments */
1071               if (span.end > 0) {
1072                  RENDER_SPAN( span );
1073               }
1074
1075               /*
1076                * Advance to the next scan line.  Compute the
1077                * new edge coordinates, and adjust the
1078                * pixel-center x coordinate so that it stays
1079                * on or inside the major edge.
1080                */
1081               (span.y)++;
1082               lines--;
1083
1084               fxLeftEdge += fdxLeftEdge;
1085               fxRightEdge += fdxRightEdge;
1086
1087
1088               fError += fdError;
1089               if (fError >= 0) {
1090                  fError -= FIXED_ONE;
1091#ifdef PIXEL_ADDRESS
1092                  pRow = (PIXEL_TYPE *) ((GLubyte *) pRow + dPRowOuter);
1093#endif
1094#ifdef INTERP_Z
1095#  ifdef DEPTH_TYPE
1096                  zRow = (DEPTH_TYPE *) ((GLubyte *) zRow + dZRowOuter);
1097#  endif
1098                  fz += fdzOuter;
1099#endif
1100#ifdef INTERP_FOG
1101                  fogLeft += dfogOuter;
1102#endif
1103#if defined(INTERP_RGB)
1104                  fr += fdrOuter;
1105                  fg += fdgOuter;
1106                  fb += fdbOuter;
1107#endif
1108#if defined(INTERP_ALPHA)
1109                  fa += fdaOuter;
1110#endif
1111#if defined(INTERP_SPEC)
1112                  fsr += fdsrOuter;
1113                  fsg += fdsgOuter;
1114                  fsb += fdsbOuter;
1115#endif
1116#ifdef INTERP_INDEX
1117                  fi += fdiOuter;
1118#endif
1119#ifdef INTERP_INT_TEX
1120                  fs += fdsOuter;
1121                  ft += fdtOuter;
1122#endif
1123#ifdef INTERP_TEX
1124                  sLeft += dsOuter;
1125                  tLeft += dtOuter;
1126                  uLeft += duOuter;
1127                  vLeft += dvOuter;
1128#endif
1129#ifdef INTERP_MULTITEX
1130                  {
1131                     GLuint u;
1132                     for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
1133                        if (ctx->Texture.Unit[u]._ReallyEnabled) {
1134                           sLeft[u] += dsOuter[u];
1135                           tLeft[u] += dtOuter[u];
1136                           uLeft[u] += duOuter[u];
1137                           vLeft[u] += dvOuter[u];
1138                        }
1139                     }
1140                  }
1141#endif
1142               }
1143               else {
1144#ifdef PIXEL_ADDRESS
1145                  pRow = (PIXEL_TYPE *) ((GLubyte *) pRow + dPRowInner);
1146#endif
1147#ifdef INTERP_Z
1148#  ifdef DEPTH_TYPE
1149                  zRow = (DEPTH_TYPE *) ((GLubyte *) zRow + dZRowInner);
1150#  endif
1151                  fz += fdzInner;
1152#endif
1153#ifdef INTERP_FOG
1154                  fogLeft += dfogInner;
1155#endif
1156#if defined(INTERP_RGB)
1157                  fr += fdrInner;
1158                  fg += fdgInner;
1159                  fb += fdbInner;
1160#endif
1161#if defined(INTERP_ALPHA)
1162                  fa += fdaInner;
1163#endif
1164#if defined(INTERP_SPEC)
1165                  fsr += fdsrInner;
1166                  fsg += fdsgInner;
1167                  fsb += fdsbInner;
1168#endif
1169#ifdef INTERP_INDEX
1170                  fi += fdiInner;
1171#endif
1172#ifdef INTERP_INT_TEX
1173                  fs += fdsInner;
1174                  ft += fdtInner;
1175#endif
1176#ifdef INTERP_TEX
1177                  sLeft += dsInner;
1178                  tLeft += dtInner;
1179                  uLeft += duInner;
1180                  vLeft += dvInner;
1181#endif
1182#ifdef INTERP_MULTITEX
1183                  {
1184                     GLuint u;
1185                     for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
1186                        if (ctx->Texture.Unit[u]._ReallyEnabled) {
1187                           sLeft[u] += dsInner[u];
1188                           tLeft[u] += dtInner[u];
1189                           uLeft[u] += duInner[u];
1190                           vLeft[u] += dvInner[u];
1191                        }
1192                     }
1193                  }
1194#endif
1195               }
1196            } /*while lines>0*/
1197
1198         } /* for subTriangle */
1199
1200      }
1201#ifdef CLEANUP_CODE
1202      CLEANUP_CODE
1203#endif
1204   }
1205}
1206
1207#undef SETUP_CODE
1208#undef CLEANUP_CODE
1209#undef RENDER_SPAN
1210
1211#undef PIXEL_TYPE
1212#undef BYTES_PER_ROW
1213#undef PIXEL_ADDRESS
1214
1215#undef INTERP_Z
1216#undef INTERP_FOG
1217#undef INTERP_RGB
1218#undef INTERP_ALPHA
1219#undef INTERP_SPEC
1220#undef INTERP_INDEX
1221#undef INTERP_INT_TEX
1222#undef INTERP_TEX
1223#undef INTERP_MULTITEX
1224
1225#undef S_SCALE
1226#undef T_SCALE
1227
1228#undef FixedToDepth
1229
1230#undef DO_OCCLUSION_TEST
1231#undef NAME
1232