texgetimage.c revision 81a4d34f07d95e6a4bf6ab105efbee4fed116e55
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 "image.h" 37#include "texcompress.h" 38#include "texformat.h" 39#include "texgetimage.h" 40#include "teximage.h" 41#include "texstate.h" 42 43 44 45#if FEATURE_EXT_texture_sRGB 46 47/** 48 * Test if given texture image is an sRGB format. 49 */ 50static GLboolean 51is_srgb_teximage(const struct gl_texture_image *texImage) 52{ 53 switch (texImage->TexFormat->MesaFormat) { 54 case MESA_FORMAT_SRGB8: 55 case MESA_FORMAT_SRGBA8: 56 case MESA_FORMAT_SARGB8: 57 case MESA_FORMAT_SL8: 58 case MESA_FORMAT_SLA8: 59 case MESA_FORMAT_SRGB_DXT1: 60 case MESA_FORMAT_SRGBA_DXT1: 61 case MESA_FORMAT_SRGBA_DXT3: 62 case MESA_FORMAT_SRGBA_DXT5: 63 return GL_TRUE; 64 default: 65 return GL_FALSE; 66 } 67} 68 69 70/** 71 * Convert a float value from linear space to a 72 * non-linear sRGB value in [0, 255]. 73 * Not terribly efficient. 74 */ 75static INLINE GLfloat 76linear_to_nonlinear(GLfloat cl) 77{ 78 /* can't have values outside [0, 1] */ 79 GLfloat cs; 80 if (cl < 0.0031308f) { 81 cs = 12.92f * cl; 82 } 83 else { 84 cs = (GLfloat)(1.055 * _mesa_pow(cl, 0.41666) - 0.055); 85 } 86 return cs; 87} 88 89#endif /* FEATURE_EXT_texture_sRGB */ 90 91 92/** 93 * Can the given type represent negative values? 94 */ 95static INLINE GLboolean 96type_with_negative_values(GLenum type) 97{ 98 switch (type) { 99 case GL_BYTE: 100 case GL_SHORT: 101 case GL_INT: 102 case GL_FLOAT: 103 case GL_HALF_FLOAT_ARB: 104 return GL_TRUE; 105 default: 106 return GL_FALSE; 107 } 108} 109 110 111/** 112 * This is the software fallback for Driver.GetTexImage(). 113 * All error checking will have been done before this routine is called. 114 */ 115void 116_mesa_get_teximage(GLcontext *ctx, GLenum target, GLint level, 117 GLenum format, GLenum type, GLvoid *pixels, 118 struct gl_texture_object *texObj, 119 struct gl_texture_image *texImage) 120{ 121 const GLuint dimensions = (target == GL_TEXTURE_3D) ? 3 : 2; 122 123 if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { 124 /* Packing texture image into a PBO. 125 * Map the (potentially) VRAM-based buffer into our process space so 126 * we can write into it with the code below. 127 * A hardware driver might use a sophisticated blit to move the 128 * texture data to the PBO if the PBO is in VRAM along with the texture. 129 */ 130 GLubyte *buf = (GLubyte *) 131 ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT, 132 GL_WRITE_ONLY_ARB, ctx->Pack.BufferObj); 133 if (!buf) { 134 /* out of memory or other unexpected error */ 135 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage(map PBO failed)"); 136 return; 137 138 } 139 /* <pixels> was an offset into the PBO. 140 * Now make it a real, client-side pointer inside the mapped region. 141 */ 142 pixels = ADD_POINTERS(buf, pixels); 143 } 144 else if (!pixels) { 145 /* not an error */ 146 return; 147 } 148 149 { 150 const GLint width = texImage->Width; 151 const GLint height = texImage->Height; 152 const GLint depth = texImage->Depth; 153 GLint img, row; 154 for (img = 0; img < depth; img++) { 155 for (row = 0; row < height; row++) { 156 /* compute destination address in client memory */ 157 GLvoid *dest = _mesa_image_address( dimensions, &ctx->Pack, pixels, 158 width, height, format, type, 159 img, row, 0); 160 assert(dest); 161 162 if (format == GL_COLOR_INDEX) { 163 GLuint indexRow[MAX_WIDTH]; 164 GLint col; 165 /* Can't use FetchTexel here because that returns RGBA */ 166 if (texImage->TexFormat->IndexBits == 8) { 167 const GLubyte *src = (const GLubyte *) texImage->Data; 168 src += width * (img * texImage->Height + row); 169 for (col = 0; col < width; col++) { 170 indexRow[col] = src[col]; 171 } 172 } 173 else if (texImage->TexFormat->IndexBits == 16) { 174 const GLushort *src = (const GLushort *) texImage->Data; 175 src += width * (img * texImage->Height + row); 176 for (col = 0; col < width; col++) { 177 indexRow[col] = src[col]; 178 } 179 } 180 else { 181 _mesa_problem(ctx, 182 "Color index problem in _mesa_GetTexImage"); 183 } 184 _mesa_pack_index_span(ctx, width, type, dest, 185 indexRow, &ctx->Pack, 186 0 /* no image transfer */); 187 } 188 else if (format == GL_DEPTH_COMPONENT) { 189 GLfloat depthRow[MAX_WIDTH]; 190 GLint col; 191 for (col = 0; col < width; col++) { 192 (*texImage->FetchTexelf)(texImage, col, row, img, 193 depthRow + col); 194 } 195 _mesa_pack_depth_span(ctx, width, dest, type, 196 depthRow, &ctx->Pack); 197 } 198 else if (format == GL_DEPTH_STENCIL_EXT) { 199 /* XXX Note: we're bypassing texImage->FetchTexel()! */ 200 const GLuint *src = (const GLuint *) texImage->Data; 201 src += width * row + width * height * img; 202 _mesa_memcpy(dest, src, width * sizeof(GLuint)); 203 if (ctx->Pack.SwapBytes) { 204 _mesa_swap4((GLuint *) dest, width); 205 } 206 } 207 else if (format == GL_YCBCR_MESA) { 208 /* No pixel transfer */ 209 const GLint rowstride = texImage->RowStride; 210 MEMCPY(dest, 211 (const GLushort *) texImage->Data + row * rowstride, 212 width * sizeof(GLushort)); 213 /* check for byte swapping */ 214 if ((texImage->TexFormat->MesaFormat == MESA_FORMAT_YCBCR 215 && type == GL_UNSIGNED_SHORT_8_8_REV_MESA) || 216 (texImage->TexFormat->MesaFormat == MESA_FORMAT_YCBCR_REV 217 && type == GL_UNSIGNED_SHORT_8_8_MESA)) { 218 if (!ctx->Pack.SwapBytes) 219 _mesa_swap2((GLushort *) dest, width); 220 } 221 else if (ctx->Pack.SwapBytes) { 222 _mesa_swap2((GLushort *) dest, width); 223 } 224 } 225#if FEATURE_EXT_texture_sRGB 226 else if (is_srgb_teximage(texImage)) { 227 /* special case this since need to backconvert values */ 228 /* convert row to RGBA format */ 229 GLfloat rgba[MAX_WIDTH][4]; 230 GLint col; 231 GLbitfield transferOps = 0x0; 232 233 for (col = 0; col < width; col++) { 234 (*texImage->FetchTexelf)(texImage, col, row, img, rgba[col]); 235 if (texImage->_BaseFormat == GL_LUMINANCE) { 236 rgba[col][RCOMP] = linear_to_nonlinear(rgba[col][RCOMP]); 237 rgba[col][GCOMP] = 0.0; 238 rgba[col][BCOMP] = 0.0; 239 } 240 else if (texImage->_BaseFormat == GL_LUMINANCE_ALPHA) { 241 rgba[col][RCOMP] = linear_to_nonlinear(rgba[col][RCOMP]); 242 rgba[col][GCOMP] = 0.0; 243 rgba[col][BCOMP] = 0.0; 244 } 245 else if (texImage->_BaseFormat == GL_RGB || 246 texImage->_BaseFormat == GL_RGBA) { 247 rgba[col][RCOMP] = linear_to_nonlinear(rgba[col][RCOMP]); 248 rgba[col][GCOMP] = linear_to_nonlinear(rgba[col][GCOMP]); 249 rgba[col][BCOMP] = linear_to_nonlinear(rgba[col][BCOMP]); 250 } 251 } 252 _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba, 253 format, type, dest, 254 &ctx->Pack, transferOps); 255 } 256#endif /* FEATURE_EXT_texture_sRGB */ 257 else { 258 /* general case: convert row to RGBA format */ 259 GLfloat rgba[MAX_WIDTH][4]; 260 GLint col; 261 GLbitfield transferOps = 0x0; 262 263 /* clamp does not apply to GetTexImage (final conversion)? 264 * Looks like we need clamp though when going from format 265 * containing negative values to unsigned format. 266 */ 267 if (format == GL_LUMINANCE || format == GL_LUMINANCE_ALPHA) 268 transferOps |= IMAGE_CLAMP_BIT; 269 else if (!type_with_negative_values(type) && 270 (texImage->TexFormat->DataType == GL_FLOAT || 271 texImage->TexFormat->DataType == GL_SIGNED_NORMALIZED)) 272 transferOps |= IMAGE_CLAMP_BIT; 273 274 for (col = 0; col < width; col++) { 275 (*texImage->FetchTexelf)(texImage, col, row, img, rgba[col]); 276 if (texImage->_BaseFormat == GL_ALPHA) { 277 rgba[col][RCOMP] = 0.0; 278 rgba[col][GCOMP] = 0.0; 279 rgba[col][BCOMP] = 0.0; 280 } 281 else if (texImage->_BaseFormat == GL_LUMINANCE) { 282 rgba[col][GCOMP] = 0.0; 283 rgba[col][BCOMP] = 0.0; 284 rgba[col][ACOMP] = 1.0; 285 } 286 else if (texImage->_BaseFormat == GL_LUMINANCE_ALPHA) { 287 rgba[col][GCOMP] = 0.0; 288 rgba[col][BCOMP] = 0.0; 289 } 290 else if (texImage->_BaseFormat == GL_INTENSITY) { 291 rgba[col][GCOMP] = 0.0; 292 rgba[col][BCOMP] = 0.0; 293 rgba[col][ACOMP] = 1.0; 294 } 295 } 296 _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba, 297 format, type, dest, 298 &ctx->Pack, transferOps); 299 } /* format */ 300 } /* row */ 301 } /* img */ 302 } 303 304 if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { 305 ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT, 306 ctx->Pack.BufferObj); 307 } 308} 309 310 311 312/** 313 * This is the software fallback for Driver.GetCompressedTexImage(). 314 * All error checking will have been done before this routine is called. 315 */ 316void 317_mesa_get_compressed_teximage(GLcontext *ctx, GLenum target, GLint level, 318 GLvoid *img, 319 struct gl_texture_object *texObj, 320 struct gl_texture_image *texImage) 321{ 322 GLuint size; 323 324 if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { 325 /* pack texture image into a PBO */ 326 GLubyte *buf = (GLubyte *) 327 ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT, 328 GL_WRITE_ONLY_ARB, ctx->Pack.BufferObj); 329 if (!buf) { 330 /* out of memory or other unexpected error */ 331 _mesa_error(ctx, GL_OUT_OF_MEMORY, 332 "glGetCompresssedTexImage(map PBO failed)"); 333 return; 334 } 335 img = ADD_POINTERS(buf, img); 336 } 337 else if (!img) { 338 /* not an error */ 339 return; 340 } 341 342 /* don't use texImage->CompressedSize since that may be padded out */ 343 size = _mesa_compressed_texture_size(ctx, texImage->Width, texImage->Height, 344 texImage->Depth, 345 texImage->TexFormat->MesaFormat); 346 347 /* just memcpy, no pixelstore or pixel transfer */ 348 _mesa_memcpy(img, texImage->Data, size); 349 350 if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { 351 ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT, 352 ctx->Pack.BufferObj); 353 } 354} 355 356 357 358/** 359 * Do error checking for a glGetTexImage() call. 360 * \return GL_TRUE if any error, GL_FALSE if no errors. 361 */ 362static GLboolean 363getteximage_error_check(GLcontext *ctx, GLenum target, GLint level, 364 GLenum format, GLenum type, GLvoid *pixels ) 365{ 366 const struct gl_texture_unit *texUnit; 367 struct gl_texture_object *texObj; 368 struct gl_texture_image *texImage; 369 const GLuint maxLevels = _mesa_max_texture_levels(ctx, target); 370 371 if (maxLevels == 0) { 372 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target=0x%x)", target); 373 return GL_TRUE; 374 } 375 376 if (level < 0 || level >= maxLevels) { 377 _mesa_error( ctx, GL_INVALID_VALUE, "glGetTexImage(level)" ); 378 return GL_TRUE; 379 } 380 381 if (_mesa_sizeof_packed_type(type) <= 0) { 382 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexImage(type)" ); 383 return GL_TRUE; 384 } 385 386 if (_mesa_components_in_format(format) <= 0 || 387 format == GL_STENCIL_INDEX) { 388 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexImage(format)" ); 389 return GL_TRUE; 390 } 391 392 if (!ctx->Extensions.EXT_paletted_texture && _mesa_is_index_format(format)) { 393 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)"); 394 return GL_TRUE; 395 } 396 397 if (!ctx->Extensions.ARB_depth_texture && _mesa_is_depth_format(format)) { 398 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)"); 399 return GL_TRUE; 400 } 401 402 if (!ctx->Extensions.MESA_ycbcr_texture && _mesa_is_ycbcr_format(format)) { 403 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)"); 404 return GL_TRUE; 405 } 406 407 if (!ctx->Extensions.EXT_packed_depth_stencil 408 && _mesa_is_depthstencil_format(format)) { 409 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)"); 410 return GL_TRUE; 411 } 412 413 if (!ctx->Extensions.ATI_envmap_bumpmap 414 && _mesa_is_dudv_format(format)) { 415 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)"); 416 return GL_TRUE; 417 } 418 419 texUnit = _mesa_get_current_tex_unit(ctx); 420 texObj = _mesa_select_tex_object(ctx, texUnit, target); 421 422 if (!texObj || _mesa_is_proxy_texture(target)) { 423 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target)"); 424 return GL_TRUE; 425 } 426 427 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 428 if (!texImage) { 429 /* out of memory */ 430 return GL_TRUE; 431 } 432 433 /* Make sure the requested image format is compatible with the 434 * texture's format. Note that a color index texture can be converted 435 * to RGBA so that combo is allowed. 436 */ 437 if (_mesa_is_color_format(format) 438 && !_mesa_is_color_format(texImage->TexFormat->BaseFormat) 439 && !_mesa_is_index_format(texImage->TexFormat->BaseFormat)) { 440 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); 441 return GL_TRUE; 442 } 443 else if (_mesa_is_index_format(format) 444 && !_mesa_is_index_format(texImage->TexFormat->BaseFormat)) { 445 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); 446 return GL_TRUE; 447 } 448 else if (_mesa_is_depth_format(format) 449 && !_mesa_is_depth_format(texImage->TexFormat->BaseFormat) 450 && !_mesa_is_depthstencil_format(texImage->TexFormat->BaseFormat)) { 451 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); 452 return GL_TRUE; 453 } 454 else if (_mesa_is_ycbcr_format(format) 455 && !_mesa_is_ycbcr_format(texImage->TexFormat->BaseFormat)) { 456 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); 457 return GL_TRUE; 458 } 459 else if (_mesa_is_depthstencil_format(format) 460 && !_mesa_is_depthstencil_format(texImage->TexFormat->BaseFormat)) { 461 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); 462 return GL_TRUE; 463 } 464 else if (_mesa_is_dudv_format(format) 465 && !_mesa_is_dudv_format(texImage->TexFormat->BaseFormat)) { 466 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); 467 return GL_TRUE; 468 } 469 470 if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { 471 /* packing texture image into a PBO */ 472 const GLuint dimensions = (target == GL_TEXTURE_3D) ? 3 : 2; 473 if (!_mesa_validate_pbo_access(dimensions, &ctx->Pack, texImage->Width, 474 texImage->Height, texImage->Depth, 475 format, type, pixels)) { 476 _mesa_error(ctx, GL_INVALID_OPERATION, 477 "glGetTexImage(out of bounds PBO write)"); 478 return GL_TRUE; 479 } 480 481 /* PBO should not be mapped */ 482 if (_mesa_bufferobj_mapped(ctx->Pack.BufferObj)) { 483 _mesa_error(ctx, GL_INVALID_OPERATION, 484 "glGetTexImage(PBO is mapped)"); 485 return GL_TRUE; 486 } 487 } 488 489 return GL_FALSE; 490} 491 492 493 494/** 495 * Get texture image. Called by glGetTexImage. 496 * 497 * \param target texture target. 498 * \param level image level. 499 * \param format pixel data format for returned image. 500 * \param type pixel data type for returned image. 501 * \param pixels returned pixel data. 502 */ 503void GLAPIENTRY 504_mesa_GetTexImage( GLenum target, GLint level, GLenum format, 505 GLenum type, GLvoid *pixels ) 506{ 507 const struct gl_texture_unit *texUnit; 508 struct gl_texture_object *texObj; 509 GET_CURRENT_CONTEXT(ctx); 510 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 511 512 if (getteximage_error_check(ctx, target, level, format, type, pixels)) { 513 return; 514 } 515 516 texUnit = _mesa_get_current_tex_unit(ctx); 517 texObj = _mesa_select_tex_object(ctx, texUnit, target); 518 519 if (MESA_VERBOSE & (VERBOSE_API | VERBOSE_TEXTURE)) { 520 struct gl_texture_image *texImage = 521 _mesa_select_tex_image(ctx, texObj, target, level); 522 _mesa_debug(ctx, "glGetTexImage(tex %u) format = %d, w=%d, h=%d," 523 " dstFmt=0x%x, dstType=0x%x\n", 524 texObj->Name, 525 texImage->TexFormat->MesaFormat, 526 texImage->Width, texImage->Height, 527 format, type); 528 } 529 530 _mesa_lock_texture(ctx, texObj); 531 { 532 struct gl_texture_image *texImage = 533 _mesa_select_tex_image(ctx, texObj, target, level); 534 535 /* typically, this will call _mesa_get_teximage() */ 536 ctx->Driver.GetTexImage(ctx, target, level, format, type, pixels, 537 texObj, texImage); 538 } 539 _mesa_unlock_texture(ctx, texObj); 540} 541 542 543 544/** 545 * Do error checking for a glGetCompressedTexImage() call. 546 * \return GL_TRUE if any error, GL_FALSE if no errors. 547 */ 548static GLboolean 549getcompressedteximage_error_check(GLcontext *ctx, GLenum target, GLint level, 550 GLvoid *img) 551{ 552 const struct gl_texture_unit *texUnit; 553 struct gl_texture_object *texObj; 554 struct gl_texture_image *texImage; 555 const GLuint maxLevels = _mesa_max_texture_levels(ctx, target); 556 557 if (maxLevels == 0) { 558 _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImage(target=0x%x)", 559 target); 560 return GL_TRUE; 561 } 562 563 if (level < 0 || level >= maxLevels) { 564 _mesa_error(ctx, GL_INVALID_VALUE, 565 "glGetCompressedTexImageARB(bad level = %d)", level); 566 return GL_TRUE; 567 } 568 569 if (_mesa_is_proxy_texture(target)) { 570 _mesa_error(ctx, GL_INVALID_ENUM, 571 "glGetCompressedTexImageARB(bad target = %s)", 572 _mesa_lookup_enum_by_nr(target)); 573 return GL_TRUE; 574 } 575 576 texUnit = _mesa_get_current_tex_unit(ctx); 577 texObj = _mesa_select_tex_object(ctx, texUnit, target); 578 579 if (!texObj) { 580 _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB(target)"); 581 return GL_TRUE; 582 } 583 584 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 585 586 if (!texImage) { 587 /* probably invalid mipmap level */ 588 _mesa_error(ctx, GL_INVALID_VALUE, 589 "glGetCompressedTexImageARB(level)"); 590 return GL_TRUE; 591 } 592 593 if (!texImage->IsCompressed) { 594 _mesa_error(ctx, GL_INVALID_OPERATION, 595 "glGetCompressedTexImageARB(texture is not compressed)"); 596 return GL_TRUE; 597 } 598 599 if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { 600 /* make sure PBO is not mapped */ 601 if (_mesa_bufferobj_mapped(ctx->Pack.BufferObj)) { 602 _mesa_error(ctx, GL_INVALID_OPERATION, 603 "glGetCompressedTexImage(PBO is mapped)"); 604 return GL_TRUE; 605 } 606 607 /* do bounds checking on PBO write */ 608 if ((const GLubyte *) img + texImage->CompressedSize > 609 (const GLubyte *) ctx->Pack.BufferObj->Size) { 610 _mesa_error(ctx, GL_INVALID_OPERATION, 611 "glGetCompressedTexImage(out of bounds PBO write)"); 612 return GL_TRUE; 613 } 614 } 615 616 return GL_FALSE; 617} 618 619 620void GLAPIENTRY 621_mesa_GetCompressedTexImageARB(GLenum target, GLint level, GLvoid *img) 622{ 623 const struct gl_texture_unit *texUnit; 624 struct gl_texture_object *texObj; 625 GET_CURRENT_CONTEXT(ctx); 626 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 627 628 if (getcompressedteximage_error_check(ctx, target, level, img)) { 629 return; 630 } 631 632 texUnit = _mesa_get_current_tex_unit(ctx); 633 texObj = _mesa_select_tex_object(ctx, texUnit, target); 634 635 if (MESA_VERBOSE & (VERBOSE_API | VERBOSE_TEXTURE)) { 636 struct gl_texture_image *texImage = 637 _mesa_select_tex_image(ctx, texObj, target, level); 638 _mesa_debug(ctx, 639 "glGetCompressedTexImage(tex %u) format = %d, w=%d, h=%d\n", 640 texObj->Name, 641 texImage->TexFormat->MesaFormat, 642 texImage->Width, texImage->Height); 643 } 644 645 _mesa_lock_texture(ctx, texObj); 646 { 647 struct gl_texture_image *texImage = 648 _mesa_select_tex_image(ctx, texObj, target, level); 649 650 /* this typically calls _mesa_get_compressed_teximage() */ 651 ctx->Driver.GetCompressedTexImage(ctx, target, level, img, 652 texObj, texImage); 653 } 654 _mesa_unlock_texture(ctx, texObj); 655} 656