s_span.c revision e4f976b8b9d74a74b5816146cb11880c3a493929
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/** 27 * \file swrast/s_span.c 28 * \brief Span processing functions used by all rasterization functions. 29 * This is where all the per-fragment tests are performed 30 * \author Brian Paul 31 */ 32 33#include "glheader.h" 34#include "colormac.h" 35#include "context.h" 36#include "macros.h" 37#include "imports.h" 38#include "image.h" 39 40#include "s_atifragshader.h" 41#include "s_alpha.h" 42#include "s_blend.h" 43#include "s_context.h" 44#include "s_depth.h" 45#include "s_fog.h" 46#include "s_logic.h" 47#include "s_masking.h" 48#include "s_fragprog.h" 49#include "s_span.h" 50#include "s_stencil.h" 51#include "s_texcombine.h" 52 53 54/** 55 * Init span's Z interpolation values to the RasterPos Z. 56 * Used during setup for glDraw/CopyPixels. 57 */ 58void 59_swrast_span_default_z( GLcontext *ctx, SWspan *span ) 60{ 61 const GLfloat depthMax = ctx->DrawBuffer->_DepthMaxF; 62 if (ctx->DrawBuffer->Visual.depthBits <= 16) 63 span->z = FloatToFixed(ctx->Current.RasterPos[2] * depthMax + 0.5F); 64 else 65 span->z = (GLint) (ctx->Current.RasterPos[2] * depthMax + 0.5F); 66 span->zStep = 0; 67 span->interpMask |= SPAN_Z; 68} 69 70 71/** 72 * Init span's fog interpolation values to the RasterPos fog. 73 * Used during setup for glDraw/CopyPixels. 74 */ 75void 76_swrast_span_default_fog( GLcontext *ctx, SWspan *span ) 77{ 78 span->attrStart[FRAG_ATTRIB_FOGC][0] 79 = _swrast_z_to_fogfactor(ctx, ctx->Current.RasterDistance); 80 span->attrStepX[FRAG_ATTRIB_FOGC][0] = 0.0; 81 span->attrStepY[FRAG_ATTRIB_FOGC][0] = 0.0; 82 span->interpMask |= SPAN_FOG; 83} 84 85 86/** 87 * Init span's rgba or index interpolation values to the RasterPos color. 88 * Used during setup for glDraw/CopyPixels. 89 */ 90void 91_swrast_span_default_color( GLcontext *ctx, SWspan *span ) 92{ 93 if (ctx->Visual.rgbMode) { 94 GLchan r, g, b, a; 95 UNCLAMPED_FLOAT_TO_CHAN(r, ctx->Current.RasterColor[0]); 96 UNCLAMPED_FLOAT_TO_CHAN(g, ctx->Current.RasterColor[1]); 97 UNCLAMPED_FLOAT_TO_CHAN(b, ctx->Current.RasterColor[2]); 98 UNCLAMPED_FLOAT_TO_CHAN(a, ctx->Current.RasterColor[3]); 99#if CHAN_TYPE == GL_FLOAT 100 span->red = r; 101 span->green = g; 102 span->blue = b; 103 span->alpha = a; 104#else 105 span->red = IntToFixed(r); 106 span->green = IntToFixed(g); 107 span->blue = IntToFixed(b); 108 span->alpha = IntToFixed(a); 109#endif 110 span->redStep = 0; 111 span->greenStep = 0; 112 span->blueStep = 0; 113 span->alphaStep = 0; 114 span->interpMask |= SPAN_RGBA; 115 } 116 else { 117 span->index = FloatToFixed(ctx->Current.RasterIndex); 118 span->indexStep = 0; 119 span->interpMask |= SPAN_INDEX; 120 } 121} 122 123 124/** 125 * Init span's texcoord interpolation values to the RasterPos texcoords. 126 * Used during setup for glDraw/CopyPixels. 127 */ 128void 129_swrast_span_default_texcoords( GLcontext *ctx, SWspan *span ) 130{ 131 GLuint i; 132 for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) { 133 const GLuint attr = FRAG_ATTRIB_TEX0 + i; 134 const GLfloat *tc = ctx->Current.RasterTexCoords[i]; 135 if (ctx->FragmentProgram._Current || ctx->ATIFragmentShader._Enabled) { 136 COPY_4V(span->attrStart[attr], tc); 137 } 138 else if (tc[3] > 0.0F) { 139 /* use (s/q, t/q, r/q, 1) */ 140 span->attrStart[attr][0] = tc[0] / tc[3]; 141 span->attrStart[attr][1] = tc[1] / tc[3]; 142 span->attrStart[attr][2] = tc[2] / tc[3]; 143 span->attrStart[attr][3] = 1.0; 144 } 145 else { 146 ASSIGN_4V(span->attrStart[attr], 0.0F, 0.0F, 0.0F, 1.0F); 147 } 148 ASSIGN_4V(span->attrStepX[attr], 0.0F, 0.0F, 0.0F, 0.0F); 149 ASSIGN_4V(span->attrStepY[attr], 0.0F, 0.0F, 0.0F, 0.0F); 150 } 151 span->interpMask |= SPAN_TEXTURE; 152} 153 154 155/** 156 * Interpolate primary colors to fill in the span->array->color array. 157 */ 158static INLINE void 159interpolate_colors(SWspan *span) 160{ 161 const GLuint n = span->end; 162 GLuint i; 163 164 ASSERT((span->interpMask & SPAN_RGBA) && 165 !(span->arrayMask & SPAN_RGBA)); 166 167 switch (span->array->ChanType) { 168#if CHAN_BITS != 32 169 case GL_UNSIGNED_BYTE: 170 { 171 GLubyte (*rgba)[4] = span->array->color.sz1.rgba; 172 if (span->interpMask & SPAN_FLAT) { 173 GLubyte color[4]; 174 color[RCOMP] = FixedToInt(span->red); 175 color[GCOMP] = FixedToInt(span->green); 176 color[BCOMP] = FixedToInt(span->blue); 177 color[ACOMP] = FixedToInt(span->alpha); 178 for (i = 0; i < n; i++) { 179 COPY_4UBV(rgba[i], color); 180 } 181 } 182 else { 183 GLfixed r = span->red; 184 GLfixed g = span->green; 185 GLfixed b = span->blue; 186 GLfixed a = span->alpha; 187 GLint dr = span->redStep; 188 GLint dg = span->greenStep; 189 GLint db = span->blueStep; 190 GLint da = span->alphaStep; 191 for (i = 0; i < n; i++) { 192 rgba[i][RCOMP] = FixedToChan(r); 193 rgba[i][GCOMP] = FixedToChan(g); 194 rgba[i][BCOMP] = FixedToChan(b); 195 rgba[i][ACOMP] = FixedToChan(a); 196 r += dr; 197 g += dg; 198 b += db; 199 a += da; 200 } 201 } 202 } 203 break; 204 case GL_UNSIGNED_SHORT: 205 { 206 GLushort (*rgba)[4] = span->array->color.sz2.rgba; 207 if (span->interpMask & SPAN_FLAT) { 208 GLushort color[4]; 209 color[RCOMP] = FixedToInt(span->red); 210 color[GCOMP] = FixedToInt(span->green); 211 color[BCOMP] = FixedToInt(span->blue); 212 color[ACOMP] = FixedToInt(span->alpha); 213 for (i = 0; i < n; i++) { 214 COPY_4V(rgba[i], color); 215 } 216 } 217 else { 218 GLushort (*rgba)[4] = span->array->color.sz2.rgba; 219 GLfixed r, g, b, a; 220 GLint dr, dg, db, da; 221 r = span->red; 222 g = span->green; 223 b = span->blue; 224 a = span->alpha; 225 dr = span->redStep; 226 dg = span->greenStep; 227 db = span->blueStep; 228 da = span->alphaStep; 229 for (i = 0; i < n; i++) { 230 rgba[i][RCOMP] = FixedToChan(r); 231 rgba[i][GCOMP] = FixedToChan(g); 232 rgba[i][BCOMP] = FixedToChan(b); 233 rgba[i][ACOMP] = FixedToChan(a); 234 r += dr; 235 g += dg; 236 b += db; 237 a += da; 238 } 239 } 240 } 241 break; 242#endif 243 case GL_FLOAT: 244 { 245 GLfloat (*rgba)[4] = span->array->attribs[FRAG_ATTRIB_COL0]; 246 GLfloat r, g, b, a, dr, dg, db, da; 247 r = span->red; 248 g = span->green; 249 b = span->blue; 250 a = span->alpha; 251 if (span->interpMask & SPAN_FLAT) { 252 dr = dg = db = da = 0.0; 253 } 254 else { 255 dr = span->redStep; 256 dg = span->greenStep; 257 db = span->blueStep; 258 da = span->alphaStep; 259 } 260 for (i = 0; i < n; i++) { 261 rgba[i][RCOMP] = r; 262 rgba[i][GCOMP] = g; 263 rgba[i][BCOMP] = b; 264 rgba[i][ACOMP] = a; 265 r += dr; 266 g += dg; 267 b += db; 268 a += da; 269 } 270 } 271 break; 272 default: 273 _mesa_problem(NULL, "bad datatype in interpolate_colors"); 274 } 275 span->arrayMask |= SPAN_RGBA; 276} 277 278 279/** 280 * Interpolate specular/secondary colors. 281 */ 282static INLINE void 283interpolate_specular(SWspan *span) 284{ 285 const GLuint n = span->end; 286 GLuint i; 287 288 switch (span->array->ChanType) { 289#if CHAN_BITS != 32 290 case GL_UNSIGNED_BYTE: 291 { 292 GLubyte (*spec)[4] = span->array->color.sz1.spec; 293 if (span->interpMask & SPAN_FLAT) { 294 GLubyte color[4]; 295 color[RCOMP] = FixedToInt(span->specRed); 296 color[GCOMP] = FixedToInt(span->specGreen); 297 color[BCOMP] = FixedToInt(span->specBlue); 298 color[ACOMP] = 0; 299 for (i = 0; i < n; i++) { 300 COPY_4UBV(spec[i], color); 301 } 302 } 303 else { 304 GLfixed r = span->specRed; 305 GLfixed g = span->specGreen; 306 GLfixed b = span->specBlue; 307 GLint dr = span->specRedStep; 308 GLint dg = span->specGreenStep; 309 GLint db = span->specBlueStep; 310 for (i = 0; i < n; i++) { 311 spec[i][RCOMP] = CLAMP(FixedToChan(r), 0, 255); 312 spec[i][GCOMP] = CLAMP(FixedToChan(g), 0, 255); 313 spec[i][BCOMP] = CLAMP(FixedToChan(b), 0, 255); 314 spec[i][ACOMP] = 0; 315 r += dr; 316 g += dg; 317 b += db; 318 } 319 } 320 } 321 break; 322 case GL_UNSIGNED_SHORT: 323 { 324 GLushort (*spec)[4] = span->array->color.sz2.spec; 325 if (span->interpMask & SPAN_FLAT) { 326 GLushort color[4]; 327 color[RCOMP] = FixedToInt(span->specRed); 328 color[GCOMP] = FixedToInt(span->specGreen); 329 color[BCOMP] = FixedToInt(span->specBlue); 330 color[ACOMP] = 0; 331 for (i = 0; i < n; i++) { 332 COPY_4V(spec[i], color); 333 } 334 } 335 else { 336 GLfixed r = FloatToFixed(span->specRed); 337 GLfixed g = FloatToFixed(span->specGreen); 338 GLfixed b = FloatToFixed(span->specBlue); 339 GLint dr = FloatToFixed(span->specRedStep); 340 GLint dg = FloatToFixed(span->specGreenStep); 341 GLint db = FloatToFixed(span->specBlueStep); 342 for (i = 0; i < n; i++) { 343 spec[i][RCOMP] = FixedToInt(r); 344 spec[i][GCOMP] = FixedToInt(g); 345 spec[i][BCOMP] = FixedToInt(b); 346 spec[i][ACOMP] = 0; 347 r += dr; 348 g += dg; 349 b += db; 350 } 351 } 352 } 353 break; 354#endif 355 case GL_FLOAT: 356 { 357 GLfloat (*spec)[4] = span->array->attribs[FRAG_ATTRIB_COL1]; 358#if CHAN_BITS <= 16 359 GLfloat r = CHAN_TO_FLOAT(FixedToChan(span->specRed)); 360 GLfloat g = CHAN_TO_FLOAT(FixedToChan(span->specGreen)); 361 GLfloat b = CHAN_TO_FLOAT(FixedToChan(span->specBlue)); 362#else 363 GLfloat r = span->specRed; 364 GLfloat g = span->specGreen; 365 GLfloat b = span->specBlue; 366#endif 367 GLfloat dr, dg, db; 368 if (span->interpMask & SPAN_FLAT) { 369 dr = dg = db = 0.0; 370 } 371 else { 372#if CHAN_BITS <= 16 373 dr = CHAN_TO_FLOAT(FixedToChan(span->specRedStep)); 374 dg = CHAN_TO_FLOAT(FixedToChan(span->specGreenStep)); 375 db = CHAN_TO_FLOAT(FixedToChan(span->specBlueStep)); 376#else 377 dr = span->specRedStep; 378 dg = span->specGreenStep; 379 db = span->specBlueStep; 380#endif 381 } 382 for (i = 0; i < n; i++) { 383 spec[i][RCOMP] = r; 384 spec[i][GCOMP] = g; 385 spec[i][BCOMP] = b; 386 spec[i][ACOMP] = 0.0F; 387 r += dr; 388 g += dg; 389 b += db; 390 } 391 } 392 break; 393 default: 394 _mesa_problem(NULL, "bad datatype in interpolate_specular"); 395 } 396 span->arrayMask |= SPAN_SPEC; 397} 398 399 400/* Fill in the span.color.index array from the interpolation values */ 401static INLINE void 402interpolate_indexes(GLcontext *ctx, SWspan *span) 403{ 404 GLfixed index = span->index; 405 const GLint indexStep = span->indexStep; 406 const GLuint n = span->end; 407 GLuint *indexes = span->array->index; 408 GLuint i; 409 (void) ctx; 410 ASSERT((span->interpMask & SPAN_INDEX) && 411 !(span->arrayMask & SPAN_INDEX)); 412 413 if ((span->interpMask & SPAN_FLAT) || (indexStep == 0)) { 414 /* constant color */ 415 index = FixedToInt(index); 416 for (i = 0; i < n; i++) { 417 indexes[i] = index; 418 } 419 } 420 else { 421 /* interpolate */ 422 for (i = 0; i < n; i++) { 423 indexes[i] = FixedToInt(index); 424 index += indexStep; 425 } 426 } 427 span->arrayMask |= SPAN_INDEX; 428 span->interpMask &= ~SPAN_INDEX; 429} 430 431 432/* Fill in the span.array.fog values from the interpolation values */ 433static INLINE void 434interpolate_fog(const GLcontext *ctx, SWspan *span) 435{ 436 GLfloat (*fog)[4] = span->array->attribs[FRAG_ATTRIB_FOGC]; 437 const GLfloat fogStep = span->attrStepX[FRAG_ATTRIB_FOGC][0]; 438 GLfloat fogCoord = span->attrStart[FRAG_ATTRIB_FOGC][0]; 439 const GLuint haveW = (span->interpMask & SPAN_W); 440 const GLfloat wStep = haveW ? span->attrStepX[FRAG_ATTRIB_WPOS][3] : 0.0F; 441 GLfloat w = haveW ? span->attrStart[FRAG_ATTRIB_WPOS][3] : 1.0F; 442 GLuint i; 443 for (i = 0; i < span->end; i++) { 444 fog[i][0] = fogCoord / w; 445 fogCoord += fogStep; 446 w += wStep; 447 } 448 span->arrayMask |= SPAN_FOG; 449} 450 451 452/* Fill in the span.zArray array from the interpolation values */ 453void 454_swrast_span_interpolate_z( const GLcontext *ctx, SWspan *span ) 455{ 456 const GLuint n = span->end; 457 GLuint i; 458 459 ASSERT((span->interpMask & SPAN_Z) && 460 !(span->arrayMask & SPAN_Z)); 461 462 if (ctx->DrawBuffer->Visual.depthBits <= 16) { 463 GLfixed zval = span->z; 464 GLuint *z = span->array->z; 465 for (i = 0; i < n; i++) { 466 z[i] = FixedToInt(zval); 467 zval += span->zStep; 468 } 469 } 470 else { 471 /* Deep Z buffer, no fixed->int shift */ 472 GLuint zval = span->z; 473 GLuint *z = span->array->z; 474 for (i = 0; i < n; i++) { 475 z[i] = zval; 476 zval += span->zStep; 477 } 478 } 479 span->interpMask &= ~SPAN_Z; 480 span->arrayMask |= SPAN_Z; 481} 482 483 484/* 485 * This the ideal solution, as given in the OpenGL spec. 486 */ 487#if 0 488static GLfloat 489compute_lambda(GLfloat dsdx, GLfloat dsdy, GLfloat dtdx, GLfloat dtdy, 490 GLfloat dqdx, GLfloat dqdy, GLfloat texW, GLfloat texH, 491 GLfloat s, GLfloat t, GLfloat q, GLfloat invQ) 492{ 493 GLfloat dudx = texW * ((s + dsdx) / (q + dqdx) - s * invQ); 494 GLfloat dvdx = texH * ((t + dtdx) / (q + dqdx) - t * invQ); 495 GLfloat dudy = texW * ((s + dsdy) / (q + dqdy) - s * invQ); 496 GLfloat dvdy = texH * ((t + dtdy) / (q + dqdy) - t * invQ); 497 GLfloat x = SQRTF(dudx * dudx + dvdx * dvdx); 498 GLfloat y = SQRTF(dudy * dudy + dvdy * dvdy); 499 GLfloat rho = MAX2(x, y); 500 GLfloat lambda = LOG2(rho); 501 return lambda; 502} 503#endif 504 505 506/* 507 * This is a faster approximation 508 */ 509GLfloat 510_swrast_compute_lambda(GLfloat dsdx, GLfloat dsdy, GLfloat dtdx, GLfloat dtdy, 511 GLfloat dqdx, GLfloat dqdy, GLfloat texW, GLfloat texH, 512 GLfloat s, GLfloat t, GLfloat q, GLfloat invQ) 513{ 514 GLfloat dsdx2 = (s + dsdx) / (q + dqdx) - s * invQ; 515 GLfloat dtdx2 = (t + dtdx) / (q + dqdx) - t * invQ; 516 GLfloat dsdy2 = (s + dsdy) / (q + dqdy) - s * invQ; 517 GLfloat dtdy2 = (t + dtdy) / (q + dqdy) - t * invQ; 518 GLfloat maxU, maxV, rho, lambda; 519 dsdx2 = FABSF(dsdx2); 520 dsdy2 = FABSF(dsdy2); 521 dtdx2 = FABSF(dtdx2); 522 dtdy2 = FABSF(dtdy2); 523 maxU = MAX2(dsdx2, dsdy2) * texW; 524 maxV = MAX2(dtdx2, dtdy2) * texH; 525 rho = MAX2(maxU, maxV); 526 lambda = LOG2(rho); 527 return lambda; 528} 529 530 531/** 532 * Fill in the span.texcoords array from the interpolation values. 533 * Note: in the places where we divide by Q (or mult by invQ) we're 534 * really doing two things: perspective correction and texcoord 535 * projection. Remember, for texcoord (s,t,r,q) we need to index 536 * texels with (s/q, t/q, r/q). 537 * If we're using a fragment program, we never do the division 538 * for texcoord projection. That's done by the TXP instruction 539 * or user-written code. 540 */ 541static void 542interpolate_texcoords(GLcontext *ctx, SWspan *span) 543{ 544 const GLuint maxUnit 545 = (ctx->Texture._EnabledCoordUnits > 1) ? ctx->Const.MaxTextureUnits : 1; 546 GLuint u; 547 548 ASSERT(span->interpMask & SPAN_TEXTURE); 549 ASSERT(!(span->arrayMask & SPAN_TEXTURE)); 550 551 span->arrayMask |= SPAN_TEXTURE; 552 553 /* XXX CoordUnits vs. ImageUnits */ 554 for (u = 0; u < maxUnit; u++) { 555 if (ctx->Texture._EnabledCoordUnits & (1 << u)) { 556 const GLuint attr = FRAG_ATTRIB_TEX0 + u; 557 const struct gl_texture_object *obj =ctx->Texture.Unit[u]._Current; 558 GLfloat texW, texH; 559 GLboolean needLambda; 560 GLfloat (*texcoord)[4] = span->array->attribs[attr]; 561 GLfloat *lambda = span->array->lambda[u]; 562 const GLfloat dsdx = span->attrStepX[attr][0]; 563 const GLfloat dsdy = span->attrStepY[attr][0]; 564 const GLfloat dtdx = span->attrStepX[attr][1]; 565 const GLfloat dtdy = span->attrStepY[attr][1]; 566 const GLfloat drdx = span->attrStepX[attr][2]; 567 const GLfloat dqdx = span->attrStepX[attr][3]; 568 const GLfloat dqdy = span->attrStepY[attr][3]; 569 GLfloat s = span->attrStart[attr][0]; 570 GLfloat t = span->attrStart[attr][1]; 571 GLfloat r = span->attrStart[attr][2]; 572 GLfloat q = span->attrStart[attr][3]; 573 574 if (obj) { 575 const struct gl_texture_image *img = obj->Image[0][obj->BaseLevel]; 576 needLambda = (obj->MinFilter != obj->MagFilter) 577 || ctx->FragmentProgram._Current; 578 texW = img->WidthScale; 579 texH = img->HeightScale; 580 } 581 else { 582 /* using a fragment program */ 583 texW = 1.0; 584 texH = 1.0; 585 needLambda = GL_FALSE; 586 } 587 588 if (needLambda) { 589 GLuint i; 590 if (ctx->FragmentProgram._Current 591 || ctx->ATIFragmentShader._Enabled) { 592 /* do perspective correction but don't divide s, t, r by q */ 593 const GLfloat dwdx = span->attrStepX[FRAG_ATTRIB_WPOS][3]; 594 GLfloat w = span->attrStart[FRAG_ATTRIB_WPOS][3]; 595 for (i = 0; i < span->end; i++) { 596 const GLfloat invW = 1.0F / w; 597 texcoord[i][0] = s * invW; 598 texcoord[i][1] = t * invW; 599 texcoord[i][2] = r * invW; 600 texcoord[i][3] = q * invW; 601 lambda[i] = _swrast_compute_lambda(dsdx, dsdy, dtdx, dtdy, 602 dqdx, dqdy, texW, texH, 603 s, t, q, invW); 604 s += dsdx; 605 t += dtdx; 606 r += drdx; 607 q += dqdx; 608 w += dwdx; 609 } 610 } 611 else { 612 for (i = 0; i < span->end; i++) { 613 const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q); 614 texcoord[i][0] = s * invQ; 615 texcoord[i][1] = t * invQ; 616 texcoord[i][2] = r * invQ; 617 texcoord[i][3] = q; 618 lambda[i] = _swrast_compute_lambda(dsdx, dsdy, dtdx, dtdy, 619 dqdx, dqdy, texW, texH, 620 s, t, q, invQ); 621 s += dsdx; 622 t += dtdx; 623 r += drdx; 624 q += dqdx; 625 } 626 } 627 span->arrayMask |= SPAN_LAMBDA; 628 } 629 else { 630 GLuint i; 631 if (ctx->FragmentProgram._Current || 632 ctx->ATIFragmentShader._Enabled) { 633 /* do perspective correction but don't divide s, t, r by q */ 634 const GLfloat dwdx = span->attrStepX[FRAG_ATTRIB_WPOS][3]; 635 GLfloat w = span->attrStart[FRAG_ATTRIB_WPOS][3]; 636 for (i = 0; i < span->end; i++) { 637 const GLfloat invW = 1.0F / w; 638 texcoord[i][0] = s * invW; 639 texcoord[i][1] = t * invW; 640 texcoord[i][2] = r * invW; 641 texcoord[i][3] = q * invW; 642 lambda[i] = 0.0; 643 s += dsdx; 644 t += dtdx; 645 r += drdx; 646 q += dqdx; 647 w += dwdx; 648 } 649 } 650 else if (dqdx == 0.0F) { 651 /* Ortho projection or polygon's parallel to window X axis */ 652 const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q); 653 for (i = 0; i < span->end; i++) { 654 texcoord[i][0] = s * invQ; 655 texcoord[i][1] = t * invQ; 656 texcoord[i][2] = r * invQ; 657 texcoord[i][3] = q; 658 lambda[i] = 0.0; 659 s += dsdx; 660 t += dtdx; 661 r += drdx; 662 } 663 } 664 else { 665 for (i = 0; i < span->end; i++) { 666 const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q); 667 texcoord[i][0] = s * invQ; 668 texcoord[i][1] = t * invQ; 669 texcoord[i][2] = r * invQ; 670 texcoord[i][3] = q; 671 lambda[i] = 0.0; 672 s += dsdx; 673 t += dtdx; 674 r += drdx; 675 q += dqdx; 676 } 677 } 678 } /* lambda */ 679 } /* if */ 680 } /* for */ 681} 682 683 684 685/** 686 * Fill in the arrays->attribs[FRAG_ATTRIB_VARx] arrays from the 687 * interpolation values. 688 * XXX since interpolants/arrays are getting uniformed, we might merge 689 * this with interpolate_texcoords(), interpolate_Fog(), etc. someday. 690 */ 691static INLINE void 692interpolate_varying(GLcontext *ctx, SWspan *span) 693{ 694 GLuint var; 695 const GLbitfield inputsUsed = ctx->FragmentProgram._Current->Base.InputsRead; 696 697 ASSERT(span->interpMask & SPAN_VARYING); 698 ASSERT(!(span->arrayMask & SPAN_VARYING)); 699 700 span->arrayMask |= SPAN_VARYING; 701 702 for (var = 0; var < MAX_VARYING; var++) { 703 if (inputsUsed & FRAG_BIT_VAR(var)) { 704 const GLuint attr = FRAG_ATTRIB_VAR0 + var; 705 GLuint j; 706 for (j = 0; j < 4; j++) { 707 const GLfloat dvdx = span->attrStepX[attr][j]; 708 GLfloat v = span->attrStart[attr][j]; 709 const GLfloat dwdx = span->attrStepX[FRAG_ATTRIB_WPOS][3]; 710 GLfloat w = span->attrStart[FRAG_ATTRIB_WPOS][3]; 711 GLuint k; 712 for (k = 0; k < span->end; k++) { 713 GLfloat invW = 1.0f / w; 714 span->array->attribs[attr][k][j] = v * invW; 715 v += dvdx; 716 w += dwdx; 717 } 718 } 719 } 720 } 721} 722 723 724/** 725 * Fill in the arrays->attribs[FRAG_ATTRIB_WPOS] array. 726 */ 727static INLINE void 728interpolate_wpos(GLcontext *ctx, SWspan *span) 729{ 730 GLfloat (*wpos)[4] = span->array->attribs[FRAG_ATTRIB_WPOS]; 731 GLuint i; 732 if (span->arrayMask & SPAN_XY) { 733 for (i = 0; i < span->end; i++) { 734 wpos[i][0] = (GLfloat) span->array->x[i]; 735 wpos[i][1] = (GLfloat) span->array->y[i]; 736 } 737 } 738 else { 739 for (i = 0; i < span->end; i++) { 740 wpos[i][0] = (GLfloat) span->x + i; 741 wpos[i][1] = (GLfloat) span->y; 742 } 743 } 744 for (i = 0; i < span->end; i++) { 745 wpos[i][2] = (GLfloat) span->array->z[i] / ctx->DrawBuffer->_DepthMaxF; 746 wpos[i][3] = span->attrStart[FRAG_ATTRIB_WPOS][3] 747 + i * span->attrStepX[FRAG_ATTRIB_WPOS][3]; 748 } 749} 750 751 752/** 753 * Apply the current polygon stipple pattern to a span of pixels. 754 */ 755static INLINE void 756stipple_polygon_span(GLcontext *ctx, SWspan *span) 757{ 758 GLubyte *mask = span->array->mask; 759 760 ASSERT(ctx->Polygon.StippleFlag); 761 762 if (span->arrayMask & SPAN_XY) { 763 /* arrays of x/y pixel coords */ 764 GLuint i; 765 for (i = 0; i < span->end; i++) { 766 const GLint col = span->array->x[i] % 32; 767 const GLint row = span->array->y[i] % 32; 768 const GLuint stipple = ctx->PolygonStipple[row]; 769 if (((1 << col) & stipple) == 0) { 770 mask[i] = 0; 771 } 772 } 773 } 774 else { 775 /* horizontal span of pixels */ 776 const GLuint highBit = 1 << 31; 777 const GLuint stipple = ctx->PolygonStipple[span->y % 32]; 778 GLuint i, m = highBit >> (GLuint) (span->x % 32); 779 for (i = 0; i < span->end; i++) { 780 if ((m & stipple) == 0) { 781 mask[i] = 0; 782 } 783 m = m >> 1; 784 if (m == 0) { 785 m = highBit; 786 } 787 } 788 } 789 span->writeAll = GL_FALSE; 790} 791 792 793/** 794 * Clip a pixel span to the current buffer/window boundaries: 795 * DrawBuffer->_Xmin, _Xmax, _Ymin, _Ymax. This will accomplish 796 * window clipping and scissoring. 797 * Return: GL_TRUE some pixels still visible 798 * GL_FALSE nothing visible 799 */ 800static INLINE GLuint 801clip_span( GLcontext *ctx, SWspan *span ) 802{ 803 const GLint xmin = ctx->DrawBuffer->_Xmin; 804 const GLint xmax = ctx->DrawBuffer->_Xmax; 805 const GLint ymin = ctx->DrawBuffer->_Ymin; 806 const GLint ymax = ctx->DrawBuffer->_Ymax; 807 808 if (span->arrayMask & SPAN_XY) { 809 /* arrays of x/y pixel coords */ 810 const GLint *x = span->array->x; 811 const GLint *y = span->array->y; 812 const GLint n = span->end; 813 GLubyte *mask = span->array->mask; 814 GLint i; 815 if (span->arrayMask & SPAN_MASK) { 816 /* note: using & intead of && to reduce branches */ 817 for (i = 0; i < n; i++) { 818 mask[i] &= (x[i] >= xmin) & (x[i] < xmax) 819 & (y[i] >= ymin) & (y[i] < ymax); 820 } 821 } 822 else { 823 /* note: using & intead of && to reduce branches */ 824 for (i = 0; i < n; i++) { 825 mask[i] = (x[i] >= xmin) & (x[i] < xmax) 826 & (y[i] >= ymin) & (y[i] < ymax); 827 } 828 } 829 return GL_TRUE; /* some pixels visible */ 830 } 831 else { 832 /* horizontal span of pixels */ 833 const GLint x = span->x; 834 const GLint y = span->y; 835 const GLint n = span->end; 836 837 /* Trivial rejection tests */ 838 if (y < ymin || y >= ymax || x + n <= xmin || x >= xmax) { 839 span->end = 0; 840 return GL_FALSE; /* all pixels clipped */ 841 } 842 843 /* Clip to the left */ 844 if (x < xmin) { 845 ASSERT(x + n > xmin); 846 span->writeAll = GL_FALSE; 847 _mesa_bzero(span->array->mask, (xmin - x) * sizeof(GLubyte)); 848 } 849 850 /* Clip to right */ 851 if (x + n > xmax) { 852 ASSERT(x < xmax); 853 span->end = xmax - x; 854 } 855 856 return GL_TRUE; /* some pixels visible */ 857 } 858} 859 860 861/** 862 * Apply all the per-fragment opertions to a span of color index fragments 863 * and write them to the enabled color drawbuffers. 864 * The 'span' parameter can be considered to be const. Note that 865 * span->interpMask and span->arrayMask may be changed but will be restored 866 * to their original values before returning. 867 */ 868void 869_swrast_write_index_span( GLcontext *ctx, SWspan *span) 870{ 871 const SWcontext *swrast = SWRAST_CONTEXT(ctx); 872 const GLbitfield origInterpMask = span->interpMask; 873 const GLbitfield origArrayMask = span->arrayMask; 874 875 ASSERT(span->end <= MAX_WIDTH); 876 ASSERT(span->primitive == GL_POINT || span->primitive == GL_LINE || 877 span->primitive == GL_POLYGON || span->primitive == GL_BITMAP); 878 ASSERT((span->interpMask | span->arrayMask) & SPAN_INDEX); 879 ASSERT((span->interpMask & span->arrayMask) == 0); 880 881 if (span->arrayMask & SPAN_MASK) { 882 /* mask was initialized by caller, probably glBitmap */ 883 span->writeAll = GL_FALSE; 884 } 885 else { 886 _mesa_memset(span->array->mask, 1, span->end); 887 span->writeAll = GL_TRUE; 888 } 889 890 /* Clipping */ 891 if ((swrast->_RasterMask & CLIP_BIT) || (span->primitive != GL_POLYGON)) { 892 if (!clip_span(ctx, span)) { 893 return; 894 } 895 } 896 897 /* Depth bounds test */ 898 if (ctx->Depth.BoundsTest && ctx->DrawBuffer->Visual.depthBits > 0) { 899 if (!_swrast_depth_bounds_test(ctx, span)) { 900 return; 901 } 902 } 903 904#ifdef DEBUG 905 /* Make sure all fragments are within window bounds */ 906 if (span->arrayMask & SPAN_XY) { 907 GLuint i; 908 for (i = 0; i < span->end; i++) { 909 if (span->array->mask[i]) { 910 assert(span->array->x[i] >= ctx->DrawBuffer->_Xmin); 911 assert(span->array->x[i] < ctx->DrawBuffer->_Xmax); 912 assert(span->array->y[i] >= ctx->DrawBuffer->_Ymin); 913 assert(span->array->y[i] < ctx->DrawBuffer->_Ymax); 914 } 915 } 916 } 917#endif 918 919 /* Polygon Stippling */ 920 if (ctx->Polygon.StippleFlag && span->primitive == GL_POLYGON) { 921 stipple_polygon_span(ctx, span); 922 } 923 924 /* Stencil and Z testing */ 925 if (ctx->Depth.Test || ctx->Stencil.Enabled) { 926 if (span->interpMask & SPAN_Z) 927 _swrast_span_interpolate_z(ctx, span); 928 929 if (ctx->Stencil.Enabled) { 930 if (!_swrast_stencil_and_ztest_span(ctx, span)) { 931 span->arrayMask = origArrayMask; 932 return; 933 } 934 } 935 else { 936 ASSERT(ctx->Depth.Test); 937 if (!_swrast_depth_test_span(ctx, span)) { 938 span->interpMask = origInterpMask; 939 span->arrayMask = origArrayMask; 940 return; 941 } 942 } 943 } 944 945#if FEATURE_ARB_occlusion_query 946 if (ctx->Query.CurrentOcclusionObject) { 947 /* update count of 'passed' fragments */ 948 struct gl_query_object *q = ctx->Query.CurrentOcclusionObject; 949 GLuint i; 950 for (i = 0; i < span->end; i++) 951 q->Result += span->array->mask[i]; 952 } 953#endif 954 955 /* we have to wait until after occlusion to do this test */ 956 if (ctx->Color.DrawBuffer == GL_NONE || ctx->Color.IndexMask == 0) { 957 /* write no pixels */ 958 span->arrayMask = origArrayMask; 959 return; 960 } 961 962 /* Interpolate the color indexes if needed */ 963 if (swrast->_FogEnabled || 964 ctx->Color.IndexLogicOpEnabled || 965 ctx->Color.IndexMask != 0xffffffff || 966 (span->arrayMask & SPAN_COVERAGE)) { 967 if (span->interpMask & SPAN_INDEX) { 968 interpolate_indexes(ctx, span); 969 } 970 } 971 972 /* Fog */ 973 if (swrast->_FogEnabled) { 974 _swrast_fog_ci_span(ctx, span); 975 } 976 977 /* Antialias coverage application */ 978 if (span->arrayMask & SPAN_COVERAGE) { 979 const GLfloat *coverage = span->array->coverage; 980 GLuint *index = span->array->index; 981 GLuint i; 982 for (i = 0; i < span->end; i++) { 983 ASSERT(coverage[i] < 16); 984 index[i] = (index[i] & ~0xf) | ((GLuint) coverage[i]); 985 } 986 } 987 988 /* 989 * Write to renderbuffers 990 */ 991 { 992 struct gl_framebuffer *fb = ctx->DrawBuffer; 993 const GLuint output = 0; /* only frag progs can write to other outputs */ 994 const GLuint numDrawBuffers = fb->_NumColorDrawBuffers[output]; 995 GLuint indexSave[MAX_WIDTH]; 996 GLuint buf; 997 998 if (numDrawBuffers > 1) { 999 /* save indexes for second, third renderbuffer writes */ 1000 _mesa_memcpy(indexSave, span->array->index, 1001 span->end * sizeof(indexSave[0])); 1002 } 1003 1004 for (buf = 0; buf < fb->_NumColorDrawBuffers[output]; buf++) { 1005 struct gl_renderbuffer *rb = fb->_ColorDrawBuffers[output][buf]; 1006 ASSERT(rb->_BaseFormat == GL_COLOR_INDEX); 1007 1008 if (ctx->Color.IndexLogicOpEnabled) { 1009 _swrast_logicop_ci_span(ctx, rb, span); 1010 } 1011 1012 if (ctx->Color.IndexMask != 0xffffffff) { 1013 _swrast_mask_ci_span(ctx, rb, span); 1014 } 1015 1016 if ((span->interpMask & SPAN_INDEX) && span->indexStep == 0) { 1017 /* all fragments have same color index */ 1018 GLubyte index8; 1019 GLushort index16; 1020 GLuint index32; 1021 void *value; 1022 1023 if (rb->DataType == GL_UNSIGNED_BYTE) { 1024 index8 = FixedToInt(span->index); 1025 value = &index8; 1026 } 1027 else if (rb->DataType == GL_UNSIGNED_SHORT) { 1028 index16 = FixedToInt(span->index); 1029 value = &index16; 1030 } 1031 else { 1032 ASSERT(rb->DataType == GL_UNSIGNED_INT); 1033 index32 = FixedToInt(span->index); 1034 value = &index32; 1035 } 1036 1037 if (span->arrayMask & SPAN_XY) { 1038 rb->PutMonoValues(ctx, rb, span->end, span->array->x, 1039 span->array->y, value, span->array->mask); 1040 } 1041 else { 1042 rb->PutMonoRow(ctx, rb, span->end, span->x, span->y, 1043 value, span->array->mask); 1044 } 1045 } 1046 else { 1047 /* each fragment is a different color */ 1048 GLubyte index8[MAX_WIDTH]; 1049 GLushort index16[MAX_WIDTH]; 1050 void *values; 1051 1052 if (rb->DataType == GL_UNSIGNED_BYTE) { 1053 GLuint k; 1054 for (k = 0; k < span->end; k++) { 1055 index8[k] = (GLubyte) span->array->index[k]; 1056 } 1057 values = index8; 1058 } 1059 else if (rb->DataType == GL_UNSIGNED_SHORT) { 1060 GLuint k; 1061 for (k = 0; k < span->end; k++) { 1062 index16[k] = (GLushort) span->array->index[k]; 1063 } 1064 values = index16; 1065 } 1066 else { 1067 ASSERT(rb->DataType == GL_UNSIGNED_INT); 1068 values = span->array->index; 1069 } 1070 1071 if (span->arrayMask & SPAN_XY) { 1072 rb->PutValues(ctx, rb, span->end, 1073 span->array->x, span->array->y, 1074 values, span->array->mask); 1075 } 1076 else { 1077 rb->PutRow(ctx, rb, span->end, span->x, span->y, 1078 values, span->array->mask); 1079 } 1080 } 1081 1082 if (buf + 1 < numDrawBuffers) { 1083 /* restore original span values */ 1084 _mesa_memcpy(span->array->index, indexSave, 1085 span->end * sizeof(indexSave[0])); 1086 } 1087 } /* for buf */ 1088 } 1089 1090 span->interpMask = origInterpMask; 1091 span->arrayMask = origArrayMask; 1092} 1093 1094 1095/** 1096 * Add specular color to base color. This is used only when 1097 * GL_LIGHT_MODEL_COLOR_CONTROL = GL_SEPARATE_SPECULAR_COLOR. 1098 */ 1099static INLINE void 1100add_specular(GLcontext *ctx, SWspan *span) 1101{ 1102 switch (span->array->ChanType) { 1103 case GL_UNSIGNED_BYTE: 1104 { 1105 GLubyte (*rgba)[4] = span->array->color.sz1.rgba; 1106 GLubyte (*spec)[4] = span->array->color.sz1.spec; 1107 GLuint i; 1108 for (i = 0; i < span->end; i++) { 1109 GLint r = rgba[i][RCOMP] + spec[i][RCOMP]; 1110 GLint g = rgba[i][GCOMP] + spec[i][GCOMP]; 1111 GLint b = rgba[i][BCOMP] + spec[i][BCOMP]; 1112 GLint a = rgba[i][ACOMP] + spec[i][ACOMP]; 1113 rgba[i][RCOMP] = MIN2(r, 255); 1114 rgba[i][GCOMP] = MIN2(g, 255); 1115 rgba[i][BCOMP] = MIN2(b, 255); 1116 rgba[i][ACOMP] = MIN2(a, 255); 1117 } 1118 } 1119 break; 1120 case GL_UNSIGNED_SHORT: 1121 { 1122 GLushort (*rgba)[4] = span->array->color.sz2.rgba; 1123 GLushort (*spec)[4] = span->array->color.sz2.spec; 1124 GLuint i; 1125 for (i = 0; i < span->end; i++) { 1126 GLint r = rgba[i][RCOMP] + spec[i][RCOMP]; 1127 GLint g = rgba[i][GCOMP] + spec[i][GCOMP]; 1128 GLint b = rgba[i][BCOMP] + spec[i][BCOMP]; 1129 GLint a = rgba[i][ACOMP] + spec[i][ACOMP]; 1130 rgba[i][RCOMP] = MIN2(r, 65535); 1131 rgba[i][GCOMP] = MIN2(g, 65535); 1132 rgba[i][BCOMP] = MIN2(b, 65535); 1133 rgba[i][ACOMP] = MIN2(a, 65535); 1134 } 1135 } 1136 break; 1137 case GL_FLOAT: 1138 { 1139 GLfloat (*rgba)[4] = span->array->attribs[FRAG_ATTRIB_COL0]; 1140 GLfloat (*spec)[4] = span->array->attribs[FRAG_ATTRIB_COL1]; 1141 GLuint i; 1142 for (i = 0; i < span->end; i++) { 1143 rgba[i][RCOMP] += spec[i][RCOMP]; 1144 rgba[i][GCOMP] += spec[i][GCOMP]; 1145 rgba[i][BCOMP] += spec[i][BCOMP]; 1146 rgba[i][ACOMP] += spec[i][ACOMP]; 1147 } 1148 } 1149 break; 1150 default: 1151 _mesa_problem(ctx, "Invalid datatype in add_specular"); 1152 } 1153} 1154 1155 1156/** 1157 * Apply antialiasing coverage value to alpha values. 1158 */ 1159static INLINE void 1160apply_aa_coverage(SWspan *span) 1161{ 1162 const GLfloat *coverage = span->array->coverage; 1163 GLuint i; 1164 if (span->array->ChanType == GL_UNSIGNED_BYTE) { 1165 GLubyte (*rgba)[4] = span->array->color.sz1.rgba; 1166 for (i = 0; i < span->end; i++) { 1167 const GLfloat a = rgba[i][ACOMP] * coverage[i]; 1168 rgba[i][ACOMP] = (GLubyte) CLAMP(a, 0.0, 255.0); 1169 ASSERT(coverage[i] >= 0.0); 1170 ASSERT(coverage[i] <= 1.0); 1171 } 1172 } 1173 else if (span->array->ChanType == GL_UNSIGNED_SHORT) { 1174 GLushort (*rgba)[4] = span->array->color.sz2.rgba; 1175 for (i = 0; i < span->end; i++) { 1176 const GLfloat a = rgba[i][ACOMP] * coverage[i]; 1177 rgba[i][ACOMP] = (GLushort) CLAMP(a, 0.0, 65535.0); 1178 } 1179 } 1180 else { 1181 GLfloat (*rgba)[4] = span->array->attribs[FRAG_ATTRIB_COL0]; 1182 for (i = 0; i < span->end; i++) { 1183 rgba[i][ACOMP] = rgba[i][ACOMP] * coverage[i]; 1184 } 1185 } 1186} 1187 1188 1189/** 1190 * Clamp span's float colors to [0,1] 1191 */ 1192static INLINE void 1193clamp_colors(SWspan *span) 1194{ 1195 GLfloat (*rgba)[4] = span->array->attribs[FRAG_ATTRIB_COL0]; 1196 GLuint i; 1197 ASSERT(span->array->ChanType == GL_FLOAT); 1198 for (i = 0; i < span->end; i++) { 1199 rgba[i][RCOMP] = CLAMP(rgba[i][RCOMP], 0.0F, 1.0F); 1200 rgba[i][GCOMP] = CLAMP(rgba[i][GCOMP], 0.0F, 1.0F); 1201 rgba[i][BCOMP] = CLAMP(rgba[i][BCOMP], 0.0F, 1.0F); 1202 rgba[i][ACOMP] = CLAMP(rgba[i][ACOMP], 0.0F, 1.0F); 1203 } 1204} 1205 1206 1207/** 1208 * Convert the span's color arrays to the given type. 1209 */ 1210static INLINE void 1211convert_color_type(SWspan *span, GLenum newType) 1212{ 1213 GLvoid *src, *dst; 1214 if (span->array->ChanType == GL_UNSIGNED_BYTE) { 1215 src = span->array->color.sz1.rgba; 1216 } 1217 else if (span->array->ChanType == GL_UNSIGNED_BYTE) { 1218 src = span->array->color.sz2.rgba; 1219 } 1220 else { 1221 src = span->array->attribs[FRAG_ATTRIB_COL0]; 1222 } 1223 if (newType == GL_UNSIGNED_BYTE) { 1224 dst = span->array->color.sz1.rgba; 1225 } 1226 else if (newType == GL_UNSIGNED_BYTE) { 1227 dst = span->array->color.sz2.rgba; 1228 } 1229 else { 1230 dst = span->array->attribs[FRAG_ATTRIB_COL0]; 1231 } 1232 1233 _mesa_convert_colors(span->array->ChanType, src, 1234 newType, dst, 1235 span->end, span->array->mask); 1236 1237 span->array->ChanType = newType; 1238} 1239 1240 1241 1242/** 1243 * Apply fragment shader, fragment program or normal texturing to span. 1244 */ 1245static INLINE void 1246shade_texture_span(GLcontext *ctx, SWspan *span) 1247{ 1248 /* Now we need the rgba array, fill it in if needed */ 1249 if (span->interpMask & SPAN_RGBA) 1250 interpolate_colors(span); 1251 1252 if (ctx->Texture._EnabledCoordUnits && (span->interpMask & SPAN_TEXTURE)) 1253 interpolate_texcoords(ctx, span); 1254 1255 if (ctx->FragmentProgram._Current || 1256 ctx->ATIFragmentShader._Enabled) { 1257 1258 /* use float colors if running a fragment program or shader */ 1259 const GLenum oldType = span->array->ChanType; 1260 const GLenum newType = GL_FLOAT; 1261 if (oldType != newType) { 1262 GLvoid *src = (oldType == GL_UNSIGNED_BYTE) 1263 ? (GLvoid *) span->array->color.sz1.rgba 1264 : (GLvoid *) span->array->color.sz2.rgba; 1265 _mesa_convert_colors(oldType, src, 1266 newType, span->array->attribs[FRAG_ATTRIB_COL0], 1267 span->end, span->array->mask); 1268 span->array->ChanType = newType; 1269 } 1270 1271 /* fragment programs/shaders may need specular, fog and Z coords */ 1272 if (span->interpMask & SPAN_SPEC) 1273 interpolate_specular(span); 1274 1275 if (span->interpMask & SPAN_FOG) 1276 interpolate_fog(ctx, span); 1277 1278 if (span->interpMask & SPAN_Z) 1279 _swrast_span_interpolate_z (ctx, span); 1280 1281 if (ctx->Shader.CurrentProgram && span->interpMask & SPAN_VARYING) 1282 interpolate_varying(ctx, span); 1283 1284 if (ctx->FragmentProgram._Current && 1285 (ctx->FragmentProgram._Current->Base.InputsRead & FRAG_BIT_WPOS)) 1286 interpolate_wpos(ctx, span); 1287 1288 /* Run fragment program/shader now */ 1289 if (ctx->FragmentProgram._Current) { 1290 _swrast_exec_fragment_program(ctx, span); 1291 } 1292 else { 1293 ASSERT(ctx->ATIFragmentShader._Enabled); 1294 _swrast_exec_fragment_shader(ctx, span); 1295 } 1296 } 1297 else if (ctx->Texture._EnabledUnits && (span->arrayMask & SPAN_TEXTURE)) { 1298 /* conventional texturing */ 1299 _swrast_texture_span(ctx, span); 1300 } 1301} 1302 1303 1304 1305/** 1306 * Apply all the per-fragment operations to a span. 1307 * This now includes texturing (_swrast_write_texture_span() is history). 1308 * This function may modify any of the array values in the span. 1309 * span->interpMask and span->arrayMask may be changed but will be restored 1310 * to their original values before returning. 1311 */ 1312void 1313_swrast_write_rgba_span( GLcontext *ctx, SWspan *span) 1314{ 1315 const SWcontext *swrast = SWRAST_CONTEXT(ctx); 1316 const GLuint colorMask = *((GLuint *) ctx->Color.ColorMask); 1317 const GLbitfield origInterpMask = span->interpMask; 1318 const GLbitfield origArrayMask = span->arrayMask; 1319 const GLenum chanType = span->array->ChanType; 1320 const GLboolean shader = (ctx->FragmentProgram._Current 1321 || ctx->ATIFragmentShader._Enabled); 1322 const GLboolean shaderOrTexture = shader || ctx->Texture._EnabledUnits; 1323 GLboolean deferredTexture; 1324 1325 /* 1326 printf("%s() interp 0x%x array 0x%x\n", __FUNCTION__, 1327 span->interpMask, span->arrayMask); 1328 */ 1329 1330 ASSERT(span->primitive == GL_POINT || 1331 span->primitive == GL_LINE || 1332 span->primitive == GL_POLYGON || 1333 span->primitive == GL_BITMAP); 1334 ASSERT(span->end <= MAX_WIDTH); 1335 ASSERT((span->interpMask & span->arrayMask) == 0); 1336 ASSERT((span->interpMask & SPAN_RGBA) ^ (span->arrayMask & SPAN_RGBA)); 1337 1338 /* check for conditions that prevent deferred shading */ 1339 if (ctx->Color.AlphaEnabled) { 1340 /* alpha test depends on post-texture/shader colors */ 1341 deferredTexture = GL_FALSE; 1342 } 1343 else if (shaderOrTexture) { 1344 if (ctx->FragmentProgram._Current) { 1345 if (ctx->FragmentProgram.Current->Base.OutputsWritten 1346 & (1 << FRAG_RESULT_DEPR)) { 1347 /* Z comes from fragment program/shader */ 1348 deferredTexture = GL_FALSE; 1349 } 1350 else { 1351 deferredTexture = GL_TRUE; 1352 } 1353 } 1354 else { 1355 /* ATI frag shader or conventional texturing */ 1356 deferredTexture = GL_TRUE; 1357 } 1358 } 1359 else { 1360 /* no texturing or shadering */ 1361 deferredTexture = GL_FALSE; 1362 } 1363 1364 /* Fragment write masks */ 1365 if (span->arrayMask & SPAN_MASK) { 1366 /* mask was initialized by caller, probably glBitmap */ 1367 span->writeAll = GL_FALSE; 1368 } 1369 else { 1370 _mesa_memset(span->array->mask, 1, span->end); 1371 span->writeAll = GL_TRUE; 1372 } 1373 1374 /* Clip to window/scissor box */ 1375 if ((swrast->_RasterMask & CLIP_BIT) || (span->primitive != GL_POLYGON)) { 1376 if (!clip_span(ctx, span)) { 1377 return; 1378 } 1379 } 1380 1381#ifdef DEBUG 1382 /* Make sure all fragments are within window bounds */ 1383 if (span->arrayMask & SPAN_XY) { 1384 GLuint i; 1385 for (i = 0; i < span->end; i++) { 1386 if (span->array->mask[i]) { 1387 assert(span->array->x[i] >= ctx->DrawBuffer->_Xmin); 1388 assert(span->array->x[i] < ctx->DrawBuffer->_Xmax); 1389 assert(span->array->y[i] >= ctx->DrawBuffer->_Ymin); 1390 assert(span->array->y[i] < ctx->DrawBuffer->_Ymax); 1391 } 1392 } 1393 } 1394#endif 1395 1396 /* Polygon Stippling */ 1397 if (ctx->Polygon.StippleFlag && span->primitive == GL_POLYGON) { 1398 stipple_polygon_span(ctx, span); 1399 } 1400 1401 /* This is the normal place to compute the resulting fragment color/Z. 1402 * As an optimization, we try to defer this until after Z/stencil 1403 * testing in order to try to avoid computing colors that we won't 1404 * actually need. 1405 */ 1406 if (shaderOrTexture && !deferredTexture) { 1407 shade_texture_span(ctx, span); 1408 } 1409 1410 /* Do the alpha test */ 1411 if (ctx->Color.AlphaEnabled) { 1412 if (!_swrast_alpha_test(ctx, span)) { 1413 goto end; 1414 } 1415 } 1416 1417 /* Stencil and Z testing */ 1418 if (ctx->Stencil.Enabled || ctx->Depth.Test) { 1419 if (span->interpMask & SPAN_Z) 1420 _swrast_span_interpolate_z(ctx, span); 1421 1422 if (ctx->Stencil.Enabled && ctx->DrawBuffer->Visual.stencilBits > 0) { 1423 /* Combined Z/stencil tests */ 1424 if (!_swrast_stencil_and_ztest_span(ctx, span)) { 1425 goto end; 1426 } 1427 } 1428 else if (ctx->DrawBuffer->Visual.depthBits > 0) { 1429 /* Just regular depth testing */ 1430 ASSERT(ctx->Depth.Test); 1431 ASSERT(span->arrayMask & SPAN_Z); 1432 if (!_swrast_depth_test_span(ctx, span)) { 1433 goto end; 1434 } 1435 } 1436 } 1437 1438#if FEATURE_ARB_occlusion_query 1439 if (ctx->Query.CurrentOcclusionObject) { 1440 /* update count of 'passed' fragments */ 1441 struct gl_query_object *q = ctx->Query.CurrentOcclusionObject; 1442 GLuint i; 1443 for (i = 0; i < span->end; i++) 1444 q->Result += span->array->mask[i]; 1445 } 1446#endif 1447 1448 /* We had to wait until now to check for glColorMask(0,0,0,0) because of 1449 * the occlusion test. 1450 */ 1451 if (colorMask == 0x0) { 1452 goto end; 1453 } 1454 1455 /* If we were able to defer fragment color computation to now, there's 1456 * a good chance that many fragments will have already been killed by 1457 * Z/stencil testing. 1458 */ 1459 if (deferredTexture) { 1460 ASSERT(shaderOrTexture); 1461 shade_texture_span(ctx, span); 1462 } 1463 1464 if ((span->arrayMask & SPAN_RGBA) == 0) { 1465 interpolate_colors(span); 1466 } 1467 1468 ASSERT(span->arrayMask & SPAN_RGBA); 1469 1470 if (!shader) { 1471 /* Add base and specular colors */ 1472 if (ctx->Fog.ColorSumEnabled || 1473 (ctx->Light.Enabled && 1474 ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)) { 1475 if (span->interpMask & SPAN_SPEC) { 1476 interpolate_specular(span); 1477 } 1478 if (span->arrayMask & SPAN_SPEC) { 1479 add_specular(ctx, span); 1480 } 1481 else { 1482 /* We probably added the base/specular colors during the 1483 * vertex stage! 1484 */ 1485 } 1486 } 1487 } 1488 1489 /* Fog */ 1490 if (swrast->_FogEnabled) { 1491 _swrast_fog_rgba_span(ctx, span); 1492 } 1493 1494 /* Antialias coverage application */ 1495 if (span->arrayMask & SPAN_COVERAGE) { 1496 apply_aa_coverage(span); 1497 } 1498 1499 /* Clamp color/alpha values over the range [0.0, 1.0] before storage */ 1500 if (ctx->Color.ClampFragmentColor == GL_TRUE && 1501 span->array->ChanType == GL_FLOAT) { 1502 clamp_colors(span); 1503 } 1504 1505 /* 1506 * Write to renderbuffers 1507 */ 1508 { 1509 struct gl_framebuffer *fb = ctx->DrawBuffer; 1510 const GLuint output = 0; /* only frag progs can write to other outputs */ 1511 const GLuint numDrawBuffers = fb->_NumColorDrawBuffers[output]; 1512 GLchan rgbaSave[MAX_WIDTH][4]; 1513 GLuint buf; 1514 1515 if (numDrawBuffers > 0) { 1516 if (fb->_ColorDrawBuffers[output][0]->DataType 1517 != span->array->ChanType) { 1518 convert_color_type(span, 1519 fb->_ColorDrawBuffers[output][0]->DataType); 1520 } 1521 } 1522 1523 if (numDrawBuffers > 1) { 1524 /* save colors for second, third renderbuffer writes */ 1525 _mesa_memcpy(rgbaSave, span->array->rgba, 1526 4 * span->end * sizeof(GLchan)); 1527 } 1528 1529 for (buf = 0; buf < numDrawBuffers; buf++) { 1530 struct gl_renderbuffer *rb = fb->_ColorDrawBuffers[output][buf]; 1531 ASSERT(rb->_BaseFormat == GL_RGBA || rb->_BaseFormat == GL_RGB); 1532 1533 if (ctx->Color._LogicOpEnabled) { 1534 _swrast_logicop_rgba_span(ctx, rb, span); 1535 } 1536 else if (ctx->Color.BlendEnabled) { 1537 _swrast_blend_span(ctx, rb, span); 1538 } 1539 1540 if (colorMask != 0xffffffff) { 1541 _swrast_mask_rgba_span(ctx, rb, span); 1542 } 1543 1544 if (span->arrayMask & SPAN_XY) { 1545 /* array of pixel coords */ 1546 ASSERT(rb->PutValues); 1547 rb->PutValues(ctx, rb, span->end, 1548 span->array->x, span->array->y, 1549 span->array->rgba, span->array->mask); 1550 } 1551 else { 1552 /* horizontal run of pixels */ 1553 ASSERT(rb->PutRow); 1554 rb->PutRow(ctx, rb, span->end, span->x, span->y, span->array->rgba, 1555 span->writeAll ? NULL: span->array->mask); 1556 } 1557 1558 if (buf + 1 < numDrawBuffers) { 1559 /* restore original span values */ 1560 _mesa_memcpy(span->array->rgba, rgbaSave, 1561 4 * span->end * sizeof(GLchan)); 1562 } 1563 } /* for buf */ 1564 1565 } 1566 1567end: 1568 /* restore these values before returning */ 1569 span->interpMask = origInterpMask; 1570 span->arrayMask = origArrayMask; 1571 span->array->ChanType = chanType; 1572} 1573 1574 1575/** 1576 * Read RGBA pixels from a renderbuffer. Clipping will be done to prevent 1577 * reading ouside the buffer's boundaries. 1578 * \param dstType datatype for returned colors 1579 * \param rgba the returned colors 1580 */ 1581void 1582_swrast_read_rgba_span( GLcontext *ctx, struct gl_renderbuffer *rb, 1583 GLuint n, GLint x, GLint y, GLenum dstType, 1584 GLvoid *rgba) 1585{ 1586 const GLint bufWidth = (GLint) rb->Width; 1587 const GLint bufHeight = (GLint) rb->Height; 1588 1589 if (y < 0 || y >= bufHeight || x + (GLint) n < 0 || x >= bufWidth) { 1590 /* completely above, below, or right */ 1591 /* XXX maybe leave rgba values undefined? */ 1592 _mesa_bzero(rgba, 4 * n * sizeof(GLchan)); 1593 } 1594 else { 1595 GLint skip, length; 1596 if (x < 0) { 1597 /* left edge clipping */ 1598 skip = -x; 1599 length = (GLint) n - skip; 1600 if (length < 0) { 1601 /* completely left of window */ 1602 return; 1603 } 1604 if (length > bufWidth) { 1605 length = bufWidth; 1606 } 1607 } 1608 else if ((GLint) (x + n) > bufWidth) { 1609 /* right edge clipping */ 1610 skip = 0; 1611 length = bufWidth - x; 1612 if (length < 0) { 1613 /* completely to right of window */ 1614 return; 1615 } 1616 } 1617 else { 1618 /* no clipping */ 1619 skip = 0; 1620 length = (GLint) n; 1621 } 1622 1623 ASSERT(rb); 1624 ASSERT(rb->GetRow); 1625 ASSERT(rb->_BaseFormat == GL_RGB || rb->_BaseFormat == GL_RGBA); 1626 1627 if (rb->DataType == dstType) { 1628 rb->GetRow(ctx, rb, length, x + skip, y, 1629 (GLubyte *) rgba + skip * RGBA_PIXEL_SIZE(rb->DataType)); 1630 } 1631 else { 1632 GLuint temp[MAX_WIDTH * 4]; 1633 rb->GetRow(ctx, rb, length, x + skip, y, temp); 1634 _mesa_convert_colors(rb->DataType, temp, 1635 dstType, (GLubyte *) rgba + skip * RGBA_PIXEL_SIZE(dstType), 1636 length, NULL); 1637 } 1638 } 1639} 1640 1641 1642/** 1643 * Read CI pixels from a renderbuffer. Clipping will be done to prevent 1644 * reading ouside the buffer's boundaries. 1645 */ 1646void 1647_swrast_read_index_span( GLcontext *ctx, struct gl_renderbuffer *rb, 1648 GLuint n, GLint x, GLint y, GLuint index[] ) 1649{ 1650 const GLint bufWidth = (GLint) rb->Width; 1651 const GLint bufHeight = (GLint) rb->Height; 1652 1653 if (y < 0 || y >= bufHeight || x + (GLint) n < 0 || x >= bufWidth) { 1654 /* completely above, below, or right */ 1655 _mesa_bzero(index, n * sizeof(GLuint)); 1656 } 1657 else { 1658 GLint skip, length; 1659 if (x < 0) { 1660 /* left edge clipping */ 1661 skip = -x; 1662 length = (GLint) n - skip; 1663 if (length < 0) { 1664 /* completely left of window */ 1665 return; 1666 } 1667 if (length > bufWidth) { 1668 length = bufWidth; 1669 } 1670 } 1671 else if ((GLint) (x + n) > bufWidth) { 1672 /* right edge clipping */ 1673 skip = 0; 1674 length = bufWidth - x; 1675 if (length < 0) { 1676 /* completely to right of window */ 1677 return; 1678 } 1679 } 1680 else { 1681 /* no clipping */ 1682 skip = 0; 1683 length = (GLint) n; 1684 } 1685 1686 ASSERT(rb->GetRow); 1687 ASSERT(rb->_BaseFormat == GL_COLOR_INDEX); 1688 1689 if (rb->DataType == GL_UNSIGNED_BYTE) { 1690 GLubyte index8[MAX_WIDTH]; 1691 GLint i; 1692 rb->GetRow(ctx, rb, length, x + skip, y, index8); 1693 for (i = 0; i < length; i++) 1694 index[skip + i] = index8[i]; 1695 } 1696 else if (rb->DataType == GL_UNSIGNED_SHORT) { 1697 GLushort index16[MAX_WIDTH]; 1698 GLint i; 1699 rb->GetRow(ctx, rb, length, x + skip, y, index16); 1700 for (i = 0; i < length; i++) 1701 index[skip + i] = index16[i]; 1702 } 1703 else if (rb->DataType == GL_UNSIGNED_INT) { 1704 rb->GetRow(ctx, rb, length, x + skip, y, index + skip); 1705 } 1706 } 1707} 1708 1709 1710/** 1711 * Wrapper for gl_renderbuffer::GetValues() which does clipping to avoid 1712 * reading values outside the buffer bounds. 1713 * We can use this for reading any format/type of renderbuffer. 1714 * \param valueSize is the size in bytes of each value (pixel) put into the 1715 * values array. 1716 */ 1717void 1718_swrast_get_values(GLcontext *ctx, struct gl_renderbuffer *rb, 1719 GLuint count, const GLint x[], const GLint y[], 1720 void *values, GLuint valueSize) 1721{ 1722 GLuint i, inCount = 0, inStart = 0; 1723 1724 for (i = 0; i < count; i++) { 1725 if (x[i] >= 0 && y[i] >= 0 && 1726 x[i] < (GLint) rb->Width && y[i] < (GLint) rb->Height) { 1727 /* inside */ 1728 if (inCount == 0) 1729 inStart = i; 1730 inCount++; 1731 } 1732 else { 1733 if (inCount > 0) { 1734 /* read [inStart, inStart + inCount) */ 1735 rb->GetValues(ctx, rb, inCount, x + inStart, y + inStart, 1736 (GLubyte *) values + inStart * valueSize); 1737 inCount = 0; 1738 } 1739 } 1740 } 1741 if (inCount > 0) { 1742 /* read last values */ 1743 rb->GetValues(ctx, rb, inCount, x + inStart, y + inStart, 1744 (GLubyte *) values + inStart * valueSize); 1745 } 1746} 1747 1748 1749/** 1750 * Wrapper for gl_renderbuffer::PutRow() which does clipping. 1751 * \param valueSize size of each value (pixel) in bytes 1752 */ 1753void 1754_swrast_put_row(GLcontext *ctx, struct gl_renderbuffer *rb, 1755 GLuint count, GLint x, GLint y, 1756 const GLvoid *values, GLuint valueSize) 1757{ 1758 GLint skip = 0; 1759 1760 if (y < 0 || y >= (GLint) rb->Height) 1761 return; /* above or below */ 1762 1763 if (x + (GLint) count <= 0 || x >= (GLint) rb->Width) 1764 return; /* entirely left or right */ 1765 1766 if ((GLint) (x + count) > (GLint) rb->Width) { 1767 /* right clip */ 1768 GLint clip = x + count - rb->Width; 1769 count -= clip; 1770 } 1771 1772 if (x < 0) { 1773 /* left clip */ 1774 skip = -x; 1775 x = 0; 1776 count -= skip; 1777 } 1778 1779 rb->PutRow(ctx, rb, count, x, y, 1780 (const GLubyte *) values + skip * valueSize, NULL); 1781} 1782 1783 1784/** 1785 * Wrapper for gl_renderbuffer::GetRow() which does clipping. 1786 * \param valueSize size of each value (pixel) in bytes 1787 */ 1788void 1789_swrast_get_row(GLcontext *ctx, struct gl_renderbuffer *rb, 1790 GLuint count, GLint x, GLint y, 1791 GLvoid *values, GLuint valueSize) 1792{ 1793 GLint skip = 0; 1794 1795 if (y < 0 || y >= (GLint) rb->Height) 1796 return; /* above or below */ 1797 1798 if (x + (GLint) count <= 0 || x >= (GLint) rb->Width) 1799 return; /* entirely left or right */ 1800 1801 if (x + count > rb->Width) { 1802 /* right clip */ 1803 GLint clip = x + count - rb->Width; 1804 count -= clip; 1805 } 1806 1807 if (x < 0) { 1808 /* left clip */ 1809 skip = -x; 1810 x = 0; 1811 count -= skip; 1812 } 1813 1814 rb->GetRow(ctx, rb, count, x, y, (GLubyte *) values + skip * valueSize); 1815} 1816 1817 1818/** 1819 * Get RGBA pixels from the given renderbuffer. Put the pixel colors into 1820 * the span's specular color arrays. The specular color arrays should no 1821 * longer be needed by time this function is called. 1822 * Used by blending, logicop and masking functions. 1823 * \return pointer to the colors we read. 1824 */ 1825void * 1826_swrast_get_dest_rgba(GLcontext *ctx, struct gl_renderbuffer *rb, 1827 SWspan *span) 1828{ 1829 const GLuint pixelSize = RGBA_PIXEL_SIZE(span->array->ChanType); 1830 void *rbPixels; 1831 1832 /* 1833 * Determine pixel size (in bytes). 1834 * Point rbPixels to a temporary space (use specular color arrays). 1835 */ 1836 if (span->array->ChanType == GL_UNSIGNED_BYTE) { 1837 rbPixels = span->array->color.sz1.spec; 1838 } 1839 else if (span->array->ChanType == GL_UNSIGNED_SHORT) { 1840 rbPixels = span->array->color.sz2.spec; 1841 } 1842 else { 1843 rbPixels = span->array->attribs[FRAG_ATTRIB_COL1]; 1844 } 1845 1846 /* Get destination values from renderbuffer */ 1847 if (span->arrayMask & SPAN_XY) { 1848 _swrast_get_values(ctx, rb, span->end, span->array->x, span->array->y, 1849 rbPixels, pixelSize); 1850 } 1851 else { 1852 _swrast_get_row(ctx, rb, span->end, span->x, span->y, 1853 rbPixels, pixelSize); 1854 } 1855 1856 return rbPixels; 1857} 1858