2 * Mesa 3-D graphics library
4 * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
5 * Copyright (c) 2009 VMware, Inc.
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:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
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.
28 * Code for glGetTexImage() and glGetCompressedTexImage().
33 #include "bufferobj.h"
37 #include "format_unpack.h"
38 #include "glformats.h"
43 #include "texcompress.h"
44 #include "texgetimage.h"
50 * Can the given type represent negative values?
52 static inline GLboolean
53 type_needs_clamping(GLenum type
)
60 case GL_HALF_FLOAT_ARB
:
61 case GL_UNSIGNED_INT_10F_11F_11F_REV
:
62 case GL_UNSIGNED_INT_5_9_9_9_REV
:
71 * glGetTexImage for depth/Z pixels.
74 get_tex_depth(struct gl_context
*ctx
, GLuint dimensions
,
75 GLenum format
, GLenum type
, GLvoid
*pixels
,
76 struct gl_texture_image
*texImage
)
78 const GLint width
= texImage
->Width
;
79 const GLint height
= texImage
->Height
;
80 const GLint depth
= texImage
->Depth
;
82 GLfloat
*depthRow
= malloc(width
* sizeof(GLfloat
));
85 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glGetTexImage");
89 for (img
= 0; img
< depth
; img
++) {
93 /* map src texture buffer */
94 ctx
->Driver
.MapTextureImage(ctx
, texImage
, img
,
95 0, 0, width
, height
, GL_MAP_READ_BIT
,
96 &srcMap
, &srcRowStride
);
99 for (row
= 0; row
< height
; row
++) {
100 void *dest
= _mesa_image_address(dimensions
, &ctx
->Pack
, pixels
,
101 width
, height
, format
, type
,
103 const GLubyte
*src
= srcMap
+ row
* srcRowStride
;
104 _mesa_unpack_float_z_row(texImage
->TexFormat
, width
, src
, depthRow
);
105 _mesa_pack_depth_span(ctx
, width
, dest
, type
, depthRow
, &ctx
->Pack
);
108 ctx
->Driver
.UnmapTextureImage(ctx
, texImage
, img
);
111 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glGetTexImage");
121 * glGetTexImage for depth/stencil pixels.
124 get_tex_depth_stencil(struct gl_context
*ctx
, GLuint dimensions
,
125 GLenum format
, GLenum type
, GLvoid
*pixels
,
126 struct gl_texture_image
*texImage
)
128 const GLint width
= texImage
->Width
;
129 const GLint height
= texImage
->Height
;
130 const GLint depth
= texImage
->Depth
;
133 assert(format
== GL_DEPTH_STENCIL
);
134 assert(type
== GL_UNSIGNED_INT_24_8
||
135 type
== GL_FLOAT_32_UNSIGNED_INT_24_8_REV
);
137 for (img
= 0; img
< depth
; img
++) {
141 /* map src texture buffer */
142 ctx
->Driver
.MapTextureImage(ctx
, texImage
, img
,
143 0, 0, width
, height
, GL_MAP_READ_BIT
,
144 &srcMap
, &rowstride
);
147 for (row
= 0; row
< height
; row
++) {
148 const GLubyte
*src
= srcMap
+ row
* rowstride
;
149 void *dest
= _mesa_image_address(dimensions
, &ctx
->Pack
, pixels
,
150 width
, height
, format
, type
,
152 _mesa_unpack_depth_stencil_row(texImage
->TexFormat
,
154 (const GLuint
*) src
,
156 if (ctx
->Pack
.SwapBytes
) {
157 _mesa_swap4((GLuint
*) dest
, width
);
161 ctx
->Driver
.UnmapTextureImage(ctx
, texImage
, img
);
164 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glGetTexImage");
172 * glGetTexImage for YCbCr pixels.
175 get_tex_ycbcr(struct gl_context
*ctx
, GLuint dimensions
,
176 GLenum format
, GLenum type
, GLvoid
*pixels
,
177 struct gl_texture_image
*texImage
)
179 const GLint width
= texImage
->Width
;
180 const GLint height
= texImage
->Height
;
181 const GLint depth
= texImage
->Depth
;
184 for (img
= 0; img
< depth
; img
++) {
188 /* map src texture buffer */
189 ctx
->Driver
.MapTextureImage(ctx
, texImage
, img
,
190 0, 0, width
, height
, GL_MAP_READ_BIT
,
191 &srcMap
, &rowstride
);
194 for (row
= 0; row
< height
; row
++) {
195 const GLubyte
*src
= srcMap
+ row
* rowstride
;
196 void *dest
= _mesa_image_address(dimensions
, &ctx
->Pack
, pixels
,
197 width
, height
, format
, type
,
199 memcpy(dest
, src
, width
* sizeof(GLushort
));
201 /* check for byte swapping */
202 if ((texImage
->TexFormat
== MESA_FORMAT_YCBCR
203 && type
== GL_UNSIGNED_SHORT_8_8_REV_MESA
) ||
204 (texImage
->TexFormat
== MESA_FORMAT_YCBCR_REV
205 && type
== GL_UNSIGNED_SHORT_8_8_MESA
)) {
206 if (!ctx
->Pack
.SwapBytes
)
207 _mesa_swap2((GLushort
*) dest
, width
);
209 else if (ctx
->Pack
.SwapBytes
) {
210 _mesa_swap2((GLushort
*) dest
, width
);
214 ctx
->Driver
.UnmapTextureImage(ctx
, texImage
, img
);
217 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glGetTexImage");
225 * Get a color texture image with decompression.
228 get_tex_rgba_compressed(struct gl_context
*ctx
, GLuint dimensions
,
229 GLenum format
, GLenum type
, GLvoid
*pixels
,
230 struct gl_texture_image
*texImage
,
231 GLbitfield transferOps
)
233 /* don't want to apply sRGB -> RGB conversion here so override the format */
234 const mesa_format texFormat
=
235 _mesa_get_srgb_format_linear(texImage
->TexFormat
);
236 const GLenum baseFormat
= _mesa_get_format_base_format(texFormat
);
237 const GLenum destBaseFormat
= _mesa_base_tex_format(ctx
, format
);
238 GLenum rebaseFormat
= GL_NONE
;
239 const GLuint width
= texImage
->Width
;
240 const GLuint height
= texImage
->Height
;
241 const GLuint depth
= texImage
->Depth
;
242 GLfloat
*tempImage
, *tempSlice
, *srcRow
;
245 /* Decompress into temp float buffer, then pack into user buffer */
246 tempImage
= malloc(width
* height
* depth
247 * 4 * sizeof(GLfloat
));
249 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glGetTexImage()");
253 /* Decompress the texture image slices - results in 'tempImage' */
254 for (slice
= 0; slice
< depth
; slice
++) {
258 tempSlice
= tempImage
+ slice
* 4 * width
* height
;
260 ctx
->Driver
.MapTextureImage(ctx
, texImage
, slice
,
263 &srcMap
, &srcRowStride
);
265 _mesa_decompress_image(texFormat
, width
, height
,
266 srcMap
, srcRowStride
, tempSlice
);
268 ctx
->Driver
.UnmapTextureImage(ctx
, texImage
, slice
);
271 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glGetTexImage");
277 if (baseFormat
== GL_LUMINANCE
||
278 baseFormat
== GL_INTENSITY
||
279 baseFormat
== GL_LUMINANCE_ALPHA
) {
280 /* If a luminance (or intensity) texture is read back as RGB(A), the
281 * returned value should be (L,0,0,1), not (L,L,L,1). Set rebaseFormat
284 rebaseFormat
= texImage
->_BaseFormat
;
286 else if ((baseFormat
== GL_RGBA
||
287 baseFormat
== GL_RGB
||
288 baseFormat
== GL_RG
) &&
289 (destBaseFormat
== GL_LUMINANCE
||
290 destBaseFormat
== GL_LUMINANCE_ALPHA
||
291 destBaseFormat
== GL_LUMINANCE_INTEGER_EXT
||
292 destBaseFormat
== GL_LUMINANCE_ALPHA_INTEGER_EXT
)) {
293 /* If we're reading back an RGB(A) texture as luminance then we need
294 * to return L=tex(R). Note, that's different from glReadPixels which
297 rebaseFormat
= GL_LUMINANCE_ALPHA
; /* this covers GL_LUMINANCE too */
301 _mesa_rebase_rgba_float(width
* height
, (GLfloat (*)[4]) tempImage
,
305 tempSlice
= tempImage
;
306 for (slice
= 0; slice
< depth
; slice
++) {
308 for (row
= 0; row
< height
; row
++) {
309 void *dest
= _mesa_image_address(dimensions
, &ctx
->Pack
, pixels
,
310 width
, height
, format
, type
,
313 _mesa_pack_rgba_span_float(ctx
, width
, (GLfloat (*)[4]) srcRow
,
314 format
, type
, dest
, &ctx
->Pack
, transferOps
);
317 tempSlice
+= 4 * width
* height
;
325 * Return a base GL format given the user-requested format
326 * for glGetTexImage().
329 _mesa_base_pack_format(GLenum format
)
334 case GL_BGRA_INTEGER
:
335 case GL_RGBA_INTEGER
:
343 case GL_GREEN_INTEGER
:
345 case GL_BLUE_INTEGER
:
347 case GL_ALPHA_INTEGER
:
349 case GL_LUMINANCE_INTEGER_EXT
:
351 case GL_LUMINANCE_ALPHA_INTEGER_EXT
:
352 return GL_LUMINANCE_ALPHA
;
360 * Get an uncompressed color texture image.
363 get_tex_rgba_uncompressed(struct gl_context
*ctx
, GLuint dimensions
,
364 GLenum format
, GLenum type
, GLvoid
*pixels
,
365 struct gl_texture_image
*texImage
,
366 GLbitfield transferOps
)
368 /* don't want to apply sRGB -> RGB conversion here so override the format */
369 const mesa_format texFormat
=
370 _mesa_get_srgb_format_linear(texImage
->TexFormat
);
371 const GLuint width
= texImage
->Width
;
372 GLenum destBaseFormat
= _mesa_base_pack_format(format
);
373 GLenum rebaseFormat
= GL_NONE
;
374 GLuint height
= texImage
->Height
;
375 GLuint depth
= texImage
->Depth
;
378 GLuint (*rgba_uint
)[4];
379 GLboolean tex_is_integer
= _mesa_is_format_integer_color(texImage
->TexFormat
);
380 GLboolean tex_is_uint
= _mesa_is_format_unsigned(texImage
->TexFormat
);
381 GLenum texBaseFormat
= _mesa_get_format_base_format(texImage
->TexFormat
);
383 /* Allocate buffer for one row of texels */
384 rgba
= malloc(4 * width
* sizeof(GLfloat
));
385 rgba_uint
= (GLuint (*)[4]) rgba
;
387 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glGetTexImage()");
391 if (texImage
->TexObject
->Target
== GL_TEXTURE_1D_ARRAY
) {
396 if (texImage
->_BaseFormat
== GL_LUMINANCE
||
397 texImage
->_BaseFormat
== GL_INTENSITY
||
398 texImage
->_BaseFormat
== GL_LUMINANCE_ALPHA
) {
399 /* If a luminance (or intensity) texture is read back as RGB(A), the
400 * returned value should be (L,0,0,1), not (L,L,L,1). Set rebaseFormat
403 rebaseFormat
= texImage
->_BaseFormat
;
405 else if ((texImage
->_BaseFormat
== GL_RGBA
||
406 texImage
->_BaseFormat
== GL_RGB
||
407 texImage
->_BaseFormat
== GL_RG
) &&
408 (destBaseFormat
== GL_LUMINANCE
||
409 destBaseFormat
== GL_LUMINANCE_ALPHA
||
410 destBaseFormat
== GL_LUMINANCE_INTEGER_EXT
||
411 destBaseFormat
== GL_LUMINANCE_ALPHA_INTEGER_EXT
)) {
412 /* If we're reading back an RGB(A) texture as luminance then we need
413 * to return L=tex(R). Note, that's different from glReadPixels which
416 rebaseFormat
= GL_LUMINANCE_ALPHA
; /* this covers GL_LUMINANCE too */
418 else if (texImage
->_BaseFormat
!= texBaseFormat
) {
419 /* The internal format and the real format differ, so we can't rely
420 * on the unpack functions setting the correct constant values.
421 * (e.g. reading back GL_RGB8 which is actually RGBA won't set alpha=1)
423 switch (texImage
->_BaseFormat
) {
425 if ((texBaseFormat
== GL_RGBA
||
426 texBaseFormat
== GL_RGB
||
427 texBaseFormat
== GL_RG
) &&
428 (destBaseFormat
== GL_RGBA
||
429 destBaseFormat
== GL_RGB
||
430 destBaseFormat
== GL_RG
||
431 destBaseFormat
== GL_GREEN
)) {
432 rebaseFormat
= texImage
->_BaseFormat
;
437 if ((texBaseFormat
== GL_RGBA
||
438 texBaseFormat
== GL_RGB
) &&
439 (destBaseFormat
== GL_RGBA
||
440 destBaseFormat
== GL_RGB
||
441 destBaseFormat
== GL_BLUE
)) {
442 rebaseFormat
= texImage
->_BaseFormat
;
447 if (texBaseFormat
== GL_RGBA
&&
448 (destBaseFormat
== GL_RGBA
||
449 destBaseFormat
== GL_ALPHA
||
450 destBaseFormat
== GL_LUMINANCE_ALPHA
)) {
451 rebaseFormat
= texImage
->_BaseFormat
;
456 if (destBaseFormat
!= GL_ALPHA
) {
457 rebaseFormat
= texImage
->_BaseFormat
;
463 for (img
= 0; img
< depth
; img
++) {
467 /* map src texture buffer */
468 ctx
->Driver
.MapTextureImage(ctx
, texImage
, img
,
469 0, 0, width
, height
, GL_MAP_READ_BIT
,
470 &srcMap
, &rowstride
);
472 for (row
= 0; row
< height
; row
++) {
473 const GLubyte
*src
= srcMap
+ row
* rowstride
;
474 void *dest
= _mesa_image_address(dimensions
, &ctx
->Pack
, pixels
,
475 width
, height
, format
, type
,
478 if (tex_is_integer
) {
479 _mesa_unpack_uint_rgba_row(texFormat
, width
, src
, rgba_uint
);
481 _mesa_rebase_rgba_uint(width
, rgba_uint
, rebaseFormat
);
483 _mesa_pack_rgba_span_from_uints(ctx
, width
,
484 (GLuint (*)[4]) rgba_uint
,
487 _mesa_pack_rgba_span_from_ints(ctx
, width
,
488 (GLint (*)[4]) rgba_uint
,
492 _mesa_unpack_rgba_row(texFormat
, width
, src
, rgba
);
494 _mesa_rebase_rgba_float(width
, rgba
, rebaseFormat
);
495 _mesa_pack_rgba_span_float(ctx
, width
, (GLfloat (*)[4]) rgba
,
497 &ctx
->Pack
, transferOps
);
501 /* Unmap the src texture buffer */
502 ctx
->Driver
.UnmapTextureImage(ctx
, texImage
, img
);
505 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glGetTexImage");
515 * glGetTexImage for color formats (RGBA, RGB, alpha, LA, etc).
516 * Compressed textures are handled here as well.
519 get_tex_rgba(struct gl_context
*ctx
, GLuint dimensions
,
520 GLenum format
, GLenum type
, GLvoid
*pixels
,
521 struct gl_texture_image
*texImage
)
523 const GLenum dataType
= _mesa_get_format_datatype(texImage
->TexFormat
);
524 GLbitfield transferOps
= 0x0;
526 /* In general, clamping does not apply to glGetTexImage, except when
527 * the returned type of the image can't hold negative values.
529 if (type_needs_clamping(type
)) {
530 /* the returned image type can't have negative values */
531 if (dataType
== GL_FLOAT
||
532 dataType
== GL_HALF_FLOAT
||
533 dataType
== GL_SIGNED_NORMALIZED
||
534 format
== GL_LUMINANCE
||
535 format
== GL_LUMINANCE_ALPHA
) {
536 transferOps
|= IMAGE_CLAMP_BIT
;
540 if (_mesa_is_format_compressed(texImage
->TexFormat
)) {
541 get_tex_rgba_compressed(ctx
, dimensions
, format
, type
,
542 pixels
, texImage
, transferOps
);
545 get_tex_rgba_uncompressed(ctx
, dimensions
, format
, type
,
546 pixels
, texImage
, transferOps
);
552 * Try to do glGetTexImage() with simple memcpy().
553 * \return GL_TRUE if done, GL_FALSE otherwise
556 get_tex_memcpy(struct gl_context
*ctx
, GLenum format
, GLenum type
,
558 struct gl_texture_image
*texImage
)
560 const GLenum target
= texImage
->TexObject
->Target
;
561 GLboolean memCopy
= GL_FALSE
;
562 GLenum texBaseFormat
= _mesa_get_format_base_format(texImage
->TexFormat
);
565 * Check if we can use memcpy to copy from the hardware texture
566 * format to the user's format/type.
567 * Note that GL's pixel transfer ops don't apply to glGetTexImage()
569 if ((target
== GL_TEXTURE_1D
||
570 target
== GL_TEXTURE_2D
||
571 target
== GL_TEXTURE_RECTANGLE
||
572 _mesa_is_cube_face(target
)) &&
573 texBaseFormat
== texImage
->_BaseFormat
) {
574 memCopy
= _mesa_format_matches_format_and_type(texImage
->TexFormat
,
576 ctx
->Pack
.SwapBytes
);
580 const GLuint bpp
= _mesa_get_format_bytes(texImage
->TexFormat
);
581 const GLuint bytesPerRow
= texImage
->Width
* bpp
;
583 _mesa_image_address2d(&ctx
->Pack
, pixels
, texImage
->Width
,
584 texImage
->Height
, format
, type
, 0, 0);
585 const GLint dstRowStride
=
586 _mesa_image_row_stride(&ctx
->Pack
, texImage
->Width
, format
, type
);
590 /* map src texture buffer */
591 ctx
->Driver
.MapTextureImage(ctx
, texImage
, 0,
592 0, 0, texImage
->Width
, texImage
->Height
,
593 GL_MAP_READ_BIT
, &src
, &srcRowStride
);
596 if (bytesPerRow
== dstRowStride
&& bytesPerRow
== srcRowStride
) {
597 memcpy(dst
, src
, bytesPerRow
* texImage
->Height
);
601 for (row
= 0; row
< texImage
->Height
; row
++) {
602 memcpy(dst
, src
, bytesPerRow
);
608 /* unmap src texture buffer */
609 ctx
->Driver
.UnmapTextureImage(ctx
, texImage
, 0);
612 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glGetTexImage");
621 * This is the software fallback for Driver.GetTexImage().
622 * All error checking will have been done before this routine is called.
623 * We'll call ctx->Driver.MapTextureImage() to access the data, then
624 * unmap with ctx->Driver.UnmapTextureImage().
627 _mesa_get_teximage(struct gl_context
*ctx
,
628 GLenum format
, GLenum type
, GLvoid
*pixels
,
629 struct gl_texture_image
*texImage
)
631 const GLuint dimensions
=
632 _mesa_get_texture_dimensions(texImage
->TexObject
->Target
);
634 /* map dest buffer, if PBO */
635 if (_mesa_is_bufferobj(ctx
->Pack
.BufferObj
)) {
636 /* Packing texture image into a PBO.
637 * Map the (potentially) VRAM-based buffer into our process space so
638 * we can write into it with the code below.
639 * A hardware driver might use a sophisticated blit to move the
640 * texture data to the PBO if the PBO is in VRAM along with the texture.
642 GLubyte
*buf
= (GLubyte
*)
643 ctx
->Driver
.MapBufferRange(ctx
, 0, ctx
->Pack
.BufferObj
->Size
,
644 GL_MAP_WRITE_BIT
, ctx
->Pack
.BufferObj
,
647 /* out of memory or other unexpected error */
648 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glGetTexImage(map PBO failed)");
651 /* <pixels> was an offset into the PBO.
652 * Now make it a real, client-side pointer inside the mapped region.
654 pixels
= ADD_POINTERS(buf
, pixels
);
657 if (get_tex_memcpy(ctx
, format
, type
, pixels
, texImage
)) {
660 else if (format
== GL_DEPTH_COMPONENT
) {
661 get_tex_depth(ctx
, dimensions
, format
, type
, pixels
, texImage
);
663 else if (format
== GL_DEPTH_STENCIL_EXT
) {
664 get_tex_depth_stencil(ctx
, dimensions
, format
, type
, pixels
, texImage
);
666 else if (format
== GL_YCBCR_MESA
) {
667 get_tex_ycbcr(ctx
, dimensions
, format
, type
, pixels
, texImage
);
670 get_tex_rgba(ctx
, dimensions
, format
, type
, pixels
, texImage
);
673 if (_mesa_is_bufferobj(ctx
->Pack
.BufferObj
)) {
674 ctx
->Driver
.UnmapBuffer(ctx
, ctx
->Pack
.BufferObj
, MAP_INTERNAL
);
681 * This is the software fallback for Driver.GetCompressedTexImage().
682 * All error checking will have been done before this routine is called.
685 _mesa_get_compressed_teximage(struct gl_context
*ctx
,
686 struct gl_texture_image
*texImage
,
689 const GLuint row_stride
=
690 _mesa_format_row_stride(texImage
->TexFormat
, texImage
->Width
);
695 if (_mesa_is_bufferobj(ctx
->Pack
.BufferObj
)) {
696 /* pack texture image into a PBO */
697 GLubyte
*buf
= (GLubyte
*)
698 ctx
->Driver
.MapBufferRange(ctx
, 0, ctx
->Pack
.BufferObj
->Size
,
699 GL_MAP_WRITE_BIT
, ctx
->Pack
.BufferObj
,
702 /* out of memory or other unexpected error */
703 _mesa_error(ctx
, GL_OUT_OF_MEMORY
,
704 "glGetCompresssedTexImage(map PBO failed)");
707 img
= ADD_POINTERS(buf
, img
);
710 /* map src texture buffer */
711 ctx
->Driver
.MapTextureImage(ctx
, texImage
, 0,
712 0, 0, texImage
->Width
, texImage
->Height
,
713 GL_MAP_READ_BIT
, &src
, &srcRowStride
);
716 /* no pixelstore or pixel transfer, but respect stride */
718 if (row_stride
== srcRowStride
) {
719 const GLuint size
= _mesa_format_image_size(texImage
->TexFormat
,
723 memcpy(img
, src
, size
);
727 _mesa_get_format_block_size(texImage
->TexFormat
, &bw
, &bh
);
728 for (i
= 0; i
< (texImage
->Height
+ bh
- 1) / bh
; i
++) {
729 memcpy((GLubyte
*)img
+ i
* row_stride
,
730 (GLubyte
*)src
+ i
* srcRowStride
,
735 ctx
->Driver
.UnmapTextureImage(ctx
, texImage
, 0);
738 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glGetCompresssedTexImage");
741 if (_mesa_is_bufferobj(ctx
->Pack
.BufferObj
)) {
742 ctx
->Driver
.UnmapBuffer(ctx
, ctx
->Pack
.BufferObj
, MAP_INTERNAL
);
748 * Validate the texture target enum supplied to glTexImage or
749 * glCompressedTexImage.
752 legal_getteximage_target(struct gl_context
*ctx
, GLenum target
)
759 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB
:
760 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB
:
761 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB
:
762 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB
:
763 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB
:
764 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB
:
765 return ctx
->Extensions
.ARB_texture_cube_map
;
766 case GL_TEXTURE_RECTANGLE_NV
:
767 return ctx
->Extensions
.NV_texture_rectangle
;
768 case GL_TEXTURE_1D_ARRAY_EXT
:
769 case GL_TEXTURE_2D_ARRAY_EXT
:
770 return ctx
->Extensions
.EXT_texture_array
;
771 case GL_TEXTURE_CUBE_MAP_ARRAY
:
772 return ctx
->Extensions
.ARB_texture_cube_map_array
;
780 * Do error checking for a glGetTexImage() call.
781 * \return GL_TRUE if any error, GL_FALSE if no errors.
784 getteximage_error_check(struct gl_context
*ctx
, GLenum target
, GLint level
,
785 GLenum format
, GLenum type
, GLsizei clientMemSize
,
788 struct gl_texture_object
*texObj
;
789 struct gl_texture_image
*texImage
;
790 const GLint maxLevels
= _mesa_max_texture_levels(ctx
, target
);
791 const GLuint dimensions
= (target
== GL_TEXTURE_3D
) ? 3 : 2;
792 GLenum baseFormat
, err
;
794 if (!legal_getteximage_target(ctx
, target
)) {
795 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetTexImage(target=0x%x)", target
);
799 assert(maxLevels
!= 0);
800 if (level
< 0 || level
>= maxLevels
) {
801 _mesa_error( ctx
, GL_INVALID_VALUE
, "glGetTexImage(level)" );
805 err
= _mesa_error_check_format_and_type(ctx
, format
, type
);
806 if (err
!= GL_NO_ERROR
) {
807 _mesa_error(ctx
, err
, "glGetTexImage(format/type)");
811 texObj
= _mesa_get_current_tex_object(ctx
, target
);
814 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetTexImage(target)");
818 texImage
= _mesa_select_tex_image(ctx
, texObj
, target
, level
);
820 /* non-existant texture image */
824 baseFormat
= _mesa_get_format_base_format(texImage
->TexFormat
);
826 /* Make sure the requested image format is compatible with the
829 if (_mesa_is_color_format(format
)
830 && !_mesa_is_color_format(baseFormat
)) {
831 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetTexImage(format mismatch)");
834 else if (_mesa_is_depth_format(format
)
835 && !_mesa_is_depth_format(baseFormat
)
836 && !_mesa_is_depthstencil_format(baseFormat
)) {
837 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetTexImage(format mismatch)");
840 else if (_mesa_is_stencil_format(format
)
841 && !ctx
->Extensions
.ARB_texture_stencil8
) {
842 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetTexImage(format=GL_STENCIL_INDEX)");
845 else if (_mesa_is_ycbcr_format(format
)
846 && !_mesa_is_ycbcr_format(baseFormat
)) {
847 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetTexImage(format mismatch)");
850 else if (_mesa_is_depthstencil_format(format
)
851 && !_mesa_is_depthstencil_format(baseFormat
)) {
852 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetTexImage(format mismatch)");
855 else if (_mesa_is_dudv_format(format
)
856 && !_mesa_is_dudv_format(baseFormat
)) {
857 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetTexImage(format mismatch)");
860 else if (_mesa_is_enum_format_integer(format
) !=
861 _mesa_is_format_integer(texImage
->TexFormat
)) {
862 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetTexImage(format mismatch)");
866 if (!_mesa_validate_pbo_access(dimensions
, &ctx
->Pack
, texImage
->Width
,
867 texImage
->Height
, texImage
->Depth
,
868 format
, type
, clientMemSize
, pixels
)) {
869 if (_mesa_is_bufferobj(ctx
->Pack
.BufferObj
)) {
870 _mesa_error(ctx
, GL_INVALID_OPERATION
,
871 "glGetTexImage(out of bounds PBO access)");
873 _mesa_error(ctx
, GL_INVALID_OPERATION
,
874 "glGetnTexImageARB(out of bounds access:"
875 " bufSize (%d) is too small)", clientMemSize
);
880 if (_mesa_is_bufferobj(ctx
->Pack
.BufferObj
)) {
881 /* PBO should not be mapped */
882 if (_mesa_check_disallowed_mapping(ctx
->Pack
.BufferObj
)) {
883 _mesa_error(ctx
, GL_INVALID_OPERATION
,
884 "glGetTexImage(PBO is mapped)");
895 * Get texture image. Called by glGetTexImage.
897 * \param target texture target.
898 * \param level image level.
899 * \param format pixel data format for returned image.
900 * \param type pixel data type for returned image.
901 * \param bufSize size of the pixels data buffer.
902 * \param pixels returned pixel data.
905 _mesa_GetnTexImageARB( GLenum target
, GLint level
, GLenum format
,
906 GLenum type
, GLsizei bufSize
, GLvoid
*pixels
)
908 struct gl_texture_object
*texObj
;
909 struct gl_texture_image
*texImage
;
910 GET_CURRENT_CONTEXT(ctx
);
912 FLUSH_VERTICES(ctx
, 0);
914 if (getteximage_error_check(ctx
, target
, level
, format
, type
,
919 if (!_mesa_is_bufferobj(ctx
->Pack
.BufferObj
) && !pixels
) {
920 /* not an error, do nothing */
924 texObj
= _mesa_get_current_tex_object(ctx
, target
);
925 texImage
= _mesa_select_tex_image(ctx
, texObj
, target
, level
);
927 if (_mesa_is_zero_size_texture(texImage
))
930 if (MESA_VERBOSE
& (VERBOSE_API
| VERBOSE_TEXTURE
)) {
931 _mesa_debug(ctx
, "glGetTexImage(tex %u) format = %s, w=%d, h=%d,"
932 " dstFmt=0x%x, dstType=0x%x\n",
934 _mesa_get_format_name(texImage
->TexFormat
),
935 texImage
->Width
, texImage
->Height
,
939 _mesa_lock_texture(ctx
, texObj
);
941 ctx
->Driver
.GetTexImage(ctx
, format
, type
, pixels
, texImage
);
943 _mesa_unlock_texture(ctx
, texObj
);
948 _mesa_GetTexImage( GLenum target
, GLint level
, GLenum format
,
949 GLenum type
, GLvoid
*pixels
)
951 _mesa_GetnTexImageARB(target
, level
, format
, type
, INT_MAX
, pixels
);
956 * Do error checking for a glGetCompressedTexImage() call.
957 * \return GL_TRUE if any error, GL_FALSE if no errors.
960 getcompressedteximage_error_check(struct gl_context
*ctx
, GLenum target
,
961 GLint level
, GLsizei clientMemSize
, GLvoid
*img
)
963 struct gl_texture_object
*texObj
;
964 struct gl_texture_image
*texImage
;
965 const GLint maxLevels
= _mesa_max_texture_levels(ctx
, target
);
966 GLuint compressedSize
, dimensions
;
968 if (!legal_getteximage_target(ctx
, target
)) {
969 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetCompressedTexImage(target=0x%x)",
974 assert(maxLevels
!= 0);
975 if (level
< 0 || level
>= maxLevels
) {
976 _mesa_error(ctx
, GL_INVALID_VALUE
,
977 "glGetCompressedTexImageARB(bad level = %d)", level
);
981 texObj
= _mesa_get_current_tex_object(ctx
, target
);
983 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetCompressedTexImageARB(target)");
987 texImage
= _mesa_select_tex_image(ctx
, texObj
, target
, level
);
990 /* probably invalid mipmap level */
991 _mesa_error(ctx
, GL_INVALID_VALUE
,
992 "glGetCompressedTexImageARB(level)");
996 if (!_mesa_is_format_compressed(texImage
->TexFormat
)) {
997 _mesa_error(ctx
, GL_INVALID_OPERATION
,
998 "glGetCompressedTexImageARB(texture is not compressed)");
1002 compressedSize
= _mesa_format_image_size(texImage
->TexFormat
,
1007 /* Check for invalid pixel storage modes */
1008 dimensions
= _mesa_get_texture_dimensions(texImage
->TexObject
->Target
);
1009 if (!_mesa_compressed_texture_pixel_storage_error_check(ctx
, dimensions
,
1011 "glGetCompressedTexImageARB")) {
1015 if (!_mesa_is_bufferobj(ctx
->Pack
.BufferObj
)) {
1016 /* do bounds checking on writing to client memory */
1017 if (clientMemSize
< (GLsizei
) compressedSize
) {
1018 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1019 "glGetnCompressedTexImageARB(out of bounds access:"
1020 " bufSize (%d) is too small)", clientMemSize
);
1024 /* do bounds checking on PBO write */
1025 if ((const GLubyte
*) img
+ compressedSize
>
1026 (const GLubyte
*) ctx
->Pack
.BufferObj
->Size
) {
1027 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1028 "glGetCompressedTexImage(out of bounds PBO access)");
1032 /* make sure PBO is not mapped */
1033 if (_mesa_check_disallowed_mapping(ctx
->Pack
.BufferObj
)) {
1034 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1035 "glGetCompressedTexImage(PBO is mapped)");
1045 _mesa_GetnCompressedTexImageARB(GLenum target
, GLint level
, GLsizei bufSize
,
1048 struct gl_texture_object
*texObj
;
1049 struct gl_texture_image
*texImage
;
1050 GET_CURRENT_CONTEXT(ctx
);
1052 FLUSH_VERTICES(ctx
, 0);
1054 if (getcompressedteximage_error_check(ctx
, target
, level
, bufSize
, img
)) {
1058 if (!_mesa_is_bufferobj(ctx
->Pack
.BufferObj
) && !img
) {
1059 /* not an error, do nothing */
1063 texObj
= _mesa_get_current_tex_object(ctx
, target
);
1064 texImage
= _mesa_select_tex_image(ctx
, texObj
, target
, level
);
1066 if (_mesa_is_zero_size_texture(texImage
))
1069 if (MESA_VERBOSE
& (VERBOSE_API
| VERBOSE_TEXTURE
)) {
1071 "glGetCompressedTexImage(tex %u) format = %s, w=%d, h=%d\n",
1073 _mesa_get_format_name(texImage
->TexFormat
),
1074 texImage
->Width
, texImage
->Height
);
1077 _mesa_lock_texture(ctx
, texObj
);
1079 ctx
->Driver
.GetCompressedTexImage(ctx
, texImage
, img
);
1081 _mesa_unlock_texture(ctx
, texObj
);
1085 _mesa_GetCompressedTexImage(GLenum target
, GLint level
, GLvoid
*img
)
1087 _mesa_GetnCompressedTexImageARB(target
, level
, INT_MAX
, img
);