1/* 2 * Mesa 3-D graphics library 3 * Version: 7.1 4 * 5 * Copyright (C) 1999-2008 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#include "glheader.h" 26#include "imports.h" 27#include "bufferobj.h" 28#include "context.h" 29#include "enums.h" 30#include "readpix.h" 31#include "framebuffer.h" 32#include "formats.h" 33#include "format_unpack.h" 34#include "image.h" 35#include "mtypes.h" 36#include "pack.h" 37#include "pbo.h" 38#include "state.h" 39#include "glformats.h" 40#include "fbobject.h" 41#include "teximage.h" 42 43/* Inexplicably, GL_HALF_FLOAT_OES has a different value than GL_HALF_FLOAT. 44 */ 45#ifndef GL_HALF_FLOAT_OES 46#define GL_HALF_FLOAT_OES 0x8D61 47#endif 48 49/** 50 * Tries to implement glReadPixels() of GL_DEPTH_COMPONENT using memcpy of the 51 * mapping. 52 */ 53static GLboolean 54fast_read_depth_pixels( struct gl_context *ctx, 55 GLint x, GLint y, 56 GLsizei width, GLsizei height, 57 GLenum type, GLvoid *pixels, 58 const struct gl_pixelstore_attrib *packing ) 59{ 60 struct gl_framebuffer *fb = ctx->ReadBuffer; 61 struct gl_renderbuffer *rb = fb->Attachment[BUFFER_DEPTH].Renderbuffer; 62 GLubyte *map, *dst; 63 int stride, dstStride, j; 64 65 if (ctx->Pixel.DepthScale != 1.0 || ctx->Pixel.DepthBias != 0.0) 66 return GL_FALSE; 67 68 if (packing->SwapBytes) 69 return GL_FALSE; 70 71 if (_mesa_get_format_datatype(rb->Format) != GL_UNSIGNED_NORMALIZED) 72 return GL_FALSE; 73 74 if (!((type == GL_UNSIGNED_SHORT && rb->Format == MESA_FORMAT_Z16) || 75 type == GL_UNSIGNED_INT)) 76 return GL_FALSE; 77 78 ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT, 79 &map, &stride); 80 81 if (!map) { 82 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels"); 83 return GL_TRUE; /* don't bother trying the slow path */ 84 } 85 86 dstStride = _mesa_image_row_stride(packing, width, GL_DEPTH_COMPONENT, type); 87 dst = (GLubyte *) _mesa_image_address2d(packing, pixels, width, height, 88 GL_DEPTH_COMPONENT, type, 0, 0); 89 90 for (j = 0; j < height; j++) { 91 if (type == GL_UNSIGNED_INT) { 92 _mesa_unpack_uint_z_row(rb->Format, width, map, (GLuint *)dst); 93 } else { 94 ASSERT(type == GL_UNSIGNED_SHORT && rb->Format == MESA_FORMAT_Z16); 95 memcpy(dst, map, width * 2); 96 } 97 98 map += stride; 99 dst += dstStride; 100 } 101 ctx->Driver.UnmapRenderbuffer(ctx, rb); 102 103 return GL_TRUE; 104} 105 106/** 107 * Read pixels for format=GL_DEPTH_COMPONENT. 108 */ 109static void 110read_depth_pixels( struct gl_context *ctx, 111 GLint x, GLint y, 112 GLsizei width, GLsizei height, 113 GLenum type, GLvoid *pixels, 114 const struct gl_pixelstore_attrib *packing ) 115{ 116 struct gl_framebuffer *fb = ctx->ReadBuffer; 117 struct gl_renderbuffer *rb = fb->Attachment[BUFFER_DEPTH].Renderbuffer; 118 GLint j; 119 GLubyte *dst, *map; 120 int dstStride, stride; 121 GLfloat *depthValues; 122 123 if (!rb) 124 return; 125 126 /* clipping should have been done already */ 127 ASSERT(x >= 0); 128 ASSERT(y >= 0); 129 ASSERT(x + width <= (GLint) rb->Width); 130 ASSERT(y + height <= (GLint) rb->Height); 131 132 if (fast_read_depth_pixels(ctx, x, y, width, height, type, pixels, packing)) 133 return; 134 135 dstStride = _mesa_image_row_stride(packing, width, GL_DEPTH_COMPONENT, type); 136 dst = (GLubyte *) _mesa_image_address2d(packing, pixels, width, height, 137 GL_DEPTH_COMPONENT, type, 0, 0); 138 139 ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT, 140 &map, &stride); 141 if (!map) { 142 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels"); 143 return; 144 } 145 146 depthValues = (GLfloat *) malloc(width * sizeof(GLfloat)); 147 148 if (depthValues) { 149 /* General case (slower) */ 150 for (j = 0; j < height; j++, y++) { 151 _mesa_unpack_float_z_row(rb->Format, width, map, depthValues); 152 _mesa_pack_depth_span(ctx, width, dst, type, depthValues, packing); 153 154 dst += dstStride; 155 map += stride; 156 } 157 } 158 else { 159 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels"); 160 } 161 162 free(depthValues); 163 164 ctx->Driver.UnmapRenderbuffer(ctx, rb); 165} 166 167 168/** 169 * Read pixels for format=GL_STENCIL_INDEX. 170 */ 171static void 172read_stencil_pixels( struct gl_context *ctx, 173 GLint x, GLint y, 174 GLsizei width, GLsizei height, 175 GLenum type, GLvoid *pixels, 176 const struct gl_pixelstore_attrib *packing ) 177{ 178 struct gl_framebuffer *fb = ctx->ReadBuffer; 179 struct gl_renderbuffer *rb = fb->Attachment[BUFFER_STENCIL].Renderbuffer; 180 GLint j; 181 GLubyte *map, *stencil; 182 GLint stride; 183 184 if (!rb) 185 return; 186 187 ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT, 188 &map, &stride); 189 if (!map) { 190 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels"); 191 return; 192 } 193 194 stencil = (GLubyte *) malloc(width * sizeof(GLubyte)); 195 196 if (stencil) { 197 /* process image row by row */ 198 for (j = 0; j < height; j++) { 199 GLvoid *dest; 200 201 _mesa_unpack_ubyte_stencil_row(rb->Format, width, map, stencil); 202 dest = _mesa_image_address2d(packing, pixels, width, height, 203 GL_STENCIL_INDEX, type, j, 0); 204 205 _mesa_pack_stencil_span(ctx, width, type, dest, stencil, packing); 206 207 map += stride; 208 } 209 } 210 else { 211 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels"); 212 } 213 214 free(stencil); 215 216 ctx->Driver.UnmapRenderbuffer(ctx, rb); 217} 218 219 220/** 221 * Try to do glReadPixels of RGBA data using a simple memcpy or swizzle. 222 * \return GL_TRUE if successful, GL_FALSE otherwise (use the slow path) 223 */ 224static GLboolean 225fast_read_rgba_pixels_memcpy( struct gl_context *ctx, 226 GLint x, GLint y, 227 GLsizei width, GLsizei height, 228 GLenum format, GLenum type, 229 GLvoid *pixels, 230 const struct gl_pixelstore_attrib *packing, 231 GLbitfield transferOps ) 232{ 233 struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorReadBuffer; 234 GLubyte *dst, *map; 235 int dstStride, stride, j, texelBytes; 236 GLboolean swizzle_rb = GL_FALSE, copy_xrgb = GL_FALSE; 237 238 /* XXX we could check for other swizzle/special cases here as needed */ 239 if (rb->Format == MESA_FORMAT_RGBA8888_REV && 240 format == GL_BGRA && 241 type == GL_UNSIGNED_INT_8_8_8_8_REV && 242 !ctx->Pack.SwapBytes) { 243 swizzle_rb = GL_TRUE; 244 } 245 else if (rb->Format == MESA_FORMAT_XRGB8888 && 246 format == GL_BGRA && 247 type == GL_UNSIGNED_INT_8_8_8_8_REV && 248 !ctx->Pack.SwapBytes) { 249 copy_xrgb = GL_TRUE; 250 } 251 else if (!_mesa_format_matches_format_and_type(rb->Format, format, type, 252 ctx->Pack.SwapBytes)) 253 return GL_FALSE; 254 255 /* If the format is unsigned normalized then we can ignore clamping 256 * because the values are already in the range [0,1] so it won't 257 * have any effect anyway. 258 */ 259 if (_mesa_get_format_datatype(rb->Format) == GL_UNSIGNED_NORMALIZED) 260 transferOps &= ~IMAGE_CLAMP_BIT; 261 262 if (transferOps) 263 return GL_FALSE; 264 265 dstStride = _mesa_image_row_stride(packing, width, format, type); 266 dst = (GLubyte *) _mesa_image_address2d(packing, pixels, width, height, 267 format, type, 0, 0); 268 269 ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT, 270 &map, &stride); 271 if (!map) { 272 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels"); 273 return GL_TRUE; /* don't bother trying the slow path */ 274 } 275 276 texelBytes = _mesa_get_format_bytes(rb->Format); 277 278 if (swizzle_rb) { 279 /* swap R/B */ 280 for (j = 0; j < height; j++) { 281 int i; 282 for (i = 0; i < width; i++) { 283 GLuint *dst4 = (GLuint *) dst, *map4 = (GLuint *) map; 284 GLuint pixel = map4[i]; 285 dst4[i] = (pixel & 0xff00ff00) 286 | ((pixel & 0x00ff0000) >> 16) 287 | ((pixel & 0x000000ff) << 16); 288 } 289 dst += dstStride; 290 map += stride; 291 } 292 } else if (copy_xrgb) { 293 /* convert xrgb -> argb */ 294 for (j = 0; j < height; j++) { 295 GLuint *dst4 = (GLuint *) dst, *map4 = (GLuint *) map; 296 int i; 297 for (i = 0; i < width; i++) { 298 dst4[i] = map4[i] | 0xff000000; /* set A=0xff */ 299 } 300 dst += dstStride; 301 map += stride; 302 } 303 } else { 304 /* just memcpy */ 305 for (j = 0; j < height; j++) { 306 memcpy(dst, map, width * texelBytes); 307 dst += dstStride; 308 map += stride; 309 } 310 } 311 312 ctx->Driver.UnmapRenderbuffer(ctx, rb); 313 314 return GL_TRUE; 315} 316 317static void 318slow_read_rgba_pixels( struct gl_context *ctx, 319 GLint x, GLint y, 320 GLsizei width, GLsizei height, 321 GLenum format, GLenum type, 322 GLvoid *pixels, 323 const struct gl_pixelstore_attrib *packing, 324 GLbitfield transferOps ) 325{ 326 struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorReadBuffer; 327 const gl_format rbFormat = _mesa_get_srgb_format_linear(rb->Format); 328 void *rgba; 329 GLubyte *dst, *map; 330 int dstStride, stride, j; 331 GLboolean dst_is_integer = _mesa_is_enum_format_integer(format); 332 GLboolean dst_is_uint = _mesa_is_format_unsigned(rbFormat); 333 334 dstStride = _mesa_image_row_stride(packing, width, format, type); 335 dst = (GLubyte *) _mesa_image_address2d(packing, pixels, width, height, 336 format, type, 0, 0); 337 338 ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT, 339 &map, &stride); 340 if (!map) { 341 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels"); 342 return; 343 } 344 345 rgba = malloc(width * MAX_PIXEL_BYTES); 346 if (!rgba) 347 goto done; 348 349 for (j = 0; j < height; j++) { 350 if (dst_is_integer) { 351 _mesa_unpack_uint_rgba_row(rbFormat, width, map, (GLuint (*)[4]) rgba); 352 _mesa_rebase_rgba_uint(width, (GLuint (*)[4]) rgba, 353 rb->_BaseFormat); 354 if (dst_is_uint) { 355 _mesa_pack_rgba_span_from_uints(ctx, width, (GLuint (*)[4]) rgba, format, 356 type, dst); 357 } else { 358 _mesa_pack_rgba_span_from_ints(ctx, width, (GLint (*)[4]) rgba, format, 359 type, dst); 360 } 361 } else { 362 _mesa_unpack_rgba_row(rbFormat, width, map, (GLfloat (*)[4]) rgba); 363 _mesa_rebase_rgba_float(width, (GLfloat (*)[4]) rgba, 364 rb->_BaseFormat); 365 _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba, format, 366 type, dst, packing, transferOps); 367 } 368 dst += dstStride; 369 map += stride; 370 } 371 372 free(rgba); 373 374done: 375 ctx->Driver.UnmapRenderbuffer(ctx, rb); 376} 377 378/* 379 * Read R, G, B, A, RGB, L, or LA pixels. 380 */ 381static void 382read_rgba_pixels( struct gl_context *ctx, 383 GLint x, GLint y, 384 GLsizei width, GLsizei height, 385 GLenum format, GLenum type, GLvoid *pixels, 386 const struct gl_pixelstore_attrib *packing ) 387{ 388 GLbitfield transferOps = ctx->_ImageTransferState; 389 struct gl_framebuffer *fb = ctx->ReadBuffer; 390 struct gl_renderbuffer *rb = fb->_ColorReadBuffer; 391 392 if (!rb) 393 return; 394 395 if ((ctx->Color._ClampReadColor == GL_TRUE || type != GL_FLOAT) && 396 !_mesa_is_enum_format_integer(format)) { 397 transferOps |= IMAGE_CLAMP_BIT; 398 } 399 400 /* Try the optimized paths first. */ 401 if (fast_read_rgba_pixels_memcpy(ctx, x, y, width, height, 402 format, type, pixels, packing, 403 transferOps)) { 404 return; 405 } 406 407 slow_read_rgba_pixels(ctx, x, y, width, height, 408 format, type, pixels, packing, transferOps); 409} 410 411/** 412 * For a packed depth/stencil buffer being read as depth/stencil, just memcpy the 413 * data (possibly swapping 8/24 vs 24/8 as we go). 414 */ 415static GLboolean 416fast_read_depth_stencil_pixels(struct gl_context *ctx, 417 GLint x, GLint y, 418 GLsizei width, GLsizei height, 419 GLubyte *dst, int dstStride) 420{ 421 struct gl_framebuffer *fb = ctx->ReadBuffer; 422 struct gl_renderbuffer *rb = fb->Attachment[BUFFER_DEPTH].Renderbuffer; 423 struct gl_renderbuffer *stencilRb = fb->Attachment[BUFFER_STENCIL].Renderbuffer; 424 GLubyte *map; 425 int stride, i; 426 427 if (rb != stencilRb) 428 return GL_FALSE; 429 430 if (rb->Format != MESA_FORMAT_Z24_S8 && 431 rb->Format != MESA_FORMAT_S8_Z24) 432 return GL_FALSE; 433 434 ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT, 435 &map, &stride); 436 if (!map) { 437 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels"); 438 return GL_TRUE; /* don't bother trying the slow path */ 439 } 440 441 for (i = 0; i < height; i++) { 442 _mesa_unpack_uint_24_8_depth_stencil_row(rb->Format, width, 443 map, (GLuint *)dst); 444 map += stride; 445 dst += dstStride; 446 } 447 448 ctx->Driver.UnmapRenderbuffer(ctx, rb); 449 450 return GL_TRUE; 451} 452 453 454/** 455 * For non-float-depth and stencil buffers being read as 24/8 depth/stencil, 456 * copy the integer data directly instead of converting depth to float and 457 * re-packing. 458 */ 459static GLboolean 460fast_read_depth_stencil_pixels_separate(struct gl_context *ctx, 461 GLint x, GLint y, 462 GLsizei width, GLsizei height, 463 uint32_t *dst, int dstStride) 464{ 465 struct gl_framebuffer *fb = ctx->ReadBuffer; 466 struct gl_renderbuffer *depthRb = fb->Attachment[BUFFER_DEPTH].Renderbuffer; 467 struct gl_renderbuffer *stencilRb = fb->Attachment[BUFFER_STENCIL].Renderbuffer; 468 GLubyte *depthMap, *stencilMap, *stencilVals; 469 int depthStride, stencilStride, i, j; 470 471 if (_mesa_get_format_datatype(depthRb->Format) != GL_UNSIGNED_NORMALIZED) 472 return GL_FALSE; 473 474 ctx->Driver.MapRenderbuffer(ctx, depthRb, x, y, width, height, 475 GL_MAP_READ_BIT, &depthMap, &depthStride); 476 if (!depthMap) { 477 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels"); 478 return GL_TRUE; /* don't bother trying the slow path */ 479 } 480 481 ctx->Driver.MapRenderbuffer(ctx, stencilRb, x, y, width, height, 482 GL_MAP_READ_BIT, &stencilMap, &stencilStride); 483 if (!stencilMap) { 484 ctx->Driver.UnmapRenderbuffer(ctx, depthRb); 485 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels"); 486 return GL_TRUE; /* don't bother trying the slow path */ 487 } 488 489 stencilVals = (GLubyte *) malloc(width * sizeof(GLubyte)); 490 491 if (stencilVals) { 492 for (j = 0; j < height; j++) { 493 _mesa_unpack_uint_z_row(depthRb->Format, width, depthMap, dst); 494 _mesa_unpack_ubyte_stencil_row(stencilRb->Format, width, 495 stencilMap, stencilVals); 496 497 for (i = 0; i < width; i++) { 498 dst[i] = (dst[i] & 0xffffff00) | stencilVals[i]; 499 } 500 501 depthMap += depthStride; 502 stencilMap += stencilStride; 503 dst += dstStride / 4; 504 } 505 } 506 else { 507 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels"); 508 } 509 510 free(stencilVals); 511 512 ctx->Driver.UnmapRenderbuffer(ctx, depthRb); 513 ctx->Driver.UnmapRenderbuffer(ctx, stencilRb); 514 515 return GL_TRUE; 516} 517 518static void 519slow_read_depth_stencil_pixels_separate(struct gl_context *ctx, 520 GLint x, GLint y, 521 GLsizei width, GLsizei height, 522 GLenum type, 523 const struct gl_pixelstore_attrib *packing, 524 GLubyte *dst, int dstStride) 525{ 526 struct gl_framebuffer *fb = ctx->ReadBuffer; 527 struct gl_renderbuffer *depthRb = fb->Attachment[BUFFER_DEPTH].Renderbuffer; 528 struct gl_renderbuffer *stencilRb = fb->Attachment[BUFFER_STENCIL].Renderbuffer; 529 GLubyte *depthMap, *stencilMap; 530 int depthStride, stencilStride, j; 531 GLubyte *stencilVals; 532 GLfloat *depthVals; 533 534 535 /* The depth and stencil buffers might be separate, or a single buffer. 536 * If one buffer, only map it once. 537 */ 538 ctx->Driver.MapRenderbuffer(ctx, depthRb, x, y, width, height, 539 GL_MAP_READ_BIT, &depthMap, &depthStride); 540 if (!depthMap) { 541 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels"); 542 return; 543 } 544 545 if (stencilRb != depthRb) { 546 ctx->Driver.MapRenderbuffer(ctx, stencilRb, x, y, width, height, 547 GL_MAP_READ_BIT, &stencilMap, 548 &stencilStride); 549 if (!stencilMap) { 550 ctx->Driver.UnmapRenderbuffer(ctx, depthRb); 551 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels"); 552 return; 553 } 554 } 555 else { 556 stencilMap = depthMap; 557 stencilStride = depthStride; 558 } 559 560 stencilVals = (GLubyte *) malloc(width * sizeof(GLubyte)); 561 depthVals = (GLfloat *) malloc(width * sizeof(GLfloat)); 562 563 if (stencilVals && depthVals) { 564 for (j = 0; j < height; j++) { 565 _mesa_unpack_float_z_row(depthRb->Format, width, depthMap, depthVals); 566 _mesa_unpack_ubyte_stencil_row(stencilRb->Format, width, 567 stencilMap, stencilVals); 568 569 _mesa_pack_depth_stencil_span(ctx, width, type, (GLuint *)dst, 570 depthVals, stencilVals, packing); 571 572 depthMap += depthStride; 573 stencilMap += stencilStride; 574 dst += dstStride; 575 } 576 } 577 else { 578 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels"); 579 } 580 581 free(stencilVals); 582 free(depthVals); 583 584 ctx->Driver.UnmapRenderbuffer(ctx, depthRb); 585 if (stencilRb != depthRb) { 586 ctx->Driver.UnmapRenderbuffer(ctx, stencilRb); 587 } 588} 589 590 591/** 592 * Read combined depth/stencil values. 593 * We'll have already done error checking to be sure the expected 594 * depth and stencil buffers really exist. 595 */ 596static void 597read_depth_stencil_pixels(struct gl_context *ctx, 598 GLint x, GLint y, 599 GLsizei width, GLsizei height, 600 GLenum type, GLvoid *pixels, 601 const struct gl_pixelstore_attrib *packing ) 602{ 603 const GLboolean scaleOrBias 604 = ctx->Pixel.DepthScale != 1.0 || ctx->Pixel.DepthBias != 0.0; 605 const GLboolean stencilTransfer = ctx->Pixel.IndexShift 606 || ctx->Pixel.IndexOffset || ctx->Pixel.MapStencilFlag; 607 GLubyte *dst; 608 int dstStride; 609 610 dst = (GLubyte *) _mesa_image_address2d(packing, pixels, 611 width, height, 612 GL_DEPTH_STENCIL_EXT, 613 type, 0, 0); 614 dstStride = _mesa_image_row_stride(packing, width, 615 GL_DEPTH_STENCIL_EXT, type); 616 617 /* Fast 24/8 reads. */ 618 if (type == GL_UNSIGNED_INT_24_8 && 619 !scaleOrBias && !stencilTransfer && !packing->SwapBytes) { 620 if (fast_read_depth_stencil_pixels(ctx, x, y, width, height, 621 dst, dstStride)) 622 return; 623 624 if (fast_read_depth_stencil_pixels_separate(ctx, x, y, width, height, 625 (uint32_t *)dst, dstStride)) 626 return; 627 } 628 629 slow_read_depth_stencil_pixels_separate(ctx, x, y, width, height, 630 type, packing, 631 dst, dstStride); 632} 633 634 635 636/** 637 * Software fallback routine for ctx->Driver.ReadPixels(). 638 * By time we get here, all error checking will have been done. 639 */ 640void 641_mesa_readpixels(struct gl_context *ctx, 642 GLint x, GLint y, GLsizei width, GLsizei height, 643 GLenum format, GLenum type, 644 const struct gl_pixelstore_attrib *packing, 645 GLvoid *pixels) 646{ 647 struct gl_pixelstore_attrib clippedPacking = *packing; 648 649 if (ctx->NewState) 650 _mesa_update_state(ctx); 651 652 /* Do all needed clipping here, so that we can forget about it later */ 653 if (_mesa_clip_readpixels(ctx, &x, &y, &width, &height, &clippedPacking)) { 654 655 pixels = _mesa_map_pbo_dest(ctx, &clippedPacking, pixels); 656 657 if (pixels) { 658 switch (format) { 659 case GL_STENCIL_INDEX: 660 read_stencil_pixels(ctx, x, y, width, height, type, pixels, 661 &clippedPacking); 662 break; 663 case GL_DEPTH_COMPONENT: 664 read_depth_pixels(ctx, x, y, width, height, type, pixels, 665 &clippedPacking); 666 break; 667 case GL_DEPTH_STENCIL_EXT: 668 read_depth_stencil_pixels(ctx, x, y, width, height, type, pixels, 669 &clippedPacking); 670 break; 671 default: 672 /* all other formats should be color formats */ 673 read_rgba_pixels(ctx, x, y, width, height, format, type, pixels, 674 &clippedPacking); 675 } 676 677 _mesa_unmap_pbo_dest(ctx, &clippedPacking); 678 } 679 } 680} 681 682 683void GLAPIENTRY 684_mesa_ReadnPixelsARB( GLint x, GLint y, GLsizei width, GLsizei height, 685 GLenum format, GLenum type, GLsizei bufSize, 686 GLvoid *pixels ) 687{ 688 GLenum err; 689 690 GET_CURRENT_CONTEXT(ctx); 691 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 692 693 FLUSH_CURRENT(ctx, 0); 694 695 if (MESA_VERBOSE & VERBOSE_API) 696 _mesa_debug(ctx, "glReadPixels(%d, %d, %s, %s, %p)\n", 697 width, height, 698 _mesa_lookup_enum_by_nr(format), 699 _mesa_lookup_enum_by_nr(type), 700 pixels); 701 702 if (width < 0 || height < 0) { 703 _mesa_error( ctx, GL_INVALID_VALUE, 704 "glReadPixels(width=%d height=%d)", width, height ); 705 return; 706 } 707 708 /* OpenGL ES 1.x and OpenGL ES 2.0 impose additional restrictions on the 709 * combinations of format and type that can be used. 710 * 711 * Technically, only two combinations are actually allowed: 712 * GL_RGBA/GL_UNSIGNED_BYTE, and some implementation-specific internal 713 * preferred combination. This code doesn't know what that preferred 714 * combination is, and Mesa can handle anything valid. Just work instead. 715 */ 716 if (_mesa_is_gles(ctx) && ctx->Version < 30) { 717 err = _mesa_es_error_check_format_and_type(format, type, 2); 718 if (err == GL_NO_ERROR) { 719 if (type == GL_FLOAT || type == GL_HALF_FLOAT_OES) { 720 err = GL_INVALID_OPERATION; 721 } else if (format == GL_DEPTH_COMPONENT 722 || format == GL_DEPTH_STENCIL) { 723 err = GL_INVALID_ENUM; 724 } 725 } 726 727 if (err != GL_NO_ERROR) { 728 _mesa_error(ctx, err, "glReadPixels(invalid format %s and/or type %s)", 729 _mesa_lookup_enum_by_nr(format), 730 _mesa_lookup_enum_by_nr(type)); 731 return; 732 } 733 } 734 735 if (ctx->NewState) 736 _mesa_update_state(ctx); 737 738 err = _mesa_error_check_format_and_type(ctx, format, type); 739 if (err != GL_NO_ERROR) { 740 _mesa_error(ctx, err, "glReadPixels(invalid format %s and/or type %s)", 741 _mesa_lookup_enum_by_nr(format), 742 _mesa_lookup_enum_by_nr(type)); 743 return; 744 } 745 746 if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { 747 _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, 748 "glReadPixels(incomplete framebuffer)" ); 749 return; 750 } 751 752 if (_mesa_is_user_fbo(ctx->ReadBuffer) && 753 ctx->ReadBuffer->Visual.samples > 0) { 754 _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(multisample FBO)"); 755 return; 756 } 757 758 if (!_mesa_source_buffer_exists(ctx, format)) { 759 _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(no readbuffer)"); 760 return; 761 } 762 763 /* Check that the destination format and source buffer are both 764 * integer-valued or both non-integer-valued. 765 */ 766 if (ctx->Extensions.EXT_texture_integer && _mesa_is_color_format(format)) { 767 const struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorReadBuffer; 768 const GLboolean srcInteger = _mesa_is_format_integer_color(rb->Format); 769 const GLboolean dstInteger = _mesa_is_enum_format_integer(format); 770 if (dstInteger != srcInteger) { 771 _mesa_error(ctx, GL_INVALID_OPERATION, 772 "glReadPixels(integer / non-integer format mismatch"); 773 return; 774 } 775 } 776 777 if (width == 0 || height == 0) 778 return; /* nothing to do */ 779 780 if (!_mesa_validate_pbo_access(2, &ctx->Pack, width, height, 1, 781 format, type, bufSize, pixels)) { 782 if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { 783 _mesa_error(ctx, GL_INVALID_OPERATION, 784 "glReadPixels(out of bounds PBO access)"); 785 } else { 786 _mesa_error(ctx, GL_INVALID_OPERATION, 787 "glReadnPixelsARB(out of bounds access:" 788 " bufSize (%d) is too small)", bufSize); 789 } 790 return; 791 } 792 793 if (_mesa_is_bufferobj(ctx->Pack.BufferObj) && 794 _mesa_bufferobj_mapped(ctx->Pack.BufferObj)) { 795 /* buffer is mapped - that's an error */ 796 _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(PBO is mapped)"); 797 return; 798 } 799 800 ctx->Driver.ReadPixels(ctx, x, y, width, height, 801 format, type, &ctx->Pack, pixels); 802} 803 804void GLAPIENTRY 805_mesa_ReadPixels( GLint x, GLint y, GLsizei width, GLsizei height, 806 GLenum format, GLenum type, GLvoid *pixels ) 807{ 808 _mesa_ReadnPixelsARB(x, y, width, height, format, type, INT_MAX, pixels); 809} 810