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