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