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