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