1848b8605Smrg/*
2848b8605Smrg * Mesa 3-D graphics library
3848b8605Smrg *
4848b8605Smrg * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
5848b8605Smrg *
6848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a
7848b8605Smrg * copy of this software and associated documentation files (the "Software"),
8848b8605Smrg * to deal in the Software without restriction, including without limitation
9848b8605Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the
11848b8605Smrg * Software is furnished to do so, subject to the following conditions:
12848b8605Smrg *
13848b8605Smrg * The above copyright notice and this permission notice shall be included
14848b8605Smrg * in all copies or substantial portions of the Software.
15848b8605Smrg *
16848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19848b8605Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20848b8605Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21848b8605Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22848b8605Smrg * OTHER DEALINGS IN THE SOFTWARE.
23848b8605Smrg */
24848b8605Smrg
25848b8605Smrg/*
26848b8605Smrg * Triangle Rasterizer Template
27848b8605Smrg *
28848b8605Smrg * This file is #include'd to generate custom triangle rasterizers.
29848b8605Smrg *
30848b8605Smrg * The following macros may be defined to indicate what auxillary information
31848b8605Smrg * must be interpolated across the triangle:
32848b8605Smrg *    INTERP_Z        - if defined, interpolate integer Z values
33848b8605Smrg *    INTERP_RGB      - if defined, interpolate integer RGB values
34848b8605Smrg *    INTERP_ALPHA    - if defined, interpolate integer Alpha values
35848b8605Smrg *    INTERP_INT_TEX  - if defined, interpolate integer ST texcoords
36848b8605Smrg *                         (fast, simple 2-D texture mapping, without
37848b8605Smrg *                         perspective correction)
38848b8605Smrg *    INTERP_ATTRIBS  - if defined, interpolate arbitrary attribs (texcoords,
39848b8605Smrg *                         varying vars, etc)  This also causes W to be
40848b8605Smrg *                         computed for perspective correction).
41848b8605Smrg *
42848b8605Smrg * When one can directly address pixels in the color buffer the following
43848b8605Smrg * macros can be defined and used to compute pixel addresses during
44848b8605Smrg * rasterization (see pRow):
45848b8605Smrg *    PIXEL_TYPE          - the datatype of a pixel (GLubyte, GLushort, GLuint)
46848b8605Smrg *    BYTES_PER_ROW       - number of bytes per row in the color buffer
47848b8605Smrg *    PIXEL_ADDRESS(X,Y)  - returns the address of pixel at (X,Y) where
48848b8605Smrg *                          Y==0 at bottom of screen and increases upward.
49848b8605Smrg *
50848b8605Smrg * Similarly, for direct depth buffer access, this type is used for depth
51848b8605Smrg * buffer addressing (see zRow):
52848b8605Smrg *    DEPTH_TYPE          - either GLushort or GLuint
53848b8605Smrg *
54848b8605Smrg * Optionally, one may provide one-time setup code per triangle:
55848b8605Smrg *    SETUP_CODE    - code which is to be executed once per triangle
56848b8605Smrg *
57848b8605Smrg * The following macro MUST be defined:
58848b8605Smrg *    RENDER_SPAN(span) - code to write a span of pixels.
59848b8605Smrg *
60848b8605Smrg * This code was designed for the origin to be in the lower-left corner.
61848b8605Smrg *
62848b8605Smrg * Inspired by triangle rasterizer code written by Allen Akin.  Thanks Allen!
63848b8605Smrg *
64848b8605Smrg *
65848b8605Smrg * Some notes on rasterization accuracy:
66848b8605Smrg *
67848b8605Smrg * This code uses fixed point arithmetic (the GLfixed type) to iterate
68848b8605Smrg * over the triangle edges and interpolate ancillary data (such as Z,
69848b8605Smrg * color, secondary color, etc).  The number of fractional bits in
70848b8605Smrg * GLfixed and the value of SUB_PIXEL_BITS has a direct bearing on the
71848b8605Smrg * accuracy of rasterization.
72848b8605Smrg *
73848b8605Smrg * If SUB_PIXEL_BITS=4 then we'll snap the vertices to the nearest
74848b8605Smrg * 1/16 of a pixel.  If we're walking up a long, nearly vertical edge
75848b8605Smrg * (dx=1/16, dy=1024) we'll need 4 + 10 = 14 fractional bits in
76848b8605Smrg * GLfixed to walk the edge without error.  If the maximum viewport
77848b8605Smrg * height is 4K pixels, then we'll need 4 + 12 = 16 fractional bits.
78848b8605Smrg *
79848b8605Smrg * Historically, Mesa has used 11 fractional bits in GLfixed, snaps
80848b8605Smrg * vertices to 1/16 pixel and allowed a maximum viewport height of 2K
81848b8605Smrg * pixels.  11 fractional bits is actually insufficient for accurately
82848b8605Smrg * rasterizing some triangles.  More recently, the maximum viewport
83848b8605Smrg * height was increased to 4K pixels.  Thus, Mesa should be using 16
84848b8605Smrg * fractional bits in GLfixed.  Unfortunately, there may be some issues
85848b8605Smrg * with setting FIXED_FRAC_BITS=16, such as multiplication overflow.
86848b8605Smrg * This will have to be examined in some detail...
87848b8605Smrg *
88848b8605Smrg * For now, if you find rasterization errors, particularly with tall,
89848b8605Smrg * sliver triangles, try increasing FIXED_FRAC_BITS and/or decreasing
90848b8605Smrg * SUB_PIXEL_BITS.
91848b8605Smrg */
92848b8605Smrg
93848b8605Smrg
94b8e80941Smrg#ifndef MAX_GLUINT
95b8e80941Smrg#define MAX_GLUINT	0xffffffffu
96b8e80941Smrg#endif
97b8e80941Smrg
98b8e80941Smrg
99848b8605Smrg/*
100848b8605Smrg * Some code we unfortunately need to prevent negative interpolated colors.
101848b8605Smrg */
102848b8605Smrg#ifndef CLAMP_INTERPOLANT
103848b8605Smrg#define CLAMP_INTERPOLANT(CHANNEL, CHANNELSTEP, LEN)		\
104848b8605Smrgdo {								\
105848b8605Smrg   GLfixed endVal = span.CHANNEL + (LEN) * span.CHANNELSTEP;	\
106848b8605Smrg   if (endVal < 0) {						\
107848b8605Smrg      span.CHANNEL -= endVal;					\
108848b8605Smrg   }								\
109848b8605Smrg   if (span.CHANNEL < 0) {					\
110848b8605Smrg      span.CHANNEL = 0;						\
111848b8605Smrg   }								\
112848b8605Smrg} while (0)
113848b8605Smrg#endif
114848b8605Smrg
115848b8605Smrg
116848b8605Smrgstatic void NAME(struct gl_context *ctx, const SWvertex *v0,
117848b8605Smrg                                 const SWvertex *v1,
118848b8605Smrg                                 const SWvertex *v2 )
119848b8605Smrg{
120848b8605Smrg   typedef struct {
121848b8605Smrg      const SWvertex *v0, *v1;   /* Y(v0) < Y(v1) */
122848b8605Smrg      GLfloat dx;	/* X(v1) - X(v0) */
123848b8605Smrg      GLfloat dy;	/* Y(v1) - Y(v0) */
124848b8605Smrg      GLfloat dxdy;	/* dx/dy */
125848b8605Smrg      GLfixed fdxdy;	/* dx/dy in fixed-point */
126848b8605Smrg      GLfloat adjy;	/* adjust from v[0]->fy to fsy, scaled */
127848b8605Smrg      GLfixed fsx;	/* first sample point x coord */
128848b8605Smrg      GLfixed fsy;
129848b8605Smrg      GLfixed fx0;	/* fixed pt X of lower endpoint */
130848b8605Smrg      GLint lines;	/* number of lines to be sampled on this edge */
131848b8605Smrg   } EdgeT;
132848b8605Smrg
133848b8605Smrg   const SWcontext *swrast = SWRAST_CONTEXT(ctx);
134848b8605Smrg#ifdef INTERP_Z
135848b8605Smrg   const GLint depthBits = ctx->DrawBuffer->Visual.depthBits;
136848b8605Smrg   const GLint fixedToDepthShift = depthBits <= 16 ? FIXED_SHIFT : 0;
137848b8605Smrg   const GLfloat maxDepth = ctx->DrawBuffer->_DepthMaxF;
138848b8605Smrg#define FixedToDepth(F)  ((F) >> fixedToDepthShift)
139848b8605Smrg#endif
140848b8605Smrg   EdgeT eMaj, eTop, eBot;
141848b8605Smrg   GLfloat oneOverArea;
142848b8605Smrg   const SWvertex *vMin, *vMid, *vMax;  /* Y(vMin)<=Y(vMid)<=Y(vMax) */
143848b8605Smrg   GLfloat bf = SWRAST_CONTEXT(ctx)->_BackfaceSign;
144848b8605Smrg   const GLint snapMask = ~((FIXED_ONE / (1 << SUB_PIXEL_BITS)) - 1); /* for x/y coord snapping */
145848b8605Smrg   GLfixed vMin_fx, vMin_fy, vMid_fx, vMid_fy, vMax_fx, vMax_fy;
146848b8605Smrg
147848b8605Smrg   SWspan span;
148848b8605Smrg
149848b8605Smrg   (void) swrast;
150848b8605Smrg
151848b8605Smrg   INIT_SPAN(span, GL_POLYGON);
152848b8605Smrg   span.y = 0; /* silence warnings */
153848b8605Smrg
154848b8605Smrg#ifdef INTERP_Z
155848b8605Smrg   (void) fixedToDepthShift;
156848b8605Smrg#endif
157848b8605Smrg
158848b8605Smrg   /*
159b8e80941Smrg   printf("%s()\n", __func__);
160848b8605Smrg   printf("  %g, %g, %g\n",
161848b8605Smrg          v0->attrib[VARYING_SLOT_POS][0],
162848b8605Smrg          v0->attrib[VARYING_SLOT_POS][1],
163848b8605Smrg          v0->attrib[VARYING_SLOT_POS][2]);
164848b8605Smrg   printf("  %g, %g, %g\n",
165848b8605Smrg          v1->attrib[VARYING_SLOT_POS][0],
166848b8605Smrg          v1->attrib[VARYING_SLOT_POS][1],
167848b8605Smrg          v1->attrib[VARYING_SLOT_POS][2]);
168848b8605Smrg   printf("  %g, %g, %g\n",
169848b8605Smrg          v2->attrib[VARYING_SLOT_POS][0],
170848b8605Smrg          v2->attrib[VARYING_SLOT_POS][1],
171848b8605Smrg          v2->attrib[VARYING_SLOT_POS][2]);
172848b8605Smrg   */
173848b8605Smrg
174848b8605Smrg   /* Compute fixed point x,y coords w/ half-pixel offsets and snapping.
175848b8605Smrg    * And find the order of the 3 vertices along the Y axis.
176848b8605Smrg    */
177848b8605Smrg   {
178848b8605Smrg      const GLfixed fy0 = FloatToFixed(v0->attrib[VARYING_SLOT_POS][1] - 0.5F) & snapMask;
179848b8605Smrg      const GLfixed fy1 = FloatToFixed(v1->attrib[VARYING_SLOT_POS][1] - 0.5F) & snapMask;
180848b8605Smrg      const GLfixed fy2 = FloatToFixed(v2->attrib[VARYING_SLOT_POS][1] - 0.5F) & snapMask;
181848b8605Smrg      if (fy0 <= fy1) {
182848b8605Smrg         if (fy1 <= fy2) {
183848b8605Smrg            /* y0 <= y1 <= y2 */
184848b8605Smrg            vMin = v0;   vMid = v1;   vMax = v2;
185848b8605Smrg            vMin_fy = fy0;  vMid_fy = fy1;  vMax_fy = fy2;
186848b8605Smrg         }
187848b8605Smrg         else if (fy2 <= fy0) {
188848b8605Smrg            /* y2 <= y0 <= y1 */
189848b8605Smrg            vMin = v2;   vMid = v0;   vMax = v1;
190848b8605Smrg            vMin_fy = fy2;  vMid_fy = fy0;  vMax_fy = fy1;
191848b8605Smrg         }
192848b8605Smrg         else {
193848b8605Smrg            /* y0 <= y2 <= y1 */
194848b8605Smrg            vMin = v0;   vMid = v2;   vMax = v1;
195848b8605Smrg            vMin_fy = fy0;  vMid_fy = fy2;  vMax_fy = fy1;
196848b8605Smrg            bf = -bf;
197848b8605Smrg         }
198848b8605Smrg      }
199848b8605Smrg      else {
200848b8605Smrg         if (fy0 <= fy2) {
201848b8605Smrg            /* y1 <= y0 <= y2 */
202848b8605Smrg            vMin = v1;   vMid = v0;   vMax = v2;
203848b8605Smrg            vMin_fy = fy1;  vMid_fy = fy0;  vMax_fy = fy2;
204848b8605Smrg            bf = -bf;
205848b8605Smrg         }
206848b8605Smrg         else if (fy2 <= fy1) {
207848b8605Smrg            /* y2 <= y1 <= y0 */
208848b8605Smrg            vMin = v2;   vMid = v1;   vMax = v0;
209848b8605Smrg            vMin_fy = fy2;  vMid_fy = fy1;  vMax_fy = fy0;
210848b8605Smrg            bf = -bf;
211848b8605Smrg         }
212848b8605Smrg         else {
213848b8605Smrg            /* y1 <= y2 <= y0 */
214848b8605Smrg            vMin = v1;   vMid = v2;   vMax = v0;
215848b8605Smrg            vMin_fy = fy1;  vMid_fy = fy2;  vMax_fy = fy0;
216848b8605Smrg         }
217848b8605Smrg      }
218848b8605Smrg
219848b8605Smrg      /* fixed point X coords */
220848b8605Smrg      vMin_fx = FloatToFixed(vMin->attrib[VARYING_SLOT_POS][0] + 0.5F) & snapMask;
221848b8605Smrg      vMid_fx = FloatToFixed(vMid->attrib[VARYING_SLOT_POS][0] + 0.5F) & snapMask;
222848b8605Smrg      vMax_fx = FloatToFixed(vMax->attrib[VARYING_SLOT_POS][0] + 0.5F) & snapMask;
223848b8605Smrg   }
224848b8605Smrg
225848b8605Smrg   /* vertex/edge relationship */
226848b8605Smrg   eMaj.v0 = vMin;   eMaj.v1 = vMax;   /*TODO: .v1's not needed */
227848b8605Smrg   eTop.v0 = vMid;   eTop.v1 = vMax;
228848b8605Smrg   eBot.v0 = vMin;   eBot.v1 = vMid;
229848b8605Smrg
230848b8605Smrg   /* compute deltas for each edge:  vertex[upper] - vertex[lower] */
231848b8605Smrg   eMaj.dx = FixedToFloat(vMax_fx - vMin_fx);
232848b8605Smrg   eMaj.dy = FixedToFloat(vMax_fy - vMin_fy);
233848b8605Smrg   eTop.dx = FixedToFloat(vMax_fx - vMid_fx);
234848b8605Smrg   eTop.dy = FixedToFloat(vMax_fy - vMid_fy);
235848b8605Smrg   eBot.dx = FixedToFloat(vMid_fx - vMin_fx);
236848b8605Smrg   eBot.dy = FixedToFloat(vMid_fy - vMin_fy);
237848b8605Smrg
238848b8605Smrg   /* compute area, oneOverArea and perform backface culling */
239848b8605Smrg   {
240848b8605Smrg      const GLfloat area = eMaj.dx * eBot.dy - eBot.dx * eMaj.dy;
241848b8605Smrg
242848b8605Smrg      if (IS_INF_OR_NAN(area) || area == 0.0F)
243848b8605Smrg         return;
244848b8605Smrg
245b8e80941Smrg      if (area * bf * swrast->_BackfaceCullSign < 0.0F)
246848b8605Smrg         return;
247848b8605Smrg
248848b8605Smrg      oneOverArea = 1.0F / area;
249848b8605Smrg
250848b8605Smrg      /* 0 = front, 1 = back */
251848b8605Smrg      span.facing = oneOverArea * bf > 0.0F;
252848b8605Smrg   }
253848b8605Smrg
254848b8605Smrg   /* Edge setup.  For a triangle strip these could be reused... */
255848b8605Smrg   {
256848b8605Smrg      eMaj.fsy = FixedCeil(vMin_fy);
257848b8605Smrg      eMaj.lines = FixedToInt(FixedCeil(vMax_fy - eMaj.fsy));
258848b8605Smrg      if (eMaj.lines > 0) {
259848b8605Smrg         eMaj.dxdy = eMaj.dx / eMaj.dy;
260848b8605Smrg         eMaj.fdxdy = SignedFloatToFixed(eMaj.dxdy);
261848b8605Smrg         eMaj.adjy = (GLfloat) (eMaj.fsy - vMin_fy);  /* SCALED! */
262848b8605Smrg         eMaj.fx0 = vMin_fx;
263848b8605Smrg         eMaj.fsx = eMaj.fx0 + (GLfixed) (eMaj.adjy * eMaj.dxdy);
264848b8605Smrg      }
265848b8605Smrg      else {
266848b8605Smrg         return;  /*CULLED*/
267848b8605Smrg      }
268848b8605Smrg
269848b8605Smrg      eTop.fsy = FixedCeil(vMid_fy);
270848b8605Smrg      eTop.lines = FixedToInt(FixedCeil(vMax_fy - eTop.fsy));
271848b8605Smrg      if (eTop.lines > 0) {
272848b8605Smrg         eTop.dxdy = eTop.dx / eTop.dy;
273848b8605Smrg         eTop.fdxdy = SignedFloatToFixed(eTop.dxdy);
274848b8605Smrg         eTop.adjy = (GLfloat) (eTop.fsy - vMid_fy); /* SCALED! */
275848b8605Smrg         eTop.fx0 = vMid_fx;
276848b8605Smrg         eTop.fsx = eTop.fx0 + (GLfixed) (eTop.adjy * eTop.dxdy);
277848b8605Smrg      }
278848b8605Smrg
279848b8605Smrg      eBot.fsy = FixedCeil(vMin_fy);
280848b8605Smrg      eBot.lines = FixedToInt(FixedCeil(vMid_fy - eBot.fsy));
281848b8605Smrg      if (eBot.lines > 0) {
282848b8605Smrg         eBot.dxdy = eBot.dx / eBot.dy;
283848b8605Smrg         eBot.fdxdy = SignedFloatToFixed(eBot.dxdy);
284848b8605Smrg         eBot.adjy = (GLfloat) (eBot.fsy - vMin_fy);  /* SCALED! */
285848b8605Smrg         eBot.fx0 = vMin_fx;
286848b8605Smrg         eBot.fsx = eBot.fx0 + (GLfixed) (eBot.adjy * eBot.dxdy);
287848b8605Smrg      }
288848b8605Smrg   }
289848b8605Smrg
290848b8605Smrg   /*
291848b8605Smrg    * Conceptually, we view a triangle as two subtriangles
292848b8605Smrg    * separated by a perfectly horizontal line.  The edge that is
293848b8605Smrg    * intersected by this line is one with maximal absolute dy; we
294848b8605Smrg    * call it a ``major'' edge.  The other two edges are the
295848b8605Smrg    * ``top'' edge (for the upper subtriangle) and the ``bottom''
296848b8605Smrg    * edge (for the lower subtriangle).  If either of these two
297848b8605Smrg    * edges is horizontal or very close to horizontal, the
298848b8605Smrg    * corresponding subtriangle might cover zero sample points;
299848b8605Smrg    * we take care to handle such cases, for performance as well
300848b8605Smrg    * as correctness.
301848b8605Smrg    *
302848b8605Smrg    * By stepping rasterization parameters along the major edge,
303848b8605Smrg    * we can avoid recomputing them at the discontinuity where
304848b8605Smrg    * the top and bottom edges meet.  However, this forces us to
305848b8605Smrg    * be able to scan both left-to-right and right-to-left.
306848b8605Smrg    * Also, we must determine whether the major edge is at the
307848b8605Smrg    * left or right side of the triangle.  We do this by
308848b8605Smrg    * computing the magnitude of the cross-product of the major
309848b8605Smrg    * and top edges.  Since this magnitude depends on the sine of
310848b8605Smrg    * the angle between the two edges, its sign tells us whether
311848b8605Smrg    * we turn to the left or to the right when travelling along
312848b8605Smrg    * the major edge to the top edge, and from this we infer
313848b8605Smrg    * whether the major edge is on the left or the right.
314848b8605Smrg    *
315848b8605Smrg    * Serendipitously, this cross-product magnitude is also a
316848b8605Smrg    * value we need to compute the iteration parameter
317848b8605Smrg    * derivatives for the triangle, and it can be used to perform
318848b8605Smrg    * backface culling because its sign tells us whether the
319848b8605Smrg    * triangle is clockwise or counterclockwise.  In this code we
320848b8605Smrg    * refer to it as ``area'' because it's also proportional to
321848b8605Smrg    * the pixel area of the triangle.
322848b8605Smrg    */
323848b8605Smrg
324848b8605Smrg   {
325848b8605Smrg      GLint scan_from_left_to_right;  /* true if scanning left-to-right */
326848b8605Smrg
327848b8605Smrg      /*
328848b8605Smrg       * Execute user-supplied setup code
329848b8605Smrg       */
330848b8605Smrg#ifdef SETUP_CODE
331848b8605Smrg      SETUP_CODE
332848b8605Smrg#endif
333848b8605Smrg
334848b8605Smrg      scan_from_left_to_right = (oneOverArea < 0.0F);
335848b8605Smrg
336848b8605Smrg
337848b8605Smrg      /* compute d?/dx and d?/dy derivatives */
338848b8605Smrg#ifdef INTERP_Z
339848b8605Smrg      span.interpMask |= SPAN_Z;
340848b8605Smrg      {
341848b8605Smrg         GLfloat eMaj_dz = vMax->attrib[VARYING_SLOT_POS][2] - vMin->attrib[VARYING_SLOT_POS][2];
342848b8605Smrg         GLfloat eBot_dz = vMid->attrib[VARYING_SLOT_POS][2] - vMin->attrib[VARYING_SLOT_POS][2];
343848b8605Smrg         span.attrStepX[VARYING_SLOT_POS][2] = oneOverArea * (eMaj_dz * eBot.dy - eMaj.dy * eBot_dz);
344848b8605Smrg         if (span.attrStepX[VARYING_SLOT_POS][2] > maxDepth ||
345848b8605Smrg             span.attrStepX[VARYING_SLOT_POS][2] < -maxDepth) {
346848b8605Smrg            /* probably a sliver triangle */
347848b8605Smrg            span.attrStepX[VARYING_SLOT_POS][2] = 0.0;
348848b8605Smrg            span.attrStepY[VARYING_SLOT_POS][2] = 0.0;
349848b8605Smrg         }
350848b8605Smrg         else {
351848b8605Smrg            span.attrStepY[VARYING_SLOT_POS][2] = oneOverArea * (eMaj.dx * eBot_dz - eMaj_dz * eBot.dx);
352848b8605Smrg         }
353848b8605Smrg         if (depthBits <= 16)
354848b8605Smrg            span.zStep = SignedFloatToFixed(span.attrStepX[VARYING_SLOT_POS][2]);
355848b8605Smrg         else
356848b8605Smrg            span.zStep = (GLint) span.attrStepX[VARYING_SLOT_POS][2];
357848b8605Smrg      }
358848b8605Smrg#endif
359848b8605Smrg#ifdef INTERP_RGB
360848b8605Smrg      span.interpMask |= SPAN_RGBA;
361848b8605Smrg      if (ctx->Light.ShadeModel == GL_SMOOTH) {
362848b8605Smrg         GLfloat eMaj_dr = (GLfloat) (vMax->color[RCOMP] - vMin->color[RCOMP]);
363848b8605Smrg         GLfloat eBot_dr = (GLfloat) (vMid->color[RCOMP] - vMin->color[RCOMP]);
364848b8605Smrg         GLfloat eMaj_dg = (GLfloat) (vMax->color[GCOMP] - vMin->color[GCOMP]);
365848b8605Smrg         GLfloat eBot_dg = (GLfloat) (vMid->color[GCOMP] - vMin->color[GCOMP]);
366848b8605Smrg         GLfloat eMaj_db = (GLfloat) (vMax->color[BCOMP] - vMin->color[BCOMP]);
367848b8605Smrg         GLfloat eBot_db = (GLfloat) (vMid->color[BCOMP] - vMin->color[BCOMP]);
368848b8605Smrg#  ifdef INTERP_ALPHA
369848b8605Smrg         GLfloat eMaj_da = (GLfloat) (vMax->color[ACOMP] - vMin->color[ACOMP]);
370848b8605Smrg         GLfloat eBot_da = (GLfloat) (vMid->color[ACOMP] - vMin->color[ACOMP]);
371848b8605Smrg#  endif
372848b8605Smrg         span.attrStepX[VARYING_SLOT_COL0][0] = oneOverArea * (eMaj_dr * eBot.dy - eMaj.dy * eBot_dr);
373848b8605Smrg         span.attrStepY[VARYING_SLOT_COL0][0] = oneOverArea * (eMaj.dx * eBot_dr - eMaj_dr * eBot.dx);
374848b8605Smrg         span.attrStepX[VARYING_SLOT_COL0][1] = oneOverArea * (eMaj_dg * eBot.dy - eMaj.dy * eBot_dg);
375848b8605Smrg         span.attrStepY[VARYING_SLOT_COL0][1] = oneOverArea * (eMaj.dx * eBot_dg - eMaj_dg * eBot.dx);
376848b8605Smrg         span.attrStepX[VARYING_SLOT_COL0][2] = oneOverArea * (eMaj_db * eBot.dy - eMaj.dy * eBot_db);
377848b8605Smrg         span.attrStepY[VARYING_SLOT_COL0][2] = oneOverArea * (eMaj.dx * eBot_db - eMaj_db * eBot.dx);
378848b8605Smrg         span.redStep   = SignedFloatToFixed(span.attrStepX[VARYING_SLOT_COL0][0]);
379848b8605Smrg         span.greenStep = SignedFloatToFixed(span.attrStepX[VARYING_SLOT_COL0][1]);
380848b8605Smrg         span.blueStep  = SignedFloatToFixed(span.attrStepX[VARYING_SLOT_COL0][2]);
381848b8605Smrg#  ifdef INTERP_ALPHA
382848b8605Smrg         span.attrStepX[VARYING_SLOT_COL0][3] = oneOverArea * (eMaj_da * eBot.dy - eMaj.dy * eBot_da);
383848b8605Smrg         span.attrStepY[VARYING_SLOT_COL0][3] = oneOverArea * (eMaj.dx * eBot_da - eMaj_da * eBot.dx);
384848b8605Smrg         span.alphaStep = SignedFloatToFixed(span.attrStepX[VARYING_SLOT_COL0][3]);
385848b8605Smrg#  endif /* INTERP_ALPHA */
386848b8605Smrg      }
387848b8605Smrg      else {
388b8e80941Smrg         assert(ctx->Light.ShadeModel == GL_FLAT);
389848b8605Smrg         span.interpMask |= SPAN_FLAT;
390848b8605Smrg         span.attrStepX[VARYING_SLOT_COL0][0] = span.attrStepY[VARYING_SLOT_COL0][0] = 0.0F;
391848b8605Smrg         span.attrStepX[VARYING_SLOT_COL0][1] = span.attrStepY[VARYING_SLOT_COL0][1] = 0.0F;
392848b8605Smrg         span.attrStepX[VARYING_SLOT_COL0][2] = span.attrStepY[VARYING_SLOT_COL0][2] = 0.0F;
393848b8605Smrg	 span.redStep   = 0;
394848b8605Smrg	 span.greenStep = 0;
395848b8605Smrg	 span.blueStep  = 0;
396848b8605Smrg#  ifdef INTERP_ALPHA
397848b8605Smrg         span.attrStepX[VARYING_SLOT_COL0][3] = span.attrStepY[VARYING_SLOT_COL0][3] = 0.0F;
398848b8605Smrg	 span.alphaStep = 0;
399848b8605Smrg#  endif
400848b8605Smrg      }
401848b8605Smrg#endif /* INTERP_RGB */
402848b8605Smrg#ifdef INTERP_INT_TEX
403848b8605Smrg      {
404848b8605Smrg         GLfloat eMaj_ds = (vMax->attrib[VARYING_SLOT_TEX0][0] - vMin->attrib[VARYING_SLOT_TEX0][0]) * S_SCALE;
405848b8605Smrg         GLfloat eBot_ds = (vMid->attrib[VARYING_SLOT_TEX0][0] - vMin->attrib[VARYING_SLOT_TEX0][0]) * S_SCALE;
406848b8605Smrg         GLfloat eMaj_dt = (vMax->attrib[VARYING_SLOT_TEX0][1] - vMin->attrib[VARYING_SLOT_TEX0][1]) * T_SCALE;
407848b8605Smrg         GLfloat eBot_dt = (vMid->attrib[VARYING_SLOT_TEX0][1] - vMin->attrib[VARYING_SLOT_TEX0][1]) * T_SCALE;
408848b8605Smrg         span.attrStepX[VARYING_SLOT_TEX0][0] = oneOverArea * (eMaj_ds * eBot.dy - eMaj.dy * eBot_ds);
409848b8605Smrg         span.attrStepY[VARYING_SLOT_TEX0][0] = oneOverArea * (eMaj.dx * eBot_ds - eMaj_ds * eBot.dx);
410848b8605Smrg         span.attrStepX[VARYING_SLOT_TEX0][1] = oneOverArea * (eMaj_dt * eBot.dy - eMaj.dy * eBot_dt);
411848b8605Smrg         span.attrStepY[VARYING_SLOT_TEX0][1] = oneOverArea * (eMaj.dx * eBot_dt - eMaj_dt * eBot.dx);
412848b8605Smrg         span.intTexStep[0] = SignedFloatToFixed(span.attrStepX[VARYING_SLOT_TEX0][0]);
413848b8605Smrg         span.intTexStep[1] = SignedFloatToFixed(span.attrStepX[VARYING_SLOT_TEX0][1]);
414848b8605Smrg      }
415848b8605Smrg#endif
416848b8605Smrg#ifdef INTERP_ATTRIBS
417848b8605Smrg      {
418848b8605Smrg         /* attrib[VARYING_SLOT_POS][3] is 1/W */
419848b8605Smrg         const GLfloat wMax = vMax->attrib[VARYING_SLOT_POS][3];
420848b8605Smrg         const GLfloat wMin = vMin->attrib[VARYING_SLOT_POS][3];
421848b8605Smrg         const GLfloat wMid = vMid->attrib[VARYING_SLOT_POS][3];
422848b8605Smrg         {
423848b8605Smrg            const GLfloat eMaj_dw = wMax - wMin;
424848b8605Smrg            const GLfloat eBot_dw = wMid - wMin;
425848b8605Smrg            span.attrStepX[VARYING_SLOT_POS][3] = oneOverArea * (eMaj_dw * eBot.dy - eMaj.dy * eBot_dw);
426848b8605Smrg            span.attrStepY[VARYING_SLOT_POS][3] = oneOverArea * (eMaj.dx * eBot_dw - eMaj_dw * eBot.dx);
427848b8605Smrg         }
428848b8605Smrg         ATTRIB_LOOP_BEGIN
429848b8605Smrg            if (swrast->_InterpMode[attr] == GL_FLAT) {
430848b8605Smrg               ASSIGN_4V(span.attrStepX[attr], 0.0, 0.0, 0.0, 0.0);
431848b8605Smrg               ASSIGN_4V(span.attrStepY[attr], 0.0, 0.0, 0.0, 0.0);
432848b8605Smrg            }
433848b8605Smrg            else {
434848b8605Smrg               GLuint c;
435848b8605Smrg               for (c = 0; c < 4; c++) {
436848b8605Smrg                  GLfloat eMaj_da = vMax->attrib[attr][c] * wMax - vMin->attrib[attr][c] * wMin;
437848b8605Smrg                  GLfloat eBot_da = vMid->attrib[attr][c] * wMid - vMin->attrib[attr][c] * wMin;
438848b8605Smrg                  span.attrStepX[attr][c] = oneOverArea * (eMaj_da * eBot.dy - eMaj.dy * eBot_da);
439848b8605Smrg                  span.attrStepY[attr][c] = oneOverArea * (eMaj.dx * eBot_da - eMaj_da * eBot.dx);
440848b8605Smrg               }
441848b8605Smrg            }
442848b8605Smrg         ATTRIB_LOOP_END
443848b8605Smrg      }
444848b8605Smrg#endif
445848b8605Smrg
446848b8605Smrg      /*
447848b8605Smrg       * We always sample at pixel centers.  However, we avoid
448848b8605Smrg       * explicit half-pixel offsets in this code by incorporating
449848b8605Smrg       * the proper offset in each of x and y during the
450848b8605Smrg       * transformation to window coordinates.
451848b8605Smrg       *
452848b8605Smrg       * We also apply the usual rasterization rules to prevent
453848b8605Smrg       * cracks and overlaps.  A pixel is considered inside a
454848b8605Smrg       * subtriangle if it meets all of four conditions: it is on or
455848b8605Smrg       * to the right of the left edge, strictly to the left of the
456848b8605Smrg       * right edge, on or below the top edge, and strictly above
457848b8605Smrg       * the bottom edge.  (Some edges may be degenerate.)
458848b8605Smrg       *
459848b8605Smrg       * The following discussion assumes left-to-right scanning
460848b8605Smrg       * (that is, the major edge is on the left); the right-to-left
461848b8605Smrg       * case is a straightforward variation.
462848b8605Smrg       *
463848b8605Smrg       * We start by finding the half-integral y coordinate that is
464848b8605Smrg       * at or below the top of the triangle.  This gives us the
465848b8605Smrg       * first scan line that could possibly contain pixels that are
466848b8605Smrg       * inside the triangle.
467848b8605Smrg       *
468848b8605Smrg       * Next we creep down the major edge until we reach that y,
469848b8605Smrg       * and compute the corresponding x coordinate on the edge.
470848b8605Smrg       * Then we find the half-integral x that lies on or just
471848b8605Smrg       * inside the edge.  This is the first pixel that might lie in
472848b8605Smrg       * the interior of the triangle.  (We won't know for sure
473848b8605Smrg       * until we check the other edges.)
474848b8605Smrg       *
475848b8605Smrg       * As we rasterize the triangle, we'll step down the major
476848b8605Smrg       * edge.  For each step in y, we'll move an integer number
477848b8605Smrg       * of steps in x.  There are two possible x step sizes, which
478848b8605Smrg       * we'll call the ``inner'' step (guaranteed to land on the
479848b8605Smrg       * edge or inside it) and the ``outer'' step (guaranteed to
480848b8605Smrg       * land on the edge or outside it).  The inner and outer steps
481848b8605Smrg       * differ by one.  During rasterization we maintain an error
482848b8605Smrg       * term that indicates our distance from the true edge, and
483848b8605Smrg       * select either the inner step or the outer step, whichever
484848b8605Smrg       * gets us to the first pixel that falls inside the triangle.
485848b8605Smrg       *
486848b8605Smrg       * All parameters (z, red, etc.) as well as the buffer
487848b8605Smrg       * addresses for color and z have inner and outer step values,
488848b8605Smrg       * so that we can increment them appropriately.  This method
489848b8605Smrg       * eliminates the need to adjust parameters by creeping a
490848b8605Smrg       * sub-pixel amount into the triangle at each scanline.
491848b8605Smrg       */
492848b8605Smrg
493848b8605Smrg      {
494848b8605Smrg         GLint subTriangle;
495848b8605Smrg         GLfixed fxLeftEdge = 0, fxRightEdge = 0;
496848b8605Smrg         GLfixed fdxLeftEdge = 0, fdxRightEdge = 0;
497848b8605Smrg         GLfixed fError = 0, fdError = 0;
498848b8605Smrg#ifdef PIXEL_ADDRESS
499848b8605Smrg         PIXEL_TYPE *pRow = NULL;
500848b8605Smrg         GLint dPRowOuter = 0, dPRowInner;  /* offset in bytes */
501848b8605Smrg#endif
502848b8605Smrg#ifdef INTERP_Z
503848b8605Smrg#  ifdef DEPTH_TYPE
504848b8605Smrg         struct gl_renderbuffer *zrb
505848b8605Smrg            = ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
506848b8605Smrg         DEPTH_TYPE *zRow = NULL;
507848b8605Smrg         GLint dZRowOuter = 0, dZRowInner;  /* offset in bytes */
508848b8605Smrg#  endif
509848b8605Smrg         GLuint zLeft = 0;
510848b8605Smrg         GLfixed fdzOuter = 0, fdzInner;
511848b8605Smrg#endif
512848b8605Smrg#ifdef INTERP_RGB
513848b8605Smrg         GLint rLeft = 0, fdrOuter = 0, fdrInner;
514848b8605Smrg         GLint gLeft = 0, fdgOuter = 0, fdgInner;
515848b8605Smrg         GLint bLeft = 0, fdbOuter = 0, fdbInner;
516848b8605Smrg#endif
517848b8605Smrg#ifdef INTERP_ALPHA
518848b8605Smrg         GLint aLeft = 0, fdaOuter = 0, fdaInner;
519848b8605Smrg#endif
520848b8605Smrg#ifdef INTERP_INT_TEX
521848b8605Smrg         GLfixed sLeft=0, dsOuter=0, dsInner;
522848b8605Smrg         GLfixed tLeft=0, dtOuter=0, dtInner;
523848b8605Smrg#endif
524848b8605Smrg#ifdef INTERP_ATTRIBS
525848b8605Smrg         GLfloat wLeft = 0, dwOuter = 0, dwInner;
526848b8605Smrg         GLfloat attrLeft[VARYING_SLOT_MAX][4];
527848b8605Smrg         GLfloat daOuter[VARYING_SLOT_MAX][4], daInner[VARYING_SLOT_MAX][4];
528848b8605Smrg#endif
529848b8605Smrg
530848b8605Smrg         for (subTriangle=0; subTriangle<=1; subTriangle++) {
531848b8605Smrg            EdgeT *eLeft, *eRight;
532848b8605Smrg            int setupLeft, setupRight;
533848b8605Smrg            int lines;
534848b8605Smrg
535848b8605Smrg            if (subTriangle==0) {
536848b8605Smrg               /* bottom half */
537848b8605Smrg               if (scan_from_left_to_right) {
538848b8605Smrg                  eLeft = &eMaj;
539848b8605Smrg                  eRight = &eBot;
540848b8605Smrg                  lines = eRight->lines;
541848b8605Smrg                  setupLeft = 1;
542848b8605Smrg                  setupRight = 1;
543848b8605Smrg               }
544848b8605Smrg               else {
545848b8605Smrg                  eLeft = &eBot;
546848b8605Smrg                  eRight = &eMaj;
547848b8605Smrg                  lines = eLeft->lines;
548848b8605Smrg                  setupLeft = 1;
549848b8605Smrg                  setupRight = 1;
550848b8605Smrg               }
551848b8605Smrg            }
552848b8605Smrg            else {
553848b8605Smrg               /* top half */
554848b8605Smrg               if (scan_from_left_to_right) {
555848b8605Smrg                  eLeft = &eMaj;
556848b8605Smrg                  eRight = &eTop;
557848b8605Smrg                  lines = eRight->lines;
558848b8605Smrg                  setupLeft = 0;
559848b8605Smrg                  setupRight = 1;
560848b8605Smrg               }
561848b8605Smrg               else {
562848b8605Smrg                  eLeft = &eTop;
563848b8605Smrg                  eRight = &eMaj;
564848b8605Smrg                  lines = eLeft->lines;
565848b8605Smrg                  setupLeft = 1;
566848b8605Smrg                  setupRight = 0;
567848b8605Smrg               }
568848b8605Smrg               if (lines == 0)
569848b8605Smrg                  return;
570848b8605Smrg            }
571848b8605Smrg
572848b8605Smrg            if (setupLeft && eLeft->lines > 0) {
573848b8605Smrg               const SWvertex *vLower = eLeft->v0;
574848b8605Smrg               const GLfixed fsy = eLeft->fsy;
575848b8605Smrg               const GLfixed fsx = eLeft->fsx;  /* no fractional part */
576848b8605Smrg               const GLfixed fx = FixedCeil(fsx);  /* no fractional part */
577848b8605Smrg               const GLfixed adjx = (GLfixed) (fx - eLeft->fx0); /* SCALED! */
578848b8605Smrg               const GLfixed adjy = (GLfixed) eLeft->adjy;      /* SCALED! */
579848b8605Smrg               GLint idxOuter;
580848b8605Smrg               GLfloat dxOuter;
581848b8605Smrg               GLfixed fdxOuter;
582848b8605Smrg
583848b8605Smrg               fError = fx - fsx - FIXED_ONE;
584848b8605Smrg               fxLeftEdge = fsx - FIXED_EPSILON;
585848b8605Smrg               fdxLeftEdge = eLeft->fdxdy;
586848b8605Smrg               fdxOuter = FixedFloor(fdxLeftEdge - FIXED_EPSILON);
587848b8605Smrg               fdError = fdxOuter - fdxLeftEdge + FIXED_ONE;
588848b8605Smrg               idxOuter = FixedToInt(fdxOuter);
589848b8605Smrg               dxOuter = (GLfloat) idxOuter;
590848b8605Smrg               span.y = FixedToInt(fsy);
591848b8605Smrg
592848b8605Smrg               /* silence warnings on some compilers */
593848b8605Smrg               (void) dxOuter;
594848b8605Smrg               (void) adjx;
595848b8605Smrg               (void) adjy;
596848b8605Smrg               (void) vLower;
597848b8605Smrg
598848b8605Smrg#ifdef PIXEL_ADDRESS
599848b8605Smrg               {
600848b8605Smrg                  pRow = (PIXEL_TYPE *) PIXEL_ADDRESS(FixedToInt(fxLeftEdge), span.y);
601848b8605Smrg                  dPRowOuter = -((int)BYTES_PER_ROW) + idxOuter * sizeof(PIXEL_TYPE);
602848b8605Smrg                  /* negative because Y=0 at bottom and increases upward */
603848b8605Smrg               }
604848b8605Smrg#endif
605848b8605Smrg               /*
606848b8605Smrg                * Now we need the set of parameter (z, color, etc.) values at
607848b8605Smrg                * the point (fx, fsy).  This gives us properly-sampled parameter
608848b8605Smrg                * values that we can step from pixel to pixel.  Furthermore,
609848b8605Smrg                * although we might have intermediate results that overflow
610848b8605Smrg                * the normal parameter range when we step temporarily outside
611848b8605Smrg                * the triangle, we shouldn't overflow or underflow for any
612848b8605Smrg                * pixel that's actually inside the triangle.
613848b8605Smrg                */
614848b8605Smrg
615848b8605Smrg#ifdef INTERP_Z
616848b8605Smrg               {
617848b8605Smrg                  GLfloat z0 = vLower->attrib[VARYING_SLOT_POS][2];
618848b8605Smrg                  if (depthBits <= 16) {
619848b8605Smrg                     /* interpolate fixed-pt values */
620848b8605Smrg                     GLfloat tmp = (z0 * FIXED_SCALE
621848b8605Smrg                                    + span.attrStepX[VARYING_SLOT_POS][2] * adjx
622848b8605Smrg                                    + span.attrStepY[VARYING_SLOT_POS][2] * adjy) + FIXED_HALF;
623848b8605Smrg                     if (tmp < MAX_GLUINT / 2)
624848b8605Smrg                        zLeft = (GLfixed) tmp;
625848b8605Smrg                     else
626848b8605Smrg                        zLeft = MAX_GLUINT / 2;
627848b8605Smrg                     fdzOuter = SignedFloatToFixed(span.attrStepY[VARYING_SLOT_POS][2] +
628848b8605Smrg                                                   dxOuter * span.attrStepX[VARYING_SLOT_POS][2]);
629848b8605Smrg                  }
630848b8605Smrg                  else {
631848b8605Smrg                     /* interpolate depth values w/out scaling */
632848b8605Smrg                     zLeft = (GLuint) (z0 + span.attrStepX[VARYING_SLOT_POS][2] * FixedToFloat(adjx)
633848b8605Smrg                                          + span.attrStepY[VARYING_SLOT_POS][2] * FixedToFloat(adjy));
634848b8605Smrg                     fdzOuter = (GLint) (span.attrStepY[VARYING_SLOT_POS][2] +
635848b8605Smrg                                         dxOuter * span.attrStepX[VARYING_SLOT_POS][2]);
636848b8605Smrg                  }
637848b8605Smrg#  ifdef DEPTH_TYPE
638848b8605Smrg                  zRow = (DEPTH_TYPE *)
639848b8605Smrg                    _swrast_pixel_address(zrb, FixedToInt(fxLeftEdge), span.y);
640848b8605Smrg                  dZRowOuter = (ctx->DrawBuffer->Width + idxOuter) * sizeof(DEPTH_TYPE);
641848b8605Smrg#  endif
642848b8605Smrg               }
643848b8605Smrg#endif
644848b8605Smrg#ifdef INTERP_RGB
645848b8605Smrg               if (ctx->Light.ShadeModel == GL_SMOOTH) {
646848b8605Smrg                  rLeft = (GLint)(ChanToFixed(vLower->color[RCOMP])
647848b8605Smrg                                  + span.attrStepX[VARYING_SLOT_COL0][0] * adjx
648848b8605Smrg                                  + span.attrStepY[VARYING_SLOT_COL0][0] * adjy) + FIXED_HALF;
649848b8605Smrg                  gLeft = (GLint)(ChanToFixed(vLower->color[GCOMP])
650848b8605Smrg                                  + span.attrStepX[VARYING_SLOT_COL0][1] * adjx
651848b8605Smrg                                  + span.attrStepY[VARYING_SLOT_COL0][1] * adjy) + FIXED_HALF;
652848b8605Smrg                  bLeft = (GLint)(ChanToFixed(vLower->color[BCOMP])
653848b8605Smrg                                  + span.attrStepX[VARYING_SLOT_COL0][2] * adjx
654848b8605Smrg                                  + span.attrStepY[VARYING_SLOT_COL0][2] * adjy) + FIXED_HALF;
655848b8605Smrg                  fdrOuter = SignedFloatToFixed(span.attrStepY[VARYING_SLOT_COL0][0]
656848b8605Smrg                                                + dxOuter * span.attrStepX[VARYING_SLOT_COL0][0]);
657848b8605Smrg                  fdgOuter = SignedFloatToFixed(span.attrStepY[VARYING_SLOT_COL0][1]
658848b8605Smrg                                                + dxOuter * span.attrStepX[VARYING_SLOT_COL0][1]);
659848b8605Smrg                  fdbOuter = SignedFloatToFixed(span.attrStepY[VARYING_SLOT_COL0][2]
660848b8605Smrg                                                + dxOuter * span.attrStepX[VARYING_SLOT_COL0][2]);
661848b8605Smrg#  ifdef INTERP_ALPHA
662848b8605Smrg                  aLeft = (GLint)(ChanToFixed(vLower->color[ACOMP])
663848b8605Smrg                                  + span.attrStepX[VARYING_SLOT_COL0][3] * adjx
664848b8605Smrg                                  + span.attrStepY[VARYING_SLOT_COL0][3] * adjy) + FIXED_HALF;
665848b8605Smrg                  fdaOuter = SignedFloatToFixed(span.attrStepY[VARYING_SLOT_COL0][3]
666848b8605Smrg                                                + dxOuter * span.attrStepX[VARYING_SLOT_COL0][3]);
667848b8605Smrg#  endif
668848b8605Smrg               }
669848b8605Smrg               else {
670b8e80941Smrg                  assert(ctx->Light.ShadeModel == GL_FLAT);
671848b8605Smrg                  rLeft = ChanToFixed(v2->color[RCOMP]);
672848b8605Smrg                  gLeft = ChanToFixed(v2->color[GCOMP]);
673848b8605Smrg                  bLeft = ChanToFixed(v2->color[BCOMP]);
674848b8605Smrg                  fdrOuter = fdgOuter = fdbOuter = 0;
675848b8605Smrg#  ifdef INTERP_ALPHA
676848b8605Smrg                  aLeft = ChanToFixed(v2->color[ACOMP]);
677848b8605Smrg                  fdaOuter = 0;
678848b8605Smrg#  endif
679848b8605Smrg               }
680848b8605Smrg#endif /* INTERP_RGB */
681848b8605Smrg
682848b8605Smrg
683848b8605Smrg#ifdef INTERP_INT_TEX
684848b8605Smrg               {
685848b8605Smrg                  GLfloat s0, t0;
686848b8605Smrg                  s0 = vLower->attrib[VARYING_SLOT_TEX0][0] * S_SCALE;
687848b8605Smrg                  sLeft = (GLfixed)(s0 * FIXED_SCALE + span.attrStepX[VARYING_SLOT_TEX0][0] * adjx
688848b8605Smrg                                 + span.attrStepY[VARYING_SLOT_TEX0][0] * adjy) + FIXED_HALF;
689848b8605Smrg                  dsOuter = SignedFloatToFixed(span.attrStepY[VARYING_SLOT_TEX0][0]
690848b8605Smrg                                               + dxOuter * span.attrStepX[VARYING_SLOT_TEX0][0]);
691848b8605Smrg
692848b8605Smrg                  t0 = vLower->attrib[VARYING_SLOT_TEX0][1] * T_SCALE;
693848b8605Smrg                  tLeft = (GLfixed)(t0 * FIXED_SCALE + span.attrStepX[VARYING_SLOT_TEX0][1] * adjx
694848b8605Smrg                                 + span.attrStepY[VARYING_SLOT_TEX0][1] * adjy) + FIXED_HALF;
695848b8605Smrg                  dtOuter = SignedFloatToFixed(span.attrStepY[VARYING_SLOT_TEX0][1]
696848b8605Smrg                                               + dxOuter * span.attrStepX[VARYING_SLOT_TEX0][1]);
697848b8605Smrg               }
698848b8605Smrg#endif
699848b8605Smrg#ifdef INTERP_ATTRIBS
700848b8605Smrg               {
701848b8605Smrg                  const GLuint attr = VARYING_SLOT_POS;
702848b8605Smrg                  wLeft = vLower->attrib[VARYING_SLOT_POS][3]
703848b8605Smrg                        + (span.attrStepX[attr][3] * adjx
704848b8605Smrg                           + span.attrStepY[attr][3] * adjy) * (1.0F/FIXED_SCALE);
705848b8605Smrg                  dwOuter = span.attrStepY[attr][3] + dxOuter * span.attrStepX[attr][3];
706848b8605Smrg               }
707848b8605Smrg               ATTRIB_LOOP_BEGIN
708848b8605Smrg                  const GLfloat invW = vLower->attrib[VARYING_SLOT_POS][3];
709848b8605Smrg                  if (swrast->_InterpMode[attr] == GL_FLAT) {
710848b8605Smrg                     GLuint c;
711848b8605Smrg                     for (c = 0; c < 4; c++) {
712848b8605Smrg                        attrLeft[attr][c] = v2->attrib[attr][c] * invW;
713848b8605Smrg                        daOuter[attr][c] = 0.0;
714848b8605Smrg                     }
715848b8605Smrg                  }
716848b8605Smrg                  else {
717848b8605Smrg                     GLuint c;
718848b8605Smrg                     for (c = 0; c < 4; c++) {
719848b8605Smrg                        const GLfloat a = vLower->attrib[attr][c] * invW;
720848b8605Smrg                        attrLeft[attr][c] = a + (  span.attrStepX[attr][c] * adjx
721848b8605Smrg                                                 + span.attrStepY[attr][c] * adjy) * (1.0F/FIXED_SCALE);
722848b8605Smrg                        daOuter[attr][c] = span.attrStepY[attr][c] + dxOuter * span.attrStepX[attr][c];
723848b8605Smrg                     }
724848b8605Smrg                  }
725848b8605Smrg               ATTRIB_LOOP_END
726848b8605Smrg#endif
727848b8605Smrg            } /*if setupLeft*/
728848b8605Smrg
729848b8605Smrg
730848b8605Smrg            if (setupRight && eRight->lines>0) {
731848b8605Smrg               fxRightEdge = eRight->fsx - FIXED_EPSILON;
732848b8605Smrg               fdxRightEdge = eRight->fdxdy;
733848b8605Smrg            }
734848b8605Smrg
735848b8605Smrg            if (lines==0) {
736848b8605Smrg               continue;
737848b8605Smrg            }
738848b8605Smrg
739848b8605Smrg
740848b8605Smrg            /* Rasterize setup */
741848b8605Smrg#ifdef PIXEL_ADDRESS
742848b8605Smrg            dPRowInner = dPRowOuter + sizeof(PIXEL_TYPE);
743848b8605Smrg#endif
744848b8605Smrg#ifdef INTERP_Z
745848b8605Smrg#  ifdef DEPTH_TYPE
746848b8605Smrg            dZRowInner = dZRowOuter + sizeof(DEPTH_TYPE);
747848b8605Smrg#  endif
748848b8605Smrg            fdzInner = fdzOuter + span.zStep;
749848b8605Smrg#endif
750848b8605Smrg#ifdef INTERP_RGB
751848b8605Smrg            fdrInner = fdrOuter + span.redStep;
752848b8605Smrg            fdgInner = fdgOuter + span.greenStep;
753848b8605Smrg            fdbInner = fdbOuter + span.blueStep;
754848b8605Smrg#endif
755848b8605Smrg#ifdef INTERP_ALPHA
756848b8605Smrg            fdaInner = fdaOuter + span.alphaStep;
757848b8605Smrg#endif
758848b8605Smrg#ifdef INTERP_INT_TEX
759848b8605Smrg            dsInner = dsOuter + span.intTexStep[0];
760848b8605Smrg            dtInner = dtOuter + span.intTexStep[1];
761848b8605Smrg#endif
762848b8605Smrg#ifdef INTERP_ATTRIBS
763848b8605Smrg            dwInner = dwOuter + span.attrStepX[VARYING_SLOT_POS][3];
764848b8605Smrg            ATTRIB_LOOP_BEGIN
765848b8605Smrg               GLuint c;
766848b8605Smrg               for (c = 0; c < 4; c++) {
767848b8605Smrg                  daInner[attr][c] = daOuter[attr][c] + span.attrStepX[attr][c];
768848b8605Smrg               }
769848b8605Smrg            ATTRIB_LOOP_END
770848b8605Smrg#endif
771848b8605Smrg
772848b8605Smrg            while (lines > 0) {
773848b8605Smrg               /* initialize the span interpolants to the leftmost value */
774848b8605Smrg               /* ff = fixed-pt fragment */
775848b8605Smrg               const GLint right = FixedToInt(fxRightEdge);
776848b8605Smrg               span.x = FixedToInt(fxLeftEdge);
777848b8605Smrg               if (right <= span.x)
778848b8605Smrg                  span.end = 0;
779848b8605Smrg               else
780848b8605Smrg                  span.end = right - span.x;
781848b8605Smrg
782848b8605Smrg#ifdef INTERP_Z
783848b8605Smrg               span.z = zLeft;
784848b8605Smrg#endif
785848b8605Smrg#ifdef INTERP_RGB
786848b8605Smrg               span.red = rLeft;
787848b8605Smrg               span.green = gLeft;
788848b8605Smrg               span.blue = bLeft;
789848b8605Smrg#endif
790848b8605Smrg#ifdef INTERP_ALPHA
791848b8605Smrg               span.alpha = aLeft;
792848b8605Smrg#endif
793848b8605Smrg#ifdef INTERP_INT_TEX
794848b8605Smrg               span.intTex[0] = sLeft;
795848b8605Smrg               span.intTex[1] = tLeft;
796848b8605Smrg#endif
797848b8605Smrg
798848b8605Smrg#ifdef INTERP_ATTRIBS
799848b8605Smrg               span.attrStart[VARYING_SLOT_POS][3] = wLeft;
800848b8605Smrg               ATTRIB_LOOP_BEGIN
801848b8605Smrg                  GLuint c;
802848b8605Smrg                  for (c = 0; c < 4; c++) {
803848b8605Smrg                     span.attrStart[attr][c] = attrLeft[attr][c];
804848b8605Smrg                  }
805848b8605Smrg               ATTRIB_LOOP_END
806848b8605Smrg#endif
807848b8605Smrg
808848b8605Smrg               /* This is where we actually generate fragments */
809848b8605Smrg               /* XXX the test for span.y > 0 _shouldn't_ be needed but
810848b8605Smrg                * it fixes a problem on 64-bit Opterons (bug 4842).
811848b8605Smrg                */
812848b8605Smrg               if (span.end > 0 && span.y >= 0) {
813848b8605Smrg                  const GLint len = span.end - 1;
814848b8605Smrg                  (void) len;
815848b8605Smrg#ifdef INTERP_RGB
816848b8605Smrg                  CLAMP_INTERPOLANT(red, redStep, len);
817848b8605Smrg                  CLAMP_INTERPOLANT(green, greenStep, len);
818848b8605Smrg                  CLAMP_INTERPOLANT(blue, blueStep, len);
819848b8605Smrg#endif
820848b8605Smrg#ifdef INTERP_ALPHA
821848b8605Smrg                  CLAMP_INTERPOLANT(alpha, alphaStep, len);
822848b8605Smrg#endif
823848b8605Smrg                  {
824848b8605Smrg                     RENDER_SPAN( span );
825848b8605Smrg                  }
826848b8605Smrg               }
827848b8605Smrg
828848b8605Smrg               /*
829848b8605Smrg                * Advance to the next scan line.  Compute the
830848b8605Smrg                * new edge coordinates, and adjust the
831848b8605Smrg                * pixel-center x coordinate so that it stays
832848b8605Smrg                * on or inside the major edge.
833848b8605Smrg                */
834848b8605Smrg               span.y++;
835848b8605Smrg               lines--;
836848b8605Smrg
837848b8605Smrg               fxLeftEdge += fdxLeftEdge;
838848b8605Smrg               fxRightEdge += fdxRightEdge;
839848b8605Smrg
840848b8605Smrg               fError += fdError;
841848b8605Smrg               if (fError >= 0) {
842848b8605Smrg                  fError -= FIXED_ONE;
843848b8605Smrg
844848b8605Smrg#ifdef PIXEL_ADDRESS
845848b8605Smrg                  pRow = (PIXEL_TYPE *) ((GLubyte *) pRow + dPRowOuter);
846848b8605Smrg#endif
847848b8605Smrg#ifdef INTERP_Z
848848b8605Smrg#  ifdef DEPTH_TYPE
849848b8605Smrg                  zRow = (DEPTH_TYPE *) ((GLubyte *) zRow + dZRowOuter);
850848b8605Smrg#  endif
851848b8605Smrg                  zLeft += fdzOuter;
852848b8605Smrg#endif
853848b8605Smrg#ifdef INTERP_RGB
854848b8605Smrg                  rLeft += fdrOuter;
855848b8605Smrg                  gLeft += fdgOuter;
856848b8605Smrg                  bLeft += fdbOuter;
857848b8605Smrg#endif
858848b8605Smrg#ifdef INTERP_ALPHA
859848b8605Smrg                  aLeft += fdaOuter;
860848b8605Smrg#endif
861848b8605Smrg#ifdef INTERP_INT_TEX
862848b8605Smrg                  sLeft += dsOuter;
863848b8605Smrg                  tLeft += dtOuter;
864848b8605Smrg#endif
865848b8605Smrg#ifdef INTERP_ATTRIBS
866848b8605Smrg                  wLeft += dwOuter;
867848b8605Smrg                  ATTRIB_LOOP_BEGIN
868848b8605Smrg                     GLuint c;
869848b8605Smrg                     for (c = 0; c < 4; c++) {
870848b8605Smrg                        attrLeft[attr][c] += daOuter[attr][c];
871848b8605Smrg                     }
872848b8605Smrg                  ATTRIB_LOOP_END
873848b8605Smrg#endif
874848b8605Smrg               }
875848b8605Smrg               else {
876848b8605Smrg#ifdef PIXEL_ADDRESS
877848b8605Smrg                  pRow = (PIXEL_TYPE *) ((GLubyte *) pRow + dPRowInner);
878848b8605Smrg#endif
879848b8605Smrg#ifdef INTERP_Z
880848b8605Smrg#  ifdef DEPTH_TYPE
881848b8605Smrg                  zRow = (DEPTH_TYPE *) ((GLubyte *) zRow + dZRowInner);
882848b8605Smrg#  endif
883848b8605Smrg                  zLeft += fdzInner;
884848b8605Smrg#endif
885848b8605Smrg#ifdef INTERP_RGB
886848b8605Smrg                  rLeft += fdrInner;
887848b8605Smrg                  gLeft += fdgInner;
888848b8605Smrg                  bLeft += fdbInner;
889848b8605Smrg#endif
890848b8605Smrg#ifdef INTERP_ALPHA
891848b8605Smrg                  aLeft += fdaInner;
892848b8605Smrg#endif
893848b8605Smrg#ifdef INTERP_INT_TEX
894848b8605Smrg                  sLeft += dsInner;
895848b8605Smrg                  tLeft += dtInner;
896848b8605Smrg#endif
897848b8605Smrg#ifdef INTERP_ATTRIBS
898848b8605Smrg                  wLeft += dwInner;
899848b8605Smrg                  ATTRIB_LOOP_BEGIN
900848b8605Smrg                     GLuint c;
901848b8605Smrg                     for (c = 0; c < 4; c++) {
902848b8605Smrg                        attrLeft[attr][c] += daInner[attr][c];
903848b8605Smrg                     }
904848b8605Smrg                  ATTRIB_LOOP_END
905848b8605Smrg#endif
906848b8605Smrg               }
907848b8605Smrg            } /*while lines>0*/
908848b8605Smrg
909848b8605Smrg         } /* for subTriangle */
910848b8605Smrg
911848b8605Smrg      }
912848b8605Smrg   }
913848b8605Smrg}
914848b8605Smrg
915848b8605Smrg#undef SETUP_CODE
916848b8605Smrg#undef RENDER_SPAN
917848b8605Smrg
918848b8605Smrg#undef PIXEL_TYPE
919848b8605Smrg#undef BYTES_PER_ROW
920848b8605Smrg#undef PIXEL_ADDRESS
921848b8605Smrg#undef DEPTH_TYPE
922848b8605Smrg
923848b8605Smrg#undef INTERP_Z
924848b8605Smrg#undef INTERP_RGB
925848b8605Smrg#undef INTERP_ALPHA
926848b8605Smrg#undef INTERP_INT_TEX
927848b8605Smrg#undef INTERP_ATTRIBS
928848b8605Smrg
929848b8605Smrg#undef S_SCALE
930848b8605Smrg#undef T_SCALE
931848b8605Smrg
932848b8605Smrg#undef FixedToDepth
933848b8605Smrg
934848b8605Smrg#undef NAME
935