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