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