fix some CHAN_TYPE==GL_FLOAT breakage
[mesa.git] / src / mesa / swrast / s_tritemp.h
1 /*
2 * Mesa 3-D graphics library
3 * Version: 6.5.3
4 *
5 * Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25 /*
26 * Triangle Rasterizer Template
27 *
28 * This file is #include'd to generate custom triangle rasterizers.
29 *
30 * The following macros may be defined to indicate what auxillary information
31 * must be interpolated across the triangle:
32 * INTERP_Z - if defined, interpolate vertex Z values
33 * INTERP_W - if defined, interpolate vertex W values
34 * INTERP_FOG - if defined, interpolate fog values
35 * INTERP_RGB - if defined, interpolate RGB values
36 * INTERP_ALPHA - if defined, interpolate Alpha values (req's INTERP_RGB)
37 * INTERP_SPEC - if defined, interpolate specular RGB values
38 * INTERP_INDEX - if defined, interpolate color index values
39 * INTERP_INT_TEX - if defined, interpolate integer ST texcoords
40 * (fast, simple 2-D texture mapping)
41 * INTERP_TEX - if defined, interpolate texcoords and varying vars
42 * NOTE: OpenGL STRQ = Mesa STUV (R was taken for red)
43 *
44 * When one can directly address pixels in the color buffer the following
45 * macros can be defined and used to compute pixel addresses during
46 * rasterization (see pRow):
47 * PIXEL_TYPE - the datatype of a pixel (GLubyte, GLushort, GLuint)
48 * BYTES_PER_ROW - number of bytes per row in the color buffer
49 * PIXEL_ADDRESS(X,Y) - returns the address of pixel at (X,Y) where
50 * Y==0 at bottom of screen and increases upward.
51 *
52 * Similarly, for direct depth buffer access, this type is used for depth
53 * buffer addressing:
54 * DEPTH_TYPE - either GLushort or GLuint
55 *
56 * Optionally, one may provide one-time setup code per triangle:
57 * SETUP_CODE - code which is to be executed once per triangle
58 * CLEANUP_CODE - code to execute at end of triangle
59 *
60 * The following macro MUST be defined:
61 * RENDER_SPAN(span) - code to write a span of pixels.
62 *
63 * This code was designed for the origin to be in the lower-left corner.
64 *
65 * Inspired by triangle rasterizer code written by Allen Akin. Thanks Allen!
66 *
67 *
68 * Some notes on rasterization accuracy:
69 *
70 * This code uses fixed point arithmetic (the GLfixed type) to iterate
71 * over the triangle edges and interpolate ancillary data (such as Z,
72 * color, secondary color, etc). The number of fractional bits in
73 * GLfixed and the value of SUB_PIXEL_BITS has a direct bearing on the
74 * accuracy of rasterization.
75 *
76 * If SUB_PIXEL_BITS=4 then we'll snap the vertices to the nearest
77 * 1/16 of a pixel. If we're walking up a long, nearly vertical edge
78 * (dx=1/16, dy=1024) we'll need 4 + 10 = 14 fractional bits in
79 * GLfixed to walk the edge without error. If the maximum viewport
80 * height is 4K pixels, then we'll need 4 + 12 = 16 fractional bits.
81 *
82 * Historically, Mesa has used 11 fractional bits in GLfixed, snaps
83 * vertices to 1/16 pixel and allowed a maximum viewport height of 2K
84 * pixels. 11 fractional bits is actually insufficient for accurately
85 * rasterizing some triangles. More recently, the maximum viewport
86 * height was increased to 4K pixels. Thus, Mesa should be using 16
87 * fractional bits in GLfixed. Unfortunately, there may be some issues
88 * with setting FIXED_FRAC_BITS=16, such as multiplication overflow.
89 * This will have to be examined in some detail...
90 *
91 * For now, if you find rasterization errors, particularly with tall,
92 * sliver triangles, try increasing FIXED_FRAC_BITS and/or decreasing
93 * SUB_PIXEL_BITS.
94 */
95
96 /*
97 * ColorTemp is used for intermediate color values.
98 */
99 #if CHAN_TYPE == GL_FLOAT
100 #define ColorTemp GLfloat
101 #else
102 #define ColorTemp GLint /* same as GLfixed */
103 #endif
104
105
106 /*
107 * Walk triangle edges with GLfixed or GLdouble
108 */
109 #if TRIANGLE_WALK_DOUBLE
110 #define GLinterp GLdouble
111 #define InterpToInt(X) ((GLint) (X))
112 #define INTERP_ONE 1.0
113 #else
114 #define GLinterp GLfixed
115 #define InterpToInt(X) FixedToInt(X)
116 #define INTERP_ONE FIXED_ONE
117 #endif
118
119
120 #define TEXVAR_LOOP(CODE) \
121 { \
122 GLuint attr; \
123 for (attr = swrast->_MinFragmentAttrib; \
124 attr < swrast->_MaxFragmentAttrib; attr++) { \
125 if (swrast->_FragmentAttribs & (1 << attr)) { \
126 CODE \
127 } \
128 } \
129 }
130
131
132
133
134 /*
135 * Some code we unfortunately need to prevent negative interpolated colors.
136 */
137 #ifndef CLAMP_INTERPOLANT
138 #define CLAMP_INTERPOLANT(CHANNEL, CHANNELSTEP, LEN) \
139 do { \
140 GLfixed endVal = span.CHANNEL + (LEN) * span.CHANNELSTEP; \
141 if (endVal < 0) { \
142 span.CHANNEL -= endVal; \
143 } \
144 if (span.CHANNEL < 0) { \
145 span.CHANNEL = 0; \
146 } \
147 } while (0)
148 #endif
149
150
151 static void NAME(GLcontext *ctx, const SWvertex *v0,
152 const SWvertex *v1,
153 const SWvertex *v2 )
154 {
155 typedef struct {
156 const SWvertex *v0, *v1; /* Y(v0) < Y(v1) */
157 #if TRIANGLE_WALK_DOUBLE
158 GLdouble dx; /* X(v1) - X(v0) */
159 GLdouble dy; /* Y(v1) - Y(v0) */
160 GLdouble dxdy; /* dx/dy */
161 GLdouble adjy; /* adjust from v[0]->fy to fsy, scaled */
162 GLdouble fsx; /* first sample point x coord */
163 GLdouble fsy;
164 GLdouble fx0; /*X of lower endpoint */
165 #else
166 GLfloat dx; /* X(v1) - X(v0) */
167 GLfloat dy; /* Y(v1) - Y(v0) */
168 GLfloat dxdy; /* dx/dy */
169 GLfixed fdxdy; /* dx/dy in fixed-point */
170 GLfloat adjy; /* adjust from v[0]->fy to fsy, scaled */
171 GLfixed fsx; /* first sample point x coord */
172 GLfixed fsy;
173 GLfixed fx0; /* fixed pt X of lower endpoint */
174 #endif
175 GLint lines; /* number of lines to be sampled on this edge */
176 } EdgeT;
177
178 const SWcontext *swrast = SWRAST_CONTEXT(ctx);
179 #ifdef INTERP_Z
180 const GLint depthBits = ctx->DrawBuffer->Visual.depthBits;
181 const GLint fixedToDepthShift = depthBits <= 16 ? FIXED_SHIFT : 0;
182 const GLfloat maxDepth = ctx->DrawBuffer->_DepthMaxF;
183 #define FixedToDepth(F) ((F) >> fixedToDepthShift)
184 #endif
185 EdgeT eMaj, eTop, eBot;
186 GLfloat oneOverArea;
187 const SWvertex *vMin, *vMid, *vMax; /* Y(vMin)<=Y(vMid)<=Y(vMax) */
188 GLfloat bf = SWRAST_CONTEXT(ctx)->_BackfaceSign;
189 #if !TRIANGLE_WALK_DOUBLE
190 const GLint snapMask = ~((FIXED_ONE / (1 << SUB_PIXEL_BITS)) - 1); /* for x/y coord snapping */
191 #endif
192 GLinterp vMin_fx, vMin_fy, vMid_fx, vMid_fy, vMax_fx, vMax_fy;
193
194 SWspan span;
195
196 (void) swrast;
197
198 INIT_SPAN(span, GL_POLYGON, 0, 0, 0);
199 span.y = 0; /* silence warnings */
200
201 #ifdef INTERP_Z
202 (void) fixedToDepthShift;
203 #endif
204
205 /*
206 printf("%s()\n", __FUNCTION__);
207 printf(" %g, %g, %g\n", v0->win[0], v0->win[1], v0->win[2]);
208 printf(" %g, %g, %g\n", v1->win[0], v1->win[1], v1->win[2]);
209 printf(" %g, %g, %g\n", v2->win[0], v2->win[1], v2->win[2]);
210 */
211 /*
212 ASSERT(v0->win[2] >= 0.0);
213 ASSERT(v1->win[2] >= 0.0);
214 ASSERT(v2->win[2] >= 0.0);
215 */
216 /* Compute fixed point x,y coords w/ half-pixel offsets and snapping.
217 * And find the order of the 3 vertices along the Y axis.
218 */
219 {
220 #if TRIANGLE_WALK_DOUBLE
221 const GLdouble fy0 = v0->win[1] - 0.5;
222 const GLdouble fy1 = v1->win[1] - 0.5;
223 const GLdouble fy2 = v2->win[1] - 0.5;
224 #else
225 const GLfixed fy0 = FloatToFixed(v0->win[1] - 0.5F) & snapMask;
226 const GLfixed fy1 = FloatToFixed(v1->win[1] - 0.5F) & snapMask;
227 const GLfixed fy2 = FloatToFixed(v2->win[1] - 0.5F) & snapMask;
228 #endif
229 if (fy0 <= fy1) {
230 if (fy1 <= fy2) {
231 /* y0 <= y1 <= y2 */
232 vMin = v0; vMid = v1; vMax = v2;
233 vMin_fy = fy0; vMid_fy = fy1; vMax_fy = fy2;
234 }
235 else if (fy2 <= fy0) {
236 /* y2 <= y0 <= y1 */
237 vMin = v2; vMid = v0; vMax = v1;
238 vMin_fy = fy2; vMid_fy = fy0; vMax_fy = fy1;
239 }
240 else {
241 /* y0 <= y2 <= y1 */
242 vMin = v0; vMid = v2; vMax = v1;
243 vMin_fy = fy0; vMid_fy = fy2; vMax_fy = fy1;
244 bf = -bf;
245 }
246 }
247 else {
248 if (fy0 <= fy2) {
249 /* y1 <= y0 <= y2 */
250 vMin = v1; vMid = v0; vMax = v2;
251 vMin_fy = fy1; vMid_fy = fy0; vMax_fy = fy2;
252 bf = -bf;
253 }
254 else if (fy2 <= fy1) {
255 /* y2 <= y1 <= y0 */
256 vMin = v2; vMid = v1; vMax = v0;
257 vMin_fy = fy2; vMid_fy = fy1; vMax_fy = fy0;
258 bf = -bf;
259 }
260 else {
261 /* y1 <= y2 <= y0 */
262 vMin = v1; vMid = v2; vMax = v0;
263 vMin_fy = fy1; vMid_fy = fy2; vMax_fy = fy0;
264 }
265 }
266
267 /* fixed point X coords */
268 #if TRIANGLE_WALK_DOUBLE
269 vMin_fx = vMin->win[0] + 0.5;
270 vMid_fx = vMid->win[0] + 0.5;
271 vMax_fx = vMax->win[0] + 0.5;
272 #else
273 vMin_fx = FloatToFixed(vMin->win[0] + 0.5F) & snapMask;
274 vMid_fx = FloatToFixed(vMid->win[0] + 0.5F) & snapMask;
275 vMax_fx = FloatToFixed(vMax->win[0] + 0.5F) & snapMask;
276 #endif
277 }
278
279 /* vertex/edge relationship */
280 eMaj.v0 = vMin; eMaj.v1 = vMax; /*TODO: .v1's not needed */
281 eTop.v0 = vMid; eTop.v1 = vMax;
282 eBot.v0 = vMin; eBot.v1 = vMid;
283
284 /* compute deltas for each edge: vertex[upper] - vertex[lower] */
285 #if TRIANGLE_WALK_DOUBLE
286 eMaj.dx = vMax_fx - vMin_fx;
287 eMaj.dy = vMax_fy - vMin_fy;
288 eTop.dx = vMax_fx - vMid_fx;
289 eTop.dy = vMax_fy - vMid_fy;
290 eBot.dx = vMid_fx - vMin_fx;
291 eBot.dy = vMid_fy - vMin_fy;
292 #else
293 eMaj.dx = FixedToFloat(vMax_fx - vMin_fx);
294 eMaj.dy = FixedToFloat(vMax_fy - vMin_fy);
295 eTop.dx = FixedToFloat(vMax_fx - vMid_fx);
296 eTop.dy = FixedToFloat(vMax_fy - vMid_fy);
297 eBot.dx = FixedToFloat(vMid_fx - vMin_fx);
298 eBot.dy = FixedToFloat(vMid_fy - vMin_fy);
299 #endif
300
301 /* compute area, oneOverArea and perform backface culling */
302 {
303 #if TRIANGLE_WALK_DOUBLE
304 const GLdouble area = eMaj.dx * eBot.dy - eBot.dx * eMaj.dy;
305 #else
306 const GLfloat area = eMaj.dx * eBot.dy - eBot.dx * eMaj.dy;
307 #endif
308 /* Do backface culling */
309 if (area * bf < 0.0)
310 return;
311
312 if (IS_INF_OR_NAN(area) || area == 0.0F)
313 return;
314
315 oneOverArea = 1.0F / area;
316 }
317
318
319 span.facing = ctx->_Facing; /* for 2-sided stencil test */
320
321 /* Edge setup. For a triangle strip these could be reused... */
322 {
323 #if TRIANGLE_WALK_DOUBLE
324 eMaj.fsy = CEILF(vMin_fy);
325 eMaj.lines = (GLint) CEILF(vMax_fy - eMaj.fsy);
326 #else
327 eMaj.fsy = FixedCeil(vMin_fy);
328 eMaj.lines = FixedToInt(FixedCeil(vMax_fy - eMaj.fsy));
329 #endif
330 if (eMaj.lines > 0) {
331 eMaj.dxdy = eMaj.dx / eMaj.dy;
332 #if TRIANGLE_WALK_DOUBLE
333 eMaj.adjy = (eMaj.fsy - vMin_fy) * FIXED_SCALE; /* SCALED! */
334 eMaj.fx0 = vMin_fx;
335 eMaj.fsx = eMaj.fx0 + (eMaj.adjy * eMaj.dxdy) / (GLdouble) FIXED_SCALE;
336 #else
337 eMaj.fdxdy = SignedFloatToFixed(eMaj.dxdy);
338 eMaj.adjy = (GLfloat) (eMaj.fsy - vMin_fy); /* SCALED! */
339 eMaj.fx0 = vMin_fx;
340 eMaj.fsx = eMaj.fx0 + (GLfixed) (eMaj.adjy * eMaj.dxdy);
341 #endif
342 }
343 else {
344 return; /*CULLED*/
345 }
346
347 #if TRIANGLE_WALK_DOUBLE
348 eTop.fsy = CEILF(vMid_fy);
349 eTop.lines = (GLint) CEILF(vMax_fy - eTop.fsy);
350 #else
351 eTop.fsy = FixedCeil(vMid_fy);
352 eTop.lines = FixedToInt(FixedCeil(vMax_fy - eTop.fsy));
353 #endif
354 if (eTop.lines > 0) {
355 eTop.dxdy = eTop.dx / eTop.dy;
356 #if TRIANGLE_WALK_DOUBLE
357 eTop.adjy = (eTop.fsy - vMid_fy) * FIXED_SCALE; /* SCALED! */
358 eTop.fx0 = vMid_fx;
359 eTop.fsx = eTop.fx0 + (eTop.adjy * eTop.dxdy) / (GLdouble) FIXED_SCALE;
360 #else
361 eTop.fdxdy = SignedFloatToFixed(eTop.dxdy);
362 eTop.adjy = (GLfloat) (eTop.fsy - vMid_fy); /* SCALED! */
363 eTop.fx0 = vMid_fx;
364 eTop.fsx = eTop.fx0 + (GLfixed) (eTop.adjy * eTop.dxdy);
365 #endif
366 }
367
368 #if TRIANGLE_WALK_DOUBLE
369 eBot.fsy = CEILF(vMin_fy);
370 eBot.lines = (GLint) CEILF(vMid_fy - eBot.fsy);
371 #else
372 eBot.fsy = FixedCeil(vMin_fy);
373 eBot.lines = FixedToInt(FixedCeil(vMid_fy - eBot.fsy));
374 #endif
375 if (eBot.lines > 0) {
376 eBot.dxdy = eBot.dx / eBot.dy;
377 #if TRIANGLE_WALK_DOUBLE
378 eBot.adjy = (eBot.fsy - vMin_fy) * FIXED_SCALE; /* SCALED! */
379 eBot.fx0 = vMin_fx;
380 eBot.fsx = eBot.fx0 + (eBot.adjy * eBot.dxdy) / (GLdouble) FIXED_SCALE;
381 #else
382 eBot.fdxdy = SignedFloatToFixed(eBot.dxdy);
383 eBot.adjy = (GLfloat) (eBot.fsy - vMin_fy); /* SCALED! */
384 eBot.fx0 = vMin_fx;
385 eBot.fsx = eBot.fx0 + (GLfixed) (eBot.adjy * eBot.dxdy);
386 #endif
387 }
388 }
389
390 /*
391 * Conceptually, we view a triangle as two subtriangles
392 * separated by a perfectly horizontal line. The edge that is
393 * intersected by this line is one with maximal absolute dy; we
394 * call it a ``major'' edge. The other two edges are the
395 * ``top'' edge (for the upper subtriangle) and the ``bottom''
396 * edge (for the lower subtriangle). If either of these two
397 * edges is horizontal or very close to horizontal, the
398 * corresponding subtriangle might cover zero sample points;
399 * we take care to handle such cases, for performance as well
400 * as correctness.
401 *
402 * By stepping rasterization parameters along the major edge,
403 * we can avoid recomputing them at the discontinuity where
404 * the top and bottom edges meet. However, this forces us to
405 * be able to scan both left-to-right and right-to-left.
406 * Also, we must determine whether the major edge is at the
407 * left or right side of the triangle. We do this by
408 * computing the magnitude of the cross-product of the major
409 * and top edges. Since this magnitude depends on the sine of
410 * the angle between the two edges, its sign tells us whether
411 * we turn to the left or to the right when travelling along
412 * the major edge to the top edge, and from this we infer
413 * whether the major edge is on the left or the right.
414 *
415 * Serendipitously, this cross-product magnitude is also a
416 * value we need to compute the iteration parameter
417 * derivatives for the triangle, and it can be used to perform
418 * backface culling because its sign tells us whether the
419 * triangle is clockwise or counterclockwise. In this code we
420 * refer to it as ``area'' because it's also proportional to
421 * the pixel area of the triangle.
422 */
423
424 {
425 GLint scan_from_left_to_right; /* true if scanning left-to-right */
426 #ifdef INTERP_INDEX
427 GLfloat didx, didy;
428 #endif
429
430 /*
431 * Execute user-supplied setup code
432 */
433 #ifdef SETUP_CODE
434 SETUP_CODE
435 #endif
436
437 scan_from_left_to_right = (oneOverArea < 0.0F);
438
439
440 /* compute d?/dx and d?/dy derivatives */
441 #ifdef INTERP_Z
442 span.interpMask |= SPAN_Z;
443 {
444 GLfloat eMaj_dz = vMax->win[2] - vMin->win[2];
445 GLfloat eBot_dz = vMid->win[2] - vMin->win[2];
446 span.attrStepX[FRAG_ATTRIB_WPOS][2] = oneOverArea * (eMaj_dz * eBot.dy - eMaj.dy * eBot_dz);
447 if (span.attrStepX[FRAG_ATTRIB_WPOS][2] > maxDepth || span.attrStepX[FRAG_ATTRIB_WPOS][2] < -maxDepth) {
448 /* probably a sliver triangle */
449 span.attrStepX[FRAG_ATTRIB_WPOS][2] = 0.0;
450 span.attrStepY[FRAG_ATTRIB_WPOS][2] = 0.0;
451 }
452 else {
453 span.attrStepY[FRAG_ATTRIB_WPOS][2] = oneOverArea * (eMaj.dx * eBot_dz - eMaj_dz * eBot.dx);
454 }
455 if (depthBits <= 16)
456 span.zStep = SignedFloatToFixed(span.attrStepX[FRAG_ATTRIB_WPOS][2]);
457 else
458 span.zStep = (GLint) span.attrStepX[FRAG_ATTRIB_WPOS][2];
459 }
460 #endif
461 #ifdef INTERP_W
462 span.interpMask |= SPAN_W;
463 {
464 const GLfloat eMaj_dw = vMax->win[3] - vMin->win[3];
465 const GLfloat eBot_dw = vMid->win[3] - vMin->win[3];
466 span.attrStepX[FRAG_ATTRIB_WPOS][3] = oneOverArea * (eMaj_dw * eBot.dy - eMaj.dy * eBot_dw);
467 span.attrStepY[FRAG_ATTRIB_WPOS][3] = oneOverArea * (eMaj.dx * eBot_dw - eMaj_dw * eBot.dx);
468 }
469 #endif
470 #ifdef INTERP_FOG
471 span.interpMask |= SPAN_FOG;
472 {
473 # ifdef INTERP_W
474 const GLfloat wMax = vMax->win[3], wMin = vMin->win[3], wMid = vMid->win[3];
475 const GLfloat eMaj_dfog = vMax->fog * wMax - vMin->fog * wMin;
476 const GLfloat eBot_dfog = vMid->fog * wMid - vMin->fog * wMin;
477 # else
478 const GLfloat eMaj_dfog = vMax->fog - vMin->fog;
479 const GLfloat eBot_dfog = vMid->fog - vMin->fog;
480 # endif
481 span.attrStepX[FRAG_ATTRIB_FOGC][0] = oneOverArea * (eMaj_dfog * eBot.dy - eMaj.dy * eBot_dfog);
482 span.attrStepY[FRAG_ATTRIB_FOGC][0] = oneOverArea * (eMaj.dx * eBot_dfog - eMaj_dfog * eBot.dx);
483 }
484 #endif
485 #ifdef INTERP_RGB
486 span.interpMask |= SPAN_RGBA;
487 if (ctx->Light.ShadeModel == GL_SMOOTH) {
488 GLfloat eMaj_dr = (GLfloat) ((ColorTemp) vMax->color[RCOMP] - (ColorTemp) vMin->color[RCOMP]);
489 GLfloat eBot_dr = (GLfloat) ((ColorTemp) vMid->color[RCOMP] - (ColorTemp) vMin->color[RCOMP]);
490 GLfloat eMaj_dg = (GLfloat) ((ColorTemp) vMax->color[GCOMP] - (ColorTemp) vMin->color[GCOMP]);
491 GLfloat eBot_dg = (GLfloat) ((ColorTemp) vMid->color[GCOMP] - (ColorTemp) vMin->color[GCOMP]);
492 GLfloat eMaj_db = (GLfloat) ((ColorTemp) vMax->color[BCOMP] - (ColorTemp) vMin->color[BCOMP]);
493 GLfloat eBot_db = (GLfloat) ((ColorTemp) vMid->color[BCOMP] - (ColorTemp) vMin->color[BCOMP]);
494 # ifdef INTERP_ALPHA
495 GLfloat eMaj_da = (GLfloat) ((ColorTemp) vMax->color[ACOMP] - (ColorTemp) vMin->color[ACOMP]);
496 GLfloat eBot_da = (GLfloat) ((ColorTemp) vMid->color[ACOMP] - (ColorTemp) vMin->color[ACOMP]);
497 # endif
498 span.attrStepX[FRAG_ATTRIB_COL0][0] = oneOverArea * (eMaj_dr * eBot.dy - eMaj.dy * eBot_dr);
499 span.attrStepY[FRAG_ATTRIB_COL0][0] = oneOverArea * (eMaj.dx * eBot_dr - eMaj_dr * eBot.dx);
500 span.attrStepX[FRAG_ATTRIB_COL0][1] = oneOverArea * (eMaj_dg * eBot.dy - eMaj.dy * eBot_dg);
501 span.attrStepY[FRAG_ATTRIB_COL0][1] = oneOverArea * (eMaj.dx * eBot_dg - eMaj_dg * eBot.dx);
502 span.attrStepX[FRAG_ATTRIB_COL0][2] = oneOverArea * (eMaj_db * eBot.dy - eMaj.dy * eBot_db);
503 span.attrStepY[FRAG_ATTRIB_COL0][2] = oneOverArea * (eMaj.dx * eBot_db - eMaj_db * eBot.dx);
504 # if CHAN_TYPE == GL_FLOAT
505 span.redStep = span.attrStepX[FRAG_ATTRIB_COL0][0];
506 span.greenStep = span.attrStepX[FRAG_ATTRIB_COL0][1];
507 span.blueStep = span.attrStepX[FRAG_ATTRIB_COL0][2];
508 # else
509 span.redStep = SignedFloatToFixed(span.attrStepX[FRAG_ATTRIB_COL0][0]);
510 span.greenStep = SignedFloatToFixed(span.attrStepX[FRAG_ATTRIB_COL0][1]);
511 span.blueStep = SignedFloatToFixed(span.attrStepX[FRAG_ATTRIB_COL0][2]);
512 # endif /* GL_FLOAT */
513 # ifdef INTERP_ALPHA
514 span.attrStepX[FRAG_ATTRIB_COL0][3] = oneOverArea * (eMaj_da * eBot.dy - eMaj.dy * eBot_da);
515 span.attrStepX[FRAG_ATTRIB_COL0][3] = oneOverArea * (eMaj.dx * eBot_da - eMaj_da * eBot.dx);
516 # if CHAN_TYPE == GL_FLOAT
517 span.alphaStep = span.attrStepX[FRAG_ATTRIB_COL0][3];
518 # else
519 span.alphaStep = SignedFloatToFixed(span.attrStepX[FRAG_ATTRIB_COL0][3]);
520 # endif /* GL_FLOAT */
521 # endif /* INTERP_ALPHA */
522 }
523 else {
524 ASSERT(ctx->Light.ShadeModel == GL_FLAT);
525 span.interpMask |= SPAN_FLAT;
526 span.attrStepX[FRAG_ATTRIB_COL0][0] = span.attrStepY[FRAG_ATTRIB_COL0][0] = 0.0F;
527 span.attrStepX[FRAG_ATTRIB_COL0][1] = span.attrStepY[FRAG_ATTRIB_COL0][1] = 0.0F;
528 span.attrStepX[FRAG_ATTRIB_COL0][2] = span.attrStepY[FRAG_ATTRIB_COL0][2] = 0.0F;
529 # if CHAN_TYPE == GL_FLOAT
530 span.redStep = 0.0F;
531 span.greenStep = 0.0F;
532 span.blueStep = 0.0F;
533 # else
534 span.redStep = 0;
535 span.greenStep = 0;
536 span.blueStep = 0;
537 # endif /* GL_FLOAT */
538 # ifdef INTERP_ALPHA
539 span.attrStepX[FRAG_ATTRIB_COL0][3] = span.attrStepX[FRAG_ATTRIB_COL0][3] = 0.0F;
540 # if CHAN_TYPE == GL_FLOAT
541 span.alphaStep = 0.0F;
542 # else
543 span.alphaStep = 0;
544 # endif /* GL_FLOAT */
545 # endif
546 }
547 #endif /* INTERP_RGB */
548 #ifdef INTERP_SPEC
549 span.interpMask |= SPAN_SPEC;
550 if (ctx->Light.ShadeModel == GL_SMOOTH) {
551 GLfloat eMaj_dsr = (GLfloat) ((ColorTemp) vMax->specular[RCOMP] - (ColorTemp) vMin->specular[RCOMP]);
552 GLfloat eBot_dsr = (GLfloat) ((ColorTemp) vMid->specular[RCOMP] - (ColorTemp) vMin->specular[RCOMP]);
553 GLfloat eMaj_dsg = (GLfloat) ((ColorTemp) vMax->specular[GCOMP] - (ColorTemp) vMin->specular[GCOMP]);
554 GLfloat eBot_dsg = (GLfloat) ((ColorTemp) vMid->specular[GCOMP] - (ColorTemp) vMin->specular[GCOMP]);
555 GLfloat eMaj_dsb = (GLfloat) ((ColorTemp) vMax->specular[BCOMP] - (ColorTemp) vMin->specular[BCOMP]);
556 GLfloat eBot_dsb = (GLfloat) ((ColorTemp) vMid->specular[BCOMP] - (ColorTemp) vMin->specular[BCOMP]);
557 span.attrStepX[FRAG_ATTRIB_COL1][0] = oneOverArea * (eMaj_dsr * eBot.dy - eMaj.dy * eBot_dsr);
558 span.attrStepY[FRAG_ATTRIB_COL1][0] = oneOverArea * (eMaj.dx * eBot_dsr - eMaj_dsr * eBot.dx);
559 span.attrStepX[FRAG_ATTRIB_COL1][1] = oneOverArea * (eMaj_dsg * eBot.dy - eMaj.dy * eBot_dsg);
560 span.attrStepY[FRAG_ATTRIB_COL1][1] = oneOverArea * (eMaj.dx * eBot_dsg - eMaj_dsg * eBot.dx);
561 span.attrStepX[FRAG_ATTRIB_COL1][2] = oneOverArea * (eMaj_dsb * eBot.dy - eMaj.dy * eBot_dsb);
562 span.attrStepY[FRAG_ATTRIB_COL1][2] = oneOverArea * (eMaj.dx * eBot_dsb - eMaj_dsb * eBot.dx);
563 # if CHAN_TYPE == GL_FLOAT
564 span.specRedStep = span.attrStepX[FRAG_ATTRIB_COL1][0];
565 span.specGreenStep = span.attrStepX[FRAG_ATTRIB_COL1][1];
566 span.specBlueStep = span.attrStepX[FRAG_ATTRIB_COL1][2];
567 # else
568 span.specRedStep = SignedFloatToFixed(span.attrStepX[FRAG_ATTRIB_COL1][0]);
569 span.specGreenStep = SignedFloatToFixed(span.attrStepX[FRAG_ATTRIB_COL1][1]);
570 span.specBlueStep = SignedFloatToFixed(span.attrStepX[FRAG_ATTRIB_COL1][2]);
571 # endif
572 }
573 else {
574 span.attrStepX[FRAG_ATTRIB_COL1][0] = span.attrStepY[FRAG_ATTRIB_COL1][0] = 0.0F;
575 span.attrStepX[FRAG_ATTRIB_COL1][1] = span.attrStepY[FRAG_ATTRIB_COL1][1] = 0.0F;
576 span.attrStepX[FRAG_ATTRIB_COL1][2] = span.attrStepY[FRAG_ATTRIB_COL1][2] = 0.0F;
577 # if CHAN_TYPE == GL_FLOAT
578 span.specRedStep = 0.0F;
579 span.specGreenStep = 0.0F;
580 span.specBlueStep = 0.0F;
581 # else
582 span.specRedStep = 0;
583 span.specGreenStep = 0;
584 span.specBlueStep = 0;
585 # endif
586 }
587 #endif /* INTERP_SPEC */
588 #ifdef INTERP_INDEX
589 span.interpMask |= SPAN_INDEX;
590 if (ctx->Light.ShadeModel == GL_SMOOTH) {
591 GLfloat eMaj_di = vMax->index - vMin->index;
592 GLfloat eBot_di = vMid->index - vMin->index;
593 didx = oneOverArea * (eMaj_di * eBot.dy - eMaj.dy * eBot_di);
594 didy = oneOverArea * (eMaj.dx * eBot_di - eMaj_di * eBot.dx);
595 span.indexStep = SignedFloatToFixed(didx);
596 }
597 else {
598 span.interpMask |= SPAN_FLAT;
599 didx = didy = 0.0F;
600 span.indexStep = 0;
601 }
602 #endif
603 #ifdef INTERP_INT_TEX
604 span.interpMask |= SPAN_INT_TEXTURE;
605 {
606 GLfloat eMaj_ds = (vMax->attrib[FRAG_ATTRIB_TEX0][0] - vMin->attrib[FRAG_ATTRIB_TEX0][0]) * S_SCALE;
607 GLfloat eBot_ds = (vMid->attrib[FRAG_ATTRIB_TEX0][0] - vMin->attrib[FRAG_ATTRIB_TEX0][0]) * S_SCALE;
608 GLfloat eMaj_dt = (vMax->attrib[FRAG_ATTRIB_TEX0][1] - vMin->attrib[FRAG_ATTRIB_TEX0][1]) * T_SCALE;
609 GLfloat eBot_dt = (vMid->attrib[FRAG_ATTRIB_TEX0][1] - vMin->attrib[FRAG_ATTRIB_TEX0][1]) * T_SCALE;
610 span.attrStepX[FRAG_ATTRIB_TEX0][0] = oneOverArea * (eMaj_ds * eBot.dy - eMaj.dy * eBot_ds);
611 span.attrStepY[FRAG_ATTRIB_TEX0][0] = oneOverArea * (eMaj.dx * eBot_ds - eMaj_ds * eBot.dx);
612 span.attrStepX[FRAG_ATTRIB_TEX0][1] = oneOverArea * (eMaj_dt * eBot.dy - eMaj.dy * eBot_dt);
613 span.attrStepY[FRAG_ATTRIB_TEX0][1] = oneOverArea * (eMaj.dx * eBot_dt - eMaj_dt * eBot.dx);
614 span.intTexStep[0] = SignedFloatToFixed(span.attrStepX[FRAG_ATTRIB_TEX0][0]);
615 span.intTexStep[1] = SignedFloatToFixed(span.attrStepX[FRAG_ATTRIB_TEX0][1]);
616 }
617 #endif
618 #ifdef INTERP_TEX
619 span.interpMask |= (SPAN_TEXTURE | SPAN_VARYING);
620 {
621 /* win[3] is 1/W */
622 const GLfloat wMax = vMax->win[3], wMin = vMin->win[3], wMid = vMid->win[3];
623 TEXVAR_LOOP(
624 GLfloat eMaj_ds = vMax->attrib[attr][0] * wMax - vMin->attrib[attr][0] * wMin;
625 GLfloat eBot_ds = vMid->attrib[attr][0] * wMid - vMin->attrib[attr][0] * wMin;
626 GLfloat eMaj_dt = vMax->attrib[attr][1] * wMax - vMin->attrib[attr][1] * wMin;
627 GLfloat eBot_dt = vMid->attrib[attr][1] * wMid - vMin->attrib[attr][1] * wMin;
628 GLfloat eMaj_du = vMax->attrib[attr][2] * wMax - vMin->attrib[attr][2] * wMin;
629 GLfloat eBot_du = vMid->attrib[attr][2] * wMid - vMin->attrib[attr][2] * wMin;
630 GLfloat eMaj_dv = vMax->attrib[attr][3] * wMax - vMin->attrib[attr][3] * wMin;
631 GLfloat eBot_dv = vMid->attrib[attr][3] * wMid - vMin->attrib[attr][3] * wMin;
632 span.attrStepX[attr][0] = oneOverArea * (eMaj_ds * eBot.dy - eMaj.dy * eBot_ds);
633 span.attrStepY[attr][0] = oneOverArea * (eMaj.dx * eBot_ds - eMaj_ds * eBot.dx);
634 span.attrStepX[attr][1] = oneOverArea * (eMaj_dt * eBot.dy - eMaj.dy * eBot_dt);
635 span.attrStepY[attr][1] = oneOverArea * (eMaj.dx * eBot_dt - eMaj_dt * eBot.dx);
636 span.attrStepX[attr][2] = oneOverArea * (eMaj_du * eBot.dy - eMaj.dy * eBot_du);
637 span.attrStepY[attr][2] = oneOverArea * (eMaj.dx * eBot_du - eMaj_du * eBot.dx);
638 span.attrStepX[attr][3] = oneOverArea * (eMaj_dv * eBot.dy - eMaj.dy * eBot_dv);
639 span.attrStepY[attr][3] = oneOverArea * (eMaj.dx * eBot_dv - eMaj_dv * eBot.dx);
640 )
641 }
642 #endif
643
644 /*
645 * We always sample at pixel centers. However, we avoid
646 * explicit half-pixel offsets in this code by incorporating
647 * the proper offset in each of x and y during the
648 * transformation to window coordinates.
649 *
650 * We also apply the usual rasterization rules to prevent
651 * cracks and overlaps. A pixel is considered inside a
652 * subtriangle if it meets all of four conditions: it is on or
653 * to the right of the left edge, strictly to the left of the
654 * right edge, on or below the top edge, and strictly above
655 * the bottom edge. (Some edges may be degenerate.)
656 *
657 * The following discussion assumes left-to-right scanning
658 * (that is, the major edge is on the left); the right-to-left
659 * case is a straightforward variation.
660 *
661 * We start by finding the half-integral y coordinate that is
662 * at or below the top of the triangle. This gives us the
663 * first scan line that could possibly contain pixels that are
664 * inside the triangle.
665 *
666 * Next we creep down the major edge until we reach that y,
667 * and compute the corresponding x coordinate on the edge.
668 * Then we find the half-integral x that lies on or just
669 * inside the edge. This is the first pixel that might lie in
670 * the interior of the triangle. (We won't know for sure
671 * until we check the other edges.)
672 *
673 * As we rasterize the triangle, we'll step down the major
674 * edge. For each step in y, we'll move an integer number
675 * of steps in x. There are two possible x step sizes, which
676 * we'll call the ``inner'' step (guaranteed to land on the
677 * edge or inside it) and the ``outer'' step (guaranteed to
678 * land on the edge or outside it). The inner and outer steps
679 * differ by one. During rasterization we maintain an error
680 * term that indicates our distance from the true edge, and
681 * select either the inner step or the outer step, whichever
682 * gets us to the first pixel that falls inside the triangle.
683 *
684 * All parameters (z, red, etc.) as well as the buffer
685 * addresses for color and z have inner and outer step values,
686 * so that we can increment them appropriately. This method
687 * eliminates the need to adjust parameters by creeping a
688 * sub-pixel amount into the triangle at each scanline.
689 */
690
691 {
692 GLint subTriangle;
693 GLinterp fxLeftEdge = 0, fxRightEdge = 0;
694 GLinterp fdxLeftEdge = 0, fdxRightEdge = 0;
695 GLinterp fError = 0, fdError = 0;
696 #ifdef PIXEL_ADDRESS
697 PIXEL_TYPE *pRow = NULL;
698 GLint dPRowOuter = 0, dPRowInner; /* offset in bytes */
699 #endif
700 #ifdef INTERP_Z
701 # ifdef DEPTH_TYPE
702 struct gl_renderbuffer *zrb
703 = ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
704 DEPTH_TYPE *zRow = NULL;
705 GLint dZRowOuter = 0, dZRowInner; /* offset in bytes */
706 # endif
707 GLuint zLeft = 0;
708 GLfixed fdzOuter = 0, fdzInner;
709 #endif
710 #ifdef INTERP_W
711 GLfloat wLeft = 0, dwOuter = 0, dwInner;
712 #endif
713 #ifdef INTERP_FOG
714 GLfloat fogLeft = 0, dfogOuter = 0, dfogInner;
715 #endif
716 #ifdef INTERP_RGB
717 ColorTemp rLeft = 0, fdrOuter = 0, fdrInner;
718 ColorTemp gLeft = 0, fdgOuter = 0, fdgInner;
719 ColorTemp bLeft = 0, fdbOuter = 0, fdbInner;
720 #endif
721 #ifdef INTERP_ALPHA
722 ColorTemp aLeft = 0, fdaOuter = 0, fdaInner;
723 #endif
724 #ifdef INTERP_SPEC
725 ColorTemp srLeft=0, dsrOuter=0, dsrInner;
726 ColorTemp sgLeft=0, dsgOuter=0, dsgInner;
727 ColorTemp sbLeft=0, dsbOuter=0, dsbInner;
728 #endif
729 #ifdef INTERP_INDEX
730 GLfixed iLeft=0, diOuter=0, diInner;
731 #endif
732 #ifdef INTERP_INT_TEX
733 GLfixed sLeft=0, dsOuter=0, dsInner;
734 GLfixed tLeft=0, dtOuter=0, dtInner;
735 #endif
736 #ifdef INTERP_TEX
737 GLfloat sLeft[FRAG_ATTRIB_MAX];
738 GLfloat tLeft[FRAG_ATTRIB_MAX];
739 GLfloat uLeft[FRAG_ATTRIB_MAX];
740 GLfloat vLeft[FRAG_ATTRIB_MAX];
741 GLfloat dsOuter[FRAG_ATTRIB_MAX], dsInner[FRAG_ATTRIB_MAX];
742 GLfloat dtOuter[FRAG_ATTRIB_MAX], dtInner[FRAG_ATTRIB_MAX];
743 GLfloat duOuter[FRAG_ATTRIB_MAX], duInner[FRAG_ATTRIB_MAX];
744 GLfloat dvOuter[FRAG_ATTRIB_MAX], dvInner[FRAG_ATTRIB_MAX];
745 #endif
746
747 for (subTriangle=0; subTriangle<=1; subTriangle++) {
748 EdgeT *eLeft, *eRight;
749 int setupLeft, setupRight;
750 int lines;
751
752 if (subTriangle==0) {
753 /* bottom half */
754 if (scan_from_left_to_right) {
755 eLeft = &eMaj;
756 eRight = &eBot;
757 lines = eRight->lines;
758 setupLeft = 1;
759 setupRight = 1;
760 }
761 else {
762 eLeft = &eBot;
763 eRight = &eMaj;
764 lines = eLeft->lines;
765 setupLeft = 1;
766 setupRight = 1;
767 }
768 }
769 else {
770 /* top half */
771 if (scan_from_left_to_right) {
772 eLeft = &eMaj;
773 eRight = &eTop;
774 lines = eRight->lines;
775 setupLeft = 0;
776 setupRight = 1;
777 }
778 else {
779 eLeft = &eTop;
780 eRight = &eMaj;
781 lines = eLeft->lines;
782 setupLeft = 1;
783 setupRight = 0;
784 }
785 if (lines == 0)
786 return;
787 }
788
789 if (setupLeft && eLeft->lines > 0) {
790 const SWvertex *vLower = eLeft->v0;
791 #if TRIANGLE_WALK_DOUBLE
792 const GLdouble fsy = eLeft->fsy;
793 const GLdouble fsx = eLeft->fsx;
794 const GLdouble fx = CEILF(fsx);
795 const GLdouble adjx = (fx - eLeft->fx0) * FIXED_SCALE; /* SCALED! */
796 #else
797 const GLfixed fsy = eLeft->fsy;
798 const GLfixed fsx = eLeft->fsx; /* no fractional part */
799 const GLfixed fx = FixedCeil(fsx); /* no fractional part */
800 const GLfixed adjx = (GLinterp) (fx - eLeft->fx0); /* SCALED! */
801 #endif
802 const GLinterp adjy = (GLinterp) eLeft->adjy; /* SCALED! */
803 GLint idxOuter;
804 #if TRIANGLE_WALK_DOUBLE
805 GLdouble dxOuter;
806
807 fError = fx - fsx - 1.0;
808 fxLeftEdge = fsx;
809 fdxLeftEdge = eLeft->dxdy;
810 dxOuter = FLOORF(fdxLeftEdge);
811 fdError = dxOuter - fdxLeftEdge + 1.0;
812 idxOuter = (GLint) dxOuter;
813 span.y = (GLint) fsy;
814 #else
815 GLfloat dxOuter;
816 GLfixed fdxOuter;
817
818 fError = fx - fsx - FIXED_ONE;
819 fxLeftEdge = fsx - FIXED_EPSILON;
820 fdxLeftEdge = eLeft->fdxdy;
821 fdxOuter = FixedFloor(fdxLeftEdge - FIXED_EPSILON);
822 fdError = fdxOuter - fdxLeftEdge + FIXED_ONE;
823 idxOuter = FixedToInt(fdxOuter);
824 dxOuter = (GLfloat) idxOuter;
825 span.y = FixedToInt(fsy);
826 #endif
827
828 /* silence warnings on some compilers */
829 (void) dxOuter;
830 (void) adjx;
831 (void) adjy;
832 (void) vLower;
833
834 #ifdef PIXEL_ADDRESS
835 {
836 pRow = (PIXEL_TYPE *) PIXEL_ADDRESS(InterpToInt(fxLeftEdge), span.y);
837 dPRowOuter = -((int)BYTES_PER_ROW) + idxOuter * sizeof(PIXEL_TYPE);
838 /* negative because Y=0 at bottom and increases upward */
839 }
840 #endif
841 /*
842 * Now we need the set of parameter (z, color, etc.) values at
843 * the point (fx, fsy). This gives us properly-sampled parameter
844 * values that we can step from pixel to pixel. Furthermore,
845 * although we might have intermediate results that overflow
846 * the normal parameter range when we step temporarily outside
847 * the triangle, we shouldn't overflow or underflow for any
848 * pixel that's actually inside the triangle.
849 */
850
851 #ifdef INTERP_Z
852 {
853 GLfloat z0 = vLower->win[2];
854 if (depthBits <= 16) {
855 /* interpolate fixed-pt values */
856 GLfloat tmp = (z0 * FIXED_SCALE
857 + span.attrStepX[FRAG_ATTRIB_WPOS][2] * adjx
858 + span.attrStepY[FRAG_ATTRIB_WPOS][2] * adjy) + FIXED_HALF;
859 if (tmp < MAX_GLUINT / 2)
860 zLeft = (GLfixed) tmp;
861 else
862 zLeft = MAX_GLUINT / 2;
863 fdzOuter = SignedFloatToFixed(span.attrStepY[FRAG_ATTRIB_WPOS][2] + dxOuter * span.attrStepX[FRAG_ATTRIB_WPOS][2]);
864 }
865 else {
866 /* interpolate depth values w/out scaling */
867 zLeft = (GLuint) (z0 + span.attrStepX[FRAG_ATTRIB_WPOS][2] * FixedToFloat(adjx)
868 + span.attrStepY[FRAG_ATTRIB_WPOS][2] * FixedToFloat(adjy));
869 fdzOuter = (GLint) (span.attrStepY[FRAG_ATTRIB_WPOS][2] + dxOuter * span.attrStepX[FRAG_ATTRIB_WPOS][2]);
870 }
871 # ifdef DEPTH_TYPE
872 zRow = (DEPTH_TYPE *)
873 zrb->GetPointer(ctx, zrb, InterpToInt(fxLeftEdge), span.y);
874 dZRowOuter = (ctx->DrawBuffer->Width + idxOuter) * sizeof(DEPTH_TYPE);
875 # endif
876 }
877 #endif
878 #ifdef INTERP_W
879 wLeft = vLower->win[3] + (span.attrStepX[FRAG_ATTRIB_WPOS][3] * adjx + span.attrStepY[FRAG_ATTRIB_WPOS][3] * adjy) * (1.0F/FIXED_SCALE);
880 dwOuter = span.attrStepY[FRAG_ATTRIB_WPOS][3] + dxOuter * span.attrStepX[FRAG_ATTRIB_WPOS][3];
881 #endif
882 #ifdef INTERP_FOG
883 # ifdef INTERP_W
884 fogLeft = vLower->fog * vLower->win[3] + (span.attrStepX[FRAG_ATTRIB_FOGC][0] * adjx + span.attrStepY[FRAG_ATTRIB_FOGC][0] * adjy) * (1.0F/FIXED_SCALE);
885 # else
886 fogLeft = vLower->fog + (span.attrStepX[FRAG_ATTRIB_FOGC][0] * adjx + span.attrStepY[FRAG_ATTRIB_FOGC][0] * adjy) * (1.0F/FIXED_SCALE);
887 # endif
888 dfogOuter = span.attrStepY[FRAG_ATTRIB_FOGC][0] + dxOuter * span.attrStepX[FRAG_ATTRIB_FOGC][0];
889 #endif
890 #ifdef INTERP_RGB
891 if (ctx->Light.ShadeModel == GL_SMOOTH) {
892 # if CHAN_TYPE == GL_FLOAT
893 rLeft = vLower->color[RCOMP] + (span.attrStepX[FRAG_ATTRIB_COL0][0] * adjx + span.attrStepY[FRAG_ATTRIB_COL0][0] * adjy) * (1.0F / FIXED_SCALE);
894 gLeft = vLower->color[GCOMP] + (span.attrStepX[FRAG_ATTRIB_COL0][1] * adjx + span.attrStepY[FRAG_ATTRIB_COL0][1] * adjy) * (1.0F / FIXED_SCALE);
895 bLeft = vLower->color[BCOMP] + (span.attrStepX[FRAG_ATTRIB_COL0][2] * adjx + span.attrStepY[FRAG_ATTRIB_COL0][2] * adjy) * (1.0F / FIXED_SCALE);
896 fdrOuter = span.attrStepY[FRAG_ATTRIB_COL0][0] + dxOuter * span.attrStepX[FRAG_ATTRIB_COL0][0];
897 fdgOuter = span.attrStepY[FRAG_ATTRIB_COL0][1] + dxOuter * span.attrStepX[FRAG_ATTRIB_COL0][1];
898 fdbOuter = span.attrStepY[FRAG_ATTRIB_COL0][2] + dxOuter * span.attrStepX[FRAG_ATTRIB_COL0][2];
899 # else
900 rLeft = (GLint)(ChanToFixed(vLower->color[RCOMP]) + span.attrStepX[FRAG_ATTRIB_COL0][0] * adjx + span.attrStepY[FRAG_ATTRIB_COL0][0] * adjy) + FIXED_HALF;
901 gLeft = (GLint)(ChanToFixed(vLower->color[GCOMP]) + span.attrStepX[FRAG_ATTRIB_COL0][1] * adjx + span.attrStepY[FRAG_ATTRIB_COL0][1] * adjy) + FIXED_HALF;
902 bLeft = (GLint)(ChanToFixed(vLower->color[BCOMP]) + span.attrStepX[FRAG_ATTRIB_COL0][2] * adjx + span.attrStepY[FRAG_ATTRIB_COL0][2] * adjy) + FIXED_HALF;
903 fdrOuter = SignedFloatToFixed(span.attrStepY[FRAG_ATTRIB_COL0][0] + dxOuter * span.attrStepX[FRAG_ATTRIB_COL0][0]);
904 fdgOuter = SignedFloatToFixed(span.attrStepY[FRAG_ATTRIB_COL0][1] + dxOuter * span.attrStepX[FRAG_ATTRIB_COL0][1]);
905 fdbOuter = SignedFloatToFixed(span.attrStepY[FRAG_ATTRIB_COL0][2] + dxOuter * span.attrStepX[FRAG_ATTRIB_COL0][2]);
906 # endif
907 # ifdef INTERP_ALPHA
908 # if CHAN_TYPE == GL_FLOAT
909 aLeft = vLower->color[ACOMP] + (span.attrStepX[FRAG_ATTRIB_COL0][3] * adjx + span.attrStepX[FRAG_ATTRIB_COL0][3] * adjy) * (1.0F / FIXED_SCALE);
910 fdaOuter = span.attrStepX[FRAG_ATTRIB_COL0][3] + dxOuter * span.attrStepX[FRAG_ATTRIB_COL0][3];
911 # else
912 aLeft = (GLint)(ChanToFixed(vLower->color[ACOMP]) + span.attrStepX[FRAG_ATTRIB_COL0][3] * adjx + span.attrStepX[FRAG_ATTRIB_COL0][3] * adjy) + FIXED_HALF;
913 fdaOuter = SignedFloatToFixed(span.attrStepX[FRAG_ATTRIB_COL0][3] + dxOuter * span.attrStepX[FRAG_ATTRIB_COL0][3]);
914 # endif
915 # endif
916 }
917 else {
918 ASSERT(ctx->Light.ShadeModel == GL_FLAT);
919 # if CHAN_TYPE == GL_FLOAT
920 rLeft = v2->color[RCOMP];
921 gLeft = v2->color[GCOMP];
922 bLeft = v2->color[BCOMP];
923 fdrOuter = fdgOuter = fdbOuter = 0.0F;
924 # else
925 rLeft = ChanToFixed(v2->color[RCOMP]);
926 gLeft = ChanToFixed(v2->color[GCOMP]);
927 bLeft = ChanToFixed(v2->color[BCOMP]);
928 fdrOuter = fdgOuter = fdbOuter = 0;
929 # endif
930 # ifdef INTERP_ALPHA
931 # if CHAN_TYPE == GL_FLOAT
932 aLeft = v2->color[ACOMP];
933 fdaOuter = 0.0F;
934 # else
935 aLeft = ChanToFixed(v2->color[ACOMP]);
936 fdaOuter = 0;
937 # endif
938 # endif
939 }
940 #endif /* INTERP_RGB */
941
942
943 #ifdef INTERP_SPEC
944 if (ctx->Light.ShadeModel == GL_SMOOTH) {
945 # if CHAN_TYPE == GL_FLOAT
946 srLeft = vLower->specular[RCOMP] + (span.attrStepX[FRAG_ATTRIB_COL1][0] * adjx + span.attrStepY[FRAG_ATTRIB_COL1][0] * adjy) * (1.0F / FIXED_SCALE);
947 sgLeft = vLower->specular[GCOMP] + (span.attrStepX[FRAG_ATTRIB_COL1][1] * adjx + span.attrStepY[FRAG_ATTRIB_COL1][1] * adjy) * (1.0F / FIXED_SCALE);
948 sbLeft = vLower->specular[BCOMP] + (span.attrStepX[FRAG_ATTRIB_COL1][2] * adjx + span.attrStepY[FRAG_ATTRIB_COL1][2] * adjy) * (1.0F / FIXED_SCALE);
949 dsrOuter = span.attrStepY[FRAG_ATTRIB_COL1][0] + dxOuter * span.attrStepX[FRAG_ATTRIB_COL1][0];
950 dsgOuter = span.attrStepY[FRAG_ATTRIB_COL1][1] + dxOuter * span.attrStepX[FRAG_ATTRIB_COL1][1];
951 dsbOuter = span.attrStepY[FRAG_ATTRIB_COL1][2] + dxOuter * span.attrStepX[FRAG_ATTRIB_COL1][2];
952 # else
953 srLeft = (GLfixed) (ChanToFixed(vLower->specular[RCOMP]) + span.attrStepX[FRAG_ATTRIB_COL1][0] * adjx + span.attrStepY[FRAG_ATTRIB_COL1][0] * adjy) + FIXED_HALF;
954 sgLeft = (GLfixed) (ChanToFixed(vLower->specular[GCOMP]) + span.attrStepX[FRAG_ATTRIB_COL1][1] * adjx + span.attrStepY[FRAG_ATTRIB_COL1][1] * adjy) + FIXED_HALF;
955 sbLeft = (GLfixed) (ChanToFixed(vLower->specular[BCOMP]) + span.attrStepX[FRAG_ATTRIB_COL1][2] * adjx + span.attrStepY[FRAG_ATTRIB_COL1][2] * adjy) + FIXED_HALF;
956 dsrOuter = SignedFloatToFixed(span.attrStepY[FRAG_ATTRIB_COL1][0] + dxOuter * span.attrStepX[FRAG_ATTRIB_COL1][0]);
957 dsgOuter = SignedFloatToFixed(span.attrStepY[FRAG_ATTRIB_COL1][1] + dxOuter * span.attrStepX[FRAG_ATTRIB_COL1][1]);
958 dsbOuter = SignedFloatToFixed(span.attrStepY[FRAG_ATTRIB_COL1][2] + dxOuter * span.attrStepX[FRAG_ATTRIB_COL1][2]);
959 # endif
960 }
961 else {
962 ASSERT(ctx->Light.ShadeModel == GL_FLAT);
963 #if CHAN_TYPE == GL_FLOAT
964 srLeft = v2->specular[RCOMP];
965 sgLeft = v2->specular[GCOMP];
966 sbLeft = v2->specular[BCOMP];
967 dsrOuter = dsgOuter = dsbOuter = 0.0F;
968 # else
969 srLeft = ChanToFixed(v2->specular[RCOMP]);
970 sgLeft = ChanToFixed(v2->specular[GCOMP]);
971 sbLeft = ChanToFixed(v2->specular[BCOMP]);
972 dsrOuter = dsgOuter = dsbOuter = 0;
973 # endif
974 }
975 #endif
976
977 #ifdef INTERP_INDEX
978 if (ctx->Light.ShadeModel == GL_SMOOTH) {
979 iLeft = (GLfixed)(vLower->index * FIXED_SCALE
980 + didx * adjx + didy * adjy) + FIXED_HALF;
981 diOuter = SignedFloatToFixed(didy + dxOuter * didx);
982 }
983 else {
984 ASSERT(ctx->Light.ShadeModel == GL_FLAT);
985 iLeft = FloatToFixed(v2->index);
986 diOuter = 0;
987 }
988 #endif
989 #ifdef INTERP_INT_TEX
990 {
991 GLfloat s0, t0;
992 s0 = vLower->attrib[FRAG_ATTRIB_TEX0][0] * S_SCALE;
993 sLeft = (GLfixed)(s0 * FIXED_SCALE + span.attrStepX[FRAG_ATTRIB_TEX0][0] * adjx
994 + span.attrStepY[FRAG_ATTRIB_TEX0][0] * adjy) + FIXED_HALF;
995 dsOuter = SignedFloatToFixed(span.attrStepY[FRAG_ATTRIB_TEX0][0] + dxOuter * span.attrStepX[FRAG_ATTRIB_TEX0][0]);
996
997 t0 = vLower->attrib[FRAG_ATTRIB_TEX0][1] * T_SCALE;
998 tLeft = (GLfixed)(t0 * FIXED_SCALE + span.attrStepX[FRAG_ATTRIB_TEX0][1] * adjx
999 + span.attrStepY[FRAG_ATTRIB_TEX0][1] * adjy) + FIXED_HALF;
1000 dtOuter = SignedFloatToFixed(span.attrStepY[FRAG_ATTRIB_TEX0][1] + dxOuter * span.attrStepX[FRAG_ATTRIB_TEX0][1]);
1001 }
1002 #endif
1003 #ifdef INTERP_TEX
1004 TEXVAR_LOOP(
1005 const GLfloat invW = vLower->win[3];
1006 const GLfloat s0 = vLower->attrib[attr][0] * invW;
1007 const GLfloat t0 = vLower->attrib[attr][1] * invW;
1008 const GLfloat u0 = vLower->attrib[attr][2] * invW;
1009 const GLfloat v0 = vLower->attrib[attr][3] * invW;
1010 sLeft[attr] = s0 + (span.attrStepX[attr][0] * adjx + span.attrStepY[attr][0] * adjy) * (1.0F/FIXED_SCALE);
1011 tLeft[attr] = t0 + (span.attrStepX[attr][1] * adjx + span.attrStepY[attr][1] * adjy) * (1.0F/FIXED_SCALE);
1012 uLeft[attr] = u0 + (span.attrStepX[attr][2] * adjx + span.attrStepY[attr][2] * adjy) * (1.0F/FIXED_SCALE);
1013 vLeft[attr] = v0 + (span.attrStepX[attr][3] * adjx + span.attrStepY[attr][3] * adjy) * (1.0F/FIXED_SCALE);
1014 dsOuter[attr] = span.attrStepY[attr][0] + dxOuter * span.attrStepX[attr][0];
1015 dtOuter[attr] = span.attrStepY[attr][1] + dxOuter * span.attrStepX[attr][1];
1016 duOuter[attr] = span.attrStepY[attr][2] + dxOuter * span.attrStepX[attr][2];
1017 dvOuter[attr] = span.attrStepY[attr][3] + dxOuter * span.attrStepX[attr][3];
1018 )
1019 #endif
1020 } /*if setupLeft*/
1021
1022
1023 if (setupRight && eRight->lines>0) {
1024 #if TRIANGLE_WALK_DOUBLE
1025 fxRightEdge = eRight->fsx;
1026 fdxRightEdge = eRight->dxdy;
1027 #else
1028 fxRightEdge = eRight->fsx - FIXED_EPSILON;
1029 fdxRightEdge = eRight->fdxdy;
1030 #endif
1031 }
1032
1033 if (lines==0) {
1034 continue;
1035 }
1036
1037
1038 /* Rasterize setup */
1039 #ifdef PIXEL_ADDRESS
1040 dPRowInner = dPRowOuter + sizeof(PIXEL_TYPE);
1041 #endif
1042 #ifdef INTERP_Z
1043 # ifdef DEPTH_TYPE
1044 dZRowInner = dZRowOuter + sizeof(DEPTH_TYPE);
1045 # endif
1046 fdzInner = fdzOuter + span.zStep;
1047 #endif
1048 #ifdef INTERP_W
1049 dwInner = dwOuter + span.attrStepX[FRAG_ATTRIB_WPOS][3];
1050 #endif
1051 #ifdef INTERP_FOG
1052 dfogInner = dfogOuter + span.attrStepX[FRAG_ATTRIB_FOGC][0];
1053 #endif
1054 #ifdef INTERP_RGB
1055 fdrInner = fdrOuter + span.redStep;
1056 fdgInner = fdgOuter + span.greenStep;
1057 fdbInner = fdbOuter + span.blueStep;
1058 #endif
1059 #ifdef INTERP_ALPHA
1060 fdaInner = fdaOuter + span.alphaStep;
1061 #endif
1062 #ifdef INTERP_SPEC
1063 dsrInner = dsrOuter + span.specRedStep;
1064 dsgInner = dsgOuter + span.specGreenStep;
1065 dsbInner = dsbOuter + span.specBlueStep;
1066 #endif
1067 #ifdef INTERP_INDEX
1068 diInner = diOuter + span.indexStep;
1069 #endif
1070 #ifdef INTERP_INT_TEX
1071 dsInner = dsOuter + span.intTexStep[0];
1072 dtInner = dtOuter + span.intTexStep[1];
1073 #endif
1074 #ifdef INTERP_TEX
1075 TEXVAR_LOOP(
1076 dsInner[attr] = dsOuter[attr] + span.attrStepX[attr][0];
1077 dtInner[attr] = dtOuter[attr] + span.attrStepX[attr][1];
1078 duInner[attr] = duOuter[attr] + span.attrStepX[attr][2];
1079 dvInner[attr] = dvOuter[attr] + span.attrStepX[attr][3];
1080 )
1081 #endif
1082
1083 while (lines > 0) {
1084 /* initialize the span interpolants to the leftmost value */
1085 /* ff = fixed-pt fragment */
1086 const GLint right = InterpToInt(fxRightEdge);
1087 span.x = InterpToInt(fxLeftEdge);
1088 if (right <= span.x)
1089 span.end = 0;
1090 else
1091 span.end = right - span.x;
1092
1093 #ifdef INTERP_Z
1094 span.z = zLeft;
1095 #endif
1096 #ifdef INTERP_W
1097 span.attrStart[FRAG_ATTRIB_WPOS][3] = wLeft;
1098 #endif
1099 #ifdef INTERP_FOG
1100 span.attrStart[FRAG_ATTRIB_FOGC][0] = fogLeft;
1101 #endif
1102 #ifdef INTERP_RGB
1103 span.red = rLeft;
1104 span.green = gLeft;
1105 span.blue = bLeft;
1106 #endif
1107 #ifdef INTERP_ALPHA
1108 span.alpha = aLeft;
1109 #endif
1110 #ifdef INTERP_SPEC
1111 span.specRed = srLeft;
1112 span.specGreen = sgLeft;
1113 span.specBlue = sbLeft;
1114 #endif
1115 #ifdef INTERP_INDEX
1116 span.index = iLeft;
1117 #endif
1118 #ifdef INTERP_INT_TEX
1119 span.intTex[0] = sLeft;
1120 span.intTex[1] = tLeft;
1121 #endif
1122
1123 #ifdef INTERP_TEX
1124 TEXVAR_LOOP(
1125 span.attrStart[attr][0] = sLeft[attr];
1126 span.attrStart[attr][1] = tLeft[attr];
1127 span.attrStart[attr][2] = uLeft[attr];
1128 span.attrStart[attr][3] = vLeft[attr];
1129 )
1130 #endif
1131
1132 /* This is where we actually generate fragments */
1133 /* XXX the test for span.y > 0 _shouldn't_ be needed but
1134 * it fixes a problem on 64-bit Opterons (bug 4842).
1135 */
1136 if (span.end > 0 && span.y >= 0) {
1137 const GLint len = span.end - 1;
1138 (void) len;
1139 #ifdef INTERP_RGB
1140 CLAMP_INTERPOLANT(red, redStep, len);
1141 CLAMP_INTERPOLANT(green, greenStep, len);
1142 CLAMP_INTERPOLANT(blue, blueStep, len);
1143 #endif
1144 #ifdef INTERP_ALPHA
1145 CLAMP_INTERPOLANT(alpha, alphaStep, len);
1146 #endif
1147 #ifdef INTERP_SPEC
1148 CLAMP_INTERPOLANT(specRed, specRedStep, len);
1149 CLAMP_INTERPOLANT(specGreen, specGreenStep, len);
1150 CLAMP_INTERPOLANT(specBlue, specBlueStep, len);
1151 #endif
1152 #ifdef INTERP_INDEX
1153 CLAMP_INTERPOLANT(index, indexStep, len);
1154 #endif
1155 {
1156 RENDER_SPAN( span );
1157 }
1158 }
1159
1160 /*
1161 * Advance to the next scan line. Compute the
1162 * new edge coordinates, and adjust the
1163 * pixel-center x coordinate so that it stays
1164 * on or inside the major edge.
1165 */
1166 span.y++;
1167 lines--;
1168
1169 fxLeftEdge += fdxLeftEdge;
1170 fxRightEdge += fdxRightEdge;
1171
1172 fError += fdError;
1173 if (fError >= 0) {
1174 fError -= INTERP_ONE;
1175
1176 #ifdef PIXEL_ADDRESS
1177 pRow = (PIXEL_TYPE *) ((GLubyte *) pRow + dPRowOuter);
1178 #endif
1179 #ifdef INTERP_Z
1180 # ifdef DEPTH_TYPE
1181 zRow = (DEPTH_TYPE *) ((GLubyte *) zRow + dZRowOuter);
1182 # endif
1183 zLeft += fdzOuter;
1184 #endif
1185 #ifdef INTERP_W
1186 wLeft += dwOuter;
1187 #endif
1188 #ifdef INTERP_FOG
1189 fogLeft += dfogOuter;
1190 #endif
1191 #ifdef INTERP_RGB
1192 rLeft += fdrOuter;
1193 gLeft += fdgOuter;
1194 bLeft += fdbOuter;
1195 #endif
1196 #ifdef INTERP_ALPHA
1197 aLeft += fdaOuter;
1198 #endif
1199 #ifdef INTERP_SPEC
1200 srLeft += dsrOuter;
1201 sgLeft += dsgOuter;
1202 sbLeft += dsbOuter;
1203 #endif
1204 #ifdef INTERP_INDEX
1205 iLeft += diOuter;
1206 #endif
1207 #ifdef INTERP_INT_TEX
1208 sLeft += dsOuter;
1209 tLeft += dtOuter;
1210 #endif
1211 #ifdef INTERP_TEX
1212 TEXVAR_LOOP(
1213 sLeft[attr] += dsOuter[attr];
1214 tLeft[attr] += dtOuter[attr];
1215 uLeft[attr] += duOuter[attr];
1216 vLeft[attr] += dvOuter[attr];
1217 )
1218 #endif
1219 }
1220 else {
1221 #ifdef PIXEL_ADDRESS
1222 pRow = (PIXEL_TYPE *) ((GLubyte *) pRow + dPRowInner);
1223 #endif
1224 #ifdef INTERP_Z
1225 # ifdef DEPTH_TYPE
1226 zRow = (DEPTH_TYPE *) ((GLubyte *) zRow + dZRowInner);
1227 # endif
1228 zLeft += fdzInner;
1229 #endif
1230 #ifdef INTERP_W
1231 wLeft += dwInner;
1232 #endif
1233 #ifdef INTERP_FOG
1234 fogLeft += dfogInner;
1235 #endif
1236 #ifdef INTERP_RGB
1237 rLeft += fdrInner;
1238 gLeft += fdgInner;
1239 bLeft += fdbInner;
1240 #endif
1241 #ifdef INTERP_ALPHA
1242 aLeft += fdaInner;
1243 #endif
1244 #ifdef INTERP_SPEC
1245 srLeft += dsrInner;
1246 sgLeft += dsgInner;
1247 sbLeft += dsbInner;
1248 #endif
1249 #ifdef INTERP_INDEX
1250 iLeft += diInner;
1251 #endif
1252 #ifdef INTERP_INT_TEX
1253 sLeft += dsInner;
1254 tLeft += dtInner;
1255 #endif
1256 #ifdef INTERP_TEX
1257 TEXVAR_LOOP(
1258 sLeft[attr] += dsInner[attr];
1259 tLeft[attr] += dtInner[attr];
1260 uLeft[attr] += duInner[attr];
1261 vLeft[attr] += dvInner[attr];
1262 )
1263 #endif
1264 }
1265 } /*while lines>0*/
1266
1267 } /* for subTriangle */
1268
1269 }
1270 #ifdef CLEANUP_CODE
1271 CLEANUP_CODE
1272 #endif
1273 }
1274 }
1275
1276 #undef SETUP_CODE
1277 #undef CLEANUP_CODE
1278 #undef RENDER_SPAN
1279
1280 #undef PIXEL_TYPE
1281 #undef BYTES_PER_ROW
1282 #undef PIXEL_ADDRESS
1283 #undef DEPTH_TYPE
1284
1285 #undef INTERP_Z
1286 #undef INTERP_W
1287 #undef INTERP_FOG
1288 #undef INTERP_RGB
1289 #undef INTERP_ALPHA
1290 #undef INTERP_SPEC
1291 #undef INTERP_INDEX
1292 #undef INTERP_INT_TEX
1293 #undef INTERP_TEX
1294 #undef TEX_UNIT_LOOP
1295 #undef VARYING_LOOP
1296
1297 #undef S_SCALE
1298 #undef T_SCALE
1299
1300 #undef FixedToDepth
1301 #undef ColorTemp
1302 #undef GLinterp
1303 #undef InterpToInt
1304 #undef INTERP_ONE
1305
1306 #undef NAME