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