texgetimage.c revision cdc920a0
14a49301eSmrg/* 24a49301eSmrg * Mesa 3-D graphics library 34a49301eSmrg * Version: 7.7 44a49301eSmrg * 54a49301eSmrg * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. 64a49301eSmrg * Copyright (c) 2009 VMware, Inc. 74a49301eSmrg * 84a49301eSmrg * Permission is hereby granted, free of charge, to any person obtaining a 94a49301eSmrg * copy of this software and associated documentation files (the "Software"), 104a49301eSmrg * to deal in the Software without restriction, including without limitation 114a49301eSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 124a49301eSmrg * and/or sell copies of the Software, and to permit persons to whom the 134a49301eSmrg * Software is furnished to do so, subject to the following conditions: 144a49301eSmrg * 154a49301eSmrg * The above copyright notice and this permission notice shall be included 164a49301eSmrg * in all copies or substantial portions of the Software. 174a49301eSmrg * 184a49301eSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 194a49301eSmrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 204a49301eSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 214a49301eSmrg * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 224a49301eSmrg * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 234a49301eSmrg * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 244a49301eSmrg */ 254a49301eSmrg 264a49301eSmrg 274a49301eSmrg/** 284a49301eSmrg * Code for glGetTexImage() and glGetCompressedTexImage(). 294a49301eSmrg */ 304a49301eSmrg 314a49301eSmrg 324a49301eSmrg#include "glheader.h" 334a49301eSmrg#include "bufferobj.h" 344a49301eSmrg#include "enums.h" 354a49301eSmrg#include "context.h" 364a49301eSmrg#include "formats.h" 374a49301eSmrg#include "image.h" 384a49301eSmrg#include "texgetimage.h" 394a49301eSmrg#include "teximage.h" 404a49301eSmrg 414a49301eSmrg 424a49301eSmrg 434a49301eSmrg/** 444a49301eSmrg * Can the given type represent negative values? 454a49301eSmrg */ 464a49301eSmrgstatic INLINE GLboolean 474a49301eSmrgtype_with_negative_values(GLenum type) 484a49301eSmrg{ 494a49301eSmrg switch (type) { 504a49301eSmrg case GL_BYTE: 514a49301eSmrg case GL_SHORT: 524a49301eSmrg case GL_INT: 534a49301eSmrg case GL_FLOAT: 544a49301eSmrg case GL_HALF_FLOAT_ARB: 554a49301eSmrg return GL_TRUE; 564a49301eSmrg default: 574a49301eSmrg return GL_FALSE; 584a49301eSmrg } 594a49301eSmrg} 604a49301eSmrg 614a49301eSmrg 624a49301eSmrg/** 634a49301eSmrg * glGetTexImage for color index pixels. 644a49301eSmrg */ 654a49301eSmrgstatic void 664a49301eSmrgget_tex_color_index(GLcontext *ctx, GLuint dimensions, 674a49301eSmrg GLenum format, GLenum type, GLvoid *pixels, 684a49301eSmrg const struct gl_texture_image *texImage) 694a49301eSmrg{ 704a49301eSmrg const GLint width = texImage->Width; 714a49301eSmrg const GLint height = texImage->Height; 724a49301eSmrg const GLint depth = texImage->Depth; 734a49301eSmrg const GLuint indexBits = 744a49301eSmrg _mesa_get_format_bits(texImage->TexFormat, GL_TEXTURE_INDEX_SIZE_EXT); 754a49301eSmrg const GLbitfield transferOps = 0x0; 764a49301eSmrg GLint img, row, col; 774a49301eSmrg 784a49301eSmrg for (img = 0; img < depth; img++) { 794a49301eSmrg for (row = 0; row < height; row++) { 804a49301eSmrg GLuint indexRow[MAX_WIDTH] = { 0 }; 814a49301eSmrg void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels, 824a49301eSmrg width, height, format, type, 834a49301eSmrg img, row, 0); 844a49301eSmrg assert(dest); 854a49301eSmrg 864a49301eSmrg if (indexBits == 8) { 874a49301eSmrg const GLubyte *src = (const GLubyte *) texImage->Data; 884a49301eSmrg src += width * (img * texImage->Height + row); 894a49301eSmrg for (col = 0; col < width; col++) { 904a49301eSmrg indexRow[col] = src[col]; 914a49301eSmrg } 924a49301eSmrg } 934a49301eSmrg else if (indexBits == 16) { 944a49301eSmrg const GLushort *src = (const GLushort *) texImage->Data; 954a49301eSmrg src += width * (img * texImage->Height + row); 964a49301eSmrg for (col = 0; col < width; col++) { 974a49301eSmrg indexRow[col] = src[col]; 984a49301eSmrg } 994a49301eSmrg } 1004a49301eSmrg else { 1014a49301eSmrg _mesa_problem(ctx, "Color index problem in _mesa_GetTexImage"); 1024a49301eSmrg } 1034a49301eSmrg _mesa_pack_index_span(ctx, width, type, dest, 1044a49301eSmrg indexRow, &ctx->Pack, transferOps); 1054a49301eSmrg } 1064a49301eSmrg } 1074a49301eSmrg} 1084a49301eSmrg 1094a49301eSmrg 1104a49301eSmrg/** 1114a49301eSmrg * glGetTexImage for depth/Z pixels. 1124a49301eSmrg */ 1134a49301eSmrgstatic void 1144a49301eSmrgget_tex_depth(GLcontext *ctx, GLuint dimensions, 1154a49301eSmrg GLenum format, GLenum type, GLvoid *pixels, 1164a49301eSmrg const struct gl_texture_image *texImage) 1174a49301eSmrg{ 1184a49301eSmrg const GLint width = texImage->Width; 1194a49301eSmrg const GLint height = texImage->Height; 1204a49301eSmrg const GLint depth = texImage->Depth; 1214a49301eSmrg GLint img, row, col; 1224a49301eSmrg 1234a49301eSmrg for (img = 0; img < depth; img++) { 1244a49301eSmrg for (row = 0; row < height; row++) { 1254a49301eSmrg GLfloat depthRow[MAX_WIDTH]; 1264a49301eSmrg void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels, 1274a49301eSmrg width, height, format, type, 1284a49301eSmrg img, row, 0); 1294a49301eSmrg assert(dest); 1304a49301eSmrg 1314a49301eSmrg for (col = 0; col < width; col++) { 1324a49301eSmrg texImage->FetchTexelf(texImage, col, row, img, depthRow + col); 1334a49301eSmrg } 1344a49301eSmrg _mesa_pack_depth_span(ctx, width, dest, type, depthRow, &ctx->Pack); 1354a49301eSmrg } 1364a49301eSmrg } 1374a49301eSmrg} 1384a49301eSmrg 1394a49301eSmrg 1404a49301eSmrg/** 1414a49301eSmrg * glGetTexImage for depth/stencil pixels. 1424a49301eSmrg */ 1434a49301eSmrgstatic void 1444a49301eSmrgget_tex_depth_stencil(GLcontext *ctx, GLuint dimensions, 1454a49301eSmrg GLenum format, GLenum type, GLvoid *pixels, 1464a49301eSmrg const struct gl_texture_image *texImage) 1474a49301eSmrg{ 1484a49301eSmrg const GLint width = texImage->Width; 1494a49301eSmrg const GLint height = texImage->Height; 1504a49301eSmrg const GLint depth = texImage->Depth; 1514a49301eSmrg const GLuint *src = (const GLuint *) texImage->Data; 1524a49301eSmrg GLint img, row; 1534a49301eSmrg 1544a49301eSmrg for (img = 0; img < depth; img++) { 1554a49301eSmrg for (row = 0; row < height; row++) { 1564a49301eSmrg void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels, 1574a49301eSmrg width, height, format, type, 1584a49301eSmrg img, row, 0); 159cdc920a0Smrg memcpy(dest, src, width * sizeof(GLuint)); 1604a49301eSmrg if (ctx->Pack.SwapBytes) { 1614a49301eSmrg _mesa_swap4((GLuint *) dest, width); 1624a49301eSmrg } 1634a49301eSmrg 1644a49301eSmrg src += width * row + width * height * img; 1654a49301eSmrg } 1664a49301eSmrg } 1674a49301eSmrg} 1684a49301eSmrg 1694a49301eSmrg 1704a49301eSmrg/** 1714a49301eSmrg * glGetTexImage for YCbCr pixels. 1724a49301eSmrg */ 1734a49301eSmrgstatic void 1744a49301eSmrgget_tex_ycbcr(GLcontext *ctx, GLuint dimensions, 1754a49301eSmrg GLenum format, GLenum type, GLvoid *pixels, 1764a49301eSmrg const struct gl_texture_image *texImage) 1774a49301eSmrg{ 1784a49301eSmrg const GLint width = texImage->Width; 1794a49301eSmrg const GLint height = texImage->Height; 1804a49301eSmrg const GLint depth = texImage->Depth; 1814a49301eSmrg const GLint rowstride = texImage->RowStride; 1824a49301eSmrg const GLushort *src = (const GLushort *) texImage->Data; 1834a49301eSmrg GLint img, row; 1844a49301eSmrg 1854a49301eSmrg for (img = 0; img < depth; img++) { 1864a49301eSmrg for (row = 0; row < height; row++) { 1874a49301eSmrg void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels, 1884a49301eSmrg width, height, format, type, 1894a49301eSmrg img, row, 0); 190cdc920a0Smrg memcpy(dest, src, width * sizeof(GLushort)); 1914a49301eSmrg 1924a49301eSmrg /* check for byte swapping */ 1934a49301eSmrg if ((texImage->TexFormat == MESA_FORMAT_YCBCR 1944a49301eSmrg && type == GL_UNSIGNED_SHORT_8_8_REV_MESA) || 1954a49301eSmrg (texImage->TexFormat == MESA_FORMAT_YCBCR_REV 1964a49301eSmrg && type == GL_UNSIGNED_SHORT_8_8_MESA)) { 1974a49301eSmrg if (!ctx->Pack.SwapBytes) 1984a49301eSmrg _mesa_swap2((GLushort *) dest, width); 1994a49301eSmrg } 2004a49301eSmrg else if (ctx->Pack.SwapBytes) { 2014a49301eSmrg _mesa_swap2((GLushort *) dest, width); 2024a49301eSmrg } 2034a49301eSmrg 2044a49301eSmrg src += rowstride; 2054a49301eSmrg } 2064a49301eSmrg } 2074a49301eSmrg} 2084a49301eSmrg 2094a49301eSmrg 210cdc920a0Smrg#if FEATURE_EXT_texture_sRGB 211cdc920a0Smrg 212cdc920a0Smrg 213cdc920a0Smrg/** 214cdc920a0Smrg * Convert a float value from linear space to a 215cdc920a0Smrg * non-linear sRGB value in [0, 255]. 216cdc920a0Smrg * Not terribly efficient. 217cdc920a0Smrg */ 218cdc920a0Smrgstatic INLINE GLfloat 219cdc920a0Smrglinear_to_nonlinear(GLfloat cl) 220cdc920a0Smrg{ 221cdc920a0Smrg /* can't have values outside [0, 1] */ 222cdc920a0Smrg GLfloat cs; 223cdc920a0Smrg if (cl < 0.0031308f) { 224cdc920a0Smrg cs = 12.92f * cl; 225cdc920a0Smrg } 226cdc920a0Smrg else { 227cdc920a0Smrg cs = (GLfloat)(1.055 * _mesa_pow(cl, 0.41666) - 0.055); 228cdc920a0Smrg } 229cdc920a0Smrg return cs; 230cdc920a0Smrg} 231cdc920a0Smrg 232cdc920a0Smrg 2334a49301eSmrg/** 2344a49301eSmrg * glGetTexImagefor sRGB pixels; 2354a49301eSmrg */ 2364a49301eSmrgstatic void 2374a49301eSmrgget_tex_srgb(GLcontext *ctx, GLuint dimensions, 2384a49301eSmrg GLenum format, GLenum type, GLvoid *pixels, 2394a49301eSmrg const struct gl_texture_image *texImage) 2404a49301eSmrg{ 2414a49301eSmrg const GLint width = texImage->Width; 2424a49301eSmrg const GLint height = texImage->Height; 2434a49301eSmrg const GLint depth = texImage->Depth; 2444a49301eSmrg const GLbitfield transferOps = 0x0; 2454a49301eSmrg GLint img, row; 2464a49301eSmrg 2474a49301eSmrg for (img = 0; img < depth; img++) { 2484a49301eSmrg for (row = 0; row < height; row++) { 2494a49301eSmrg void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels, 2504a49301eSmrg width, height, format, type, 2514a49301eSmrg img, row, 0); 2524a49301eSmrg 2534a49301eSmrg GLfloat rgba[MAX_WIDTH][4]; 2544a49301eSmrg GLint col; 2554a49301eSmrg 2564a49301eSmrg /* convert row to RGBA format */ 2574a49301eSmrg for (col = 0; col < width; col++) { 2584a49301eSmrg texImage->FetchTexelf(texImage, col, row, img, rgba[col]); 2594a49301eSmrg if (texImage->_BaseFormat == GL_LUMINANCE) { 2604a49301eSmrg rgba[col][RCOMP] = linear_to_nonlinear(rgba[col][RCOMP]); 2614a49301eSmrg rgba[col][GCOMP] = 0.0; 2624a49301eSmrg rgba[col][BCOMP] = 0.0; 2634a49301eSmrg } 2644a49301eSmrg else if (texImage->_BaseFormat == GL_LUMINANCE_ALPHA) { 2654a49301eSmrg rgba[col][RCOMP] = linear_to_nonlinear(rgba[col][RCOMP]); 2664a49301eSmrg rgba[col][GCOMP] = 0.0; 2674a49301eSmrg rgba[col][BCOMP] = 0.0; 2684a49301eSmrg } 2694a49301eSmrg else if (texImage->_BaseFormat == GL_RGB || 2704a49301eSmrg texImage->_BaseFormat == GL_RGBA) { 2714a49301eSmrg rgba[col][RCOMP] = linear_to_nonlinear(rgba[col][RCOMP]); 2724a49301eSmrg rgba[col][GCOMP] = linear_to_nonlinear(rgba[col][GCOMP]); 2734a49301eSmrg rgba[col][BCOMP] = linear_to_nonlinear(rgba[col][BCOMP]); 2744a49301eSmrg } 2754a49301eSmrg } 2764a49301eSmrg _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba, 2774a49301eSmrg format, type, dest, 2784a49301eSmrg &ctx->Pack, transferOps); 2794a49301eSmrg } 2804a49301eSmrg } 2814a49301eSmrg} 2824a49301eSmrg 2834a49301eSmrg 284cdc920a0Smrg#else /* FEATURE_EXT_texture_sRGB */ 285cdc920a0Smrg 286cdc920a0Smrg 287cdc920a0Smrgstatic INLINE void 288cdc920a0Smrgget_tex_srgb(GLcontext *ctx, GLuint dimensions, 289cdc920a0Smrg GLenum format, GLenum type, GLvoid *pixels, 290cdc920a0Smrg const struct gl_texture_image *texImage) 291cdc920a0Smrg{ 292cdc920a0Smrg ASSERT_NO_FEATURE(); 293cdc920a0Smrg} 294cdc920a0Smrg 295cdc920a0Smrg 296cdc920a0Smrg#endif /* FEATURE_EXT_texture_sRGB */ 297cdc920a0Smrg 298cdc920a0Smrg 2994a49301eSmrg/** 3004a49301eSmrg * glGetTexImagefor RGBA, Luminance, etc. pixels. 3014a49301eSmrg * This is the slow way since we use texture sampling. 3024a49301eSmrg */ 3034a49301eSmrgstatic void 3044a49301eSmrgget_tex_rgba(GLcontext *ctx, GLuint dimensions, 3054a49301eSmrg GLenum format, GLenum type, GLvoid *pixels, 3064a49301eSmrg const struct gl_texture_image *texImage) 3074a49301eSmrg{ 3084a49301eSmrg const GLint width = texImage->Width; 3094a49301eSmrg const GLint height = texImage->Height; 3104a49301eSmrg const GLint depth = texImage->Depth; 3114a49301eSmrg /* Normally, no pixel transfer ops are performed during glGetTexImage. 3124a49301eSmrg * The only possible exception is component clamping to [0,1]. 3134a49301eSmrg */ 3144a49301eSmrg GLbitfield transferOps = 0x0; 3154a49301eSmrg GLint img, row; 3164a49301eSmrg 3174a49301eSmrg for (img = 0; img < depth; img++) { 3184a49301eSmrg for (row = 0; row < height; row++) { 3194a49301eSmrg void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels, 3204a49301eSmrg width, height, format, type, 3214a49301eSmrg img, row, 0); 3224a49301eSmrg GLfloat rgba[MAX_WIDTH][4]; 3234a49301eSmrg GLint col; 3244a49301eSmrg GLenum dataType = _mesa_get_format_datatype(texImage->TexFormat); 3254a49301eSmrg 3264a49301eSmrg /* clamp does not apply to GetTexImage (final conversion)? 3274a49301eSmrg * Looks like we need clamp though when going from format 3284a49301eSmrg * containing negative values to unsigned format. 3294a49301eSmrg */ 3304a49301eSmrg if (format == GL_LUMINANCE || format == GL_LUMINANCE_ALPHA) { 3314a49301eSmrg transferOps |= IMAGE_CLAMP_BIT; 3324a49301eSmrg } 3334a49301eSmrg else if (!type_with_negative_values(type) && 3344a49301eSmrg (dataType == GL_FLOAT || 3354a49301eSmrg dataType == GL_SIGNED_NORMALIZED)) { 3364a49301eSmrg transferOps |= IMAGE_CLAMP_BIT; 3374a49301eSmrg } 3384a49301eSmrg 3394a49301eSmrg for (col = 0; col < width; col++) { 3404a49301eSmrg texImage->FetchTexelf(texImage, col, row, img, rgba[col]); 3414a49301eSmrg if (texImage->_BaseFormat == GL_ALPHA) { 3424a49301eSmrg rgba[col][RCOMP] = 0.0F; 3434a49301eSmrg rgba[col][GCOMP] = 0.0F; 3444a49301eSmrg rgba[col][BCOMP] = 0.0F; 3454a49301eSmrg } 3464a49301eSmrg else if (texImage->_BaseFormat == GL_LUMINANCE) { 3474a49301eSmrg rgba[col][GCOMP] = 0.0F; 3484a49301eSmrg rgba[col][BCOMP] = 0.0F; 3494a49301eSmrg rgba[col][ACOMP] = 1.0F; 3504a49301eSmrg } 3514a49301eSmrg else if (texImage->_BaseFormat == GL_LUMINANCE_ALPHA) { 3524a49301eSmrg rgba[col][GCOMP] = 0.0F; 3534a49301eSmrg rgba[col][BCOMP] = 0.0F; 3544a49301eSmrg } 3554a49301eSmrg else if (texImage->_BaseFormat == GL_INTENSITY) { 3564a49301eSmrg rgba[col][GCOMP] = 0.0F; 3574a49301eSmrg rgba[col][BCOMP] = 0.0F; 3584a49301eSmrg rgba[col][ACOMP] = 1.0F; 3594a49301eSmrg } 3604a49301eSmrg } 3614a49301eSmrg _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba, 3624a49301eSmrg format, type, dest, 3634a49301eSmrg &ctx->Pack, transferOps); 3644a49301eSmrg } 3654a49301eSmrg } 3664a49301eSmrg} 3674a49301eSmrg 3684a49301eSmrg 3694a49301eSmrg/** 3704a49301eSmrg * Try to do glGetTexImage() with simple memcpy(). 3714a49301eSmrg * \return GL_TRUE if done, GL_FALSE otherwise 3724a49301eSmrg */ 3734a49301eSmrgstatic GLboolean 3744a49301eSmrgget_tex_memcpy(GLcontext *ctx, GLenum format, GLenum type, GLvoid *pixels, 3754a49301eSmrg const struct gl_texture_object *texObj, 3764a49301eSmrg const struct gl_texture_image *texImage) 3774a49301eSmrg{ 3784a49301eSmrg GLboolean memCopy = GL_FALSE; 3794a49301eSmrg 3804a49301eSmrg /* Texture image should have been mapped already */ 3814a49301eSmrg assert(texImage->Data); 3824a49301eSmrg 3834a49301eSmrg /* 3844a49301eSmrg * Check if the src/dst formats are compatible. 3854a49301eSmrg * Also note that GL's pixel transfer ops don't apply to glGetTexImage() 3864a49301eSmrg * so we don't have to worry about those. 3874a49301eSmrg * XXX more format combinations could be supported here. 3884a49301eSmrg */ 3894a49301eSmrg if ((texObj->Target == GL_TEXTURE_1D || 3904a49301eSmrg texObj->Target == GL_TEXTURE_2D || 3914a49301eSmrg texObj->Target == GL_TEXTURE_RECTANGLE || 3924a49301eSmrg (texObj->Target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && 3934a49301eSmrg texObj->Target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z))) { 3944a49301eSmrg if (texImage->TexFormat == MESA_FORMAT_ARGB8888 && 3954a49301eSmrg format == GL_BGRA && 3964a49301eSmrg type == GL_UNSIGNED_BYTE && 3974a49301eSmrg !ctx->Pack.SwapBytes && 3984a49301eSmrg _mesa_little_endian()) { 3994a49301eSmrg memCopy = GL_TRUE; 4004a49301eSmrg } 4014a49301eSmrg else if (texImage->TexFormat == MESA_FORMAT_AL88 && 4024a49301eSmrg format == GL_LUMINANCE_ALPHA && 4034a49301eSmrg type == GL_UNSIGNED_BYTE && 4044a49301eSmrg !ctx->Pack.SwapBytes && 4054a49301eSmrg _mesa_little_endian()) { 4064a49301eSmrg memCopy = GL_TRUE; 4074a49301eSmrg } 4084a49301eSmrg else if (texImage->TexFormat == MESA_FORMAT_L8 && 4094a49301eSmrg format == GL_LUMINANCE && 4104a49301eSmrg type == GL_UNSIGNED_BYTE) { 4114a49301eSmrg memCopy = GL_TRUE; 4124a49301eSmrg } 4134a49301eSmrg else if (texImage->TexFormat == MESA_FORMAT_A8 && 4144a49301eSmrg format == GL_ALPHA && 4154a49301eSmrg type == GL_UNSIGNED_BYTE) { 4164a49301eSmrg memCopy = GL_TRUE; 4174a49301eSmrg } 4184a49301eSmrg } 4194a49301eSmrg 4204a49301eSmrg if (memCopy) { 4214a49301eSmrg const GLuint bpp = _mesa_get_format_bytes(texImage->TexFormat); 4224a49301eSmrg const GLuint bytesPerRow = texImage->Width * bpp; 4234a49301eSmrg GLubyte *dst = 4244a49301eSmrg _mesa_image_address2d(&ctx->Pack, pixels, texImage->Width, 4254a49301eSmrg texImage->Height, format, type, 0, 0); 4264a49301eSmrg const GLint dstRowStride = 4274a49301eSmrg _mesa_image_row_stride(&ctx->Pack, texImage->Width, format, type); 4284a49301eSmrg const GLubyte *src = texImage->Data; 4294a49301eSmrg const GLint srcRowStride = texImage->RowStride * bpp; 4304a49301eSmrg GLuint row; 4314a49301eSmrg 4324a49301eSmrg if (bytesPerRow == dstRowStride && bytesPerRow == srcRowStride) { 4334a49301eSmrg memcpy(dst, src, bytesPerRow * texImage->Height); 4344a49301eSmrg } 4354a49301eSmrg else { 4364a49301eSmrg for (row = 0; row < texImage->Height; row++) { 4374a49301eSmrg memcpy(dst, src, bytesPerRow); 4384a49301eSmrg dst += dstRowStride; 4394a49301eSmrg src += srcRowStride; 4404a49301eSmrg } 4414a49301eSmrg } 4424a49301eSmrg } 4434a49301eSmrg 4444a49301eSmrg return memCopy; 4454a49301eSmrg} 4464a49301eSmrg 4474a49301eSmrg 4484a49301eSmrg/** 4494a49301eSmrg * This is the software fallback for Driver.GetTexImage(). 4504a49301eSmrg * All error checking will have been done before this routine is called. 4514a49301eSmrg * The texture image must be mapped. 4524a49301eSmrg */ 4534a49301eSmrgvoid 4544a49301eSmrg_mesa_get_teximage(GLcontext *ctx, GLenum target, GLint level, 4554a49301eSmrg GLenum format, GLenum type, GLvoid *pixels, 4564a49301eSmrg struct gl_texture_object *texObj, 4574a49301eSmrg struct gl_texture_image *texImage) 4584a49301eSmrg{ 4594a49301eSmrg GLuint dimensions; 4604a49301eSmrg 4614a49301eSmrg /* If we get here, the texture image should be mapped */ 4624a49301eSmrg assert(texImage->Data); 4634a49301eSmrg 4644a49301eSmrg switch (target) { 4654a49301eSmrg case GL_TEXTURE_1D: 4664a49301eSmrg dimensions = 1; 4674a49301eSmrg break; 4684a49301eSmrg case GL_TEXTURE_3D: 4694a49301eSmrg dimensions = 3; 4704a49301eSmrg break; 4714a49301eSmrg default: 4724a49301eSmrg dimensions = 2; 4734a49301eSmrg } 4744a49301eSmrg 4754a49301eSmrg if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { 4764a49301eSmrg /* Packing texture image into a PBO. 4774a49301eSmrg * Map the (potentially) VRAM-based buffer into our process space so 4784a49301eSmrg * we can write into it with the code below. 4794a49301eSmrg * A hardware driver might use a sophisticated blit to move the 4804a49301eSmrg * texture data to the PBO if the PBO is in VRAM along with the texture. 4814a49301eSmrg */ 4824a49301eSmrg GLubyte *buf = (GLubyte *) 4834a49301eSmrg ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT, 4844a49301eSmrg GL_WRITE_ONLY_ARB, ctx->Pack.BufferObj); 4854a49301eSmrg if (!buf) { 4864a49301eSmrg /* out of memory or other unexpected error */ 4874a49301eSmrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage(map PBO failed)"); 4884a49301eSmrg return; 4894a49301eSmrg } 4904a49301eSmrg /* <pixels> was an offset into the PBO. 4914a49301eSmrg * Now make it a real, client-side pointer inside the mapped region. 4924a49301eSmrg */ 4934a49301eSmrg pixels = ADD_POINTERS(buf, pixels); 4944a49301eSmrg } 4954a49301eSmrg 4964a49301eSmrg if (get_tex_memcpy(ctx, format, type, pixels, texObj, texImage)) { 4974a49301eSmrg /* all done */ 4984a49301eSmrg } 4994a49301eSmrg else if (format == GL_COLOR_INDEX) { 5004a49301eSmrg get_tex_color_index(ctx, dimensions, format, type, pixels, texImage); 5014a49301eSmrg } 5024a49301eSmrg else if (format == GL_DEPTH_COMPONENT) { 5034a49301eSmrg get_tex_depth(ctx, dimensions, format, type, pixels, texImage); 5044a49301eSmrg } 5054a49301eSmrg else if (format == GL_DEPTH_STENCIL_EXT) { 5064a49301eSmrg get_tex_depth_stencil(ctx, dimensions, format, type, pixels, texImage); 5074a49301eSmrg } 5084a49301eSmrg else if (format == GL_YCBCR_MESA) { 5094a49301eSmrg get_tex_ycbcr(ctx, dimensions, format, type, pixels, texImage); 5104a49301eSmrg } 5114a49301eSmrg else if (_mesa_get_format_color_encoding(texImage->TexFormat) == GL_SRGB) { 5124a49301eSmrg get_tex_srgb(ctx, dimensions, format, type, pixels, texImage); 5134a49301eSmrg } 5144a49301eSmrg else { 5154a49301eSmrg get_tex_rgba(ctx, dimensions, format, type, pixels, texImage); 5164a49301eSmrg } 5174a49301eSmrg 5184a49301eSmrg if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { 5194a49301eSmrg ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT, 5204a49301eSmrg ctx->Pack.BufferObj); 5214a49301eSmrg } 5224a49301eSmrg} 5234a49301eSmrg 5244a49301eSmrg 5254a49301eSmrg 5264a49301eSmrg/** 5274a49301eSmrg * This is the software fallback for Driver.GetCompressedTexImage(). 5284a49301eSmrg * All error checking will have been done before this routine is called. 5294a49301eSmrg */ 5304a49301eSmrgvoid 5314a49301eSmrg_mesa_get_compressed_teximage(GLcontext *ctx, GLenum target, GLint level, 5324a49301eSmrg GLvoid *img, 5334a49301eSmrg struct gl_texture_object *texObj, 5344a49301eSmrg struct gl_texture_image *texImage) 5354a49301eSmrg{ 5364a49301eSmrg const GLuint row_stride = _mesa_format_row_stride(texImage->TexFormat, 5374a49301eSmrg texImage->Width); 5384a49301eSmrg const GLuint row_stride_stored = _mesa_format_row_stride(texImage->TexFormat, 5394a49301eSmrg texImage->RowStride); 5404a49301eSmrg GLuint i; 5414a49301eSmrg 5424a49301eSmrg if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { 5434a49301eSmrg /* pack texture image into a PBO */ 5444a49301eSmrg GLubyte *buf = (GLubyte *) 5454a49301eSmrg ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT, 5464a49301eSmrg GL_WRITE_ONLY_ARB, ctx->Pack.BufferObj); 5474a49301eSmrg if (!buf) { 5484a49301eSmrg /* out of memory or other unexpected error */ 5494a49301eSmrg _mesa_error(ctx, GL_OUT_OF_MEMORY, 5504a49301eSmrg "glGetCompresssedTexImage(map PBO failed)"); 5514a49301eSmrg return; 5524a49301eSmrg } 5534a49301eSmrg img = ADD_POINTERS(buf, img); 5544a49301eSmrg } 5554a49301eSmrg 5564a49301eSmrg /* no pixelstore or pixel transfer, but respect stride */ 5574a49301eSmrg 5584a49301eSmrg if (row_stride == row_stride_stored) { 5594a49301eSmrg const GLuint size = _mesa_format_image_size(texImage->TexFormat, 5604a49301eSmrg texImage->Width, 5614a49301eSmrg texImage->Height, 5624a49301eSmrg texImage->Depth); 563cdc920a0Smrg memcpy(img, texImage->Data, size); 5644a49301eSmrg } 5654a49301eSmrg else { 5664a49301eSmrg GLuint bw, bh; 5674a49301eSmrg _mesa_get_format_block_size(texImage->TexFormat, &bw, &bh); 5684a49301eSmrg for (i = 0; i < (texImage->Height + bh - 1) / bh; i++) { 5694a49301eSmrg memcpy((GLubyte *)img + i * row_stride, 570cdc920a0Smrg (GLubyte *)texImage->Data + i * row_stride_stored, 571cdc920a0Smrg row_stride); 5724a49301eSmrg } 5734a49301eSmrg } 5744a49301eSmrg 5754a49301eSmrg if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { 5764a49301eSmrg ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT, 5774a49301eSmrg ctx->Pack.BufferObj); 5784a49301eSmrg } 5794a49301eSmrg} 5804a49301eSmrg 5814a49301eSmrg 5824a49301eSmrg 5834a49301eSmrg/** 5844a49301eSmrg * Do error checking for a glGetTexImage() call. 5854a49301eSmrg * \return GL_TRUE if any error, GL_FALSE if no errors. 5864a49301eSmrg */ 5874a49301eSmrgstatic GLboolean 5884a49301eSmrggetteximage_error_check(GLcontext *ctx, GLenum target, GLint level, 5894a49301eSmrg GLenum format, GLenum type, GLvoid *pixels ) 5904a49301eSmrg{ 5914a49301eSmrg struct gl_texture_object *texObj; 5924a49301eSmrg struct gl_texture_image *texImage; 593cdc920a0Smrg const GLint maxLevels = _mesa_max_texture_levels(ctx, target); 5944a49301eSmrg GLenum baseFormat; 5954a49301eSmrg 5964a49301eSmrg if (maxLevels == 0) { 5974a49301eSmrg _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target=0x%x)", target); 5984a49301eSmrg return GL_TRUE; 5994a49301eSmrg } 6004a49301eSmrg 6014a49301eSmrg if (level < 0 || level >= maxLevels) { 6024a49301eSmrg _mesa_error( ctx, GL_INVALID_VALUE, "glGetTexImage(level)" ); 6034a49301eSmrg return GL_TRUE; 6044a49301eSmrg } 6054a49301eSmrg 6064a49301eSmrg if (_mesa_sizeof_packed_type(type) <= 0) { 6074a49301eSmrg _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexImage(type)" ); 6084a49301eSmrg return GL_TRUE; 6094a49301eSmrg } 6104a49301eSmrg 6114a49301eSmrg if (_mesa_components_in_format(format) <= 0 || 6124a49301eSmrg format == GL_STENCIL_INDEX) { 6134a49301eSmrg _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexImage(format)" ); 6144a49301eSmrg return GL_TRUE; 6154a49301eSmrg } 6164a49301eSmrg 6174a49301eSmrg if (!ctx->Extensions.EXT_paletted_texture && _mesa_is_index_format(format)) { 6184a49301eSmrg _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)"); 6194a49301eSmrg return GL_TRUE; 6204a49301eSmrg } 6214a49301eSmrg 6224a49301eSmrg if (!ctx->Extensions.ARB_depth_texture && _mesa_is_depth_format(format)) { 6234a49301eSmrg _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)"); 6244a49301eSmrg return GL_TRUE; 6254a49301eSmrg } 6264a49301eSmrg 6274a49301eSmrg if (!ctx->Extensions.MESA_ycbcr_texture && _mesa_is_ycbcr_format(format)) { 6284a49301eSmrg _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)"); 6294a49301eSmrg return GL_TRUE; 6304a49301eSmrg } 6314a49301eSmrg 6324a49301eSmrg if (!ctx->Extensions.EXT_packed_depth_stencil 6334a49301eSmrg && _mesa_is_depthstencil_format(format)) { 6344a49301eSmrg _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)"); 6354a49301eSmrg return GL_TRUE; 6364a49301eSmrg } 6374a49301eSmrg 6384a49301eSmrg if (!ctx->Extensions.ATI_envmap_bumpmap 6394a49301eSmrg && _mesa_is_dudv_format(format)) { 6404a49301eSmrg _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)"); 6414a49301eSmrg return GL_TRUE; 6424a49301eSmrg } 6434a49301eSmrg 6444a49301eSmrg texObj = _mesa_get_current_tex_object(ctx, target); 6454a49301eSmrg 6464a49301eSmrg if (!texObj || _mesa_is_proxy_texture(target)) { 6474a49301eSmrg _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target)"); 6484a49301eSmrg return GL_TRUE; 6494a49301eSmrg } 6504a49301eSmrg 6514a49301eSmrg texImage = _mesa_select_tex_image(ctx, texObj, target, level); 6524a49301eSmrg if (!texImage) { 6534a49301eSmrg /* out of memory */ 6544a49301eSmrg return GL_TRUE; 6554a49301eSmrg } 6564a49301eSmrg 6574a49301eSmrg baseFormat = _mesa_get_format_base_format(texImage->TexFormat); 6584a49301eSmrg 6594a49301eSmrg /* Make sure the requested image format is compatible with the 6604a49301eSmrg * texture's format. Note that a color index texture can be converted 6614a49301eSmrg * to RGBA so that combo is allowed. 6624a49301eSmrg */ 6634a49301eSmrg if (_mesa_is_color_format(format) 6644a49301eSmrg && !_mesa_is_color_format(baseFormat) 6654a49301eSmrg && !_mesa_is_index_format(baseFormat)) { 6664a49301eSmrg _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); 6674a49301eSmrg return GL_TRUE; 6684a49301eSmrg } 6694a49301eSmrg else if (_mesa_is_index_format(format) 6704a49301eSmrg && !_mesa_is_index_format(baseFormat)) { 6714a49301eSmrg _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); 6724a49301eSmrg return GL_TRUE; 6734a49301eSmrg } 6744a49301eSmrg else if (_mesa_is_depth_format(format) 6754a49301eSmrg && !_mesa_is_depth_format(baseFormat) 6764a49301eSmrg && !_mesa_is_depthstencil_format(baseFormat)) { 6774a49301eSmrg _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); 6784a49301eSmrg return GL_TRUE; 6794a49301eSmrg } 6804a49301eSmrg else if (_mesa_is_ycbcr_format(format) 6814a49301eSmrg && !_mesa_is_ycbcr_format(baseFormat)) { 6824a49301eSmrg _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); 6834a49301eSmrg return GL_TRUE; 6844a49301eSmrg } 6854a49301eSmrg else if (_mesa_is_depthstencil_format(format) 6864a49301eSmrg && !_mesa_is_depthstencil_format(baseFormat)) { 6874a49301eSmrg _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); 6884a49301eSmrg return GL_TRUE; 6894a49301eSmrg } 6904a49301eSmrg else if (_mesa_is_dudv_format(format) 6914a49301eSmrg && !_mesa_is_dudv_format(baseFormat)) { 6924a49301eSmrg _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); 6934a49301eSmrg return GL_TRUE; 6944a49301eSmrg } 6954a49301eSmrg 6964a49301eSmrg if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { 6974a49301eSmrg /* packing texture image into a PBO */ 6984a49301eSmrg const GLuint dimensions = (target == GL_TEXTURE_3D) ? 3 : 2; 6994a49301eSmrg if (!_mesa_validate_pbo_access(dimensions, &ctx->Pack, texImage->Width, 7004a49301eSmrg texImage->Height, texImage->Depth, 7014a49301eSmrg format, type, pixels)) { 7024a49301eSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 7034a49301eSmrg "glGetTexImage(out of bounds PBO write)"); 7044a49301eSmrg return GL_TRUE; 7054a49301eSmrg } 7064a49301eSmrg 7074a49301eSmrg /* PBO should not be mapped */ 7084a49301eSmrg if (_mesa_bufferobj_mapped(ctx->Pack.BufferObj)) { 7094a49301eSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 7104a49301eSmrg "glGetTexImage(PBO is mapped)"); 7114a49301eSmrg return GL_TRUE; 7124a49301eSmrg } 7134a49301eSmrg } 7144a49301eSmrg 7154a49301eSmrg return GL_FALSE; 7164a49301eSmrg} 7174a49301eSmrg 7184a49301eSmrg 7194a49301eSmrg 7204a49301eSmrg/** 7214a49301eSmrg * Get texture image. Called by glGetTexImage. 7224a49301eSmrg * 7234a49301eSmrg * \param target texture target. 7244a49301eSmrg * \param level image level. 7254a49301eSmrg * \param format pixel data format for returned image. 7264a49301eSmrg * \param type pixel data type for returned image. 7274a49301eSmrg * \param pixels returned pixel data. 7284a49301eSmrg */ 7294a49301eSmrgvoid GLAPIENTRY 7304a49301eSmrg_mesa_GetTexImage( GLenum target, GLint level, GLenum format, 7314a49301eSmrg GLenum type, GLvoid *pixels ) 7324a49301eSmrg{ 7334a49301eSmrg struct gl_texture_object *texObj; 7344a49301eSmrg struct gl_texture_image *texImage; 7354a49301eSmrg GET_CURRENT_CONTEXT(ctx); 7364a49301eSmrg ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 7374a49301eSmrg 7384a49301eSmrg if (getteximage_error_check(ctx, target, level, format, type, pixels)) { 7394a49301eSmrg return; 7404a49301eSmrg } 7414a49301eSmrg 7424a49301eSmrg if (!_mesa_is_bufferobj(ctx->Pack.BufferObj) && !pixels) { 7434a49301eSmrg /* not an error, do nothing */ 7444a49301eSmrg return; 7454a49301eSmrg } 7464a49301eSmrg 7474a49301eSmrg texObj = _mesa_get_current_tex_object(ctx, target); 7484a49301eSmrg texImage = _mesa_select_tex_image(ctx, texObj, target, level); 7494a49301eSmrg 7504a49301eSmrg if (MESA_VERBOSE & (VERBOSE_API | VERBOSE_TEXTURE)) { 7514a49301eSmrg _mesa_debug(ctx, "glGetTexImage(tex %u) format = %s, w=%d, h=%d," 7524a49301eSmrg " dstFmt=0x%x, dstType=0x%x\n", 7534a49301eSmrg texObj->Name, 7544a49301eSmrg _mesa_get_format_name(texImage->TexFormat), 7554a49301eSmrg texImage->Width, texImage->Height, 7564a49301eSmrg format, type); 7574a49301eSmrg } 7584a49301eSmrg 7594a49301eSmrg _mesa_lock_texture(ctx, texObj); 7604a49301eSmrg { 7614a49301eSmrg ctx->Driver.GetTexImage(ctx, target, level, format, type, pixels, 7624a49301eSmrg texObj, texImage); 7634a49301eSmrg } 7644a49301eSmrg _mesa_unlock_texture(ctx, texObj); 7654a49301eSmrg} 7664a49301eSmrg 7674a49301eSmrg 7684a49301eSmrg 7694a49301eSmrg/** 7704a49301eSmrg * Do error checking for a glGetCompressedTexImage() call. 7714a49301eSmrg * \return GL_TRUE if any error, GL_FALSE if no errors. 7724a49301eSmrg */ 7734a49301eSmrgstatic GLboolean 7744a49301eSmrggetcompressedteximage_error_check(GLcontext *ctx, GLenum target, GLint level, 7754a49301eSmrg GLvoid *img) 7764a49301eSmrg{ 7774a49301eSmrg struct gl_texture_object *texObj; 7784a49301eSmrg struct gl_texture_image *texImage; 779cdc920a0Smrg const GLint maxLevels = _mesa_max_texture_levels(ctx, target); 7804a49301eSmrg 7814a49301eSmrg if (maxLevels == 0) { 7824a49301eSmrg _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImage(target=0x%x)", 7834a49301eSmrg target); 7844a49301eSmrg return GL_TRUE; 7854a49301eSmrg } 7864a49301eSmrg 7874a49301eSmrg if (level < 0 || level >= maxLevels) { 7884a49301eSmrg _mesa_error(ctx, GL_INVALID_VALUE, 7894a49301eSmrg "glGetCompressedTexImageARB(bad level = %d)", level); 7904a49301eSmrg return GL_TRUE; 7914a49301eSmrg } 7924a49301eSmrg 7934a49301eSmrg if (_mesa_is_proxy_texture(target)) { 7944a49301eSmrg _mesa_error(ctx, GL_INVALID_ENUM, 7954a49301eSmrg "glGetCompressedTexImageARB(bad target = %s)", 7964a49301eSmrg _mesa_lookup_enum_by_nr(target)); 7974a49301eSmrg return GL_TRUE; 7984a49301eSmrg } 7994a49301eSmrg 8004a49301eSmrg texObj = _mesa_get_current_tex_object(ctx, target); 8014a49301eSmrg if (!texObj) { 8024a49301eSmrg _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB(target)"); 8034a49301eSmrg return GL_TRUE; 8044a49301eSmrg } 8054a49301eSmrg 8064a49301eSmrg texImage = _mesa_select_tex_image(ctx, texObj, target, level); 8074a49301eSmrg 8084a49301eSmrg if (!texImage) { 8094a49301eSmrg /* probably invalid mipmap level */ 8104a49301eSmrg _mesa_error(ctx, GL_INVALID_VALUE, 8114a49301eSmrg "glGetCompressedTexImageARB(level)"); 8124a49301eSmrg return GL_TRUE; 8134a49301eSmrg } 8144a49301eSmrg 8154a49301eSmrg if (!_mesa_is_format_compressed(texImage->TexFormat)) { 8164a49301eSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 8174a49301eSmrg "glGetCompressedTexImageARB(texture is not compressed)"); 8184a49301eSmrg return GL_TRUE; 8194a49301eSmrg } 8204a49301eSmrg 8214a49301eSmrg if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { 8224a49301eSmrg GLuint compressedSize; 8234a49301eSmrg 8244a49301eSmrg /* make sure PBO is not mapped */ 8254a49301eSmrg if (_mesa_bufferobj_mapped(ctx->Pack.BufferObj)) { 8264a49301eSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 8274a49301eSmrg "glGetCompressedTexImage(PBO is mapped)"); 8284a49301eSmrg return GL_TRUE; 8294a49301eSmrg } 8304a49301eSmrg 8314a49301eSmrg compressedSize = _mesa_format_image_size(texImage->TexFormat, 8324a49301eSmrg texImage->Width, 8334a49301eSmrg texImage->Height, 8344a49301eSmrg texImage->Depth); 8354a49301eSmrg 8364a49301eSmrg /* do bounds checking on PBO write */ 8374a49301eSmrg if ((const GLubyte *) img + compressedSize > 8384a49301eSmrg (const GLubyte *) ctx->Pack.BufferObj->Size) { 8394a49301eSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 8404a49301eSmrg "glGetCompressedTexImage(out of bounds PBO write)"); 8414a49301eSmrg return GL_TRUE; 8424a49301eSmrg } 8434a49301eSmrg } 8444a49301eSmrg 8454a49301eSmrg return GL_FALSE; 8464a49301eSmrg} 8474a49301eSmrg 8484a49301eSmrg 8494a49301eSmrgvoid GLAPIENTRY 8504a49301eSmrg_mesa_GetCompressedTexImageARB(GLenum target, GLint level, GLvoid *img) 8514a49301eSmrg{ 8524a49301eSmrg struct gl_texture_object *texObj; 8534a49301eSmrg struct gl_texture_image *texImage; 8544a49301eSmrg GET_CURRENT_CONTEXT(ctx); 8554a49301eSmrg ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 8564a49301eSmrg 8574a49301eSmrg if (getcompressedteximage_error_check(ctx, target, level, img)) { 8584a49301eSmrg return; 8594a49301eSmrg } 8604a49301eSmrg 8614a49301eSmrg if (_mesa_is_bufferobj(ctx->Pack.BufferObj) && !img) { 8624a49301eSmrg /* not an error, do nothing */ 8634a49301eSmrg return; 8644a49301eSmrg } 8654a49301eSmrg 8664a49301eSmrg texObj = _mesa_get_current_tex_object(ctx, target); 8674a49301eSmrg texImage = _mesa_select_tex_image(ctx, texObj, target, level); 8684a49301eSmrg 8694a49301eSmrg if (MESA_VERBOSE & (VERBOSE_API | VERBOSE_TEXTURE)) { 8704a49301eSmrg _mesa_debug(ctx, 8714a49301eSmrg "glGetCompressedTexImage(tex %u) format = %s, w=%d, h=%d\n", 8724a49301eSmrg texObj->Name, 8734a49301eSmrg _mesa_get_format_name(texImage->TexFormat), 8744a49301eSmrg texImage->Width, texImage->Height); 8754a49301eSmrg } 8764a49301eSmrg 8774a49301eSmrg _mesa_lock_texture(ctx, texObj); 8784a49301eSmrg { 8794a49301eSmrg ctx->Driver.GetCompressedTexImage(ctx, target, level, img, 8804a49301eSmrg texObj, texImage); 8814a49301eSmrg } 8824a49301eSmrg _mesa_unlock_texture(ctx, texObj); 8834a49301eSmrg} 884