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