1848b8605Smrg/* 2848b8605Smrg * Mesa 3-D graphics library 3848b8605Smrg * 4848b8605Smrg * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. 5848b8605Smrg * Copyright (c) 2009 VMware, Inc. 6848b8605Smrg * 7848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a 8848b8605Smrg * copy of this software and associated documentation files (the "Software"), 9848b8605Smrg * to deal in the Software without restriction, including without limitation 10848b8605Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the 12848b8605Smrg * Software is furnished to do so, subject to the following conditions: 13848b8605Smrg * 14848b8605Smrg * The above copyright notice and this permission notice shall be included 15848b8605Smrg * in all copies or substantial portions of the Software. 16848b8605Smrg * 17848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20848b8605Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21848b8605Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22848b8605Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23848b8605Smrg * OTHER DEALINGS IN THE SOFTWARE. 24848b8605Smrg */ 25848b8605Smrg 26848b8605Smrg 27848b8605Smrg/** 28848b8605Smrg * Code for glGetTexImage() and glGetCompressedTexImage(). 29848b8605Smrg */ 30848b8605Smrg 31848b8605Smrg 32848b8605Smrg#include "glheader.h" 33848b8605Smrg#include "bufferobj.h" 34848b8605Smrg#include "enums.h" 35848b8605Smrg#include "context.h" 36848b8605Smrg#include "formats.h" 37848b8605Smrg#include "format_unpack.h" 38848b8605Smrg#include "glformats.h" 39848b8605Smrg#include "image.h" 40848b8605Smrg#include "mtypes.h" 41848b8605Smrg#include "pack.h" 42848b8605Smrg#include "pbo.h" 43848b8605Smrg#include "pixelstore.h" 44848b8605Smrg#include "texcompress.h" 45848b8605Smrg#include "texgetimage.h" 46848b8605Smrg#include "teximage.h" 47b8e80941Smrg#include "texobj.h" 48848b8605Smrg#include "texstore.h" 49b8e80941Smrg#include "format_utils.h" 50b8e80941Smrg#include "pixeltransfer.h" 51848b8605Smrg 52848b8605Smrg/** 53848b8605Smrg * Can the given type represent negative values? 54848b8605Smrg */ 55848b8605Smrgstatic inline GLboolean 56848b8605Smrgtype_needs_clamping(GLenum type) 57848b8605Smrg{ 58848b8605Smrg switch (type) { 59848b8605Smrg case GL_BYTE: 60848b8605Smrg case GL_SHORT: 61848b8605Smrg case GL_INT: 62848b8605Smrg case GL_FLOAT: 63848b8605Smrg case GL_HALF_FLOAT_ARB: 64848b8605Smrg case GL_UNSIGNED_INT_10F_11F_11F_REV: 65848b8605Smrg case GL_UNSIGNED_INT_5_9_9_9_REV: 66848b8605Smrg return GL_FALSE; 67848b8605Smrg default: 68848b8605Smrg return GL_TRUE; 69848b8605Smrg } 70848b8605Smrg} 71848b8605Smrg 72848b8605Smrg 73848b8605Smrg/** 74848b8605Smrg * glGetTexImage for depth/Z pixels. 75848b8605Smrg */ 76848b8605Smrgstatic void 77848b8605Smrgget_tex_depth(struct gl_context *ctx, GLuint dimensions, 78b8e80941Smrg GLint xoffset, GLint yoffset, GLint zoffset, 79b8e80941Smrg GLsizei width, GLsizei height, GLint depth, 80848b8605Smrg GLenum format, GLenum type, GLvoid *pixels, 81848b8605Smrg struct gl_texture_image *texImage) 82848b8605Smrg{ 83848b8605Smrg GLint img, row; 84848b8605Smrg GLfloat *depthRow = malloc(width * sizeof(GLfloat)); 85848b8605Smrg 86848b8605Smrg if (!depthRow) { 87848b8605Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage"); 88848b8605Smrg return; 89848b8605Smrg } 90848b8605Smrg 91848b8605Smrg for (img = 0; img < depth; img++) { 92848b8605Smrg GLubyte *srcMap; 93848b8605Smrg GLint srcRowStride; 94848b8605Smrg 95848b8605Smrg /* map src texture buffer */ 96b8e80941Smrg ctx->Driver.MapTextureImage(ctx, texImage, zoffset + img, 97b8e80941Smrg xoffset, yoffset, width, height, 98b8e80941Smrg GL_MAP_READ_BIT, &srcMap, &srcRowStride); 99848b8605Smrg 100848b8605Smrg if (srcMap) { 101848b8605Smrg for (row = 0; row < height; row++) { 102848b8605Smrg void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels, 103848b8605Smrg width, height, format, type, 104848b8605Smrg img, row, 0); 105848b8605Smrg const GLubyte *src = srcMap + row * srcRowStride; 106848b8605Smrg _mesa_unpack_float_z_row(texImage->TexFormat, width, src, depthRow); 107848b8605Smrg _mesa_pack_depth_span(ctx, width, dest, type, depthRow, &ctx->Pack); 108848b8605Smrg } 109848b8605Smrg 110b8e80941Smrg ctx->Driver.UnmapTextureImage(ctx, texImage, zoffset + img); 111848b8605Smrg } 112848b8605Smrg else { 113848b8605Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage"); 114848b8605Smrg break; 115848b8605Smrg } 116848b8605Smrg } 117848b8605Smrg 118848b8605Smrg free(depthRow); 119848b8605Smrg} 120848b8605Smrg 121848b8605Smrg 122848b8605Smrg/** 123848b8605Smrg * glGetTexImage for depth/stencil pixels. 124848b8605Smrg */ 125848b8605Smrgstatic void 126848b8605Smrgget_tex_depth_stencil(struct gl_context *ctx, GLuint dimensions, 127b8e80941Smrg GLint xoffset, GLint yoffset, GLint zoffset, 128b8e80941Smrg GLsizei width, GLsizei height, GLint depth, 129848b8605Smrg GLenum format, GLenum type, GLvoid *pixels, 130848b8605Smrg struct gl_texture_image *texImage) 131848b8605Smrg{ 132848b8605Smrg GLint img, row; 133848b8605Smrg 134848b8605Smrg assert(format == GL_DEPTH_STENCIL); 135848b8605Smrg assert(type == GL_UNSIGNED_INT_24_8 || 136848b8605Smrg type == GL_FLOAT_32_UNSIGNED_INT_24_8_REV); 137848b8605Smrg 138848b8605Smrg for (img = 0; img < depth; img++) { 139848b8605Smrg GLubyte *srcMap; 140848b8605Smrg GLint rowstride; 141848b8605Smrg 142848b8605Smrg /* map src texture buffer */ 143b8e80941Smrg ctx->Driver.MapTextureImage(ctx, texImage, zoffset + img, 144b8e80941Smrg xoffset, yoffset, width, height, 145b8e80941Smrg GL_MAP_READ_BIT, &srcMap, &rowstride); 146848b8605Smrg 147848b8605Smrg if (srcMap) { 148848b8605Smrg for (row = 0; row < height; row++) { 149848b8605Smrg const GLubyte *src = srcMap + row * rowstride; 150848b8605Smrg void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels, 151848b8605Smrg width, height, format, type, 152848b8605Smrg img, row, 0); 153848b8605Smrg _mesa_unpack_depth_stencil_row(texImage->TexFormat, 154848b8605Smrg width, 155848b8605Smrg (const GLuint *) src, 156848b8605Smrg type, dest); 157848b8605Smrg if (ctx->Pack.SwapBytes) { 158848b8605Smrg _mesa_swap4((GLuint *) dest, width); 159848b8605Smrg } 160848b8605Smrg } 161848b8605Smrg 162b8e80941Smrg ctx->Driver.UnmapTextureImage(ctx, texImage, zoffset + img); 163b8e80941Smrg } 164b8e80941Smrg else { 165b8e80941Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage"); 166b8e80941Smrg break; 167b8e80941Smrg } 168b8e80941Smrg } 169b8e80941Smrg} 170b8e80941Smrg 171b8e80941Smrg/** 172b8e80941Smrg * glGetTexImage for stencil pixels. 173b8e80941Smrg */ 174b8e80941Smrgstatic void 175b8e80941Smrgget_tex_stencil(struct gl_context *ctx, GLuint dimensions, 176b8e80941Smrg GLint xoffset, GLint yoffset, GLint zoffset, 177b8e80941Smrg GLsizei width, GLsizei height, GLint depth, 178b8e80941Smrg GLenum format, GLenum type, GLvoid *pixels, 179b8e80941Smrg struct gl_texture_image *texImage) 180b8e80941Smrg{ 181b8e80941Smrg GLint img, row; 182b8e80941Smrg 183b8e80941Smrg assert(format == GL_STENCIL_INDEX); 184b8e80941Smrg 185b8e80941Smrg for (img = 0; img < depth; img++) { 186b8e80941Smrg GLubyte *srcMap; 187b8e80941Smrg GLint rowstride; 188b8e80941Smrg 189b8e80941Smrg /* map src texture buffer */ 190b8e80941Smrg ctx->Driver.MapTextureImage(ctx, texImage, zoffset + img, 191b8e80941Smrg xoffset, yoffset, width, height, 192b8e80941Smrg GL_MAP_READ_BIT, 193b8e80941Smrg &srcMap, &rowstride); 194b8e80941Smrg 195b8e80941Smrg if (srcMap) { 196b8e80941Smrg for (row = 0; row < height; row++) { 197b8e80941Smrg const GLubyte *src = srcMap + row * rowstride; 198b8e80941Smrg void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels, 199b8e80941Smrg width, height, format, type, 200b8e80941Smrg img, row, 0); 201b8e80941Smrg _mesa_unpack_ubyte_stencil_row(texImage->TexFormat, 202b8e80941Smrg width, 203b8e80941Smrg (const GLuint *) src, 204b8e80941Smrg dest); 205b8e80941Smrg } 206b8e80941Smrg 207b8e80941Smrg ctx->Driver.UnmapTextureImage(ctx, texImage, zoffset + img); 208848b8605Smrg } 209848b8605Smrg else { 210848b8605Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage"); 211848b8605Smrg break; 212848b8605Smrg } 213848b8605Smrg } 214848b8605Smrg} 215848b8605Smrg 216848b8605Smrg 217848b8605Smrg/** 218848b8605Smrg * glGetTexImage for YCbCr pixels. 219848b8605Smrg */ 220848b8605Smrgstatic void 221848b8605Smrgget_tex_ycbcr(struct gl_context *ctx, GLuint dimensions, 222b8e80941Smrg GLint xoffset, GLint yoffset, GLint zoffset, 223b8e80941Smrg GLsizei width, GLsizei height, GLint depth, 224848b8605Smrg GLenum format, GLenum type, GLvoid *pixels, 225848b8605Smrg struct gl_texture_image *texImage) 226848b8605Smrg{ 227848b8605Smrg GLint img, row; 228848b8605Smrg 229848b8605Smrg for (img = 0; img < depth; img++) { 230848b8605Smrg GLubyte *srcMap; 231848b8605Smrg GLint rowstride; 232848b8605Smrg 233848b8605Smrg /* map src texture buffer */ 234b8e80941Smrg ctx->Driver.MapTextureImage(ctx, texImage, zoffset + img, 235b8e80941Smrg xoffset, yoffset, width, height, 236b8e80941Smrg GL_MAP_READ_BIT, &srcMap, &rowstride); 237848b8605Smrg 238848b8605Smrg if (srcMap) { 239848b8605Smrg for (row = 0; row < height; row++) { 240848b8605Smrg const GLubyte *src = srcMap + row * rowstride; 241848b8605Smrg void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels, 242848b8605Smrg width, height, format, type, 243848b8605Smrg img, row, 0); 244848b8605Smrg memcpy(dest, src, width * sizeof(GLushort)); 245848b8605Smrg 246848b8605Smrg /* check for byte swapping */ 247848b8605Smrg if ((texImage->TexFormat == MESA_FORMAT_YCBCR 248848b8605Smrg && type == GL_UNSIGNED_SHORT_8_8_REV_MESA) || 249848b8605Smrg (texImage->TexFormat == MESA_FORMAT_YCBCR_REV 250848b8605Smrg && type == GL_UNSIGNED_SHORT_8_8_MESA)) { 251848b8605Smrg if (!ctx->Pack.SwapBytes) 252848b8605Smrg _mesa_swap2((GLushort *) dest, width); 253848b8605Smrg } 254848b8605Smrg else if (ctx->Pack.SwapBytes) { 255848b8605Smrg _mesa_swap2((GLushort *) dest, width); 256848b8605Smrg } 257848b8605Smrg } 258848b8605Smrg 259b8e80941Smrg ctx->Driver.UnmapTextureImage(ctx, texImage, zoffset + img); 260848b8605Smrg } 261848b8605Smrg else { 262848b8605Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage"); 263848b8605Smrg break; 264848b8605Smrg } 265848b8605Smrg } 266848b8605Smrg} 267848b8605Smrg 268b8e80941Smrg/** 269b8e80941Smrg * Depending on the base format involved we may need to apply a rebase 270b8e80941Smrg * transform (for example: if we download to a Luminance format we want 271b8e80941Smrg * G=0 and B=0). 272b8e80941Smrg */ 273b8e80941Smrgstatic bool 274b8e80941Smrgteximage_needs_rebase(mesa_format texFormat, GLenum baseFormat, 275b8e80941Smrg bool is_compressed, uint8_t *rebaseSwizzle) 276b8e80941Smrg{ 277b8e80941Smrg bool needsRebase = false; 278b8e80941Smrg 279b8e80941Smrg if (baseFormat == GL_LUMINANCE || 280b8e80941Smrg baseFormat == GL_INTENSITY) { 281b8e80941Smrg needsRebase = true; 282b8e80941Smrg rebaseSwizzle[0] = MESA_FORMAT_SWIZZLE_X; 283b8e80941Smrg rebaseSwizzle[1] = MESA_FORMAT_SWIZZLE_ZERO; 284b8e80941Smrg rebaseSwizzle[2] = MESA_FORMAT_SWIZZLE_ZERO; 285b8e80941Smrg rebaseSwizzle[3] = MESA_FORMAT_SWIZZLE_ONE; 286b8e80941Smrg } else if (baseFormat == GL_LUMINANCE_ALPHA) { 287b8e80941Smrg needsRebase = true; 288b8e80941Smrg rebaseSwizzle[0] = MESA_FORMAT_SWIZZLE_X; 289b8e80941Smrg rebaseSwizzle[1] = MESA_FORMAT_SWIZZLE_ZERO; 290b8e80941Smrg rebaseSwizzle[2] = MESA_FORMAT_SWIZZLE_ZERO; 291b8e80941Smrg rebaseSwizzle[3] = MESA_FORMAT_SWIZZLE_W; 292b8e80941Smrg } else if (!is_compressed && 293b8e80941Smrg (baseFormat != _mesa_get_format_base_format(texFormat))) { 294b8e80941Smrg needsRebase = 295b8e80941Smrg _mesa_compute_rgba2base2rgba_component_mapping(baseFormat, 296b8e80941Smrg rebaseSwizzle); 297b8e80941Smrg } 298b8e80941Smrg 299b8e80941Smrg return needsRebase; 300b8e80941Smrg} 301b8e80941Smrg 302848b8605Smrg 303848b8605Smrg/** 304848b8605Smrg * Get a color texture image with decompression. 305848b8605Smrg */ 306848b8605Smrgstatic void 307848b8605Smrgget_tex_rgba_compressed(struct gl_context *ctx, GLuint dimensions, 308b8e80941Smrg GLint xoffset, GLint yoffset, GLint zoffset, 309b8e80941Smrg GLsizei width, GLsizei height, GLint depth, 310848b8605Smrg GLenum format, GLenum type, GLvoid *pixels, 311848b8605Smrg struct gl_texture_image *texImage, 312848b8605Smrg GLbitfield transferOps) 313848b8605Smrg{ 314848b8605Smrg /* don't want to apply sRGB -> RGB conversion here so override the format */ 315848b8605Smrg const mesa_format texFormat = 316848b8605Smrg _mesa_get_srgb_format_linear(texImage->TexFormat); 317848b8605Smrg const GLenum baseFormat = _mesa_get_format_base_format(texFormat); 318b8e80941Smrg GLfloat *tempImage, *tempSlice; 319b8e80941Smrg GLuint slice; 320b8e80941Smrg int srcStride, dstStride; 321b8e80941Smrg uint32_t dstFormat; 322b8e80941Smrg bool needsRebase; 323b8e80941Smrg uint8_t rebaseSwizzle[4]; 324848b8605Smrg 325848b8605Smrg /* Decompress into temp float buffer, then pack into user buffer */ 326b8e80941Smrg tempImage = malloc(width * height * depth * 4 * sizeof(GLfloat)); 327848b8605Smrg if (!tempImage) { 328848b8605Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage()"); 329848b8605Smrg return; 330848b8605Smrg } 331848b8605Smrg 332848b8605Smrg /* Decompress the texture image slices - results in 'tempImage' */ 333848b8605Smrg for (slice = 0; slice < depth; slice++) { 334848b8605Smrg GLubyte *srcMap; 335848b8605Smrg GLint srcRowStride; 336848b8605Smrg 337848b8605Smrg tempSlice = tempImage + slice * 4 * width * height; 338848b8605Smrg 339b8e80941Smrg ctx->Driver.MapTextureImage(ctx, texImage, zoffset + slice, 340b8e80941Smrg xoffset, yoffset, width, height, 341848b8605Smrg GL_MAP_READ_BIT, 342848b8605Smrg &srcMap, &srcRowStride); 343848b8605Smrg if (srcMap) { 344848b8605Smrg _mesa_decompress_image(texFormat, width, height, 345848b8605Smrg srcMap, srcRowStride, tempSlice); 346848b8605Smrg 347b8e80941Smrg ctx->Driver.UnmapTextureImage(ctx, texImage, zoffset + slice); 348848b8605Smrg } 349848b8605Smrg else { 350848b8605Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage"); 351848b8605Smrg free(tempImage); 352848b8605Smrg return; 353848b8605Smrg } 354848b8605Smrg } 355848b8605Smrg 356b8e80941Smrg needsRebase = teximage_needs_rebase(texFormat, baseFormat, true, 357b8e80941Smrg rebaseSwizzle); 358848b8605Smrg 359b8e80941Smrg srcStride = 4 * width * sizeof(GLfloat); 360b8e80941Smrg dstStride = _mesa_image_row_stride(&ctx->Pack, width, format, type); 361b8e80941Smrg dstFormat = _mesa_format_from_format_and_type(format, type); 362848b8605Smrg tempSlice = tempImage; 363848b8605Smrg for (slice = 0; slice < depth; slice++) { 364b8e80941Smrg void *dest = _mesa_image_address(dimensions, &ctx->Pack, pixels, 365b8e80941Smrg width, height, format, type, 366b8e80941Smrg slice, 0, 0); 367b8e80941Smrg _mesa_format_convert(dest, dstFormat, dstStride, 368b8e80941Smrg tempSlice, RGBA32_FLOAT, srcStride, 369b8e80941Smrg width, height, 370b8e80941Smrg needsRebase ? rebaseSwizzle : NULL); 371b8e80941Smrg 372b8e80941Smrg /* Handle byte swapping if required */ 373b8e80941Smrg if (ctx->Pack.SwapBytes) { 374b8e80941Smrg _mesa_swap_bytes_2d_image(format, type, &ctx->Pack, 375b8e80941Smrg width, height, dest, dest); 376848b8605Smrg } 377b8e80941Smrg 378848b8605Smrg tempSlice += 4 * width * height; 379848b8605Smrg } 380848b8605Smrg 381848b8605Smrg free(tempImage); 382848b8605Smrg} 383848b8605Smrg 384848b8605Smrg 385848b8605Smrg/** 386848b8605Smrg * Return a base GL format given the user-requested format 387848b8605Smrg * for glGetTexImage(). 388848b8605Smrg */ 389848b8605SmrgGLenum 390848b8605Smrg_mesa_base_pack_format(GLenum format) 391848b8605Smrg{ 392848b8605Smrg switch (format) { 393848b8605Smrg case GL_ABGR_EXT: 394848b8605Smrg case GL_BGRA: 395848b8605Smrg case GL_BGRA_INTEGER: 396848b8605Smrg case GL_RGBA_INTEGER: 397848b8605Smrg return GL_RGBA; 398848b8605Smrg case GL_BGR: 399848b8605Smrg case GL_BGR_INTEGER: 400848b8605Smrg case GL_RGB_INTEGER: 401848b8605Smrg return GL_RGB; 402848b8605Smrg case GL_RED_INTEGER: 403848b8605Smrg return GL_RED; 404848b8605Smrg case GL_GREEN_INTEGER: 405848b8605Smrg return GL_GREEN; 406848b8605Smrg case GL_BLUE_INTEGER: 407848b8605Smrg return GL_BLUE; 408848b8605Smrg case GL_ALPHA_INTEGER: 409848b8605Smrg return GL_ALPHA; 410848b8605Smrg case GL_LUMINANCE_INTEGER_EXT: 411848b8605Smrg return GL_LUMINANCE; 412848b8605Smrg case GL_LUMINANCE_ALPHA_INTEGER_EXT: 413848b8605Smrg return GL_LUMINANCE_ALPHA; 414848b8605Smrg default: 415848b8605Smrg return format; 416848b8605Smrg } 417848b8605Smrg} 418848b8605Smrg 419848b8605Smrg 420848b8605Smrg/** 421848b8605Smrg * Get an uncompressed color texture image. 422848b8605Smrg */ 423848b8605Smrgstatic void 424848b8605Smrgget_tex_rgba_uncompressed(struct gl_context *ctx, GLuint dimensions, 425b8e80941Smrg GLint xoffset, GLint yoffset, GLint zoffset, 426b8e80941Smrg GLsizei width, GLsizei height, GLint depth, 427848b8605Smrg GLenum format, GLenum type, GLvoid *pixels, 428848b8605Smrg struct gl_texture_image *texImage, 429848b8605Smrg GLbitfield transferOps) 430848b8605Smrg{ 431848b8605Smrg /* don't want to apply sRGB -> RGB conversion here so override the format */ 432848b8605Smrg const mesa_format texFormat = 433848b8605Smrg _mesa_get_srgb_format_linear(texImage->TexFormat); 434b8e80941Smrg GLuint img; 435b8e80941Smrg GLboolean dst_is_integer; 436b8e80941Smrg uint32_t dst_format; 437b8e80941Smrg int dst_stride; 438b8e80941Smrg uint8_t rebaseSwizzle[4]; 439b8e80941Smrg bool needsRebase; 440b8e80941Smrg void *rgba = NULL; 441b8e80941Smrg 442b8e80941Smrg needsRebase = teximage_needs_rebase(texFormat, texImage->_BaseFormat, false, 443b8e80941Smrg rebaseSwizzle); 444b8e80941Smrg 445b8e80941Smrg /* Describe the dst format */ 446b8e80941Smrg dst_is_integer = _mesa_is_enum_format_integer(format); 447b8e80941Smrg dst_format = _mesa_format_from_format_and_type(format, type); 448b8e80941Smrg dst_stride = _mesa_image_row_stride(&ctx->Pack, width, format, type); 449b8e80941Smrg 450b8e80941Smrg /* Since _mesa_format_convert does not handle transferOps we need to handle 451b8e80941Smrg * them before we call the function. This requires to convert to RGBA float 452b8e80941Smrg * first so we can call _mesa_apply_rgba_transfer_ops. If the dst format is 453b8e80941Smrg * integer then transferOps do not apply. 454b8e80941Smrg */ 455b8e80941Smrg assert(!transferOps || (transferOps && !dst_is_integer)); 456b8e80941Smrg (void) dst_is_integer; /* silence unused var warning */ 457848b8605Smrg 458848b8605Smrg for (img = 0; img < depth; img++) { 459848b8605Smrg GLubyte *srcMap; 460848b8605Smrg GLint rowstride; 461b8e80941Smrg GLubyte *img_src; 462b8e80941Smrg void *dest; 463b8e80941Smrg void *src; 464b8e80941Smrg int src_stride; 465b8e80941Smrg uint32_t src_format; 466848b8605Smrg 467848b8605Smrg /* map src texture buffer */ 468b8e80941Smrg ctx->Driver.MapTextureImage(ctx, texImage, zoffset + img, 469b8e80941Smrg xoffset, yoffset, width, height, 470b8e80941Smrg GL_MAP_READ_BIT, 471848b8605Smrg &srcMap, &rowstride); 472b8e80941Smrg if (!srcMap) { 473b8e80941Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage"); 474b8e80941Smrg goto done; 475b8e80941Smrg } 476848b8605Smrg 477b8e80941Smrg img_src = srcMap; 478b8e80941Smrg dest = _mesa_image_address(dimensions, &ctx->Pack, pixels, 479b8e80941Smrg width, height, format, type, 480b8e80941Smrg img, 0, 0); 481b8e80941Smrg 482b8e80941Smrg if (transferOps) { 483b8e80941Smrg uint32_t rgba_format; 484b8e80941Smrg int rgba_stride; 485b8e80941Smrg bool need_convert = false; 486b8e80941Smrg 487b8e80941Smrg /* We will convert to RGBA float */ 488b8e80941Smrg rgba_format = RGBA32_FLOAT; 489b8e80941Smrg rgba_stride = width * 4 * sizeof(GLfloat); 490b8e80941Smrg 491b8e80941Smrg /* If we are lucky and the dst format matches the RGBA format we need 492b8e80941Smrg * to convert to, then we can convert directly into the dst buffer 493b8e80941Smrg * and avoid the final conversion/copy from the rgba buffer to the dst 494b8e80941Smrg * buffer. 495b8e80941Smrg */ 496b8e80941Smrg if (format == rgba_format) { 497b8e80941Smrg rgba = dest; 498b8e80941Smrg } else { 499b8e80941Smrg need_convert = true; 500b8e80941Smrg if (rgba == NULL) { /* Allocate the RGBA buffer only once */ 501b8e80941Smrg rgba = malloc(height * rgba_stride); 502b8e80941Smrg if (!rgba) { 503b8e80941Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage()"); 504b8e80941Smrg ctx->Driver.UnmapTextureImage(ctx, texImage, img); 505b8e80941Smrg return; 506848b8605Smrg } 507b8e80941Smrg } 508b8e80941Smrg } 509b8e80941Smrg 510b8e80941Smrg _mesa_format_convert(rgba, rgba_format, rgba_stride, 511b8e80941Smrg img_src, texFormat, rowstride, 512b8e80941Smrg width, height, 513b8e80941Smrg needsRebase ? rebaseSwizzle : NULL); 514b8e80941Smrg 515b8e80941Smrg /* Handle transfer ops now */ 516b8e80941Smrg _mesa_apply_rgba_transfer_ops(ctx, transferOps, width * height, rgba); 517b8e80941Smrg 518b8e80941Smrg /* If we had to rebase, we have already handled that */ 519b8e80941Smrg needsRebase = false; 520b8e80941Smrg 521b8e80941Smrg /* If we were lucky and our RGBA conversion matches the dst format, 522b8e80941Smrg * then we are done. 523b8e80941Smrg */ 524b8e80941Smrg if (!need_convert) 525b8e80941Smrg goto do_swap; 526b8e80941Smrg 527b8e80941Smrg /* Otherwise, we need to convert from RGBA to dst next */ 528b8e80941Smrg src = rgba; 529b8e80941Smrg src_format = rgba_format; 530b8e80941Smrg src_stride = rgba_stride; 531b8e80941Smrg } else { 532b8e80941Smrg /* No RGBA conversion needed, convert directly to dst */ 533b8e80941Smrg src = img_src; 534b8e80941Smrg src_format = texFormat; 535b8e80941Smrg src_stride = rowstride; 536848b8605Smrg } 537b8e80941Smrg 538b8e80941Smrg /* Do the conversion to destination format */ 539b8e80941Smrg _mesa_format_convert(dest, dst_format, dst_stride, 540b8e80941Smrg src, src_format, src_stride, 541b8e80941Smrg width, height, 542b8e80941Smrg needsRebase ? rebaseSwizzle : NULL); 543b8e80941Smrg 544b8e80941Smrg do_swap: 545b8e80941Smrg /* Handle byte swapping if required */ 546b8e80941Smrg if (ctx->Pack.SwapBytes) 547b8e80941Smrg _mesa_swap_bytes_2d_image(format, type, &ctx->Pack, 548b8e80941Smrg width, height, dest, dest); 549b8e80941Smrg 550b8e80941Smrg /* Unmap the src texture buffer */ 551b8e80941Smrg ctx->Driver.UnmapTextureImage(ctx, texImage, zoffset + img); 552848b8605Smrg } 553848b8605Smrg 554b8e80941Smrgdone: 555848b8605Smrg free(rgba); 556848b8605Smrg} 557848b8605Smrg 558848b8605Smrg 559848b8605Smrg/** 560848b8605Smrg * glGetTexImage for color formats (RGBA, RGB, alpha, LA, etc). 561848b8605Smrg * Compressed textures are handled here as well. 562848b8605Smrg */ 563848b8605Smrgstatic void 564848b8605Smrgget_tex_rgba(struct gl_context *ctx, GLuint dimensions, 565b8e80941Smrg GLint xoffset, GLint yoffset, GLint zoffset, 566b8e80941Smrg GLsizei width, GLsizei height, GLint depth, 567848b8605Smrg GLenum format, GLenum type, GLvoid *pixels, 568848b8605Smrg struct gl_texture_image *texImage) 569848b8605Smrg{ 570848b8605Smrg const GLenum dataType = _mesa_get_format_datatype(texImage->TexFormat); 571848b8605Smrg GLbitfield transferOps = 0x0; 572848b8605Smrg 573848b8605Smrg /* In general, clamping does not apply to glGetTexImage, except when 574848b8605Smrg * the returned type of the image can't hold negative values. 575848b8605Smrg */ 576848b8605Smrg if (type_needs_clamping(type)) { 577848b8605Smrg /* the returned image type can't have negative values */ 578848b8605Smrg if (dataType == GL_FLOAT || 579848b8605Smrg dataType == GL_HALF_FLOAT || 580848b8605Smrg dataType == GL_SIGNED_NORMALIZED || 581848b8605Smrg format == GL_LUMINANCE || 582848b8605Smrg format == GL_LUMINANCE_ALPHA) { 583848b8605Smrg transferOps |= IMAGE_CLAMP_BIT; 584848b8605Smrg } 585848b8605Smrg } 586848b8605Smrg 587848b8605Smrg if (_mesa_is_format_compressed(texImage->TexFormat)) { 588b8e80941Smrg get_tex_rgba_compressed(ctx, dimensions, 589b8e80941Smrg xoffset, yoffset, zoffset, 590b8e80941Smrg width, height, depth, 591b8e80941Smrg format, type, 592848b8605Smrg pixels, texImage, transferOps); 593848b8605Smrg } 594848b8605Smrg else { 595b8e80941Smrg get_tex_rgba_uncompressed(ctx, dimensions, 596b8e80941Smrg xoffset, yoffset, zoffset, 597b8e80941Smrg width, height, depth, 598b8e80941Smrg format, type, 599848b8605Smrg pixels, texImage, transferOps); 600848b8605Smrg } 601848b8605Smrg} 602848b8605Smrg 603848b8605Smrg 604848b8605Smrg/** 605848b8605Smrg * Try to do glGetTexImage() with simple memcpy(). 606848b8605Smrg * \return GL_TRUE if done, GL_FALSE otherwise 607848b8605Smrg */ 608848b8605Smrgstatic GLboolean 609b8e80941Smrgget_tex_memcpy(struct gl_context *ctx, 610b8e80941Smrg GLint xoffset, GLint yoffset, GLint zoffset, 611b8e80941Smrg GLsizei width, GLsizei height, GLint depth, 612b8e80941Smrg GLenum format, GLenum type, GLvoid *pixels, 613848b8605Smrg struct gl_texture_image *texImage) 614848b8605Smrg{ 615848b8605Smrg const GLenum target = texImage->TexObject->Target; 616848b8605Smrg GLboolean memCopy = GL_FALSE; 617848b8605Smrg GLenum texBaseFormat = _mesa_get_format_base_format(texImage->TexFormat); 618848b8605Smrg 619848b8605Smrg /* 620848b8605Smrg * Check if we can use memcpy to copy from the hardware texture 621848b8605Smrg * format to the user's format/type. 622848b8605Smrg * Note that GL's pixel transfer ops don't apply to glGetTexImage() 623848b8605Smrg */ 624848b8605Smrg if ((target == GL_TEXTURE_1D || 625848b8605Smrg target == GL_TEXTURE_2D || 626848b8605Smrg target == GL_TEXTURE_RECTANGLE || 627848b8605Smrg _mesa_is_cube_face(target)) && 628848b8605Smrg texBaseFormat == texImage->_BaseFormat) { 629848b8605Smrg memCopy = _mesa_format_matches_format_and_type(texImage->TexFormat, 630848b8605Smrg format, type, 631b8e80941Smrg ctx->Pack.SwapBytes, NULL); 632b8e80941Smrg } 633b8e80941Smrg 634b8e80941Smrg if (depth > 1) { 635b8e80941Smrg /* only a single slice is supported at this time */ 636b8e80941Smrg memCopy = FALSE; 637848b8605Smrg } 638848b8605Smrg 639848b8605Smrg if (memCopy) { 640848b8605Smrg const GLuint bpp = _mesa_get_format_bytes(texImage->TexFormat); 641b8e80941Smrg const GLint bytesPerRow = width * bpp; 642848b8605Smrg GLubyte *dst = 643b8e80941Smrg _mesa_image_address2d(&ctx->Pack, pixels, width, height, 644b8e80941Smrg format, type, 0, 0); 645848b8605Smrg const GLint dstRowStride = 646b8e80941Smrg _mesa_image_row_stride(&ctx->Pack, width, format, type); 647848b8605Smrg GLubyte *src; 648848b8605Smrg GLint srcRowStride; 649848b8605Smrg 650848b8605Smrg /* map src texture buffer */ 651b8e80941Smrg ctx->Driver.MapTextureImage(ctx, texImage, zoffset, 652b8e80941Smrg xoffset, yoffset, width, height, 653848b8605Smrg GL_MAP_READ_BIT, &src, &srcRowStride); 654848b8605Smrg 655848b8605Smrg if (src) { 656848b8605Smrg if (bytesPerRow == dstRowStride && bytesPerRow == srcRowStride) { 657b8e80941Smrg memcpy(dst, src, bytesPerRow * height); 658848b8605Smrg } 659848b8605Smrg else { 660848b8605Smrg GLuint row; 661b8e80941Smrg for (row = 0; row < height; row++) { 662848b8605Smrg memcpy(dst, src, bytesPerRow); 663848b8605Smrg dst += dstRowStride; 664848b8605Smrg src += srcRowStride; 665848b8605Smrg } 666848b8605Smrg } 667848b8605Smrg 668848b8605Smrg /* unmap src texture buffer */ 669b8e80941Smrg ctx->Driver.UnmapTextureImage(ctx, texImage, zoffset); 670848b8605Smrg } 671848b8605Smrg else { 672848b8605Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage"); 673848b8605Smrg } 674848b8605Smrg } 675848b8605Smrg 676848b8605Smrg return memCopy; 677848b8605Smrg} 678848b8605Smrg 679848b8605Smrg 680848b8605Smrg/** 681b8e80941Smrg * This is the software fallback for Driver.GetTexSubImage(). 682848b8605Smrg * All error checking will have been done before this routine is called. 683848b8605Smrg * We'll call ctx->Driver.MapTextureImage() to access the data, then 684848b8605Smrg * unmap with ctx->Driver.UnmapTextureImage(). 685848b8605Smrg */ 686848b8605Smrgvoid 687b8e80941Smrg_mesa_GetTexSubImage_sw(struct gl_context *ctx, 688b8e80941Smrg GLint xoffset, GLint yoffset, GLint zoffset, 689b8e80941Smrg GLsizei width, GLsizei height, GLint depth, 690b8e80941Smrg GLenum format, GLenum type, GLvoid *pixels, 691b8e80941Smrg struct gl_texture_image *texImage) 692848b8605Smrg{ 693848b8605Smrg const GLuint dimensions = 694848b8605Smrg _mesa_get_texture_dimensions(texImage->TexObject->Target); 695848b8605Smrg 696848b8605Smrg /* map dest buffer, if PBO */ 697848b8605Smrg if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { 698848b8605Smrg /* Packing texture image into a PBO. 699848b8605Smrg * Map the (potentially) VRAM-based buffer into our process space so 700848b8605Smrg * we can write into it with the code below. 701848b8605Smrg * A hardware driver might use a sophisticated blit to move the 702848b8605Smrg * texture data to the PBO if the PBO is in VRAM along with the texture. 703848b8605Smrg */ 704848b8605Smrg GLubyte *buf = (GLubyte *) 705848b8605Smrg ctx->Driver.MapBufferRange(ctx, 0, ctx->Pack.BufferObj->Size, 706848b8605Smrg GL_MAP_WRITE_BIT, ctx->Pack.BufferObj, 707848b8605Smrg MAP_INTERNAL); 708848b8605Smrg if (!buf) { 709848b8605Smrg /* out of memory or other unexpected error */ 710848b8605Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage(map PBO failed)"); 711848b8605Smrg return; 712848b8605Smrg } 713848b8605Smrg /* <pixels> was an offset into the PBO. 714848b8605Smrg * Now make it a real, client-side pointer inside the mapped region. 715848b8605Smrg */ 716848b8605Smrg pixels = ADD_POINTERS(buf, pixels); 717848b8605Smrg } 718848b8605Smrg 719b8e80941Smrg /* for all array textures, the Z axis selects the layer */ 720b8e80941Smrg if (texImage->TexObject->Target == GL_TEXTURE_1D_ARRAY) { 721b8e80941Smrg depth = height; 722b8e80941Smrg height = 1; 723b8e80941Smrg zoffset = yoffset; 724b8e80941Smrg yoffset = 0; 725b8e80941Smrg assert(zoffset + depth <= texImage->Height); 726b8e80941Smrg } else { 727b8e80941Smrg assert(zoffset + depth <= texImage->Depth); 728b8e80941Smrg } 729b8e80941Smrg 730b8e80941Smrg if (get_tex_memcpy(ctx, xoffset, yoffset, zoffset, width, height, depth, 731b8e80941Smrg format, type, pixels, texImage)) { 732848b8605Smrg /* all done */ 733848b8605Smrg } 734848b8605Smrg else if (format == GL_DEPTH_COMPONENT) { 735b8e80941Smrg get_tex_depth(ctx, dimensions, xoffset, yoffset, zoffset, 736b8e80941Smrg width, height, depth, format, type, pixels, texImage); 737848b8605Smrg } 738848b8605Smrg else if (format == GL_DEPTH_STENCIL_EXT) { 739b8e80941Smrg get_tex_depth_stencil(ctx, dimensions, xoffset, yoffset, zoffset, 740b8e80941Smrg width, height, depth, format, type, pixels, 741b8e80941Smrg texImage); 742b8e80941Smrg } 743b8e80941Smrg else if (format == GL_STENCIL_INDEX) { 744b8e80941Smrg get_tex_stencil(ctx, dimensions, xoffset, yoffset, zoffset, 745b8e80941Smrg width, height, depth, format, type, pixels, texImage); 746848b8605Smrg } 747848b8605Smrg else if (format == GL_YCBCR_MESA) { 748b8e80941Smrg get_tex_ycbcr(ctx, dimensions, xoffset, yoffset, zoffset, 749b8e80941Smrg width, height, depth, format, type, pixels, texImage); 750848b8605Smrg } 751848b8605Smrg else { 752b8e80941Smrg get_tex_rgba(ctx, dimensions, xoffset, yoffset, zoffset, 753b8e80941Smrg width, height, depth, format, type, pixels, texImage); 754848b8605Smrg } 755848b8605Smrg 756848b8605Smrg if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { 757848b8605Smrg ctx->Driver.UnmapBuffer(ctx, ctx->Pack.BufferObj, MAP_INTERNAL); 758848b8605Smrg } 759848b8605Smrg} 760848b8605Smrg 761848b8605Smrg 762848b8605Smrg 763848b8605Smrg/** 764b8e80941Smrg * This function assumes that all error checking has been done. 765848b8605Smrg */ 766b8e80941Smrgstatic void 767b8e80941Smrgget_compressed_texsubimage_sw(struct gl_context *ctx, 768848b8605Smrg struct gl_texture_image *texImage, 769b8e80941Smrg GLint xoffset, GLint yoffset, 770b8e80941Smrg GLint zoffset, GLsizei width, 771b8e80941Smrg GLint height, GLint depth, 772848b8605Smrg GLvoid *img) 773848b8605Smrg{ 774848b8605Smrg const GLuint dimensions = 775848b8605Smrg _mesa_get_texture_dimensions(texImage->TexObject->Target); 776848b8605Smrg struct compressed_pixelstore store; 777b8e80941Smrg GLint slice; 778848b8605Smrg GLubyte *dest; 779848b8605Smrg 780848b8605Smrg _mesa_compute_compressed_pixelstore(dimensions, texImage->TexFormat, 781b8e80941Smrg width, height, depth, 782b8e80941Smrg &ctx->Pack, &store); 783848b8605Smrg 784848b8605Smrg if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { 785848b8605Smrg /* pack texture image into a PBO */ 786848b8605Smrg dest = (GLubyte *) 787848b8605Smrg ctx->Driver.MapBufferRange(ctx, 0, ctx->Pack.BufferObj->Size, 788848b8605Smrg GL_MAP_WRITE_BIT, ctx->Pack.BufferObj, 789848b8605Smrg MAP_INTERNAL); 790848b8605Smrg if (!dest) { 791848b8605Smrg /* out of memory or other unexpected error */ 792848b8605Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, 793848b8605Smrg "glGetCompresssedTexImage(map PBO failed)"); 794848b8605Smrg return; 795848b8605Smrg } 796848b8605Smrg dest = ADD_POINTERS(dest, img); 797848b8605Smrg } else { 798848b8605Smrg dest = img; 799848b8605Smrg } 800848b8605Smrg 801848b8605Smrg dest += store.SkipBytes; 802848b8605Smrg 803848b8605Smrg for (slice = 0; slice < store.CopySlices; slice++) { 804848b8605Smrg GLint srcRowStride; 805848b8605Smrg GLubyte *src; 806848b8605Smrg 807848b8605Smrg /* map src texture buffer */ 808b8e80941Smrg ctx->Driver.MapTextureImage(ctx, texImage, zoffset + slice, 809b8e80941Smrg xoffset, yoffset, width, height, 810848b8605Smrg GL_MAP_READ_BIT, &src, &srcRowStride); 811848b8605Smrg 812848b8605Smrg if (src) { 813b8e80941Smrg GLint i; 814848b8605Smrg for (i = 0; i < store.CopyRowsPerSlice; i++) { 815848b8605Smrg memcpy(dest, src, store.CopyBytesPerRow); 816848b8605Smrg dest += store.TotalBytesPerRow; 817848b8605Smrg src += srcRowStride; 818848b8605Smrg } 819848b8605Smrg 820b8e80941Smrg ctx->Driver.UnmapTextureImage(ctx, texImage, zoffset + slice); 821848b8605Smrg 822848b8605Smrg /* Advance to next slice */ 823b8e80941Smrg dest += store.TotalBytesPerRow * (store.TotalRowsPerSlice - 824b8e80941Smrg store.CopyRowsPerSlice); 825848b8605Smrg 826848b8605Smrg } else { 827848b8605Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetCompresssedTexImage"); 828848b8605Smrg } 829848b8605Smrg } 830848b8605Smrg 831848b8605Smrg if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { 832848b8605Smrg ctx->Driver.UnmapBuffer(ctx, ctx->Pack.BufferObj, MAP_INTERNAL); 833848b8605Smrg } 834848b8605Smrg} 835848b8605Smrg 836848b8605Smrg 837848b8605Smrg/** 838b8e80941Smrg * Validate the texture target enum supplied to glGetTex(ture)Image or 839b8e80941Smrg * glGetCompressedTex(ture)Image. 840848b8605Smrg */ 841848b8605Smrgstatic GLboolean 842b8e80941Smrglegal_getteximage_target(struct gl_context *ctx, GLenum target, bool dsa) 843848b8605Smrg{ 844848b8605Smrg switch (target) { 845848b8605Smrg case GL_TEXTURE_1D: 846848b8605Smrg case GL_TEXTURE_2D: 847848b8605Smrg case GL_TEXTURE_3D: 848848b8605Smrg return GL_TRUE; 849848b8605Smrg case GL_TEXTURE_RECTANGLE_NV: 850848b8605Smrg return ctx->Extensions.NV_texture_rectangle; 851848b8605Smrg case GL_TEXTURE_1D_ARRAY_EXT: 852848b8605Smrg case GL_TEXTURE_2D_ARRAY_EXT: 853848b8605Smrg return ctx->Extensions.EXT_texture_array; 854848b8605Smrg case GL_TEXTURE_CUBE_MAP_ARRAY: 855848b8605Smrg return ctx->Extensions.ARB_texture_cube_map_array; 856b8e80941Smrg 857b8e80941Smrg /* Section 8.11 (Texture Queries) of the OpenGL 4.5 core profile spec 858b8e80941Smrg * (30.10.2014) says: 859b8e80941Smrg * "An INVALID_ENUM error is generated if the effective target is not 860b8e80941Smrg * one of TEXTURE_1D, TEXTURE_2D, TEXTURE_3D, TEXTURE_1D_ARRAY, 861b8e80941Smrg * TEXTURE_2D_ARRAY, TEXTURE_CUBE_MAP_ARRAY, TEXTURE_RECTANGLE, one of 862b8e80941Smrg * the targets from table 8.19 (for GetTexImage and GetnTexImage *only*), 863b8e80941Smrg * or TEXTURE_CUBE_MAP (for GetTextureImage *only*)." (Emphasis added.) 864b8e80941Smrg */ 865b8e80941Smrg case GL_TEXTURE_CUBE_MAP_POSITIVE_X: 866b8e80941Smrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: 867b8e80941Smrg case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: 868b8e80941Smrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: 869b8e80941Smrg case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: 870b8e80941Smrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: 871b8e80941Smrg return dsa ? GL_FALSE : ctx->Extensions.ARB_texture_cube_map; 872b8e80941Smrg case GL_TEXTURE_CUBE_MAP: 873b8e80941Smrg return dsa ? GL_TRUE : GL_FALSE; 874848b8605Smrg default: 875848b8605Smrg return GL_FALSE; 876848b8605Smrg } 877848b8605Smrg} 878848b8605Smrg 879848b8605Smrg 880848b8605Smrg/** 881b8e80941Smrg * Wrapper for _mesa_select_tex_image() which can handle target being 882b8e80941Smrg * GL_TEXTURE_CUBE_MAP in which case we use zoffset to select a cube face. 883b8e80941Smrg * This can happen for glGetTextureImage and glGetTextureSubImage (DSA 884b8e80941Smrg * functions). 885848b8605Smrg */ 886b8e80941Smrgstatic struct gl_texture_image * 887b8e80941Smrgselect_tex_image(const struct gl_texture_object *texObj, GLenum target, 888b8e80941Smrg GLint level, GLint zoffset) 889848b8605Smrg{ 890b8e80941Smrg assert(level >= 0); 891b8e80941Smrg assert(level < MAX_TEXTURE_LEVELS); 892b8e80941Smrg if (target == GL_TEXTURE_CUBE_MAP) { 893b8e80941Smrg assert(zoffset >= 0); 894b8e80941Smrg assert(zoffset < 6); 895b8e80941Smrg target = GL_TEXTURE_CUBE_MAP_POSITIVE_X + zoffset; 896b8e80941Smrg } 897b8e80941Smrg return _mesa_select_tex_image(texObj, target, level); 898b8e80941Smrg} 899848b8605Smrg 900b8e80941Smrg 901b8e80941Smrg/** 902b8e80941Smrg * Error-check the offset and size arguments to 903b8e80941Smrg * glGet[Compressed]TextureSubImage(). 904b8e80941Smrg * \return true if error, false if no error. 905b8e80941Smrg */ 906b8e80941Smrgstatic bool 907b8e80941Smrgdimensions_error_check(struct gl_context *ctx, 908b8e80941Smrg struct gl_texture_object *texObj, 909b8e80941Smrg GLenum target, GLint level, 910b8e80941Smrg GLint xoffset, GLint yoffset, GLint zoffset, 911b8e80941Smrg GLsizei width, GLsizei height, GLsizei depth, 912b8e80941Smrg const char *caller) 913b8e80941Smrg{ 914b8e80941Smrg const struct gl_texture_image *texImage; 915b8e80941Smrg GLuint imageWidth = 0, imageHeight = 0, imageDepth = 0; 916b8e80941Smrg 917b8e80941Smrg if (xoffset < 0) { 918b8e80941Smrg _mesa_error(ctx, GL_INVALID_VALUE, "%s(xoffset = %d)", caller, xoffset); 919b8e80941Smrg return true; 920848b8605Smrg } 921848b8605Smrg 922b8e80941Smrg if (yoffset < 0) { 923b8e80941Smrg _mesa_error(ctx, GL_INVALID_VALUE, "%s(yoffset = %d)", caller, yoffset); 924b8e80941Smrg return true; 925848b8605Smrg } 926848b8605Smrg 927b8e80941Smrg if (zoffset < 0) { 928b8e80941Smrg _mesa_error(ctx, GL_INVALID_VALUE, "%s(zoffset = %d)", caller, zoffset); 929b8e80941Smrg return true; 930848b8605Smrg } 931848b8605Smrg 932b8e80941Smrg if (width < 0) { 933b8e80941Smrg _mesa_error(ctx, GL_INVALID_VALUE, "%s(width = %d)", caller, width); 934b8e80941Smrg return true; 935b8e80941Smrg } 936848b8605Smrg 937b8e80941Smrg if (height < 0) { 938b8e80941Smrg _mesa_error(ctx, GL_INVALID_VALUE, "%s(height = %d)", caller, height); 939b8e80941Smrg return true; 940848b8605Smrg } 941848b8605Smrg 942b8e80941Smrg if (depth < 0) { 943b8e80941Smrg _mesa_error(ctx, GL_INVALID_VALUE, "%s(depth = %d)", caller, depth); 944b8e80941Smrg return true; 945848b8605Smrg } 946848b8605Smrg 947b8e80941Smrg /* do special per-target checks */ 948b8e80941Smrg switch (target) { 949b8e80941Smrg case GL_TEXTURE_1D: 950b8e80941Smrg if (yoffset != 0) { 951b8e80941Smrg _mesa_error(ctx, GL_INVALID_VALUE, 952b8e80941Smrg "%s(1D, yoffset = %d)", caller, yoffset); 953b8e80941Smrg return true; 954b8e80941Smrg } 955b8e80941Smrg if (height != 1) { 956b8e80941Smrg _mesa_error(ctx, GL_INVALID_VALUE, 957b8e80941Smrg "%s(1D, height = %d)", caller, height); 958b8e80941Smrg return true; 959b8e80941Smrg } 960b8e80941Smrg /* fall-through */ 961b8e80941Smrg case GL_TEXTURE_1D_ARRAY: 962b8e80941Smrg case GL_TEXTURE_2D: 963b8e80941Smrg case GL_TEXTURE_RECTANGLE: 964b8e80941Smrg if (zoffset != 0) { 965b8e80941Smrg _mesa_error(ctx, GL_INVALID_VALUE, 966b8e80941Smrg "%s(zoffset = %d)", caller, zoffset); 967b8e80941Smrg return true; 968b8e80941Smrg } 969b8e80941Smrg if (depth != 1) { 970b8e80941Smrg _mesa_error(ctx, GL_INVALID_VALUE, 971b8e80941Smrg "%s(depth = %d)", caller, depth); 972b8e80941Smrg return true; 973b8e80941Smrg } 974b8e80941Smrg break; 975b8e80941Smrg case GL_TEXTURE_CUBE_MAP: 976b8e80941Smrg /* Non-array cube maps are special because we have a gl_texture_image 977b8e80941Smrg * per face. 978b8e80941Smrg */ 979b8e80941Smrg if (zoffset + depth > 6) { 980b8e80941Smrg _mesa_error(ctx, GL_INVALID_VALUE, 981b8e80941Smrg "%s(zoffset + depth = %d)", caller, zoffset + depth); 982b8e80941Smrg return true; 983b8e80941Smrg } 984b8e80941Smrg break; 985b8e80941Smrg default: 986b8e80941Smrg ; /* nothing */ 987848b8605Smrg } 988b8e80941Smrg 989b8e80941Smrg texImage = select_tex_image(texObj, target, level, zoffset); 990b8e80941Smrg if (texImage) { 991b8e80941Smrg imageWidth = texImage->Width; 992b8e80941Smrg imageHeight = texImage->Height; 993b8e80941Smrg imageDepth = texImage->Depth; 994848b8605Smrg } 995b8e80941Smrg 996b8e80941Smrg if (xoffset + width > imageWidth) { 997b8e80941Smrg _mesa_error(ctx, GL_INVALID_VALUE, 998b8e80941Smrg "%s(xoffset %d + width %d > %u)", 999b8e80941Smrg caller, xoffset, width, imageWidth); 1000b8e80941Smrg return true; 1001848b8605Smrg } 1002b8e80941Smrg 1003b8e80941Smrg if (yoffset + height > imageHeight) { 1004b8e80941Smrg _mesa_error(ctx, GL_INVALID_VALUE, 1005b8e80941Smrg "%s(yoffset %d + height %d > %u)", 1006b8e80941Smrg caller, yoffset, height, imageHeight); 1007b8e80941Smrg return true; 1008848b8605Smrg } 1009b8e80941Smrg 1010b8e80941Smrg if (target != GL_TEXTURE_CUBE_MAP) { 1011b8e80941Smrg /* Cube map error checking was done above */ 1012b8e80941Smrg if (zoffset + depth > imageDepth) { 1013b8e80941Smrg _mesa_error(ctx, GL_INVALID_VALUE, 1014b8e80941Smrg "%s(zoffset %d + depth %d > %u)", 1015b8e80941Smrg caller, zoffset, depth, imageDepth); 1016b8e80941Smrg return true; 1017b8e80941Smrg } 1018848b8605Smrg } 1019b8e80941Smrg 1020b8e80941Smrg /* Extra checks for compressed textures */ 1021b8e80941Smrg if (texImage) { 1022b8e80941Smrg GLuint bw, bh, bd; 1023b8e80941Smrg _mesa_get_format_block_size_3d(texImage->TexFormat, &bw, &bh, &bd); 1024b8e80941Smrg if (bw > 1 || bh > 1 || bd > 1) { 1025b8e80941Smrg /* offset must be multiple of block size */ 1026b8e80941Smrg if (xoffset % bw != 0) { 1027b8e80941Smrg _mesa_error(ctx, GL_INVALID_VALUE, 1028b8e80941Smrg "%s(xoffset = %d)", caller, xoffset); 1029b8e80941Smrg return true; 1030b8e80941Smrg } 1031b8e80941Smrg if (target != GL_TEXTURE_1D && target != GL_TEXTURE_1D_ARRAY) { 1032b8e80941Smrg if (yoffset % bh != 0) { 1033b8e80941Smrg _mesa_error(ctx, GL_INVALID_VALUE, 1034b8e80941Smrg "%s(yoffset = %d)", caller, yoffset); 1035b8e80941Smrg return true; 1036b8e80941Smrg } 1037b8e80941Smrg } 1038b8e80941Smrg 1039b8e80941Smrg if (zoffset % bd != 0) { 1040b8e80941Smrg _mesa_error(ctx, GL_INVALID_VALUE, 1041b8e80941Smrg "%s(zoffset = %d)", caller, zoffset); 1042b8e80941Smrg return true; 1043b8e80941Smrg } 1044b8e80941Smrg 1045b8e80941Smrg /* The size must be a multiple of bw x bh x bd, or we must be using a 1046b8e80941Smrg * offset+size that exactly hits the edge of the image. 1047b8e80941Smrg */ 1048b8e80941Smrg if ((width % bw != 0) && 1049b8e80941Smrg (xoffset + width != (GLint) texImage->Width)) { 1050b8e80941Smrg _mesa_error(ctx, GL_INVALID_VALUE, 1051b8e80941Smrg "%s(width = %d)", caller, width); 1052b8e80941Smrg return true; 1053b8e80941Smrg } 1054b8e80941Smrg 1055b8e80941Smrg if ((height % bh != 0) && 1056b8e80941Smrg (yoffset + height != (GLint) texImage->Height)) { 1057b8e80941Smrg _mesa_error(ctx, GL_INVALID_VALUE, 1058b8e80941Smrg "%s(height = %d)", caller, height); 1059b8e80941Smrg return true; 1060b8e80941Smrg } 1061b8e80941Smrg 1062b8e80941Smrg if ((depth % bd != 0) && 1063b8e80941Smrg (zoffset + depth != (GLint) texImage->Depth)) { 1064b8e80941Smrg _mesa_error(ctx, GL_INVALID_VALUE, 1065b8e80941Smrg "%s(depth = %d)", caller, depth); 1066b8e80941Smrg return true; 1067b8e80941Smrg } 1068b8e80941Smrg } 1069b8e80941Smrg } 1070b8e80941Smrg 1071b8e80941Smrg if (width == 0 || height == 0 || depth == 0) { 1072b8e80941Smrg /* Not an error, but nothing to do. Return 'true' so that the 1073b8e80941Smrg * caller simply returns. 1074b8e80941Smrg */ 1075b8e80941Smrg return true; 1076848b8605Smrg } 1077848b8605Smrg 1078b8e80941Smrg return false; 1079b8e80941Smrg} 1080b8e80941Smrg 1081b8e80941Smrg 1082b8e80941Smrg/** 1083b8e80941Smrg * Do PBO-related error checking for getting uncompressed images. 1084b8e80941Smrg * \return true if there was an error (or the GetTexImage is to be a no-op) 1085b8e80941Smrg */ 1086b8e80941Smrgstatic bool 1087b8e80941Smrgpbo_error_check(struct gl_context *ctx, GLenum target, 1088b8e80941Smrg GLsizei width, GLsizei height, GLsizei depth, 1089b8e80941Smrg GLenum format, GLenum type, GLsizei clientMemSize, 1090b8e80941Smrg GLvoid *pixels, 1091b8e80941Smrg const char *caller) 1092b8e80941Smrg{ 1093b8e80941Smrg const GLuint dimensions = (target == GL_TEXTURE_3D) ? 3 : 2; 1094b8e80941Smrg 1095b8e80941Smrg if (!_mesa_validate_pbo_access(dimensions, &ctx->Pack, width, height, depth, 1096848b8605Smrg format, type, clientMemSize, pixels)) { 1097848b8605Smrg if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { 1098848b8605Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 1099b8e80941Smrg "%s(out of bounds PBO access)", caller); 1100848b8605Smrg } else { 1101848b8605Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 1102b8e80941Smrg "%s(out of bounds access: bufSize (%d) is too small)", 1103b8e80941Smrg caller, clientMemSize); 1104848b8605Smrg } 1105b8e80941Smrg return true; 1106848b8605Smrg } 1107848b8605Smrg 1108848b8605Smrg if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { 1109848b8605Smrg /* PBO should not be mapped */ 1110848b8605Smrg if (_mesa_check_disallowed_mapping(ctx->Pack.BufferObj)) { 1111848b8605Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 1112b8e80941Smrg "%s(PBO is mapped)", caller); 1113b8e80941Smrg return true; 1114848b8605Smrg } 1115848b8605Smrg } 1116848b8605Smrg 1117b8e80941Smrg if (!_mesa_is_bufferobj(ctx->Pack.BufferObj) && !pixels) { 1118b8e80941Smrg /* not an error, do nothing */ 1119b8e80941Smrg return true; 1120b8e80941Smrg } 1121848b8605Smrg 1122b8e80941Smrg return false; 1123b8e80941Smrg} 1124848b8605Smrg 1125848b8605Smrg 1126848b8605Smrg/** 1127b8e80941Smrg * Do teximage-related error checking for getting uncompressed images. 1128b8e80941Smrg * \return true if there was an error 1129848b8605Smrg */ 1130b8e80941Smrgstatic bool 1131b8e80941Smrgteximage_error_check(struct gl_context *ctx, 1132b8e80941Smrg struct gl_texture_image *texImage, 1133b8e80941Smrg GLenum format, const char *caller) 1134848b8605Smrg{ 1135b8e80941Smrg GLenum baseFormat; 1136b8e80941Smrg assert(texImage); 1137848b8605Smrg 1138b8e80941Smrg /* 1139b8e80941Smrg * Format and type checking has been moved up to GetnTexImage and 1140b8e80941Smrg * GetTextureImage so that it happens before getting the texImage object. 1141b8e80941Smrg */ 1142848b8605Smrg 1143b8e80941Smrg baseFormat = _mesa_get_format_base_format(texImage->TexFormat); 1144848b8605Smrg 1145b8e80941Smrg /* Make sure the requested image format is compatible with the 1146b8e80941Smrg * texture's format. 1147b8e80941Smrg */ 1148b8e80941Smrg if (_mesa_is_color_format(format) 1149b8e80941Smrg && !_mesa_is_color_format(baseFormat)) { 1150b8e80941Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 1151b8e80941Smrg "%s(format mismatch)", caller); 1152b8e80941Smrg return true; 1153848b8605Smrg } 1154b8e80941Smrg else if (_mesa_is_depth_format(format) 1155b8e80941Smrg && !_mesa_is_depth_format(baseFormat) 1156b8e80941Smrg && !_mesa_is_depthstencil_format(baseFormat)) { 1157b8e80941Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 1158b8e80941Smrg "%s(format mismatch)", caller); 1159b8e80941Smrg return true; 1160848b8605Smrg } 1161b8e80941Smrg else if (_mesa_is_stencil_format(format) 1162b8e80941Smrg && !ctx->Extensions.ARB_texture_stencil8) { 1163b8e80941Smrg _mesa_error(ctx, GL_INVALID_ENUM, 1164b8e80941Smrg "%s(format=GL_STENCIL_INDEX)", caller); 1165b8e80941Smrg return true; 1166848b8605Smrg } 1167b8e80941Smrg else if (_mesa_is_stencil_format(format) 1168b8e80941Smrg && !_mesa_is_depthstencil_format(baseFormat) 1169b8e80941Smrg && !_mesa_is_stencil_format(baseFormat)) { 1170b8e80941Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 1171b8e80941Smrg "%s(format mismatch)", caller); 1172b8e80941Smrg return true; 1173b8e80941Smrg } 1174b8e80941Smrg else if (_mesa_is_ycbcr_format(format) 1175b8e80941Smrg && !_mesa_is_ycbcr_format(baseFormat)) { 1176b8e80941Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 1177b8e80941Smrg "%s(format mismatch)", caller); 1178b8e80941Smrg return true; 1179b8e80941Smrg } 1180b8e80941Smrg else if (_mesa_is_depthstencil_format(format) 1181b8e80941Smrg && !_mesa_is_depthstencil_format(baseFormat)) { 1182b8e80941Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 1183b8e80941Smrg "%s(format mismatch)", caller); 1184b8e80941Smrg return true; 1185b8e80941Smrg } 1186b8e80941Smrg else if (!_mesa_is_stencil_format(format) && 1187b8e80941Smrg _mesa_is_enum_format_integer(format) != 1188b8e80941Smrg _mesa_is_format_integer(texImage->TexFormat)) { 1189b8e80941Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 1190b8e80941Smrg "%s(format mismatch)", caller); 1191b8e80941Smrg return true; 1192b8e80941Smrg } 1193b8e80941Smrg 1194b8e80941Smrg return false; 1195848b8605Smrg} 1196848b8605Smrg 1197848b8605Smrg 1198b8e80941Smrg/** 1199b8e80941Smrg * Do common teximage-related error checking for getting uncompressed images. 1200b8e80941Smrg * \return true if there was an error 1201b8e80941Smrg */ 1202b8e80941Smrgstatic bool 1203b8e80941Smrgcommon_error_check(struct gl_context *ctx, 1204b8e80941Smrg struct gl_texture_object *texObj, 1205b8e80941Smrg GLenum target, GLint level, 1206b8e80941Smrg GLsizei width, GLsizei height, GLsizei depth, 1207b8e80941Smrg GLenum format, GLenum type, GLsizei bufSize, 1208b8e80941Smrg GLvoid *pixels, const char *caller) 1209848b8605Smrg{ 1210b8e80941Smrg GLenum err; 1211b8e80941Smrg GLint maxLevels; 1212b8e80941Smrg 1213b8e80941Smrg if (texObj->Target == 0) { 1214b8e80941Smrg _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid texture)", caller); 1215b8e80941Smrg return true; 1216b8e80941Smrg } 1217b8e80941Smrg 1218b8e80941Smrg maxLevels = _mesa_max_texture_levels(ctx, target); 1219b8e80941Smrg if (level < 0 || level >= maxLevels) { 1220b8e80941Smrg _mesa_error(ctx, GL_INVALID_VALUE, "%s(level = %d)", caller, level); 1221b8e80941Smrg return true; 1222b8e80941Smrg } 1223b8e80941Smrg 1224b8e80941Smrg err = _mesa_error_check_format_and_type(ctx, format, type); 1225b8e80941Smrg if (err != GL_NO_ERROR) { 1226b8e80941Smrg _mesa_error(ctx, err, "%s(format/type)", caller); 1227b8e80941Smrg return true; 1228b8e80941Smrg } 1229b8e80941Smrg 1230b8e80941Smrg /* According to OpenGL 4.6 spec, section 8.11.4 ("Texture Image Queries"): 1231b8e80941Smrg * 1232b8e80941Smrg * "An INVALID_OPERATION error is generated by GetTextureImage if the 1233b8e80941Smrg * effective target is TEXTURE_CUBE_MAP or TEXTURE_CUBE_MAP_ARRAY , 1234b8e80941Smrg * and the texture object is not cube complete or cube array complete, 1235b8e80941Smrg * respectively." 1236b8e80941Smrg * 1237b8e80941Smrg * This applies also to GetTextureSubImage, GetCompressedTexImage, 1238b8e80941Smrg * GetCompressedTextureImage, and GetnCompressedTexImage. 1239b8e80941Smrg */ 1240b8e80941Smrg if (target == GL_TEXTURE_CUBE_MAP && !_mesa_cube_complete(texObj)) { 1241b8e80941Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 1242b8e80941Smrg "%s(cube incomplete)", caller); 1243b8e80941Smrg return true; 1244b8e80941Smrg } 1245b8e80941Smrg 1246b8e80941Smrg return false; 1247848b8605Smrg} 1248848b8605Smrg 1249848b8605Smrg 1250848b8605Smrg/** 1251b8e80941Smrg * Do error checking for all (non-compressed) get-texture-image functions. 1252b8e80941Smrg * \return true if any error, false if no errors. 1253848b8605Smrg */ 1254b8e80941Smrgstatic bool 1255b8e80941Smrggetteximage_error_check(struct gl_context *ctx, 1256b8e80941Smrg struct gl_texture_object *texObj, 1257b8e80941Smrg GLenum target, GLint level, 1258b8e80941Smrg GLsizei width, GLsizei height, GLsizei depth, 1259b8e80941Smrg GLenum format, GLenum type, GLsizei bufSize, 1260b8e80941Smrg GLvoid *pixels, const char *caller) 1261848b8605Smrg{ 1262848b8605Smrg struct gl_texture_image *texImage; 1263848b8605Smrg 1264b8e80941Smrg assert(texObj); 1265b8e80941Smrg 1266b8e80941Smrg if (common_error_check(ctx, texObj, target, level, width, height, depth, 1267b8e80941Smrg format, type, bufSize, pixels, caller)) { 1268b8e80941Smrg return true; 1269848b8605Smrg } 1270848b8605Smrg 1271b8e80941Smrg if (width == 0 || height == 0 || depth == 0) { 1272b8e80941Smrg /* Not an error, but nothing to do. Return 'true' so that the 1273b8e80941Smrg * caller simply returns. 1274b8e80941Smrg */ 1275b8e80941Smrg return true; 1276b8e80941Smrg } 1277b8e80941Smrg 1278b8e80941Smrg if (pbo_error_check(ctx, target, width, height, depth, 1279b8e80941Smrg format, type, bufSize, pixels, caller)) { 1280b8e80941Smrg return true; 1281b8e80941Smrg } 1282b8e80941Smrg 1283b8e80941Smrg texImage = select_tex_image(texObj, target, level, 0); 1284b8e80941Smrg if (teximage_error_check(ctx, texImage, format, caller)) { 1285b8e80941Smrg return true; 1286b8e80941Smrg } 1287b8e80941Smrg 1288b8e80941Smrg return false; 1289b8e80941Smrg} 1290b8e80941Smrg 1291b8e80941Smrg 1292b8e80941Smrg/** 1293b8e80941Smrg * Do error checking for all (non-compressed) get-texture-image functions. 1294b8e80941Smrg * \return true if any error, false if no errors. 1295b8e80941Smrg */ 1296b8e80941Smrgstatic bool 1297b8e80941Smrggettexsubimage_error_check(struct gl_context *ctx, 1298b8e80941Smrg struct gl_texture_object *texObj, 1299b8e80941Smrg GLenum target, GLint level, 1300b8e80941Smrg GLint xoffset, GLint yoffset, GLint zoffset, 1301b8e80941Smrg GLsizei width, GLsizei height, GLsizei depth, 1302b8e80941Smrg GLenum format, GLenum type, GLsizei bufSize, 1303b8e80941Smrg GLvoid *pixels, const char *caller) 1304b8e80941Smrg{ 1305b8e80941Smrg struct gl_texture_image *texImage; 1306b8e80941Smrg 1307b8e80941Smrg assert(texObj); 1308b8e80941Smrg 1309b8e80941Smrg if (common_error_check(ctx, texObj, target, level, width, height, depth, 1310b8e80941Smrg format, type, bufSize, pixels, caller)) { 1311b8e80941Smrg return true; 1312b8e80941Smrg } 1313b8e80941Smrg 1314b8e80941Smrg if (dimensions_error_check(ctx, texObj, target, level, 1315b8e80941Smrg xoffset, yoffset, zoffset, 1316b8e80941Smrg width, height, depth, caller)) { 1317b8e80941Smrg return true; 1318b8e80941Smrg } 1319b8e80941Smrg 1320b8e80941Smrg if (pbo_error_check(ctx, target, width, height, depth, 1321b8e80941Smrg format, type, bufSize, pixels, caller)) { 1322b8e80941Smrg return true; 1323b8e80941Smrg } 1324b8e80941Smrg 1325b8e80941Smrg texImage = select_tex_image(texObj, target, level, zoffset); 1326b8e80941Smrg if (teximage_error_check(ctx, texImage, format, caller)) { 1327b8e80941Smrg return true; 1328b8e80941Smrg } 1329b8e80941Smrg 1330b8e80941Smrg return false; 1331b8e80941Smrg} 1332b8e80941Smrg 1333b8e80941Smrg 1334b8e80941Smrg/** 1335b8e80941Smrg * Return the width, height and depth of a texture image. 1336b8e80941Smrg * This function must be resilient to bad parameter values since 1337b8e80941Smrg * this is called before full error checking. 1338b8e80941Smrg */ 1339b8e80941Smrgstatic void 1340b8e80941Smrgget_texture_image_dims(const struct gl_texture_object *texObj, 1341b8e80941Smrg GLenum target, GLint level, 1342b8e80941Smrg GLsizei *width, GLsizei *height, GLsizei *depth) 1343b8e80941Smrg{ 1344b8e80941Smrg const struct gl_texture_image *texImage = NULL; 1345b8e80941Smrg 1346b8e80941Smrg if (level >= 0 && level < MAX_TEXTURE_LEVELS) { 1347b8e80941Smrg texImage = _mesa_select_tex_image(texObj, target, level); 1348b8e80941Smrg } 1349b8e80941Smrg 1350b8e80941Smrg if (texImage) { 1351b8e80941Smrg *width = texImage->Width; 1352b8e80941Smrg *height = texImage->Height; 1353b8e80941Smrg if (target == GL_TEXTURE_CUBE_MAP) { 1354b8e80941Smrg *depth = 6; 1355b8e80941Smrg } 1356b8e80941Smrg else { 1357b8e80941Smrg *depth = texImage->Depth; 1358b8e80941Smrg } 1359b8e80941Smrg } 1360b8e80941Smrg else { 1361b8e80941Smrg *width = *height = *depth = 0; 1362b8e80941Smrg } 1363b8e80941Smrg} 1364b8e80941Smrg 1365b8e80941Smrg 1366b8e80941Smrg/** 1367b8e80941Smrg * Common code for all (uncompressed) get-texture-image functions. 1368b8e80941Smrg * \param texObj the texture object (should not be null) 1369b8e80941Smrg * \param target user-provided target, or 0 for DSA 1370b8e80941Smrg * \param level image level. 1371b8e80941Smrg * \param format pixel data format for returned image. 1372b8e80941Smrg * \param type pixel data type for returned image. 1373b8e80941Smrg * \param bufSize size of the pixels data buffer. 1374b8e80941Smrg * \param pixels returned pixel data. 1375b8e80941Smrg * \param caller name of calling function 1376b8e80941Smrg */ 1377b8e80941Smrgstatic void 1378b8e80941Smrgget_texture_image(struct gl_context *ctx, 1379b8e80941Smrg struct gl_texture_object *texObj, 1380b8e80941Smrg GLenum target, GLint level, 1381b8e80941Smrg GLint xoffset, GLint yoffset, GLint zoffset, 1382b8e80941Smrg GLsizei width, GLsizei height, GLint depth, 1383b8e80941Smrg GLenum format, GLenum type, 1384b8e80941Smrg GLvoid *pixels, const char *caller) 1385b8e80941Smrg{ 1386b8e80941Smrg struct gl_texture_image *texImage; 1387b8e80941Smrg unsigned firstFace, numFaces, i; 1388b8e80941Smrg GLint imageStride; 1389b8e80941Smrg 1390b8e80941Smrg FLUSH_VERTICES(ctx, 0); 1391b8e80941Smrg 1392b8e80941Smrg texImage = select_tex_image(texObj, target, level, zoffset); 1393b8e80941Smrg assert(texImage); /* should have been error checked already */ 1394b8e80941Smrg 1395b8e80941Smrg if (_mesa_is_zero_size_texture(texImage)) { 1396b8e80941Smrg /* no image data to return */ 1397b8e80941Smrg return; 1398b8e80941Smrg } 1399b8e80941Smrg 1400b8e80941Smrg if (MESA_VERBOSE & (VERBOSE_API | VERBOSE_TEXTURE)) { 1401b8e80941Smrg _mesa_debug(ctx, "%s(tex %u) format = %s, w=%d, h=%d," 1402b8e80941Smrg " dstFmt=0x%x, dstType=0x%x\n", 1403b8e80941Smrg caller, texObj->Name, 1404b8e80941Smrg _mesa_get_format_name(texImage->TexFormat), 1405b8e80941Smrg texImage->Width, texImage->Height, 1406b8e80941Smrg format, type); 1407b8e80941Smrg } 1408b8e80941Smrg 1409b8e80941Smrg if (target == GL_TEXTURE_CUBE_MAP) { 1410b8e80941Smrg /* Compute stride between cube faces */ 1411b8e80941Smrg imageStride = _mesa_image_image_stride(&ctx->Pack, width, height, 1412b8e80941Smrg format, type); 1413b8e80941Smrg firstFace = zoffset; 1414b8e80941Smrg numFaces = depth; 1415b8e80941Smrg zoffset = 0; 1416b8e80941Smrg depth = 1; 1417b8e80941Smrg } 1418b8e80941Smrg else { 1419b8e80941Smrg imageStride = 0; 1420b8e80941Smrg firstFace = _mesa_tex_target_to_face(target); 1421b8e80941Smrg numFaces = 1; 1422b8e80941Smrg } 1423b8e80941Smrg 1424b8e80941Smrg _mesa_lock_texture(ctx, texObj); 1425b8e80941Smrg 1426b8e80941Smrg for (i = 0; i < numFaces; i++) { 1427b8e80941Smrg texImage = texObj->Image[firstFace + i][level]; 1428b8e80941Smrg assert(texImage); 1429b8e80941Smrg 1430b8e80941Smrg ctx->Driver.GetTexSubImage(ctx, xoffset, yoffset, zoffset, 1431b8e80941Smrg width, height, depth, 1432b8e80941Smrg format, type, pixels, texImage); 1433b8e80941Smrg 1434b8e80941Smrg /* next cube face */ 1435b8e80941Smrg pixels = (GLubyte *) pixels + imageStride; 1436b8e80941Smrg } 1437b8e80941Smrg 1438b8e80941Smrg _mesa_unlock_texture(ctx, texObj); 1439b8e80941Smrg} 1440b8e80941Smrg 1441b8e80941Smrg 1442b8e80941Smrgvoid GLAPIENTRY 1443b8e80941Smrg_mesa_GetnTexImageARB(GLenum target, GLint level, GLenum format, GLenum type, 1444b8e80941Smrg GLsizei bufSize, GLvoid *pixels) 1445b8e80941Smrg{ 1446b8e80941Smrg GET_CURRENT_CONTEXT(ctx); 1447b8e80941Smrg static const char *caller = "glGetnTexImageARB"; 1448b8e80941Smrg GLsizei width, height, depth; 1449b8e80941Smrg struct gl_texture_object *texObj; 1450b8e80941Smrg 1451b8e80941Smrg if (!legal_getteximage_target(ctx, target, false)) { 1452b8e80941Smrg _mesa_error(ctx, GL_INVALID_ENUM, "%s", caller); 1453b8e80941Smrg return; 1454b8e80941Smrg } 1455b8e80941Smrg 1456b8e80941Smrg texObj = _mesa_get_current_tex_object(ctx, target); 1457b8e80941Smrg assert(texObj); 1458b8e80941Smrg 1459b8e80941Smrg get_texture_image_dims(texObj, target, level, &width, &height, &depth); 1460b8e80941Smrg 1461b8e80941Smrg if (getteximage_error_check(ctx, texObj, target, level, 1462b8e80941Smrg width, height, depth, 1463b8e80941Smrg format, type, bufSize, pixels, caller)) { 1464b8e80941Smrg return; 1465b8e80941Smrg } 1466b8e80941Smrg 1467b8e80941Smrg get_texture_image(ctx, texObj, target, level, 1468b8e80941Smrg 0, 0, 0, width, height, depth, 1469b8e80941Smrg format, type, pixels, caller); 1470b8e80941Smrg} 1471b8e80941Smrg 1472b8e80941Smrg 1473b8e80941Smrgvoid GLAPIENTRY 1474b8e80941Smrg_mesa_GetTexImage(GLenum target, GLint level, GLenum format, GLenum type, 1475b8e80941Smrg GLvoid *pixels ) 1476b8e80941Smrg{ 1477b8e80941Smrg GET_CURRENT_CONTEXT(ctx); 1478b8e80941Smrg static const char *caller = "glGetTexImage"; 1479b8e80941Smrg GLsizei width, height, depth; 1480b8e80941Smrg struct gl_texture_object *texObj; 1481b8e80941Smrg 1482b8e80941Smrg if (!legal_getteximage_target(ctx, target, false)) { 1483b8e80941Smrg _mesa_error(ctx, GL_INVALID_ENUM, "%s", caller); 1484b8e80941Smrg return; 1485848b8605Smrg } 1486848b8605Smrg 1487848b8605Smrg texObj = _mesa_get_current_tex_object(ctx, target); 1488b8e80941Smrg assert(texObj); 1489b8e80941Smrg 1490b8e80941Smrg get_texture_image_dims(texObj, target, level, &width, &height, &depth); 1491b8e80941Smrg 1492b8e80941Smrg if (getteximage_error_check(ctx, texObj, target, level, 1493b8e80941Smrg width, height, depth, 1494b8e80941Smrg format, type, INT_MAX, pixels, caller)) { 1495b8e80941Smrg return; 1496b8e80941Smrg } 1497b8e80941Smrg 1498b8e80941Smrg get_texture_image(ctx, texObj, target, level, 1499b8e80941Smrg 0, 0, 0, width, height, depth, 1500b8e80941Smrg format, type, pixels, caller); 1501b8e80941Smrg} 1502b8e80941Smrg 1503b8e80941Smrg 1504b8e80941Smrgvoid GLAPIENTRY 1505b8e80941Smrg_mesa_GetTextureImage(GLuint texture, GLint level, GLenum format, GLenum type, 1506b8e80941Smrg GLsizei bufSize, GLvoid *pixels) 1507b8e80941Smrg{ 1508b8e80941Smrg GET_CURRENT_CONTEXT(ctx); 1509b8e80941Smrg GLsizei width, height, depth; 1510b8e80941Smrg static const char *caller = "glGetTextureImage"; 1511b8e80941Smrg struct gl_texture_object *texObj = 1512b8e80941Smrg _mesa_lookup_texture_err(ctx, texture, caller); 1513b8e80941Smrg 1514848b8605Smrg if (!texObj) { 1515b8e80941Smrg return; 1516b8e80941Smrg } 1517b8e80941Smrg 1518b8e80941Smrg if (!legal_getteximage_target(ctx, texObj->Target, true)) { 1519b8e80941Smrg _mesa_error(ctx, GL_INVALID_OPERATION, "%s", caller); 1520b8e80941Smrg return; 1521848b8605Smrg } 1522848b8605Smrg 1523b8e80941Smrg get_texture_image_dims(texObj, texObj->Target, level, 1524b8e80941Smrg &width, &height, &depth); 1525b8e80941Smrg 1526b8e80941Smrg if (getteximage_error_check(ctx, texObj, texObj->Target, level, 1527b8e80941Smrg width, height, depth, 1528b8e80941Smrg format, type, bufSize, pixels, caller)) { 1529b8e80941Smrg return; 1530b8e80941Smrg } 1531b8e80941Smrg 1532b8e80941Smrg get_texture_image(ctx, texObj, texObj->Target, level, 1533b8e80941Smrg 0, 0, 0, width, height, depth, 1534b8e80941Smrg format, type, pixels, caller); 1535b8e80941Smrg} 1536b8e80941Smrg 1537b8e80941Smrg 1538b8e80941Smrgvoid GLAPIENTRY 1539b8e80941Smrg_mesa_GetTextureSubImage(GLuint texture, GLint level, 1540b8e80941Smrg GLint xoffset, GLint yoffset, GLint zoffset, 1541b8e80941Smrg GLsizei width, GLsizei height, GLsizei depth, 1542b8e80941Smrg GLenum format, GLenum type, GLsizei bufSize, 1543b8e80941Smrg void *pixels) 1544b8e80941Smrg{ 1545b8e80941Smrg GET_CURRENT_CONTEXT(ctx); 1546b8e80941Smrg static const char *caller = "glGetTextureSubImage"; 1547b8e80941Smrg struct gl_texture_object *texObj = 1548b8e80941Smrg _mesa_lookup_texture_err(ctx, texture, caller); 1549848b8605Smrg 1550b8e80941Smrg if (!texObj) { 1551b8e80941Smrg return; 1552b8e80941Smrg } 1553b8e80941Smrg 1554b8e80941Smrg if (!legal_getteximage_target(ctx, texObj->Target, true)) { 1555b8e80941Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 1556b8e80941Smrg "%s(buffer/multisample texture)", caller); 1557b8e80941Smrg return; 1558b8e80941Smrg } 1559b8e80941Smrg 1560b8e80941Smrg if (gettexsubimage_error_check(ctx, texObj, texObj->Target, level, 1561b8e80941Smrg xoffset, yoffset, zoffset, 1562b8e80941Smrg width, height, depth, 1563b8e80941Smrg format, type, bufSize, pixels, caller)) { 1564b8e80941Smrg return; 1565b8e80941Smrg } 1566b8e80941Smrg 1567b8e80941Smrg get_texture_image(ctx, texObj, texObj->Target, level, 1568b8e80941Smrg xoffset, yoffset, zoffset, width, height, depth, 1569b8e80941Smrg format, type, pixels, caller); 1570b8e80941Smrg} 1571b8e80941Smrg 1572b8e80941Smrg 1573b8e80941Smrg 1574b8e80941Smrg/** 1575b8e80941Smrg * Compute the number of bytes which will be written when retrieving 1576b8e80941Smrg * a sub-region of a compressed texture. 1577b8e80941Smrg */ 1578b8e80941Smrgstatic GLsizei 1579b8e80941Smrgpacked_compressed_size(GLuint dimensions, mesa_format format, 1580b8e80941Smrg GLsizei width, GLsizei height, GLsizei depth, 1581b8e80941Smrg const struct gl_pixelstore_attrib *packing) 1582b8e80941Smrg{ 1583b8e80941Smrg struct compressed_pixelstore st; 1584b8e80941Smrg GLsizei totalBytes; 1585b8e80941Smrg 1586b8e80941Smrg _mesa_compute_compressed_pixelstore(dimensions, format, 1587b8e80941Smrg width, height, depth, 1588b8e80941Smrg packing, &st); 1589b8e80941Smrg totalBytes = 1590b8e80941Smrg (st.CopySlices - 1) * st.TotalRowsPerSlice * st.TotalBytesPerRow + 1591b8e80941Smrg st.SkipBytes + 1592b8e80941Smrg (st.CopyRowsPerSlice - 1) * st.TotalBytesPerRow + 1593b8e80941Smrg st.CopyBytesPerRow; 1594b8e80941Smrg 1595b8e80941Smrg return totalBytes; 1596b8e80941Smrg} 1597b8e80941Smrg 1598b8e80941Smrg 1599b8e80941Smrg/** 1600b8e80941Smrg * Do error checking for getting compressed texture images. 1601b8e80941Smrg * \return true if any error, false if no errors. 1602b8e80941Smrg */ 1603b8e80941Smrgstatic bool 1604b8e80941Smrggetcompressedteximage_error_check(struct gl_context *ctx, 1605b8e80941Smrg struct gl_texture_object *texObj, 1606b8e80941Smrg GLenum target, GLint level, 1607b8e80941Smrg GLint xoffset, GLint yoffset, GLint zoffset, 1608b8e80941Smrg GLsizei width, GLsizei height, GLsizei depth, 1609b8e80941Smrg GLsizei bufSize, GLvoid *pixels, 1610b8e80941Smrg const char *caller) 1611b8e80941Smrg{ 1612b8e80941Smrg struct gl_texture_image *texImage; 1613b8e80941Smrg GLint maxLevels; 1614b8e80941Smrg GLsizei totalBytes; 1615b8e80941Smrg GLuint dimensions; 1616b8e80941Smrg 1617b8e80941Smrg assert(texObj); 1618b8e80941Smrg 1619b8e80941Smrg if (texObj->Target == 0) { 1620b8e80941Smrg _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid texture)", caller); 1621b8e80941Smrg return true; 1622b8e80941Smrg } 1623b8e80941Smrg 1624b8e80941Smrg maxLevels = _mesa_max_texture_levels(ctx, target); 1625b8e80941Smrg if (level < 0 || level >= maxLevels) { 1626848b8605Smrg _mesa_error(ctx, GL_INVALID_VALUE, 1627b8e80941Smrg "%s(bad level = %d)", caller, level); 1628b8e80941Smrg return true; 1629848b8605Smrg } 1630848b8605Smrg 1631b8e80941Smrg if (dimensions_error_check(ctx, texObj, target, level, 1632b8e80941Smrg xoffset, yoffset, zoffset, 1633b8e80941Smrg width, height, depth, caller)) { 1634b8e80941Smrg return true; 1635b8e80941Smrg } 1636b8e80941Smrg 1637b8e80941Smrg texImage = select_tex_image(texObj, target, level, zoffset); 1638b8e80941Smrg assert(texImage); 1639b8e80941Smrg 1640848b8605Smrg if (!_mesa_is_format_compressed(texImage->TexFormat)) { 1641848b8605Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 1642b8e80941Smrg "%s(texture is not compressed)", caller); 1643b8e80941Smrg return true; 1644848b8605Smrg } 1645848b8605Smrg 1646848b8605Smrg /* Check for invalid pixel storage modes */ 1647b8e80941Smrg dimensions = _mesa_get_texture_dimensions(texObj->Target); 1648848b8605Smrg if (!_mesa_compressed_pixel_storage_error_check(ctx, dimensions, 1649b8e80941Smrg &ctx->Pack, 1650b8e80941Smrg caller)) { 1651b8e80941Smrg return true; 1652848b8605Smrg } 1653848b8605Smrg 1654b8e80941Smrg /* Compute number of bytes that may be touched in the dest buffer */ 1655b8e80941Smrg totalBytes = packed_compressed_size(dimensions, texImage->TexFormat, 1656b8e80941Smrg width, height, depth, 1657b8e80941Smrg &ctx->Pack); 1658b8e80941Smrg 1659b8e80941Smrg /* Do dest buffer bounds checking */ 1660b8e80941Smrg if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { 1661848b8605Smrg /* do bounds checking on PBO write */ 1662b8e80941Smrg if ((GLubyte *) pixels + totalBytes > 1663b8e80941Smrg (GLubyte *) ctx->Pack.BufferObj->Size) { 1664848b8605Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 1665b8e80941Smrg "%s(out of bounds PBO access)", caller); 1666b8e80941Smrg return true; 1667848b8605Smrg } 1668848b8605Smrg 1669848b8605Smrg /* make sure PBO is not mapped */ 1670848b8605Smrg if (_mesa_check_disallowed_mapping(ctx->Pack.BufferObj)) { 1671b8e80941Smrg _mesa_error(ctx, GL_INVALID_OPERATION, "%s(PBO is mapped)", caller); 1672b8e80941Smrg return true; 1673b8e80941Smrg } 1674b8e80941Smrg } 1675b8e80941Smrg else { 1676b8e80941Smrg /* do bounds checking on writing to client memory */ 1677b8e80941Smrg if (totalBytes > bufSize) { 1678848b8605Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 1679b8e80941Smrg "%s(out of bounds access: bufSize (%d) is too small)", 1680b8e80941Smrg caller, bufSize); 1681b8e80941Smrg return true; 1682848b8605Smrg } 1683848b8605Smrg } 1684848b8605Smrg 1685b8e80941Smrg if (!_mesa_is_bufferobj(ctx->Pack.BufferObj) && !pixels) { 1686b8e80941Smrg /* not an error, but do nothing */ 1687b8e80941Smrg return true; 1688b8e80941Smrg } 1689b8e80941Smrg 1690b8e80941Smrg return false; 1691848b8605Smrg} 1692848b8605Smrg 1693848b8605Smrg 1694b8e80941Smrg/** 1695b8e80941Smrg * Common helper for all glGetCompressed-teximage functions. 1696b8e80941Smrg */ 1697b8e80941Smrgstatic void 1698b8e80941Smrgget_compressed_texture_image(struct gl_context *ctx, 1699b8e80941Smrg struct gl_texture_object *texObj, 1700b8e80941Smrg GLenum target, GLint level, 1701b8e80941Smrg GLint xoffset, GLint yoffset, GLint zoffset, 1702b8e80941Smrg GLsizei width, GLsizei height, GLint depth, 1703b8e80941Smrg GLvoid *pixels, 1704b8e80941Smrg const char *caller) 1705848b8605Smrg{ 1706848b8605Smrg struct gl_texture_image *texImage; 1707b8e80941Smrg unsigned firstFace, numFaces, i, imageStride; 1708848b8605Smrg 1709848b8605Smrg FLUSH_VERTICES(ctx, 0); 1710848b8605Smrg 1711b8e80941Smrg texImage = select_tex_image(texObj, target, level, zoffset); 1712b8e80941Smrg assert(texImage); /* should have been error checked already */ 1713848b8605Smrg 1714848b8605Smrg if (_mesa_is_zero_size_texture(texImage)) 1715848b8605Smrg return; 1716848b8605Smrg 1717848b8605Smrg if (MESA_VERBOSE & (VERBOSE_API | VERBOSE_TEXTURE)) { 1718848b8605Smrg _mesa_debug(ctx, 1719b8e80941Smrg "%s(tex %u) format = %s, w=%d, h=%d\n", 1720b8e80941Smrg caller, texObj->Name, 1721848b8605Smrg _mesa_get_format_name(texImage->TexFormat), 1722848b8605Smrg texImage->Width, texImage->Height); 1723848b8605Smrg } 1724848b8605Smrg 1725b8e80941Smrg if (target == GL_TEXTURE_CUBE_MAP) { 1726b8e80941Smrg struct compressed_pixelstore store; 1727b8e80941Smrg 1728b8e80941Smrg /* Compute image stride between cube faces */ 1729b8e80941Smrg _mesa_compute_compressed_pixelstore(2, texImage->TexFormat, 1730b8e80941Smrg width, height, depth, 1731b8e80941Smrg &ctx->Pack, &store); 1732b8e80941Smrg imageStride = store.TotalBytesPerRow * store.TotalRowsPerSlice; 1733b8e80941Smrg 1734b8e80941Smrg firstFace = zoffset; 1735b8e80941Smrg numFaces = depth; 1736b8e80941Smrg zoffset = 0; 1737b8e80941Smrg depth = 1; 1738b8e80941Smrg } 1739b8e80941Smrg else { 1740b8e80941Smrg imageStride = 0; 1741b8e80941Smrg firstFace = _mesa_tex_target_to_face(target); 1742b8e80941Smrg numFaces = 1; 1743b8e80941Smrg } 1744b8e80941Smrg 1745848b8605Smrg _mesa_lock_texture(ctx, texObj); 1746b8e80941Smrg 1747b8e80941Smrg for (i = 0; i < numFaces; i++) { 1748b8e80941Smrg texImage = texObj->Image[firstFace + i][level]; 1749b8e80941Smrg assert(texImage); 1750b8e80941Smrg 1751b8e80941Smrg get_compressed_texsubimage_sw(ctx, texImage, 1752b8e80941Smrg xoffset, yoffset, zoffset, 1753b8e80941Smrg width, height, depth, pixels); 1754b8e80941Smrg 1755b8e80941Smrg /* next cube face */ 1756b8e80941Smrg pixels = (GLubyte *) pixels + imageStride; 1757848b8605Smrg } 1758b8e80941Smrg 1759848b8605Smrg _mesa_unlock_texture(ctx, texObj); 1760848b8605Smrg} 1761848b8605Smrg 1762b8e80941Smrg 1763848b8605Smrgvoid GLAPIENTRY 1764b8e80941Smrg_mesa_GetnCompressedTexImageARB(GLenum target, GLint level, GLsizei bufSize, 1765b8e80941Smrg GLvoid *pixels) 1766848b8605Smrg{ 1767b8e80941Smrg GET_CURRENT_CONTEXT(ctx); 1768b8e80941Smrg static const char *caller = "glGetnCompressedTexImageARB"; 1769b8e80941Smrg GLsizei width, height, depth; 1770b8e80941Smrg struct gl_texture_object *texObj; 1771b8e80941Smrg 1772b8e80941Smrg if (!legal_getteximage_target(ctx, target, false)) { 1773b8e80941Smrg _mesa_error(ctx, GL_INVALID_ENUM, "%s", caller); 1774b8e80941Smrg return; 1775b8e80941Smrg } 1776b8e80941Smrg 1777b8e80941Smrg texObj = _mesa_get_current_tex_object(ctx, target); 1778b8e80941Smrg assert(texObj); 1779b8e80941Smrg 1780b8e80941Smrg get_texture_image_dims(texObj, target, level, &width, &height, &depth); 1781b8e80941Smrg 1782b8e80941Smrg if (getcompressedteximage_error_check(ctx, texObj, target, level, 1783b8e80941Smrg 0, 0, 0, width, height, depth, 1784b8e80941Smrg INT_MAX, pixels, caller)) { 1785b8e80941Smrg return; 1786b8e80941Smrg } 1787b8e80941Smrg 1788b8e80941Smrg get_compressed_texture_image(ctx, texObj, target, level, 1789b8e80941Smrg 0, 0, 0, width, height, depth, 1790b8e80941Smrg pixels, caller); 1791b8e80941Smrg} 1792b8e80941Smrg 1793b8e80941Smrg 1794b8e80941Smrgvoid GLAPIENTRY 1795b8e80941Smrg_mesa_GetCompressedTexImage(GLenum target, GLint level, GLvoid *pixels) 1796b8e80941Smrg{ 1797b8e80941Smrg GET_CURRENT_CONTEXT(ctx); 1798b8e80941Smrg static const char *caller = "glGetCompressedTexImage"; 1799b8e80941Smrg GLsizei width, height, depth; 1800b8e80941Smrg struct gl_texture_object *texObj; 1801b8e80941Smrg 1802b8e80941Smrg if (!legal_getteximage_target(ctx, target, false)) { 1803b8e80941Smrg _mesa_error(ctx, GL_INVALID_ENUM, "%s", caller); 1804b8e80941Smrg return; 1805b8e80941Smrg } 1806b8e80941Smrg 1807b8e80941Smrg texObj = _mesa_get_current_tex_object(ctx, target); 1808b8e80941Smrg assert(texObj); 1809b8e80941Smrg 1810b8e80941Smrg get_texture_image_dims(texObj, target, level, 1811b8e80941Smrg &width, &height, &depth); 1812b8e80941Smrg 1813b8e80941Smrg if (getcompressedteximage_error_check(ctx, texObj, target, level, 1814b8e80941Smrg 0, 0, 0, width, height, depth, 1815b8e80941Smrg INT_MAX, pixels, caller)) { 1816b8e80941Smrg return; 1817b8e80941Smrg } 1818b8e80941Smrg 1819b8e80941Smrg get_compressed_texture_image(ctx, texObj, target, level, 1820b8e80941Smrg 0, 0, 0, width, height, depth, 1821b8e80941Smrg pixels, caller); 1822b8e80941Smrg} 1823b8e80941Smrg 1824b8e80941Smrg 1825b8e80941Smrgvoid GLAPIENTRY 1826b8e80941Smrg_mesa_GetCompressedTextureImage(GLuint texture, GLint level, 1827b8e80941Smrg GLsizei bufSize, GLvoid *pixels) 1828b8e80941Smrg{ 1829b8e80941Smrg GET_CURRENT_CONTEXT(ctx); 1830b8e80941Smrg static const char *caller = "glGetCompressedTextureImage"; 1831b8e80941Smrg GLsizei width, height, depth; 1832b8e80941Smrg struct gl_texture_object *texObj = 1833b8e80941Smrg _mesa_lookup_texture_err(ctx, texture, caller); 1834b8e80941Smrg 1835b8e80941Smrg if (!texObj) { 1836b8e80941Smrg return; 1837b8e80941Smrg } 1838b8e80941Smrg 1839b8e80941Smrg get_texture_image_dims(texObj, texObj->Target, level, 1840b8e80941Smrg &width, &height, &depth); 1841b8e80941Smrg 1842b8e80941Smrg if (getcompressedteximage_error_check(ctx, texObj, texObj->Target, level, 1843b8e80941Smrg 0, 0, 0, width, height, depth, 1844b8e80941Smrg bufSize, pixels, caller)) { 1845b8e80941Smrg return; 1846b8e80941Smrg } 1847b8e80941Smrg 1848b8e80941Smrg get_compressed_texture_image(ctx, texObj, texObj->Target, level, 1849b8e80941Smrg 0, 0, 0, width, height, depth, 1850b8e80941Smrg pixels, caller); 1851b8e80941Smrg} 1852b8e80941Smrg 1853b8e80941Smrg 1854b8e80941Smrgvoid APIENTRY 1855b8e80941Smrg_mesa_GetCompressedTextureSubImage(GLuint texture, GLint level, 1856b8e80941Smrg GLint xoffset, GLint yoffset, 1857b8e80941Smrg GLint zoffset, GLsizei width, 1858b8e80941Smrg GLsizei height, GLsizei depth, 1859b8e80941Smrg GLsizei bufSize, void *pixels) 1860b8e80941Smrg{ 1861b8e80941Smrg GET_CURRENT_CONTEXT(ctx); 1862b8e80941Smrg static const char *caller = "glGetCompressedTextureImage"; 1863b8e80941Smrg struct gl_texture_object *texObj = NULL; 1864b8e80941Smrg 1865b8e80941Smrg texObj = _mesa_lookup_texture_err(ctx, texture, caller); 1866b8e80941Smrg if (!texObj) { 1867b8e80941Smrg return; 1868b8e80941Smrg } 1869b8e80941Smrg 1870b8e80941Smrg if (getcompressedteximage_error_check(ctx, texObj, texObj->Target, level, 1871b8e80941Smrg xoffset, yoffset, zoffset, 1872b8e80941Smrg width, height, depth, 1873b8e80941Smrg bufSize, pixels, caller)) { 1874b8e80941Smrg return; 1875b8e80941Smrg } 1876b8e80941Smrg 1877b8e80941Smrg get_compressed_texture_image(ctx, texObj, texObj->Target, level, 1878b8e80941Smrg xoffset, yoffset, zoffset, 1879b8e80941Smrg width, height, depth, 1880b8e80941Smrg pixels, caller); 1881848b8605Smrg} 1882