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