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