xref: /reactos/dll/opengl/mesa/tritemp.h (revision 1734f297)
1 /* $Id: tritemp.h,v 1.17 1998/01/16 03:46:07 brianp Exp $ */
2 
3 /*
4  * Mesa 3-D graphics library
5  * Version:  2.6
6  * Copyright (C) 1995-1997  Brian Paul
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public
19  * License along with this library; if not, write to the Free
20  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21  */
22 
23 
24 /*
25  * $Log: tritemp.h,v $
26  * Revision 1.17  1998/01/16 03:46:07  brianp
27  * fixed a few Windows compilation warnings (Theodore Jump)
28  *
29  * Revision 1.16  1997/09/18 01:08:10  brianp
30  * fixed S_SCALE / T_SCALE mix-up
31  *
32  * Revision 1.15  1997/08/22 01:53:03  brianp
33  * another attempt at fixing under/overflow errors
34  *
35  * Revision 1.14  1997/08/13 02:10:13  brianp
36  * added code to prevent over/underflow (Guido Jansen, Magnus Lundin)
37  *
38  * Revision 1.13  1997/06/20 02:52:49  brianp
39  * changed color components from GLfixed to GLubyte
40  *
41  * Revision 1.12  1997/03/14 00:25:02  brianp
42  * fixed unitialized memory read, contributed by Tom Schmidt
43  *
44  * Revision 1.11  1997/02/09 18:51:10  brianp
45  * fixed typo in texture R interpolation code
46  *
47  * Revision 1.10  1996/12/20 23:12:23  brianp
48  * another attempt at preventing color interpolation over/underflow
49  *
50  * Revision 1.9  1996/12/18 20:38:25  brianp
51  * commented out unused zp declaration
52  *
53  * Revision 1.8  1996/12/12 22:37:49  brianp
54  * projective textures didn't work right
55  *
56  * Revision 1.7  1996/11/02 06:17:37  brianp
57  * fixed some float/int roundoff and over/underflow errors (hopefully)
58  *
59  * Revision 1.6  1996/10/01 04:13:09  brianp
60  * fixed Z interpolation for >16-bit depth buffer
61  * added color underflow error check
62  *
63  * Revision 1.5  1996/09/27 01:32:59  brianp
64  * removed unused variables
65  *
66  * Revision 1.4  1996/09/18 01:03:43  brianp
67  * tightened threshold for culling by area
68  *
69  * Revision 1.3  1996/09/15 14:19:16  brianp
70  * now use GLframebuffer and GLvisual
71  *
72  * Revision 1.2  1996/09/14 06:41:38  brianp
73  * perspective correct texture code wasn't sub-pixel accurate (Doug Rabson)
74  *
75  * Revision 1.1  1996/09/13 01:38:16  brianp
76  * Initial revision
77  *
78  */
79 
80 
81 /*
82  * Triangle Rasterizer Template
83  *
84  * This file is #include'd to generate custom triangle rasterizers.
85  *
86  * The following macros may be defined to indicate what auxillary information
87  * must be interplated across the triangle:
88  *    INTERP_Z      - if defined, interpolate Z values
89  *    INTERP_RGB    - if defined, interpolate RGB values
90  *    INTERP_ALPHA  - if defined, interpolate Alpha values
91  *    INTERP_INDEX  - if defined, interpolate color index values
92  *    INTERP_ST     - if defined, interpolate integer ST texcoords
93  *                         (fast, simple 2-D texture mapping)
94  *    INTERP_STW    - if defined, interpolate float ST texcoords and W
95  *                         (2-D texture maps with perspective correction)
96  *    INTERP_UV     - if defined, interpolate float UV texcoords too
97  *                         (for 3-D, 4-D? texture maps)
98  *
99  * When one can directly address pixels in the color buffer the following
100  * macros can be defined and used to compute pixel addresses during
101  * rasterization (see pRow):
102  *    PIXEL_TYPE          - the datatype of a pixel (GLubyte, GLushort, GLuint)
103  *    BYTES_PER_ROW       - number of bytes per row in the color buffer
104  *    PIXEL_ADDRESS(X,Y)  - returns the address of pixel at (X,Y) where
105  *                          Y==0 at bottom of screen and increases upward.
106  *
107  * Optionally, one may provide one-time setup code per triangle:
108  *    SETUP_CODE    - code which is to be executed once per triangle
109  *
110  * The following macro MUST be defined:
111  *    INNER_LOOP(LEFT,RIGHT,Y) - code to write a span of pixels.
112  *        Something like:
113  *
114  *                    for (x=LEFT; x<RIGHT;x++) {
115  *                       put_pixel(x,Y);
116  *                       // increment fixed point interpolants
117  *                    }
118  *
119  * This code was designed for the origin to be in the lower-left corner.
120  *
121  * Inspired by triangle rasterizer code written by Allen Akin.  Thanks Allen!
122  */
123 
124 
125 /*void triangle( GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint pv )*/
126 {
127    typedef struct {
128         GLint v0, v1;     /* Y(v0) < Y(v1) */
129 	GLfloat dx;	/* X(v1) - X(v0) */
130 	GLfloat dy;	/* Y(v1) - Y(v0) */
131 	GLfixed fdxdy;	/* dx/dy in fixed-point */
132 	GLfixed fsx;	/* first sample point x coord */
133 	GLfixed fsy;
134 	GLfloat adjy;	/* adjust from v[0]->fy to fsy, scaled */
135 	GLint lines;	/* number of lines to be sampled on this edge */
136 	GLfixed fx0;	/* fixed pt X of lower endpoint */
137    } EdgeT;
138 
139    struct vertex_buffer *VB = ctx->VB;
140    EdgeT eMaj, eTop, eBot;
141    GLfloat oneOverArea;
142    int vMin, vMid, vMax;       /* vertex indexes:  Y(vMin)<=Y(vMid)<=Y(vMax) */
143 
144    /* find the order of the 3 vertices along the Y axis */
145    {
146       GLfloat y0 = VB->Win[v0][1];
147       GLfloat y1 = VB->Win[v1][1];
148       GLfloat y2 = VB->Win[v2][1];
149 
150       if (y0<=y1) {
151 	 if (y1<=y2) {
152 	    vMin = v0;   vMid = v1;   vMax = v2;   /* y0<=y1<=y2 */
153 	 }
154 	 else if (y2<=y0) {
155 	    vMin = v2;   vMid = v0;   vMax = v1;   /* y2<=y0<=y1 */
156 	 }
157 	 else {
158 	    vMin = v0;   vMid = v2;   vMax = v1;   /* y0<=y2<=y1 */
159 	 }
160       }
161       else {
162 	 if (y0<=y2) {
163 	    vMin = v1;   vMid = v0;   vMax = v2;   /* y1<=y0<=y2 */
164 	 }
165 	 else if (y2<=y1) {
166 	    vMin = v2;   vMid = v1;   vMax = v0;   /* y2<=y1<=y0 */
167 	 }
168 	 else {
169 	    vMin = v1;   vMid = v2;   vMax = v0;   /* y1<=y2<=y0 */
170 	 }
171       }
172    }
173 
174    /* vertex/edge relationship */
175    eMaj.v0 = vMin;   eMaj.v1 = vMax;   /*TODO: .v1's not needed */
176    eTop.v0 = vMid;   eTop.v1 = vMax;
177    eBot.v0 = vMin;   eBot.v1 = vMid;
178 
179    /* compute deltas for each edge:  vertex[v1] - vertex[v0] */
180    eMaj.dx = VB->Win[vMax][0] - VB->Win[vMin][0];
181    eMaj.dy = VB->Win[vMax][1] - VB->Win[vMin][1];
182    eTop.dx = VB->Win[vMax][0] - VB->Win[vMid][0];
183    eTop.dy = VB->Win[vMax][1] - VB->Win[vMid][1];
184    eBot.dx = VB->Win[vMid][0] - VB->Win[vMin][0];
185    eBot.dy = VB->Win[vMid][1] - VB->Win[vMin][1];
186 
187    /* compute oneOverArea */
188    {
189       GLfloat area = eMaj.dx * eBot.dy - eBot.dx * eMaj.dy;
190       if (area>-0.05f && area<0.05f) {
191          return;  /* very small; CULLED */
192       }
193       oneOverArea = 1.0F / area;
194    }
195 
196    /* Edge setup.  For a triangle strip these could be reused... */
197    {
198       /* fixed point Y coordinates */
199       GLfixed vMin_fx = FloatToFixed(VB->Win[vMin][0] + 0.5F);
200       GLfixed vMin_fy = FloatToFixed(VB->Win[vMin][1] - 0.5F);
201       GLfixed vMid_fx = FloatToFixed(VB->Win[vMid][0] + 0.5F);
202       GLfixed vMid_fy = FloatToFixed(VB->Win[vMid][1] - 0.5F);
203       GLfixed vMax_fy = FloatToFixed(VB->Win[vMax][1] - 0.5F);
204 
205       eMaj.fsy = FixedCeil(vMin_fy);
206       eMaj.lines = FixedToInt(vMax_fy + FIXED_ONE - FIXED_EPSILON - eMaj.fsy);
207       if (eMaj.lines > 0) {
208          GLfloat dxdy = eMaj.dx / eMaj.dy;
209          eMaj.fdxdy = SignedFloatToFixed(dxdy);
210          eMaj.adjy = (GLfloat) (eMaj.fsy - vMin_fy);  /* SCALED! */
211          eMaj.fx0 = vMin_fx;
212          eMaj.fsx = eMaj.fx0 + (GLfixed) (eMaj.adjy * dxdy);
213       }
214       else {
215          return;  /*CULLED*/
216       }
217 
218       eTop.fsy = FixedCeil(vMid_fy);
219       eTop.lines = FixedToInt(vMax_fy + FIXED_ONE - FIXED_EPSILON - eTop.fsy);
220       if (eTop.lines > 0) {
221          GLfloat dxdy = eTop.dx / eTop.dy;
222          eTop.fdxdy = SignedFloatToFixed(dxdy);
223          eTop.adjy = (GLfloat) (eTop.fsy - vMid_fy); /* SCALED! */
224          eTop.fx0 = vMid_fx;
225          eTop.fsx = eTop.fx0 + (GLfixed) (eTop.adjy * dxdy);
226       }
227 
228       eBot.fsy = FixedCeil(vMin_fy);
229       eBot.lines = FixedToInt(vMid_fy + FIXED_ONE - FIXED_EPSILON - eBot.fsy);
230       if (eBot.lines > 0) {
231          GLfloat dxdy = eBot.dx / eBot.dy;
232          eBot.fdxdy = SignedFloatToFixed(dxdy);
233          eBot.adjy = (GLfloat) (eBot.fsy - vMin_fy);  /* SCALED! */
234          eBot.fx0 = vMin_fx;
235          eBot.fsx = eBot.fx0 + (GLfixed) (eBot.adjy * dxdy);
236       }
237    }
238 
239    /*
240     * Conceptually, we view a triangle as two subtriangles
241     * separated by a perfectly horizontal line.  The edge that is
242     * intersected by this line is one with maximal absolute dy; we
243     * call it a ``major'' edge.  The other two edges are the
244     * ``top'' edge (for the upper subtriangle) and the ``bottom''
245     * edge (for the lower subtriangle).  If either of these two
246     * edges is horizontal or very close to horizontal, the
247     * corresponding subtriangle might cover zero sample points;
248     * we take care to handle such cases, for performance as well
249     * as correctness.
250     *
251     * By stepping rasterization parameters along the major edge,
252     * we can avoid recomputing them at the discontinuity where
253     * the top and bottom edges meet.  However, this forces us to
254     * be able to scan both left-to-right and right-to-left.
255     * Also, we must determine whether the major edge is at the
256     * left or right side of the triangle.  We do this by
257     * computing the magnitude of the cross-product of the major
258     * and top edges.  Since this magnitude depends on the sine of
259     * the angle between the two edges, its sign tells us whether
260     * we turn to the left or to the right when travelling along
261     * the major edge to the top edge, and from this we infer
262     * whether the major edge is on the left or the right.
263     *
264     * Serendipitously, this cross-product magnitude is also a
265     * value we need to compute the iteration parameter
266     * derivatives for the triangle, and it can be used to perform
267     * backface culling because its sign tells us whether the
268     * triangle is clockwise or counterclockwise.  In this code we
269     * refer to it as ``area'' because it's also proportional to
270     * the pixel area of the triangle.
271     */
272 
273    {
274       GLint ltor;		/* true if scanning left-to-right */
275 #if INTERP_Z
276       GLfloat dzdx, dzdy;      GLfixed fdzdx;
277 #endif
278 #if INTERP_RGB
279       GLfloat drdx, drdy;      GLfixed fdrdx;
280       GLfloat dgdx, dgdy;      GLfixed fdgdx;
281       GLfloat dbdx, dbdy;      GLfixed fdbdx;
282 #endif
283 #if INTERP_ALPHA
284       GLfloat dadx, dady;      GLfixed fdadx;
285 #endif
286 #if INTERP_INDEX
287       GLfloat didx, didy;      GLfixed fdidx;
288 #endif
289 #if INTERP_ST
290       GLfloat dsdx, dsdy;      GLfixed fdsdx;
291       GLfloat dtdx, dtdy;      GLfixed fdtdx;
292 #endif
293 #if INTERP_STW
294       GLfloat dsdx, dsdy;
295       GLfloat dtdx, dtdy;
296       GLfloat dwdx, dwdy;
297 #endif
298 #if INTERP_UV
299       GLfloat dudx, dudy;
300       GLfloat dvdx, dvdy;
301 #endif
302 
303       /*
304        * Execute user-supplied setup code
305        */
306 #ifdef SETUP_CODE
307       SETUP_CODE
308 #endif
309 
310       ltor = (oneOverArea < 0.0F);
311 
312       /* compute d?/dx and d?/dy derivatives */
313 #if INTERP_Z
314       {
315          GLfloat eMaj_dz, eBot_dz;
316          eMaj_dz = VB->Win[vMax][2] - VB->Win[vMin][2];
317          eBot_dz = VB->Win[vMid][2] - VB->Win[vMin][2];
318          dzdx = oneOverArea * (eMaj_dz * eBot.dy - eMaj.dy * eBot_dz);
319          if (dzdx>DEPTH_SCALE || dzdx<-DEPTH_SCALE) {
320             /* probably a sliver triangle */
321             dzdx = 0.0;
322             dzdy = 0.0;
323          }
324          else {
325             dzdy = oneOverArea * (eMaj.dx * eBot_dz - eMaj_dz * eBot.dx);
326          }
327          fdzdx = (GLint) dzdx;
328       }
329 #endif
330 #if INTERP_RGB
331       {
332          GLfloat eMaj_dr, eBot_dr;
333          eMaj_dr = (GLint) VB->Color[vMax][0] - (GLint) VB->Color[vMin][0];
334          eBot_dr = (GLint) VB->Color[vMid][0] - (GLint) VB->Color[vMin][0];
335          drdx = oneOverArea * (eMaj_dr * eBot.dy - eMaj.dy * eBot_dr);
336          fdrdx = SignedFloatToFixed(drdx);
337          drdy = oneOverArea * (eMaj.dx * eBot_dr - eMaj_dr * eBot.dx);
338       }
339       {
340          GLfloat eMaj_dg, eBot_dg;
341          eMaj_dg = (GLint) VB->Color[vMax][1] - (GLint) VB->Color[vMin][1];
342 	 eBot_dg = (GLint) VB->Color[vMid][1] - (GLint) VB->Color[vMin][1];
343          dgdx = oneOverArea * (eMaj_dg * eBot.dy - eMaj.dy * eBot_dg);
344          fdgdx = SignedFloatToFixed(dgdx);
345          dgdy = oneOverArea * (eMaj.dx * eBot_dg - eMaj_dg * eBot.dx);
346       }
347       {
348          GLfloat eMaj_db, eBot_db;
349          eMaj_db = (GLint) VB->Color[vMax][2] - (GLint) VB->Color[vMin][2];
350          eBot_db = (GLint) VB->Color[vMid][2] - (GLint) VB->Color[vMin][2];
351          dbdx = oneOverArea * (eMaj_db * eBot.dy - eMaj.dy * eBot_db);
352          fdbdx = SignedFloatToFixed(dbdx);
353 	 dbdy = oneOverArea * (eMaj.dx * eBot_db - eMaj_db * eBot.dx);
354       }
355 #endif
356 #if INTERP_ALPHA
357       {
358          GLfloat eMaj_da, eBot_da;
359          eMaj_da = (GLint) VB->Color[vMax][3] - (GLint) VB->Color[vMin][3];
360          eBot_da = (GLint) VB->Color[vMid][3] - (GLint) VB->Color[vMin][3];
361          dadx = oneOverArea * (eMaj_da * eBot.dy - eMaj.dy * eBot_da);
362          fdadx = SignedFloatToFixed(dadx);
363          dady = oneOverArea * (eMaj.dx * eBot_da - eMaj_da * eBot.dx);
364       }
365 #endif
366 #if INTERP_INDEX
367       {
368          GLfloat eMaj_di, eBot_di;
369          eMaj_di = (GLint) VB->Index[vMax] - (GLint) VB->Index[vMin];
370          eBot_di = (GLint) VB->Index[vMid] - (GLint) VB->Index[vMin];
371          didx = oneOverArea * (eMaj_di * eBot.dy - eMaj.dy * eBot_di);
372          fdidx = SignedFloatToFixed(didx);
373          didy = oneOverArea * (eMaj.dx * eBot_di - eMaj_di * eBot.dx);
374       }
375 #endif
376 #if INTERP_ST
377       {
378          GLfloat eMaj_ds, eBot_ds;
379          eMaj_ds = (VB->TexCoord[vMax][0] - VB->TexCoord[vMin][0]) * S_SCALE;
380          eBot_ds = (VB->TexCoord[vMid][0] - VB->TexCoord[vMin][0]) * S_SCALE;
381          dsdx = oneOverArea * (eMaj_ds * eBot.dy - eMaj.dy * eBot_ds);
382          fdsdx = SignedFloatToFixed(dsdx);
383          dsdy = oneOverArea * (eMaj.dx * eBot_ds - eMaj_ds * eBot.dx);
384       }
385       {
386          GLfloat eMaj_dt, eBot_dt;
387          eMaj_dt = (VB->TexCoord[vMax][1] - VB->TexCoord[vMin][1]) * T_SCALE;
388          eBot_dt = (VB->TexCoord[vMid][1] - VB->TexCoord[vMin][1]) * T_SCALE;
389          dtdx = oneOverArea * (eMaj_dt * eBot.dy - eMaj.dy * eBot_dt);
390          fdtdx = SignedFloatToFixed(dtdx);
391          dtdy = oneOverArea * (eMaj.dx * eBot_dt - eMaj_dt * eBot.dx);
392       }
393 #endif
394 #if INTERP_STW
395       {
396          GLfloat wMax = 1.0F / VB->Clip[vMax][3];
397          GLfloat wMin = 1.0F / VB->Clip[vMin][3];
398          GLfloat wMid = 1.0F / VB->Clip[vMid][3];
399          GLfloat eMaj_dw, eBot_dw;
400          GLfloat eMaj_ds, eBot_ds;
401          GLfloat eMaj_dt, eBot_dt;
402 #if INTERP_UV
403          GLfloat eMaj_du, eBot_du;
404          GLfloat eMaj_dv, eBot_dv;
405 #endif
406          eMaj_dw = wMax - wMin;
407          eBot_dw = wMid - wMin;
408          dwdx = oneOverArea * (eMaj_dw * eBot.dy - eMaj.dy * eBot_dw);
409          dwdy = oneOverArea * (eMaj.dx * eBot_dw - eMaj_dw * eBot.dx);
410 
411          eMaj_ds = VB->TexCoord[vMax][0]*wMax - VB->TexCoord[vMin][0]*wMin;
412          eBot_ds = VB->TexCoord[vMid][0]*wMid - VB->TexCoord[vMin][0]*wMin;
413          dsdx = oneOverArea * (eMaj_ds * eBot.dy - eMaj.dy * eBot_ds);
414          dsdy = oneOverArea * (eMaj.dx * eBot_ds - eMaj_ds * eBot.dx);
415 
416          eMaj_dt = VB->TexCoord[vMax][1]*wMax - VB->TexCoord[vMin][1]*wMin;
417          eBot_dt = VB->TexCoord[vMid][1]*wMid - VB->TexCoord[vMin][1]*wMin;
418          dtdx = oneOverArea * (eMaj_dt * eBot.dy - eMaj.dy * eBot_dt);
419          dtdy = oneOverArea * (eMaj.dx * eBot_dt - eMaj_dt * eBot.dx);
420 #if INTERP_UV
421          eMaj_du = VB->TexCoord[vMax][2]*wMax - VB->TexCoord[vMin][2]*wMin;
422          eBot_du = VB->TexCoord[vMid][2]*wMid - VB->TexCoord[vMin][2]*wMin;
423          dudx = oneOverArea * (eMaj_du * eBot.dy - eMaj.dy * eBot_du);
424          dudy = oneOverArea * (eMaj.dx * eBot_du - eMaj_du * eBot.dx);
425 
426          /* Note: don't divide V component by W */
427          eMaj_dv = VB->TexCoord[vMax][3] - VB->TexCoord[vMin][3];
428          eBot_dv = VB->TexCoord[vMid][3] - VB->TexCoord[vMin][3];
429          dvdx = oneOverArea * (eMaj_dv * eBot.dy - eMaj.dy * eBot_dv);
430          dvdy = oneOverArea * (eMaj.dx * eBot_dv - eMaj_dv * eBot.dx);
431 #endif
432       }
433 #endif
434 
435       /*
436        * We always sample at pixel centers.  However, we avoid
437        * explicit half-pixel offsets in this code by incorporating
438        * the proper offset in each of x and y during the
439        * transformation to window coordinates.
440        *
441        * We also apply the usual rasterization rules to prevent
442        * cracks and overlaps.  A pixel is considered inside a
443        * subtriangle if it meets all of four conditions: it is on or
444        * to the right of the left edge, strictly to the left of the
445        * right edge, on or below the top edge, and strictly above
446        * the bottom edge.  (Some edges may be degenerate.)
447        *
448        * The following discussion assumes left-to-right scanning
449        * (that is, the major edge is on the left); the right-to-left
450        * case is a straightforward variation.
451        *
452        * We start by finding the half-integral y coordinate that is
453        * at or below the top of the triangle.  This gives us the
454        * first scan line that could possibly contain pixels that are
455        * inside the triangle.
456        *
457        * Next we creep down the major edge until we reach that y,
458        * and compute the corresponding x coordinate on the edge.
459        * Then we find the half-integral x that lies on or just
460        * inside the edge.  This is the first pixel that might lie in
461        * the interior of the triangle.  (We won't know for sure
462        * until we check the other edges.)
463        *
464        * As we rasterize the triangle, we'll step down the major
465        * edge.  For each step in y, we'll move an integer number
466        * of steps in x.  There are two possible x step sizes, which
467        * we'll call the ``inner'' step (guaranteed to land on the
468        * edge or inside it) and the ``outer'' step (guaranteed to
469        * land on the edge or outside it).  The inner and outer steps
470        * differ by one.  During rasterization we maintain an error
471        * term that indicates our distance from the true edge, and
472        * select either the inner step or the outer step, whichever
473        * gets us to the first pixel that falls inside the triangle.
474        *
475        * All parameters (z, red, etc.) as well as the buffer
476        * addresses for color and z have inner and outer step values,
477        * so that we can increment them appropriately.  This method
478        * eliminates the need to adjust parameters by creeping a
479        * sub-pixel amount into the triangle at each scanline.
480        */
481 
482       {
483          int subTriangle;
484          GLfixed fx, fxLeftEdge, fxRightEdge, fdxLeftEdge, fdxRightEdge;
485          GLfixed fdxOuter;
486          int idxOuter;
487          float dxOuter;
488          GLfixed fError, fdError;
489          float adjx, adjy;
490          GLfixed fy;
491          int iy;
492 #ifdef PIXEL_ADDRESS
493          PIXEL_TYPE *pRow;
494          int dPRowOuter, dPRowInner;  /* offset in bytes */
495 #endif
496 #if INTERP_Z
497          GLdepth *zRow;
498          int dZRowOuter, dZRowInner;  /* offset in bytes */
499          GLfixed fz, fdzOuter, fdzInner;
500 #endif
501 #if INTERP_RGB
502          GLfixed fr, fdrOuter, fdrInner;
503          GLfixed fg, fdgOuter, fdgInner;
504          GLfixed fb, fdbOuter, fdbInner;
505 #endif
506 #if INTERP_ALPHA
507          GLfixed fa, fdaOuter, fdaInner;
508 #endif
509 #if INTERP_INDEX
510          GLfixed fi, fdiOuter, fdiInner;
511 #endif
512 #if INTERP_ST
513          GLfixed fs, fdsOuter, fdsInner;
514          GLfixed ft, fdtOuter, fdtInner;
515 #endif
516 #if INTERP_STW
517          GLfloat sLeft, dsOuter, dsInner;
518          GLfloat tLeft, dtOuter, dtInner;
519          GLfloat wLeft, dwOuter, dwInner;
520 #endif
521 #if INTERP_UV
522          GLfloat uLeft, duOuter, duInner;
523          GLfloat vLeft, dvOuter, dvInner;
524 #endif
525 
526          for (subTriangle=0; subTriangle<=1; subTriangle++) {
527             EdgeT *eLeft, *eRight;
528             int setupLeft, setupRight;
529             int lines;
530 
531             if (subTriangle==0) {
532                /* bottom half */
533                if (ltor) {
534                   eLeft = &eMaj;
535                   eRight = &eBot;
536                   lines = eRight->lines;
537                   setupLeft = 1;
538                   setupRight = 1;
539                }
540                else {
541                   eLeft = &eBot;
542                   eRight = &eMaj;
543                   lines = eLeft->lines;
544                   setupLeft = 1;
545                   setupRight = 1;
546                }
547             }
548             else {
549                /* top half */
550                if (ltor) {
551                   eLeft = &eMaj;
552                   eRight = &eTop;
553                   lines = eRight->lines;
554                   setupLeft = 0;
555                   setupRight = 1;
556                }
557                else {
558                   eLeft = &eTop;
559                   eRight = &eMaj;
560                   lines = eLeft->lines;
561                   setupLeft = 1;
562                   setupRight = 0;
563                }
564                if (lines==0) return;
565             }
566 
567             if (setupLeft && eLeft->lines>0) {
568                GLint vLower;
569                GLfixed fsx = eLeft->fsx;
570                fx = FixedCeil(fsx);
571                fError = fx - fsx - FIXED_ONE;
572                fxLeftEdge = fsx - FIXED_EPSILON;
573                fdxLeftEdge = eLeft->fdxdy;
574                fdxOuter = FixedFloor(fdxLeftEdge - FIXED_EPSILON);
575                fdError = fdxOuter - fdxLeftEdge + FIXED_ONE;
576                idxOuter = FixedToInt(fdxOuter);
577                dxOuter = (float) idxOuter;
578 
579                fy = eLeft->fsy;
580                iy = FixedToInt(fy);
581 
582                adjx = (float)(fx - eLeft->fx0);  /* SCALED! */
583                adjy = eLeft->adjy;		 /* SCALED! */
584 
585                vLower = eLeft->v0;
586 
587 #ifdef PIXEL_ADDRESS
588                {
589                   pRow = PIXEL_ADDRESS( FixedToInt(fxLeftEdge), iy );
590                   dPRowOuter = -((int)BYTES_PER_ROW) + idxOuter * sizeof(PIXEL_TYPE);
591                   /* negative because Y=0 at bottom and increases upward */
592                }
593 #endif
594                /*
595                 * Now we need the set of parameter (z, color, etc.) values at
596                 * the point (fx, fy).  This gives us properly-sampled parameter
597                 * values that we can step from pixel to pixel.  Furthermore,
598                 * although we might have intermediate results that overflow
599                 * the normal parameter range when we step temporarily outside
600                 * the triangle, we shouldn't overflow or underflow for any
601                 * pixel that's actually inside the triangle.
602                 */
603 
604 #if INTERP_Z
605                {
606                   GLfloat z0;
607                   z0 = VB->Win[vLower][2] + ctx->PolygonZoffset;
608 
609                   /* interpolate depth values exactly */
610                   fz = (GLint) (z0 + dzdx*FixedToFloat(adjx) + dzdy*FixedToFloat(adjy));
611                   fdzOuter = (GLint) (dzdy + dxOuter * dzdx);
612                   zRow = Z_ADDRESS( ctx, FixedToInt(fxLeftEdge), iy );
613                   dZRowOuter = (ctx->Buffer->Width + idxOuter) * sizeof(GLdepth);
614                }
615 #endif
616 #if INTERP_RGB
617                fr = (GLfixed)(IntToFixed(VB->Color[vLower][0]) + drdx * adjx + drdy * adjy)
618                     + FIXED_HALF;
619                fdrOuter = SignedFloatToFixed(drdy + dxOuter * drdx);
620 
621                fg = (GLfixed)(IntToFixed(VB->Color[vLower][1]) + dgdx * adjx + dgdy * adjy)
622                     + FIXED_HALF;
623                fdgOuter = SignedFloatToFixed(dgdy + dxOuter * dgdx);
624 
625                fb = (GLfixed)(IntToFixed(VB->Color[vLower][2]) + dbdx * adjx + dbdy * adjy)
626                     + FIXED_HALF;
627                fdbOuter = SignedFloatToFixed(dbdy + dxOuter * dbdx);
628 #endif
629 #if INTERP_ALPHA
630                fa = (GLfixed)(IntToFixed(VB->Color[vLower][3]) + dadx * adjx + dady * adjy)
631                     + FIXED_HALF;
632                fdaOuter = SignedFloatToFixed(dady + dxOuter * dadx);
633 #endif
634 #if INTERP_INDEX
635                fi = (GLfixed)(VB->Index[vLower] * FIXED_SCALE + didx * adjx
636                               + didy * adjy) + FIXED_HALF;
637                fdiOuter = SignedFloatToFixed(didy + dxOuter * didx);
638 #endif
639 #if INTERP_ST
640                {
641                   GLfloat s0, t0;
642                   s0 = VB->TexCoord[vLower][0] * S_SCALE;
643                   fs = (GLfixed)(s0 * FIXED_SCALE + dsdx * adjx + dsdy * adjy) + FIXED_HALF;
644                   fdsOuter = SignedFloatToFixed(dsdy + dxOuter * dsdx);
645                   t0 = VB->TexCoord[vLower][1] * T_SCALE;
646                   ft = (GLfixed)(t0 * FIXED_SCALE + dtdx * adjx + dtdy * adjy) + FIXED_HALF;
647                   fdtOuter = SignedFloatToFixed(dtdy + dxOuter * dtdx);
648                }
649 #endif
650 #if INTERP_STW
651                {
652                   GLfloat w0 = 1.0F / VB->Clip[vLower][3];
653                   GLfloat s0, t0, u0, v0;
654                   wLeft = w0 + (dwdx * adjx + dwdy * adjy) * (1.0F/FIXED_SCALE);
655 		  dwOuter = dwdy + dxOuter * dwdx;
656                   s0 = VB->TexCoord[vLower][0] * w0;
657                   sLeft = s0 + (dsdx * adjx + dsdy * adjy) * (1.0F/FIXED_SCALE);
658                   dsOuter = dsdy + dxOuter * dsdx;
659                   t0 = VB->TexCoord[vLower][1] * w0;
660                   tLeft = t0 + (dtdx * adjx + dtdy * adjy) * (1.0F/FIXED_SCALE);
661                   dtOuter = dtdy + dxOuter * dtdx;
662 #if INTERP_UV
663                   u0 = VB->TexCoord[vLower][2] * w0;
664                   uLeft = u0 + (dudx * adjx + dudy * adjy) * (1.0F/FIXED_SCALE);
665                   duOuter = dudy + dxOuter * dudx;
666                   /* Note: don't divide V component by W */
667                   v0 = VB->TexCoord[vLower][3];
668                   vLeft = v0 + (dvdx * adjx + dvdy * adjy) * (1.0F/FIXED_SCALE);
669                   dvOuter = dvdy + dxOuter * dvdx;
670 #endif
671                }
672 #endif
673 
674             } /*if setupLeft*/
675 
676 
677             if (setupRight && eRight->lines>0) {
678                fxRightEdge = eRight->fsx - FIXED_EPSILON;
679                fdxRightEdge = eRight->fdxdy;
680             }
681 
682             if (lines==0) {
683                continue;
684             }
685 
686 
687             /* Rasterize setup */
688 #ifdef PIXEL_ADDRESS
689             dPRowInner = dPRowOuter + sizeof(PIXEL_TYPE);
690 #endif
691 #if INTERP_Z
692             dZRowInner = dZRowOuter + sizeof(GLdepth);
693             fdzInner = fdzOuter + fdzdx;
694 #endif
695 #if INTERP_RGB
696             fdrInner = fdrOuter + fdrdx;
697             fdgInner = fdgOuter + fdgdx;
698             fdbInner = fdbOuter + fdbdx;
699 #endif
700 #if INTERP_ALPHA
701             fdaInner = fdaOuter + fdadx;
702 #endif
703 #if INTERP_INDEX
704             fdiInner = fdiOuter + fdidx;
705 #endif
706 #if INTERP_ST
707             fdsInner = fdsOuter + fdsdx;
708             fdtInner = fdtOuter + fdtdx;
709 #endif
710 #if INTERP_STW
711 	    dwInner = dwOuter + dwdx;
712 	    dsInner = dsOuter + dsdx;
713 	    dtInner = dtOuter + dtdx;
714 #if INTERP_UV
715 	    duInner = duOuter + dudx;
716 	    dvInner = dvOuter + dvdx;
717 #endif
718 #endif
719 
720             while (lines>0) {
721                /* initialize the span interpolants to the leftmost value */
722                /* ff = fixed-pt fragment */
723 #if INTERP_Z
724                GLfixed ffz = fz;
725                /*GLdepth *zp = zRow;*/
726 #endif
727 #if INTERP_RGB
728                GLfixed ffr = fr,  ffg = fg,  ffb = fb;
729 #endif
730 #if INTERP_ALPHA
731                GLfixed ffa = fa;
732 #endif
733 #if INTERP_INDEX
734                GLfixed ffi = fi;
735 #endif
736 #if INTERP_ST
737                GLfixed ffs = fs,  fft = ft;
738 #endif
739 #if INTERP_STW
740                GLfloat ss = sLeft,  tt = tLeft,  ww = wLeft;
741 #endif
742 #if INTERP_UV
743                GLfloat uu = uLeft,  vv = vLeft;
744 #endif
745                GLint left = FixedToInt(fxLeftEdge);
746                GLint right = FixedToInt(fxRightEdge);
747 
748 #if INTERP_RGB
749                {
750                   /* need this to accomodate round-off errors */
751                   GLfixed ffrend = ffr+(right-left-1)*fdrdx;
752                   GLfixed ffgend = ffg+(right-left-1)*fdgdx;
753                   GLfixed ffbend = ffb+(right-left-1)*fdbdx;
754                   if (ffrend<0) ffr -= ffrend;
755                   if (ffgend<0) ffg -= ffgend;
756                   if (ffbend<0) ffb -= ffbend;
757                   if (ffr<0) ffr = 0;
758                   if (ffg<0) ffg = 0;
759                   if (ffb<0) ffb = 0;
760                }
761 #endif
762 #if INTERP_ALPHA
763                {
764                   GLfixed ffaend = ffa+(right-left-1)*fdadx;
765                   if (ffaend<0) ffa -= ffaend;
766                   if (ffa<0) ffa = 0;
767                }
768 #endif
769 #if INTERP_INDEX
770                if (ffi<0) ffi = 0;
771 #endif
772 
773                INNER_LOOP( left, right, iy );
774 
775                /*
776                 * Advance to the next scan line.  Compute the
777                 * new edge coordinates, and adjust the
778                 * pixel-center x coordinate so that it stays
779                 * on or inside the major edge.
780                 */
781                iy++;
782                lines--;
783 
784                fxLeftEdge += fdxLeftEdge;
785                fxRightEdge += fdxRightEdge;
786 
787 
788                fError += fdError;
789                if (fError >= 0) {
790                   fError -= FIXED_ONE;
791 #ifdef PIXEL_ADDRESS
792                   pRow = (PIXEL_TYPE*) ((GLubyte*)pRow + dPRowOuter);
793 #endif
794 #if INTERP_Z
795                   zRow = (GLdepth*) ((GLubyte*)zRow + dZRowOuter);
796                   fz += fdzOuter;
797 #endif
798 #if INTERP_RGB
799                   fr += fdrOuter;   fg += fdgOuter;   fb += fdbOuter;
800 #endif
801 #if INTERP_ALPHA
802                   fa += fdaOuter;
803 #endif
804 #if INTERP_INDEX
805                   fi += fdiOuter;
806 #endif
807 #if INTERP_ST
808                   fs += fdsOuter;   ft += fdtOuter;
809 #endif
810 #if INTERP_STW
811 		  sLeft += dsOuter;
812 		  tLeft += dtOuter;
813 		  wLeft += dwOuter;
814 #endif
815 #if INTERP_UV
816 		  uLeft += duOuter;
817 		  vLeft += dvOuter;
818 #endif
819                }
820                else {
821 #ifdef PIXEL_ADDRESS
822                   pRow = (PIXEL_TYPE*) ((GLubyte*)pRow + dPRowInner);
823 #endif
824 #if INTERP_Z
825                   zRow = (GLdepth*) ((GLubyte*)zRow + dZRowInner);
826                   fz += fdzInner;
827 #endif
828 #if INTERP_RGB
829                   fr += fdrInner;   fg += fdgInner;   fb += fdbInner;
830 #endif
831 #if INTERP_ALPHA
832                   fa += fdaInner;
833 #endif
834 #if INTERP_INDEX
835                   fi += fdiInner;
836 #endif
837 #if INTERP_ST
838                   fs += fdsInner;   ft += fdtInner;
839 #endif
840 #if INTERP_STW
841 		  sLeft += dsInner;
842 		  tLeft += dtInner;
843 		  wLeft += dwInner;
844 #endif
845 #if INTERP_UV
846 		  uLeft += duInner;
847 		  vLeft += dvInner;
848 #endif
849                }
850             } /*while lines>0*/
851 
852          } /* for subTriangle */
853 
854       }
855    }
856 }
857 
858 #undef SETUP_CODE
859 #undef INNER_LOOP
860 
861 #undef PIXEL_TYPE
862 #undef BYTES_PER_ROW
863 #undef PIXEL_ADDRESS
864 
865 #undef INTERP_Z
866 #undef INTERP_RGB
867 #undef INTERP_ALPHA
868 #undef INTERP_INDEX
869 #undef INTERP_ST
870 #undef INTERP_STW
871 #undef INTERP_UV
872 
873 #undef S_SCALE
874 #undef T_SCALE
875