s_drawpix.c revision cfc4b4c98920293cb9a91ba0e9f89626e175c8dc
1/* 2 * Mesa 3-D graphics library 3 * Version: 7.1 4 * 5 * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a 8 * copy of this software and associated documentation files (the "Software"), 9 * to deal in the Software without restriction, including without limitation 10 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 * and/or sell copies of the Software, and to permit persons to whom the 12 * Software is furnished to do so, subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be included 15 * in all copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 */ 24 25 26#include "main/glheader.h" 27#include "main/bufferobj.h" 28#include "main/context.h" 29#include "main/convolve.h" 30#include "main/image.h" 31#include "main/macros.h" 32#include "main/imports.h" 33#include "main/pixel.h" 34#include "main/state.h" 35 36#include "s_context.h" 37#include "s_span.h" 38#include "s_stencil.h" 39#include "s_zoom.h" 40 41 42 43/** 44 * Try to do a fast and simple RGB(a) glDrawPixels. 45 * Return: GL_TRUE if success, GL_FALSE if slow path must be used instead 46 */ 47static GLboolean 48fast_draw_rgba_pixels(GLcontext *ctx, GLint x, GLint y, 49 GLsizei width, GLsizei height, 50 GLenum format, GLenum type, 51 const struct gl_pixelstore_attrib *userUnpack, 52 const GLvoid *pixels) 53{ 54 const GLint imgX = x, imgY = y; 55 struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[0]; 56 GLenum rbType; 57 SWcontext *swrast = SWRAST_CONTEXT(ctx); 58 SWspan span; 59 GLboolean simpleZoom; 60 GLint yStep; /* +1 or -1 */ 61 struct gl_pixelstore_attrib unpack; 62 GLint destX, destY, drawWidth, drawHeight; /* post clipping */ 63 64 if (!rb) 65 return GL_TRUE; /* no-op */ 66 67 rbType = rb->DataType; 68 69 if ((swrast->_RasterMask & ~CLIP_BIT) || 70 ctx->Texture._EnabledCoordUnits || 71 userUnpack->SwapBytes || 72 ctx->_ImageTransferState) { 73 /* can't handle any of those conditions */ 74 return GL_FALSE; 75 } 76 77 INIT_SPAN(span, GL_BITMAP); 78 span.arrayMask = SPAN_RGBA; 79 span.arrayAttribs = FRAG_BIT_COL0; 80 _swrast_span_default_attribs(ctx, &span); 81 82 /* copy input params since clipping may change them */ 83 unpack = *userUnpack; 84 destX = x; 85 destY = y; 86 drawWidth = width; 87 drawHeight = height; 88 89 /* check for simple zooming and clipping */ 90 if (ctx->Pixel.ZoomX == 1.0F && 91 (ctx->Pixel.ZoomY == 1.0F || ctx->Pixel.ZoomY == -1.0F)) { 92 if (!_mesa_clip_drawpixels(ctx, &destX, &destY, 93 &drawWidth, &drawHeight, &unpack)) { 94 /* image was completely clipped: no-op, all done */ 95 return GL_TRUE; 96 } 97 simpleZoom = GL_TRUE; 98 yStep = (GLint) ctx->Pixel.ZoomY; 99 ASSERT(yStep == 1 || yStep == -1); 100 } 101 else { 102 /* non-simple zooming */ 103 simpleZoom = GL_FALSE; 104 yStep = 1; 105 if (unpack.RowLength == 0) 106 unpack.RowLength = width; 107 } 108 109 /* 110 * Ready to draw! 111 */ 112 113 if (format == GL_RGBA && type == rbType) { 114 const GLubyte *src 115 = (const GLubyte *) _mesa_image_address2d(&unpack, pixels, width, 116 height, format, type, 0, 0); 117 const GLint srcStride = _mesa_image_row_stride(&unpack, width, 118 format, type); 119 if (simpleZoom) { 120 GLint row; 121 for (row = 0; row < drawHeight; row++) { 122 rb->PutRow(ctx, rb, drawWidth, destX, destY, src, NULL); 123 src += srcStride; 124 destY += yStep; 125 } 126 } 127 else { 128 /* with zooming */ 129 GLint row; 130 for (row = 0; row < drawHeight; row++) { 131 span.x = destX; 132 span.y = destY + row; 133 span.end = drawWidth; 134 span.array->ChanType = rbType; 135 _swrast_write_zoomed_rgba_span(ctx, imgX, imgY, &span, src); 136 src += srcStride; 137 } 138 span.array->ChanType = CHAN_TYPE; 139 } 140 return GL_TRUE; 141 } 142 143 if (format == GL_RGB && type == rbType) { 144 const GLubyte *src 145 = (const GLubyte *) _mesa_image_address2d(&unpack, pixels, width, 146 height, format, type, 0, 0); 147 const GLint srcStride = _mesa_image_row_stride(&unpack, width, 148 format, type); 149 if (simpleZoom) { 150 GLint row; 151 for (row = 0; row < drawHeight; row++) { 152 rb->PutRowRGB(ctx, rb, drawWidth, destX, destY, src, NULL); 153 src += srcStride; 154 destY += yStep; 155 } 156 } 157 else { 158 /* with zooming */ 159 GLint row; 160 for (row = 0; row < drawHeight; row++) { 161 span.x = destX; 162 span.y = destY; 163 span.end = drawWidth; 164 span.array->ChanType = rbType; 165 _swrast_write_zoomed_rgb_span(ctx, imgX, imgY, &span, src); 166 src += srcStride; 167 destY++; 168 } 169 span.array->ChanType = CHAN_TYPE; 170 } 171 return GL_TRUE; 172 } 173 174 /* Remaining cases haven't been tested with alignment != 1 */ 175 if (userUnpack->Alignment != 1) 176 return GL_FALSE; 177 178 if (format == GL_LUMINANCE && type == CHAN_TYPE && rbType == CHAN_TYPE) { 179 const GLchan *src = (const GLchan *) pixels 180 + (unpack.SkipRows * unpack.RowLength + unpack.SkipPixels); 181 if (simpleZoom) { 182 /* no zooming */ 183 GLint row; 184 ASSERT(drawWidth <= MAX_WIDTH); 185 for (row = 0; row < drawHeight; row++) { 186 GLchan rgb[MAX_WIDTH][3]; 187 GLint i; 188 for (i = 0;i<drawWidth;i++) { 189 rgb[i][0] = src[i]; 190 rgb[i][1] = src[i]; 191 rgb[i][2] = src[i]; 192 } 193 rb->PutRowRGB(ctx, rb, drawWidth, destX, destY, rgb, NULL); 194 src += unpack.RowLength; 195 destY += yStep; 196 } 197 } 198 else { 199 /* with zooming */ 200 GLint row; 201 ASSERT(drawWidth <= MAX_WIDTH); 202 for (row = 0; row < drawHeight; row++) { 203 GLchan rgb[MAX_WIDTH][3]; 204 GLint i; 205 for (i = 0;i<drawWidth;i++) { 206 rgb[i][0] = src[i]; 207 rgb[i][1] = src[i]; 208 rgb[i][2] = src[i]; 209 } 210 span.x = destX; 211 span.y = destY; 212 span.end = drawWidth; 213 _swrast_write_zoomed_rgb_span(ctx, imgX, imgY, &span, rgb); 214 src += unpack.RowLength; 215 destY++; 216 } 217 } 218 return GL_TRUE; 219 } 220 221 if (format == GL_LUMINANCE_ALPHA && type == CHAN_TYPE && rbType == CHAN_TYPE) { 222 const GLchan *src = (const GLchan *) pixels 223 + (unpack.SkipRows * unpack.RowLength + unpack.SkipPixels)*2; 224 if (simpleZoom) { 225 GLint row; 226 ASSERT(drawWidth <= MAX_WIDTH); 227 for (row = 0; row < drawHeight; row++) { 228 GLint i; 229 const GLchan *ptr = src; 230 for (i = 0;i<drawWidth;i++) { 231 span.array->rgba[i][0] = *ptr; 232 span.array->rgba[i][1] = *ptr; 233 span.array->rgba[i][2] = *ptr++; 234 span.array->rgba[i][3] = *ptr++; 235 } 236 rb->PutRow(ctx, rb, drawWidth, destX, destY, 237 span.array->rgba, NULL); 238 src += unpack.RowLength*2; 239 destY += yStep; 240 } 241 } 242 else { 243 /* with zooming */ 244 GLint row; 245 ASSERT(drawWidth <= MAX_WIDTH); 246 for (row = 0; row < drawHeight; row++) { 247 const GLchan *ptr = src; 248 GLint i; 249 for (i = 0;i<drawWidth;i++) { 250 span.array->rgba[i][0] = *ptr; 251 span.array->rgba[i][1] = *ptr; 252 span.array->rgba[i][2] = *ptr++; 253 span.array->rgba[i][3] = *ptr++; 254 } 255 span.x = destX; 256 span.y = destY; 257 span.end = drawWidth; 258 _swrast_write_zoomed_rgba_span(ctx, imgX, imgY, &span, 259 span.array->rgba); 260 src += unpack.RowLength*2; 261 destY++; 262 } 263 } 264 return GL_TRUE; 265 } 266 267 if (format == GL_COLOR_INDEX && type == GL_UNSIGNED_BYTE) { 268 const GLubyte *src = (const GLubyte *) pixels 269 + unpack.SkipRows * unpack.RowLength + unpack.SkipPixels; 270 if (ctx->Visual.rgbMode && rbType == GL_UNSIGNED_BYTE) { 271 /* convert ubyte/CI data to ubyte/RGBA */ 272 if (simpleZoom) { 273 GLint row; 274 for (row = 0; row < drawHeight; row++) { 275 ASSERT(drawWidth <= MAX_WIDTH); 276 _mesa_map_ci8_to_rgba8(ctx, drawWidth, src, 277 span.array->rgba8); 278 rb->PutRow(ctx, rb, drawWidth, destX, destY, 279 span.array->rgba8, NULL); 280 src += unpack.RowLength; 281 destY += yStep; 282 } 283 } 284 else { 285 /* ubyte/CI to ubyte/RGBA with zooming */ 286 GLint row; 287 for (row = 0; row < drawHeight; row++) { 288 ASSERT(drawWidth <= MAX_WIDTH); 289 _mesa_map_ci8_to_rgba8(ctx, drawWidth, src, 290 span.array->rgba8); 291 span.x = destX; 292 span.y = destY; 293 span.end = drawWidth; 294 _swrast_write_zoomed_rgba_span(ctx, imgX, imgY, &span, 295 span.array->rgba8); 296 src += unpack.RowLength; 297 destY++; 298 } 299 } 300 return GL_TRUE; 301 } 302 else if (!ctx->Visual.rgbMode && rbType == GL_UNSIGNED_INT) { 303 /* write CI data to CI frame buffer */ 304 GLint row; 305 if (simpleZoom) { 306 for (row = 0; row < drawHeight; row++) { 307 GLuint index32[MAX_WIDTH]; 308 GLint col; 309 for (col = 0; col < drawWidth; col++) 310 index32[col] = src[col]; 311 rb->PutRow(ctx, rb, drawWidth, destX, destY, index32, NULL); 312 src += unpack.RowLength; 313 destY += yStep; 314 } 315 return GL_TRUE; 316 } 317 } 318 } 319 320 /* can't handle this pixel format and/or data type */ 321 return GL_FALSE; 322} 323 324 325 326/* 327 * Draw color index image. 328 */ 329static void 330draw_index_pixels( GLcontext *ctx, GLint x, GLint y, 331 GLsizei width, GLsizei height, 332 GLenum type, 333 const struct gl_pixelstore_attrib *unpack, 334 const GLvoid *pixels ) 335{ 336 const GLint imgX = x, imgY = y; 337 const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0; 338 GLint row, skipPixels; 339 SWspan span; 340 341 INIT_SPAN(span, GL_BITMAP); 342 span.arrayMask = SPAN_INDEX; 343 _swrast_span_default_attribs(ctx, &span); 344 345 /* 346 * General solution 347 */ 348 skipPixels = 0; 349 while (skipPixels < width) { 350 const GLint spanWidth = MIN2(width - skipPixels, MAX_WIDTH); 351 ASSERT(spanWidth <= MAX_WIDTH); 352 for (row = 0; row < height; row++) { 353 const GLvoid *source = _mesa_image_address2d(unpack, pixels, 354 width, height, 355 GL_COLOR_INDEX, type, 356 row, skipPixels); 357 _mesa_unpack_index_span(ctx, spanWidth, GL_UNSIGNED_INT, 358 span.array->index, type, source, unpack, 359 ctx->_ImageTransferState); 360 361 /* These may get changed during writing/clipping */ 362 span.x = x + skipPixels; 363 span.y = y + row; 364 span.end = spanWidth; 365 366 if (zoom) 367 _swrast_write_zoomed_index_span(ctx, imgX, imgY, &span); 368 else 369 _swrast_write_index_span(ctx, &span); 370 } 371 skipPixels += spanWidth; 372 } 373} 374 375 376 377/* 378 * Draw stencil image. 379 */ 380static void 381draw_stencil_pixels( GLcontext *ctx, GLint x, GLint y, 382 GLsizei width, GLsizei height, 383 GLenum type, 384 const struct gl_pixelstore_attrib *unpack, 385 const GLvoid *pixels ) 386{ 387 const GLboolean zoom = ctx->Pixel.ZoomX != 1.0 || ctx->Pixel.ZoomY != 1.0; 388 GLint skipPixels; 389 390 /* if width > MAX_WIDTH, have to process image in chunks */ 391 skipPixels = 0; 392 while (skipPixels < width) { 393 const GLint spanX = x + skipPixels; 394 const GLint spanWidth = MIN2(width - skipPixels, MAX_WIDTH); 395 GLint row; 396 for (row = 0; row < height; row++) { 397 const GLint spanY = y + row; 398 GLstencil values[MAX_WIDTH]; 399 GLenum destType = (sizeof(GLstencil) == sizeof(GLubyte)) 400 ? GL_UNSIGNED_BYTE : GL_UNSIGNED_SHORT; 401 const GLvoid *source = _mesa_image_address2d(unpack, pixels, 402 width, height, 403 GL_COLOR_INDEX, type, 404 row, skipPixels); 405 _mesa_unpack_stencil_span(ctx, spanWidth, destType, values, 406 type, source, unpack, 407 ctx->_ImageTransferState); 408 if (zoom) { 409 _swrast_write_zoomed_stencil_span(ctx, x, y, spanWidth, 410 spanX, spanY, values); 411 } 412 else { 413 _swrast_write_stencil_span(ctx, spanWidth, spanX, spanY, values); 414 } 415 } 416 skipPixels += spanWidth; 417 } 418} 419 420 421/* 422 * Draw depth image. 423 */ 424static void 425draw_depth_pixels( GLcontext *ctx, GLint x, GLint y, 426 GLsizei width, GLsizei height, 427 GLenum type, 428 const struct gl_pixelstore_attrib *unpack, 429 const GLvoid *pixels ) 430{ 431 const GLboolean scaleOrBias 432 = ctx->Pixel.DepthScale != 1.0 || ctx->Pixel.DepthBias != 0.0; 433 const GLboolean zoom = ctx->Pixel.ZoomX != 1.0 || ctx->Pixel.ZoomY != 1.0; 434 SWspan span; 435 436 INIT_SPAN(span, GL_BITMAP); 437 span.arrayMask = SPAN_Z; 438 _swrast_span_default_attribs(ctx, &span); 439 440 if (type == GL_UNSIGNED_SHORT 441 && ctx->DrawBuffer->Visual.depthBits == 16 442 && !scaleOrBias 443 && !zoom 444 && ctx->Visual.rgbMode 445 && width <= MAX_WIDTH 446 && !unpack->SwapBytes) { 447 /* Special case: directly write 16-bit depth values */ 448 GLint row; 449 for (row = 0; row < height; row++) { 450 const GLushort *zSrc = (const GLushort *) 451 _mesa_image_address2d(unpack, pixels, width, height, 452 GL_DEPTH_COMPONENT, type, row, 0); 453 GLint i; 454 for (i = 0; i < width; i++) 455 span.array->z[i] = zSrc[i]; 456 span.x = x; 457 span.y = y + row; 458 span.end = width; 459 _swrast_write_rgba_span(ctx, &span); 460 } 461 } 462 else if (type == GL_UNSIGNED_INT 463 && !scaleOrBias 464 && !zoom 465 && ctx->Visual.rgbMode 466 && width <= MAX_WIDTH 467 && !unpack->SwapBytes) { 468 /* Special case: shift 32-bit values down to Visual.depthBits */ 469 const GLint shift = 32 - ctx->DrawBuffer->Visual.depthBits; 470 GLint row; 471 for (row = 0; row < height; row++) { 472 const GLuint *zSrc = (const GLuint *) 473 _mesa_image_address2d(unpack, pixels, width, height, 474 GL_DEPTH_COMPONENT, type, row, 0); 475 if (shift == 0) { 476 _mesa_memcpy(span.array->z, zSrc, width * sizeof(GLuint)); 477 } 478 else { 479 GLint col; 480 for (col = 0; col < width; col++) 481 span.array->z[col] = zSrc[col] >> shift; 482 } 483 span.x = x; 484 span.y = y + row; 485 span.end = width; 486 _swrast_write_rgba_span(ctx, &span); 487 } 488 } 489 else { 490 /* General case */ 491 const GLuint depthMax = ctx->DrawBuffer->_DepthMax; 492 GLint skipPixels = 0; 493 494 /* in case width > MAX_WIDTH do the copy in chunks */ 495 while (skipPixels < width) { 496 const GLint spanWidth = MIN2(width - skipPixels, MAX_WIDTH); 497 GLint row; 498 ASSERT(span.end <= MAX_WIDTH); 499 for (row = 0; row < height; row++) { 500 const GLvoid *zSrc = _mesa_image_address2d(unpack, 501 pixels, width, height, 502 GL_DEPTH_COMPONENT, type, 503 row, skipPixels); 504 505 /* Set these for each row since the _swrast_write_* function may 506 * change them while clipping. 507 */ 508 span.x = x + skipPixels; 509 span.y = y + row; 510 span.end = spanWidth; 511 512 _mesa_unpack_depth_span(ctx, spanWidth, 513 GL_UNSIGNED_INT, span.array->z, depthMax, 514 type, zSrc, unpack); 515 if (zoom) { 516 _swrast_write_zoomed_depth_span(ctx, x, y, &span); 517 } 518 else if (ctx->Visual.rgbMode) { 519 _swrast_write_rgba_span(ctx, &span); 520 } 521 else { 522 _swrast_write_index_span(ctx, &span); 523 } 524 } 525 skipPixels += spanWidth; 526 } 527 } 528} 529 530 531 532/** 533 * Draw RGBA image. 534 */ 535static void 536draw_rgba_pixels( GLcontext *ctx, GLint x, GLint y, 537 GLsizei width, GLsizei height, 538 GLenum format, GLenum type, 539 const struct gl_pixelstore_attrib *unpack, 540 const GLvoid *pixels ) 541{ 542 const GLint imgX = x, imgY = y; 543 const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0; 544 GLfloat *convImage = NULL; 545 GLbitfield transferOps = ctx->_ImageTransferState; 546 SWspan span; 547 548 /* Try an optimized glDrawPixels first */ 549 if (fast_draw_rgba_pixels(ctx, x, y, width, height, format, type, 550 unpack, pixels)) { 551 return; 552 } 553 554 INIT_SPAN(span, GL_BITMAP); 555 _swrast_span_default_attribs(ctx, &span); 556 span.arrayMask = SPAN_RGBA; 557 span.arrayAttribs = FRAG_BIT_COL0; /* we're fill in COL0 attrib values */ 558 559 if (ctx->Pixel.Convolution2DEnabled || ctx->Pixel.Separable2DEnabled) { 560 /* Convolution has to be handled specially. We'll create an 561 * intermediate image, applying all pixel transfer operations 562 * up to convolution. Then we'll convolve the image. Then 563 * we'll proceed with the rest of the transfer operations and 564 * rasterize the image. 565 */ 566 GLint row; 567 GLfloat *dest, *tmpImage; 568 569 tmpImage = (GLfloat *) _mesa_malloc(width * height * 4 * sizeof(GLfloat)); 570 if (!tmpImage) { 571 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels"); 572 return; 573 } 574 convImage = (GLfloat *) _mesa_malloc(width * height * 4 * sizeof(GLfloat)); 575 if (!convImage) { 576 _mesa_free(tmpImage); 577 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels"); 578 return; 579 } 580 581 /* Unpack the image and apply transfer ops up to convolution */ 582 dest = tmpImage; 583 for (row = 0; row < height; row++) { 584 const GLvoid *source = _mesa_image_address2d(unpack, 585 pixels, width, height, format, type, row, 0); 586 _mesa_unpack_color_span_float(ctx, width, GL_RGBA, (GLfloat *) dest, 587 format, type, source, unpack, 588 transferOps & IMAGE_PRE_CONVOLUTION_BITS); 589 dest += width * 4; 590 } 591 592 /* do convolution */ 593 if (ctx->Pixel.Convolution2DEnabled) { 594 _mesa_convolve_2d_image(ctx, &width, &height, tmpImage, convImage); 595 } 596 else { 597 ASSERT(ctx->Pixel.Separable2DEnabled); 598 _mesa_convolve_sep_image(ctx, &width, &height, tmpImage, convImage); 599 } 600 _mesa_free(tmpImage); 601 602 /* continue transfer ops and draw the convolved image */ 603 unpack = &ctx->DefaultPacking; 604 pixels = convImage; 605 format = GL_RGBA; 606 type = GL_FLOAT; 607 transferOps &= IMAGE_POST_CONVOLUTION_BITS; 608 } 609 else if (ctx->Pixel.Convolution1DEnabled) { 610 /* we only want to apply 1D convolution to glTexImage1D */ 611 transferOps &= ~(IMAGE_CONVOLUTION_BIT | 612 IMAGE_POST_CONVOLUTION_SCALE_BIAS); 613 } 614 615 if (ctx->DrawBuffer->_NumColorDrawBuffers > 0 && 616 ctx->DrawBuffer->_ColorDrawBuffers[0]->DataType != GL_FLOAT && 617 ctx->Color.ClampFragmentColor != GL_FALSE) { 618 /* need to clamp colors before applying fragment ops */ 619 transferOps |= IMAGE_CLAMP_BIT; 620 } 621 622 /* 623 * General solution 624 */ 625 { 626 const GLboolean sink = (ctx->Pixel.MinMaxEnabled && ctx->MinMax.Sink) 627 || (ctx->Pixel.HistogramEnabled && ctx->Histogram.Sink); 628 const GLbitfield interpMask = span.interpMask; 629 const GLbitfield arrayMask = span.arrayMask; 630 const GLint srcStride 631 = _mesa_image_row_stride(unpack, width, format, type); 632 GLint skipPixels = 0; 633 /* use span array for temp color storage */ 634 GLfloat *rgba = (GLfloat *) span.array->attribs[FRAG_ATTRIB_COL0]; 635 636 /* if the span is wider than MAX_WIDTH we have to do it in chunks */ 637 while (skipPixels < width) { 638 const GLint spanWidth = MIN2(width - skipPixels, MAX_WIDTH); 639 const GLubyte *source 640 = (const GLubyte *) _mesa_image_address2d(unpack, pixels, 641 width, height, format, 642 type, 0, skipPixels); 643 GLint row; 644 645 for (row = 0; row < height; row++) { 646 /* get image row as float/RGBA */ 647 _mesa_unpack_color_span_float(ctx, spanWidth, GL_RGBA, rgba, 648 format, type, source, unpack, 649 transferOps); 650 /* draw the span */ 651 if (!sink) { 652 /* Set these for each row since the _swrast_write_* functions 653 * may change them while clipping/rendering. 654 */ 655 span.array->ChanType = GL_FLOAT; 656 span.x = x + skipPixels; 657 span.y = y + row; 658 span.end = spanWidth; 659 span.arrayMask = arrayMask; 660 span.interpMask = interpMask; 661 if (zoom) { 662 _swrast_write_zoomed_rgba_span(ctx, imgX, imgY, &span, rgba); 663 } 664 else { 665 _swrast_write_rgba_span(ctx, &span); 666 } 667 } 668 669 source += srcStride; 670 } /* for row */ 671 672 skipPixels += spanWidth; 673 } /* while skipPixels < width */ 674 675 /* XXX this is ugly/temporary, to undo above change */ 676 span.array->ChanType = CHAN_TYPE; 677 } 678 679 if (convImage) { 680 _mesa_free(convImage); 681 } 682} 683 684 685/** 686 * This is a bit different from drawing GL_DEPTH_COMPONENT pixels. 687 * The only per-pixel operations that apply are depth scale/bias, 688 * stencil offset/shift, GL_DEPTH_WRITEMASK and GL_STENCIL_WRITEMASK, 689 * and pixel zoom. 690 * Also, only the depth buffer and stencil buffers are touched, not the 691 * color buffer(s). 692 */ 693static void 694draw_depth_stencil_pixels(GLcontext *ctx, GLint x, GLint y, 695 GLsizei width, GLsizei height, GLenum type, 696 const struct gl_pixelstore_attrib *unpack, 697 const GLvoid *pixels) 698{ 699 const GLint imgX = x, imgY = y; 700 const GLboolean scaleOrBias 701 = ctx->Pixel.DepthScale != 1.0 || ctx->Pixel.DepthBias != 0.0; 702 const GLuint depthMax = ctx->DrawBuffer->_DepthMax; 703 const GLuint stencilMask = ctx->Stencil.WriteMask[0]; 704 const GLuint stencilType = (STENCIL_BITS == 8) ? 705 GL_UNSIGNED_BYTE : GL_UNSIGNED_SHORT; 706 const GLboolean zoom = ctx->Pixel.ZoomX != 1.0 || ctx->Pixel.ZoomY != 1.0; 707 struct gl_renderbuffer *depthRb, *stencilRb; 708 struct gl_pixelstore_attrib clippedUnpack = *unpack; 709 710 if (!zoom) { 711 if (!_mesa_clip_drawpixels(ctx, &x, &y, &width, &height, 712 &clippedUnpack)) { 713 /* totally clipped */ 714 return; 715 } 716 } 717 718 depthRb = ctx->ReadBuffer->Attachment[BUFFER_DEPTH].Renderbuffer; 719 stencilRb = ctx->ReadBuffer->Attachment[BUFFER_STENCIL].Renderbuffer; 720 ASSERT(depthRb); 721 ASSERT(stencilRb); 722 723 if (depthRb->_BaseFormat == GL_DEPTH_STENCIL_EXT && 724 stencilRb->_BaseFormat == GL_DEPTH_STENCIL_EXT && 725 depthRb == stencilRb && 726 !scaleOrBias && 727 !zoom && 728 ctx->Depth.Mask && 729 (stencilMask & 0xff) == 0xff) { 730 /* This is the ideal case. 731 * Drawing GL_DEPTH_STENCIL pixels into a combined depth/stencil buffer. 732 * Plus, no pixel transfer ops, zooming, or masking needed. 733 */ 734 GLint i; 735 for (i = 0; i < height; i++) { 736 const GLuint *src = (const GLuint *) 737 _mesa_image_address2d(&clippedUnpack, pixels, width, height, 738 GL_DEPTH_STENCIL_EXT, type, i, 0); 739 depthRb->PutRow(ctx, depthRb, width, x, y + i, src, NULL); 740 } 741 } 742 else { 743 /* sub-optimal cases: 744 * Separate depth/stencil buffers, or pixel transfer ops required. 745 */ 746 /* XXX need to handle very wide images (skippixels) */ 747 GLint i; 748 749 depthRb = ctx->DrawBuffer->_DepthBuffer; 750 stencilRb = ctx->DrawBuffer->_StencilBuffer; 751 752 for (i = 0; i < height; i++) { 753 const GLuint *depthStencilSrc = (const GLuint *) 754 _mesa_image_address2d(&clippedUnpack, pixels, width, height, 755 GL_DEPTH_STENCIL_EXT, type, i, 0); 756 757 if (ctx->Depth.Mask) { 758 if (!scaleOrBias && ctx->DrawBuffer->Visual.depthBits == 24) { 759 /* fast path 24-bit zbuffer */ 760 GLuint zValues[MAX_WIDTH]; 761 GLint j; 762 ASSERT(depthRb->DataType == GL_UNSIGNED_INT); 763 for (j = 0; j < width; j++) { 764 zValues[j] = depthStencilSrc[j] >> 8; 765 } 766 if (zoom) 767 _swrast_write_zoomed_z_span(ctx, imgX, imgY, width, 768 x, y + i, zValues); 769 else 770 depthRb->PutRow(ctx, depthRb, width, x, y + i, zValues,NULL); 771 } 772 else if (!scaleOrBias && ctx->DrawBuffer->Visual.depthBits == 16) { 773 /* fast path 16-bit zbuffer */ 774 GLushort zValues[MAX_WIDTH]; 775 GLint j; 776 ASSERT(depthRb->DataType == GL_UNSIGNED_SHORT); 777 for (j = 0; j < width; j++) { 778 zValues[j] = depthStencilSrc[j] >> 16; 779 } 780 if (zoom) 781 _swrast_write_zoomed_z_span(ctx, imgX, imgY, width, 782 x, y + i, zValues); 783 else 784 depthRb->PutRow(ctx, depthRb, width, x, y + i, zValues,NULL); 785 } 786 else { 787 /* general case */ 788 GLuint zValues[MAX_WIDTH]; /* 16 or 32-bit Z value storage */ 789 _mesa_unpack_depth_span(ctx, width, 790 depthRb->DataType, zValues, depthMax, 791 type, depthStencilSrc, &clippedUnpack); 792 if (zoom) { 793 _swrast_write_zoomed_z_span(ctx, imgX, imgY, width, x, 794 y + i, zValues); 795 } 796 else { 797 depthRb->PutRow(ctx, depthRb, width, x, y + i, zValues,NULL); 798 } 799 } 800 } 801 802 if (stencilMask != 0x0) { 803 GLstencil stencilValues[MAX_WIDTH]; 804 /* get stencil values, with shift/offset/mapping */ 805 _mesa_unpack_stencil_span(ctx, width, stencilType, stencilValues, 806 type, depthStencilSrc, &clippedUnpack, 807 ctx->_ImageTransferState); 808 if (zoom) 809 _swrast_write_zoomed_stencil_span(ctx, imgX, imgY, width, 810 x, y + i, stencilValues); 811 else 812 _swrast_write_stencil_span(ctx, width, x, y + i, stencilValues); 813 } 814 } 815 } 816} 817 818 819/** 820 * Execute software-based glDrawPixels. 821 * By time we get here, all error checking will have been done. 822 */ 823void 824_swrast_DrawPixels( GLcontext *ctx, 825 GLint x, GLint y, 826 GLsizei width, GLsizei height, 827 GLenum format, GLenum type, 828 const struct gl_pixelstore_attrib *unpack, 829 const GLvoid *pixels ) 830{ 831 SWcontext *swrast = SWRAST_CONTEXT(ctx); 832 833 RENDER_START(swrast,ctx); 834 835 if (ctx->NewState) 836 _mesa_update_state(ctx); 837 838 if (swrast->NewState) 839 _swrast_validate_derived( ctx ); 840 841 pixels = _mesa_map_drawpix_pbo(ctx, unpack, pixels); 842 if (!pixels) { 843 RENDER_FINISH(swrast,ctx); 844 return; 845 } 846 847 switch (format) { 848 case GL_STENCIL_INDEX: 849 draw_stencil_pixels( ctx, x, y, width, height, type, unpack, pixels ); 850 break; 851 case GL_DEPTH_COMPONENT: 852 draw_depth_pixels( ctx, x, y, width, height, type, unpack, pixels ); 853 break; 854 case GL_COLOR_INDEX: 855 if (ctx->Visual.rgbMode) 856 draw_rgba_pixels(ctx, x,y, width, height, format, type, unpack, pixels); 857 else 858 draw_index_pixels(ctx, x, y, width, height, type, unpack, pixels); 859 break; 860 case GL_RED: 861 case GL_GREEN: 862 case GL_BLUE: 863 case GL_ALPHA: 864 case GL_LUMINANCE: 865 case GL_LUMINANCE_ALPHA: 866 case GL_RGB: 867 case GL_BGR: 868 case GL_RGBA: 869 case GL_BGRA: 870 case GL_ABGR_EXT: 871 draw_rgba_pixels(ctx, x, y, width, height, format, type, unpack, pixels); 872 break; 873 case GL_DEPTH_STENCIL_EXT: 874 draw_depth_stencil_pixels(ctx, x, y, width, height, 875 type, unpack, pixels); 876 break; 877 default: 878 _mesa_problem(ctx, "unexpected format in _swrast_DrawPixels"); 879 /* don't return yet, clean-up */ 880 } 881 882 RENDER_FINISH(swrast,ctx); 883 884 _mesa_unmap_drapix_pbo(ctx, unpack); 885} 886 887 888 889#if 0 /* experimental */ 890/* 891 * Execute glDrawDepthPixelsMESA(). 892 */ 893void 894_swrast_DrawDepthPixelsMESA( GLcontext *ctx, 895 GLint x, GLint y, 896 GLsizei width, GLsizei height, 897 GLenum colorFormat, GLenum colorType, 898 const GLvoid *colors, 899 GLenum depthType, const GLvoid *depths, 900 const struct gl_pixelstore_attrib *unpack ) 901{ 902 SWcontext *swrast = SWRAST_CONTEXT(ctx); 903 904 if (swrast->NewState) 905 _swrast_validate_derived( ctx ); 906 907 RENDER_START(swrast,ctx); 908 909 switch (colorFormat) { 910 case GL_COLOR_INDEX: 911 if (ctx->Visual.rgbMode) 912 draw_rgba_pixels(ctx, x,y, width, height, colorFormat, colorType, 913 unpack, colors); 914 else 915 draw_index_pixels(ctx, x, y, width, height, colorType, 916 unpack, colors); 917 break; 918 case GL_RED: 919 case GL_GREEN: 920 case GL_BLUE: 921 case GL_ALPHA: 922 case GL_LUMINANCE: 923 case GL_LUMINANCE_ALPHA: 924 case GL_RGB: 925 case GL_BGR: 926 case GL_RGBA: 927 case GL_BGRA: 928 case GL_ABGR_EXT: 929 draw_rgba_pixels(ctx, x, y, width, height, colorFormat, colorType, 930 unpack, colors); 931 break; 932 default: 933 _mesa_problem(ctx, "unexpected format in glDrawDepthPixelsMESA"); 934 } 935 936 RENDER_FINISH(swrast,ctx); 937} 938#endif 939