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