texgetimage.c revision ce64b6d612dc167c4b8c00594d87517d6ed0e5fa
1/* 2 * Mesa 3-D graphics library 3 * Version: 7.7 4 * 5 * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. 6 * Copyright (c) 2009 VMware, Inc. 7 * 8 * Permission is hereby granted, free of charge, to any person obtaining a 9 * copy of this software and associated documentation files (the "Software"), 10 * to deal in the Software without restriction, including without limitation 11 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 12 * and/or sell copies of the Software, and to permit persons to whom the 13 * Software is furnished to do so, subject to the following conditions: 14 * 15 * The above copyright notice and this permission notice shall be included 16 * in all copies or substantial portions of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 22 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 * CONNECTION WITH THE SOFTWARE OR THE USE OR 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 "image.h" 39#include "mfeatures.h" 40#include "mtypes.h" 41#include "pack.h" 42#include "pbo.h" 43#include "texcompress.h" 44#include "texgetimage.h" 45#include "teximage.h" 46 47 48 49/** 50 * Can the given type represent negative values? 51 */ 52static INLINE GLboolean 53type_with_negative_values(GLenum type) 54{ 55 switch (type) { 56 case GL_BYTE: 57 case GL_SHORT: 58 case GL_INT: 59 case GL_FLOAT: 60 case GL_HALF_FLOAT_ARB: 61 return GL_TRUE; 62 default: 63 return GL_FALSE; 64 } 65} 66 67 68/** 69 * glGetTexImage for depth/Z pixels. 70 */ 71static void 72get_tex_depth(struct gl_context *ctx, GLuint dimensions, 73 GLenum format, GLenum type, GLvoid *pixels, 74 const struct gl_texture_image *texImage) 75{ 76 const GLint width = texImage->Width; 77 const GLint height = texImage->Height; 78 const GLint depth = texImage->Depth; 79 GLint img, row; 80 GLfloat *depthRow = (GLfloat *) malloc(width * sizeof(GLfloat)); 81 const GLint texelSize = _mesa_get_format_bytes(texImage->TexFormat); 82 83 if (!depthRow) { 84 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage"); 85 return; 86 } 87 88 for (img = 0; img < depth; img++) { 89 for (row = 0; row < height; row++) { 90 void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels, 91 width, height, format, type, 92 img, row, 0); 93 const GLubyte *src = (GLubyte *) texImage->Data + 94 (texImage->ImageOffsets[img] + 95 texImage->RowStride * row) * texelSize; 96 97 _mesa_unpack_float_z_row(texImage->TexFormat, width, src, depthRow); 98 99 _mesa_pack_depth_span(ctx, width, dest, type, depthRow, &ctx->Pack); 100 } 101 } 102 103 free(depthRow); 104} 105 106 107/** 108 * glGetTexImage for depth/stencil pixels. 109 */ 110static void 111get_tex_depth_stencil(struct gl_context *ctx, GLuint dimensions, 112 GLenum format, GLenum type, GLvoid *pixels, 113 const struct gl_texture_image *texImage) 114{ 115 const GLint width = texImage->Width; 116 const GLint height = texImage->Height; 117 const GLint depth = texImage->Depth; 118 const GLint rowstride = texImage->RowStride; 119 const GLuint *src = (const GLuint *) texImage->Data; 120 GLint img, row; 121 122 for (img = 0; img < depth; img++) { 123 for (row = 0; row < height; row++) { 124 void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels, 125 width, height, format, type, 126 img, row, 0); 127 memcpy(dest, src, width * sizeof(GLuint)); 128 if (ctx->Pack.SwapBytes) { 129 _mesa_swap4((GLuint *) dest, width); 130 } 131 132 src += rowstride; 133 } 134 } 135} 136 137 138/** 139 * glGetTexImage for YCbCr pixels. 140 */ 141static void 142get_tex_ycbcr(struct gl_context *ctx, GLuint dimensions, 143 GLenum format, GLenum type, GLvoid *pixels, 144 const struct gl_texture_image *texImage) 145{ 146 const GLint width = texImage->Width; 147 const GLint height = texImage->Height; 148 const GLint depth = texImage->Depth; 149 const GLint rowstride = texImage->RowStride; 150 const GLushort *src = (const GLushort *) texImage->Data; 151 GLint img, row; 152 153 for (img = 0; img < depth; img++) { 154 for (row = 0; row < height; row++) { 155 void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels, 156 width, height, format, type, 157 img, row, 0); 158 memcpy(dest, src, width * sizeof(GLushort)); 159 160 /* check for byte swapping */ 161 if ((texImage->TexFormat == MESA_FORMAT_YCBCR 162 && type == GL_UNSIGNED_SHORT_8_8_REV_MESA) || 163 (texImage->TexFormat == MESA_FORMAT_YCBCR_REV 164 && type == GL_UNSIGNED_SHORT_8_8_MESA)) { 165 if (!ctx->Pack.SwapBytes) 166 _mesa_swap2((GLushort *) dest, width); 167 } 168 else if (ctx->Pack.SwapBytes) { 169 _mesa_swap2((GLushort *) dest, width); 170 } 171 172 src += rowstride; 173 } 174 } 175} 176 177 178/** 179 * glGetTexImage for color formats (RGBA, RGB, alpha, LA, etc). 180 * Compressed textures are handled here as well. 181 */ 182static void 183get_tex_rgba(struct gl_context *ctx, GLuint dimensions, 184 GLenum format, GLenum type, GLvoid *pixels, 185 struct gl_texture_image *texImage) 186{ 187 /* don't want to apply sRGB -> RGB conversion here so override the format */ 188 const gl_format texFormat = _mesa_get_srgb_format_linear(texImage->TexFormat); 189 const GLuint width = texImage->Width; 190 const GLuint height = texImage->Height; 191 const GLuint depth = texImage->Depth; 192 const GLenum dataType = _mesa_get_format_datatype(texFormat); 193 const GLenum baseFormat = _mesa_get_format_base_format(texFormat); 194 /* Normally, no pixel transfer ops are performed during glGetTexImage. 195 * The only possible exception is component clamping to [0,1]. 196 */ 197 GLbitfield transferOps = 0x0; 198 199 /* In general, clamping does not apply to glGetTexImage, except when 200 * the returned type of the image can't hold negative values. 201 */ 202 if (!type_with_negative_values(type)) { 203 /* the returned image type can't have negative values */ 204 if (dataType == GL_FLOAT || 205 dataType == GL_SIGNED_NORMALIZED || 206 format == GL_LUMINANCE || 207 format == GL_LUMINANCE_ALPHA) { 208 transferOps |= IMAGE_CLAMP_BIT; 209 } 210 } 211 212 if (_mesa_is_format_compressed(texFormat)) { 213 /* Decompress into temp buffer, then pack into user buffer */ 214 GLfloat *tempImage, *srcRow; 215 GLuint row; 216 217 tempImage = (GLfloat *) malloc(texImage->Width * texImage->Height * 218 texImage->Depth * 4 * sizeof(GLfloat)); 219 if (!tempImage) { 220 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage()"); 221 return; 222 } 223 224 _mesa_decompress_image(texFormat, texImage->Width, texImage->Height, 225 texImage->Data, texImage->RowStride, tempImage); 226 227 if (baseFormat == GL_LUMINANCE || 228 baseFormat == GL_LUMINANCE_ALPHA) { 229 /* Set green and blue to zero since the pack function here will 230 * compute L=R+G+B. 231 */ 232 GLuint i; 233 for (i = 0; i < width * height; i++) { 234 tempImage[i * 4 + GCOMP] = tempImage[i * 4 + BCOMP] = 0.0f; 235 } 236 } 237 238 srcRow = tempImage; 239 for (row = 0; row < height; row++) { 240 void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels, 241 width, height, format, type, 242 0, row, 0); 243 244 _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) srcRow, 245 format, type, dest, &ctx->Pack, transferOps); 246 srcRow += width * 4; 247 } 248 249 free(tempImage); 250 } 251 else { 252 /* No decompression needed */ 253 const GLint texelSize = _mesa_get_format_bytes(texFormat); 254 GLuint img, row; 255 GLfloat (*rgba)[4]; 256 257 rgba = (GLfloat (*)[4]) malloc(4 * width * sizeof(GLfloat)); 258 if (!rgba) { 259 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage()"); 260 return; 261 } 262 263 for (img = 0; img < depth; img++) { 264 for (row = 0; row < height; row++) { 265 void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels, 266 width, height, format, type, 267 img, row, 0); 268 const GLubyte *src = (const GLubyte *) texImage->Data + 269 (texImage->ImageOffsets[img] + 270 texImage->RowStride * row) * texelSize; 271 272 _mesa_unpack_rgba_row(texFormat, width, src, rgba); 273 274 if (texImage->_BaseFormat == GL_ALPHA) { 275 GLint col; 276 for (col = 0; col < width; col++) { 277 rgba[col][RCOMP] = 0.0F; 278 rgba[col][GCOMP] = 0.0F; 279 rgba[col][BCOMP] = 0.0F; 280 } 281 } 282 else if (texImage->_BaseFormat == GL_LUMINANCE) { 283 GLint col; 284 for (col = 0; col < width; col++) { 285 rgba[col][GCOMP] = 0.0F; 286 rgba[col][BCOMP] = 0.0F; 287 rgba[col][ACOMP] = 1.0F; 288 } 289 } 290 else if (texImage->_BaseFormat == GL_LUMINANCE_ALPHA) { 291 GLint col; 292 for (col = 0; col < width; col++) { 293 rgba[col][GCOMP] = 0.0F; 294 rgba[col][BCOMP] = 0.0F; 295 } 296 } 297 else if (texImage->_BaseFormat == GL_INTENSITY) { 298 GLint col; 299 for (col = 0; col < width; col++) { 300 rgba[col][GCOMP] = 0.0F; 301 rgba[col][BCOMP] = 0.0F; 302 rgba[col][ACOMP] = 1.0F; 303 } 304 } 305 306 _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba, 307 format, type, dest, 308 &ctx->Pack, transferOps); 309 } 310 } 311 312 free(rgba); 313 } 314} 315 316 317/** 318 * Try to do glGetTexImage() with simple memcpy(). 319 * \return GL_TRUE if done, GL_FALSE otherwise 320 */ 321static GLboolean 322get_tex_memcpy(struct gl_context *ctx, GLenum format, GLenum type, GLvoid *pixels, 323 const struct gl_texture_object *texObj, 324 const struct gl_texture_image *texImage) 325{ 326 GLboolean memCopy = GL_FALSE; 327 328 /* Texture image should have been mapped already */ 329 assert(texImage->Data); 330 331 /* 332 * Check if the src/dst formats are compatible. 333 * Also note that GL's pixel transfer ops don't apply to glGetTexImage() 334 * so we don't have to worry about those. 335 * XXX more format combinations could be supported here. 336 */ 337 if ((texObj->Target == GL_TEXTURE_1D || 338 texObj->Target == GL_TEXTURE_2D || 339 texObj->Target == GL_TEXTURE_RECTANGLE || 340 (texObj->Target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && 341 texObj->Target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z))) { 342 if ((texImage->TexFormat == MESA_FORMAT_ARGB8888 || 343 texImage->TexFormat == MESA_FORMAT_SARGB8) && 344 format == GL_BGRA && 345 (type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_INT_8_8_8_8_REV) && 346 !ctx->Pack.SwapBytes && 347 _mesa_little_endian()) { 348 memCopy = GL_TRUE; 349 } 350 else if ((texImage->TexFormat == MESA_FORMAT_AL88 || 351 texImage->TexFormat == MESA_FORMAT_SLA8) && 352 format == GL_LUMINANCE_ALPHA && 353 type == GL_UNSIGNED_BYTE && 354 !ctx->Pack.SwapBytes && 355 _mesa_little_endian()) { 356 memCopy = GL_TRUE; 357 } 358 else if ((texImage->TexFormat == MESA_FORMAT_L8 || 359 texImage->TexFormat == MESA_FORMAT_SL8) && 360 format == GL_LUMINANCE && 361 type == GL_UNSIGNED_BYTE) { 362 memCopy = GL_TRUE; 363 } 364 else if (texImage->TexFormat == MESA_FORMAT_L16 && 365 format == GL_LUMINANCE && 366 type == GL_UNSIGNED_SHORT) { 367 memCopy = GL_TRUE; 368 } 369 else if (texImage->TexFormat == MESA_FORMAT_A8 && 370 format == GL_ALPHA && 371 type == GL_UNSIGNED_BYTE) { 372 memCopy = GL_TRUE; 373 } 374 else if (texImage->TexFormat == MESA_FORMAT_A16 && 375 format == GL_ALPHA && 376 type == GL_UNSIGNED_SHORT) { 377 memCopy = GL_TRUE; 378 } 379 } 380 381 if (memCopy) { 382 const GLuint bpp = _mesa_get_format_bytes(texImage->TexFormat); 383 const GLuint bytesPerRow = texImage->Width * bpp; 384 GLubyte *dst = 385 _mesa_image_address2d(&ctx->Pack, pixels, texImage->Width, 386 texImage->Height, format, type, 0, 0); 387 const GLint dstRowStride = 388 _mesa_image_row_stride(&ctx->Pack, texImage->Width, format, type); 389 const GLubyte *src = texImage->Data; 390 const GLint srcRowStride = texImage->RowStride * bpp; 391 GLuint row; 392 393 if (bytesPerRow == dstRowStride && bytesPerRow == srcRowStride) { 394 memcpy(dst, src, bytesPerRow * texImage->Height); 395 } 396 else { 397 for (row = 0; row < texImage->Height; row++) { 398 memcpy(dst, src, bytesPerRow); 399 dst += dstRowStride; 400 src += srcRowStride; 401 } 402 } 403 } 404 405 return memCopy; 406} 407 408 409/** 410 * This is the software fallback for Driver.GetTexImage(). 411 * All error checking will have been done before this routine is called. 412 * The texture image must be mapped. 413 */ 414void 415_mesa_get_teximage(struct gl_context *ctx, GLenum target, GLint level, 416 GLenum format, GLenum type, GLvoid *pixels, 417 struct gl_texture_object *texObj, 418 struct gl_texture_image *texImage) 419{ 420 GLuint dimensions; 421 422 /* If we get here, the texture image should be mapped */ 423 assert(texImage->Data); 424 425 switch (target) { 426 case GL_TEXTURE_1D: 427 dimensions = 1; 428 break; 429 case GL_TEXTURE_3D: 430 dimensions = 3; 431 break; 432 default: 433 dimensions = 2; 434 } 435 436 if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { 437 /* Packing texture image into a PBO. 438 * Map the (potentially) VRAM-based buffer into our process space so 439 * we can write into it with the code below. 440 * A hardware driver might use a sophisticated blit to move the 441 * texture data to the PBO if the PBO is in VRAM along with the texture. 442 */ 443 GLubyte *buf = (GLubyte *) 444 ctx->Driver.MapBufferRange(ctx, 0, ctx->Pack.BufferObj->Size, 445 GL_MAP_WRITE_BIT, ctx->Pack.BufferObj); 446 if (!buf) { 447 /* out of memory or other unexpected error */ 448 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage(map PBO failed)"); 449 return; 450 } 451 /* <pixels> was an offset into the PBO. 452 * Now make it a real, client-side pointer inside the mapped region. 453 */ 454 pixels = ADD_POINTERS(buf, pixels); 455 } 456 457 if (get_tex_memcpy(ctx, format, type, pixels, texObj, texImage)) { 458 /* all done */ 459 } 460 else if (format == GL_DEPTH_COMPONENT) { 461 get_tex_depth(ctx, dimensions, format, type, pixels, texImage); 462 } 463 else if (format == GL_DEPTH_STENCIL_EXT) { 464 get_tex_depth_stencil(ctx, dimensions, format, type, pixels, texImage); 465 } 466 else if (format == GL_YCBCR_MESA) { 467 get_tex_ycbcr(ctx, dimensions, format, type, pixels, texImage); 468 } 469 else { 470 get_tex_rgba(ctx, dimensions, format, type, pixels, texImage); 471 } 472 473 if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { 474 ctx->Driver.UnmapBuffer(ctx, ctx->Pack.BufferObj); 475 } 476} 477 478 479 480/** 481 * This is the software fallback for Driver.GetCompressedTexImage(). 482 * All error checking will have been done before this routine is called. 483 */ 484void 485_mesa_get_compressed_teximage(struct gl_context *ctx, GLenum target, GLint level, 486 GLvoid *img, 487 struct gl_texture_object *texObj, 488 struct gl_texture_image *texImage) 489{ 490 const GLuint row_stride = _mesa_format_row_stride(texImage->TexFormat, 491 texImage->Width); 492 const GLuint row_stride_stored = _mesa_format_row_stride(texImage->TexFormat, 493 texImage->RowStride); 494 GLuint i; 495 496 if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { 497 /* pack texture image into a PBO */ 498 GLubyte *buf = (GLubyte *) 499 ctx->Driver.MapBufferRange(ctx, 0, ctx->Pack.BufferObj->Size, 500 GL_MAP_WRITE_BIT, ctx->Pack.BufferObj); 501 if (!buf) { 502 /* out of memory or other unexpected error */ 503 _mesa_error(ctx, GL_OUT_OF_MEMORY, 504 "glGetCompresssedTexImage(map PBO failed)"); 505 return; 506 } 507 img = ADD_POINTERS(buf, img); 508 } 509 510 /* no pixelstore or pixel transfer, but respect stride */ 511 512 if (row_stride == row_stride_stored) { 513 const GLuint size = _mesa_format_image_size(texImage->TexFormat, 514 texImage->Width, 515 texImage->Height, 516 texImage->Depth); 517 memcpy(img, texImage->Data, size); 518 } 519 else { 520 GLuint bw, bh; 521 _mesa_get_format_block_size(texImage->TexFormat, &bw, &bh); 522 for (i = 0; i < (texImage->Height + bh - 1) / bh; i++) { 523 memcpy((GLubyte *)img + i * row_stride, 524 (GLubyte *)texImage->Data + i * row_stride_stored, 525 row_stride); 526 } 527 } 528 529 if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { 530 ctx->Driver.UnmapBuffer(ctx, ctx->Pack.BufferObj); 531 } 532} 533 534 535 536/** 537 * Do error checking for a glGetTexImage() call. 538 * \return GL_TRUE if any error, GL_FALSE if no errors. 539 */ 540static GLboolean 541getteximage_error_check(struct gl_context *ctx, GLenum target, GLint level, 542 GLenum format, GLenum type, GLsizei clientMemSize, 543 GLvoid *pixels ) 544{ 545 struct gl_texture_object *texObj; 546 struct gl_texture_image *texImage; 547 const GLint maxLevels = _mesa_max_texture_levels(ctx, target); 548 const GLuint dimensions = (target == GL_TEXTURE_3D) ? 3 : 2; 549 GLenum baseFormat; 550 551 if (maxLevels == 0) { 552 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target=0x%x)", target); 553 return GL_TRUE; 554 } 555 556 if (level < 0 || level >= maxLevels) { 557 _mesa_error( ctx, GL_INVALID_VALUE, "glGetTexImage(level)" ); 558 return GL_TRUE; 559 } 560 561 if (_mesa_sizeof_packed_type(type) <= 0) { 562 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexImage(type)" ); 563 return GL_TRUE; 564 } 565 566 if (_mesa_components_in_format(format) <= 0 || 567 format == GL_STENCIL_INDEX || 568 format == GL_COLOR_INDEX) { 569 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexImage(format)" ); 570 return GL_TRUE; 571 } 572 573 if (!ctx->Extensions.ARB_depth_texture && _mesa_is_depth_format(format)) { 574 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)"); 575 return GL_TRUE; 576 } 577 578 if (!ctx->Extensions.MESA_ycbcr_texture && _mesa_is_ycbcr_format(format)) { 579 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)"); 580 return GL_TRUE; 581 } 582 583 if (!ctx->Extensions.EXT_packed_depth_stencil 584 && _mesa_is_depthstencil_format(format)) { 585 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)"); 586 return GL_TRUE; 587 } 588 589 if (!ctx->Extensions.ATI_envmap_bumpmap 590 && _mesa_is_dudv_format(format)) { 591 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)"); 592 return GL_TRUE; 593 } 594 595 texObj = _mesa_get_current_tex_object(ctx, target); 596 597 if (!texObj || _mesa_is_proxy_texture(target)) { 598 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target)"); 599 return GL_TRUE; 600 } 601 602 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 603 if (!texImage) { 604 /* out of memory */ 605 return GL_TRUE; 606 } 607 608 baseFormat = _mesa_get_format_base_format(texImage->TexFormat); 609 610 /* Make sure the requested image format is compatible with the 611 * texture's format. 612 */ 613 if (_mesa_is_color_format(format) 614 && !_mesa_is_color_format(baseFormat)) { 615 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); 616 return GL_TRUE; 617 } 618 else if (_mesa_is_depth_format(format) 619 && !_mesa_is_depth_format(baseFormat) 620 && !_mesa_is_depthstencil_format(baseFormat)) { 621 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); 622 return GL_TRUE; 623 } 624 else if (_mesa_is_ycbcr_format(format) 625 && !_mesa_is_ycbcr_format(baseFormat)) { 626 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); 627 return GL_TRUE; 628 } 629 else if (_mesa_is_depthstencil_format(format) 630 && !_mesa_is_depthstencil_format(baseFormat)) { 631 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); 632 return GL_TRUE; 633 } 634 else if (_mesa_is_dudv_format(format) 635 && !_mesa_is_dudv_format(baseFormat)) { 636 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); 637 return GL_TRUE; 638 } 639 640 if (!_mesa_validate_pbo_access(dimensions, &ctx->Pack, texImage->Width, 641 texImage->Height, texImage->Depth, 642 format, type, clientMemSize, pixels)) { 643 if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { 644 _mesa_error(ctx, GL_INVALID_OPERATION, 645 "glGetTexImage(out of bounds PBO access)"); 646 } else { 647 _mesa_error(ctx, GL_INVALID_OPERATION, 648 "glGetnTexImageARB(out of bounds access:" 649 " bufSize (%d) is too small)", clientMemSize); 650 } 651 return GL_TRUE; 652 } 653 654 if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { 655 /* PBO should not be mapped */ 656 if (_mesa_bufferobj_mapped(ctx->Pack.BufferObj)) { 657 _mesa_error(ctx, GL_INVALID_OPERATION, 658 "glGetTexImage(PBO is mapped)"); 659 return GL_TRUE; 660 } 661 } 662 663 return GL_FALSE; 664} 665 666 667 668/** 669 * Get texture image. Called by glGetTexImage. 670 * 671 * \param target texture target. 672 * \param level image level. 673 * \param format pixel data format for returned image. 674 * \param type pixel data type for returned image. 675 * \param bufSize size of the pixels data buffer. 676 * \param pixels returned pixel data. 677 */ 678void GLAPIENTRY 679_mesa_GetnTexImageARB( GLenum target, GLint level, GLenum format, 680 GLenum type, GLsizei bufSize, GLvoid *pixels ) 681{ 682 struct gl_texture_object *texObj; 683 struct gl_texture_image *texImage; 684 GET_CURRENT_CONTEXT(ctx); 685 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 686 687 if (getteximage_error_check(ctx, target, level, format, type, 688 bufSize, pixels)) { 689 return; 690 } 691 692 if (!_mesa_is_bufferobj(ctx->Pack.BufferObj) && !pixels) { 693 /* not an error, do nothing */ 694 return; 695 } 696 697 texObj = _mesa_get_current_tex_object(ctx, target); 698 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 699 700 if (MESA_VERBOSE & (VERBOSE_API | VERBOSE_TEXTURE)) { 701 _mesa_debug(ctx, "glGetTexImage(tex %u) format = %s, w=%d, h=%d," 702 " dstFmt=0x%x, dstType=0x%x\n", 703 texObj->Name, 704 _mesa_get_format_name(texImage->TexFormat), 705 texImage->Width, texImage->Height, 706 format, type); 707 } 708 709 _mesa_lock_texture(ctx, texObj); 710 { 711 ctx->Driver.GetTexImage(ctx, target, level, format, type, pixels, 712 texObj, texImage); 713 } 714 _mesa_unlock_texture(ctx, texObj); 715} 716 717 718void GLAPIENTRY 719_mesa_GetTexImage( GLenum target, GLint level, GLenum format, 720 GLenum type, GLvoid *pixels ) 721{ 722 _mesa_GetnTexImageARB(target, level, format, type, INT_MAX, pixels); 723} 724 725 726/** 727 * Do error checking for a glGetCompressedTexImage() call. 728 * \return GL_TRUE if any error, GL_FALSE if no errors. 729 */ 730static GLboolean 731getcompressedteximage_error_check(struct gl_context *ctx, GLenum target, 732 GLint level, GLsizei clientMemSize, GLvoid *img) 733{ 734 struct gl_texture_object *texObj; 735 struct gl_texture_image *texImage; 736 const GLint maxLevels = _mesa_max_texture_levels(ctx, target); 737 GLuint compressedSize; 738 739 if (maxLevels == 0) { 740 _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImage(target=0x%x)", 741 target); 742 return GL_TRUE; 743 } 744 745 if (level < 0 || level >= maxLevels) { 746 _mesa_error(ctx, GL_INVALID_VALUE, 747 "glGetCompressedTexImageARB(bad level = %d)", level); 748 return GL_TRUE; 749 } 750 751 if (_mesa_is_proxy_texture(target)) { 752 _mesa_error(ctx, GL_INVALID_ENUM, 753 "glGetCompressedTexImageARB(bad target = %s)", 754 _mesa_lookup_enum_by_nr(target)); 755 return GL_TRUE; 756 } 757 758 texObj = _mesa_get_current_tex_object(ctx, target); 759 if (!texObj) { 760 _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB(target)"); 761 return GL_TRUE; 762 } 763 764 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 765 766 if (!texImage) { 767 /* probably invalid mipmap level */ 768 _mesa_error(ctx, GL_INVALID_VALUE, 769 "glGetCompressedTexImageARB(level)"); 770 return GL_TRUE; 771 } 772 773 if (!_mesa_is_format_compressed(texImage->TexFormat)) { 774 _mesa_error(ctx, GL_INVALID_OPERATION, 775 "glGetCompressedTexImageARB(texture is not compressed)"); 776 return GL_TRUE; 777 } 778 779 compressedSize = _mesa_format_image_size(texImage->TexFormat, 780 texImage->Width, 781 texImage->Height, 782 texImage->Depth); 783 784 if (!_mesa_is_bufferobj(ctx->Pack.BufferObj)) { 785 /* do bounds checking on writing to client memory */ 786 if (clientMemSize < compressedSize) { 787 _mesa_error(ctx, GL_INVALID_OPERATION, 788 "glGetnCompressedTexImageARB(out of bounds access:" 789 " bufSize (%d) is too small)", clientMemSize); 790 } 791 } else { 792 /* do bounds checking on PBO write */ 793 if ((const GLubyte *) img + compressedSize > 794 (const GLubyte *) ctx->Pack.BufferObj->Size) { 795 _mesa_error(ctx, GL_INVALID_OPERATION, 796 "glGetCompressedTexImage(out of bounds PBO access)"); 797 return GL_TRUE; 798 } 799 800 /* make sure PBO is not mapped */ 801 if (_mesa_bufferobj_mapped(ctx->Pack.BufferObj)) { 802 _mesa_error(ctx, GL_INVALID_OPERATION, 803 "glGetCompressedTexImage(PBO is mapped)"); 804 return GL_TRUE; 805 } 806 } 807 808 return GL_FALSE; 809} 810 811 812void GLAPIENTRY 813_mesa_GetnCompressedTexImageARB(GLenum target, GLint level, GLsizei bufSize, 814 GLvoid *img) 815{ 816 struct gl_texture_object *texObj; 817 struct gl_texture_image *texImage; 818 GET_CURRENT_CONTEXT(ctx); 819 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 820 821 if (getcompressedteximage_error_check(ctx, target, level, bufSize, img)) { 822 return; 823 } 824 825 if (_mesa_is_bufferobj(ctx->Pack.BufferObj) && !img) { 826 /* not an error, do nothing */ 827 return; 828 } 829 830 texObj = _mesa_get_current_tex_object(ctx, target); 831 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 832 833 if (MESA_VERBOSE & (VERBOSE_API | VERBOSE_TEXTURE)) { 834 _mesa_debug(ctx, 835 "glGetCompressedTexImage(tex %u) format = %s, w=%d, h=%d\n", 836 texObj->Name, 837 _mesa_get_format_name(texImage->TexFormat), 838 texImage->Width, texImage->Height); 839 } 840 841 _mesa_lock_texture(ctx, texObj); 842 { 843 ctx->Driver.GetCompressedTexImage(ctx, target, level, img, 844 texObj, texImage); 845 } 846 _mesa_unlock_texture(ctx, texObj); 847} 848 849void GLAPIENTRY 850_mesa_GetCompressedTexImageARB(GLenum target, GLint level, GLvoid *img) 851{ 852 _mesa_GetnCompressedTexImageARB(target, level, INT_MAX, img); 853} 854