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