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