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