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