texgetimage.c revision b8e80941
1/* 2 * Mesa 3-D graphics library 3 * 4 * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. 5 * Copyright (c) 2009 VMware, Inc. 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 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 * OTHER DEALINGS IN THE SOFTWARE. 24 */ 25 26 27/** 28 * Code for glGetTexImage() and glGetCompressedTexImage(). 29 */ 30 31 32#include "glheader.h" 33#include "bufferobj.h" 34#include "enums.h" 35#include "context.h" 36#include "formats.h" 37#include "format_unpack.h" 38#include "glformats.h" 39#include "image.h" 40#include "mtypes.h" 41#include "pack.h" 42#include "pbo.h" 43#include "pixelstore.h" 44#include "texcompress.h" 45#include "texgetimage.h" 46#include "teximage.h" 47#include "texobj.h" 48#include "texstore.h" 49#include "format_utils.h" 50#include "pixeltransfer.h" 51 52/** 53 * Can the given type represent negative values? 54 */ 55static inline GLboolean 56type_needs_clamping(GLenum type) 57{ 58 switch (type) { 59 case GL_BYTE: 60 case GL_SHORT: 61 case GL_INT: 62 case GL_FLOAT: 63 case GL_HALF_FLOAT_ARB: 64 case GL_UNSIGNED_INT_10F_11F_11F_REV: 65 case GL_UNSIGNED_INT_5_9_9_9_REV: 66 return GL_FALSE; 67 default: 68 return GL_TRUE; 69 } 70} 71 72 73/** 74 * glGetTexImage for depth/Z pixels. 75 */ 76static void 77get_tex_depth(struct gl_context *ctx, GLuint dimensions, 78 GLint xoffset, GLint yoffset, GLint zoffset, 79 GLsizei width, GLsizei height, GLint depth, 80 GLenum format, GLenum type, GLvoid *pixels, 81 struct gl_texture_image *texImage) 82{ 83 GLint img, row; 84 GLfloat *depthRow = malloc(width * sizeof(GLfloat)); 85 86 if (!depthRow) { 87 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage"); 88 return; 89 } 90 91 for (img = 0; img < depth; img++) { 92 GLubyte *srcMap; 93 GLint srcRowStride; 94 95 /* map src texture buffer */ 96 ctx->Driver.MapTextureImage(ctx, texImage, zoffset + img, 97 xoffset, yoffset, width, height, 98 GL_MAP_READ_BIT, &srcMap, &srcRowStride); 99 100 if (srcMap) { 101 for (row = 0; row < height; row++) { 102 void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels, 103 width, height, format, type, 104 img, row, 0); 105 const GLubyte *src = srcMap + row * srcRowStride; 106 _mesa_unpack_float_z_row(texImage->TexFormat, width, src, depthRow); 107 _mesa_pack_depth_span(ctx, width, dest, type, depthRow, &ctx->Pack); 108 } 109 110 ctx->Driver.UnmapTextureImage(ctx, texImage, zoffset + img); 111 } 112 else { 113 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage"); 114 break; 115 } 116 } 117 118 free(depthRow); 119} 120 121 122/** 123 * glGetTexImage for depth/stencil pixels. 124 */ 125static void 126get_tex_depth_stencil(struct gl_context *ctx, GLuint dimensions, 127 GLint xoffset, GLint yoffset, GLint zoffset, 128 GLsizei width, GLsizei height, GLint depth, 129 GLenum format, GLenum type, GLvoid *pixels, 130 struct gl_texture_image *texImage) 131{ 132 GLint img, row; 133 134 assert(format == GL_DEPTH_STENCIL); 135 assert(type == GL_UNSIGNED_INT_24_8 || 136 type == GL_FLOAT_32_UNSIGNED_INT_24_8_REV); 137 138 for (img = 0; img < depth; img++) { 139 GLubyte *srcMap; 140 GLint rowstride; 141 142 /* map src texture buffer */ 143 ctx->Driver.MapTextureImage(ctx, texImage, zoffset + img, 144 xoffset, yoffset, width, height, 145 GL_MAP_READ_BIT, &srcMap, &rowstride); 146 147 if (srcMap) { 148 for (row = 0; row < height; row++) { 149 const GLubyte *src = srcMap + row * rowstride; 150 void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels, 151 width, height, format, type, 152 img, row, 0); 153 _mesa_unpack_depth_stencil_row(texImage->TexFormat, 154 width, 155 (const GLuint *) src, 156 type, dest); 157 if (ctx->Pack.SwapBytes) { 158 _mesa_swap4((GLuint *) dest, width); 159 } 160 } 161 162 ctx->Driver.UnmapTextureImage(ctx, texImage, zoffset + img); 163 } 164 else { 165 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage"); 166 break; 167 } 168 } 169} 170 171/** 172 * glGetTexImage for stencil pixels. 173 */ 174static void 175get_tex_stencil(struct gl_context *ctx, GLuint dimensions, 176 GLint xoffset, GLint yoffset, GLint zoffset, 177 GLsizei width, GLsizei height, GLint depth, 178 GLenum format, GLenum type, GLvoid *pixels, 179 struct gl_texture_image *texImage) 180{ 181 GLint img, row; 182 183 assert(format == GL_STENCIL_INDEX); 184 185 for (img = 0; img < depth; img++) { 186 GLubyte *srcMap; 187 GLint rowstride; 188 189 /* map src texture buffer */ 190 ctx->Driver.MapTextureImage(ctx, texImage, zoffset + img, 191 xoffset, yoffset, width, height, 192 GL_MAP_READ_BIT, 193 &srcMap, &rowstride); 194 195 if (srcMap) { 196 for (row = 0; row < height; row++) { 197 const GLubyte *src = srcMap + row * rowstride; 198 void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels, 199 width, height, format, type, 200 img, row, 0); 201 _mesa_unpack_ubyte_stencil_row(texImage->TexFormat, 202 width, 203 (const GLuint *) src, 204 dest); 205 } 206 207 ctx->Driver.UnmapTextureImage(ctx, texImage, zoffset + img); 208 } 209 else { 210 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage"); 211 break; 212 } 213 } 214} 215 216 217/** 218 * glGetTexImage for YCbCr pixels. 219 */ 220static void 221get_tex_ycbcr(struct gl_context *ctx, GLuint dimensions, 222 GLint xoffset, GLint yoffset, GLint zoffset, 223 GLsizei width, GLsizei height, GLint depth, 224 GLenum format, GLenum type, GLvoid *pixels, 225 struct gl_texture_image *texImage) 226{ 227 GLint img, row; 228 229 for (img = 0; img < depth; img++) { 230 GLubyte *srcMap; 231 GLint rowstride; 232 233 /* map src texture buffer */ 234 ctx->Driver.MapTextureImage(ctx, texImage, zoffset + img, 235 xoffset, yoffset, width, height, 236 GL_MAP_READ_BIT, &srcMap, &rowstride); 237 238 if (srcMap) { 239 for (row = 0; row < height; row++) { 240 const GLubyte *src = srcMap + row * rowstride; 241 void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels, 242 width, height, format, type, 243 img, row, 0); 244 memcpy(dest, src, width * sizeof(GLushort)); 245 246 /* check for byte swapping */ 247 if ((texImage->TexFormat == MESA_FORMAT_YCBCR 248 && type == GL_UNSIGNED_SHORT_8_8_REV_MESA) || 249 (texImage->TexFormat == MESA_FORMAT_YCBCR_REV 250 && type == GL_UNSIGNED_SHORT_8_8_MESA)) { 251 if (!ctx->Pack.SwapBytes) 252 _mesa_swap2((GLushort *) dest, width); 253 } 254 else if (ctx->Pack.SwapBytes) { 255 _mesa_swap2((GLushort *) dest, width); 256 } 257 } 258 259 ctx->Driver.UnmapTextureImage(ctx, texImage, zoffset + img); 260 } 261 else { 262 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage"); 263 break; 264 } 265 } 266} 267 268/** 269 * Depending on the base format involved we may need to apply a rebase 270 * transform (for example: if we download to a Luminance format we want 271 * G=0 and B=0). 272 */ 273static bool 274teximage_needs_rebase(mesa_format texFormat, GLenum baseFormat, 275 bool is_compressed, uint8_t *rebaseSwizzle) 276{ 277 bool needsRebase = false; 278 279 if (baseFormat == GL_LUMINANCE || 280 baseFormat == GL_INTENSITY) { 281 needsRebase = true; 282 rebaseSwizzle[0] = MESA_FORMAT_SWIZZLE_X; 283 rebaseSwizzle[1] = MESA_FORMAT_SWIZZLE_ZERO; 284 rebaseSwizzle[2] = MESA_FORMAT_SWIZZLE_ZERO; 285 rebaseSwizzle[3] = MESA_FORMAT_SWIZZLE_ONE; 286 } else if (baseFormat == GL_LUMINANCE_ALPHA) { 287 needsRebase = true; 288 rebaseSwizzle[0] = MESA_FORMAT_SWIZZLE_X; 289 rebaseSwizzle[1] = MESA_FORMAT_SWIZZLE_ZERO; 290 rebaseSwizzle[2] = MESA_FORMAT_SWIZZLE_ZERO; 291 rebaseSwizzle[3] = MESA_FORMAT_SWIZZLE_W; 292 } else if (!is_compressed && 293 (baseFormat != _mesa_get_format_base_format(texFormat))) { 294 needsRebase = 295 _mesa_compute_rgba2base2rgba_component_mapping(baseFormat, 296 rebaseSwizzle); 297 } 298 299 return needsRebase; 300} 301 302 303/** 304 * Get a color texture image with decompression. 305 */ 306static void 307get_tex_rgba_compressed(struct gl_context *ctx, GLuint dimensions, 308 GLint xoffset, GLint yoffset, GLint zoffset, 309 GLsizei width, GLsizei height, GLint depth, 310 GLenum format, GLenum type, GLvoid *pixels, 311 struct gl_texture_image *texImage, 312 GLbitfield transferOps) 313{ 314 /* don't want to apply sRGB -> RGB conversion here so override the format */ 315 const mesa_format texFormat = 316 _mesa_get_srgb_format_linear(texImage->TexFormat); 317 const GLenum baseFormat = _mesa_get_format_base_format(texFormat); 318 GLfloat *tempImage, *tempSlice; 319 GLuint slice; 320 int srcStride, dstStride; 321 uint32_t dstFormat; 322 bool needsRebase; 323 uint8_t rebaseSwizzle[4]; 324 325 /* Decompress into temp float buffer, then pack into user buffer */ 326 tempImage = malloc(width * height * depth * 4 * sizeof(GLfloat)); 327 if (!tempImage) { 328 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage()"); 329 return; 330 } 331 332 /* Decompress the texture image slices - results in 'tempImage' */ 333 for (slice = 0; slice < depth; slice++) { 334 GLubyte *srcMap; 335 GLint srcRowStride; 336 337 tempSlice = tempImage + slice * 4 * width * height; 338 339 ctx->Driver.MapTextureImage(ctx, texImage, zoffset + slice, 340 xoffset, yoffset, width, height, 341 GL_MAP_READ_BIT, 342 &srcMap, &srcRowStride); 343 if (srcMap) { 344 _mesa_decompress_image(texFormat, width, height, 345 srcMap, srcRowStride, tempSlice); 346 347 ctx->Driver.UnmapTextureImage(ctx, texImage, zoffset + slice); 348 } 349 else { 350 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage"); 351 free(tempImage); 352 return; 353 } 354 } 355 356 needsRebase = teximage_needs_rebase(texFormat, baseFormat, true, 357 rebaseSwizzle); 358 359 srcStride = 4 * width * sizeof(GLfloat); 360 dstStride = _mesa_image_row_stride(&ctx->Pack, width, format, type); 361 dstFormat = _mesa_format_from_format_and_type(format, type); 362 tempSlice = tempImage; 363 for (slice = 0; slice < depth; slice++) { 364 void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels, 365 width, height, format, type, 366 slice, 0, 0); 367 _mesa_format_convert(dest, dstFormat, dstStride, 368 tempSlice, RGBA32_FLOAT, srcStride, 369 width, height, 370 needsRebase ? rebaseSwizzle : NULL); 371 372 /* Handle byte swapping if required */ 373 if (ctx->Pack.SwapBytes) { 374 _mesa_swap_bytes_2d_image(format, type, &ctx->Pack, 375 width, height, dest, dest); 376 } 377 378 tempSlice += 4 * width * height; 379 } 380 381 free(tempImage); 382} 383 384 385/** 386 * Return a base GL format given the user-requested format 387 * for glGetTexImage(). 388 */ 389GLenum 390_mesa_base_pack_format(GLenum format) 391{ 392 switch (format) { 393 case GL_ABGR_EXT: 394 case GL_BGRA: 395 case GL_BGRA_INTEGER: 396 case GL_RGBA_INTEGER: 397 return GL_RGBA; 398 case GL_BGR: 399 case GL_BGR_INTEGER: 400 case GL_RGB_INTEGER: 401 return GL_RGB; 402 case GL_RED_INTEGER: 403 return GL_RED; 404 case GL_GREEN_INTEGER: 405 return GL_GREEN; 406 case GL_BLUE_INTEGER: 407 return GL_BLUE; 408 case GL_ALPHA_INTEGER: 409 return GL_ALPHA; 410 case GL_LUMINANCE_INTEGER_EXT: 411 return GL_LUMINANCE; 412 case GL_LUMINANCE_ALPHA_INTEGER_EXT: 413 return GL_LUMINANCE_ALPHA; 414 default: 415 return format; 416 } 417} 418 419 420/** 421 * Get an uncompressed color texture image. 422 */ 423static void 424get_tex_rgba_uncompressed(struct gl_context *ctx, GLuint dimensions, 425 GLint xoffset, GLint yoffset, GLint zoffset, 426 GLsizei width, GLsizei height, GLint depth, 427 GLenum format, GLenum type, GLvoid *pixels, 428 struct gl_texture_image *texImage, 429 GLbitfield transferOps) 430{ 431 /* don't want to apply sRGB -> RGB conversion here so override the format */ 432 const mesa_format texFormat = 433 _mesa_get_srgb_format_linear(texImage->TexFormat); 434 GLuint img; 435 GLboolean dst_is_integer; 436 uint32_t dst_format; 437 int dst_stride; 438 uint8_t rebaseSwizzle[4]; 439 bool needsRebase; 440 void *rgba = NULL; 441 442 needsRebase = teximage_needs_rebase(texFormat, texImage->_BaseFormat, false, 443 rebaseSwizzle); 444 445 /* Describe the dst format */ 446 dst_is_integer = _mesa_is_enum_format_integer(format); 447 dst_format = _mesa_format_from_format_and_type(format, type); 448 dst_stride = _mesa_image_row_stride(&ctx->Pack, width, format, type); 449 450 /* Since _mesa_format_convert does not handle transferOps we need to handle 451 * them before we call the function. This requires to convert to RGBA float 452 * first so we can call _mesa_apply_rgba_transfer_ops. If the dst format is 453 * integer then transferOps do not apply. 454 */ 455 assert(!transferOps || (transferOps && !dst_is_integer)); 456 (void) dst_is_integer; /* silence unused var warning */ 457 458 for (img = 0; img < depth; img++) { 459 GLubyte *srcMap; 460 GLint rowstride; 461 GLubyte *img_src; 462 void *dest; 463 void *src; 464 int src_stride; 465 uint32_t src_format; 466 467 /* map src texture buffer */ 468 ctx->Driver.MapTextureImage(ctx, texImage, zoffset + img, 469 xoffset, yoffset, width, height, 470 GL_MAP_READ_BIT, 471 &srcMap, &rowstride); 472 if (!srcMap) { 473 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage"); 474 goto done; 475 } 476 477 img_src = srcMap; 478 dest = _mesa_image_address(dimensions, &ctx->Pack, pixels, 479 width, height, format, type, 480 img, 0, 0); 481 482 if (transferOps) { 483 uint32_t rgba_format; 484 int rgba_stride; 485 bool need_convert = false; 486 487 /* We will convert to RGBA float */ 488 rgba_format = RGBA32_FLOAT; 489 rgba_stride = width * 4 * sizeof(GLfloat); 490 491 /* If we are lucky and the dst format matches the RGBA format we need 492 * to convert to, then we can convert directly into the dst buffer 493 * and avoid the final conversion/copy from the rgba buffer to the dst 494 * buffer. 495 */ 496 if (format == rgba_format) { 497 rgba = dest; 498 } else { 499 need_convert = true; 500 if (rgba == NULL) { /* Allocate the RGBA buffer only once */ 501 rgba = malloc(height * rgba_stride); 502 if (!rgba) { 503 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage()"); 504 ctx->Driver.UnmapTextureImage(ctx, texImage, img); 505 return; 506 } 507 } 508 } 509 510 _mesa_format_convert(rgba, rgba_format, rgba_stride, 511 img_src, texFormat, rowstride, 512 width, height, 513 needsRebase ? rebaseSwizzle : NULL); 514 515 /* Handle transfer ops now */ 516 _mesa_apply_rgba_transfer_ops(ctx, transferOps, width * height, rgba); 517 518 /* If we had to rebase, we have already handled that */ 519 needsRebase = false; 520 521 /* If we were lucky and our RGBA conversion matches the dst format, 522 * then we are done. 523 */ 524 if (!need_convert) 525 goto do_swap; 526 527 /* Otherwise, we need to convert from RGBA to dst next */ 528 src = rgba; 529 src_format = rgba_format; 530 src_stride = rgba_stride; 531 } else { 532 /* No RGBA conversion needed, convert directly to dst */ 533 src = img_src; 534 src_format = texFormat; 535 src_stride = rowstride; 536 } 537 538 /* Do the conversion to destination format */ 539 _mesa_format_convert(dest, dst_format, dst_stride, 540 src, src_format, src_stride, 541 width, height, 542 needsRebase ? rebaseSwizzle : NULL); 543 544 do_swap: 545 /* Handle byte swapping if required */ 546 if (ctx->Pack.SwapBytes) 547 _mesa_swap_bytes_2d_image(format, type, &ctx->Pack, 548 width, height, dest, dest); 549 550 /* Unmap the src texture buffer */ 551 ctx->Driver.UnmapTextureImage(ctx, texImage, zoffset + img); 552 } 553 554done: 555 free(rgba); 556} 557 558 559/** 560 * glGetTexImage for color formats (RGBA, RGB, alpha, LA, etc). 561 * Compressed textures are handled here as well. 562 */ 563static void 564get_tex_rgba(struct gl_context *ctx, GLuint dimensions, 565 GLint xoffset, GLint yoffset, GLint zoffset, 566 GLsizei width, GLsizei height, GLint depth, 567 GLenum format, GLenum type, GLvoid *pixels, 568 struct gl_texture_image *texImage) 569{ 570 const GLenum dataType = _mesa_get_format_datatype(texImage->TexFormat); 571 GLbitfield transferOps = 0x0; 572 573 /* In general, clamping does not apply to glGetTexImage, except when 574 * the returned type of the image can't hold negative values. 575 */ 576 if (type_needs_clamping(type)) { 577 /* the returned image type can't have negative values */ 578 if (dataType == GL_FLOAT || 579 dataType == GL_HALF_FLOAT || 580 dataType == GL_SIGNED_NORMALIZED || 581 format == GL_LUMINANCE || 582 format == GL_LUMINANCE_ALPHA) { 583 transferOps |= IMAGE_CLAMP_BIT; 584 } 585 } 586 587 if (_mesa_is_format_compressed(texImage->TexFormat)) { 588 get_tex_rgba_compressed(ctx, dimensions, 589 xoffset, yoffset, zoffset, 590 width, height, depth, 591 format, type, 592 pixels, texImage, transferOps); 593 } 594 else { 595 get_tex_rgba_uncompressed(ctx, dimensions, 596 xoffset, yoffset, zoffset, 597 width, height, depth, 598 format, type, 599 pixels, texImage, transferOps); 600 } 601} 602 603 604/** 605 * Try to do glGetTexImage() with simple memcpy(). 606 * \return GL_TRUE if done, GL_FALSE otherwise 607 */ 608static GLboolean 609get_tex_memcpy(struct gl_context *ctx, 610 GLint xoffset, GLint yoffset, GLint zoffset, 611 GLsizei width, GLsizei height, GLint depth, 612 GLenum format, GLenum type, GLvoid *pixels, 613 struct gl_texture_image *texImage) 614{ 615 const GLenum target = texImage->TexObject->Target; 616 GLboolean memCopy = GL_FALSE; 617 GLenum texBaseFormat = _mesa_get_format_base_format(texImage->TexFormat); 618 619 /* 620 * Check if we can use memcpy to copy from the hardware texture 621 * format to the user's format/type. 622 * Note that GL's pixel transfer ops don't apply to glGetTexImage() 623 */ 624 if ((target == GL_TEXTURE_1D || 625 target == GL_TEXTURE_2D || 626 target == GL_TEXTURE_RECTANGLE || 627 _mesa_is_cube_face(target)) && 628 texBaseFormat == texImage->_BaseFormat) { 629 memCopy = _mesa_format_matches_format_and_type(texImage->TexFormat, 630 format, type, 631 ctx->Pack.SwapBytes, NULL); 632 } 633 634 if (depth > 1) { 635 /* only a single slice is supported at this time */ 636 memCopy = FALSE; 637 } 638 639 if (memCopy) { 640 const GLuint bpp = _mesa_get_format_bytes(texImage->TexFormat); 641 const GLint bytesPerRow = width * bpp; 642 GLubyte *dst = 643 _mesa_image_address2d(&ctx->Pack, pixels, width, height, 644 format, type, 0, 0); 645 const GLint dstRowStride = 646 _mesa_image_row_stride(&ctx->Pack, width, format, type); 647 GLubyte *src; 648 GLint srcRowStride; 649 650 /* map src texture buffer */ 651 ctx->Driver.MapTextureImage(ctx, texImage, zoffset, 652 xoffset, yoffset, width, height, 653 GL_MAP_READ_BIT, &src, &srcRowStride); 654 655 if (src) { 656 if (bytesPerRow == dstRowStride && bytesPerRow == srcRowStride) { 657 memcpy(dst, src, bytesPerRow * height); 658 } 659 else { 660 GLuint row; 661 for (row = 0; row < height; row++) { 662 memcpy(dst, src, bytesPerRow); 663 dst += dstRowStride; 664 src += srcRowStride; 665 } 666 } 667 668 /* unmap src texture buffer */ 669 ctx->Driver.UnmapTextureImage(ctx, texImage, zoffset); 670 } 671 else { 672 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage"); 673 } 674 } 675 676 return memCopy; 677} 678 679 680/** 681 * This is the software fallback for Driver.GetTexSubImage(). 682 * All error checking will have been done before this routine is called. 683 * We'll call ctx->Driver.MapTextureImage() to access the data, then 684 * unmap with ctx->Driver.UnmapTextureImage(). 685 */ 686void 687_mesa_GetTexSubImage_sw(struct gl_context *ctx, 688 GLint xoffset, GLint yoffset, GLint zoffset, 689 GLsizei width, GLsizei height, GLint depth, 690 GLenum format, GLenum type, GLvoid *pixels, 691 struct gl_texture_image *texImage) 692{ 693 const GLuint dimensions = 694 _mesa_get_texture_dimensions(texImage->TexObject->Target); 695 696 /* map dest buffer, if PBO */ 697 if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { 698 /* Packing texture image into a PBO. 699 * Map the (potentially) VRAM-based buffer into our process space so 700 * we can write into it with the code below. 701 * A hardware driver might use a sophisticated blit to move the 702 * texture data to the PBO if the PBO is in VRAM along with the texture. 703 */ 704 GLubyte *buf = (GLubyte *) 705 ctx->Driver.MapBufferRange(ctx, 0, ctx->Pack.BufferObj->Size, 706 GL_MAP_WRITE_BIT, ctx->Pack.BufferObj, 707 MAP_INTERNAL); 708 if (!buf) { 709 /* out of memory or other unexpected error */ 710 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage(map PBO failed)"); 711 return; 712 } 713 /* <pixels> was an offset into the PBO. 714 * Now make it a real, client-side pointer inside the mapped region. 715 */ 716 pixels = ADD_POINTERS(buf, pixels); 717 } 718 719 /* for all array textures, the Z axis selects the layer */ 720 if (texImage->TexObject->Target == GL_TEXTURE_1D_ARRAY) { 721 depth = height; 722 height = 1; 723 zoffset = yoffset; 724 yoffset = 0; 725 assert(zoffset + depth <= texImage->Height); 726 } else { 727 assert(zoffset + depth <= texImage->Depth); 728 } 729 730 if (get_tex_memcpy(ctx, xoffset, yoffset, zoffset, width, height, depth, 731 format, type, pixels, texImage)) { 732 /* all done */ 733 } 734 else if (format == GL_DEPTH_COMPONENT) { 735 get_tex_depth(ctx, dimensions, xoffset, yoffset, zoffset, 736 width, height, depth, format, type, pixels, texImage); 737 } 738 else if (format == GL_DEPTH_STENCIL_EXT) { 739 get_tex_depth_stencil(ctx, dimensions, xoffset, yoffset, zoffset, 740 width, height, depth, format, type, pixels, 741 texImage); 742 } 743 else if (format == GL_STENCIL_INDEX) { 744 get_tex_stencil(ctx, dimensions, xoffset, yoffset, zoffset, 745 width, height, depth, format, type, pixels, texImage); 746 } 747 else if (format == GL_YCBCR_MESA) { 748 get_tex_ycbcr(ctx, dimensions, xoffset, yoffset, zoffset, 749 width, height, depth, format, type, pixels, texImage); 750 } 751 else { 752 get_tex_rgba(ctx, dimensions, xoffset, yoffset, zoffset, 753 width, height, depth, format, type, pixels, texImage); 754 } 755 756 if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { 757 ctx->Driver.UnmapBuffer(ctx, ctx->Pack.BufferObj, MAP_INTERNAL); 758 } 759} 760 761 762 763/** 764 * This function assumes that all error checking has been done. 765 */ 766static void 767get_compressed_texsubimage_sw(struct gl_context *ctx, 768 struct gl_texture_image *texImage, 769 GLint xoffset, GLint yoffset, 770 GLint zoffset, GLsizei width, 771 GLint height, GLint depth, 772 GLvoid *img) 773{ 774 const GLuint dimensions = 775 _mesa_get_texture_dimensions(texImage->TexObject->Target); 776 struct compressed_pixelstore store; 777 GLint slice; 778 GLubyte *dest; 779 780 _mesa_compute_compressed_pixelstore(dimensions, texImage->TexFormat, 781 width, height, depth, 782 &ctx->Pack, &store); 783 784 if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { 785 /* pack texture image into a PBO */ 786 dest = (GLubyte *) 787 ctx->Driver.MapBufferRange(ctx, 0, ctx->Pack.BufferObj->Size, 788 GL_MAP_WRITE_BIT, ctx->Pack.BufferObj, 789 MAP_INTERNAL); 790 if (!dest) { 791 /* out of memory or other unexpected error */ 792 _mesa_error(ctx, GL_OUT_OF_MEMORY, 793 "glGetCompresssedTexImage(map PBO failed)"); 794 return; 795 } 796 dest = ADD_POINTERS(dest, img); 797 } else { 798 dest = img; 799 } 800 801 dest += store.SkipBytes; 802 803 for (slice = 0; slice < store.CopySlices; slice++) { 804 GLint srcRowStride; 805 GLubyte *src; 806 807 /* map src texture buffer */ 808 ctx->Driver.MapTextureImage(ctx, texImage, zoffset + slice, 809 xoffset, yoffset, width, height, 810 GL_MAP_READ_BIT, &src, &srcRowStride); 811 812 if (src) { 813 GLint i; 814 for (i = 0; i < store.CopyRowsPerSlice; i++) { 815 memcpy(dest, src, store.CopyBytesPerRow); 816 dest += store.TotalBytesPerRow; 817 src += srcRowStride; 818 } 819 820 ctx->Driver.UnmapTextureImage(ctx, texImage, zoffset + slice); 821 822 /* Advance to next slice */ 823 dest += store.TotalBytesPerRow * (store.TotalRowsPerSlice - 824 store.CopyRowsPerSlice); 825 826 } else { 827 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetCompresssedTexImage"); 828 } 829 } 830 831 if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { 832 ctx->Driver.UnmapBuffer(ctx, ctx->Pack.BufferObj, MAP_INTERNAL); 833 } 834} 835 836 837/** 838 * Validate the texture target enum supplied to glGetTex(ture)Image or 839 * glGetCompressedTex(ture)Image. 840 */ 841static GLboolean 842legal_getteximage_target(struct gl_context *ctx, GLenum target, bool dsa) 843{ 844 switch (target) { 845 case GL_TEXTURE_1D: 846 case GL_TEXTURE_2D: 847 case GL_TEXTURE_3D: 848 return GL_TRUE; 849 case GL_TEXTURE_RECTANGLE_NV: 850 return ctx->Extensions.NV_texture_rectangle; 851 case GL_TEXTURE_1D_ARRAY_EXT: 852 case GL_TEXTURE_2D_ARRAY_EXT: 853 return ctx->Extensions.EXT_texture_array; 854 case GL_TEXTURE_CUBE_MAP_ARRAY: 855 return ctx->Extensions.ARB_texture_cube_map_array; 856 857 /* Section 8.11 (Texture Queries) of the OpenGL 4.5 core profile spec 858 * (30.10.2014) says: 859 * "An INVALID_ENUM error is generated if the effective target is not 860 * one of TEXTURE_1D, TEXTURE_2D, TEXTURE_3D, TEXTURE_1D_ARRAY, 861 * TEXTURE_2D_ARRAY, TEXTURE_CUBE_MAP_ARRAY, TEXTURE_RECTANGLE, one of 862 * the targets from table 8.19 (for GetTexImage and GetnTexImage *only*), 863 * or TEXTURE_CUBE_MAP (for GetTextureImage *only*)." (Emphasis added.) 864 */ 865 case GL_TEXTURE_CUBE_MAP_POSITIVE_X: 866 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: 867 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: 868 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: 869 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: 870 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: 871 return dsa ? GL_FALSE : ctx->Extensions.ARB_texture_cube_map; 872 case GL_TEXTURE_CUBE_MAP: 873 return dsa ? GL_TRUE : GL_FALSE; 874 default: 875 return GL_FALSE; 876 } 877} 878 879 880/** 881 * Wrapper for _mesa_select_tex_image() which can handle target being 882 * GL_TEXTURE_CUBE_MAP in which case we use zoffset to select a cube face. 883 * This can happen for glGetTextureImage and glGetTextureSubImage (DSA 884 * functions). 885 */ 886static struct gl_texture_image * 887select_tex_image(const struct gl_texture_object *texObj, GLenum target, 888 GLint level, GLint zoffset) 889{ 890 assert(level >= 0); 891 assert(level < MAX_TEXTURE_LEVELS); 892 if (target == GL_TEXTURE_CUBE_MAP) { 893 assert(zoffset >= 0); 894 assert(zoffset < 6); 895 target = GL_TEXTURE_CUBE_MAP_POSITIVE_X + zoffset; 896 } 897 return _mesa_select_tex_image(texObj, target, level); 898} 899 900 901/** 902 * Error-check the offset and size arguments to 903 * glGet[Compressed]TextureSubImage(). 904 * \return true if error, false if no error. 905 */ 906static bool 907dimensions_error_check(struct gl_context *ctx, 908 struct gl_texture_object *texObj, 909 GLenum target, GLint level, 910 GLint xoffset, GLint yoffset, GLint zoffset, 911 GLsizei width, GLsizei height, GLsizei depth, 912 const char *caller) 913{ 914 const struct gl_texture_image *texImage; 915 GLuint imageWidth = 0, imageHeight = 0, imageDepth = 0; 916 917 if (xoffset < 0) { 918 _mesa_error(ctx, GL_INVALID_VALUE, "%s(xoffset = %d)", caller, xoffset); 919 return true; 920 } 921 922 if (yoffset < 0) { 923 _mesa_error(ctx, GL_INVALID_VALUE, "%s(yoffset = %d)", caller, yoffset); 924 return true; 925 } 926 927 if (zoffset < 0) { 928 _mesa_error(ctx, GL_INVALID_VALUE, "%s(zoffset = %d)", caller, zoffset); 929 return true; 930 } 931 932 if (width < 0) { 933 _mesa_error(ctx, GL_INVALID_VALUE, "%s(width = %d)", caller, width); 934 return true; 935 } 936 937 if (height < 0) { 938 _mesa_error(ctx, GL_INVALID_VALUE, "%s(height = %d)", caller, height); 939 return true; 940 } 941 942 if (depth < 0) { 943 _mesa_error(ctx, GL_INVALID_VALUE, "%s(depth = %d)", caller, depth); 944 return true; 945 } 946 947 /* do special per-target checks */ 948 switch (target) { 949 case GL_TEXTURE_1D: 950 if (yoffset != 0) { 951 _mesa_error(ctx, GL_INVALID_VALUE, 952 "%s(1D, yoffset = %d)", caller, yoffset); 953 return true; 954 } 955 if (height != 1) { 956 _mesa_error(ctx, GL_INVALID_VALUE, 957 "%s(1D, height = %d)", caller, height); 958 return true; 959 } 960 /* fall-through */ 961 case GL_TEXTURE_1D_ARRAY: 962 case GL_TEXTURE_2D: 963 case GL_TEXTURE_RECTANGLE: 964 if (zoffset != 0) { 965 _mesa_error(ctx, GL_INVALID_VALUE, 966 "%s(zoffset = %d)", caller, zoffset); 967 return true; 968 } 969 if (depth != 1) { 970 _mesa_error(ctx, GL_INVALID_VALUE, 971 "%s(depth = %d)", caller, depth); 972 return true; 973 } 974 break; 975 case GL_TEXTURE_CUBE_MAP: 976 /* Non-array cube maps are special because we have a gl_texture_image 977 * per face. 978 */ 979 if (zoffset + depth > 6) { 980 _mesa_error(ctx, GL_INVALID_VALUE, 981 "%s(zoffset + depth = %d)", caller, zoffset + depth); 982 return true; 983 } 984 break; 985 default: 986 ; /* nothing */ 987 } 988 989 texImage = select_tex_image(texObj, target, level, zoffset); 990 if (texImage) { 991 imageWidth = texImage->Width; 992 imageHeight = texImage->Height; 993 imageDepth = texImage->Depth; 994 } 995 996 if (xoffset + width > imageWidth) { 997 _mesa_error(ctx, GL_INVALID_VALUE, 998 "%s(xoffset %d + width %d > %u)", 999 caller, xoffset, width, imageWidth); 1000 return true; 1001 } 1002 1003 if (yoffset + height > imageHeight) { 1004 _mesa_error(ctx, GL_INVALID_VALUE, 1005 "%s(yoffset %d + height %d > %u)", 1006 caller, yoffset, height, imageHeight); 1007 return true; 1008 } 1009 1010 if (target != GL_TEXTURE_CUBE_MAP) { 1011 /* Cube map error checking was done above */ 1012 if (zoffset + depth > imageDepth) { 1013 _mesa_error(ctx, GL_INVALID_VALUE, 1014 "%s(zoffset %d + depth %d > %u)", 1015 caller, zoffset, depth, imageDepth); 1016 return true; 1017 } 1018 } 1019 1020 /* Extra checks for compressed textures */ 1021 if (texImage) { 1022 GLuint bw, bh, bd; 1023 _mesa_get_format_block_size_3d(texImage->TexFormat, &bw, &bh, &bd); 1024 if (bw > 1 || bh > 1 || bd > 1) { 1025 /* offset must be multiple of block size */ 1026 if (xoffset % bw != 0) { 1027 _mesa_error(ctx, GL_INVALID_VALUE, 1028 "%s(xoffset = %d)", caller, xoffset); 1029 return true; 1030 } 1031 if (target != GL_TEXTURE_1D && target != GL_TEXTURE_1D_ARRAY) { 1032 if (yoffset % bh != 0) { 1033 _mesa_error(ctx, GL_INVALID_VALUE, 1034 "%s(yoffset = %d)", caller, yoffset); 1035 return true; 1036 } 1037 } 1038 1039 if (zoffset % bd != 0) { 1040 _mesa_error(ctx, GL_INVALID_VALUE, 1041 "%s(zoffset = %d)", caller, zoffset); 1042 return true; 1043 } 1044 1045 /* The size must be a multiple of bw x bh x bd, or we must be using a 1046 * offset+size that exactly hits the edge of the image. 1047 */ 1048 if ((width % bw != 0) && 1049 (xoffset + width != (GLint) texImage->Width)) { 1050 _mesa_error(ctx, GL_INVALID_VALUE, 1051 "%s(width = %d)", caller, width); 1052 return true; 1053 } 1054 1055 if ((height % bh != 0) && 1056 (yoffset + height != (GLint) texImage->Height)) { 1057 _mesa_error(ctx, GL_INVALID_VALUE, 1058 "%s(height = %d)", caller, height); 1059 return true; 1060 } 1061 1062 if ((depth % bd != 0) && 1063 (zoffset + depth != (GLint) texImage->Depth)) { 1064 _mesa_error(ctx, GL_INVALID_VALUE, 1065 "%s(depth = %d)", caller, depth); 1066 return true; 1067 } 1068 } 1069 } 1070 1071 if (width == 0 || height == 0 || depth == 0) { 1072 /* Not an error, but nothing to do. Return 'true' so that the 1073 * caller simply returns. 1074 */ 1075 return true; 1076 } 1077 1078 return false; 1079} 1080 1081 1082/** 1083 * Do PBO-related error checking for getting uncompressed images. 1084 * \return true if there was an error (or the GetTexImage is to be a no-op) 1085 */ 1086static bool 1087pbo_error_check(struct gl_context *ctx, GLenum target, 1088 GLsizei width, GLsizei height, GLsizei depth, 1089 GLenum format, GLenum type, GLsizei clientMemSize, 1090 GLvoid *pixels, 1091 const char *caller) 1092{ 1093 const GLuint dimensions = (target == GL_TEXTURE_3D) ? 3 : 2; 1094 1095 if (!_mesa_validate_pbo_access(dimensions, &ctx->Pack, width, height, depth, 1096 format, type, clientMemSize, pixels)) { 1097 if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { 1098 _mesa_error(ctx, GL_INVALID_OPERATION, 1099 "%s(out of bounds PBO access)", caller); 1100 } else { 1101 _mesa_error(ctx, GL_INVALID_OPERATION, 1102 "%s(out of bounds access: bufSize (%d) is too small)", 1103 caller, clientMemSize); 1104 } 1105 return true; 1106 } 1107 1108 if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { 1109 /* PBO should not be mapped */ 1110 if (_mesa_check_disallowed_mapping(ctx->Pack.BufferObj)) { 1111 _mesa_error(ctx, GL_INVALID_OPERATION, 1112 "%s(PBO is mapped)", caller); 1113 return true; 1114 } 1115 } 1116 1117 if (!_mesa_is_bufferobj(ctx->Pack.BufferObj) && !pixels) { 1118 /* not an error, do nothing */ 1119 return true; 1120 } 1121 1122 return false; 1123} 1124 1125 1126/** 1127 * Do teximage-related error checking for getting uncompressed images. 1128 * \return true if there was an error 1129 */ 1130static bool 1131teximage_error_check(struct gl_context *ctx, 1132 struct gl_texture_image *texImage, 1133 GLenum format, const char *caller) 1134{ 1135 GLenum baseFormat; 1136 assert(texImage); 1137 1138 /* 1139 * Format and type checking has been moved up to GetnTexImage and 1140 * GetTextureImage so that it happens before getting the texImage object. 1141 */ 1142 1143 baseFormat = _mesa_get_format_base_format(texImage->TexFormat); 1144 1145 /* Make sure the requested image format is compatible with the 1146 * texture's format. 1147 */ 1148 if (_mesa_is_color_format(format) 1149 && !_mesa_is_color_format(baseFormat)) { 1150 _mesa_error(ctx, GL_INVALID_OPERATION, 1151 "%s(format mismatch)", caller); 1152 return true; 1153 } 1154 else if (_mesa_is_depth_format(format) 1155 && !_mesa_is_depth_format(baseFormat) 1156 && !_mesa_is_depthstencil_format(baseFormat)) { 1157 _mesa_error(ctx, GL_INVALID_OPERATION, 1158 "%s(format mismatch)", caller); 1159 return true; 1160 } 1161 else if (_mesa_is_stencil_format(format) 1162 && !ctx->Extensions.ARB_texture_stencil8) { 1163 _mesa_error(ctx, GL_INVALID_ENUM, 1164 "%s(format=GL_STENCIL_INDEX)", caller); 1165 return true; 1166 } 1167 else if (_mesa_is_stencil_format(format) 1168 && !_mesa_is_depthstencil_format(baseFormat) 1169 && !_mesa_is_stencil_format(baseFormat)) { 1170 _mesa_error(ctx, GL_INVALID_OPERATION, 1171 "%s(format mismatch)", caller); 1172 return true; 1173 } 1174 else if (_mesa_is_ycbcr_format(format) 1175 && !_mesa_is_ycbcr_format(baseFormat)) { 1176 _mesa_error(ctx, GL_INVALID_OPERATION, 1177 "%s(format mismatch)", caller); 1178 return true; 1179 } 1180 else if (_mesa_is_depthstencil_format(format) 1181 && !_mesa_is_depthstencil_format(baseFormat)) { 1182 _mesa_error(ctx, GL_INVALID_OPERATION, 1183 "%s(format mismatch)", caller); 1184 return true; 1185 } 1186 else if (!_mesa_is_stencil_format(format) && 1187 _mesa_is_enum_format_integer(format) != 1188 _mesa_is_format_integer(texImage->TexFormat)) { 1189 _mesa_error(ctx, GL_INVALID_OPERATION, 1190 "%s(format mismatch)", caller); 1191 return true; 1192 } 1193 1194 return false; 1195} 1196 1197 1198/** 1199 * Do common teximage-related error checking for getting uncompressed images. 1200 * \return true if there was an error 1201 */ 1202static bool 1203common_error_check(struct gl_context *ctx, 1204 struct gl_texture_object *texObj, 1205 GLenum target, GLint level, 1206 GLsizei width, GLsizei height, GLsizei depth, 1207 GLenum format, GLenum type, GLsizei bufSize, 1208 GLvoid *pixels, const char *caller) 1209{ 1210 GLenum err; 1211 GLint maxLevels; 1212 1213 if (texObj->Target == 0) { 1214 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid texture)", caller); 1215 return true; 1216 } 1217 1218 maxLevels = _mesa_max_texture_levels(ctx, target); 1219 if (level < 0 || level >= maxLevels) { 1220 _mesa_error(ctx, GL_INVALID_VALUE, "%s(level = %d)", caller, level); 1221 return true; 1222 } 1223 1224 err = _mesa_error_check_format_and_type(ctx, format, type); 1225 if (err != GL_NO_ERROR) { 1226 _mesa_error(ctx, err, "%s(format/type)", caller); 1227 return true; 1228 } 1229 1230 /* According to OpenGL 4.6 spec, section 8.11.4 ("Texture Image Queries"): 1231 * 1232 * "An INVALID_OPERATION error is generated by GetTextureImage if the 1233 * effective target is TEXTURE_CUBE_MAP or TEXTURE_CUBE_MAP_ARRAY , 1234 * and the texture object is not cube complete or cube array complete, 1235 * respectively." 1236 * 1237 * This applies also to GetTextureSubImage, GetCompressedTexImage, 1238 * GetCompressedTextureImage, and GetnCompressedTexImage. 1239 */ 1240 if (target == GL_TEXTURE_CUBE_MAP && !_mesa_cube_complete(texObj)) { 1241 _mesa_error(ctx, GL_INVALID_OPERATION, 1242 "%s(cube incomplete)", caller); 1243 return true; 1244 } 1245 1246 return false; 1247} 1248 1249 1250/** 1251 * Do error checking for all (non-compressed) get-texture-image functions. 1252 * \return true if any error, false if no errors. 1253 */ 1254static bool 1255getteximage_error_check(struct gl_context *ctx, 1256 struct gl_texture_object *texObj, 1257 GLenum target, GLint level, 1258 GLsizei width, GLsizei height, GLsizei depth, 1259 GLenum format, GLenum type, GLsizei bufSize, 1260 GLvoid *pixels, const char *caller) 1261{ 1262 struct gl_texture_image *texImage; 1263 1264 assert(texObj); 1265 1266 if (common_error_check(ctx, texObj, target, level, width, height, depth, 1267 format, type, bufSize, pixels, caller)) { 1268 return true; 1269 } 1270 1271 if (width == 0 || height == 0 || depth == 0) { 1272 /* Not an error, but nothing to do. Return 'true' so that the 1273 * caller simply returns. 1274 */ 1275 return true; 1276 } 1277 1278 if (pbo_error_check(ctx, target, width, height, depth, 1279 format, type, bufSize, pixels, caller)) { 1280 return true; 1281 } 1282 1283 texImage = select_tex_image(texObj, target, level, 0); 1284 if (teximage_error_check(ctx, texImage, format, caller)) { 1285 return true; 1286 } 1287 1288 return false; 1289} 1290 1291 1292/** 1293 * Do error checking for all (non-compressed) get-texture-image functions. 1294 * \return true if any error, false if no errors. 1295 */ 1296static bool 1297gettexsubimage_error_check(struct gl_context *ctx, 1298 struct gl_texture_object *texObj, 1299 GLenum target, GLint level, 1300 GLint xoffset, GLint yoffset, GLint zoffset, 1301 GLsizei width, GLsizei height, GLsizei depth, 1302 GLenum format, GLenum type, GLsizei bufSize, 1303 GLvoid *pixels, const char *caller) 1304{ 1305 struct gl_texture_image *texImage; 1306 1307 assert(texObj); 1308 1309 if (common_error_check(ctx, texObj, target, level, width, height, depth, 1310 format, type, bufSize, pixels, caller)) { 1311 return true; 1312 } 1313 1314 if (dimensions_error_check(ctx, texObj, target, level, 1315 xoffset, yoffset, zoffset, 1316 width, height, depth, caller)) { 1317 return true; 1318 } 1319 1320 if (pbo_error_check(ctx, target, width, height, depth, 1321 format, type, bufSize, pixels, caller)) { 1322 return true; 1323 } 1324 1325 texImage = select_tex_image(texObj, target, level, zoffset); 1326 if (teximage_error_check(ctx, texImage, format, caller)) { 1327 return true; 1328 } 1329 1330 return false; 1331} 1332 1333 1334/** 1335 * Return the width, height and depth of a texture image. 1336 * This function must be resilient to bad parameter values since 1337 * this is called before full error checking. 1338 */ 1339static void 1340get_texture_image_dims(const struct gl_texture_object *texObj, 1341 GLenum target, GLint level, 1342 GLsizei *width, GLsizei *height, GLsizei *depth) 1343{ 1344 const struct gl_texture_image *texImage = NULL; 1345 1346 if (level >= 0 && level < MAX_TEXTURE_LEVELS) { 1347 texImage = _mesa_select_tex_image(texObj, target, level); 1348 } 1349 1350 if (texImage) { 1351 *width = texImage->Width; 1352 *height = texImage->Height; 1353 if (target == GL_TEXTURE_CUBE_MAP) { 1354 *depth = 6; 1355 } 1356 else { 1357 *depth = texImage->Depth; 1358 } 1359 } 1360 else { 1361 *width = *height = *depth = 0; 1362 } 1363} 1364 1365 1366/** 1367 * Common code for all (uncompressed) get-texture-image functions. 1368 * \param texObj the texture object (should not be null) 1369 * \param target user-provided target, or 0 for DSA 1370 * \param level image level. 1371 * \param format pixel data format for returned image. 1372 * \param type pixel data type for returned image. 1373 * \param bufSize size of the pixels data buffer. 1374 * \param pixels returned pixel data. 1375 * \param caller name of calling function 1376 */ 1377static void 1378get_texture_image(struct gl_context *ctx, 1379 struct gl_texture_object *texObj, 1380 GLenum target, GLint level, 1381 GLint xoffset, GLint yoffset, GLint zoffset, 1382 GLsizei width, GLsizei height, GLint depth, 1383 GLenum format, GLenum type, 1384 GLvoid *pixels, const char *caller) 1385{ 1386 struct gl_texture_image *texImage; 1387 unsigned firstFace, numFaces, i; 1388 GLint imageStride; 1389 1390 FLUSH_VERTICES(ctx, 0); 1391 1392 texImage = select_tex_image(texObj, target, level, zoffset); 1393 assert(texImage); /* should have been error checked already */ 1394 1395 if (_mesa_is_zero_size_texture(texImage)) { 1396 /* no image data to return */ 1397 return; 1398 } 1399 1400 if (MESA_VERBOSE & (VERBOSE_API | VERBOSE_TEXTURE)) { 1401 _mesa_debug(ctx, "%s(tex %u) format = %s, w=%d, h=%d," 1402 " dstFmt=0x%x, dstType=0x%x\n", 1403 caller, texObj->Name, 1404 _mesa_get_format_name(texImage->TexFormat), 1405 texImage->Width, texImage->Height, 1406 format, type); 1407 } 1408 1409 if (target == GL_TEXTURE_CUBE_MAP) { 1410 /* Compute stride between cube faces */ 1411 imageStride = _mesa_image_image_stride(&ctx->Pack, width, height, 1412 format, type); 1413 firstFace = zoffset; 1414 numFaces = depth; 1415 zoffset = 0; 1416 depth = 1; 1417 } 1418 else { 1419 imageStride = 0; 1420 firstFace = _mesa_tex_target_to_face(target); 1421 numFaces = 1; 1422 } 1423 1424 _mesa_lock_texture(ctx, texObj); 1425 1426 for (i = 0; i < numFaces; i++) { 1427 texImage = texObj->Image[firstFace + i][level]; 1428 assert(texImage); 1429 1430 ctx->Driver.GetTexSubImage(ctx, xoffset, yoffset, zoffset, 1431 width, height, depth, 1432 format, type, pixels, texImage); 1433 1434 /* next cube face */ 1435 pixels = (GLubyte *) pixels + imageStride; 1436 } 1437 1438 _mesa_unlock_texture(ctx, texObj); 1439} 1440 1441 1442void GLAPIENTRY 1443_mesa_GetnTexImageARB(GLenum target, GLint level, GLenum format, GLenum type, 1444 GLsizei bufSize, GLvoid *pixels) 1445{ 1446 GET_CURRENT_CONTEXT(ctx); 1447 static const char *caller = "glGetnTexImageARB"; 1448 GLsizei width, height, depth; 1449 struct gl_texture_object *texObj; 1450 1451 if (!legal_getteximage_target(ctx, target, false)) { 1452 _mesa_error(ctx, GL_INVALID_ENUM, "%s", caller); 1453 return; 1454 } 1455 1456 texObj = _mesa_get_current_tex_object(ctx, target); 1457 assert(texObj); 1458 1459 get_texture_image_dims(texObj, target, level, &width, &height, &depth); 1460 1461 if (getteximage_error_check(ctx, texObj, target, level, 1462 width, height, depth, 1463 format, type, bufSize, pixels, caller)) { 1464 return; 1465 } 1466 1467 get_texture_image(ctx, texObj, target, level, 1468 0, 0, 0, width, height, depth, 1469 format, type, pixels, caller); 1470} 1471 1472 1473void GLAPIENTRY 1474_mesa_GetTexImage(GLenum target, GLint level, GLenum format, GLenum type, 1475 GLvoid *pixels ) 1476{ 1477 GET_CURRENT_CONTEXT(ctx); 1478 static const char *caller = "glGetTexImage"; 1479 GLsizei width, height, depth; 1480 struct gl_texture_object *texObj; 1481 1482 if (!legal_getteximage_target(ctx, target, false)) { 1483 _mesa_error(ctx, GL_INVALID_ENUM, "%s", caller); 1484 return; 1485 } 1486 1487 texObj = _mesa_get_current_tex_object(ctx, target); 1488 assert(texObj); 1489 1490 get_texture_image_dims(texObj, target, level, &width, &height, &depth); 1491 1492 if (getteximage_error_check(ctx, texObj, target, level, 1493 width, height, depth, 1494 format, type, INT_MAX, pixels, caller)) { 1495 return; 1496 } 1497 1498 get_texture_image(ctx, texObj, target, level, 1499 0, 0, 0, width, height, depth, 1500 format, type, pixels, caller); 1501} 1502 1503 1504void GLAPIENTRY 1505_mesa_GetTextureImage(GLuint texture, GLint level, GLenum format, GLenum type, 1506 GLsizei bufSize, GLvoid *pixels) 1507{ 1508 GET_CURRENT_CONTEXT(ctx); 1509 GLsizei width, height, depth; 1510 static const char *caller = "glGetTextureImage"; 1511 struct gl_texture_object *texObj = 1512 _mesa_lookup_texture_err(ctx, texture, caller); 1513 1514 if (!texObj) { 1515 return; 1516 } 1517 1518 if (!legal_getteximage_target(ctx, texObj->Target, true)) { 1519 _mesa_error(ctx, GL_INVALID_OPERATION, "%s", caller); 1520 return; 1521 } 1522 1523 get_texture_image_dims(texObj, texObj->Target, level, 1524 &width, &height, &depth); 1525 1526 if (getteximage_error_check(ctx, texObj, texObj->Target, level, 1527 width, height, depth, 1528 format, type, bufSize, pixels, caller)) { 1529 return; 1530 } 1531 1532 get_texture_image(ctx, texObj, texObj->Target, level, 1533 0, 0, 0, width, height, depth, 1534 format, type, pixels, caller); 1535} 1536 1537 1538void GLAPIENTRY 1539_mesa_GetTextureSubImage(GLuint texture, GLint level, 1540 GLint xoffset, GLint yoffset, GLint zoffset, 1541 GLsizei width, GLsizei height, GLsizei depth, 1542 GLenum format, GLenum type, GLsizei bufSize, 1543 void *pixels) 1544{ 1545 GET_CURRENT_CONTEXT(ctx); 1546 static const char *caller = "glGetTextureSubImage"; 1547 struct gl_texture_object *texObj = 1548 _mesa_lookup_texture_err(ctx, texture, caller); 1549 1550 if (!texObj) { 1551 return; 1552 } 1553 1554 if (!legal_getteximage_target(ctx, texObj->Target, true)) { 1555 _mesa_error(ctx, GL_INVALID_OPERATION, 1556 "%s(buffer/multisample texture)", caller); 1557 return; 1558 } 1559 1560 if (gettexsubimage_error_check(ctx, texObj, texObj->Target, level, 1561 xoffset, yoffset, zoffset, 1562 width, height, depth, 1563 format, type, bufSize, pixels, caller)) { 1564 return; 1565 } 1566 1567 get_texture_image(ctx, texObj, texObj->Target, level, 1568 xoffset, yoffset, zoffset, width, height, depth, 1569 format, type, pixels, caller); 1570} 1571 1572 1573 1574/** 1575 * Compute the number of bytes which will be written when retrieving 1576 * a sub-region of a compressed texture. 1577 */ 1578static GLsizei 1579packed_compressed_size(GLuint dimensions, mesa_format format, 1580 GLsizei width, GLsizei height, GLsizei depth, 1581 const struct gl_pixelstore_attrib *packing) 1582{ 1583 struct compressed_pixelstore st; 1584 GLsizei totalBytes; 1585 1586 _mesa_compute_compressed_pixelstore(dimensions, format, 1587 width, height, depth, 1588 packing, &st); 1589 totalBytes = 1590 (st.CopySlices - 1) * st.TotalRowsPerSlice * st.TotalBytesPerRow + 1591 st.SkipBytes + 1592 (st.CopyRowsPerSlice - 1) * st.TotalBytesPerRow + 1593 st.CopyBytesPerRow; 1594 1595 return totalBytes; 1596} 1597 1598 1599/** 1600 * Do error checking for getting compressed texture images. 1601 * \return true if any error, false if no errors. 1602 */ 1603static bool 1604getcompressedteximage_error_check(struct gl_context *ctx, 1605 struct gl_texture_object *texObj, 1606 GLenum target, GLint level, 1607 GLint xoffset, GLint yoffset, GLint zoffset, 1608 GLsizei width, GLsizei height, GLsizei depth, 1609 GLsizei bufSize, GLvoid *pixels, 1610 const char *caller) 1611{ 1612 struct gl_texture_image *texImage; 1613 GLint maxLevels; 1614 GLsizei totalBytes; 1615 GLuint dimensions; 1616 1617 assert(texObj); 1618 1619 if (texObj->Target == 0) { 1620 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid texture)", caller); 1621 return true; 1622 } 1623 1624 maxLevels = _mesa_max_texture_levels(ctx, target); 1625 if (level < 0 || level >= maxLevels) { 1626 _mesa_error(ctx, GL_INVALID_VALUE, 1627 "%s(bad level = %d)", caller, level); 1628 return true; 1629 } 1630 1631 if (dimensions_error_check(ctx, texObj, target, level, 1632 xoffset, yoffset, zoffset, 1633 width, height, depth, caller)) { 1634 return true; 1635 } 1636 1637 texImage = select_tex_image(texObj, target, level, zoffset); 1638 assert(texImage); 1639 1640 if (!_mesa_is_format_compressed(texImage->TexFormat)) { 1641 _mesa_error(ctx, GL_INVALID_OPERATION, 1642 "%s(texture is not compressed)", caller); 1643 return true; 1644 } 1645 1646 /* Check for invalid pixel storage modes */ 1647 dimensions = _mesa_get_texture_dimensions(texObj->Target); 1648 if (!_mesa_compressed_pixel_storage_error_check(ctx, dimensions, 1649 &ctx->Pack, 1650 caller)) { 1651 return true; 1652 } 1653 1654 /* Compute number of bytes that may be touched in the dest buffer */ 1655 totalBytes = packed_compressed_size(dimensions, texImage->TexFormat, 1656 width, height, depth, 1657 &ctx->Pack); 1658 1659 /* Do dest buffer bounds checking */ 1660 if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { 1661 /* do bounds checking on PBO write */ 1662 if ((GLubyte *) pixels + totalBytes > 1663 (GLubyte *) ctx->Pack.BufferObj->Size) { 1664 _mesa_error(ctx, GL_INVALID_OPERATION, 1665 "%s(out of bounds PBO access)", caller); 1666 return true; 1667 } 1668 1669 /* make sure PBO is not mapped */ 1670 if (_mesa_check_disallowed_mapping(ctx->Pack.BufferObj)) { 1671 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(PBO is mapped)", caller); 1672 return true; 1673 } 1674 } 1675 else { 1676 /* do bounds checking on writing to client memory */ 1677 if (totalBytes > bufSize) { 1678 _mesa_error(ctx, GL_INVALID_OPERATION, 1679 "%s(out of bounds access: bufSize (%d) is too small)", 1680 caller, bufSize); 1681 return true; 1682 } 1683 } 1684 1685 if (!_mesa_is_bufferobj(ctx->Pack.BufferObj) && !pixels) { 1686 /* not an error, but do nothing */ 1687 return true; 1688 } 1689 1690 return false; 1691} 1692 1693 1694/** 1695 * Common helper for all glGetCompressed-teximage functions. 1696 */ 1697static void 1698get_compressed_texture_image(struct gl_context *ctx, 1699 struct gl_texture_object *texObj, 1700 GLenum target, GLint level, 1701 GLint xoffset, GLint yoffset, GLint zoffset, 1702 GLsizei width, GLsizei height, GLint depth, 1703 GLvoid *pixels, 1704 const char *caller) 1705{ 1706 struct gl_texture_image *texImage; 1707 unsigned firstFace, numFaces, i, imageStride; 1708 1709 FLUSH_VERTICES(ctx, 0); 1710 1711 texImage = select_tex_image(texObj, target, level, zoffset); 1712 assert(texImage); /* should have been error checked already */ 1713 1714 if (_mesa_is_zero_size_texture(texImage)) 1715 return; 1716 1717 if (MESA_VERBOSE & (VERBOSE_API | VERBOSE_TEXTURE)) { 1718 _mesa_debug(ctx, 1719 "%s(tex %u) format = %s, w=%d, h=%d\n", 1720 caller, texObj->Name, 1721 _mesa_get_format_name(texImage->TexFormat), 1722 texImage->Width, texImage->Height); 1723 } 1724 1725 if (target == GL_TEXTURE_CUBE_MAP) { 1726 struct compressed_pixelstore store; 1727 1728 /* Compute image stride between cube faces */ 1729 _mesa_compute_compressed_pixelstore(2, texImage->TexFormat, 1730 width, height, depth, 1731 &ctx->Pack, &store); 1732 imageStride = store.TotalBytesPerRow * store.TotalRowsPerSlice; 1733 1734 firstFace = zoffset; 1735 numFaces = depth; 1736 zoffset = 0; 1737 depth = 1; 1738 } 1739 else { 1740 imageStride = 0; 1741 firstFace = _mesa_tex_target_to_face(target); 1742 numFaces = 1; 1743 } 1744 1745 _mesa_lock_texture(ctx, texObj); 1746 1747 for (i = 0; i < numFaces; i++) { 1748 texImage = texObj->Image[firstFace + i][level]; 1749 assert(texImage); 1750 1751 get_compressed_texsubimage_sw(ctx, texImage, 1752 xoffset, yoffset, zoffset, 1753 width, height, depth, pixels); 1754 1755 /* next cube face */ 1756 pixels = (GLubyte *) pixels + imageStride; 1757 } 1758 1759 _mesa_unlock_texture(ctx, texObj); 1760} 1761 1762 1763void GLAPIENTRY 1764_mesa_GetnCompressedTexImageARB(GLenum target, GLint level, GLsizei bufSize, 1765 GLvoid *pixels) 1766{ 1767 GET_CURRENT_CONTEXT(ctx); 1768 static const char *caller = "glGetnCompressedTexImageARB"; 1769 GLsizei width, height, depth; 1770 struct gl_texture_object *texObj; 1771 1772 if (!legal_getteximage_target(ctx, target, false)) { 1773 _mesa_error(ctx, GL_INVALID_ENUM, "%s", caller); 1774 return; 1775 } 1776 1777 texObj = _mesa_get_current_tex_object(ctx, target); 1778 assert(texObj); 1779 1780 get_texture_image_dims(texObj, target, level, &width, &height, &depth); 1781 1782 if (getcompressedteximage_error_check(ctx, texObj, target, level, 1783 0, 0, 0, width, height, depth, 1784 INT_MAX, pixels, caller)) { 1785 return; 1786 } 1787 1788 get_compressed_texture_image(ctx, texObj, target, level, 1789 0, 0, 0, width, height, depth, 1790 pixels, caller); 1791} 1792 1793 1794void GLAPIENTRY 1795_mesa_GetCompressedTexImage(GLenum target, GLint level, GLvoid *pixels) 1796{ 1797 GET_CURRENT_CONTEXT(ctx); 1798 static const char *caller = "glGetCompressedTexImage"; 1799 GLsizei width, height, depth; 1800 struct gl_texture_object *texObj; 1801 1802 if (!legal_getteximage_target(ctx, target, false)) { 1803 _mesa_error(ctx, GL_INVALID_ENUM, "%s", caller); 1804 return; 1805 } 1806 1807 texObj = _mesa_get_current_tex_object(ctx, target); 1808 assert(texObj); 1809 1810 get_texture_image_dims(texObj, target, level, 1811 &width, &height, &depth); 1812 1813 if (getcompressedteximage_error_check(ctx, texObj, target, level, 1814 0, 0, 0, width, height, depth, 1815 INT_MAX, pixels, caller)) { 1816 return; 1817 } 1818 1819 get_compressed_texture_image(ctx, texObj, target, level, 1820 0, 0, 0, width, height, depth, 1821 pixels, caller); 1822} 1823 1824 1825void GLAPIENTRY 1826_mesa_GetCompressedTextureImage(GLuint texture, GLint level, 1827 GLsizei bufSize, GLvoid *pixels) 1828{ 1829 GET_CURRENT_CONTEXT(ctx); 1830 static const char *caller = "glGetCompressedTextureImage"; 1831 GLsizei width, height, depth; 1832 struct gl_texture_object *texObj = 1833 _mesa_lookup_texture_err(ctx, texture, caller); 1834 1835 if (!texObj) { 1836 return; 1837 } 1838 1839 get_texture_image_dims(texObj, texObj->Target, level, 1840 &width, &height, &depth); 1841 1842 if (getcompressedteximage_error_check(ctx, texObj, texObj->Target, level, 1843 0, 0, 0, width, height, depth, 1844 bufSize, pixels, caller)) { 1845 return; 1846 } 1847 1848 get_compressed_texture_image(ctx, texObj, texObj->Target, level, 1849 0, 0, 0, width, height, depth, 1850 pixels, caller); 1851} 1852 1853 1854void APIENTRY 1855_mesa_GetCompressedTextureSubImage(GLuint texture, GLint level, 1856 GLint xoffset, GLint yoffset, 1857 GLint zoffset, GLsizei width, 1858 GLsizei height, GLsizei depth, 1859 GLsizei bufSize, void *pixels) 1860{ 1861 GET_CURRENT_CONTEXT(ctx); 1862 static const char *caller = "glGetCompressedTextureImage"; 1863 struct gl_texture_object *texObj = NULL; 1864 1865 texObj = _mesa_lookup_texture_err(ctx, texture, caller); 1866 if (!texObj) { 1867 return; 1868 } 1869 1870 if (getcompressedteximage_error_check(ctx, texObj, texObj->Target, level, 1871 xoffset, yoffset, zoffset, 1872 width, height, depth, 1873 bufSize, pixels, caller)) { 1874 return; 1875 } 1876 1877 get_compressed_texture_image(ctx, texObj, texObj->Target, level, 1878 xoffset, yoffset, zoffset, 1879 width, height, depth, 1880 pixels, caller); 1881} 1882