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