s_aatritemp.h revision dd34fe8679fa200e55cfaf8e80bbecdecea084e3
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/* 27 * Antialiased Triangle Rasterizer Template 28 * 29 * This file is #include'd to generate custom AA triangle rasterizers. 30 * NOTE: this code hasn't been optimized yet. That'll come after it 31 * works correctly. 32 * 33 * The following macros may be defined to indicate what auxillary information 34 * must be copmuted across the triangle: 35 * DO_Z - if defined, compute Z values 36 * DO_RGBA - if defined, compute RGBA values 37 * DO_INDEX - if defined, compute color index values 38 * DO_SPEC - if defined, compute specular RGB values 39 * DO_TEXVAR - if defined, compute texcoords, varying 40 */ 41 42/*void triangle( GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint pv )*/ 43{ 44 const SWcontext *swrast = SWRAST_CONTEXT(ctx); 45 const GLfloat *p0 = v0->win; 46 const GLfloat *p1 = v1->win; 47 const GLfloat *p2 = v2->win; 48 const SWvertex *vMin, *vMid, *vMax; 49 GLint iyMin, iyMax; 50 GLfloat yMin, yMax; 51 GLboolean ltor; 52 GLfloat majDx, majDy; /* major (i.e. long) edge dx and dy */ 53 54 SWspan span; 55 56#ifdef DO_Z 57 GLfloat zPlane[4]; 58#endif 59#ifdef DO_FOG 60 GLfloat fogPlane[4]; 61#else 62 GLfloat *fog = NULL; 63#endif 64#ifdef DO_RGBA 65 GLfloat rPlane[4], gPlane[4], bPlane[4], aPlane[4]; 66#endif 67#ifdef DO_INDEX 68 GLfloat iPlane[4]; 69#endif 70#ifdef DO_SPEC 71 GLfloat srPlane[4], sgPlane[4], sbPlane[4]; 72#endif 73#if defined(DO_TEXVAR) 74 GLfloat sPlane[FRAG_ATTRIB_MAX][4]; /* texture S */ 75 GLfloat tPlane[FRAG_ATTRIB_MAX][4]; /* texture T */ 76 GLfloat uPlane[FRAG_ATTRIB_MAX][4]; /* texture R */ 77 GLfloat vPlane[FRAG_ATTRIB_MAX][4]; /* texture Q */ 78 GLfloat texWidth[FRAG_ATTRIB_MAX]; 79 GLfloat texHeight[FRAG_ATTRIB_MAX]; 80#endif 81 GLfloat bf = SWRAST_CONTEXT(ctx)->_BackfaceSign; 82 83 (void) swrast; 84 85 INIT_SPAN(span, GL_POLYGON, 0, 0, SPAN_COVERAGE); 86 87 /* determine bottom to top order of vertices */ 88 { 89 GLfloat y0 = v0->win[1]; 90 GLfloat y1 = v1->win[1]; 91 GLfloat y2 = v2->win[1]; 92 if (y0 <= y1) { 93 if (y1 <= y2) { 94 vMin = v0; vMid = v1; vMax = v2; /* y0<=y1<=y2 */ 95 } 96 else if (y2 <= y0) { 97 vMin = v2; vMid = v0; vMax = v1; /* y2<=y0<=y1 */ 98 } 99 else { 100 vMin = v0; vMid = v2; vMax = v1; bf = -bf; /* y0<=y2<=y1 */ 101 } 102 } 103 else { 104 if (y0 <= y2) { 105 vMin = v1; vMid = v0; vMax = v2; bf = -bf; /* y1<=y0<=y2 */ 106 } 107 else if (y2 <= y1) { 108 vMin = v2; vMid = v1; vMax = v0; bf = -bf; /* y2<=y1<=y0 */ 109 } 110 else { 111 vMin = v1; vMid = v2; vMax = v0; /* y1<=y2<=y0 */ 112 } 113 } 114 } 115 116 majDx = vMax->win[0] - vMin->win[0]; 117 majDy = vMax->win[1] - vMin->win[1]; 118 119 { 120 const GLfloat botDx = vMid->win[0] - vMin->win[0]; 121 const GLfloat botDy = vMid->win[1] - vMin->win[1]; 122 const GLfloat area = majDx * botDy - botDx * majDy; 123 /* Do backface culling */ 124 if (area * bf < 0 || area == 0 || IS_INF_OR_NAN(area)) 125 return; 126 ltor = (GLboolean) (area < 0.0F); 127 } 128 129 /* Plane equation setup: 130 * We evaluate plane equations at window (x,y) coordinates in order 131 * to compute color, Z, fog, texcoords, etc. This isn't terribly 132 * efficient but it's easy and reliable. 133 */ 134#ifdef DO_Z 135 compute_plane(p0, p1, p2, p0[2], p1[2], p2[2], zPlane); 136 span.arrayMask |= SPAN_Z; 137#endif 138#ifdef DO_FOG 139 compute_plane(p0, p1, p2, v0->fog, v1->fog, v2->fog, fogPlane); 140 span.arrayMask |= SPAN_FOG; 141#endif 142#ifdef DO_RGBA 143 if (ctx->Light.ShadeModel == GL_SMOOTH) { 144 compute_plane(p0, p1, p2, v0->color[RCOMP], v1->color[RCOMP], v2->color[RCOMP], rPlane); 145 compute_plane(p0, p1, p2, v0->color[GCOMP], v1->color[GCOMP], v2->color[GCOMP], gPlane); 146 compute_plane(p0, p1, p2, v0->color[BCOMP], v1->color[BCOMP], v2->color[BCOMP], bPlane); 147 compute_plane(p0, p1, p2, v0->color[ACOMP], v1->color[ACOMP], v2->color[ACOMP], aPlane); 148 } 149 else { 150 constant_plane(v2->color[RCOMP], rPlane); 151 constant_plane(v2->color[GCOMP], gPlane); 152 constant_plane(v2->color[BCOMP], bPlane); 153 constant_plane(v2->color[ACOMP], aPlane); 154 } 155 span.arrayMask |= SPAN_RGBA; 156#endif 157#ifdef DO_INDEX 158 if (ctx->Light.ShadeModel == GL_SMOOTH) { 159 compute_plane(p0, p1, p2, (GLfloat) v0->index, 160 v1->index, v2->index, iPlane); 161 } 162 else { 163 constant_plane(v2->index, iPlane); 164 } 165 span.arrayMask |= SPAN_INDEX; 166#endif 167#ifdef DO_SPEC 168 if (ctx->Light.ShadeModel == GL_SMOOTH) { 169 compute_plane(p0, p1, p2, v0->specular[RCOMP], v1->specular[RCOMP], v2->specular[RCOMP], srPlane); 170 compute_plane(p0, p1, p2, v0->specular[GCOMP], v1->specular[GCOMP], v2->specular[GCOMP], sgPlane); 171 compute_plane(p0, p1, p2, v0->specular[BCOMP], v1->specular[BCOMP], v2->specular[BCOMP], sbPlane); 172 } 173 else { 174 constant_plane(v2->specular[RCOMP], srPlane); 175 constant_plane(v2->specular[GCOMP], sgPlane); 176 constant_plane(v2->specular[BCOMP], sbPlane); 177 } 178 span.arrayMask |= SPAN_SPEC; 179#endif 180#if defined(DO_TEXVAR) 181 { 182 GLuint attr; 183 const GLfloat invW0 = v0->win[3]; 184 const GLfloat invW1 = v1->win[3]; 185 const GLfloat invW2 = v2->win[3]; 186 for (attr = swrast->_MinFragmentAttrib; attr < swrast->_MaxFragmentAttrib; attr++) { 187 if (swrast->_FragmentAttribs & (1 << attr)) { 188 const GLfloat s0 = v0->attrib[attr][0] * invW0; 189 const GLfloat s1 = v1->attrib[attr][0] * invW1; 190 const GLfloat s2 = v2->attrib[attr][0] * invW2; 191 const GLfloat t0 = v0->attrib[attr][1] * invW0; 192 const GLfloat t1 = v1->attrib[attr][1] * invW1; 193 const GLfloat t2 = v2->attrib[attr][1] * invW2; 194 const GLfloat r0 = v0->attrib[attr][2] * invW0; 195 const GLfloat r1 = v1->attrib[attr][2] * invW1; 196 const GLfloat r2 = v2->attrib[attr][2] * invW2; 197 const GLfloat q0 = v0->attrib[attr][3] * invW0; 198 const GLfloat q1 = v1->attrib[attr][3] * invW1; 199 const GLfloat q2 = v2->attrib[attr][3] * invW2; 200 compute_plane(p0, p1, p2, s0, s1, s2, sPlane[attr]); 201 compute_plane(p0, p1, p2, t0, t1, t2, tPlane[attr]); 202 compute_plane(p0, p1, p2, r0, r1, r2, uPlane[attr]); 203 compute_plane(p0, p1, p2, q0, q1, q2, vPlane[attr]); 204 if (attr < FRAG_ATTRIB_VAR0) { 205 const GLuint u = attr - FRAG_ATTRIB_TEX0; 206 const struct gl_texture_object *obj = ctx->Texture.Unit[u]._Current; 207 const struct gl_texture_image *texImage = obj->Image[0][obj->BaseLevel]; 208 texWidth[attr] = (GLfloat) texImage->Width; 209 texHeight[attr] = (GLfloat) texImage->Height; 210 } 211 else { 212 texWidth[attr] = texHeight[attr] = 1.0; 213 } 214 } 215 } 216 } 217 span.arrayMask |= (SPAN_TEXTURE | SPAN_LAMBDA | SPAN_VARYING); 218#endif 219 220 /* Begin bottom-to-top scan over the triangle. 221 * The long edge will either be on the left or right side of the 222 * triangle. We always scan from the long edge toward the shorter 223 * edges, stopping when we find that coverage = 0. If the long edge 224 * is on the left we scan left-to-right. Else, we scan right-to-left. 225 */ 226 yMin = vMin->win[1]; 227 yMax = vMax->win[1]; 228 iyMin = (GLint) yMin; 229 iyMax = (GLint) yMax + 1; 230 231 if (ltor) { 232 /* scan left to right */ 233 const GLfloat *pMin = vMin->win; 234 const GLfloat *pMid = vMid->win; 235 const GLfloat *pMax = vMax->win; 236 const GLfloat dxdy = majDx / majDy; 237 const GLfloat xAdj = dxdy < 0.0F ? -dxdy : 0.0F; 238 GLfloat x = pMin[0] - (yMin - iyMin) * dxdy; 239 GLint iy; 240 for (iy = iyMin; iy < iyMax; iy++, x += dxdy) { 241 GLint ix, startX = (GLint) (x - xAdj); 242 GLuint count; 243 GLfloat coverage = 0.0F; 244 245 /* skip over fragments with zero coverage */ 246 while (startX < MAX_WIDTH) { 247 coverage = compute_coveragef(pMin, pMid, pMax, startX, iy); 248 if (coverage > 0.0F) 249 break; 250 startX++; 251 } 252 253 /* enter interior of triangle */ 254 ix = startX; 255 count = 0; 256 while (coverage > 0.0F) { 257 /* (cx,cy) = center of fragment */ 258 const GLfloat cx = ix + 0.5F, cy = iy + 0.5F; 259 SWspanarrays *array = span.array; 260#ifdef DO_INDEX 261 array->coverage[count] = (GLfloat) compute_coveragei(pMin, pMid, pMax, ix, iy); 262#else 263 array->coverage[count] = coverage; 264#endif 265#ifdef DO_Z 266 array->z[count] = (GLuint) solve_plane(cx, cy, zPlane); 267#endif 268#ifdef DO_FOG 269 array->attribs[FRAG_ATTRIB_FOGC][count][0] = solve_plane(cx, cy, fogPlane); 270#endif 271#ifdef DO_RGBA 272 array->rgba[count][RCOMP] = solve_plane_chan(cx, cy, rPlane); 273 array->rgba[count][GCOMP] = solve_plane_chan(cx, cy, gPlane); 274 array->rgba[count][BCOMP] = solve_plane_chan(cx, cy, bPlane); 275 array->rgba[count][ACOMP] = solve_plane_chan(cx, cy, aPlane); 276#endif 277#ifdef DO_INDEX 278 array->index[count] = (GLint) solve_plane(cx, cy, iPlane); 279#endif 280#ifdef DO_SPEC 281 array->spec[count][RCOMP] = solve_plane_chan(cx, cy, srPlane); 282 array->spec[count][GCOMP] = solve_plane_chan(cx, cy, sgPlane); 283 array->spec[count][BCOMP] = solve_plane_chan(cx, cy, sbPlane); 284#endif 285#if defined(DO_TEXVAR) 286 { 287 GLuint attr; 288 for (attr = swrast->_MinFragmentAttrib; attr < swrast->_MaxFragmentAttrib; attr++) { 289 if (swrast->_FragmentAttribs & (1 << attr)) { 290 GLfloat invQ = solve_plane_recip(cx, cy, vPlane[attr]); 291 array->attribs[attr][count][0] = solve_plane(cx, cy, sPlane[attr]) * invQ; 292 array->attribs[attr][count][1] = solve_plane(cx, cy, tPlane[attr]) * invQ; 293 array->attribs[attr][count][2] = solve_plane(cx, cy, uPlane[attr]) * invQ; 294 if (attr < FRAG_ATTRIB_VAR0) { 295 const GLuint unit = attr - FRAG_ATTRIB_TEX0; 296 array->lambda[unit][count] = compute_lambda(sPlane[attr], tPlane[attr], 297 vPlane[attr], cx, cy, invQ, 298 texWidth[attr], texHeight[attr]); 299 } 300 } 301 } 302 } 303#endif 304 ix++; 305 count++; 306 coverage = compute_coveragef(pMin, pMid, pMax, ix, iy); 307 } 308 309 if (ix <= startX) 310 continue; 311 312 span.x = startX; 313 span.y = iy; 314 span.end = (GLuint) ix - (GLuint) startX; 315 ASSERT(span.interpMask == 0); 316#if defined(DO_RGBA) 317 _swrast_write_rgba_span(ctx, &span); 318#else 319 _swrast_write_index_span(ctx, &span); 320#endif 321 } 322 } 323 else { 324 /* scan right to left */ 325 const GLfloat *pMin = vMin->win; 326 const GLfloat *pMid = vMid->win; 327 const GLfloat *pMax = vMax->win; 328 const GLfloat dxdy = majDx / majDy; 329 const GLfloat xAdj = dxdy > 0 ? dxdy : 0.0F; 330 GLfloat x = pMin[0] - (yMin - iyMin) * dxdy; 331 GLint iy; 332 for (iy = iyMin; iy < iyMax; iy++, x += dxdy) { 333 GLint ix, left, startX = (GLint) (x + xAdj); 334 GLuint count, n; 335 GLfloat coverage = 0.0F; 336 337 /* make sure we're not past the window edge */ 338 if (startX >= ctx->DrawBuffer->_Xmax) { 339 startX = ctx->DrawBuffer->_Xmax - 1; 340 } 341 342 /* skip fragments with zero coverage */ 343 while (startX >= 0) { 344 coverage = compute_coveragef(pMin, pMax, pMid, startX, iy); 345 if (coverage > 0.0F) 346 break; 347 startX--; 348 } 349 350 /* enter interior of triangle */ 351 ix = startX; 352 count = 0; 353 while (coverage > 0.0F) { 354 /* (cx,cy) = center of fragment */ 355 const GLfloat cx = ix + 0.5F, cy = iy + 0.5F; 356 SWspanarrays *array = span.array; 357#ifdef DO_INDEX 358 array->coverage[ix] = (GLfloat) compute_coveragei(pMin, pMax, pMid, ix, iy); 359#else 360 array->coverage[ix] = coverage; 361#endif 362#ifdef DO_Z 363 array->z[ix] = (GLuint) solve_plane(cx, cy, zPlane); 364#endif 365#ifdef DO_FOG 366 array->attribs[FRAG_ATTRIB_FOGC][ix][0] = solve_plane(cx, cy, fogPlane); 367#endif 368#ifdef DO_RGBA 369 array->rgba[ix][RCOMP] = solve_plane_chan(cx, cy, rPlane); 370 array->rgba[ix][GCOMP] = solve_plane_chan(cx, cy, gPlane); 371 array->rgba[ix][BCOMP] = solve_plane_chan(cx, cy, bPlane); 372 array->rgba[ix][ACOMP] = solve_plane_chan(cx, cy, aPlane); 373#endif 374#ifdef DO_INDEX 375 array->index[ix] = (GLint) solve_plane(cx, cy, iPlane); 376#endif 377#ifdef DO_SPEC 378 array->spec[ix][RCOMP] = solve_plane_chan(cx, cy, srPlane); 379 array->spec[ix][GCOMP] = solve_plane_chan(cx, cy, sgPlane); 380 array->spec[ix][BCOMP] = solve_plane_chan(cx, cy, sbPlane); 381#endif 382#if defined(DO_TEXVAR) 383 { 384 GLuint attr; 385 for (attr = swrast->_MinFragmentAttrib; attr < swrast->_MaxFragmentAttrib; attr++) { 386 if (swrast->_FragmentAttribs & (1 << attr)) { 387 GLfloat invQ = solve_plane_recip(cx, cy, vPlane[attr]); 388 array->attribs[attr][ix][0] = solve_plane(cx, cy, sPlane[attr]) * invQ; 389 array->attribs[attr][ix][1] = solve_plane(cx, cy, tPlane[attr]) * invQ; 390 array->attribs[attr][ix][2] = solve_plane(cx, cy, uPlane[attr]) * invQ; 391 if (attr < FRAG_ATTRIB_VAR0) { 392 const GLuint unit = attr - FRAG_ATTRIB_TEX0; 393 array->lambda[unit][ix] = compute_lambda(sPlane[attr], 394 tPlane[attr], 395 vPlane[attr], 396 cx, cy, invQ, 397 texWidth[attr], 398 texHeight[attr]); 399 } 400 } 401 } 402 } 403#endif 404 ix--; 405 count++; 406 coverage = compute_coveragef(pMin, pMax, pMid, ix, iy); 407 } 408 409 if (startX <= ix) 410 continue; 411 412 n = (GLuint) startX - (GLuint) ix; 413 414 left = ix + 1; 415 416 /* shift all values to the left */ 417 /* XXX this is temporary */ 418 { 419 SWspanarrays *array = span.array; 420 GLint j; 421 for (j = 0; j < (GLint) n; j++) { 422#ifdef DO_RGBA 423 COPY_CHAN4(array->rgba[j], array->rgba[j + left]); 424#endif 425#ifdef DO_SPEC 426 COPY_CHAN4(array->spec[j], array->spec[j + left]); 427#endif 428#ifdef DO_INDEX 429 array->index[j] = array->index[j + left]; 430#endif 431#ifdef DO_Z 432 array->z[j] = array->z[j + left]; 433#endif 434#ifdef DO_FOG 435 array->attribs[FRAG_ATTRIB_FOGC][j][0] 436 = array->attribs[FRAG_ATTRIB_FOGC][j + left][0]; 437#endif 438#if defined(DO_TEXVAR) 439 array->lambda[0][j] = array->lambda[0][j + left]; 440#endif 441 array->coverage[j] = array->coverage[j + left]; 442 } 443 } 444#ifdef DO_TEXVAR 445 /* shift texcoords, varying */ 446 { 447 SWspanarrays *array = span.array; 448 GLuint attr; 449 for (attr = swrast->_MinFragmentAttrib; attr < swrast->_MaxFragmentAttrib; attr++) { 450 if (swrast->_FragmentAttribs & (1 << attr)) { 451 GLint j; 452 for (j = 0; j < (GLint) n; j++) { 453 array->attribs[attr][j][0] = array->attribs[attr][j + left][0]; 454 array->attribs[attr][j][1] = array->attribs[attr][j + left][1]; 455 array->attribs[attr][j][2] = array->attribs[attr][j + left][2]; 456 /*array->lambda[unit][j] = array->lambda[unit][j + left];*/ 457 } 458 } 459 } 460 } 461#endif 462 463 span.x = left; 464 span.y = iy; 465 span.end = n; 466 ASSERT(span.interpMask == 0); 467#if defined(DO_RGBA) 468 _swrast_write_rgba_span(ctx, &span); 469#else 470 _swrast_write_index_span(ctx, &span); 471#endif 472 } 473 } 474} 475 476 477#ifdef DO_Z 478#undef DO_Z 479#endif 480 481#ifdef DO_FOG 482#undef DO_FOG 483#endif 484 485#ifdef DO_RGBA 486#undef DO_RGBA 487#endif 488 489#ifdef DO_INDEX 490#undef DO_INDEX 491#endif 492 493#ifdef DO_SPEC 494#undef DO_SPEC 495#endif 496 497#ifdef DO_TEXVAR 498#undef DO_TEXVAR 499#endif 500 501#ifdef DO_OCCLUSION_TEST 502#undef DO_OCCLUSION_TEST 503#endif 504