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