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