1 /* 2 * Mesa 3-D graphics library 3 * 4 * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the "Software"), 8 * to deal in the Software without restriction, including without limitation 9 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 * and/or sell copies of the Software, and to permit persons to whom the 11 * Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included 14 * in all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 * OTHER DEALINGS IN THE SOFTWARE. 23 */ 24 25 26 #include "main/glheader.h" 27 #include "main/bufferobj.h" 28 #include "main/colormac.h" 29 #include "main/condrender.h" 30 #include "main/context.h" 31 #include "main/format_pack.h" 32 #include "main/format_utils.h" 33 #include "main/glformats.h" 34 #include "main/image.h" 35 #include "main/imports.h" 36 #include "main/macros.h" 37 #include "main/pack.h" 38 #include "main/pbo.h" 39 #include "main/pixeltransfer.h" 40 #include "main/state.h" 41 42 #include "s_context.h" 43 #include "s_span.h" 44 #include "s_stencil.h" 45 #include "s_zoom.h" 46 47 48 /** 49 * Handle a common case of drawing GL_RGB/GL_UNSIGNED_BYTE into a 50 * MESA_FORMAT_XRGB888 or MESA_FORMAT_ARGB888 renderbuffer. 51 */ 52 static void 53 fast_draw_rgb_ubyte_pixels(struct gl_context *ctx, 54 struct gl_renderbuffer *rb, 55 GLint x, GLint y, 56 GLsizei width, GLsizei height, 57 const struct gl_pixelstore_attrib *unpack, 58 const GLvoid *pixels) 59 { 60 const GLubyte *src = (const GLubyte *) 61 _mesa_image_address2d(unpack, pixels, width, 62 height, GL_RGB, GL_UNSIGNED_BYTE, 0, 0); 63 const GLint srcRowStride = _mesa_image_row_stride(unpack, width, 64 GL_RGB, GL_UNSIGNED_BYTE); 65 GLint i, j; 66 GLubyte *dst; 67 GLint dstRowStride; 68 69 ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, 70 GL_MAP_WRITE_BIT, &dst, &dstRowStride); 71 72 if (!dst) { 73 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels"); 74 return; 75 } 76 77 if (ctx->Pixel.ZoomY == -1.0f) { 78 dst = dst + (height - 1) * dstRowStride; 79 dstRowStride = -dstRowStride; 80 } 81 82 for (i = 0; i < height; i++) { 83 GLuint *dst4 = (GLuint *) dst; 84 for (j = 0; j < width; j++) { 85 dst4[j] = PACK_COLOR_8888(0xff, src[j*3+0], src[j*3+1], src[j*3+2]); 86 } 87 dst += dstRowStride; 88 src += srcRowStride; 89 } 90 91 ctx->Driver.UnmapRenderbuffer(ctx, rb); 92 } 93 94 95 /** 96 * Handle a common case of drawing GL_RGBA/GL_UNSIGNED_BYTE into a 97 * MESA_FORMAT_ARGB888 or MESA_FORMAT_xRGB888 renderbuffer. 98 */ 99 static void 100 fast_draw_rgba_ubyte_pixels(struct gl_context *ctx, 101 struct gl_renderbuffer *rb, 102 GLint x, GLint y, 103 GLsizei width, GLsizei height, 104 const struct gl_pixelstore_attrib *unpack, 105 const GLvoid *pixels) 106 { 107 const GLubyte *src = (const GLubyte *) 108 _mesa_image_address2d(unpack, pixels, width, 109 height, GL_RGBA, GL_UNSIGNED_BYTE, 0, 0); 110 const GLint srcRowStride = 111 _mesa_image_row_stride(unpack, width, GL_RGBA, GL_UNSIGNED_BYTE); 112 GLint i, j; 113 GLubyte *dst; 114 GLint dstRowStride; 115 116 ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, 117 GL_MAP_WRITE_BIT, &dst, &dstRowStride); 118 119 if (!dst) { 120 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels"); 121 return; 122 } 123 124 if (ctx->Pixel.ZoomY == -1.0f) { 125 dst = dst + (height - 1) * dstRowStride; 126 dstRowStride = -dstRowStride; 127 } 128 129 for (i = 0; i < height; i++) { 130 GLuint *dst4 = (GLuint *) dst; 131 for (j = 0; j < width; j++) { 132 dst4[j] = PACK_COLOR_8888(src[j*4+3], src[j*4+0], 133 src[j*4+1], src[j*4+2]); 134 } 135 dst += dstRowStride; 136 src += srcRowStride; 137 } 138 139 ctx->Driver.UnmapRenderbuffer(ctx, rb); 140 } 141 142 143 /** 144 * Handle a common case of drawing a format/type combination that 145 * exactly matches the renderbuffer format. 146 */ 147 static void 148 fast_draw_generic_pixels(struct gl_context *ctx, 149 struct gl_renderbuffer *rb, 150 GLint x, GLint y, 151 GLsizei width, GLsizei height, 152 GLenum format, GLenum type, 153 const struct gl_pixelstore_attrib *unpack, 154 const GLvoid *pixels) 155 { 156 const GLubyte *src = (const GLubyte *) 157 _mesa_image_address2d(unpack, pixels, width, 158 height, format, type, 0, 0); 159 const GLint srcRowStride = 160 _mesa_image_row_stride(unpack, width, format, type); 161 const GLint rowLength = width * _mesa_get_format_bytes(rb->Format); 162 GLint i; 163 GLubyte *dst; 164 GLint dstRowStride; 165 166 ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, 167 GL_MAP_WRITE_BIT, &dst, &dstRowStride); 168 169 if (!dst) { 170 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels"); 171 return; 172 } 173 174 if (ctx->Pixel.ZoomY == -1.0f) { 175 dst = dst + (height - 1) * dstRowStride; 176 dstRowStride = -dstRowStride; 177 } 178 179 for (i = 0; i < height; i++) { 180 memcpy(dst, src, rowLength); 181 dst += dstRowStride; 182 src += srcRowStride; 183 } 184 185 ctx->Driver.UnmapRenderbuffer(ctx, rb); 186 } 187 188 189 /** 190 * Try to do a fast and simple RGB(a) glDrawPixels. 191 * Return: GL_TRUE if success, GL_FALSE if slow path must be used instead 192 */ 193 static GLboolean 194 fast_draw_rgba_pixels(struct gl_context *ctx, GLint x, GLint y, 195 GLsizei width, GLsizei height, 196 GLenum format, GLenum type, 197 const struct gl_pixelstore_attrib *userUnpack, 198 const GLvoid *pixels) 199 { 200 struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[0]; 201 SWcontext *swrast = SWRAST_CONTEXT(ctx); 202 struct gl_pixelstore_attrib unpack; 203 204 if (!rb) 205 return GL_TRUE; /* no-op */ 206 207 if (ctx->DrawBuffer->_NumColorDrawBuffers > 1 || 208 (swrast->_RasterMask & ~CLIP_BIT) || 209 ctx->Texture._EnabledCoordUnits || 210 userUnpack->SwapBytes || 211 ctx->Pixel.ZoomX != 1.0f || 212 fabsf(ctx->Pixel.ZoomY) != 1.0f || 213 ctx->_ImageTransferState) { 214 /* can't handle any of those conditions */ 215 return GL_FALSE; 216 } 217 218 unpack = *userUnpack; 219 220 /* clipping */ 221 if (!_mesa_clip_drawpixels(ctx, &x, &y, &width, &height, &unpack)) { 222 /* image was completely clipped: no-op, all done */ 223 return GL_TRUE; 224 } 225 226 if (format == GL_RGB && 227 type == GL_UNSIGNED_BYTE && 228 (rb->Format == MESA_FORMAT_B8G8R8X8_UNORM || 229 rb->Format == MESA_FORMAT_B8G8R8A8_UNORM)) { 230 fast_draw_rgb_ubyte_pixels(ctx, rb, x, y, width, height, 231 &unpack, pixels); 232 return GL_TRUE; 233 } 234 235 if (format == GL_RGBA && 236 type == GL_UNSIGNED_BYTE && 237 (rb->Format == MESA_FORMAT_B8G8R8X8_UNORM || 238 rb->Format == MESA_FORMAT_B8G8R8A8_UNORM)) { 239 fast_draw_rgba_ubyte_pixels(ctx, rb, x, y, width, height, 240 &unpack, pixels); 241 return GL_TRUE; 242 } 243 244 if (_mesa_format_matches_format_and_type(rb->Format, format, type, 245 ctx->Unpack.SwapBytes, NULL)) { 246 fast_draw_generic_pixels(ctx, rb, x, y, width, height, 247 format, type, &unpack, pixels); 248 return GL_TRUE; 249 } 250 251 /* can't handle this pixel format and/or data type */ 252 return GL_FALSE; 253 } 254 255 256 257 /* 258 * Draw stencil image. 259 */ 260 static void 261 draw_stencil_pixels( struct gl_context *ctx, GLint x, GLint y, 262 GLsizei width, GLsizei height, 263 GLenum type, 264 const struct gl_pixelstore_attrib *unpack, 265 const GLvoid *pixels ) 266 { 267 const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F; 268 const GLenum destType = GL_UNSIGNED_BYTE; 269 GLint row; 270 GLubyte *values; 271 272 values = malloc(width * sizeof(GLubyte)); 273 if (!values) { 274 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels"); 275 return; 276 } 277 278 for (row = 0; row < height; row++) { 279 const GLvoid *source = _mesa_image_address2d(unpack, pixels, 280 width, height, 281 GL_STENCIL_INDEX, type, 282 row, 0); 283 _mesa_unpack_stencil_span(ctx, width, destType, values, 284 type, source, unpack, 285 ctx->_ImageTransferState); 286 if (zoom) { 287 _swrast_write_zoomed_stencil_span(ctx, x, y, width, 288 x, y, values); 289 } 290 else { 291 _swrast_write_stencil_span(ctx, width, x, y, values); 292 } 293 294 y++; 295 } 296 297 free(values); 298 } 299 300 301 /* 302 * Draw depth image. 303 */ 304 static void 305 draw_depth_pixels( struct gl_context *ctx, GLint x, GLint y, 306 GLsizei width, GLsizei height, 307 GLenum type, 308 const struct gl_pixelstore_attrib *unpack, 309 const GLvoid *pixels ) 310 { 311 const GLboolean scaleOrBias 312 = ctx->Pixel.DepthScale != 1.0f || ctx->Pixel.DepthBias != 0.0f; 313 const GLboolean zoom = ctx->Pixel.ZoomX != 1.0f || ctx->Pixel.ZoomY != 1.0f; 314 SWspan span; 315 316 INIT_SPAN(span, GL_BITMAP); 317 span.arrayMask = SPAN_Z; 318 _swrast_span_default_attribs(ctx, &span); 319 320 if (type == GL_UNSIGNED_SHORT 321 && ctx->DrawBuffer->Visual.depthBits == 16 322 && !scaleOrBias 323 && !zoom 324 && width <= SWRAST_MAX_WIDTH 325 && !unpack->SwapBytes) { 326 /* Special case: directly write 16-bit depth values */ 327 GLint row; 328 for (row = 0; row < height; row++) { 329 const GLushort *zSrc = (const GLushort *) 330 _mesa_image_address2d(unpack, pixels, width, height, 331 GL_DEPTH_COMPONENT, type, row, 0); 332 GLint i; 333 for (i = 0; i < width; i++) 334 span.array->z[i] = zSrc[i]; 335 span.x = x; 336 span.y = y + row; 337 span.end = width; 338 _swrast_write_rgba_span(ctx, &span); 339 } 340 } 341 else if (type == GL_UNSIGNED_INT 342 && !scaleOrBias 343 && !zoom 344 && width <= SWRAST_MAX_WIDTH 345 && !unpack->SwapBytes) { 346 /* Special case: shift 32-bit values down to Visual.depthBits */ 347 const GLint shift = 32 - ctx->DrawBuffer->Visual.depthBits; 348 GLint row; 349 for (row = 0; row < height; row++) { 350 const GLuint *zSrc = (const GLuint *) 351 _mesa_image_address2d(unpack, pixels, width, height, 352 GL_DEPTH_COMPONENT, type, row, 0); 353 if (shift == 0) { 354 memcpy(span.array->z, zSrc, width * sizeof(GLuint)); 355 } 356 else { 357 GLint col; 358 for (col = 0; col < width; col++) 359 span.array->z[col] = zSrc[col] >> shift; 360 } 361 span.x = x; 362 span.y = y + row; 363 span.end = width; 364 _swrast_write_rgba_span(ctx, &span); 365 } 366 } 367 else { 368 /* General case */ 369 const GLuint depthMax = ctx->DrawBuffer->_DepthMax; 370 GLint skipPixels = 0; 371 372 /* in case width > SWRAST_MAX_WIDTH do the copy in chunks */ 373 while (skipPixels < width) { 374 const GLint spanWidth = MIN2(width - skipPixels, SWRAST_MAX_WIDTH); 375 GLint row; 376 assert(span.end <= SWRAST_MAX_WIDTH); 377 for (row = 0; row < height; row++) { 378 const GLvoid *zSrc = _mesa_image_address2d(unpack, 379 pixels, width, height, 380 GL_DEPTH_COMPONENT, type, 381 row, skipPixels); 382 383 /* Set these for each row since the _swrast_write_* function may 384 * change them while clipping. 385 */ 386 span.x = x + skipPixels; 387 span.y = y + row; 388 span.end = spanWidth; 389 390 _mesa_unpack_depth_span(ctx, spanWidth, 391 GL_UNSIGNED_INT, span.array->z, depthMax, 392 type, zSrc, unpack); 393 if (zoom) { 394 _swrast_write_zoomed_depth_span(ctx, x, y, &span); 395 } 396 else { 397 _swrast_write_rgba_span(ctx, &span); 398 } 399 } 400 skipPixels += spanWidth; 401 } 402 } 403 } 404 405 406 407 /** 408 * Draw RGBA image. 409 */ 410 static void 411 draw_rgba_pixels( struct gl_context *ctx, GLint x, GLint y, 412 GLsizei width, GLsizei height, 413 GLenum format, GLenum type, 414 const struct gl_pixelstore_attrib *unpack, 415 const GLvoid *pixels ) 416 { 417 const GLint imgX = x, imgY = y; 418 const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F; 419 GLbitfield transferOps = ctx->_ImageTransferState; 420 SWspan span; 421 422 /* Try an optimized glDrawPixels first */ 423 if (fast_draw_rgba_pixels(ctx, x, y, width, height, format, type, 424 unpack, pixels)) { 425 return; 426 } 427 428 swrast_render_start(ctx); 429 430 INIT_SPAN(span, GL_BITMAP); 431 _swrast_span_default_attribs(ctx, &span); 432 span.arrayMask = SPAN_RGBA; 433 span.arrayAttribs = VARYING_BIT_COL0; /* we're fill in COL0 attrib values */ 434 435 if (ctx->DrawBuffer->_NumColorDrawBuffers > 0) { 436 GLenum datatype = _mesa_get_format_datatype( 437 ctx->DrawBuffer->_ColorDrawBuffers[0]->Format); 438 if (datatype != GL_FLOAT && 439 ctx->Color.ClampFragmentColor != GL_FALSE) { 440 /* need to clamp colors before applying fragment ops */ 441 transferOps |= IMAGE_CLAMP_BIT; 442 } 443 } 444 445 /* 446 * General solution 447 */ 448 { 449 const GLbitfield interpMask = span.interpMask; 450 const GLbitfield arrayMask = span.arrayMask; 451 GLint skipPixels = 0; 452 /* use span array for temp color storage */ 453 GLfloat *rgba = (GLfloat *) span.array->attribs[VARYING_SLOT_COL0]; 454 void *tempImage = NULL; 455 456 /* We have to deal with GL_COLOR_INDEX manually because 457 * _mesa_format_convert does not handle this format. So what we do here is 458 * convert it to RGBA ubyte first and then convert from that to dst as 459 * usual. 460 */ 461 if (format == GL_COLOR_INDEX) { 462 /* This will handle byte swapping and transferops if needed */ 463 tempImage = 464 _mesa_unpack_color_index_to_rgba_ubyte(ctx, 2, 465 pixels, format, type, 466 width, height, 1, 467 unpack, 468 transferOps); 469 if (!tempImage) { 470 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels"); 471 return; 472 } 473 474 transferOps = 0; 475 pixels = tempImage; 476 format = GL_RGBA; 477 type = GL_UNSIGNED_BYTE; 478 } else if (unpack->SwapBytes) { 479 /* We have to handle byte-swapping scenarios before calling 480 * _mesa_format_convert 481 */ 482 GLint swapSize = _mesa_sizeof_packed_type(type); 483 if (swapSize == 2 || swapSize == 4) { 484 int imageStride = _mesa_image_image_stride(unpack, width, height, format, type); 485 486 tempImage = malloc(imageStride); 487 if (!tempImage) { 488 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels"); 489 return; 490 } 491 492 _mesa_swap_bytes_2d_image(format, type, unpack, 493 width, height, tempImage, pixels); 494 495 pixels = tempImage; 496 } 497 } 498 499 const GLint srcStride 500 = _mesa_image_row_stride(unpack, width, format, type); 501 502 /* if the span is wider than SWRAST_MAX_WIDTH we have to do it in chunks */ 503 while (skipPixels < width) { 504 const GLint spanWidth = MIN2(width - skipPixels, SWRAST_MAX_WIDTH); 505 const GLubyte *source 506 = (const GLubyte *) _mesa_image_address2d(unpack, pixels, 507 width, height, format, 508 type, 0, skipPixels); 509 GLint row; 510 511 /* get image row as float/RGBA */ 512 uint32_t srcMesaFormat = _mesa_format_from_format_and_type(format, type); 513 for (row = 0; row < height; row++) { 514 int dstRowStride = 4 * width * sizeof(float); 515 _mesa_format_convert(rgba, RGBA32_FLOAT, dstRowStride, 516 (void*)source, srcMesaFormat, srcStride, 517 spanWidth, 1, NULL); 518 if (transferOps) 519 _mesa_apply_rgba_transfer_ops(ctx, transferOps, spanWidth, (GLfloat (*)[4])rgba); 520 /* Set these for each row since the _swrast_write_* functions 521 * may change them while clipping/rendering. 522 */ 523 span.array->ChanType = GL_FLOAT; 524 span.x = x + skipPixels; 525 span.y = y + row; 526 span.end = spanWidth; 527 span.arrayMask = arrayMask; 528 span.interpMask = interpMask; 529 if (zoom) { 530 _swrast_write_zoomed_rgba_span(ctx, imgX, imgY, &span, rgba); 531 } 532 else { 533 _swrast_write_rgba_span(ctx, &span); 534 } 535 536 source += srcStride; 537 } /* for row */ 538 539 skipPixels += spanWidth; 540 } /* while skipPixels < width */ 541 542 /* XXX this is ugly/temporary, to undo above change */ 543 span.array->ChanType = CHAN_TYPE; 544 545 free(tempImage); 546 } 547 548 swrast_render_finish(ctx); 549 } 550 551 552 /** 553 * Draw depth+stencil values into a MESA_FORAMT_Z24_S8 or MESA_FORMAT_Z24_UNORM_S8_UINT 554 * renderbuffer. No masking, zooming, scaling, etc. 555 */ 556 static void 557 fast_draw_depth_stencil(struct gl_context *ctx, GLint x, GLint y, 558 GLsizei width, GLsizei height, 559 const struct gl_pixelstore_attrib *unpack, 560 const GLvoid *pixels) 561 { 562 const GLenum format = GL_DEPTH_STENCIL_EXT; 563 const GLenum type = GL_UNSIGNED_INT_24_8; 564 struct gl_renderbuffer *rb = 565 ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer; 566 struct swrast_renderbuffer *srb = swrast_renderbuffer(rb); 567 GLubyte *src, *dst; 568 GLint srcRowStride, dstRowStride; 569 GLint i; 570 571 src = _mesa_image_address2d(unpack, pixels, width, height, 572 format, type, 0, 0); 573 srcRowStride = _mesa_image_row_stride(unpack, width, format, type); 574 575 dst = _swrast_pixel_address(rb, x, y); 576 dstRowStride = srb->RowStride; 577 578 for (i = 0; i < height; i++) { 579 _mesa_pack_uint_24_8_depth_stencil_row(rb->Format, width, 580 (const GLuint *) src, dst); 581 dst += dstRowStride; 582 src += srcRowStride; 583 } 584 } 585 586 587 588 /** 589 * This is a bit different from drawing GL_DEPTH_COMPONENT pixels. 590 * The only per-pixel operations that apply are depth scale/bias, 591 * stencil offset/shift, GL_DEPTH_WRITEMASK and GL_STENCIL_WRITEMASK, 592 * and pixel zoom. 593 * Also, only the depth buffer and stencil buffers are touched, not the 594 * color buffer(s). 595 */ 596 static void 597 draw_depth_stencil_pixels(struct gl_context *ctx, GLint x, GLint y, 598 GLsizei width, GLsizei height, GLenum type, 599 const struct gl_pixelstore_attrib *unpack, 600 const GLvoid *pixels) 601 { 602 const GLint imgX = x, imgY = y; 603 const GLboolean scaleOrBias 604 = ctx->Pixel.DepthScale != 1.0F || ctx->Pixel.DepthBias != 0.0F; 605 const GLuint stencilMask = ctx->Stencil.WriteMask[0]; 606 const GLenum stencilType = GL_UNSIGNED_BYTE; 607 const GLboolean zoom = ctx->Pixel.ZoomX != 1.0F || ctx->Pixel.ZoomY != 1.0F; 608 struct gl_renderbuffer *depthRb, *stencilRb; 609 struct gl_pixelstore_attrib clippedUnpack = *unpack; 610 611 if (!zoom) { 612 if (!_mesa_clip_drawpixels(ctx, &x, &y, &width, &height, 613 &clippedUnpack)) { 614 /* totally clipped */ 615 return; 616 } 617 } 618 619 depthRb = ctx->ReadBuffer->Attachment[BUFFER_DEPTH].Renderbuffer; 620 stencilRb = ctx->ReadBuffer->Attachment[BUFFER_STENCIL].Renderbuffer; 621 assert(depthRb); 622 assert(stencilRb); 623 624 if (depthRb == stencilRb && 625 (depthRb->Format == MESA_FORMAT_S8_UINT_Z24_UNORM || 626 depthRb->Format == MESA_FORMAT_Z24_UNORM_S8_UINT) && 627 type == GL_UNSIGNED_INT_24_8 && 628 !scaleOrBias && 629 !zoom && 630 ctx->Depth.Mask && 631 (stencilMask & 0xff) == 0xff) { 632 fast_draw_depth_stencil(ctx, x, y, width, height, 633 &clippedUnpack, pixels); 634 } 635 else { 636 /* sub-optimal cases: 637 * Separate depth/stencil buffers, or pixel transfer ops required. 638 */ 639 /* XXX need to handle very wide images (skippixels) */ 640 GLuint *zValues; /* 32-bit Z values */ 641 GLint i; 642 643 zValues = malloc(width * sizeof(GLuint)); 644 if (!zValues) { 645 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels"); 646 return; 647 } 648 649 for (i = 0; i < height; i++) { 650 const GLuint *depthStencilSrc = (const GLuint *) 651 _mesa_image_address2d(&clippedUnpack, pixels, width, height, 652 GL_DEPTH_STENCIL_EXT, type, i, 0); 653 654 if (ctx->Depth.Mask) { 655 _mesa_unpack_depth_span(ctx, width, 656 GL_UNSIGNED_INT, /* dest type */ 657 zValues, /* dest addr */ 658 0xffffffff, /* depth max */ 659 type, /* src type */ 660 depthStencilSrc, /* src addr */ 661 &clippedUnpack); 662 if (zoom) { 663 _swrast_write_zoomed_z_span(ctx, imgX, imgY, width, x, 664 y + i, zValues); 665 } 666 else { 667 GLubyte *dst = _swrast_pixel_address(depthRb, x, y + i); 668 _mesa_pack_uint_z_row(depthRb->Format, width, zValues, dst); 669 } 670 } 671 672 if (stencilMask != 0x0) { 673 GLubyte *stencilValues = (GLubyte *) zValues; /* re-use buffer */ 674 /* get stencil values, with shift/offset/mapping */ 675 _mesa_unpack_stencil_span(ctx, width, stencilType, stencilValues, 676 type, depthStencilSrc, &clippedUnpack, 677 ctx->_ImageTransferState); 678 if (zoom) 679 _swrast_write_zoomed_stencil_span(ctx, imgX, imgY, width, 680 x, y + i, stencilValues); 681 else 682 _swrast_write_stencil_span(ctx, width, x, y + i, stencilValues); 683 } 684 } 685 686 free(zValues); 687 } 688 } 689 690 691 /** 692 * Execute software-based glDrawPixels. 693 * By time we get here, all error checking will have been done. 694 */ 695 void 696 _swrast_DrawPixels( struct gl_context *ctx, 697 GLint x, GLint y, 698 GLsizei width, GLsizei height, 699 GLenum format, GLenum type, 700 const struct gl_pixelstore_attrib *unpack, 701 const GLvoid *pixels ) 702 { 703 SWcontext *swrast = SWRAST_CONTEXT(ctx); 704 GLboolean save_vp_override = ctx->VertexProgram._Overriden; 705 706 if (!_mesa_check_conditional_render(ctx)) 707 return; /* don't draw */ 708 709 /* We are creating fragments directly, without going through vertex 710 * programs. 711 * 712 * This override flag tells the fragment processing code that its input 713 * comes from a non-standard source, and it may therefore not rely on 714 * optimizations that assume e.g. constant color if there is no color 715 * vertex array. 716 */ 717 _mesa_set_vp_override(ctx, GL_TRUE); 718 719 if (ctx->NewState) 720 _mesa_update_state(ctx); 721 722 if (swrast->NewState) 723 _swrast_validate_derived( ctx ); 724 725 pixels = _mesa_map_pbo_source(ctx, unpack, pixels); 726 if (!pixels) { 727 _mesa_set_vp_override(ctx, save_vp_override); 728 return; 729 } 730 731 /* 732 * By time we get here, all error checking should have been done. 733 */ 734 switch (format) { 735 case GL_STENCIL_INDEX: 736 swrast_render_start(ctx); 737 draw_stencil_pixels( ctx, x, y, width, height, type, unpack, pixels ); 738 swrast_render_finish(ctx); 739 break; 740 case GL_DEPTH_COMPONENT: 741 swrast_render_start(ctx); 742 draw_depth_pixels( ctx, x, y, width, height, type, unpack, pixels ); 743 swrast_render_finish(ctx); 744 break; 745 case GL_DEPTH_STENCIL_EXT: 746 swrast_render_start(ctx); 747 draw_depth_stencil_pixels(ctx, x, y, width, height, type, unpack, pixels); 748 swrast_render_finish(ctx); 749 break; 750 default: 751 /* all other formats should be color formats */ 752 draw_rgba_pixels(ctx, x, y, width, height, format, type, unpack, pixels); 753 } 754 755 _mesa_set_vp_override(ctx, save_vp_override); 756 757 _mesa_unmap_pbo_source(ctx, unpack); 758 } 759