2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
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 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 #include "bufferobj.h"
31 #include "framebuffer.h"
33 #include "format_unpack.h"
39 #include "glformats.h"
44 * Return true if the conversion L=R+G+B is needed.
47 need_rgb_to_luminance_conversion(gl_format texFormat
, GLenum format
)
49 GLenum baseTexFormat
= _mesa_get_format_base_format(texFormat
);
51 return (baseTexFormat
== GL_RG
||
52 baseTexFormat
== GL_RGB
||
53 baseTexFormat
== GL_RGBA
) &&
54 (format
== GL_LUMINANCE
|| format
== GL_LUMINANCE_ALPHA
);
59 * Return transfer op flags for this ReadPixels operation.
62 get_readpixels_transfer_ops(const struct gl_context
*ctx
, gl_format texFormat
,
63 GLenum format
, GLenum type
, GLboolean uses_blit
)
65 GLbitfield transferOps
= ctx
->_ImageTransferState
;
67 if (format
== GL_DEPTH_COMPONENT
||
68 format
== GL_DEPTH_STENCIL
||
69 format
== GL_STENCIL_INDEX
) {
73 /* Pixel transfer ops (scale, bias, table lookup) do not apply
76 if (_mesa_is_enum_format_integer(format
)) {
81 /* For blit-based ReadPixels packing, the clamping is done automatically
82 * unless the type is float. */
83 if (ctx
->Color
._ClampReadColor
== GL_TRUE
&&
84 (type
== GL_FLOAT
|| type
== GL_HALF_FLOAT
)) {
85 transferOps
|= IMAGE_CLAMP_BIT
;
89 /* For CPU-based ReadPixels packing, the clamping must always be done
90 * for non-float types, */
91 if (ctx
->Color
._ClampReadColor
== GL_TRUE
||
92 (type
!= GL_FLOAT
&& type
!= GL_HALF_FLOAT
)) {
93 transferOps
|= IMAGE_CLAMP_BIT
;
97 /* If the format is unsigned normalized, we can ignore clamping
98 * because the values are already in the range [0,1] so it won't
99 * have any effect anyway.
101 if (_mesa_get_format_datatype(texFormat
) == GL_UNSIGNED_NORMALIZED
&&
102 !need_rgb_to_luminance_conversion(texFormat
, format
)) {
103 transferOps
&= ~IMAGE_CLAMP_BIT
;
111 * Tries to implement glReadPixels() of GL_DEPTH_COMPONENT using memcpy of the
115 fast_read_depth_pixels( struct gl_context
*ctx
,
117 GLsizei width
, GLsizei height
,
118 GLenum type
, GLvoid
*pixels
,
119 const struct gl_pixelstore_attrib
*packing
)
121 struct gl_framebuffer
*fb
= ctx
->ReadBuffer
;
122 struct gl_renderbuffer
*rb
= fb
->Attachment
[BUFFER_DEPTH
].Renderbuffer
;
124 int stride
, dstStride
, j
;
126 if (ctx
->Pixel
.DepthScale
!= 1.0 || ctx
->Pixel
.DepthBias
!= 0.0)
129 if (packing
->SwapBytes
)
132 if (_mesa_get_format_datatype(rb
->Format
) != GL_UNSIGNED_NORMALIZED
)
135 if (!((type
== GL_UNSIGNED_SHORT
&& rb
->Format
== MESA_FORMAT_Z16
) ||
136 type
== GL_UNSIGNED_INT
))
139 ctx
->Driver
.MapRenderbuffer(ctx
, rb
, x
, y
, width
, height
, GL_MAP_READ_BIT
,
143 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glReadPixels");
144 return GL_TRUE
; /* don't bother trying the slow path */
147 dstStride
= _mesa_image_row_stride(packing
, width
, GL_DEPTH_COMPONENT
, type
);
148 dst
= (GLubyte
*) _mesa_image_address2d(packing
, pixels
, width
, height
,
149 GL_DEPTH_COMPONENT
, type
, 0, 0);
151 for (j
= 0; j
< height
; j
++) {
152 if (type
== GL_UNSIGNED_INT
) {
153 _mesa_unpack_uint_z_row(rb
->Format
, width
, map
, (GLuint
*)dst
);
155 ASSERT(type
== GL_UNSIGNED_SHORT
&& rb
->Format
== MESA_FORMAT_Z16
);
156 memcpy(dst
, map
, width
* 2);
162 ctx
->Driver
.UnmapRenderbuffer(ctx
, rb
);
168 * Read pixels for format=GL_DEPTH_COMPONENT.
171 read_depth_pixels( struct gl_context
*ctx
,
173 GLsizei width
, GLsizei height
,
174 GLenum type
, GLvoid
*pixels
,
175 const struct gl_pixelstore_attrib
*packing
)
177 struct gl_framebuffer
*fb
= ctx
->ReadBuffer
;
178 struct gl_renderbuffer
*rb
= fb
->Attachment
[BUFFER_DEPTH
].Renderbuffer
;
181 int dstStride
, stride
;
182 GLfloat
*depthValues
;
187 /* clipping should have been done already */
190 ASSERT(x
+ width
<= (GLint
) rb
->Width
);
191 ASSERT(y
+ height
<= (GLint
) rb
->Height
);
193 if (fast_read_depth_pixels(ctx
, x
, y
, width
, height
, type
, pixels
, packing
))
196 dstStride
= _mesa_image_row_stride(packing
, width
, GL_DEPTH_COMPONENT
, type
);
197 dst
= (GLubyte
*) _mesa_image_address2d(packing
, pixels
, width
, height
,
198 GL_DEPTH_COMPONENT
, type
, 0, 0);
200 ctx
->Driver
.MapRenderbuffer(ctx
, rb
, x
, y
, width
, height
, GL_MAP_READ_BIT
,
203 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glReadPixels");
207 depthValues
= malloc(width
* sizeof(GLfloat
));
210 /* General case (slower) */
211 for (j
= 0; j
< height
; j
++, y
++) {
212 _mesa_unpack_float_z_row(rb
->Format
, width
, map
, depthValues
);
213 _mesa_pack_depth_span(ctx
, width
, dst
, type
, depthValues
, packing
);
220 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glReadPixels");
225 ctx
->Driver
.UnmapRenderbuffer(ctx
, rb
);
230 * Read pixels for format=GL_STENCIL_INDEX.
233 read_stencil_pixels( struct gl_context
*ctx
,
235 GLsizei width
, GLsizei height
,
236 GLenum type
, GLvoid
*pixels
,
237 const struct gl_pixelstore_attrib
*packing
)
239 struct gl_framebuffer
*fb
= ctx
->ReadBuffer
;
240 struct gl_renderbuffer
*rb
= fb
->Attachment
[BUFFER_STENCIL
].Renderbuffer
;
242 GLubyte
*map
, *stencil
;
248 ctx
->Driver
.MapRenderbuffer(ctx
, rb
, x
, y
, width
, height
, GL_MAP_READ_BIT
,
251 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glReadPixels");
255 stencil
= malloc(width
* sizeof(GLubyte
));
258 /* process image row by row */
259 for (j
= 0; j
< height
; j
++) {
262 _mesa_unpack_ubyte_stencil_row(rb
->Format
, width
, map
, stencil
);
263 dest
= _mesa_image_address2d(packing
, pixels
, width
, height
,
264 GL_STENCIL_INDEX
, type
, j
, 0);
266 _mesa_pack_stencil_span(ctx
, width
, type
, dest
, stencil
, packing
);
272 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glReadPixels");
277 ctx
->Driver
.UnmapRenderbuffer(ctx
, rb
);
282 * Try to do glReadPixels of RGBA data using a simple memcpy or swizzle.
283 * \return GL_TRUE if successful, GL_FALSE otherwise (use the slow path)
286 fast_read_rgba_pixels_memcpy( struct gl_context
*ctx
,
288 GLsizei width
, GLsizei height
,
289 GLenum format
, GLenum type
,
291 const struct gl_pixelstore_attrib
*packing
)
293 struct gl_renderbuffer
*rb
= ctx
->ReadBuffer
->_ColorReadBuffer
;
295 int dstStride
, stride
, j
, texelBytes
;
296 GLboolean swizzle_rb
= GL_FALSE
, copy_xrgb
= GL_FALSE
;
298 /* XXX we could check for other swizzle/special cases here as needed */
299 if (rb
->Format
== MESA_FORMAT_RGBA8888_REV
&&
301 type
== GL_UNSIGNED_INT_8_8_8_8_REV
&&
302 !ctx
->Pack
.SwapBytes
) {
303 swizzle_rb
= GL_TRUE
;
305 else if (rb
->Format
== MESA_FORMAT_XRGB8888
&&
307 type
== GL_UNSIGNED_INT_8_8_8_8_REV
&&
308 !ctx
->Pack
.SwapBytes
) {
311 else if (!_mesa_format_matches_format_and_type(rb
->Format
, format
, type
,
312 ctx
->Pack
.SwapBytes
))
315 dstStride
= _mesa_image_row_stride(packing
, width
, format
, type
);
316 dst
= (GLubyte
*) _mesa_image_address2d(packing
, pixels
, width
, height
,
319 ctx
->Driver
.MapRenderbuffer(ctx
, rb
, x
, y
, width
, height
, GL_MAP_READ_BIT
,
322 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glReadPixels");
323 return GL_TRUE
; /* don't bother trying the slow path */
326 texelBytes
= _mesa_get_format_bytes(rb
->Format
);
330 for (j
= 0; j
< height
; j
++) {
332 for (i
= 0; i
< width
; i
++) {
333 GLuint
*dst4
= (GLuint
*) dst
, *map4
= (GLuint
*) map
;
334 GLuint pixel
= map4
[i
];
335 dst4
[i
] = (pixel
& 0xff00ff00)
336 | ((pixel
& 0x00ff0000) >> 16)
337 | ((pixel
& 0x000000ff) << 16);
342 } else if (copy_xrgb
) {
343 /* convert xrgb -> argb */
344 for (j
= 0; j
< height
; j
++) {
345 GLuint
*dst4
= (GLuint
*) dst
, *map4
= (GLuint
*) map
;
347 for (i
= 0; i
< width
; i
++) {
348 dst4
[i
] = map4
[i
] | 0xff000000; /* set A=0xff */
355 for (j
= 0; j
< height
; j
++) {
356 memcpy(dst
, map
, width
* texelBytes
);
362 ctx
->Driver
.UnmapRenderbuffer(ctx
, rb
);
368 slow_read_rgba_pixels( struct gl_context
*ctx
,
370 GLsizei width
, GLsizei height
,
371 GLenum format
, GLenum type
,
373 const struct gl_pixelstore_attrib
*packing
,
374 GLbitfield transferOps
)
376 struct gl_renderbuffer
*rb
= ctx
->ReadBuffer
->_ColorReadBuffer
;
377 const gl_format rbFormat
= _mesa_get_srgb_format_linear(rb
->Format
);
380 int dstStride
, stride
, j
;
381 GLboolean dst_is_integer
= _mesa_is_enum_format_integer(format
);
382 GLboolean dst_is_uint
= _mesa_is_format_unsigned(rbFormat
);
384 dstStride
= _mesa_image_row_stride(packing
, width
, format
, type
);
385 dst
= (GLubyte
*) _mesa_image_address2d(packing
, pixels
, width
, height
,
388 ctx
->Driver
.MapRenderbuffer(ctx
, rb
, x
, y
, width
, height
, GL_MAP_READ_BIT
,
391 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glReadPixels");
395 rgba
= malloc(width
* MAX_PIXEL_BYTES
);
399 for (j
= 0; j
< height
; j
++) {
400 if (dst_is_integer
) {
401 _mesa_unpack_uint_rgba_row(rbFormat
, width
, map
, (GLuint (*)[4]) rgba
);
402 _mesa_rebase_rgba_uint(width
, (GLuint (*)[4]) rgba
,
405 _mesa_pack_rgba_span_from_uints(ctx
, width
, (GLuint (*)[4]) rgba
, format
,
408 _mesa_pack_rgba_span_from_ints(ctx
, width
, (GLint (*)[4]) rgba
, format
,
412 _mesa_unpack_rgba_row(rbFormat
, width
, map
, (GLfloat (*)[4]) rgba
);
413 _mesa_rebase_rgba_float(width
, (GLfloat (*)[4]) rgba
,
415 _mesa_pack_rgba_span_float(ctx
, width
, (GLfloat (*)[4]) rgba
, format
,
416 type
, dst
, packing
, transferOps
);
425 ctx
->Driver
.UnmapRenderbuffer(ctx
, rb
);
429 * Read R, G, B, A, RGB, L, or LA pixels.
432 read_rgba_pixels( struct gl_context
*ctx
,
434 GLsizei width
, GLsizei height
,
435 GLenum format
, GLenum type
, GLvoid
*pixels
,
436 const struct gl_pixelstore_attrib
*packing
)
438 GLbitfield transferOps
;
439 struct gl_framebuffer
*fb
= ctx
->ReadBuffer
;
440 struct gl_renderbuffer
*rb
= fb
->_ColorReadBuffer
;
445 transferOps
= get_readpixels_transfer_ops(ctx
, rb
->Format
, format
, type
,
448 /* Try the optimized paths first. */
450 fast_read_rgba_pixels_memcpy(ctx
, x
, y
, width
, height
,
451 format
, type
, pixels
, packing
)) {
455 slow_read_rgba_pixels(ctx
, x
, y
, width
, height
,
456 format
, type
, pixels
, packing
, transferOps
);
460 * For a packed depth/stencil buffer being read as depth/stencil, just memcpy the
461 * data (possibly swapping 8/24 vs 24/8 as we go).
464 fast_read_depth_stencil_pixels(struct gl_context
*ctx
,
466 GLsizei width
, GLsizei height
,
467 GLubyte
*dst
, int dstStride
)
469 struct gl_framebuffer
*fb
= ctx
->ReadBuffer
;
470 struct gl_renderbuffer
*rb
= fb
->Attachment
[BUFFER_DEPTH
].Renderbuffer
;
471 struct gl_renderbuffer
*stencilRb
= fb
->Attachment
[BUFFER_STENCIL
].Renderbuffer
;
478 if (rb
->Format
!= MESA_FORMAT_Z24_S8
&&
479 rb
->Format
!= MESA_FORMAT_S8_Z24
)
482 ctx
->Driver
.MapRenderbuffer(ctx
, rb
, x
, y
, width
, height
, GL_MAP_READ_BIT
,
485 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glReadPixels");
486 return GL_TRUE
; /* don't bother trying the slow path */
489 for (i
= 0; i
< height
; i
++) {
490 _mesa_unpack_uint_24_8_depth_stencil_row(rb
->Format
, width
,
496 ctx
->Driver
.UnmapRenderbuffer(ctx
, rb
);
503 * For non-float-depth and stencil buffers being read as 24/8 depth/stencil,
504 * copy the integer data directly instead of converting depth to float and
508 fast_read_depth_stencil_pixels_separate(struct gl_context
*ctx
,
510 GLsizei width
, GLsizei height
,
511 uint32_t *dst
, int dstStride
)
513 struct gl_framebuffer
*fb
= ctx
->ReadBuffer
;
514 struct gl_renderbuffer
*depthRb
= fb
->Attachment
[BUFFER_DEPTH
].Renderbuffer
;
515 struct gl_renderbuffer
*stencilRb
= fb
->Attachment
[BUFFER_STENCIL
].Renderbuffer
;
516 GLubyte
*depthMap
, *stencilMap
, *stencilVals
;
517 int depthStride
, stencilStride
, i
, j
;
519 if (_mesa_get_format_datatype(depthRb
->Format
) != GL_UNSIGNED_NORMALIZED
)
522 ctx
->Driver
.MapRenderbuffer(ctx
, depthRb
, x
, y
, width
, height
,
523 GL_MAP_READ_BIT
, &depthMap
, &depthStride
);
525 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glReadPixels");
526 return GL_TRUE
; /* don't bother trying the slow path */
529 ctx
->Driver
.MapRenderbuffer(ctx
, stencilRb
, x
, y
, width
, height
,
530 GL_MAP_READ_BIT
, &stencilMap
, &stencilStride
);
532 ctx
->Driver
.UnmapRenderbuffer(ctx
, depthRb
);
533 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glReadPixels");
534 return GL_TRUE
; /* don't bother trying the slow path */
537 stencilVals
= malloc(width
* sizeof(GLubyte
));
540 for (j
= 0; j
< height
; j
++) {
541 _mesa_unpack_uint_z_row(depthRb
->Format
, width
, depthMap
, dst
);
542 _mesa_unpack_ubyte_stencil_row(stencilRb
->Format
, width
,
543 stencilMap
, stencilVals
);
545 for (i
= 0; i
< width
; i
++) {
546 dst
[i
] = (dst
[i
] & 0xffffff00) | stencilVals
[i
];
549 depthMap
+= depthStride
;
550 stencilMap
+= stencilStride
;
551 dst
+= dstStride
/ 4;
555 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glReadPixels");
560 ctx
->Driver
.UnmapRenderbuffer(ctx
, depthRb
);
561 ctx
->Driver
.UnmapRenderbuffer(ctx
, stencilRb
);
567 slow_read_depth_stencil_pixels_separate(struct gl_context
*ctx
,
569 GLsizei width
, GLsizei height
,
571 const struct gl_pixelstore_attrib
*packing
,
572 GLubyte
*dst
, int dstStride
)
574 struct gl_framebuffer
*fb
= ctx
->ReadBuffer
;
575 struct gl_renderbuffer
*depthRb
= fb
->Attachment
[BUFFER_DEPTH
].Renderbuffer
;
576 struct gl_renderbuffer
*stencilRb
= fb
->Attachment
[BUFFER_STENCIL
].Renderbuffer
;
577 GLubyte
*depthMap
, *stencilMap
;
578 int depthStride
, stencilStride
, j
;
579 GLubyte
*stencilVals
;
583 /* The depth and stencil buffers might be separate, or a single buffer.
584 * If one buffer, only map it once.
586 ctx
->Driver
.MapRenderbuffer(ctx
, depthRb
, x
, y
, width
, height
,
587 GL_MAP_READ_BIT
, &depthMap
, &depthStride
);
589 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glReadPixels");
593 if (stencilRb
!= depthRb
) {
594 ctx
->Driver
.MapRenderbuffer(ctx
, stencilRb
, x
, y
, width
, height
,
595 GL_MAP_READ_BIT
, &stencilMap
,
598 ctx
->Driver
.UnmapRenderbuffer(ctx
, depthRb
);
599 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glReadPixels");
604 stencilMap
= depthMap
;
605 stencilStride
= depthStride
;
608 stencilVals
= malloc(width
* sizeof(GLubyte
));
609 depthVals
= malloc(width
* sizeof(GLfloat
));
611 if (stencilVals
&& depthVals
) {
612 for (j
= 0; j
< height
; j
++) {
613 _mesa_unpack_float_z_row(depthRb
->Format
, width
, depthMap
, depthVals
);
614 _mesa_unpack_ubyte_stencil_row(stencilRb
->Format
, width
,
615 stencilMap
, stencilVals
);
617 _mesa_pack_depth_stencil_span(ctx
, width
, type
, (GLuint
*)dst
,
618 depthVals
, stencilVals
, packing
);
620 depthMap
+= depthStride
;
621 stencilMap
+= stencilStride
;
626 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glReadPixels");
632 ctx
->Driver
.UnmapRenderbuffer(ctx
, depthRb
);
633 if (stencilRb
!= depthRb
) {
634 ctx
->Driver
.UnmapRenderbuffer(ctx
, stencilRb
);
640 * Read combined depth/stencil values.
641 * We'll have already done error checking to be sure the expected
642 * depth and stencil buffers really exist.
645 read_depth_stencil_pixels(struct gl_context
*ctx
,
647 GLsizei width
, GLsizei height
,
648 GLenum type
, GLvoid
*pixels
,
649 const struct gl_pixelstore_attrib
*packing
)
651 const GLboolean scaleOrBias
652 = ctx
->Pixel
.DepthScale
!= 1.0 || ctx
->Pixel
.DepthBias
!= 0.0;
653 const GLboolean stencilTransfer
= ctx
->Pixel
.IndexShift
654 || ctx
->Pixel
.IndexOffset
|| ctx
->Pixel
.MapStencilFlag
;
658 dst
= (GLubyte
*) _mesa_image_address2d(packing
, pixels
,
660 GL_DEPTH_STENCIL_EXT
,
662 dstStride
= _mesa_image_row_stride(packing
, width
,
663 GL_DEPTH_STENCIL_EXT
, type
);
665 /* Fast 24/8 reads. */
666 if (type
== GL_UNSIGNED_INT_24_8
&&
667 !scaleOrBias
&& !stencilTransfer
&& !packing
->SwapBytes
) {
668 if (fast_read_depth_stencil_pixels(ctx
, x
, y
, width
, height
,
672 if (fast_read_depth_stencil_pixels_separate(ctx
, x
, y
, width
, height
,
673 (uint32_t *)dst
, dstStride
))
677 slow_read_depth_stencil_pixels_separate(ctx
, x
, y
, width
, height
,
685 * Software fallback routine for ctx->Driver.ReadPixels().
686 * By time we get here, all error checking will have been done.
689 _mesa_readpixels(struct gl_context
*ctx
,
690 GLint x
, GLint y
, GLsizei width
, GLsizei height
,
691 GLenum format
, GLenum type
,
692 const struct gl_pixelstore_attrib
*packing
,
695 struct gl_pixelstore_attrib clippedPacking
= *packing
;
698 _mesa_update_state(ctx
);
700 /* Do all needed clipping here, so that we can forget about it later */
701 if (_mesa_clip_readpixels(ctx
, &x
, &y
, &width
, &height
, &clippedPacking
)) {
703 pixels
= _mesa_map_pbo_dest(ctx
, &clippedPacking
, pixels
);
707 case GL_STENCIL_INDEX
:
708 read_stencil_pixels(ctx
, x
, y
, width
, height
, type
, pixels
,
711 case GL_DEPTH_COMPONENT
:
712 read_depth_pixels(ctx
, x
, y
, width
, height
, type
, pixels
,
715 case GL_DEPTH_STENCIL_EXT
:
716 read_depth_stencil_pixels(ctx
, x
, y
, width
, height
, type
, pixels
,
720 /* all other formats should be color formats */
721 read_rgba_pixels(ctx
, x
, y
, width
, height
, format
, type
, pixels
,
725 _mesa_unmap_pbo_dest(ctx
, &clippedPacking
);
732 read_pixels_es3_error_check(GLenum format
, GLenum type
,
733 const struct gl_renderbuffer
*rb
)
735 const GLenum internalFormat
= rb
->InternalFormat
;
736 const GLenum data_type
= _mesa_get_format_datatype(rb
->Format
);
737 GLboolean is_unsigned_int
= GL_FALSE
;
738 GLboolean is_signed_int
= GL_FALSE
;
740 if (!_mesa_is_color_format(internalFormat
)) {
741 return GL_INVALID_OPERATION
;
744 is_unsigned_int
= _mesa_is_enum_format_unsigned_int(internalFormat
);
745 if (!is_unsigned_int
) {
746 is_signed_int
= _mesa_is_enum_format_signed_int(internalFormat
);
751 if (type
== GL_FLOAT
&& data_type
== GL_FLOAT
)
752 return GL_NO_ERROR
; /* EXT_color_buffer_float */
753 if (type
== GL_UNSIGNED_BYTE
&& data_type
== GL_UNSIGNED_NORMALIZED
)
755 if (internalFormat
== GL_RGB10_A2
&&
756 type
== GL_UNSIGNED_INT_2_10_10_10_REV
)
758 if (internalFormat
== GL_RGB10_A2UI
&& type
== GL_UNSIGNED_BYTE
)
762 /* GL_EXT_read_format_bgra */
763 if (type
== GL_UNSIGNED_BYTE
||
764 type
== GL_UNSIGNED_SHORT_4_4_4_4_REV
||
765 type
== GL_UNSIGNED_SHORT_1_5_5_5_REV
)
768 case GL_RGBA_INTEGER
:
769 if ((is_signed_int
&& type
== GL_INT
) ||
770 (is_unsigned_int
&& type
== GL_UNSIGNED_INT
))
775 return GL_INVALID_OPERATION
;
780 _mesa_ReadnPixelsARB( GLint x
, GLint y
, GLsizei width
, GLsizei height
,
781 GLenum format
, GLenum type
, GLsizei bufSize
,
784 GLenum err
= GL_NO_ERROR
;
785 struct gl_renderbuffer
*rb
;
787 GET_CURRENT_CONTEXT(ctx
);
789 FLUSH_VERTICES(ctx
, 0);
790 FLUSH_CURRENT(ctx
, 0);
792 if (MESA_VERBOSE
& VERBOSE_API
)
793 _mesa_debug(ctx
, "glReadPixels(%d, %d, %s, %s, %p)\n",
795 _mesa_lookup_enum_by_nr(format
),
796 _mesa_lookup_enum_by_nr(type
),
799 if (width
< 0 || height
< 0) {
800 _mesa_error( ctx
, GL_INVALID_VALUE
,
801 "glReadPixels(width=%d height=%d)", width
, height
);
806 _mesa_update_state(ctx
);
808 if (ctx
->ReadBuffer
->_Status
!= GL_FRAMEBUFFER_COMPLETE_EXT
) {
809 _mesa_error(ctx
, GL_INVALID_FRAMEBUFFER_OPERATION_EXT
,
810 "glReadPixels(incomplete framebuffer)" );
814 rb
= _mesa_get_read_renderbuffer_for_format(ctx
, format
);
816 _mesa_error(ctx
, GL_INVALID_OPERATION
,
817 "glReadPixels(read buffer)");
821 /* OpenGL ES 1.x and OpenGL ES 2.0 impose additional restrictions on the
822 * combinations of format and type that can be used.
824 * Technically, only two combinations are actually allowed:
825 * GL_RGBA/GL_UNSIGNED_BYTE, and some implementation-specific internal
826 * preferred combination. This code doesn't know what that preferred
827 * combination is, and Mesa can handle anything valid. Just work instead.
829 if (_mesa_is_gles(ctx
)) {
830 if (ctx
->API
== API_OPENGLES2
&&
831 _mesa_is_color_format(format
) &&
832 _mesa_get_color_read_format(ctx
) == format
&&
833 _mesa_get_color_read_type(ctx
) == type
) {
835 } else if (ctx
->Version
< 30) {
836 err
= _mesa_es_error_check_format_and_type(format
, type
, 2);
837 if (err
== GL_NO_ERROR
) {
838 if (type
== GL_FLOAT
|| type
== GL_HALF_FLOAT_OES
) {
839 err
= GL_INVALID_OPERATION
;
843 err
= read_pixels_es3_error_check(format
, type
, rb
);
846 if (err
== GL_NO_ERROR
&& (format
== GL_DEPTH_COMPONENT
847 || format
== GL_DEPTH_STENCIL
)) {
848 err
= GL_INVALID_ENUM
;
851 if (err
!= GL_NO_ERROR
) {
852 _mesa_error(ctx
, err
, "glReadPixels(invalid format %s and/or type %s)",
853 _mesa_lookup_enum_by_nr(format
),
854 _mesa_lookup_enum_by_nr(type
));
859 err
= _mesa_error_check_format_and_type(ctx
, format
, type
);
860 if (err
!= GL_NO_ERROR
) {
861 _mesa_error(ctx
, err
, "glReadPixels(invalid format %s and/or type %s)",
862 _mesa_lookup_enum_by_nr(format
),
863 _mesa_lookup_enum_by_nr(type
));
867 if (_mesa_is_user_fbo(ctx
->ReadBuffer
) &&
868 ctx
->ReadBuffer
->Visual
.samples
> 0) {
869 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glReadPixels(multisample FBO)");
873 if (!_mesa_source_buffer_exists(ctx
, format
)) {
874 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glReadPixels(no readbuffer)");
878 /* Check that the destination format and source buffer are both
879 * integer-valued or both non-integer-valued.
881 if (ctx
->Extensions
.EXT_texture_integer
&& _mesa_is_color_format(format
)) {
882 const struct gl_renderbuffer
*rb
= ctx
->ReadBuffer
->_ColorReadBuffer
;
883 const GLboolean srcInteger
= _mesa_is_format_integer_color(rb
->Format
);
884 const GLboolean dstInteger
= _mesa_is_enum_format_integer(format
);
885 if (dstInteger
!= srcInteger
) {
886 _mesa_error(ctx
, GL_INVALID_OPERATION
,
887 "glReadPixels(integer / non-integer format mismatch");
892 if (width
== 0 || height
== 0)
893 return; /* nothing to do */
895 if (!_mesa_validate_pbo_access(2, &ctx
->Pack
, width
, height
, 1,
896 format
, type
, bufSize
, pixels
)) {
897 if (_mesa_is_bufferobj(ctx
->Pack
.BufferObj
)) {
898 _mesa_error(ctx
, GL_INVALID_OPERATION
,
899 "glReadPixels(out of bounds PBO access)");
901 _mesa_error(ctx
, GL_INVALID_OPERATION
,
902 "glReadnPixelsARB(out of bounds access:"
903 " bufSize (%d) is too small)", bufSize
);
908 if (_mesa_is_bufferobj(ctx
->Pack
.BufferObj
) &&
909 _mesa_bufferobj_mapped(ctx
->Pack
.BufferObj
)) {
910 /* buffer is mapped - that's an error */
911 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glReadPixels(PBO is mapped)");
915 ctx
->Driver
.ReadPixels(ctx
, x
, y
, width
, height
,
916 format
, type
, &ctx
->Pack
, pixels
);
920 _mesa_ReadPixels( GLint x
, GLint y
, GLsizei width
, GLsizei height
,
921 GLenum format
, GLenum type
, GLvoid
*pixels
)
923 _mesa_ReadnPixelsARB(x
, y
, width
, height
, format
, type
, INT_MAX
, pixels
);