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