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