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