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