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