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