1 /* 2 * Mesa 3-D graphics library 3 * 4 * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. 5 * Copyright (C) 2009 VMware, Inc. 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 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 * OTHER DEALINGS IN THE SOFTWARE. 24 */ 25 26 27 /** 28 * \file swrast/s_span.c 29 * \brief Span processing functions used by all rasterization functions. 30 * This is where all the per-fragment tests are performed 31 * \author Brian Paul 32 */ 33 34 #include "c99_math.h" 35 #include "main/glheader.h" 36 #include "main/format_pack.h" 37 #include "main/format_unpack.h" 38 #include "main/macros.h" 39 #include "main/imports.h" 40 #include "main/image.h" 41 #include "main/samplerobj.h" 42 #include "main/teximage.h" 43 44 #include "s_atifragshader.h" 45 #include "s_alpha.h" 46 #include "s_blend.h" 47 #include "s_context.h" 48 #include "s_depth.h" 49 #include "s_fog.h" 50 #include "s_logic.h" 51 #include "s_masking.h" 52 #include "s_fragprog.h" 53 #include "s_span.h" 54 #include "s_stencil.h" 55 #include "s_texcombine.h" 56 57 #include <stdbool.h> 58 59 /** 60 * Set default fragment attributes for the span using the 61 * current raster values. Used prior to glDraw/CopyPixels 62 * and glBitmap. 63 */ 64 void 65 _swrast_span_default_attribs(struct gl_context *ctx, SWspan *span) 66 { 67 GLchan r, g, b, a; 68 /* Z*/ 69 { 70 const GLfloat depthMax = ctx->DrawBuffer->_DepthMaxF; 71 if (ctx->DrawBuffer->Visual.depthBits <= 16) 72 span->z = FloatToFixed(ctx->Current.RasterPos[2] * depthMax + 0.5F); 73 else { 74 GLfloat tmpf = ctx->Current.RasterPos[2] * depthMax; 75 tmpf = MIN2(tmpf, depthMax); 76 span->z = (GLint)tmpf; 77 } 78 span->zStep = 0; 79 span->interpMask |= SPAN_Z; 80 } 81 82 /* W (for perspective correction) */ 83 span->attrStart[VARYING_SLOT_POS][3] = 1.0; 84 span->attrStepX[VARYING_SLOT_POS][3] = 0.0; 85 span->attrStepY[VARYING_SLOT_POS][3] = 0.0; 86 87 /* primary color, or color index */ 88 UNCLAMPED_FLOAT_TO_CHAN(r, ctx->Current.RasterColor[0]); 89 UNCLAMPED_FLOAT_TO_CHAN(g, ctx->Current.RasterColor[1]); 90 UNCLAMPED_FLOAT_TO_CHAN(b, ctx->Current.RasterColor[2]); 91 UNCLAMPED_FLOAT_TO_CHAN(a, ctx->Current.RasterColor[3]); 92 #if CHAN_TYPE == GL_FLOAT 93 span->red = r; 94 span->green = g; 95 span->blue = b; 96 span->alpha = a; 97 #else 98 span->red = IntToFixed(r); 99 span->green = IntToFixed(g); 100 span->blue = IntToFixed(b); 101 span->alpha = IntToFixed(a); 102 #endif 103 span->redStep = 0; 104 span->greenStep = 0; 105 span->blueStep = 0; 106 span->alphaStep = 0; 107 span->interpMask |= SPAN_RGBA; 108 109 COPY_4V(span->attrStart[VARYING_SLOT_COL0], ctx->Current.RasterColor); 110 ASSIGN_4V(span->attrStepX[VARYING_SLOT_COL0], 0.0, 0.0, 0.0, 0.0); 111 ASSIGN_4V(span->attrStepY[VARYING_SLOT_COL0], 0.0, 0.0, 0.0, 0.0); 112 113 /* Secondary color */ 114 if (ctx->Light.Enabled || ctx->Fog.ColorSumEnabled) 115 { 116 COPY_4V(span->attrStart[VARYING_SLOT_COL1], ctx->Current.RasterSecondaryColor); 117 ASSIGN_4V(span->attrStepX[VARYING_SLOT_COL1], 0.0, 0.0, 0.0, 0.0); 118 ASSIGN_4V(span->attrStepY[VARYING_SLOT_COL1], 0.0, 0.0, 0.0, 0.0); 119 } 120 121 /* fog */ 122 { 123 const SWcontext *swrast = SWRAST_CONTEXT(ctx); 124 GLfloat fogVal; /* a coord or a blend factor */ 125 if (swrast->_PreferPixelFog) { 126 /* fog blend factors will be computed from fog coordinates per pixel */ 127 fogVal = ctx->Current.RasterDistance; 128 } 129 else { 130 /* fog blend factor should be computed from fogcoord now */ 131 fogVal = _swrast_z_to_fogfactor(ctx, ctx->Current.RasterDistance); 132 } 133 span->attrStart[VARYING_SLOT_FOGC][0] = fogVal; 134 span->attrStepX[VARYING_SLOT_FOGC][0] = 0.0; 135 span->attrStepY[VARYING_SLOT_FOGC][0] = 0.0; 136 } 137 138 /* texcoords */ 139 { 140 GLuint i; 141 for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) { 142 const GLuint attr = VARYING_SLOT_TEX0 + i; 143 const GLfloat *tc = ctx->Current.RasterTexCoords[i]; 144 if (_swrast_use_fragment_program(ctx) || 145 ctx->ATIFragmentShader._Enabled) { 146 COPY_4V(span->attrStart[attr], tc); 147 } 148 else if (tc[3] > 0.0F) { 149 /* use (s/q, t/q, r/q, 1) */ 150 span->attrStart[attr][0] = tc[0] / tc[3]; 151 span->attrStart[attr][1] = tc[1] / tc[3]; 152 span->attrStart[attr][2] = tc[2] / tc[3]; 153 span->attrStart[attr][3] = 1.0; 154 } 155 else { 156 ASSIGN_4V(span->attrStart[attr], 0.0F, 0.0F, 0.0F, 1.0F); 157 } 158 ASSIGN_4V(span->attrStepX[attr], 0.0F, 0.0F, 0.0F, 0.0F); 159 ASSIGN_4V(span->attrStepY[attr], 0.0F, 0.0F, 0.0F, 0.0F); 160 } 161 } 162 } 163 164 165 /** 166 * Interpolate the active attributes (and'd with attrMask) to 167 * fill in span->array->attribs[]. 168 * Perspective correction will be done. The point/line/triangle function 169 * should have computed attrStart/Step values for VARYING_SLOT_POS[3]! 170 */ 171 static inline void 172 interpolate_active_attribs(struct gl_context *ctx, SWspan *span, 173 GLbitfield64 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 & BITFIELD64_BIT(attr)) { 185 const GLfloat dwdx = span->attrStepX[VARYING_SLOT_POS][3]; 186 GLfloat w = span->attrStart[VARYING_SLOT_POS][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] + span->leftClip * dv0dx; 192 GLfloat v1 = span->attrStart[attr][1] + span->leftClip * dv1dx; 193 GLfloat v2 = span->attrStart[attr][2] + span->leftClip * dv2dx; 194 GLfloat v3 = span->attrStart[attr][3] + span->leftClip * dv3dx; 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 & BITFIELD64_BIT(attr)) == 0); 209 span->arrayAttribs |= BITFIELD64_BIT(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 */ 219 static inline void 220 interpolate_int_colors(struct gl_context *ctx, SWspan *span) 221 { 222 #if CHAN_BITS != 32 223 const GLuint n = span->end; 224 GLuint i; 225 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, VARYING_BIT_COL0); 307 break; 308 default: 309 _mesa_problem(ctx, "bad datatype 0x%x in interpolate_int_colors", 310 span->array->ChanType); 311 } 312 span->arrayMask |= SPAN_RGBA; 313 } 314 315 316 /** 317 * Populate the VARYING_SLOT_COL0 array. 318 */ 319 static inline void 320 interpolate_float_colors(SWspan *span) 321 { 322 GLfloat (*col0)[4] = span->array->attribs[VARYING_SLOT_COL0]; 323 const GLuint n = span->end; 324 GLuint i; 325 326 assert(!(span->arrayAttribs & VARYING_BIT_COL0)); 327 328 if (span->arrayMask & SPAN_RGBA) { 329 /* convert array of int colors */ 330 for (i = 0; i < n; i++) { 331 col0[i][0] = UBYTE_TO_FLOAT(span->array->rgba8[i][0]); 332 col0[i][1] = UBYTE_TO_FLOAT(span->array->rgba8[i][1]); 333 col0[i][2] = UBYTE_TO_FLOAT(span->array->rgba8[i][2]); 334 col0[i][3] = UBYTE_TO_FLOAT(span->array->rgba8[i][3]); 335 } 336 } 337 else { 338 /* interpolate red/green/blue/alpha to get float colors */ 339 assert(span->interpMask & SPAN_RGBA); 340 if (span->interpMask & SPAN_FLAT) { 341 GLfloat r = FixedToFloat(span->red); 342 GLfloat g = FixedToFloat(span->green); 343 GLfloat b = FixedToFloat(span->blue); 344 GLfloat a = FixedToFloat(span->alpha); 345 for (i = 0; i < n; i++) { 346 ASSIGN_4V(col0[i], r, g, b, a); 347 } 348 } 349 else { 350 GLfloat r = FixedToFloat(span->red); 351 GLfloat g = FixedToFloat(span->green); 352 GLfloat b = FixedToFloat(span->blue); 353 GLfloat a = FixedToFloat(span->alpha); 354 GLfloat dr = FixedToFloat(span->redStep); 355 GLfloat dg = FixedToFloat(span->greenStep); 356 GLfloat db = FixedToFloat(span->blueStep); 357 GLfloat da = FixedToFloat(span->alphaStep); 358 for (i = 0; i < n; i++) { 359 col0[i][0] = r; 360 col0[i][1] = g; 361 col0[i][2] = b; 362 col0[i][3] = a; 363 r += dr; 364 g += dg; 365 b += db; 366 a += da; 367 } 368 } 369 } 370 371 span->arrayAttribs |= VARYING_BIT_COL0; 372 span->array->ChanType = GL_FLOAT; 373 } 374 375 376 377 /** 378 * Fill in the span.zArray array from the span->z, zStep values. 379 */ 380 void 381 _swrast_span_interpolate_z( const struct gl_context *ctx, SWspan *span ) 382 { 383 const GLuint n = span->end; 384 GLuint i; 385 386 assert(!(span->arrayMask & SPAN_Z)); 387 388 if (ctx->DrawBuffer->Visual.depthBits <= 16) { 389 GLfixed zval = span->z; 390 GLuint *z = span->array->z; 391 for (i = 0; i < n; i++) { 392 z[i] = FixedToInt(zval); 393 zval += span->zStep; 394 } 395 } 396 else { 397 /* Deep Z buffer, no fixed->int shift */ 398 GLuint zval = span->z; 399 GLuint *z = span->array->z; 400 for (i = 0; i < n; i++) { 401 z[i] = zval; 402 zval += span->zStep; 403 } 404 } 405 span->interpMask &= ~SPAN_Z; 406 span->arrayMask |= SPAN_Z; 407 } 408 409 410 /** 411 * Compute mipmap LOD from partial derivatives. 412 * This the ideal solution, as given in the OpenGL spec. 413 */ 414 GLfloat 415 _swrast_compute_lambda(GLfloat dsdx, GLfloat dsdy, GLfloat dtdx, GLfloat dtdy, 416 GLfloat dqdx, GLfloat dqdy, GLfloat texW, GLfloat texH, 417 GLfloat s, GLfloat t, GLfloat q, GLfloat invQ) 418 { 419 GLfloat dudx = texW * ((s + dsdx) / (q + dqdx) - s * invQ); 420 GLfloat dvdx = texH * ((t + dtdx) / (q + dqdx) - t * invQ); 421 GLfloat dudy = texW * ((s + dsdy) / (q + dqdy) - s * invQ); 422 GLfloat dvdy = texH * ((t + dtdy) / (q + dqdy) - t * invQ); 423 GLfloat x = sqrtf(dudx * dudx + dvdx * dvdx); 424 GLfloat y = sqrtf(dudy * dudy + dvdy * dvdy); 425 GLfloat rho = MAX2(x, y); 426 GLfloat lambda = LOG2(rho); 427 return lambda; 428 } 429 430 431 /** 432 * Compute mipmap LOD from partial derivatives. 433 * This is a faster approximation than above function. 434 */ 435 #if 0 436 GLfloat 437 _swrast_compute_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 dsdx2 = (s + dsdx) / (q + dqdx) - s * invQ; 442 GLfloat dtdx2 = (t + dtdx) / (q + dqdx) - t * invQ; 443 GLfloat dsdy2 = (s + dsdy) / (q + dqdy) - s * invQ; 444 GLfloat dtdy2 = (t + dtdy) / (q + dqdy) - t * invQ; 445 GLfloat maxU, maxV, rho, lambda; 446 dsdx2 = fabsf(dsdx2); 447 dsdy2 = fabsf(dsdy2); 448 dtdx2 = fabsf(dtdx2); 449 dtdy2 = fabsf(dtdy2); 450 maxU = MAX2(dsdx2, dsdy2) * texW; 451 maxV = MAX2(dtdx2, dtdy2) * texH; 452 rho = MAX2(maxU, maxV); 453 lambda = LOG2(rho); 454 return lambda; 455 } 456 #endif 457 458 459 /** 460 * Fill in the span.array->attrib[VARYING_SLOT_TEXn] arrays from the 461 * using the attrStart/Step values. 462 * 463 * This function only used during fixed-function fragment processing. 464 * 465 * Note: in the places where we divide by Q (or mult by invQ) we're 466 * really doing two things: perspective correction and texcoord 467 * projection. Remember, for texcoord (s,t,r,q) we need to index 468 * texels with (s/q, t/q, r/q). 469 */ 470 static void 471 interpolate_texcoords(struct gl_context *ctx, SWspan *span) 472 { 473 const GLuint maxUnit 474 = (ctx->Texture._EnabledCoordUnits > 1) ? ctx->Const.MaxTextureUnits : 1; 475 GLuint u; 476 477 /* XXX CoordUnits vs. ImageUnits */ 478 for (u = 0; u < maxUnit; u++) { 479 if (ctx->Texture._EnabledCoordUnits & (1 << u)) { 480 const GLuint attr = VARYING_SLOT_TEX0 + u; 481 const struct gl_texture_object *obj = ctx->Texture.Unit[u]._Current; 482 GLfloat texW, texH; 483 GLboolean needLambda; 484 GLfloat (*texcoord)[4] = span->array->attribs[attr]; 485 GLfloat *lambda = span->array->lambda[u]; 486 const GLfloat dsdx = span->attrStepX[attr][0]; 487 const GLfloat dsdy = span->attrStepY[attr][0]; 488 const GLfloat dtdx = span->attrStepX[attr][1]; 489 const GLfloat dtdy = span->attrStepY[attr][1]; 490 const GLfloat drdx = span->attrStepX[attr][2]; 491 const GLfloat dqdx = span->attrStepX[attr][3]; 492 const GLfloat dqdy = span->attrStepY[attr][3]; 493 GLfloat s = span->attrStart[attr][0] + span->leftClip * dsdx; 494 GLfloat t = span->attrStart[attr][1] + span->leftClip * dtdx; 495 GLfloat r = span->attrStart[attr][2] + span->leftClip * drdx; 496 GLfloat q = span->attrStart[attr][3] + span->leftClip * dqdx; 497 498 if (obj) { 499 const struct gl_texture_image *img = _mesa_base_tex_image(obj); 500 const struct swrast_texture_image *swImg = 501 swrast_texture_image_const(img); 502 const struct gl_sampler_object *samp = _mesa_get_samplerobj(ctx, u); 503 504 needLambda = (samp->MinFilter != samp->MagFilter) 505 || _swrast_use_fragment_program(ctx); 506 /* LOD is calculated directly in the ansiotropic filter, we can 507 * skip the normal lambda function as the result is ignored. 508 */ 509 if (samp->MaxAnisotropy > 1.0F && 510 samp->MinFilter == GL_LINEAR_MIPMAP_LINEAR) { 511 needLambda = GL_FALSE; 512 } 513 texW = swImg->WidthScale; 514 texH = swImg->HeightScale; 515 } 516 else { 517 /* using a fragment program */ 518 texW = 1.0; 519 texH = 1.0; 520 needLambda = GL_FALSE; 521 } 522 523 if (needLambda) { 524 GLuint i; 525 if (_swrast_use_fragment_program(ctx) 526 || ctx->ATIFragmentShader._Enabled) { 527 /* do perspective correction but don't divide s, t, r by q */ 528 const GLfloat dwdx = span->attrStepX[VARYING_SLOT_POS][3]; 529 GLfloat w = span->attrStart[VARYING_SLOT_POS][3] + span->leftClip * dwdx; 530 for (i = 0; i < span->end; i++) { 531 const GLfloat invW = 1.0F / w; 532 texcoord[i][0] = s * invW; 533 texcoord[i][1] = t * invW; 534 texcoord[i][2] = r * invW; 535 texcoord[i][3] = q * invW; 536 lambda[i] = _swrast_compute_lambda(dsdx, dsdy, dtdx, dtdy, 537 dqdx, dqdy, texW, texH, 538 s, t, q, invW); 539 s += dsdx; 540 t += dtdx; 541 r += drdx; 542 q += dqdx; 543 w += dwdx; 544 } 545 } 546 else { 547 for (i = 0; i < span->end; i++) { 548 const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q); 549 texcoord[i][0] = s * invQ; 550 texcoord[i][1] = t * invQ; 551 texcoord[i][2] = r * invQ; 552 texcoord[i][3] = q; 553 lambda[i] = _swrast_compute_lambda(dsdx, dsdy, dtdx, dtdy, 554 dqdx, dqdy, texW, texH, 555 s, t, q, invQ); 556 s += dsdx; 557 t += dtdx; 558 r += drdx; 559 q += dqdx; 560 } 561 } 562 span->arrayMask |= SPAN_LAMBDA; 563 } 564 else { 565 GLuint i; 566 if (_swrast_use_fragment_program(ctx) || 567 ctx->ATIFragmentShader._Enabled) { 568 /* do perspective correction but don't divide s, t, r by q */ 569 const GLfloat dwdx = span->attrStepX[VARYING_SLOT_POS][3]; 570 GLfloat w = span->attrStart[VARYING_SLOT_POS][3] + span->leftClip * dwdx; 571 for (i = 0; i < span->end; i++) { 572 const GLfloat invW = 1.0F / w; 573 texcoord[i][0] = s * invW; 574 texcoord[i][1] = t * invW; 575 texcoord[i][2] = r * invW; 576 texcoord[i][3] = q * invW; 577 lambda[i] = 0.0; 578 s += dsdx; 579 t += dtdx; 580 r += drdx; 581 q += dqdx; 582 w += dwdx; 583 } 584 } 585 else if (dqdx == 0.0F) { 586 /* Ortho projection or polygon's parallel to window X axis */ 587 const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q); 588 for (i = 0; i < span->end; i++) { 589 texcoord[i][0] = s * invQ; 590 texcoord[i][1] = t * invQ; 591 texcoord[i][2] = r * invQ; 592 texcoord[i][3] = q; 593 lambda[i] = 0.0; 594 s += dsdx; 595 t += dtdx; 596 r += drdx; 597 } 598 } 599 else { 600 for (i = 0; i < span->end; i++) { 601 const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q); 602 texcoord[i][0] = s * invQ; 603 texcoord[i][1] = t * invQ; 604 texcoord[i][2] = r * invQ; 605 texcoord[i][3] = q; 606 lambda[i] = 0.0; 607 s += dsdx; 608 t += dtdx; 609 r += drdx; 610 q += dqdx; 611 } 612 } 613 } /* lambda */ 614 } /* if */ 615 } /* for */ 616 } 617 618 619 /** 620 * Fill in the arrays->attribs[VARYING_SLOT_POS] array. 621 */ 622 static inline void 623 interpolate_wpos(struct gl_context *ctx, SWspan *span) 624 { 625 GLfloat (*wpos)[4] = span->array->attribs[VARYING_SLOT_POS]; 626 GLuint i; 627 const GLfloat zScale = 1.0F / ctx->DrawBuffer->_DepthMaxF; 628 GLfloat w, dw; 629 630 if (span->arrayMask & SPAN_XY) { 631 for (i = 0; i < span->end; i++) { 632 wpos[i][0] = (GLfloat) span->array->x[i]; 633 wpos[i][1] = (GLfloat) span->array->y[i]; 634 } 635 } 636 else { 637 for (i = 0; i < span->end; i++) { 638 wpos[i][0] = (GLfloat) span->x + i; 639 wpos[i][1] = (GLfloat) span->y; 640 } 641 } 642 643 dw = span->attrStepX[VARYING_SLOT_POS][3]; 644 w = span->attrStart[VARYING_SLOT_POS][3] + span->leftClip * dw; 645 for (i = 0; i < span->end; i++) { 646 wpos[i][2] = (GLfloat) span->array->z[i] * zScale; 647 wpos[i][3] = w; 648 w += dw; 649 } 650 } 651 652 653 /** 654 * Apply the current polygon stipple pattern to a span of pixels. 655 */ 656 static inline void 657 stipple_polygon_span(struct gl_context *ctx, SWspan *span) 658 { 659 GLubyte *mask = span->array->mask; 660 661 assert(ctx->Polygon.StippleFlag); 662 663 if (span->arrayMask & SPAN_XY) { 664 /* arrays of x/y pixel coords */ 665 GLuint i; 666 for (i = 0; i < span->end; i++) { 667 const GLint col = span->array->x[i] % 32; 668 const GLint row = span->array->y[i] % 32; 669 const GLuint stipple = ctx->PolygonStipple[row]; 670 if (((1 << col) & stipple) == 0) { 671 mask[i] = 0; 672 } 673 } 674 } 675 else { 676 /* horizontal span of pixels */ 677 const GLuint highBit = 1 << 31; 678 const GLuint stipple = ctx->PolygonStipple[span->y % 32]; 679 GLuint i, m = highBit >> (GLuint) (span->x % 32); 680 for (i = 0; i < span->end; i++) { 681 if ((m & stipple) == 0) { 682 mask[i] = 0; 683 } 684 m = m >> 1; 685 if (m == 0) { 686 m = highBit; 687 } 688 } 689 } 690 span->writeAll = GL_FALSE; 691 } 692 693 694 /** 695 * Clip a pixel span to the current buffer/window boundaries: 696 * DrawBuffer->_Xmin, _Xmax, _Ymin, _Ymax. This will accomplish 697 * window clipping and scissoring. 698 * Return: GL_TRUE some pixels still visible 699 * GL_FALSE nothing visible 700 */ 701 static inline GLuint 702 clip_span( struct gl_context *ctx, SWspan *span ) 703 { 704 const GLint xmin = ctx->DrawBuffer->_Xmin; 705 const GLint xmax = ctx->DrawBuffer->_Xmax; 706 const GLint ymin = ctx->DrawBuffer->_Ymin; 707 const GLint ymax = ctx->DrawBuffer->_Ymax; 708 709 span->leftClip = 0; 710 711 if (span->arrayMask & SPAN_XY) { 712 /* arrays of x/y pixel coords */ 713 const GLint *x = span->array->x; 714 const GLint *y = span->array->y; 715 const GLint n = span->end; 716 GLubyte *mask = span->array->mask; 717 GLint i; 718 GLuint passed = 0; 719 if (span->arrayMask & SPAN_MASK) { 720 /* note: using & intead of && to reduce branches */ 721 for (i = 0; i < n; i++) { 722 mask[i] &= (x[i] >= xmin) & (x[i] < xmax) 723 & (y[i] >= ymin) & (y[i] < ymax); 724 passed += mask[i]; 725 } 726 } 727 else { 728 /* note: using & intead of && to reduce branches */ 729 for (i = 0; i < n; i++) { 730 mask[i] = (x[i] >= xmin) & (x[i] < xmax) 731 & (y[i] >= ymin) & (y[i] < ymax); 732 passed += mask[i]; 733 } 734 } 735 return passed > 0; 736 } 737 else { 738 /* horizontal span of pixels */ 739 const GLint x = span->x; 740 const GLint y = span->y; 741 GLint n = span->end; 742 743 /* Trivial rejection tests */ 744 if (y < ymin || y >= ymax || x + n <= xmin || x >= xmax) { 745 span->end = 0; 746 return GL_FALSE; /* all pixels clipped */ 747 } 748 749 /* Clip to right */ 750 if (x + n > xmax) { 751 assert(x < xmax); 752 n = span->end = xmax - x; 753 } 754 755 /* Clip to the left */ 756 if (x < xmin) { 757 const GLint leftClip = xmin - x; 758 GLuint i; 759 760 assert(leftClip > 0); 761 assert(x + n > xmin); 762 763 /* Clip 'leftClip' pixels from the left side. 764 * The span->leftClip field will be applied when we interpolate 765 * fragment attributes. 766 * For arrays of values, shift them left. 767 */ 768 for (i = 0; i < VARYING_SLOT_MAX; i++) { 769 if (span->interpMask & (1 << i)) { 770 GLuint j; 771 for (j = 0; j < 4; j++) { 772 span->attrStart[i][j] += leftClip * span->attrStepX[i][j]; 773 } 774 } 775 } 776 777 span->red += leftClip * span->redStep; 778 span->green += leftClip * span->greenStep; 779 span->blue += leftClip * span->blueStep; 780 span->alpha += leftClip * span->alphaStep; 781 span->index += leftClip * span->indexStep; 782 span->z += leftClip * span->zStep; 783 span->intTex[0] += leftClip * span->intTexStep[0]; 784 span->intTex[1] += leftClip * span->intTexStep[1]; 785 786 #define SHIFT_ARRAY(ARRAY, SHIFT, LEN) \ 787 memmove(ARRAY, ARRAY + (SHIFT), (LEN) * sizeof(ARRAY[0])) 788 789 for (i = 0; i < VARYING_SLOT_MAX; i++) { 790 if (span->arrayAttribs & BITFIELD64_BIT(i)) { 791 /* shift array elements left by 'leftClip' */ 792 SHIFT_ARRAY(span->array->attribs[i], leftClip, n - leftClip); 793 } 794 } 795 796 SHIFT_ARRAY(span->array->mask, leftClip, n - leftClip); 797 SHIFT_ARRAY(span->array->rgba8, leftClip, n - leftClip); 798 SHIFT_ARRAY(span->array->rgba16, leftClip, n - leftClip); 799 SHIFT_ARRAY(span->array->x, leftClip, n - leftClip); 800 SHIFT_ARRAY(span->array->y, leftClip, n - leftClip); 801 SHIFT_ARRAY(span->array->z, leftClip, n - leftClip); 802 SHIFT_ARRAY(span->array->index, leftClip, n - leftClip); 803 for (i = 0; i < MAX_TEXTURE_COORD_UNITS; i++) { 804 SHIFT_ARRAY(span->array->lambda[i], leftClip, n - leftClip); 805 } 806 SHIFT_ARRAY(span->array->coverage, leftClip, n - leftClip); 807 808 #undef SHIFT_ARRAY 809 810 span->leftClip = leftClip; 811 span->x = xmin; 812 span->end -= leftClip; 813 span->writeAll = GL_FALSE; 814 } 815 816 assert(span->x >= xmin); 817 assert(span->x + span->end <= xmax); 818 assert(span->y >= ymin); 819 assert(span->y < ymax); 820 821 return GL_TRUE; /* some pixels visible */ 822 } 823 } 824 825 826 /** 827 * Add specular colors to primary colors. 828 * Only called during fixed-function operation. 829 * Result is float color array (VARYING_SLOT_COL0). 830 */ 831 static inline void 832 add_specular(struct gl_context *ctx, SWspan *span) 833 { 834 const SWcontext *swrast = SWRAST_CONTEXT(ctx); 835 const GLubyte *mask = span->array->mask; 836 GLfloat (*col0)[4] = span->array->attribs[VARYING_SLOT_COL0]; 837 GLfloat (*col1)[4] = span->array->attribs[VARYING_SLOT_COL1]; 838 GLuint i; 839 840 assert(!_swrast_use_fragment_program(ctx)); 841 assert(span->arrayMask & SPAN_RGBA); 842 assert(swrast->_ActiveAttribMask & VARYING_BIT_COL1); 843 (void) swrast; /* silence warning */ 844 845 if (span->array->ChanType == GL_FLOAT) { 846 if ((span->arrayAttribs & VARYING_BIT_COL0) == 0) { 847 interpolate_active_attribs(ctx, span, VARYING_BIT_COL0); 848 } 849 } 850 else { 851 /* need float colors */ 852 if ((span->arrayAttribs & VARYING_BIT_COL0) == 0) { 853 interpolate_float_colors(span); 854 } 855 } 856 857 if ((span->arrayAttribs & VARYING_BIT_COL1) == 0) { 858 /* XXX could avoid this and interpolate COL1 in the loop below */ 859 interpolate_active_attribs(ctx, span, VARYING_BIT_COL1); 860 } 861 862 assert(span->arrayAttribs & VARYING_BIT_COL0); 863 assert(span->arrayAttribs & VARYING_BIT_COL1); 864 865 for (i = 0; i < span->end; i++) { 866 if (mask[i]) { 867 col0[i][0] += col1[i][0]; 868 col0[i][1] += col1[i][1]; 869 col0[i][2] += col1[i][2]; 870 } 871 } 872 873 span->array->ChanType = GL_FLOAT; 874 } 875 876 877 /** 878 * Apply antialiasing coverage value to alpha values. 879 */ 880 static inline void 881 apply_aa_coverage(SWspan *span) 882 { 883 const GLfloat *coverage = span->array->coverage; 884 GLuint i; 885 if (span->array->ChanType == GL_UNSIGNED_BYTE) { 886 GLubyte (*rgba)[4] = span->array->rgba8; 887 for (i = 0; i < span->end; i++) { 888 const GLfloat a = rgba[i][ACOMP] * coverage[i]; 889 rgba[i][ACOMP] = (GLubyte) CLAMP(a, 0.0F, 255.0F); 890 assert(coverage[i] >= 0.0F); 891 assert(coverage[i] <= 1.0F); 892 } 893 } 894 else if (span->array->ChanType == GL_UNSIGNED_SHORT) { 895 GLushort (*rgba)[4] = span->array->rgba16; 896 for (i = 0; i < span->end; i++) { 897 const GLfloat a = rgba[i][ACOMP] * coverage[i]; 898 rgba[i][ACOMP] = (GLushort) CLAMP(a, 0.0F, 65535.0F); 899 } 900 } 901 else { 902 GLfloat (*rgba)[4] = span->array->attribs[VARYING_SLOT_COL0]; 903 for (i = 0; i < span->end; i++) { 904 rgba[i][ACOMP] = rgba[i][ACOMP] * coverage[i]; 905 /* clamp later */ 906 } 907 } 908 } 909 910 911 /** 912 * Clamp span's float colors to [0,1] 913 */ 914 static inline void 915 clamp_colors(SWspan *span) 916 { 917 GLfloat (*rgba)[4] = span->array->attribs[VARYING_SLOT_COL0]; 918 GLuint i; 919 assert(span->array->ChanType == GL_FLOAT); 920 for (i = 0; i < span->end; i++) { 921 rgba[i][RCOMP] = CLAMP(rgba[i][RCOMP], 0.0F, 1.0F); 922 rgba[i][GCOMP] = CLAMP(rgba[i][GCOMP], 0.0F, 1.0F); 923 rgba[i][BCOMP] = CLAMP(rgba[i][BCOMP], 0.0F, 1.0F); 924 rgba[i][ACOMP] = CLAMP(rgba[i][ACOMP], 0.0F, 1.0F); 925 } 926 } 927 928 929 /** 930 * Convert the span's color arrays to the given type. 931 * The only way 'output' can be greater than zero is when we have a fragment 932 * program that writes to gl_FragData[1] or higher. 933 * \param output which fragment program color output is being processed 934 */ 935 static inline void 936 convert_color_type(SWspan *span, GLenum srcType, GLenum newType, GLuint output) 937 { 938 GLvoid *src, *dst; 939 940 if (output > 0 || srcType == GL_FLOAT) { 941 src = span->array->attribs[VARYING_SLOT_COL0 + output]; 942 span->array->ChanType = GL_FLOAT; 943 } 944 else if (srcType == GL_UNSIGNED_BYTE) { 945 src = span->array->rgba8; 946 } 947 else { 948 assert(srcType == GL_UNSIGNED_SHORT); 949 src = span->array->rgba16; 950 } 951 952 if (newType == GL_UNSIGNED_BYTE) { 953 dst = span->array->rgba8; 954 } 955 else if (newType == GL_UNSIGNED_SHORT) { 956 dst = span->array->rgba16; 957 } 958 else { 959 dst = span->array->attribs[VARYING_SLOT_COL0]; 960 } 961 962 _mesa_convert_colors(span->array->ChanType, src, 963 newType, dst, 964 span->end, span->array->mask); 965 966 span->array->ChanType = newType; 967 span->array->rgba = dst; 968 } 969 970 971 972 /** 973 * Apply fragment shader, fragment program or normal texturing to span. 974 */ 975 static inline void 976 shade_texture_span(struct gl_context *ctx, SWspan *span) 977 { 978 if (_swrast_use_fragment_program(ctx) || 979 ctx->ATIFragmentShader._Enabled) { 980 /* programmable shading */ 981 if (span->primitive == GL_BITMAP && span->array->ChanType != GL_FLOAT) { 982 convert_color_type(span, span->array->ChanType, GL_FLOAT, 0); 983 } 984 else { 985 span->array->rgba = (void *) span->array->attribs[VARYING_SLOT_COL0]; 986 } 987 988 if (span->primitive != GL_POINT || 989 (span->interpMask & SPAN_RGBA) || 990 ctx->Point.PointSprite) { 991 /* for single-pixel points, we populated the arrays already */ 992 interpolate_active_attribs(ctx, span, ~0); 993 } 994 span->array->ChanType = GL_FLOAT; 995 996 if (!(span->arrayMask & SPAN_Z)) 997 _swrast_span_interpolate_z (ctx, span); 998 999 #if 0 1000 if (inputsRead & VARYING_BIT_POS) 1001 #else 1002 /* XXX always interpolate wpos so that DDX/DDY work */ 1003 #endif 1004 interpolate_wpos(ctx, span); 1005 1006 /* Run fragment program/shader now */ 1007 if (_swrast_use_fragment_program(ctx)) { 1008 _swrast_exec_fragment_program(ctx, span); 1009 } 1010 else { 1011 assert(ctx->ATIFragmentShader._Enabled); 1012 _swrast_exec_fragment_shader(ctx, span); 1013 } 1014 } 1015 else if (ctx->Texture._EnabledCoordUnits) { 1016 /* conventional texturing */ 1017 1018 #if CHAN_BITS == 32 1019 if ((span->arrayAttribs & VARYING_BIT_COL0) == 0) { 1020 interpolate_int_colors(ctx, span); 1021 } 1022 #else 1023 if (!(span->arrayMask & SPAN_RGBA)) 1024 interpolate_int_colors(ctx, span); 1025 #endif 1026 if ((span->arrayAttribs & VARYING_BITS_TEX_ANY) == 0x0) 1027 interpolate_texcoords(ctx, span); 1028 1029 _swrast_texture_span(ctx, span); 1030 } 1031 } 1032 1033 1034 /** Put colors at x/y locations into a renderbuffer */ 1035 static void 1036 put_values(struct gl_context *ctx, struct gl_renderbuffer *rb, 1037 GLenum datatype, 1038 GLuint count, const GLint x[], const GLint y[], 1039 const void *values, const GLubyte *mask) 1040 { 1041 gl_pack_ubyte_rgba_func pack_ubyte = NULL; 1042 gl_pack_float_rgba_func pack_float = NULL; 1043 GLuint i; 1044 1045 if (datatype == GL_UNSIGNED_BYTE) 1046 pack_ubyte = _mesa_get_pack_ubyte_rgba_function(rb->Format); 1047 else 1048 pack_float = _mesa_get_pack_float_rgba_function(rb->Format); 1049 1050 for (i = 0; i < count; i++) { 1051 if (mask[i]) { 1052 GLubyte *dst = _swrast_pixel_address(rb, x[i], y[i]); 1053 1054 if (datatype == GL_UNSIGNED_BYTE) { 1055 pack_ubyte((const GLubyte *) values + 4 * i, dst); 1056 } 1057 else { 1058 assert(datatype == GL_FLOAT); 1059 pack_float((const GLfloat *) values + 4 * i, dst); 1060 } 1061 } 1062 } 1063 } 1064 1065 1066 /** Put row of colors into renderbuffer */ 1067 void 1068 _swrast_put_row(struct gl_context *ctx, struct gl_renderbuffer *rb, 1069 GLenum datatype, 1070 GLuint count, GLint x, GLint y, 1071 const void *values, const GLubyte *mask) 1072 { 1073 GLubyte *dst = _swrast_pixel_address(rb, x, y); 1074 1075 if (!mask) { 1076 if (datatype == GL_UNSIGNED_BYTE) { 1077 _mesa_pack_ubyte_rgba_row(rb->Format, count, 1078 (const GLubyte (*)[4]) values, dst); 1079 } 1080 else { 1081 assert(datatype == GL_FLOAT); 1082 _mesa_pack_float_rgba_row(rb->Format, count, 1083 (const GLfloat (*)[4]) values, dst); 1084 } 1085 } 1086 else { 1087 const GLuint bpp = _mesa_get_format_bytes(rb->Format); 1088 GLuint i, runLen, runStart; 1089 /* We can't pass a 'mask' array to the _mesa_pack_rgba_row() functions 1090 * so look for runs where mask=1... 1091 */ 1092 runLen = runStart = 0; 1093 for (i = 0; i < count; i++) { 1094 if (mask[i]) { 1095 if (runLen == 0) 1096 runStart = i; 1097 runLen++; 1098 } 1099 1100 if (!mask[i] || i == count - 1) { 1101 /* might be the end of a run of pixels */ 1102 if (runLen > 0) { 1103 if (datatype == GL_UNSIGNED_BYTE) { 1104 _mesa_pack_ubyte_rgba_row(rb->Format, runLen, 1105 (const GLubyte (*)[4]) values + runStart, 1106 dst + runStart * bpp); 1107 } 1108 else { 1109 assert(datatype == GL_FLOAT); 1110 _mesa_pack_float_rgba_row(rb->Format, runLen, 1111 (const GLfloat (*)[4]) values + runStart, 1112 dst + runStart * bpp); 1113 } 1114 runLen = 0; 1115 } 1116 } 1117 } 1118 } 1119 } 1120 1121 1122 1123 /** 1124 * Apply all the per-fragment operations to a span. 1125 * This now includes texturing (_swrast_write_texture_span() is history). 1126 * This function may modify any of the array values in the span. 1127 * span->interpMask and span->arrayMask may be changed but will be restored 1128 * to their original values before returning. 1129 */ 1130 void 1131 _swrast_write_rgba_span( struct gl_context *ctx, SWspan *span) 1132 { 1133 const SWcontext *swrast = SWRAST_CONTEXT(ctx); 1134 const GLuint *colorMask = (GLuint *) ctx->Color.ColorMask; 1135 const GLbitfield origInterpMask = span->interpMask; 1136 const GLbitfield origArrayMask = span->arrayMask; 1137 const GLbitfield64 origArrayAttribs = span->arrayAttribs; 1138 const GLenum origChanType = span->array->ChanType; 1139 void * const origRgba = span->array->rgba; 1140 const GLboolean shader = (_swrast_use_fragment_program(ctx) 1141 || ctx->ATIFragmentShader._Enabled); 1142 const GLboolean shaderOrTexture = shader || ctx->Texture._EnabledCoordUnits; 1143 struct gl_framebuffer *fb = ctx->DrawBuffer; 1144 1145 /* 1146 printf("%s() interp 0x%x array 0x%x\n", __func__, 1147 span->interpMask, span->arrayMask); 1148 */ 1149 1150 assert(span->primitive == GL_POINT || 1151 span->primitive == GL_LINE || 1152 span->primitive == GL_POLYGON || 1153 span->primitive == GL_BITMAP); 1154 1155 /* Fragment write masks */ 1156 if (span->arrayMask & SPAN_MASK) { 1157 /* mask was initialized by caller, probably glBitmap */ 1158 span->writeAll = GL_FALSE; 1159 } 1160 else { 1161 memset(span->array->mask, 1, span->end); 1162 span->writeAll = GL_TRUE; 1163 } 1164 1165 /* Clip to window/scissor box */ 1166 if (!clip_span(ctx, span)) { 1167 return; 1168 } 1169 1170 assert(span->end <= SWRAST_MAX_WIDTH); 1171 1172 /* Depth bounds test */ 1173 if (ctx->Depth.BoundsTest && fb->Visual.depthBits > 0) { 1174 if (!_swrast_depth_bounds_test(ctx, span)) { 1175 return; 1176 } 1177 } 1178 1179 #ifdef DEBUG 1180 /* Make sure all fragments are within window bounds */ 1181 if (span->arrayMask & SPAN_XY) { 1182 /* array of pixel locations */ 1183 GLuint i; 1184 for (i = 0; i < span->end; i++) { 1185 if (span->array->mask[i]) { 1186 assert(span->array->x[i] >= fb->_Xmin); 1187 assert(span->array->x[i] < fb->_Xmax); 1188 assert(span->array->y[i] >= fb->_Ymin); 1189 assert(span->array->y[i] < fb->_Ymax); 1190 } 1191 } 1192 } 1193 #endif 1194 1195 /* Polygon Stippling */ 1196 if (ctx->Polygon.StippleFlag && span->primitive == GL_POLYGON) { 1197 stipple_polygon_span(ctx, span); 1198 } 1199 1200 /* This is the normal place to compute the fragment color/Z 1201 * from texturing or shading. 1202 */ 1203 if (shaderOrTexture && !swrast->_DeferredTexture) { 1204 shade_texture_span(ctx, span); 1205 } 1206 1207 /* Do the alpha test */ 1208 if (ctx->Color.AlphaEnabled) { 1209 if (!_swrast_alpha_test(ctx, span)) { 1210 /* all fragments failed test */ 1211 goto end; 1212 } 1213 } 1214 1215 /* Stencil and Z testing */ 1216 if (ctx->Stencil._Enabled || ctx->Depth.Test) { 1217 if (!(span->arrayMask & SPAN_Z)) 1218 _swrast_span_interpolate_z(ctx, span); 1219 1220 if (ctx->Transform.DepthClamp) 1221 _swrast_depth_clamp_span(ctx, span); 1222 1223 if (ctx->Stencil._Enabled) { 1224 /* Combined Z/stencil tests */ 1225 if (!_swrast_stencil_and_ztest_span(ctx, span)) { 1226 /* all fragments failed test */ 1227 goto end; 1228 } 1229 } 1230 else if (fb->Visual.depthBits > 0) { 1231 /* Just regular depth testing */ 1232 assert(ctx->Depth.Test); 1233 assert(span->arrayMask & SPAN_Z); 1234 if (!_swrast_depth_test_span(ctx, span)) { 1235 /* all fragments failed test */ 1236 goto end; 1237 } 1238 } 1239 } 1240 1241 if (ctx->Query.CurrentOcclusionObject) { 1242 /* update count of 'passed' fragments */ 1243 struct gl_query_object *q = ctx->Query.CurrentOcclusionObject; 1244 GLuint i; 1245 for (i = 0; i < span->end; i++) 1246 q->Result += span->array->mask[i]; 1247 } 1248 1249 /* We had to wait until now to check for glColorMask(0,0,0,0) because of 1250 * the occlusion test. 1251 */ 1252 if (fb->_NumColorDrawBuffers == 1 && colorMask[0] == 0x0) { 1253 /* no colors to write */ 1254 goto end; 1255 } 1256 1257 /* If we were able to defer fragment color computation to now, there's 1258 * a good chance that many fragments will have already been killed by 1259 * Z/stencil testing. 1260 */ 1261 if (shaderOrTexture && swrast->_DeferredTexture) { 1262 shade_texture_span(ctx, span); 1263 } 1264 1265 #if CHAN_BITS == 32 1266 if ((span->arrayAttribs & VARYING_BIT_COL0) == 0) { 1267 interpolate_active_attribs(ctx, span, VARYING_BIT_COL0); 1268 } 1269 #else 1270 if ((span->arrayMask & SPAN_RGBA) == 0) { 1271 interpolate_int_colors(ctx, span); 1272 } 1273 #endif 1274 1275 assert(span->arrayMask & SPAN_RGBA); 1276 1277 if (span->primitive == GL_BITMAP || !swrast->SpecularVertexAdd) { 1278 /* Add primary and specular (diffuse + specular) colors */ 1279 if (!shader) { 1280 if (ctx->Fog.ColorSumEnabled || 1281 (ctx->Light.Enabled && 1282 ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)) { 1283 add_specular(ctx, span); 1284 } 1285 } 1286 } 1287 1288 /* Fog */ 1289 if (swrast->_FogEnabled) { 1290 _swrast_fog_rgba_span(ctx, span); 1291 } 1292 1293 /* Antialias coverage application */ 1294 if (span->arrayMask & SPAN_COVERAGE) { 1295 apply_aa_coverage(span); 1296 } 1297 1298 /* Clamp color/alpha values over the range [0.0, 1.0] before storage */ 1299 if (ctx->Color.ClampFragmentColor == GL_TRUE && 1300 span->array->ChanType == GL_FLOAT) { 1301 clamp_colors(span); 1302 } 1303 1304 /* 1305 * Write to renderbuffers. 1306 * Depending on glDrawBuffer() state and the which color outputs are 1307 * written by the fragment shader, we may either replicate one color to 1308 * all renderbuffers or write a different color to each renderbuffer. 1309 * multiFragOutputs=TRUE for the later case. 1310 */ 1311 { 1312 const GLuint numBuffers = fb->_NumColorDrawBuffers; 1313 const struct gl_program *fp = ctx->FragmentProgram._Current; 1314 const GLboolean multiFragOutputs = 1315 _swrast_use_fragment_program(ctx) 1316 && fp->info.outputs_written >= (1 << FRAG_RESULT_DATA0); 1317 /* Save srcColorType because convert_color_type() can change it */ 1318 const GLenum srcColorType = span->array->ChanType; 1319 GLuint buf; 1320 1321 for (buf = 0; buf < numBuffers; buf++) { 1322 struct gl_renderbuffer *rb = fb->_ColorDrawBuffers[buf]; 1323 1324 /* color[fragOutput] will be written to buffer[buf] */ 1325 1326 if (rb) { 1327 /* re-use one of the attribute array buffers for rgbaSave */ 1328 GLchan (*rgbaSave)[4] = (GLchan (*)[4]) span->array->attribs[0]; 1329 struct swrast_renderbuffer *srb = swrast_renderbuffer(rb); 1330 const GLenum dstColorType = srb->ColorType; 1331 1332 assert(dstColorType == GL_UNSIGNED_BYTE || 1333 dstColorType == GL_FLOAT); 1334 1335 /* set span->array->rgba to colors for renderbuffer's datatype */ 1336 if (srcColorType != dstColorType) { 1337 convert_color_type(span, srcColorType, dstColorType, 1338 multiFragOutputs ? buf : 0); 1339 } 1340 else { 1341 if (srcColorType == GL_UNSIGNED_BYTE) { 1342 span->array->rgba = span->array->rgba8; 1343 } 1344 else { 1345 span->array->rgba = (void *) 1346 span->array->attribs[VARYING_SLOT_COL0]; 1347 } 1348 } 1349 1350 if (!multiFragOutputs && numBuffers > 1) { 1351 /* save colors for second, third renderbuffer writes */ 1352 memcpy(rgbaSave, span->array->rgba, 1353 4 * span->end * sizeof(GLchan)); 1354 } 1355 1356 assert(rb->_BaseFormat == GL_RGBA || 1357 rb->_BaseFormat == GL_RGB || 1358 rb->_BaseFormat == GL_RED || 1359 rb->_BaseFormat == GL_RG || 1360 rb->_BaseFormat == GL_ALPHA); 1361 1362 if (ctx->Color.ColorLogicOpEnabled) { 1363 _swrast_logicop_rgba_span(ctx, rb, span); 1364 } 1365 else if ((ctx->Color.BlendEnabled >> buf) & 1) { 1366 _swrast_blend_span(ctx, rb, span); 1367 } 1368 1369 if (colorMask[buf] != 0xffffffff) { 1370 _swrast_mask_rgba_span(ctx, rb, span, buf); 1371 } 1372 1373 if (span->arrayMask & SPAN_XY) { 1374 /* array of pixel coords */ 1375 put_values(ctx, rb, 1376 span->array->ChanType, span->end, 1377 span->array->x, span->array->y, 1378 span->array->rgba, span->array->mask); 1379 } 1380 else { 1381 /* horizontal run of pixels */ 1382 _swrast_put_row(ctx, rb, 1383 span->array->ChanType, 1384 span->end, span->x, span->y, 1385 span->array->rgba, 1386 span->writeAll ? NULL: span->array->mask); 1387 } 1388 1389 if (!multiFragOutputs && numBuffers > 1) { 1390 /* restore original span values */ 1391 memcpy(span->array->rgba, rgbaSave, 1392 4 * span->end * sizeof(GLchan)); 1393 } 1394 1395 } /* if rb */ 1396 } /* for buf */ 1397 } 1398 1399 end: 1400 /* restore these values before returning */ 1401 span->interpMask = origInterpMask; 1402 span->arrayMask = origArrayMask; 1403 span->arrayAttribs = origArrayAttribs; 1404 span->array->ChanType = origChanType; 1405 span->array->rgba = origRgba; 1406 } 1407 1408 1409 /** 1410 * Read float RGBA pixels from a renderbuffer. Clipping will be done to 1411 * prevent reading ouside the buffer's boundaries. 1412 * \param rgba the returned colors 1413 */ 1414 void 1415 _swrast_read_rgba_span( struct gl_context *ctx, struct gl_renderbuffer *rb, 1416 GLuint n, GLint x, GLint y, 1417 GLvoid *rgba) 1418 { 1419 struct swrast_renderbuffer *srb = swrast_renderbuffer(rb); 1420 GLenum dstType = GL_FLOAT; 1421 const GLint bufWidth = (GLint) rb->Width; 1422 const GLint bufHeight = (GLint) rb->Height; 1423 1424 if (y < 0 || y >= bufHeight || x + (GLint) n < 0 || x >= bufWidth) { 1425 /* completely above, below, or right */ 1426 /* XXX maybe leave rgba values undefined? */ 1427 memset(rgba, 0, 4 * n * sizeof(GLchan)); 1428 } 1429 else { 1430 GLint skip, length; 1431 GLubyte *src; 1432 1433 if (x < 0) { 1434 /* left edge clipping */ 1435 skip = -x; 1436 length = (GLint) n - skip; 1437 if (length < 0) { 1438 /* completely left of window */ 1439 return; 1440 } 1441 if (length > bufWidth) { 1442 length = bufWidth; 1443 } 1444 } 1445 else if ((GLint) (x + n) > bufWidth) { 1446 /* right edge clipping */ 1447 skip = 0; 1448 length = bufWidth - x; 1449 if (length < 0) { 1450 /* completely to right of window */ 1451 return; 1452 } 1453 } 1454 else { 1455 /* no clipping */ 1456 skip = 0; 1457 length = (GLint) n; 1458 } 1459 1460 assert(rb); 1461 assert(rb->_BaseFormat == GL_RGBA || 1462 rb->_BaseFormat == GL_RGB || 1463 rb->_BaseFormat == GL_RG || 1464 rb->_BaseFormat == GL_RED || 1465 rb->_BaseFormat == GL_LUMINANCE || 1466 rb->_BaseFormat == GL_INTENSITY || 1467 rb->_BaseFormat == GL_LUMINANCE_ALPHA || 1468 rb->_BaseFormat == GL_ALPHA); 1469 1470 assert(srb->Map); 1471 (void) srb; /* silence unused var warning */ 1472 1473 src = _swrast_pixel_address(rb, x + skip, y); 1474 1475 if (dstType == GL_UNSIGNED_BYTE) { 1476 _mesa_unpack_ubyte_rgba_row(rb->Format, length, src, 1477 (GLubyte (*)[4]) rgba + skip); 1478 } 1479 else if (dstType == GL_FLOAT) { 1480 _mesa_unpack_rgba_row(rb->Format, length, src, 1481 (GLfloat (*)[4]) rgba + skip); 1482 } 1483 else { 1484 _mesa_problem(ctx, "unexpected type in _swrast_read_rgba_span()"); 1485 } 1486 } 1487 } 1488 1489 1490 /** 1491 * Get colors at x/y positions with clipping. 1492 * \param type type of values to return 1493 */ 1494 static void 1495 get_values(struct gl_context *ctx, struct gl_renderbuffer *rb, 1496 GLuint count, const GLint x[], const GLint y[], 1497 void *values, GLenum type) 1498 { 1499 GLuint i; 1500 1501 for (i = 0; i < count; i++) { 1502 if (x[i] >= 0 && y[i] >= 0 && 1503 x[i] < (GLint) rb->Width && y[i] < (GLint) rb->Height) { 1504 /* inside */ 1505 const GLubyte *src = _swrast_pixel_address(rb, x[i], y[i]); 1506 1507 if (type == GL_UNSIGNED_BYTE) { 1508 _mesa_unpack_ubyte_rgba_row(rb->Format, 1, src, 1509 (GLubyte (*)[4]) values + i); 1510 } 1511 else if (type == GL_FLOAT) { 1512 _mesa_unpack_rgba_row(rb->Format, 1, src, 1513 (GLfloat (*)[4]) values + i); 1514 } 1515 else { 1516 _mesa_problem(ctx, "unexpected type in get_values()"); 1517 } 1518 } 1519 } 1520 } 1521 1522 1523 /** 1524 * Get row of colors with clipping. 1525 * \param type type of values to return 1526 */ 1527 static void 1528 get_row(struct gl_context *ctx, struct gl_renderbuffer *rb, 1529 GLuint count, GLint x, GLint y, 1530 GLvoid *values, GLenum type) 1531 { 1532 GLint skip = 0; 1533 GLubyte *src; 1534 1535 if (y < 0 || y >= (GLint) rb->Height) 1536 return; /* above or below */ 1537 1538 if (x + (GLint) count <= 0 || x >= (GLint) rb->Width) 1539 return; /* entirely left or right */ 1540 1541 if (x + count > rb->Width) { 1542 /* right clip */ 1543 GLint clip = x + count - rb->Width; 1544 count -= clip; 1545 } 1546 1547 if (x < 0) { 1548 /* left clip */ 1549 skip = -x; 1550 x = 0; 1551 count -= skip; 1552 } 1553 1554 src = _swrast_pixel_address(rb, x, y); 1555 1556 if (type == GL_UNSIGNED_BYTE) { 1557 _mesa_unpack_ubyte_rgba_row(rb->Format, count, src, 1558 (GLubyte (*)[4]) values + skip); 1559 } 1560 else if (type == GL_FLOAT) { 1561 _mesa_unpack_rgba_row(rb->Format, count, src, 1562 (GLfloat (*)[4]) values + skip); 1563 } 1564 else { 1565 _mesa_problem(ctx, "unexpected type in get_row()"); 1566 } 1567 } 1568 1569 1570 /** 1571 * Get RGBA pixels from the given renderbuffer. 1572 * Used by blending, logicop and masking functions. 1573 * \return pointer to the colors we read. 1574 */ 1575 void * 1576 _swrast_get_dest_rgba(struct gl_context *ctx, struct gl_renderbuffer *rb, 1577 SWspan *span) 1578 { 1579 void *rbPixels; 1580 1581 /* Point rbPixels to a temporary space */ 1582 rbPixels = span->array->attribs[VARYING_SLOT_MAX - 1]; 1583 1584 /* Get destination values from renderbuffer */ 1585 if (span->arrayMask & SPAN_XY) { 1586 get_values(ctx, rb, span->end, span->array->x, span->array->y, 1587 rbPixels, span->array->ChanType); 1588 } 1589 else { 1590 get_row(ctx, rb, span->end, span->x, span->y, 1591 rbPixels, span->array->ChanType); 1592 } 1593 1594 return rbPixels; 1595 } 1596