2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
6 * Copyright (c) 2009 VMware, Inc.
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 * Code for glGetTexImage() and glGetCompressedTexImage().
33 #include "bufferobj.h"
38 #include "texcompress.h"
39 #include "texgetimage.h"
45 #if FEATURE_EXT_texture_sRGB
48 * Convert a float value from linear space to a
49 * non-linear sRGB value in [0, 255].
50 * Not terribly efficient.
53 linear_to_nonlinear(GLfloat cl
)
55 /* can't have values outside [0, 1] */
57 if (cl
< 0.0031308f
) {
61 cs
= (GLfloat
)(1.055 * _mesa_pow(cl
, 0.41666) - 0.055);
66 #endif /* FEATURE_EXT_texture_sRGB */
70 * Can the given type represent negative values?
72 static INLINE GLboolean
73 type_with_negative_values(GLenum type
)
80 case GL_HALF_FLOAT_ARB
:
89 * glGetTexImage for color index pixels.
92 get_tex_color_index(GLcontext
*ctx
, GLuint dimensions
,
93 GLenum format
, GLenum type
, GLvoid
*pixels
,
94 const struct gl_texture_image
*texImage
)
96 const GLint width
= texImage
->Width
;
97 const GLint height
= texImage
->Height
;
98 const GLint depth
= texImage
->Depth
;
99 const GLuint indexBits
=
100 _mesa_get_format_bits(texImage
->TexFormat
, GL_TEXTURE_INDEX_SIZE_EXT
);
101 const GLbitfield transferOps
= 0x0;
104 for (img
= 0; img
< depth
; img
++) {
105 for (row
= 0; row
< height
; row
++) {
106 GLuint indexRow
[MAX_WIDTH
] = { 0 };
107 void *dest
= _mesa_image_address(dimensions
, &ctx
->Pack
, pixels
,
108 width
, height
, format
, type
,
112 if (indexBits
== 8) {
113 const GLubyte
*src
= (const GLubyte
*) texImage
->Data
;
114 src
+= width
* (img
* texImage
->Height
+ row
);
115 for (col
= 0; col
< width
; col
++) {
116 indexRow
[col
] = src
[col
];
119 else if (indexBits
== 16) {
120 const GLushort
*src
= (const GLushort
*) texImage
->Data
;
121 src
+= width
* (img
* texImage
->Height
+ row
);
122 for (col
= 0; col
< width
; col
++) {
123 indexRow
[col
] = src
[col
];
127 _mesa_problem(ctx
, "Color index problem in _mesa_GetTexImage");
129 _mesa_pack_index_span(ctx
, width
, type
, dest
,
130 indexRow
, &ctx
->Pack
, transferOps
);
137 * glGetTexImage for depth/Z pixels.
140 get_tex_depth(GLcontext
*ctx
, GLuint dimensions
,
141 GLenum format
, GLenum type
, GLvoid
*pixels
,
142 const struct gl_texture_image
*texImage
)
144 const GLint width
= texImage
->Width
;
145 const GLint height
= texImage
->Height
;
146 const GLint depth
= texImage
->Depth
;
149 for (img
= 0; img
< depth
; img
++) {
150 for (row
= 0; row
< height
; row
++) {
151 GLfloat depthRow
[MAX_WIDTH
];
152 void *dest
= _mesa_image_address(dimensions
, &ctx
->Pack
, pixels
,
153 width
, height
, format
, type
,
157 for (col
= 0; col
< width
; col
++) {
158 texImage
->FetchTexelf(texImage
, col
, row
, img
, depthRow
+ col
);
160 _mesa_pack_depth_span(ctx
, width
, dest
, type
, depthRow
, &ctx
->Pack
);
167 * glGetTexImage for depth/stencil pixels.
170 get_tex_depth_stencil(GLcontext
*ctx
, GLuint dimensions
,
171 GLenum format
, GLenum type
, GLvoid
*pixels
,
172 const struct gl_texture_image
*texImage
)
174 const GLint width
= texImage
->Width
;
175 const GLint height
= texImage
->Height
;
176 const GLint depth
= texImage
->Depth
;
177 const GLuint
*src
= (const GLuint
*) texImage
->Data
;
180 for (img
= 0; img
< depth
; img
++) {
181 for (row
= 0; row
< height
; row
++) {
182 void *dest
= _mesa_image_address(dimensions
, &ctx
->Pack
, pixels
,
183 width
, height
, format
, type
,
185 _mesa_memcpy(dest
, src
, width
* sizeof(GLuint
));
186 if (ctx
->Pack
.SwapBytes
) {
187 _mesa_swap4((GLuint
*) dest
, width
);
190 src
+= width
* row
+ width
* height
* img
;
197 * glGetTexImage for YCbCr pixels.
200 get_tex_ycbcr(GLcontext
*ctx
, GLuint dimensions
,
201 GLenum format
, GLenum type
, GLvoid
*pixels
,
202 const struct gl_texture_image
*texImage
)
204 const GLint width
= texImage
->Width
;
205 const GLint height
= texImage
->Height
;
206 const GLint depth
= texImage
->Depth
;
207 const GLint rowstride
= texImage
->RowStride
;
208 const GLushort
*src
= (const GLushort
*) texImage
->Data
;
211 for (img
= 0; img
< depth
; img
++) {
212 for (row
= 0; row
< height
; row
++) {
213 void *dest
= _mesa_image_address(dimensions
, &ctx
->Pack
, pixels
,
214 width
, height
, format
, type
,
216 _mesa_memcpy(dest
, src
, width
* sizeof(GLushort
));
218 /* check for byte swapping */
219 if ((texImage
->TexFormat
== MESA_FORMAT_YCBCR
220 && type
== GL_UNSIGNED_SHORT_8_8_REV_MESA
) ||
221 (texImage
->TexFormat
== MESA_FORMAT_YCBCR_REV
222 && type
== GL_UNSIGNED_SHORT_8_8_MESA
)) {
223 if (!ctx
->Pack
.SwapBytes
)
224 _mesa_swap2((GLushort
*) dest
, width
);
226 else if (ctx
->Pack
.SwapBytes
) {
227 _mesa_swap2((GLushort
*) dest
, width
);
237 * glGetTexImagefor sRGB pixels;
240 get_tex_srgb(GLcontext
*ctx
, GLuint dimensions
,
241 GLenum format
, GLenum type
, GLvoid
*pixels
,
242 const struct gl_texture_image
*texImage
)
244 const GLint width
= texImage
->Width
;
245 const GLint height
= texImage
->Height
;
246 const GLint depth
= texImage
->Depth
;
247 const GLbitfield transferOps
= 0x0;
250 for (img
= 0; img
< depth
; img
++) {
251 for (row
= 0; row
< height
; row
++) {
252 void *dest
= _mesa_image_address(dimensions
, &ctx
->Pack
, pixels
,
253 width
, height
, format
, type
,
256 GLfloat rgba
[MAX_WIDTH
][4];
259 /* convert row to RGBA format */
260 for (col
= 0; col
< width
; col
++) {
261 texImage
->FetchTexelf(texImage
, col
, row
, img
, rgba
[col
]);
262 if (texImage
->_BaseFormat
== GL_LUMINANCE
) {
263 rgba
[col
][RCOMP
] = linear_to_nonlinear(rgba
[col
][RCOMP
]);
264 rgba
[col
][GCOMP
] = 0.0;
265 rgba
[col
][BCOMP
] = 0.0;
267 else if (texImage
->_BaseFormat
== GL_LUMINANCE_ALPHA
) {
268 rgba
[col
][RCOMP
] = linear_to_nonlinear(rgba
[col
][RCOMP
]);
269 rgba
[col
][GCOMP
] = 0.0;
270 rgba
[col
][BCOMP
] = 0.0;
272 else if (texImage
->_BaseFormat
== GL_RGB
||
273 texImage
->_BaseFormat
== GL_RGBA
) {
274 rgba
[col
][RCOMP
] = linear_to_nonlinear(rgba
[col
][RCOMP
]);
275 rgba
[col
][GCOMP
] = linear_to_nonlinear(rgba
[col
][GCOMP
]);
276 rgba
[col
][BCOMP
] = linear_to_nonlinear(rgba
[col
][BCOMP
]);
279 _mesa_pack_rgba_span_float(ctx
, width
, (GLfloat (*)[4]) rgba
,
281 &ctx
->Pack
, transferOps
);
288 * glGetTexImagefor RGBA, Luminance, etc. pixels.
289 * This is the slow way since we use texture sampling.
292 get_tex_rgba(GLcontext
*ctx
, GLuint dimensions
,
293 GLenum format
, GLenum type
, GLvoid
*pixels
,
294 const struct gl_texture_image
*texImage
)
296 const GLint width
= texImage
->Width
;
297 const GLint height
= texImage
->Height
;
298 const GLint depth
= texImage
->Depth
;
299 /* Normally, no pixel transfer ops are performed during glGetTexImage.
300 * The only possible exception is component clamping to [0,1].
302 GLbitfield transferOps
= 0x0;
305 for (img
= 0; img
< depth
; img
++) {
306 for (row
= 0; row
< height
; row
++) {
307 void *dest
= _mesa_image_address(dimensions
, &ctx
->Pack
, pixels
,
308 width
, height
, format
, type
,
310 GLfloat rgba
[MAX_WIDTH
][4];
312 GLenum dataType
= _mesa_get_format_datatype(texImage
->TexFormat
);
314 /* clamp does not apply to GetTexImage (final conversion)?
315 * Looks like we need clamp though when going from format
316 * containing negative values to unsigned format.
318 if (format
== GL_LUMINANCE
|| format
== GL_LUMINANCE_ALPHA
) {
319 transferOps
|= IMAGE_CLAMP_BIT
;
321 else if (!type_with_negative_values(type
) &&
322 (dataType
== GL_FLOAT
||
323 dataType
== GL_SIGNED_NORMALIZED
)) {
324 transferOps
|= IMAGE_CLAMP_BIT
;
327 for (col
= 0; col
< width
; col
++) {
328 texImage
->FetchTexelf(texImage
, col
, row
, img
, rgba
[col
]);
329 if (texImage
->_BaseFormat
== GL_ALPHA
) {
330 rgba
[col
][RCOMP
] = 0.0F
;
331 rgba
[col
][GCOMP
] = 0.0F
;
332 rgba
[col
][BCOMP
] = 0.0F
;
334 else if (texImage
->_BaseFormat
== GL_LUMINANCE
) {
335 rgba
[col
][GCOMP
] = 0.0F
;
336 rgba
[col
][BCOMP
] = 0.0F
;
337 rgba
[col
][ACOMP
] = 1.0F
;
339 else if (texImage
->_BaseFormat
== GL_LUMINANCE_ALPHA
) {
340 rgba
[col
][GCOMP
] = 0.0F
;
341 rgba
[col
][BCOMP
] = 0.0F
;
343 else if (texImage
->_BaseFormat
== GL_INTENSITY
) {
344 rgba
[col
][GCOMP
] = 0.0F
;
345 rgba
[col
][BCOMP
] = 0.0F
;
346 rgba
[col
][ACOMP
] = 1.0F
;
349 _mesa_pack_rgba_span_float(ctx
, width
, (GLfloat (*)[4]) rgba
,
351 &ctx
->Pack
, transferOps
);
358 * Try to do glGetTexImage() with simple memcpy().
359 * \return GL_TRUE if done, GL_FALSE otherwise
362 get_tex_memcpy(GLcontext
*ctx
, GLenum format
, GLenum type
, GLvoid
*pixels
,
363 const struct gl_texture_object
*texObj
,
364 const struct gl_texture_image
*texImage
)
366 GLboolean memCopy
= GL_FALSE
;
368 /* Texture image should have been mapped already */
369 assert(texImage
->Data
);
372 * Check if the src/dst formats are compatible.
373 * Also note that GL's pixel transfer ops don't apply to glGetTexImage()
374 * so we don't have to worry about those.
375 * XXX more format combinations could be supported here.
377 if ((texObj
->Target
== GL_TEXTURE_1D
||
378 texObj
->Target
== GL_TEXTURE_2D
||
379 texObj
->Target
== GL_TEXTURE_RECTANGLE
||
380 (texObj
->Target
>= GL_TEXTURE_CUBE_MAP_POSITIVE_X
&&
381 texObj
->Target
<= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
))) {
382 if (texImage
->TexFormat
== MESA_FORMAT_ARGB8888
&&
384 type
== GL_UNSIGNED_BYTE
&&
385 !ctx
->Pack
.SwapBytes
&&
386 _mesa_little_endian()) {
389 else if (texImage
->TexFormat
== MESA_FORMAT_AL88
&&
390 format
== GL_LUMINANCE_ALPHA
&&
391 type
== GL_UNSIGNED_BYTE
&&
392 !ctx
->Pack
.SwapBytes
&&
393 _mesa_little_endian()) {
396 else if (texImage
->TexFormat
== MESA_FORMAT_L8
&&
397 format
== GL_LUMINANCE
&&
398 type
== GL_UNSIGNED_BYTE
) {
401 else if (texImage
->TexFormat
== MESA_FORMAT_A8
&&
402 format
== GL_ALPHA
&&
403 type
== GL_UNSIGNED_BYTE
) {
409 const GLuint bpp
= _mesa_get_format_bytes(texImage
->TexFormat
);
410 const GLuint bytesPerRow
= texImage
->Width
* bpp
;
412 _mesa_image_address2d(&ctx
->Pack
, pixels
, texImage
->Width
,
413 texImage
->Height
, format
, type
, 0, 0);
414 const GLint dstRowStride
=
415 _mesa_image_row_stride(&ctx
->Pack
, texImage
->Width
, format
, type
);
416 const GLubyte
*src
= texImage
->Data
;
417 const GLint srcRowStride
= texImage
->RowStride
* bpp
;
420 if (bytesPerRow
== dstRowStride
&& bytesPerRow
== srcRowStride
) {
421 memcpy(dst
, src
, bytesPerRow
* texImage
->Height
);
424 for (row
= 0; row
< texImage
->Height
; row
++) {
425 memcpy(dst
, src
, bytesPerRow
);
437 * This is the software fallback for Driver.GetTexImage().
438 * All error checking will have been done before this routine is called.
439 * The texture image must be mapped.
442 _mesa_get_teximage(GLcontext
*ctx
, GLenum target
, GLint level
,
443 GLenum format
, GLenum type
, GLvoid
*pixels
,
444 struct gl_texture_object
*texObj
,
445 struct gl_texture_image
*texImage
)
449 /* If we get here, the texture image should be mapped */
450 assert(texImage
->Data
);
463 if (_mesa_is_bufferobj(ctx
->Pack
.BufferObj
)) {
464 /* Packing texture image into a PBO.
465 * Map the (potentially) VRAM-based buffer into our process space so
466 * we can write into it with the code below.
467 * A hardware driver might use a sophisticated blit to move the
468 * texture data to the PBO if the PBO is in VRAM along with the texture.
470 GLubyte
*buf
= (GLubyte
*)
471 ctx
->Driver
.MapBuffer(ctx
, GL_PIXEL_PACK_BUFFER_EXT
,
472 GL_WRITE_ONLY_ARB
, ctx
->Pack
.BufferObj
);
474 /* out of memory or other unexpected error */
475 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glGetTexImage(map PBO failed)");
478 /* <pixels> was an offset into the PBO.
479 * Now make it a real, client-side pointer inside the mapped region.
481 pixels
= ADD_POINTERS(buf
, pixels
);
484 if (get_tex_memcpy(ctx
, format
, type
, pixels
, texObj
, texImage
)) {
487 else if (format
== GL_COLOR_INDEX
) {
488 get_tex_color_index(ctx
, dimensions
, format
, type
, pixels
, texImage
);
490 else if (format
== GL_DEPTH_COMPONENT
) {
491 get_tex_depth(ctx
, dimensions
, format
, type
, pixels
, texImage
);
493 else if (format
== GL_DEPTH_STENCIL_EXT
) {
494 get_tex_depth_stencil(ctx
, dimensions
, format
, type
, pixels
, texImage
);
496 else if (format
== GL_YCBCR_MESA
) {
497 get_tex_ycbcr(ctx
, dimensions
, format
, type
, pixels
, texImage
);
499 else if (_mesa_get_format_color_encoding(texImage
->TexFormat
) == GL_SRGB
) {
500 get_tex_srgb(ctx
, dimensions
, format
, type
, pixels
, texImage
);
503 get_tex_rgba(ctx
, dimensions
, format
, type
, pixels
, texImage
);
506 if (_mesa_is_bufferobj(ctx
->Pack
.BufferObj
)) {
507 ctx
->Driver
.UnmapBuffer(ctx
, GL_PIXEL_PACK_BUFFER_EXT
,
508 ctx
->Pack
.BufferObj
);
515 * This is the software fallback for Driver.GetCompressedTexImage().
516 * All error checking will have been done before this routine is called.
519 _mesa_get_compressed_teximage(GLcontext
*ctx
, GLenum target
, GLint level
,
521 struct gl_texture_object
*texObj
,
522 struct gl_texture_image
*texImage
)
524 const GLuint row_stride
= _mesa_format_row_stride(texImage
->TexFormat
,
526 const GLuint row_stride_stored
= _mesa_format_row_stride(texImage
->TexFormat
,
527 texImage
->RowStride
);
530 if (_mesa_is_bufferobj(ctx
->Pack
.BufferObj
)) {
531 /* pack texture image into a PBO */
532 GLubyte
*buf
= (GLubyte
*)
533 ctx
->Driver
.MapBuffer(ctx
, GL_PIXEL_PACK_BUFFER_EXT
,
534 GL_WRITE_ONLY_ARB
, ctx
->Pack
.BufferObj
);
536 /* out of memory or other unexpected error */
537 _mesa_error(ctx
, GL_OUT_OF_MEMORY
,
538 "glGetCompresssedTexImage(map PBO failed)");
541 img
= ADD_POINTERS(buf
, img
);
544 /* no pixelstore or pixel transfer, but respect stride */
546 if (row_stride
== row_stride_stored
) {
547 const GLuint size
= _mesa_format_image_size(texImage
->TexFormat
,
551 _mesa_memcpy(img
, texImage
->Data
, size
);
555 _mesa_get_format_block_size(texImage
->TexFormat
, &bw
, &bh
);
556 for (i
= 0; i
< (texImage
->Height
+ bh
- 1) / bh
; i
++) {
557 memcpy((GLubyte
*)img
+ i
* row_stride
,
558 (GLubyte
*)texImage
->Data
+ i
* row_stride_stored
,
563 if (_mesa_is_bufferobj(ctx
->Pack
.BufferObj
)) {
564 ctx
->Driver
.UnmapBuffer(ctx
, GL_PIXEL_PACK_BUFFER_EXT
,
565 ctx
->Pack
.BufferObj
);
572 * Do error checking for a glGetTexImage() call.
573 * \return GL_TRUE if any error, GL_FALSE if no errors.
576 getteximage_error_check(GLcontext
*ctx
, GLenum target
, GLint level
,
577 GLenum format
, GLenum type
, GLvoid
*pixels
)
579 struct gl_texture_object
*texObj
;
580 struct gl_texture_image
*texImage
;
581 const GLuint maxLevels
= _mesa_max_texture_levels(ctx
, target
);
584 if (maxLevels
== 0) {
585 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetTexImage(target=0x%x)", target
);
589 if (level
< 0 || level
>= maxLevels
) {
590 _mesa_error( ctx
, GL_INVALID_VALUE
, "glGetTexImage(level)" );
594 if (_mesa_sizeof_packed_type(type
) <= 0) {
595 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetTexImage(type)" );
599 if (_mesa_components_in_format(format
) <= 0 ||
600 format
== GL_STENCIL_INDEX
) {
601 _mesa_error( ctx
, GL_INVALID_ENUM
, "glGetTexImage(format)" );
605 if (!ctx
->Extensions
.EXT_paletted_texture
&& _mesa_is_index_format(format
)) {
606 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetTexImage(format)");
610 if (!ctx
->Extensions
.ARB_depth_texture
&& _mesa_is_depth_format(format
)) {
611 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetTexImage(format)");
615 if (!ctx
->Extensions
.MESA_ycbcr_texture
&& _mesa_is_ycbcr_format(format
)) {
616 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetTexImage(format)");
620 if (!ctx
->Extensions
.EXT_packed_depth_stencil
621 && _mesa_is_depthstencil_format(format
)) {
622 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetTexImage(format)");
626 if (!ctx
->Extensions
.ATI_envmap_bumpmap
627 && _mesa_is_dudv_format(format
)) {
628 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetTexImage(format)");
632 texObj
= _mesa_get_current_tex_object(ctx
, target
);
634 if (!texObj
|| _mesa_is_proxy_texture(target
)) {
635 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetTexImage(target)");
639 texImage
= _mesa_select_tex_image(ctx
, texObj
, target
, level
);
645 baseFormat
= _mesa_get_format_base_format(texImage
->TexFormat
);
647 /* Make sure the requested image format is compatible with the
648 * texture's format. Note that a color index texture can be converted
649 * to RGBA so that combo is allowed.
651 if (_mesa_is_color_format(format
)
652 && !_mesa_is_color_format(baseFormat
)
653 && !_mesa_is_index_format(baseFormat
)) {
654 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetTexImage(format mismatch)");
657 else if (_mesa_is_index_format(format
)
658 && !_mesa_is_index_format(baseFormat
)) {
659 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetTexImage(format mismatch)");
662 else if (_mesa_is_depth_format(format
)
663 && !_mesa_is_depth_format(baseFormat
)
664 && !_mesa_is_depthstencil_format(baseFormat
)) {
665 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetTexImage(format mismatch)");
668 else if (_mesa_is_ycbcr_format(format
)
669 && !_mesa_is_ycbcr_format(baseFormat
)) {
670 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetTexImage(format mismatch)");
673 else if (_mesa_is_depthstencil_format(format
)
674 && !_mesa_is_depthstencil_format(baseFormat
)) {
675 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetTexImage(format mismatch)");
678 else if (_mesa_is_dudv_format(format
)
679 && !_mesa_is_dudv_format(baseFormat
)) {
680 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glGetTexImage(format mismatch)");
684 if (_mesa_is_bufferobj(ctx
->Pack
.BufferObj
)) {
685 /* packing texture image into a PBO */
686 const GLuint dimensions
= (target
== GL_TEXTURE_3D
) ? 3 : 2;
687 if (!_mesa_validate_pbo_access(dimensions
, &ctx
->Pack
, texImage
->Width
,
688 texImage
->Height
, texImage
->Depth
,
689 format
, type
, pixels
)) {
690 _mesa_error(ctx
, GL_INVALID_OPERATION
,
691 "glGetTexImage(out of bounds PBO write)");
695 /* PBO should not be mapped */
696 if (_mesa_bufferobj_mapped(ctx
->Pack
.BufferObj
)) {
697 _mesa_error(ctx
, GL_INVALID_OPERATION
,
698 "glGetTexImage(PBO is mapped)");
709 * Get texture image. Called by glGetTexImage.
711 * \param target texture target.
712 * \param level image level.
713 * \param format pixel data format for returned image.
714 * \param type pixel data type for returned image.
715 * \param pixels returned pixel data.
718 _mesa_GetTexImage( GLenum target
, GLint level
, GLenum format
,
719 GLenum type
, GLvoid
*pixels
)
721 struct gl_texture_object
*texObj
;
722 struct gl_texture_image
*texImage
;
723 GET_CURRENT_CONTEXT(ctx
);
724 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
726 if (getteximage_error_check(ctx
, target
, level
, format
, type
, pixels
)) {
730 if (!_mesa_is_bufferobj(ctx
->Pack
.BufferObj
) && !pixels
) {
731 /* not an error, do nothing */
735 texObj
= _mesa_get_current_tex_object(ctx
, target
);
736 texImage
= _mesa_select_tex_image(ctx
, texObj
, target
, level
);
738 if (MESA_VERBOSE
& (VERBOSE_API
| VERBOSE_TEXTURE
)) {
739 _mesa_debug(ctx
, "glGetTexImage(tex %u) format = %s, w=%d, h=%d,"
740 " dstFmt=0x%x, dstType=0x%x\n",
742 _mesa_get_format_name(texImage
->TexFormat
),
743 texImage
->Width
, texImage
->Height
,
747 _mesa_lock_texture(ctx
, texObj
);
749 ctx
->Driver
.GetTexImage(ctx
, target
, level
, format
, type
, pixels
,
752 _mesa_unlock_texture(ctx
, texObj
);
758 * Do error checking for a glGetCompressedTexImage() call.
759 * \return GL_TRUE if any error, GL_FALSE if no errors.
762 getcompressedteximage_error_check(GLcontext
*ctx
, GLenum target
, GLint level
,
765 struct gl_texture_object
*texObj
;
766 struct gl_texture_image
*texImage
;
767 const GLuint maxLevels
= _mesa_max_texture_levels(ctx
, target
);
769 if (maxLevels
== 0) {
770 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetCompressedTexImage(target=0x%x)",
775 if (level
< 0 || level
>= maxLevels
) {
776 _mesa_error(ctx
, GL_INVALID_VALUE
,
777 "glGetCompressedTexImageARB(bad level = %d)", level
);
781 if (_mesa_is_proxy_texture(target
)) {
782 _mesa_error(ctx
, GL_INVALID_ENUM
,
783 "glGetCompressedTexImageARB(bad target = %s)",
784 _mesa_lookup_enum_by_nr(target
));
788 texObj
= _mesa_get_current_tex_object(ctx
, target
);
790 _mesa_error(ctx
, GL_INVALID_ENUM
, "glGetCompressedTexImageARB(target)");
794 texImage
= _mesa_select_tex_image(ctx
, texObj
, target
, level
);
797 /* probably invalid mipmap level */
798 _mesa_error(ctx
, GL_INVALID_VALUE
,
799 "glGetCompressedTexImageARB(level)");
803 if (!_mesa_is_format_compressed(texImage
->TexFormat
)) {
804 _mesa_error(ctx
, GL_INVALID_OPERATION
,
805 "glGetCompressedTexImageARB(texture is not compressed)");
809 if (_mesa_is_bufferobj(ctx
->Pack
.BufferObj
)) {
810 GLuint compressedSize
;
812 /* make sure PBO is not mapped */
813 if (_mesa_bufferobj_mapped(ctx
->Pack
.BufferObj
)) {
814 _mesa_error(ctx
, GL_INVALID_OPERATION
,
815 "glGetCompressedTexImage(PBO is mapped)");
819 compressedSize
= _mesa_format_image_size(texImage
->TexFormat
,
824 /* do bounds checking on PBO write */
825 if ((const GLubyte
*) img
+ compressedSize
>
826 (const GLubyte
*) ctx
->Pack
.BufferObj
->Size
) {
827 _mesa_error(ctx
, GL_INVALID_OPERATION
,
828 "glGetCompressedTexImage(out of bounds PBO write)");
838 _mesa_GetCompressedTexImageARB(GLenum target
, GLint level
, GLvoid
*img
)
840 struct gl_texture_object
*texObj
;
841 struct gl_texture_image
*texImage
;
842 GET_CURRENT_CONTEXT(ctx
);
843 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
845 if (getcompressedteximage_error_check(ctx
, target
, level
, img
)) {
849 if (_mesa_is_bufferobj(ctx
->Pack
.BufferObj
) && !img
) {
850 /* not an error, do nothing */
854 texObj
= _mesa_get_current_tex_object(ctx
, target
);
855 texImage
= _mesa_select_tex_image(ctx
, texObj
, target
, level
);
857 if (MESA_VERBOSE
& (VERBOSE_API
| VERBOSE_TEXTURE
)) {
859 "glGetCompressedTexImage(tex %u) format = %s, w=%d, h=%d\n",
861 _mesa_get_format_name(texImage
->TexFormat
),
862 texImage
->Width
, texImage
->Height
);
865 _mesa_lock_texture(ctx
, texObj
);
867 ctx
->Driver
.GetCompressedTexImage(ctx
, target
, level
, img
,
870 _mesa_unlock_texture(ctx
, texObj
);