s_span.c revision d09df24082d69e534470f9a5f667b30c34ae6d74
1/* 2 * Mesa 3-D graphics library 3 * Version: 6.3 4 * 5 * Copyright (C) 1999-2004 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 39#include "s_atifragshader.h" 40#include "s_alpha.h" 41#include "s_alphabuf.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_nvfragprog.h" 49#include "s_span.h" 50#include "s_stencil.h" 51#include "s_texture.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, struct sw_span *span ) 60{ 61 if (ctx->Visual.depthBits <= 16) 62 span->z = FloatToFixed(ctx->Current.RasterPos[2] * ctx->DepthMax + 0.5F); 63 else 64 span->z = (GLint) (ctx->Current.RasterPos[2] * ctx->DepthMax + 0.5F); 65 span->zStep = 0; 66 span->interpMask |= SPAN_Z; 67} 68 69 70/** 71 * Init span's fog interpolation values to the RasterPos fog. 72 * Used during setup for glDraw/CopyPixels. 73 */ 74void 75_swrast_span_default_fog( GLcontext *ctx, struct sw_span *span ) 76{ 77 span->fog = _swrast_z_to_fogfactor(ctx, ctx->Current.RasterDistance); 78 span->fogStep = span->dfogdx = span->dfogdy = 0.0F; 79 span->interpMask |= SPAN_FOG; 80} 81 82 83/** 84 * Init span's rgba or index interpolation values to the RasterPos color. 85 * Used during setup for glDraw/CopyPixels. 86 */ 87void 88_swrast_span_default_color( GLcontext *ctx, struct sw_span *span ) 89{ 90 if (ctx->Visual.rgbMode) { 91 GLchan r, g, b, a; 92 UNCLAMPED_FLOAT_TO_CHAN(r, ctx->Current.RasterColor[0]); 93 UNCLAMPED_FLOAT_TO_CHAN(g, ctx->Current.RasterColor[1]); 94 UNCLAMPED_FLOAT_TO_CHAN(b, ctx->Current.RasterColor[2]); 95 UNCLAMPED_FLOAT_TO_CHAN(a, ctx->Current.RasterColor[3]); 96#if CHAN_TYPE == GL_FLOAT 97 span->red = r; 98 span->green = g; 99 span->blue = b; 100 span->alpha = a; 101#else 102 span->red = IntToFixed(r); 103 span->green = IntToFixed(g); 104 span->blue = IntToFixed(b); 105 span->alpha = IntToFixed(a); 106#endif 107 span->redStep = 0; 108 span->greenStep = 0; 109 span->blueStep = 0; 110 span->alphaStep = 0; 111 span->interpMask |= SPAN_RGBA; 112 } 113 else { 114 span->index = FloatToFixed(ctx->Current.RasterIndex); 115 span->indexStep = 0; 116 span->interpMask |= SPAN_INDEX; 117 } 118} 119 120 121/** 122 * Init span's texcoord interpolation values to the RasterPos texcoords. 123 * Used during setup for glDraw/CopyPixels. 124 */ 125void 126_swrast_span_default_texcoords( GLcontext *ctx, struct sw_span *span ) 127{ 128 GLuint i; 129 for (i = 0; i < ctx->Const.MaxTextureUnits; i++) { 130 const GLfloat *tc = ctx->Current.RasterTexCoords[i]; 131 if (ctx->FragmentProgram._Enabled || ctx->ATIFragmentShader._Enabled) { 132 COPY_4V(span->tex[i], tc); 133 } 134 else if (tc[3] > 0.0F) { 135 /* use (s/q, t/q, r/q, 1) */ 136 span->tex[i][0] = tc[0] / tc[3]; 137 span->tex[i][1] = tc[1] / tc[3]; 138 span->tex[i][2] = tc[2] / tc[3]; 139 span->tex[i][3] = 1.0; 140 } 141 else { 142 ASSIGN_4V(span->tex[i], 0.0F, 0.0F, 0.0F, 1.0F); 143 } 144 ASSIGN_4V(span->texStepX[i], 0.0F, 0.0F, 0.0F, 0.0F); 145 ASSIGN_4V(span->texStepY[i], 0.0F, 0.0F, 0.0F, 0.0F); 146 } 147 span->interpMask |= SPAN_TEXTURE; 148} 149 150 151/* Fill in the span.color.rgba array from the interpolation values */ 152static void 153interpolate_colors(GLcontext *ctx, struct sw_span *span) 154{ 155 const GLuint n = span->end; 156 GLchan (*rgba)[4] = span->array->rgba; 157 GLuint i; 158 (void) ctx; 159 160 ASSERT((span->interpMask & SPAN_RGBA) && 161 !(span->arrayMask & SPAN_RGBA)); 162 163 if (span->interpMask & SPAN_FLAT) { 164 /* constant color */ 165 GLchan color[4]; 166 color[RCOMP] = FixedToChan(span->red); 167 color[GCOMP] = FixedToChan(span->green); 168 color[BCOMP] = FixedToChan(span->blue); 169 color[ACOMP] = FixedToChan(span->alpha); 170 for (i = 0; i < n; i++) { 171 COPY_CHAN4(span->array->rgba[i], color); 172 } 173 } 174 else { 175 /* interpolate */ 176#if CHAN_TYPE == GL_FLOAT 177 GLfloat r = span->red; 178 GLfloat g = span->green; 179 GLfloat b = span->blue; 180 GLfloat a = span->alpha; 181 const GLfloat dr = span->redStep; 182 const GLfloat dg = span->greenStep; 183 const GLfloat db = span->blueStep; 184 const GLfloat da = span->alphaStep; 185#else 186 GLfixed r = span->red; 187 GLfixed g = span->green; 188 GLfixed b = span->blue; 189 GLfixed a = span->alpha; 190 const GLint dr = span->redStep; 191 const GLint dg = span->greenStep; 192 const GLint db = span->blueStep; 193 const GLint da = span->alphaStep; 194#endif 195 for (i = 0; i < n; i++) { 196 rgba[i][RCOMP] = FixedToChan(r); 197 rgba[i][GCOMP] = FixedToChan(g); 198 rgba[i][BCOMP] = FixedToChan(b); 199 rgba[i][ACOMP] = FixedToChan(a); 200 r += dr; 201 g += dg; 202 b += db; 203 a += da; 204 } 205 } 206 span->arrayMask |= SPAN_RGBA; 207} 208 209 210/* Fill in the span.color.index array from the interpolation values */ 211static void 212interpolate_indexes(GLcontext *ctx, struct sw_span *span) 213{ 214 GLfixed index = span->index; 215 const GLint indexStep = span->indexStep; 216 const GLuint n = span->end; 217 GLuint *indexes = span->array->index; 218 GLuint i; 219 (void) ctx; 220 ASSERT((span->interpMask & SPAN_INDEX) && 221 !(span->arrayMask & SPAN_INDEX)); 222 223 if ((span->interpMask & SPAN_FLAT) || (indexStep == 0)) { 224 /* constant color */ 225 index = FixedToInt(index); 226 for (i = 0; i < n; i++) { 227 indexes[i] = index; 228 } 229 } 230 else { 231 /* interpolate */ 232 for (i = 0; i < n; i++) { 233 indexes[i] = FixedToInt(index); 234 index += indexStep; 235 } 236 } 237 span->arrayMask |= SPAN_INDEX; 238} 239 240 241/* Fill in the span.->array->spec array from the interpolation values */ 242static void 243interpolate_specular(GLcontext *ctx, struct sw_span *span) 244{ 245 (void) ctx; 246 if (span->interpMask & SPAN_FLAT) { 247 /* constant color */ 248 const GLchan r = FixedToChan(span->specRed); 249 const GLchan g = FixedToChan(span->specGreen); 250 const GLchan b = FixedToChan(span->specBlue); 251 GLuint i; 252 for (i = 0; i < span->end; i++) { 253 span->array->spec[i][RCOMP] = r; 254 span->array->spec[i][GCOMP] = g; 255 span->array->spec[i][BCOMP] = b; 256 } 257 } 258 else { 259 /* interpolate */ 260#if CHAN_TYPE == GL_FLOAT 261 GLfloat r = span->specRed; 262 GLfloat g = span->specGreen; 263 GLfloat b = span->specBlue; 264#else 265 GLfixed r = span->specRed; 266 GLfixed g = span->specGreen; 267 GLfixed b = span->specBlue; 268#endif 269 GLuint i; 270 for (i = 0; i < span->end; i++) { 271 span->array->spec[i][RCOMP] = FixedToChan(r); 272 span->array->spec[i][GCOMP] = FixedToChan(g); 273 span->array->spec[i][BCOMP] = FixedToChan(b); 274 r += span->specRedStep; 275 g += span->specGreenStep; 276 b += span->specBlueStep; 277 } 278 } 279 span->arrayMask |= SPAN_SPEC; 280} 281 282 283/* Fill in the span.array.fog values from the interpolation values */ 284static void 285interpolate_fog(const GLcontext *ctx, struct sw_span *span) 286{ 287 GLfloat *fog = span->array->fog; 288 const GLfloat fogStep = span->fogStep; 289 GLfloat fogCoord = span->fog; 290 const GLuint haveW = (span->interpMask & SPAN_W); 291 const GLfloat wStep = haveW ? span->dwdx : 0.0F; 292 GLfloat w = haveW ? span->w : 1.0F; 293 GLuint i; 294 for (i = 0; i < span->end; i++) { 295 fog[i] = fogCoord / w; 296 fogCoord += fogStep; 297 w += wStep; 298 } 299 span->arrayMask |= SPAN_FOG; 300} 301 302 303/* Fill in the span.zArray array from the interpolation values */ 304void 305_swrast_span_interpolate_z( const GLcontext *ctx, struct sw_span *span ) 306{ 307 const GLuint n = span->end; 308 GLuint i; 309 310 ASSERT((span->interpMask & SPAN_Z) && 311 !(span->arrayMask & SPAN_Z)); 312 313 if (ctx->Visual.depthBits <= 16) { 314 GLfixed zval = span->z; 315 GLdepth *z = span->array->z; 316 for (i = 0; i < n; i++) { 317 z[i] = FixedToInt(zval); 318 zval += span->zStep; 319 } 320 } 321 else { 322 /* Deep Z buffer, no fixed->int shift */ 323 GLfixed zval = span->z; 324 GLdepth *z = span->array->z; 325 for (i = 0; i < n; i++) { 326 z[i] = zval; 327 zval += span->zStep; 328 } 329 } 330 span->arrayMask |= SPAN_Z; 331} 332 333 334/* 335 * This the ideal solution, as given in the OpenGL spec. 336 */ 337#if 0 338static GLfloat 339compute_lambda(GLfloat dsdx, GLfloat dsdy, GLfloat dtdx, GLfloat dtdy, 340 GLfloat dqdx, GLfloat dqdy, GLfloat texW, GLfloat texH, 341 GLfloat s, GLfloat t, GLfloat q, GLfloat invQ) 342{ 343 GLfloat dudx = texW * ((s + dsdx) / (q + dqdx) - s * invQ); 344 GLfloat dvdx = texH * ((t + dtdx) / (q + dqdx) - t * invQ); 345 GLfloat dudy = texW * ((s + dsdy) / (q + dqdy) - s * invQ); 346 GLfloat dvdy = texH * ((t + dtdy) / (q + dqdy) - t * invQ); 347 GLfloat x = SQRTF(dudx * dudx + dvdx * dvdx); 348 GLfloat y = SQRTF(dudy * dudy + dvdy * dvdy); 349 GLfloat rho = MAX2(x, y); 350 GLfloat lambda = LOG2(rho); 351 return lambda; 352} 353#endif 354 355 356/* 357 * This is a faster approximation 358 */ 359GLfloat 360_swrast_compute_lambda(GLfloat dsdx, GLfloat dsdy, GLfloat dtdx, GLfloat dtdy, 361 GLfloat dqdx, GLfloat dqdy, GLfloat texW, GLfloat texH, 362 GLfloat s, GLfloat t, GLfloat q, GLfloat invQ) 363{ 364 GLfloat dsdx2 = (s + dsdx) / (q + dqdx) - s * invQ; 365 GLfloat dtdx2 = (t + dtdx) / (q + dqdx) - t * invQ; 366 GLfloat dsdy2 = (s + dsdy) / (q + dqdy) - s * invQ; 367 GLfloat dtdy2 = (t + dtdy) / (q + dqdy) - t * invQ; 368 GLfloat maxU, maxV, rho, lambda; 369 dsdx2 = FABSF(dsdx2); 370 dsdy2 = FABSF(dsdy2); 371 dtdx2 = FABSF(dtdx2); 372 dtdy2 = FABSF(dtdy2); 373 maxU = MAX2(dsdx2, dsdy2) * texW; 374 maxV = MAX2(dtdx2, dtdy2) * texH; 375 rho = MAX2(maxU, maxV); 376 lambda = LOG2(rho); 377 return lambda; 378} 379 380 381/** 382 * Fill in the span.texcoords array from the interpolation values. 383 * Note: in the places where we divide by Q (or mult by invQ) we're 384 * really doing two things: perspective correction and texcoord 385 * projection. Remember, for texcoord (s,t,r,q) we need to index 386 * texels with (s/q, t/q, r/q). 387 * If we're using a fragment program, we never do the division 388 * for texcoord projection. That's done by the TXP instruction 389 * or user-written code. 390 */ 391static void 392interpolate_texcoords(GLcontext *ctx, struct sw_span *span) 393{ 394 ASSERT(span->interpMask & SPAN_TEXTURE); 395 ASSERT(!(span->arrayMask & SPAN_TEXTURE)); 396 397 if (ctx->Texture._EnabledCoordUnits > 1) { 398 /* multitexture */ 399 GLuint u; 400 span->arrayMask |= SPAN_TEXTURE; 401 for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { 402 if (ctx->Texture._EnabledCoordUnits & (1 << u)) { 403 const struct gl_texture_object *obj =ctx->Texture.Unit[u]._Current; 404 GLfloat texW, texH; 405 GLboolean needLambda; 406 if (obj) { 407 const struct gl_texture_image *img = obj->Image[0][obj->BaseLevel]; 408 needLambda = (obj->MinFilter != obj->MagFilter) 409 || ctx->FragmentProgram._Enabled; 410 texW = img->WidthScale; 411 texH = img->HeightScale; 412 } 413 else { 414 /* using a fragment program */ 415 texW = 1.0; 416 texH = 1.0; 417 needLambda = GL_FALSE; 418 } 419 if (needLambda) { 420 GLfloat (*texcoord)[4] = span->array->texcoords[u]; 421 GLfloat *lambda = span->array->lambda[u]; 422 const GLfloat dsdx = span->texStepX[u][0]; 423 const GLfloat dsdy = span->texStepY[u][0]; 424 const GLfloat dtdx = span->texStepX[u][1]; 425 const GLfloat dtdy = span->texStepY[u][1]; 426 const GLfloat drdx = span->texStepX[u][2]; 427 const GLfloat dqdx = span->texStepX[u][3]; 428 const GLfloat dqdy = span->texStepY[u][3]; 429 GLfloat s = span->tex[u][0]; 430 GLfloat t = span->tex[u][1]; 431 GLfloat r = span->tex[u][2]; 432 GLfloat q = span->tex[u][3]; 433 GLuint i; 434 if (ctx->FragmentProgram._Enabled) { 435 /* do perspective correction but don't divide s, t, r by q */ 436 const GLfloat dwdx = span->dwdx; 437 GLfloat w = span->w; 438 for (i = 0; i < span->end; i++) { 439 const GLfloat invW = 1.0F / w; 440 texcoord[i][0] = s * invW; 441 texcoord[i][1] = t * invW; 442 texcoord[i][2] = r * invW; 443 texcoord[i][3] = q * invW; 444 lambda[i] = _swrast_compute_lambda(dsdx, dsdy, dtdx, dtdy, 445 dqdx, dqdy, texW, texH, 446 s, t, q, invW); 447 s += dsdx; 448 t += dtdx; 449 r += drdx; 450 q += dqdx; 451 w += dwdx; 452 } 453 454 } 455 else { 456 for (i = 0; i < span->end; i++) { 457 const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q); 458 texcoord[i][0] = s * invQ; 459 texcoord[i][1] = t * invQ; 460 texcoord[i][2] = r * invQ; 461 texcoord[i][3] = q; 462 lambda[i] = _swrast_compute_lambda(dsdx, dsdy, dtdx, dtdy, 463 dqdx, dqdy, texW, texH, 464 s, t, q, invQ); 465 s += dsdx; 466 t += dtdx; 467 r += drdx; 468 q += dqdx; 469 } 470 } 471 span->arrayMask |= SPAN_LAMBDA; 472 } 473 else { 474 GLfloat (*texcoord)[4] = span->array->texcoords[u]; 475 GLfloat *lambda = span->array->lambda[u]; 476 const GLfloat dsdx = span->texStepX[u][0]; 477 const GLfloat dtdx = span->texStepX[u][1]; 478 const GLfloat drdx = span->texStepX[u][2]; 479 const GLfloat dqdx = span->texStepX[u][3]; 480 GLfloat s = span->tex[u][0]; 481 GLfloat t = span->tex[u][1]; 482 GLfloat r = span->tex[u][2]; 483 GLfloat q = span->tex[u][3]; 484 GLuint i; 485 if (ctx->FragmentProgram._Enabled) { 486 /* do perspective correction but don't divide s, t, r by q */ 487 const GLfloat dwdx = span->dwdx; 488 GLfloat w = span->w; 489 for (i = 0; i < span->end; i++) { 490 const GLfloat invW = 1.0F / w; 491 texcoord[i][0] = s * invW; 492 texcoord[i][1] = t * invW; 493 texcoord[i][2] = r * invW; 494 texcoord[i][3] = q * invW; 495 lambda[i] = 0.0; 496 s += dsdx; 497 t += dtdx; 498 r += drdx; 499 q += dqdx; 500 w += dwdx; 501 } 502 } 503 else if (dqdx == 0.0F) { 504 /* Ortho projection or polygon's parallel to window X axis */ 505 const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q); 506 for (i = 0; i < span->end; i++) { 507 texcoord[i][0] = s * invQ; 508 texcoord[i][1] = t * invQ; 509 texcoord[i][2] = r * invQ; 510 texcoord[i][3] = q; 511 lambda[i] = 0.0; 512 s += dsdx; 513 t += dtdx; 514 r += drdx; 515 } 516 } 517 else { 518 for (i = 0; i < span->end; i++) { 519 const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q); 520 texcoord[i][0] = s * invQ; 521 texcoord[i][1] = t * invQ; 522 texcoord[i][2] = r * invQ; 523 texcoord[i][3] = q; 524 lambda[i] = 0.0; 525 s += dsdx; 526 t += dtdx; 527 r += drdx; 528 q += dqdx; 529 } 530 } 531 } /* lambda */ 532 } /* if */ 533 } /* for */ 534 } 535 else { 536 /* single texture */ 537 const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current; 538 GLfloat texW, texH; 539 GLboolean needLambda; 540 if (obj) { 541 const struct gl_texture_image *img = obj->Image[0][obj->BaseLevel]; 542 needLambda = (obj->MinFilter != obj->MagFilter) 543 || ctx->FragmentProgram._Enabled; 544 texW = (GLfloat) img->WidthScale; 545 texH = (GLfloat) img->HeightScale; 546 } 547 else { 548 needLambda = GL_FALSE; 549 texW = texH = 1.0; 550 } 551 span->arrayMask |= SPAN_TEXTURE; 552 if (needLambda) { 553 /* just texture unit 0, with lambda */ 554 GLfloat (*texcoord)[4] = span->array->texcoords[0]; 555 GLfloat *lambda = span->array->lambda[0]; 556 const GLfloat dsdx = span->texStepX[0][0]; 557 const GLfloat dsdy = span->texStepY[0][0]; 558 const GLfloat dtdx = span->texStepX[0][1]; 559 const GLfloat dtdy = span->texStepY[0][1]; 560 const GLfloat drdx = span->texStepX[0][2]; 561 const GLfloat dqdx = span->texStepX[0][3]; 562 const GLfloat dqdy = span->texStepY[0][3]; 563 GLfloat s = span->tex[0][0]; 564 GLfloat t = span->tex[0][1]; 565 GLfloat r = span->tex[0][2]; 566 GLfloat q = span->tex[0][3]; 567 GLuint i; 568 if (ctx->FragmentProgram._Enabled) { 569 /* do perspective correction but don't divide s, t, r by q */ 570 const GLfloat dwdx = span->dwdx; 571 GLfloat w = span->w; 572 for (i = 0; i < span->end; i++) { 573 const GLfloat invW = 1.0F / w; 574 texcoord[i][0] = s * invW; 575 texcoord[i][1] = t * invW; 576 texcoord[i][2] = r * invW; 577 texcoord[i][3] = q * invW; 578 lambda[i] = _swrast_compute_lambda(dsdx, dsdy, dtdx, dtdy, 579 dqdx, dqdy, texW, texH, 580 s, t, q, invW); 581 s += dsdx; 582 t += dtdx; 583 r += drdx; 584 q += dqdx; 585 w += dwdx; 586 } 587 } 588 else { 589 /* tex.c */ 590 for (i = 0; i < span->end; i++) { 591 const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q); 592 lambda[i] = _swrast_compute_lambda(dsdx, dsdy, dtdx, dtdy, 593 dqdx, dqdy, texW, texH, 594 s, t, q, invQ); 595 texcoord[i][0] = s * invQ; 596 texcoord[i][1] = t * invQ; 597 texcoord[i][2] = r * invQ; 598 texcoord[i][3] = q; 599 s += dsdx; 600 t += dtdx; 601 r += drdx; 602 q += dqdx; 603 } 604 } 605 span->arrayMask |= SPAN_LAMBDA; 606 } 607 else { 608 /* just texture 0, without lambda */ 609 GLfloat (*texcoord)[4] = span->array->texcoords[0]; 610 const GLfloat dsdx = span->texStepX[0][0]; 611 const GLfloat dtdx = span->texStepX[0][1]; 612 const GLfloat drdx = span->texStepX[0][2]; 613 const GLfloat dqdx = span->texStepX[0][3]; 614 GLfloat s = span->tex[0][0]; 615 GLfloat t = span->tex[0][1]; 616 GLfloat r = span->tex[0][2]; 617 GLfloat q = span->tex[0][3]; 618 GLuint i; 619 if (ctx->FragmentProgram._Enabled) { 620 /* do perspective correction but don't divide s, t, r by q */ 621 const GLfloat dwdx = span->dwdx; 622 GLfloat w = span->w; 623 for (i = 0; i < span->end; i++) { 624 const GLfloat invW = 1.0F / w; 625 texcoord[i][0] = s * invW; 626 texcoord[i][1] = t * invW; 627 texcoord[i][2] = r * invW; 628 texcoord[i][3] = q * invW; 629 s += dsdx; 630 t += dtdx; 631 r += drdx; 632 q += dqdx; 633 w += dwdx; 634 } 635 } 636 else if (dqdx == 0.0F) { 637 /* Ortho projection or polygon's parallel to window X axis */ 638 const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q); 639 for (i = 0; i < span->end; i++) { 640 texcoord[i][0] = s * invQ; 641 texcoord[i][1] = t * invQ; 642 texcoord[i][2] = r * invQ; 643 texcoord[i][3] = q; 644 s += dsdx; 645 t += dtdx; 646 r += drdx; 647 } 648 } 649 else { 650 for (i = 0; i < span->end; i++) { 651 const GLfloat invQ = (q == 0.0F) ? 1.0F : (1.0F / q); 652 texcoord[i][0] = s * invQ; 653 texcoord[i][1] = t * invQ; 654 texcoord[i][2] = r * invQ; 655 texcoord[i][3] = q; 656 s += dsdx; 657 t += dtdx; 658 r += drdx; 659 q += dqdx; 660 } 661 } 662 } 663 } 664} 665 666 667/** 668 * Apply the current polygon stipple pattern to a span of pixels. 669 */ 670static void 671stipple_polygon_span( GLcontext *ctx, struct sw_span *span ) 672{ 673 const GLuint highbit = 0x80000000; 674 const GLuint stipple = ctx->PolygonStipple[span->y % 32]; 675 GLubyte *mask = span->array->mask; 676 GLuint i, m; 677 678 ASSERT(ctx->Polygon.StippleFlag); 679 ASSERT((span->arrayMask & SPAN_XY) == 0); 680 681 m = highbit >> (GLuint) (span->x % 32); 682 683 for (i = 0; i < span->end; i++) { 684 if ((m & stipple) == 0) { 685 mask[i] = 0; 686 } 687 m = m >> 1; 688 if (m == 0) { 689 m = highbit; 690 } 691 } 692 span->writeAll = GL_FALSE; 693} 694 695 696/** 697 * Clip a pixel span to the current buffer/window boundaries: 698 * DrawBuffer->_Xmin, _Xmax, _Ymin, _Ymax. This will accomplish 699 * window clipping and scissoring. 700 * Return: GL_TRUE some pixels still visible 701 * GL_FALSE nothing visible 702 */ 703static GLuint 704clip_span( GLcontext *ctx, struct sw_span *span ) 705{ 706 const GLint xmin = ctx->DrawBuffer->_Xmin; 707 const GLint xmax = ctx->DrawBuffer->_Xmax; 708 const GLint ymin = ctx->DrawBuffer->_Ymin; 709 const GLint ymax = ctx->DrawBuffer->_Ymax; 710 711 if (span->arrayMask & SPAN_XY) { 712 /* arrays of x/y pixel coords */ 713 const GLint *x = span->array->x; 714 const GLint *y = span->array->y; 715 const GLint n = span->end; 716 GLubyte *mask = span->array->mask; 717 GLint i; 718 if (span->arrayMask & SPAN_MASK) { 719 /* note: using & intead of && to reduce branches */ 720 for (i = 0; i < n; i++) { 721 mask[i] &= (x[i] >= xmin) & (x[i] < xmax) 722 & (y[i] >= ymin) & (y[i] < ymax); 723 } 724 } 725 else { 726 /* note: using & intead of && to reduce branches */ 727 for (i = 0; i < n; i++) { 728 mask[i] = (x[i] >= xmin) & (x[i] < xmax) 729 & (y[i] >= ymin) & (y[i] < ymax); 730 } 731 } 732 return GL_TRUE; /* some pixels visible */ 733 } 734 else { 735 /* horizontal span of pixels */ 736 const GLint x = span->x; 737 const GLint y = span->y; 738 const GLint n = span->end; 739 740 /* Trivial rejection tests */ 741 if (y < ymin || y >= ymax || x + n <= xmin || x >= xmax) { 742 span->end = 0; 743 return GL_FALSE; /* all pixels clipped */ 744 } 745 746 /* Clip to the left */ 747 if (x < xmin) { 748 ASSERT(x + n > xmin); 749 span->writeAll = GL_FALSE; 750 _mesa_bzero(span->array->mask, (xmin - x) * sizeof(GLubyte)); 751 } 752 753 /* Clip to right */ 754 if (x + n > xmax) { 755 ASSERT(x < xmax); 756 span->end = xmax - x; 757 } 758 759 return GL_TRUE; /* some pixels visible */ 760 } 761} 762 763 764 765/** 766 * Draw to more than one color buffer (or none). 767 */ 768static void 769multi_write_index_span( GLcontext *ctx, struct sw_span *span ) 770{ 771 SWcontext *swrast = SWRAST_CONTEXT(ctx); 772 GLuint bufferBit; 773 774 /* loop over four possible dest color buffers */ 775 for (bufferBit = 1; bufferBit <= 8; bufferBit <<= 1) { 776 if (bufferBit & ctx->Color._DrawDestMask[0]) { 777 GLuint indexTmp[MAX_WIDTH]; 778 ASSERT(span->end < MAX_WIDTH); 779 780 /* Set the current read/draw buffer */ 781 swrast->CurrentBufferBit = bufferBit; 782 (*swrast->Driver.SetBuffer)(ctx, ctx->DrawBuffer, bufferBit); 783 784 /* make copy of incoming indexes */ 785 MEMCPY( indexTmp, span->array->index, span->end * sizeof(GLuint) ); 786 787 if (ctx->Color.IndexLogicOpEnabled) { 788 _swrast_logicop_ci_span(ctx, span, indexTmp); 789 } 790 791 if (ctx->Color.IndexMask != 0xffffffff) { 792 _swrast_mask_index_span(ctx, span, indexTmp); 793 } 794 795 if (span->arrayMask & SPAN_XY) { 796 /* array of pixel coords */ 797 (*swrast->Driver.WriteCI32Pixels)(ctx, span->end, 798 span->array->x, span->array->y, 799 indexTmp, span->array->mask); 800 } 801 else { 802 /* horizontal run of pixels */ 803 (*swrast->Driver.WriteCI32Span)(ctx, span->end, span->x, span->y, 804 indexTmp, span->array->mask); 805 } 806 } 807 } 808 809 /* restore default dest buffer */ 810 _swrast_use_draw_buffer(ctx); 811} 812 813 814/** 815 * Draw to more than one RGBA color buffer (or none). 816 * All fragment operations, up to (but not) blending/logicop should 817 * have been done first. 818 */ 819static void 820multi_write_rgba_span( GLcontext *ctx, struct sw_span *span ) 821{ 822 const GLuint colorMask = *((GLuint *) ctx->Color.ColorMask); 823 GLuint bufferBit; 824 SWcontext *swrast = SWRAST_CONTEXT(ctx); 825 826 ASSERT(colorMask != 0x0); 827 828 if (ctx->Color.DrawBuffer == GL_NONE) 829 return; 830 831 /* loop over four possible dest color buffers */ 832 for (bufferBit = 1; bufferBit <= 8; bufferBit <<= 1) { 833 if (bufferBit & ctx->Color._DrawDestMask[0]) { 834 GLchan rgbaTmp[MAX_WIDTH][4]; 835 ASSERT(span->end < MAX_WIDTH); 836 837 /* Set the current read/draw buffer */ 838 swrast->CurrentBufferBit = bufferBit; 839 (*swrast->Driver.SetBuffer)(ctx, ctx->DrawBuffer, bufferBit); 840 841 /* make copy of incoming colors */ 842 MEMCPY( rgbaTmp, span->array->rgba, 4 * span->end * sizeof(GLchan) ); 843 844 if (ctx->Color._LogicOpEnabled) { 845 _swrast_logicop_rgba_span(ctx, span, rgbaTmp); 846 } 847 else if (ctx->Color.BlendEnabled) { 848 _swrast_blend_span(ctx, span, rgbaTmp); 849 } 850 851 if (colorMask != 0xffffffff) { 852 _swrast_mask_rgba_span(ctx, span, rgbaTmp); 853 } 854 855 if (span->arrayMask & SPAN_XY) { 856 /* array of pixel coords */ 857 (*swrast->Driver.WriteRGBAPixels)(ctx, span->end, 858 span->array->x, span->array->y, 859 (const GLchan (*)[4]) rgbaTmp, 860 span->array->mask); 861 if (SWRAST_CONTEXT(ctx)->_RasterMask & ALPHABUF_BIT) { 862 _swrast_write_alpha_pixels(ctx, span->end, 863 span->array->x, span->array->y, 864 (const GLchan (*)[4]) rgbaTmp, 865 span->array->mask); 866 } 867 } 868 else { 869 /* horizontal run of pixels */ 870 (*swrast->Driver.WriteRGBASpan)(ctx, span->end, span->x, span->y, 871 (const GLchan (*)[4]) rgbaTmp, 872 span->array->mask); 873 if (swrast->_RasterMask & ALPHABUF_BIT) { 874 _swrast_write_alpha_span(ctx, span->end, span->x, span->y, 875 (const GLchan (*)[4]) rgbaTmp, 876 span->array->mask); 877 } 878 } 879 } 880 } 881 882 /* restore default dest buffer */ 883 _swrast_use_draw_buffer(ctx); 884} 885 886 887 888/** 889 * This function may modify any of the array values in the span. 890 * span->interpMask and span->arrayMask may be changed but will be restored 891 * to their original values before returning. 892 */ 893void 894_swrast_write_index_span( GLcontext *ctx, struct sw_span *span) 895{ 896 SWcontext *swrast = SWRAST_CONTEXT(ctx); 897 const GLuint origInterpMask = span->interpMask; 898 const GLuint origArrayMask = span->arrayMask; 899 900 ASSERT(span->end <= MAX_WIDTH); 901 ASSERT(span->primitive == GL_POINT || span->primitive == GL_LINE || 902 span->primitive == GL_POLYGON || span->primitive == GL_BITMAP); 903 ASSERT((span->interpMask | span->arrayMask) & SPAN_INDEX); 904 ASSERT((span->interpMask & span->arrayMask) == 0); 905 906 if (span->arrayMask & SPAN_MASK) { 907 /* mask was initialized by caller, probably glBitmap */ 908 span->writeAll = GL_FALSE; 909 } 910 else { 911 _mesa_memset(span->array->mask, 1, span->end); 912 span->writeAll = GL_TRUE; 913 } 914 915 /* Clipping */ 916 if ((swrast->_RasterMask & CLIP_BIT) || (span->primitive != GL_POLYGON)) { 917 if (!clip_span(ctx, span)) { 918 return; 919 } 920 } 921 922 /* Depth bounds test */ 923 if (ctx->Depth.BoundsTest && ctx->Visual.depthBits > 0) { 924 if (!_swrast_depth_bounds_test(ctx, span)) { 925 return; 926 } 927 } 928 929#ifdef DEBUG 930 /* Make sure all fragments are within window bounds */ 931 if (span->arrayMask & SPAN_XY) { 932 GLuint i; 933 for (i = 0; i < span->end; i++) { 934 if (span->array->mask[i]) { 935 assert(span->array->x[i] >= ctx->DrawBuffer->_Xmin); 936 assert(span->array->x[i] < ctx->DrawBuffer->_Xmax); 937 assert(span->array->y[i] >= ctx->DrawBuffer->_Ymin); 938 assert(span->array->y[i] < ctx->DrawBuffer->_Ymax); 939 } 940 } 941 } 942#endif 943 944 /* Polygon Stippling */ 945 if (ctx->Polygon.StippleFlag && span->primitive == GL_POLYGON) { 946 stipple_polygon_span(ctx, span); 947 } 948 949 /* Depth test and stencil */ 950 if (ctx->Depth.Test || ctx->Stencil.Enabled) { 951 if (span->interpMask & SPAN_Z) 952 _swrast_span_interpolate_z(ctx, span); 953 954 if (ctx->Stencil.Enabled) { 955 if (!_swrast_stencil_and_ztest_span(ctx, span)) { 956 span->arrayMask = origArrayMask; 957 return; 958 } 959 } 960 else { 961 ASSERT(ctx->Depth.Test); 962 if (!_swrast_depth_test_span(ctx, span)) { 963 span->arrayMask = origArrayMask; 964 return; 965 } 966 } 967 } 968 969 /* if we get here, something passed the depth test */ 970 if (ctx->Depth.OcclusionTest) { 971 ctx->OcclusionResult = GL_TRUE; 972 } 973 974#if FEATURE_ARB_occlusion_query 975 if (ctx->Occlusion.Active) { 976 /* update count of 'passed' fragments */ 977 GLuint i; 978 for (i = 0; i < span->end; i++) 979 ctx->Occlusion.PassedCounter += span->array->mask[i]; 980 } 981#endif 982 983 /* we have to wait until after occlusion to do this test */ 984 if (ctx->Color.DrawBuffer == GL_NONE || ctx->Color.IndexMask == 0) { 985 /* write no pixels */ 986 span->arrayMask = origArrayMask; 987 return; 988 } 989 990 /* Interpolate the color indexes if needed */ 991 if (span->interpMask & SPAN_INDEX) { 992 interpolate_indexes(ctx, span); 993 /* clear the bit - this allows the WriteMonoCISpan optimization below */ 994 span->interpMask &= ~SPAN_INDEX; 995 } 996 997 /* Fog */ 998 if (ctx->Fog.Enabled) { 999 _swrast_fog_ci_span(ctx, span); 1000 } 1001 1002 /* Antialias coverage application */ 1003 if (span->arrayMask & SPAN_COVERAGE) { 1004 GLuint i; 1005 GLuint *index = span->array->index; 1006 GLfloat *coverage = span->array->coverage; 1007 for (i = 0; i < span->end; i++) { 1008 ASSERT(coverage[i] < 16); 1009 index[i] = (index[i] & ~0xf) | ((GLuint) coverage[i]); 1010 } 1011 } 1012 1013 if (swrast->_RasterMask & MULTI_DRAW_BIT) { 1014 /* draw to zero or two or more buffers */ 1015 multi_write_index_span(ctx, span); 1016 } 1017 else { 1018 /* normal situation: draw to exactly one buffer */ 1019 if (ctx->Color.IndexLogicOpEnabled) { 1020 _swrast_logicop_ci_span(ctx, span, span->array->index); 1021 } 1022 1023 if (ctx->Color.IndexMask != 0xffffffff) { 1024 _swrast_mask_index_span(ctx, span, span->array->index); 1025 } 1026 1027 /* write pixels */ 1028 if (span->arrayMask & SPAN_XY) { 1029 /* array of pixel coords */ 1030 if ((span->interpMask & SPAN_INDEX) && span->indexStep == 0) { 1031 /* all pixels have same color index */ 1032 (*swrast->Driver.WriteMonoCIPixels)(ctx, span->end, 1033 span->array->x, span->array->y, 1034 FixedToInt(span->index), 1035 span->array->mask); 1036 } 1037 else { 1038 (*swrast->Driver.WriteCI32Pixels)(ctx, span->end, span->array->x, 1039 span->array->y, span->array->index, 1040 span->array->mask ); 1041 } 1042 } 1043 else { 1044 /* horizontal run of pixels */ 1045 if ((span->interpMask & SPAN_INDEX) && span->indexStep == 0) { 1046 /* all pixels have same color index */ 1047 (*swrast->Driver.WriteMonoCISpan)(ctx, span->end, span->x, span->y, 1048 FixedToInt(span->index), 1049 span->array->mask); 1050 } 1051 else { 1052 (*swrast->Driver.WriteCI32Span)(ctx, span->end, span->x, span->y, 1053 span->array->index, 1054 span->array->mask); 1055 } 1056 } 1057 } 1058 1059 span->interpMask = origInterpMask; 1060 span->arrayMask = origArrayMask; 1061} 1062 1063 1064/** 1065 * Add specular color to base color. This is used only when 1066 * GL_LIGHT_MODEL_COLOR_CONTROL = GL_SEPARATE_SPECULAR_COLOR. 1067 */ 1068static void 1069add_colors(GLuint n, GLchan rgba[][4], GLchan specular[][4] ) 1070{ 1071 GLuint i; 1072 for (i = 0; i < n; i++) { 1073#if CHAN_TYPE == GL_FLOAT 1074 /* no clamping */ 1075 rgba[i][RCOMP] += specular[i][RCOMP]; 1076 rgba[i][GCOMP] += specular[i][GCOMP]; 1077 rgba[i][BCOMP] += specular[i][BCOMP]; 1078#else 1079 GLint r = rgba[i][RCOMP] + specular[i][RCOMP]; 1080 GLint g = rgba[i][GCOMP] + specular[i][GCOMP]; 1081 GLint b = rgba[i][BCOMP] + specular[i][BCOMP]; 1082 rgba[i][RCOMP] = (GLchan) MIN2(r, CHAN_MAX); 1083 rgba[i][GCOMP] = (GLchan) MIN2(g, CHAN_MAX); 1084 rgba[i][BCOMP] = (GLchan) MIN2(b, CHAN_MAX); 1085#endif 1086 } 1087} 1088 1089 1090/** 1091 * Apply all the per-fragment operations to a span. 1092 * This now includes texturing (_swrast_write_texture_span() is history). 1093 * This function may modify any of the array values in the span. 1094 * span->interpMask and span->arrayMask may be changed but will be restored 1095 * to their original values before returning. 1096 */ 1097void 1098_swrast_write_rgba_span( GLcontext *ctx, struct sw_span *span) 1099{ 1100 const GLuint colorMask = *((GLuint *) ctx->Color.ColorMask); 1101 SWcontext *swrast = SWRAST_CONTEXT(ctx); 1102 const GLuint origInterpMask = span->interpMask; 1103 const GLuint origArrayMask = span->arrayMask; 1104 1105 ASSERT(span->primitive == GL_POINT || span->primitive == GL_LINE || 1106 span->primitive == GL_POLYGON || span->primitive == GL_BITMAP); 1107 ASSERT(span->end <= MAX_WIDTH); 1108 ASSERT((span->interpMask & span->arrayMask) == 0); 1109 1110 /* 1111 printf("%s() interp 0x%x array 0x%x\n", __FUNCTION__, 1112 span->interpMask, span->arrayMask); 1113 */ 1114 1115 if (span->arrayMask & SPAN_MASK) { 1116 /* mask was initialized by caller, probably glBitmap */ 1117 span->writeAll = GL_FALSE; 1118 } 1119 else { 1120 _mesa_memset(span->array->mask, 1, span->end); 1121 span->writeAll = GL_TRUE; 1122 } 1123 1124 /* Clip to window/scissor box */ 1125 if ((swrast->_RasterMask & CLIP_BIT) || (span->primitive != GL_POLYGON)) { 1126 if (!clip_span(ctx, span)) { 1127 return; 1128 } 1129 } 1130 1131#ifdef DEBUG 1132 /* Make sure all fragments are within window bounds */ 1133 if (span->arrayMask & SPAN_XY) { 1134 GLuint i; 1135 for (i = 0; i < span->end; i++) { 1136 if (span->array->mask[i]) { 1137 assert(span->array->x[i] >= ctx->DrawBuffer->_Xmin); 1138 assert(span->array->x[i] < ctx->DrawBuffer->_Xmax); 1139 assert(span->array->y[i] >= ctx->DrawBuffer->_Ymin); 1140 assert(span->array->y[i] < ctx->DrawBuffer->_Ymax); 1141 } 1142 } 1143 } 1144#endif 1145 1146 /* Polygon Stippling */ 1147 if (ctx->Polygon.StippleFlag && span->primitive == GL_POLYGON) { 1148 stipple_polygon_span(ctx, span); 1149 } 1150 1151 /* Interpolate texcoords? */ 1152 if (ctx->Texture._EnabledCoordUnits 1153 && (span->interpMask & SPAN_TEXTURE) 1154 && (span->arrayMask & SPAN_TEXTURE) == 0) { 1155 interpolate_texcoords(ctx, span); 1156 } 1157 1158 /* If the alpha test is enabled, we have to compute the fragment colors 1159 * at this point and do the alpha test. 1160 * Else, if alpha test is not enabled, we'll try to defer fragment 1161 * color computation (by interpolation, texture mapping, fragment program) 1162 * until after the Z/stencil tests in the hope that many fragments will 1163 * get culled, leaving less work to do. 1164 */ 1165 if (ctx->Color.AlphaEnabled) { 1166 /* Now we need the rgba array, fill it in if needed */ 1167 if ((span->interpMask & SPAN_RGBA) && (span->arrayMask & SPAN_RGBA) == 0) 1168 interpolate_colors(ctx, span); 1169 1170 if (span->interpMask & SPAN_SPEC) 1171 interpolate_specular(ctx, span); 1172 1173 if (span->interpMask & SPAN_FOG) 1174 interpolate_fog(ctx, span); 1175 1176 /* Compute fragment colors with fragment program or texture lookups */ 1177 if (ctx->FragmentProgram._Enabled) 1178 /* XXX interpolate depth values here??? */ 1179 _swrast_exec_fragment_program( ctx, span ); 1180 else if (ctx->ATIFragmentShader._Enabled) 1181 _swrast_exec_fragment_shader( ctx, span ); 1182 else if (ctx->Texture._EnabledUnits) 1183 _swrast_texture_span( ctx, span ); 1184 1185 /* Do the alpha test */ 1186 if (!_swrast_alpha_test(ctx, span)) { 1187 span->arrayMask = origArrayMask; 1188 return; 1189 } 1190 } 1191 1192 /* Stencil and Z testing */ 1193 if (ctx->Stencil.Enabled || ctx->Depth.Test) { 1194 if (span->interpMask & SPAN_Z) 1195 _swrast_span_interpolate_z(ctx, span); 1196 1197 if (ctx->Stencil.Enabled) { 1198 /* Combined Z/stencil tests */ 1199 if (!_swrast_stencil_and_ztest_span(ctx, span)) { 1200 span->interpMask = origInterpMask; 1201 span->arrayMask = origArrayMask; 1202 return; 1203 } 1204 } 1205 else { 1206 /* Just regular depth testing */ 1207 ASSERT(ctx->Depth.Test); 1208 ASSERT(span->arrayMask & SPAN_Z); 1209 if (!_swrast_depth_test_span(ctx, span)) { 1210 span->interpMask = origInterpMask; 1211 span->arrayMask = origArrayMask; 1212 return; 1213 } 1214 } 1215 } 1216 1217 /* if we get here, some fragments passed the depth test */ 1218 if (ctx->Depth.OcclusionTest) { 1219 ctx->OcclusionResult = GL_TRUE; 1220 } 1221 1222#if FEATURE_ARB_occlusion_query 1223 if (ctx->Occlusion.Active) { 1224 /* update count of 'passed' fragments */ 1225 GLuint i; 1226 for (i = 0; i < span->end; i++) 1227 ctx->Occlusion.PassedCounter += span->array->mask[i]; 1228 } 1229#endif 1230 1231 /* We had to wait until now to check for glColorMask(0,0,0,0) because of 1232 * the occlusion test. 1233 */ 1234 if (colorMask == 0x0) { 1235 span->interpMask = origInterpMask; 1236 span->arrayMask = origArrayMask; 1237 return; 1238 } 1239 1240 /* If the alpha test isn't enabled, we're able to defer computing fragment 1241 * colors (by interpolation, texturing, fragment program) until now. 1242 * Hopefully, Z/stencil tests culled many of the fragments! 1243 */ 1244 if (!ctx->Color.AlphaEnabled) { 1245 /* Now we need the rgba array, fill it in if needed */ 1246 if ((span->interpMask & SPAN_RGBA) && (span->arrayMask & SPAN_RGBA) == 0) 1247 interpolate_colors(ctx, span); 1248 1249 if (span->interpMask & SPAN_SPEC) 1250 interpolate_specular(ctx, span); 1251 1252 if (span->interpMask & SPAN_FOG) 1253 interpolate_fog(ctx, span); 1254 1255 if (ctx->FragmentProgram._Enabled) 1256 _swrast_exec_fragment_program( ctx, span ); 1257 else if (ctx->ATIFragmentShader._Enabled) 1258 _swrast_exec_fragment_shader( ctx, span ); 1259 else if (ctx->Texture._EnabledUnits) 1260 _swrast_texture_span( ctx, span ); 1261 } 1262 1263 ASSERT(span->arrayMask & SPAN_RGBA); 1264 1265 if (!ctx->FragmentProgram._Enabled) { 1266 /* Add base and specular colors */ 1267 if (ctx->Fog.ColorSumEnabled || 1268 (ctx->Light.Enabled && 1269 ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)) { 1270 if (span->interpMask & SPAN_SPEC) { 1271 interpolate_specular(ctx, span); 1272 } 1273 if (span->arrayMask & SPAN_SPEC) { 1274 add_colors( span->end, span->array->rgba, span->array->spec ); 1275 } 1276 else { 1277 /* We probably added the base/specular colors during the 1278 * vertex stage! 1279 */ 1280 } 1281 } 1282 } 1283 1284 /* Fog */ 1285 if (swrast->_FogEnabled) { 1286 _swrast_fog_rgba_span(ctx, span); 1287 } 1288 1289 /* Antialias coverage application */ 1290 if (span->arrayMask & SPAN_COVERAGE) { 1291 GLchan (*rgba)[4] = span->array->rgba; 1292 GLfloat *coverage = span->array->coverage; 1293 GLuint i; 1294 for (i = 0; i < span->end; i++) { 1295 rgba[i][ACOMP] = (GLchan) (rgba[i][ACOMP] * coverage[i]); 1296 } 1297 } 1298 1299 if (swrast->_RasterMask & MULTI_DRAW_BIT) { 1300 /* need to do blend/logicop separately for each color buffer */ 1301 multi_write_rgba_span(ctx, span); 1302 } 1303 else { 1304 /* normal: write to exactly one buffer */ 1305 if (ctx->Color._LogicOpEnabled) { 1306 _swrast_logicop_rgba_span(ctx, span, span->array->rgba); 1307 } 1308 else if (ctx->Color.BlendEnabled) { 1309 _swrast_blend_span(ctx, span, span->array->rgba); 1310 } 1311 1312 /* Color component masking */ 1313 if (colorMask != 0xffffffff) { 1314 _swrast_mask_rgba_span(ctx, span, span->array->rgba); 1315 } 1316 1317 /* Finally, write the pixels to a color buffer */ 1318 if (span->arrayMask & SPAN_XY) { 1319 /* array of pixel coords */ 1320 swrast->Driver.WriteRGBAPixels(ctx, span->end, span->array->x, 1321 span->array->y, (const GLchan (*)[4]) span->array->rgba, 1322 span->array->mask); 1323 if (SWRAST_CONTEXT(ctx)->_RasterMask & ALPHABUF_BIT) { 1324 _swrast_write_alpha_pixels(ctx, span->end, 1325 span->array->x, span->array->y, 1326 (const GLchan (*)[4]) span->array->rgba, 1327 span->array->mask); 1328 } 1329 } 1330 else { 1331 /* horizontal run of pixels */ 1332 swrast->Driver.WriteRGBASpan(ctx, span->end, span->x, span->y, 1333 (const GLchan (*)[4]) span->array->rgba, 1334 span->writeAll ? NULL : span->array->mask); 1335 if (swrast->_RasterMask & ALPHABUF_BIT) { 1336 _swrast_write_alpha_span(ctx, span->end, span->x, span->y, 1337 (const GLchan (*)[4]) span->array->rgba, 1338 span->writeAll ? NULL : span->array->mask); 1339 } 1340 } 1341 } 1342 1343 span->interpMask = origInterpMask; 1344 span->arrayMask = origArrayMask; 1345} 1346 1347 1348 1349/** 1350 * Read RGBA pixels from frame buffer. Clipping will be done to prevent 1351 * reading ouside the buffer's boundaries. 1352 */ 1353void 1354_swrast_read_rgba_span( GLcontext *ctx, GLframebuffer *buffer, 1355 GLuint n, GLint x, GLint y, GLchan rgba[][4] ) 1356{ 1357 SWcontext *swrast = SWRAST_CONTEXT(ctx); 1358 const GLint bufWidth = (GLint) buffer->Width; 1359 const GLint bufHeight = (GLint) buffer->Height; 1360 1361 if (y < 0 || y >= bufHeight || x + (GLint) n < 0 || x >= bufWidth) { 1362 /* completely above, below, or right */ 1363 /* XXX maybe leave undefined? */ 1364 _mesa_bzero(rgba, 4 * n * sizeof(GLchan)); 1365 } 1366 else { 1367 GLint skip, length; 1368 if (x < 0) { 1369 /* left edge clippping */ 1370 skip = -x; 1371 length = (GLint) n - skip; 1372 if (length < 0) { 1373 /* completely left of window */ 1374 return; 1375 } 1376 if (length > bufWidth) { 1377 length = bufWidth; 1378 } 1379 } 1380 else if ((GLint) (x + n) > bufWidth) { 1381 /* right edge clipping */ 1382 skip = 0; 1383 length = bufWidth - x; 1384 if (length < 0) { 1385 /* completely to right of window */ 1386 return; 1387 } 1388 } 1389 else { 1390 /* no clipping */ 1391 skip = 0; 1392 length = (GLint) n; 1393 } 1394 1395 (*swrast->Driver.ReadRGBASpan)( ctx, length, x + skip, y, rgba + skip ); 1396 if (buffer->UseSoftwareAlphaBuffers) { 1397 _swrast_read_alpha_span(ctx, length, x + skip, y, rgba + skip); 1398 } 1399 } 1400} 1401 1402 1403/** 1404 * Read CI pixels from frame buffer. Clipping will be done to prevent 1405 * reading ouside the buffer's boundaries. 1406 */ 1407void 1408_swrast_read_index_span( GLcontext *ctx, GLframebuffer *buffer, 1409 GLuint n, GLint x, GLint y, GLuint indx[] ) 1410{ 1411 SWcontext *swrast = SWRAST_CONTEXT(ctx); 1412 const GLint bufWidth = (GLint) buffer->Width; 1413 const GLint bufHeight = (GLint) buffer->Height; 1414 1415 if (y < 0 || y >= bufHeight || x + (GLint) n < 0 || x >= bufWidth) { 1416 /* completely above, below, or right */ 1417 _mesa_bzero(indx, n * sizeof(GLuint)); 1418 } 1419 else { 1420 GLint skip, length; 1421 if (x < 0) { 1422 /* left edge clippping */ 1423 skip = -x; 1424 length = (GLint) n - skip; 1425 if (length < 0) { 1426 /* completely left of window */ 1427 return; 1428 } 1429 if (length > bufWidth) { 1430 length = bufWidth; 1431 } 1432 } 1433 else if ((GLint) (x + n) > bufWidth) { 1434 /* right edge clipping */ 1435 skip = 0; 1436 length = bufWidth - x; 1437 if (length < 0) { 1438 /* completely to right of window */ 1439 return; 1440 } 1441 } 1442 else { 1443 /* no clipping */ 1444 skip = 0; 1445 length = (GLint) n; 1446 } 1447 1448 (*swrast->Driver.ReadCI32Span)( ctx, length, skip + x, y, indx + skip ); 1449 } 1450} 1451