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