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