s_aatritemp.h revision 7117f1b4
1/* 2 * Mesa 3-D graphics library 3 * Version: 7.0.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_ATTRIBS - if defined, compute texcoords, varying, etc. 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_ATTRIBS) 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)->_BackfaceCullSign; 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 /* front/back-face determination and cullling */ 120 { 121 const GLfloat botDx = vMid->win[0] - vMin->win[0]; 122 const GLfloat botDy = vMid->win[1] - vMin->win[1]; 123 const GLfloat area = majDx * botDy - botDx * majDy; 124 /* Do backface culling */ 125 if (area * bf < 0 || area == 0 || IS_INF_OR_NAN(area)) 126 return; 127 ltor = (GLboolean) (area < 0.0F); 128 129 span.facing = area * swrast->_BackfaceSign > 0.0F; 130 } 131 132 /* Plane equation setup: 133 * We evaluate plane equations at window (x,y) coordinates in order 134 * to compute color, Z, fog, texcoords, etc. This isn't terribly 135 * efficient but it's easy and reliable. 136 */ 137#ifdef DO_Z 138 compute_plane(p0, p1, p2, p0[2], p1[2], p2[2], zPlane); 139 span.arrayMask |= SPAN_Z; 140#endif 141#ifdef DO_FOG 142 compute_plane(p0, p1, p2, 143 v0->attrib[FRAG_ATTRIB_FOGC][0], 144 v1->attrib[FRAG_ATTRIB_FOGC][0], 145 v2->attrib[FRAG_ATTRIB_FOGC][0], 146 fogPlane); 147 span.arrayMask |= SPAN_FOG; 148#endif 149#ifdef DO_RGBA 150 if (ctx->Light.ShadeModel == GL_SMOOTH) { 151 compute_plane(p0, p1, p2, v0->color[RCOMP], v1->color[RCOMP], v2->color[RCOMP], rPlane); 152 compute_plane(p0, p1, p2, v0->color[GCOMP], v1->color[GCOMP], v2->color[GCOMP], gPlane); 153 compute_plane(p0, p1, p2, v0->color[BCOMP], v1->color[BCOMP], v2->color[BCOMP], bPlane); 154 compute_plane(p0, p1, p2, v0->color[ACOMP], v1->color[ACOMP], v2->color[ACOMP], aPlane); 155 } 156 else { 157 constant_plane(v2->color[RCOMP], rPlane); 158 constant_plane(v2->color[GCOMP], gPlane); 159 constant_plane(v2->color[BCOMP], bPlane); 160 constant_plane(v2->color[ACOMP], aPlane); 161 } 162 span.arrayMask |= SPAN_RGBA; 163#endif 164#ifdef DO_INDEX 165 if (ctx->Light.ShadeModel == GL_SMOOTH) { 166 compute_plane(p0, p1, p2, (GLfloat) v0->index, 167 v1->index, v2->index, iPlane); 168 } 169 else { 170 constant_plane(v2->index, iPlane); 171 } 172 span.arrayMask |= SPAN_INDEX; 173#endif 174#ifdef DO_SPEC 175 if (ctx->Light.ShadeModel == GL_SMOOTH) { 176 compute_plane(p0, p1, p2, v0->specular[RCOMP], v1->specular[RCOMP], v2->specular[RCOMP], srPlane); 177 compute_plane(p0, p1, p2, v0->specular[GCOMP], v1->specular[GCOMP], v2->specular[GCOMP], sgPlane); 178 compute_plane(p0, p1, p2, v0->specular[BCOMP], v1->specular[BCOMP], v2->specular[BCOMP], sbPlane); 179 } 180 else { 181 constant_plane(v2->specular[RCOMP], srPlane); 182 constant_plane(v2->specular[GCOMP], sgPlane); 183 constant_plane(v2->specular[BCOMP], sbPlane); 184 } 185 span.arrayMask |= SPAN_SPEC; 186#endif 187#if defined(DO_ATTRIBS) 188 { 189 const GLfloat invW0 = v0->win[3]; 190 const GLfloat invW1 = v1->win[3]; 191 const GLfloat invW2 = v2->win[3]; 192 ATTRIB_LOOP_BEGIN 193 const GLfloat s0 = v0->attrib[attr][0] * invW0; 194 const GLfloat s1 = v1->attrib[attr][0] * invW1; 195 const GLfloat s2 = v2->attrib[attr][0] * invW2; 196 const GLfloat t0 = v0->attrib[attr][1] * invW0; 197 const GLfloat t1 = v1->attrib[attr][1] * invW1; 198 const GLfloat t2 = v2->attrib[attr][1] * invW2; 199 const GLfloat r0 = v0->attrib[attr][2] * invW0; 200 const GLfloat r1 = v1->attrib[attr][2] * invW1; 201 const GLfloat r2 = v2->attrib[attr][2] * invW2; 202 const GLfloat q0 = v0->attrib[attr][3] * invW0; 203 const GLfloat q1 = v1->attrib[attr][3] * invW1; 204 const GLfloat q2 = v2->attrib[attr][3] * invW2; 205 compute_plane(p0, p1, p2, s0, s1, s2, sPlane[attr]); 206 compute_plane(p0, p1, p2, t0, t1, t2, tPlane[attr]); 207 compute_plane(p0, p1, p2, r0, r1, r2, uPlane[attr]); 208 compute_plane(p0, p1, p2, q0, q1, q2, vPlane[attr]); 209 if (attr < FRAG_ATTRIB_VAR0 && attr >= FRAG_ATTRIB_TEX0) { 210 const GLuint u = attr - FRAG_ATTRIB_TEX0; 211 const struct gl_texture_object *obj = ctx->Texture.Unit[u]._Current; 212 const struct gl_texture_image *texImage = obj->Image[0][obj->BaseLevel]; 213 texWidth[attr] = (GLfloat) texImage->Width; 214 texHeight[attr] = (GLfloat) texImage->Height; 215 } 216 else { 217 texWidth[attr] = texHeight[attr] = 1.0; 218 } 219 ATTRIB_LOOP_END 220 } 221 span.arrayMask |= (SPAN_TEXTURE | SPAN_LAMBDA | SPAN_VARYING); 222#endif 223 224 /* Begin bottom-to-top scan over the triangle. 225 * The long edge will either be on the left or right side of the 226 * triangle. We always scan from the long edge toward the shorter 227 * edges, stopping when we find that coverage = 0. If the long edge 228 * is on the left we scan left-to-right. Else, we scan right-to-left. 229 */ 230 yMin = vMin->win[1]; 231 yMax = vMax->win[1]; 232 iyMin = (GLint) yMin; 233 iyMax = (GLint) yMax + 1; 234 235 if (ltor) { 236 /* scan left to right */ 237 const GLfloat *pMin = vMin->win; 238 const GLfloat *pMid = vMid->win; 239 const GLfloat *pMax = vMax->win; 240 const GLfloat dxdy = majDx / majDy; 241 const GLfloat xAdj = dxdy < 0.0F ? -dxdy : 0.0F; 242 GLfloat x = pMin[0] - (yMin - iyMin) * dxdy; 243 GLint iy; 244 for (iy = iyMin; iy < iyMax; iy++, x += dxdy) { 245 GLint ix, startX = (GLint) (x - xAdj); 246 GLuint count; 247 GLfloat coverage = 0.0F; 248 249 /* skip over fragments with zero coverage */ 250 while (startX < MAX_WIDTH) { 251 coverage = compute_coveragef(pMin, pMid, pMax, startX, iy); 252 if (coverage > 0.0F) 253 break; 254 startX++; 255 } 256 257 /* enter interior of triangle */ 258 ix = startX; 259 count = 0; 260 while (coverage > 0.0F) { 261 /* (cx,cy) = center of fragment */ 262 const GLfloat cx = ix + 0.5F, cy = iy + 0.5F; 263 SWspanarrays *array = span.array; 264#ifdef DO_INDEX 265 array->coverage[count] = (GLfloat) compute_coveragei(pMin, pMid, pMax, ix, iy); 266#else 267 array->coverage[count] = coverage; 268#endif 269#ifdef DO_Z 270 array->z[count] = (GLuint) solve_plane(cx, cy, zPlane); 271#endif 272#ifdef DO_FOG 273 array->attribs[FRAG_ATTRIB_FOGC][count][0] = solve_plane(cx, cy, fogPlane); 274#endif 275#ifdef DO_RGBA 276 array->rgba[count][RCOMP] = solve_plane_chan(cx, cy, rPlane); 277 array->rgba[count][GCOMP] = solve_plane_chan(cx, cy, gPlane); 278 array->rgba[count][BCOMP] = solve_plane_chan(cx, cy, bPlane); 279 array->rgba[count][ACOMP] = solve_plane_chan(cx, cy, aPlane); 280#endif 281#ifdef DO_INDEX 282 array->index[count] = (GLint) solve_plane(cx, cy, iPlane); 283#endif 284#ifdef DO_SPEC 285 array->spec[count][RCOMP] = solve_plane_chan(cx, cy, srPlane); 286 array->spec[count][GCOMP] = solve_plane_chan(cx, cy, sgPlane); 287 array->spec[count][BCOMP] = solve_plane_chan(cx, cy, sbPlane); 288#endif 289#if defined(DO_ATTRIBS) 290 ATTRIB_LOOP_BEGIN 291 GLfloat invQ = solve_plane_recip(cx, cy, vPlane[attr]); 292 array->attribs[attr][count][0] = solve_plane(cx, cy, sPlane[attr]) * invQ; 293 array->attribs[attr][count][1] = solve_plane(cx, cy, tPlane[attr]) * invQ; 294 array->attribs[attr][count][2] = solve_plane(cx, cy, uPlane[attr]) * invQ; 295 if (attr < FRAG_ATTRIB_VAR0 && attr >= FRAG_ATTRIB_TEX0) { 296 const GLuint unit = attr - FRAG_ATTRIB_TEX0; 297 array->lambda[unit][count] = compute_lambda(sPlane[attr], tPlane[attr], 298 vPlane[attr], cx, cy, invQ, 299 texWidth[attr], texHeight[attr]); 300 } 301 ATTRIB_LOOP_END 302#endif 303 ix++; 304 count++; 305 coverage = compute_coveragef(pMin, pMid, pMax, ix, iy); 306 } 307 308 if (ix <= startX) 309 continue; 310 311 span.x = startX; 312 span.y = iy; 313 span.end = (GLuint) ix - (GLuint) startX; 314 ASSERT(span.interpMask == 0); 315#if defined(DO_RGBA) 316 _swrast_write_rgba_span(ctx, &span); 317#else 318 _swrast_write_index_span(ctx, &span); 319#endif 320 } 321 } 322 else { 323 /* scan right to left */ 324 const GLfloat *pMin = vMin->win; 325 const GLfloat *pMid = vMid->win; 326 const GLfloat *pMax = vMax->win; 327 const GLfloat dxdy = majDx / majDy; 328 const GLfloat xAdj = dxdy > 0 ? dxdy : 0.0F; 329 GLfloat x = pMin[0] - (yMin - iyMin) * dxdy; 330 GLint iy; 331 for (iy = iyMin; iy < iyMax; iy++, x += dxdy) { 332 GLint ix, left, startX = (GLint) (x + xAdj); 333 GLuint count, n; 334 GLfloat coverage = 0.0F; 335 336 /* make sure we're not past the window edge */ 337 if (startX >= ctx->DrawBuffer->_Xmax) { 338 startX = ctx->DrawBuffer->_Xmax - 1; 339 } 340 341 /* skip fragments with zero coverage */ 342 while (startX > 0) { 343 coverage = compute_coveragef(pMin, pMax, pMid, startX, iy); 344 if (coverage > 0.0F) 345 break; 346 startX--; 347 } 348 349 /* enter interior of triangle */ 350 ix = startX; 351 count = 0; 352 while (coverage > 0.0F) { 353 /* (cx,cy) = center of fragment */ 354 const GLfloat cx = ix + 0.5F, cy = iy + 0.5F; 355 SWspanarrays *array = span.array; 356 ASSERT(ix >= 0); 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_ATTRIBS) 383 ATTRIB_LOOP_BEGIN 384 GLfloat invQ = solve_plane_recip(cx, cy, vPlane[attr]); 385 array->attribs[attr][ix][0] = solve_plane(cx, cy, sPlane[attr]) * invQ; 386 array->attribs[attr][ix][1] = solve_plane(cx, cy, tPlane[attr]) * invQ; 387 array->attribs[attr][ix][2] = solve_plane(cx, cy, uPlane[attr]) * invQ; 388 if (attr < FRAG_ATTRIB_VAR0 && attr >= FRAG_ATTRIB_TEX0) { 389 const GLuint unit = attr - FRAG_ATTRIB_TEX0; 390 array->lambda[unit][ix] = compute_lambda(sPlane[attr], 391 tPlane[attr], 392 vPlane[attr], 393 cx, cy, invQ, 394 texWidth[attr], 395 texHeight[attr]); 396 } 397 ATTRIB_LOOP_END 398#endif 399 ix--; 400 count++; 401 coverage = compute_coveragef(pMin, pMax, pMid, ix, iy); 402 } 403 404 if (startX <= ix) 405 continue; 406 407 n = (GLuint) startX - (GLuint) ix; 408 409 left = ix + 1; 410 411 /* shift all values to the left */ 412 /* XXX this is temporary */ 413 { 414 SWspanarrays *array = span.array; 415 GLint j; 416 for (j = 0; j < (GLint) n; j++) { 417#ifdef DO_RGBA 418 COPY_CHAN4(array->rgba[j], array->rgba[j + left]); 419#endif 420#ifdef DO_SPEC 421 COPY_CHAN4(array->spec[j], array->spec[j + left]); 422#endif 423#ifdef DO_INDEX 424 array->index[j] = array->index[j + left]; 425#endif 426#ifdef DO_Z 427 array->z[j] = array->z[j + left]; 428#endif 429#ifdef DO_FOG 430 array->attribs[FRAG_ATTRIB_FOGC][j][0] 431 = array->attribs[FRAG_ATTRIB_FOGC][j + left][0]; 432#endif 433#if defined(DO_ATTRIBS) 434 array->lambda[0][j] = array->lambda[0][j + left]; 435#endif 436 array->coverage[j] = array->coverage[j + left]; 437 } 438 } 439#ifdef DO_ATTRIBS 440 /* shift texcoords, varying */ 441 { 442 SWspanarrays *array = span.array; 443 ATTRIB_LOOP_BEGIN 444 GLint j; 445 for (j = 0; j < (GLint) n; j++) { 446 array->attribs[attr][j][0] = array->attribs[attr][j + left][0]; 447 array->attribs[attr][j][1] = array->attribs[attr][j + left][1]; 448 array->attribs[attr][j][2] = array->attribs[attr][j + left][2]; 449 /*array->lambda[unit][j] = array->lambda[unit][j + left];*/ 450 } 451 ATTRIB_LOOP_END 452 } 453#endif 454 455 span.x = left; 456 span.y = iy; 457 span.end = n; 458 ASSERT(span.interpMask == 0); 459#if defined(DO_RGBA) 460 _swrast_write_rgba_span(ctx, &span); 461#else 462 _swrast_write_index_span(ctx, &span); 463#endif 464 } 465 } 466} 467 468 469#ifdef DO_Z 470#undef DO_Z 471#endif 472 473#ifdef DO_FOG 474#undef DO_FOG 475#endif 476 477#ifdef DO_RGBA 478#undef DO_RGBA 479#endif 480 481#ifdef DO_INDEX 482#undef DO_INDEX 483#endif 484 485#ifdef DO_SPEC 486#undef DO_SPEC 487#endif 488 489#ifdef DO_ATTRIBS 490#undef DO_ATTRIBS 491#endif 492 493#ifdef DO_OCCLUSION_TEST 494#undef DO_OCCLUSION_TEST 495#endif 496