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