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