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"
43 /* Inexplicably, GL_HALF_FLOAT_OES has a different value than GL_HALF_FLOAT.
45 #ifndef GL_HALF_FLOAT_OES
46 #define GL_HALF_FLOAT_OES 0x8D61
50 * Tries to implement glReadPixels() of GL_DEPTH_COMPONENT using memcpy of the
54 fast_read_depth_pixels( struct gl_context
*ctx
,
56 GLsizei width
, GLsizei height
,
57 GLenum type
, GLvoid
*pixels
,
58 const struct gl_pixelstore_attrib
*packing
)
60 struct gl_framebuffer
*fb
= ctx
->ReadBuffer
;
61 struct gl_renderbuffer
*rb
= fb
->Attachment
[BUFFER_DEPTH
].Renderbuffer
;
63 int stride
, dstStride
, j
;
65 if (ctx
->Pixel
.DepthScale
!= 1.0 || ctx
->Pixel
.DepthBias
!= 0.0)
68 if (packing
->SwapBytes
)
71 if (_mesa_get_format_datatype(rb
->Format
) != GL_UNSIGNED_NORMALIZED
)
74 if (!((type
== GL_UNSIGNED_SHORT
&& rb
->Format
== MESA_FORMAT_Z16
) ||
75 type
== GL_UNSIGNED_INT
))
78 ctx
->Driver
.MapRenderbuffer(ctx
, rb
, x
, y
, width
, height
, GL_MAP_READ_BIT
,
82 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glReadPixels");
83 return GL_TRUE
; /* don't bother trying the slow path */
86 dstStride
= _mesa_image_row_stride(packing
, width
, GL_DEPTH_COMPONENT
, type
);
87 dst
= (GLubyte
*) _mesa_image_address2d(packing
, pixels
, width
, height
,
88 GL_DEPTH_COMPONENT
, type
, 0, 0);
90 for (j
= 0; j
< height
; j
++) {
91 if (type
== GL_UNSIGNED_INT
) {
92 _mesa_unpack_uint_z_row(rb
->Format
, width
, map
, (GLuint
*)dst
);
94 ASSERT(type
== GL_UNSIGNED_SHORT
&& rb
->Format
== MESA_FORMAT_Z16
);
95 memcpy(dst
, map
, width
* 2);
101 ctx
->Driver
.UnmapRenderbuffer(ctx
, rb
);
107 * Read pixels for format=GL_DEPTH_COMPONENT.
110 read_depth_pixels( struct gl_context
*ctx
,
112 GLsizei width
, GLsizei height
,
113 GLenum type
, GLvoid
*pixels
,
114 const struct gl_pixelstore_attrib
*packing
)
116 struct gl_framebuffer
*fb
= ctx
->ReadBuffer
;
117 struct gl_renderbuffer
*rb
= fb
->Attachment
[BUFFER_DEPTH
].Renderbuffer
;
120 int dstStride
, stride
;
121 GLfloat
*depthValues
;
126 /* clipping should have been done already */
129 ASSERT(x
+ width
<= (GLint
) rb
->Width
);
130 ASSERT(y
+ height
<= (GLint
) rb
->Height
);
132 if (fast_read_depth_pixels(ctx
, x
, y
, width
, height
, type
, pixels
, packing
))
135 dstStride
= _mesa_image_row_stride(packing
, width
, GL_DEPTH_COMPONENT
, type
);
136 dst
= (GLubyte
*) _mesa_image_address2d(packing
, pixels
, width
, height
,
137 GL_DEPTH_COMPONENT
, type
, 0, 0);
139 ctx
->Driver
.MapRenderbuffer(ctx
, rb
, x
, y
, width
, height
, GL_MAP_READ_BIT
,
142 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glReadPixels");
146 depthValues
= (GLfloat
*) malloc(width
* sizeof(GLfloat
));
149 /* General case (slower) */
150 for (j
= 0; j
< height
; j
++, y
++) {
151 _mesa_unpack_float_z_row(rb
->Format
, width
, map
, depthValues
);
152 _mesa_pack_depth_span(ctx
, width
, dst
, type
, depthValues
, packing
);
159 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glReadPixels");
164 ctx
->Driver
.UnmapRenderbuffer(ctx
, rb
);
169 * Read pixels for format=GL_STENCIL_INDEX.
172 read_stencil_pixels( struct gl_context
*ctx
,
174 GLsizei width
, GLsizei height
,
175 GLenum type
, GLvoid
*pixels
,
176 const struct gl_pixelstore_attrib
*packing
)
178 struct gl_framebuffer
*fb
= ctx
->ReadBuffer
;
179 struct gl_renderbuffer
*rb
= fb
->Attachment
[BUFFER_STENCIL
].Renderbuffer
;
181 GLubyte
*map
, *stencil
;
187 ctx
->Driver
.MapRenderbuffer(ctx
, rb
, x
, y
, width
, height
, GL_MAP_READ_BIT
,
190 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glReadPixels");
194 stencil
= (GLubyte
*) malloc(width
* sizeof(GLubyte
));
197 /* process image row by row */
198 for (j
= 0; j
< height
; j
++) {
201 _mesa_unpack_ubyte_stencil_row(rb
->Format
, width
, map
, stencil
);
202 dest
= _mesa_image_address2d(packing
, pixels
, width
, height
,
203 GL_STENCIL_INDEX
, type
, j
, 0);
205 _mesa_pack_stencil_span(ctx
, width
, type
, dest
, stencil
, packing
);
211 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glReadPixels");
216 ctx
->Driver
.UnmapRenderbuffer(ctx
, rb
);
221 * Try to do glReadPixels of RGBA data using a simple memcpy or swizzle.
222 * \return GL_TRUE if successful, GL_FALSE otherwise (use the slow path)
225 fast_read_rgba_pixels_memcpy( struct gl_context
*ctx
,
227 GLsizei width
, GLsizei height
,
228 GLenum format
, GLenum type
,
230 const struct gl_pixelstore_attrib
*packing
,
231 GLbitfield transferOps
)
233 struct gl_renderbuffer
*rb
= ctx
->ReadBuffer
->_ColorReadBuffer
;
235 int dstStride
, stride
, j
, texelBytes
;
236 GLboolean swizzle_rb
= GL_FALSE
, copy_xrgb
= GL_FALSE
;
238 /* XXX we could check for other swizzle/special cases here as needed */
239 if (rb
->Format
== MESA_FORMAT_RGBA8888_REV
&&
241 type
== GL_UNSIGNED_INT_8_8_8_8_REV
&&
242 !ctx
->Pack
.SwapBytes
) {
243 swizzle_rb
= GL_TRUE
;
245 else if (rb
->Format
== MESA_FORMAT_XRGB8888
&&
247 type
== GL_UNSIGNED_INT_8_8_8_8_REV
&&
248 !ctx
->Pack
.SwapBytes
) {
251 else if (!_mesa_format_matches_format_and_type(rb
->Format
, format
, type
,
252 ctx
->Pack
.SwapBytes
))
255 /* If the format is unsigned normalized then we can ignore clamping
256 * because the values are already in the range [0,1] so it won't
257 * have any effect anyway.
259 if (_mesa_get_format_datatype(rb
->Format
) == GL_UNSIGNED_NORMALIZED
)
260 transferOps
&= ~IMAGE_CLAMP_BIT
;
265 dstStride
= _mesa_image_row_stride(packing
, width
, format
, type
);
266 dst
= (GLubyte
*) _mesa_image_address2d(packing
, pixels
, width
, height
,
269 ctx
->Driver
.MapRenderbuffer(ctx
, rb
, x
, y
, width
, height
, GL_MAP_READ_BIT
,
272 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glReadPixels");
273 return GL_TRUE
; /* don't bother trying the slow path */
276 texelBytes
= _mesa_get_format_bytes(rb
->Format
);
280 for (j
= 0; j
< height
; j
++) {
282 for (i
= 0; i
< width
; i
++) {
283 GLuint
*dst4
= (GLuint
*) dst
, *map4
= (GLuint
*) map
;
284 GLuint pixel
= map4
[i
];
285 dst4
[i
] = (pixel
& 0xff00ff00)
286 | ((pixel
& 0x00ff0000) >> 16)
287 | ((pixel
& 0x000000ff) << 16);
292 } else if (copy_xrgb
) {
293 /* convert xrgb -> argb */
294 for (j
= 0; j
< height
; j
++) {
295 GLuint
*dst4
= (GLuint
*) dst
, *map4
= (GLuint
*) map
;
297 for (i
= 0; i
< width
; i
++) {
298 dst4
[i
] = map4
[i
] | 0xff000000; /* set A=0xff */
305 for (j
= 0; j
< height
; j
++) {
306 memcpy(dst
, map
, width
* texelBytes
);
312 ctx
->Driver
.UnmapRenderbuffer(ctx
, rb
);
318 slow_read_rgba_pixels( struct gl_context
*ctx
,
320 GLsizei width
, GLsizei height
,
321 GLenum format
, GLenum type
,
323 const struct gl_pixelstore_attrib
*packing
,
324 GLbitfield transferOps
)
326 struct gl_renderbuffer
*rb
= ctx
->ReadBuffer
->_ColorReadBuffer
;
327 const gl_format rbFormat
= _mesa_get_srgb_format_linear(rb
->Format
);
330 int dstStride
, stride
, j
;
331 GLboolean dst_is_integer
= _mesa_is_enum_format_integer(format
);
332 GLboolean dst_is_uint
= _mesa_is_format_unsigned(rbFormat
);
334 dstStride
= _mesa_image_row_stride(packing
, width
, format
, type
);
335 dst
= (GLubyte
*) _mesa_image_address2d(packing
, pixels
, width
, height
,
338 ctx
->Driver
.MapRenderbuffer(ctx
, rb
, x
, y
, width
, height
, GL_MAP_READ_BIT
,
341 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glReadPixels");
345 rgba
= malloc(width
* MAX_PIXEL_BYTES
);
349 for (j
= 0; j
< height
; j
++) {
350 if (dst_is_integer
) {
351 _mesa_unpack_uint_rgba_row(rbFormat
, width
, map
, (GLuint (*)[4]) rgba
);
352 _mesa_rebase_rgba_uint(width
, (GLuint (*)[4]) rgba
,
355 _mesa_pack_rgba_span_from_uints(ctx
, width
, (GLuint (*)[4]) rgba
, format
,
358 _mesa_pack_rgba_span_from_ints(ctx
, width
, (GLint (*)[4]) rgba
, format
,
362 _mesa_unpack_rgba_row(rbFormat
, width
, map
, (GLfloat (*)[4]) rgba
);
363 _mesa_rebase_rgba_float(width
, (GLfloat (*)[4]) rgba
,
365 _mesa_pack_rgba_span_float(ctx
, width
, (GLfloat (*)[4]) rgba
, format
,
366 type
, dst
, packing
, transferOps
);
375 ctx
->Driver
.UnmapRenderbuffer(ctx
, rb
);
379 * Read R, G, B, A, RGB, L, or LA pixels.
382 read_rgba_pixels( struct gl_context
*ctx
,
384 GLsizei width
, GLsizei height
,
385 GLenum format
, GLenum type
, GLvoid
*pixels
,
386 const struct gl_pixelstore_attrib
*packing
)
388 GLbitfield transferOps
= ctx
->_ImageTransferState
;
389 struct gl_framebuffer
*fb
= ctx
->ReadBuffer
;
390 struct gl_renderbuffer
*rb
= fb
->_ColorReadBuffer
;
395 if ((ctx
->Color
._ClampReadColor
== GL_TRUE
|| type
!= GL_FLOAT
) &&
396 !_mesa_is_enum_format_integer(format
)) {
397 transferOps
|= IMAGE_CLAMP_BIT
;
400 /* Try the optimized paths first. */
401 if (fast_read_rgba_pixels_memcpy(ctx
, x
, y
, width
, height
,
402 format
, type
, pixels
, packing
,
407 slow_read_rgba_pixels(ctx
, x
, y
, width
, height
,
408 format
, type
, pixels
, packing
, transferOps
);
412 * For a packed depth/stencil buffer being read as depth/stencil, just memcpy the
413 * data (possibly swapping 8/24 vs 24/8 as we go).
416 fast_read_depth_stencil_pixels(struct gl_context
*ctx
,
418 GLsizei width
, GLsizei height
,
419 GLubyte
*dst
, int dstStride
)
421 struct gl_framebuffer
*fb
= ctx
->ReadBuffer
;
422 struct gl_renderbuffer
*rb
= fb
->Attachment
[BUFFER_DEPTH
].Renderbuffer
;
423 struct gl_renderbuffer
*stencilRb
= fb
->Attachment
[BUFFER_STENCIL
].Renderbuffer
;
430 if (rb
->Format
!= MESA_FORMAT_Z24_S8
&&
431 rb
->Format
!= MESA_FORMAT_S8_Z24
)
434 ctx
->Driver
.MapRenderbuffer(ctx
, rb
, x
, y
, width
, height
, GL_MAP_READ_BIT
,
437 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glReadPixels");
438 return GL_TRUE
; /* don't bother trying the slow path */
441 for (i
= 0; i
< height
; i
++) {
442 _mesa_unpack_uint_24_8_depth_stencil_row(rb
->Format
, width
,
448 ctx
->Driver
.UnmapRenderbuffer(ctx
, rb
);
455 * For non-float-depth and stencil buffers being read as 24/8 depth/stencil,
456 * copy the integer data directly instead of converting depth to float and
460 fast_read_depth_stencil_pixels_separate(struct gl_context
*ctx
,
462 GLsizei width
, GLsizei height
,
463 uint32_t *dst
, int dstStride
)
465 struct gl_framebuffer
*fb
= ctx
->ReadBuffer
;
466 struct gl_renderbuffer
*depthRb
= fb
->Attachment
[BUFFER_DEPTH
].Renderbuffer
;
467 struct gl_renderbuffer
*stencilRb
= fb
->Attachment
[BUFFER_STENCIL
].Renderbuffer
;
468 GLubyte
*depthMap
, *stencilMap
, *stencilVals
;
469 int depthStride
, stencilStride
, i
, j
;
471 if (_mesa_get_format_datatype(depthRb
->Format
) != GL_UNSIGNED_NORMALIZED
)
474 ctx
->Driver
.MapRenderbuffer(ctx
, depthRb
, x
, y
, width
, height
,
475 GL_MAP_READ_BIT
, &depthMap
, &depthStride
);
477 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glReadPixels");
478 return GL_TRUE
; /* don't bother trying the slow path */
481 ctx
->Driver
.MapRenderbuffer(ctx
, stencilRb
, x
, y
, width
, height
,
482 GL_MAP_READ_BIT
, &stencilMap
, &stencilStride
);
484 ctx
->Driver
.UnmapRenderbuffer(ctx
, depthRb
);
485 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glReadPixels");
486 return GL_TRUE
; /* don't bother trying the slow path */
489 stencilVals
= (GLubyte
*) malloc(width
* sizeof(GLubyte
));
492 for (j
= 0; j
< height
; j
++) {
493 _mesa_unpack_uint_z_row(depthRb
->Format
, width
, depthMap
, dst
);
494 _mesa_unpack_ubyte_stencil_row(stencilRb
->Format
, width
,
495 stencilMap
, stencilVals
);
497 for (i
= 0; i
< width
; i
++) {
498 dst
[i
] = (dst
[i
] & 0xffffff00) | stencilVals
[i
];
501 depthMap
+= depthStride
;
502 stencilMap
+= stencilStride
;
503 dst
+= dstStride
/ 4;
507 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glReadPixels");
512 ctx
->Driver
.UnmapRenderbuffer(ctx
, depthRb
);
513 ctx
->Driver
.UnmapRenderbuffer(ctx
, stencilRb
);
519 slow_read_depth_stencil_pixels_separate(struct gl_context
*ctx
,
521 GLsizei width
, GLsizei height
,
523 const struct gl_pixelstore_attrib
*packing
,
524 GLubyte
*dst
, int dstStride
)
526 struct gl_framebuffer
*fb
= ctx
->ReadBuffer
;
527 struct gl_renderbuffer
*depthRb
= fb
->Attachment
[BUFFER_DEPTH
].Renderbuffer
;
528 struct gl_renderbuffer
*stencilRb
= fb
->Attachment
[BUFFER_STENCIL
].Renderbuffer
;
529 GLubyte
*depthMap
, *stencilMap
;
530 int depthStride
, stencilStride
, j
;
531 GLubyte
*stencilVals
;
535 /* The depth and stencil buffers might be separate, or a single buffer.
536 * If one buffer, only map it once.
538 ctx
->Driver
.MapRenderbuffer(ctx
, depthRb
, x
, y
, width
, height
,
539 GL_MAP_READ_BIT
, &depthMap
, &depthStride
);
541 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glReadPixels");
545 if (stencilRb
!= depthRb
) {
546 ctx
->Driver
.MapRenderbuffer(ctx
, stencilRb
, x
, y
, width
, height
,
547 GL_MAP_READ_BIT
, &stencilMap
,
550 ctx
->Driver
.UnmapRenderbuffer(ctx
, depthRb
);
551 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glReadPixels");
556 stencilMap
= depthMap
;
557 stencilStride
= depthStride
;
560 stencilVals
= (GLubyte
*) malloc(width
* sizeof(GLubyte
));
561 depthVals
= (GLfloat
*) malloc(width
* sizeof(GLfloat
));
563 if (stencilVals
&& depthVals
) {
564 for (j
= 0; j
< height
; j
++) {
565 _mesa_unpack_float_z_row(depthRb
->Format
, width
, depthMap
, depthVals
);
566 _mesa_unpack_ubyte_stencil_row(stencilRb
->Format
, width
,
567 stencilMap
, stencilVals
);
569 _mesa_pack_depth_stencil_span(ctx
, width
, type
, (GLuint
*)dst
,
570 depthVals
, stencilVals
, packing
);
572 depthMap
+= depthStride
;
573 stencilMap
+= stencilStride
;
578 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glReadPixels");
584 ctx
->Driver
.UnmapRenderbuffer(ctx
, depthRb
);
585 if (stencilRb
!= depthRb
) {
586 ctx
->Driver
.UnmapRenderbuffer(ctx
, stencilRb
);
592 * Read combined depth/stencil values.
593 * We'll have already done error checking to be sure the expected
594 * depth and stencil buffers really exist.
597 read_depth_stencil_pixels(struct gl_context
*ctx
,
599 GLsizei width
, GLsizei height
,
600 GLenum type
, GLvoid
*pixels
,
601 const struct gl_pixelstore_attrib
*packing
)
603 const GLboolean scaleOrBias
604 = ctx
->Pixel
.DepthScale
!= 1.0 || ctx
->Pixel
.DepthBias
!= 0.0;
605 const GLboolean stencilTransfer
= ctx
->Pixel
.IndexShift
606 || ctx
->Pixel
.IndexOffset
|| ctx
->Pixel
.MapStencilFlag
;
610 dst
= (GLubyte
*) _mesa_image_address2d(packing
, pixels
,
612 GL_DEPTH_STENCIL_EXT
,
614 dstStride
= _mesa_image_row_stride(packing
, width
,
615 GL_DEPTH_STENCIL_EXT
, type
);
617 /* Fast 24/8 reads. */
618 if (type
== GL_UNSIGNED_INT_24_8
&&
619 !scaleOrBias
&& !stencilTransfer
&& !packing
->SwapBytes
) {
620 if (fast_read_depth_stencil_pixels(ctx
, x
, y
, width
, height
,
624 if (fast_read_depth_stencil_pixels_separate(ctx
, x
, y
, width
, height
,
625 (uint32_t *)dst
, dstStride
))
629 slow_read_depth_stencil_pixels_separate(ctx
, x
, y
, width
, height
,
637 * Software fallback routine for ctx->Driver.ReadPixels().
638 * By time we get here, all error checking will have been done.
641 _mesa_readpixels(struct gl_context
*ctx
,
642 GLint x
, GLint y
, GLsizei width
, GLsizei height
,
643 GLenum format
, GLenum type
,
644 const struct gl_pixelstore_attrib
*packing
,
647 struct gl_pixelstore_attrib clippedPacking
= *packing
;
650 _mesa_update_state(ctx
);
652 /* Do all needed clipping here, so that we can forget about it later */
653 if (_mesa_clip_readpixels(ctx
, &x
, &y
, &width
, &height
, &clippedPacking
)) {
655 pixels
= _mesa_map_pbo_dest(ctx
, &clippedPacking
, pixels
);
659 case GL_STENCIL_INDEX
:
660 read_stencil_pixels(ctx
, x
, y
, width
, height
, type
, pixels
,
663 case GL_DEPTH_COMPONENT
:
664 read_depth_pixels(ctx
, x
, y
, width
, height
, type
, pixels
,
667 case GL_DEPTH_STENCIL_EXT
:
668 read_depth_stencil_pixels(ctx
, x
, y
, width
, height
, type
, pixels
,
672 /* all other formats should be color formats */
673 read_rgba_pixels(ctx
, x
, y
, width
, height
, format
, type
, pixels
,
677 _mesa_unmap_pbo_dest(ctx
, &clippedPacking
);
684 _mesa_ReadnPixelsARB( GLint x
, GLint y
, GLsizei width
, GLsizei height
,
685 GLenum format
, GLenum type
, GLsizei bufSize
,
690 GET_CURRENT_CONTEXT(ctx
);
691 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
693 FLUSH_CURRENT(ctx
, 0);
695 if (MESA_VERBOSE
& VERBOSE_API
)
696 _mesa_debug(ctx
, "glReadPixels(%d, %d, %s, %s, %p)\n",
698 _mesa_lookup_enum_by_nr(format
),
699 _mesa_lookup_enum_by_nr(type
),
702 if (width
< 0 || height
< 0) {
703 _mesa_error( ctx
, GL_INVALID_VALUE
,
704 "glReadPixels(width=%d height=%d)", width
, height
);
708 /* OpenGL ES 1.x and OpenGL ES 2.0 impose additional restrictions on the
709 * combinations of format and type that can be used.
711 * Technically, only two combinations are actually allowed:
712 * GL_RGBA/GL_UNSIGNED_BYTE, and some implementation-specific internal
713 * preferred combination. This code doesn't know what that preferred
714 * combination is, and Mesa can handle anything valid. Just work instead.
716 if (_mesa_is_gles(ctx
) && ctx
->Version
< 30) {
717 err
= _mesa_es_error_check_format_and_type(format
, type
, 2);
718 if (err
== GL_NO_ERROR
) {
719 if (type
== GL_FLOAT
|| type
== GL_HALF_FLOAT_OES
) {
720 err
= GL_INVALID_OPERATION
;
721 } else if (format
== GL_DEPTH_COMPONENT
722 || format
== GL_DEPTH_STENCIL
) {
723 err
= GL_INVALID_ENUM
;
727 if (err
!= GL_NO_ERROR
) {
728 _mesa_error(ctx
, err
, "glReadPixels(invalid format %s and/or type %s)",
729 _mesa_lookup_enum_by_nr(format
),
730 _mesa_lookup_enum_by_nr(type
));
736 _mesa_update_state(ctx
);
738 err
= _mesa_error_check_format_and_type(ctx
, format
, type
);
739 if (err
!= GL_NO_ERROR
) {
740 _mesa_error(ctx
, err
, "glReadPixels(invalid format %s and/or type %s)",
741 _mesa_lookup_enum_by_nr(format
),
742 _mesa_lookup_enum_by_nr(type
));
746 if (ctx
->ReadBuffer
->_Status
!= GL_FRAMEBUFFER_COMPLETE_EXT
) {
747 _mesa_error(ctx
, GL_INVALID_FRAMEBUFFER_OPERATION_EXT
,
748 "glReadPixels(incomplete framebuffer)" );
752 /* Check that the destination format and source buffer are both
753 * integer-valued or both non-integer-valued.
755 if (ctx
->Extensions
.EXT_texture_integer
&& _mesa_is_color_format(format
)) {
756 const struct gl_renderbuffer
*rb
= ctx
->ReadBuffer
->_ColorReadBuffer
;
757 const GLboolean srcInteger
= _mesa_is_format_integer_color(rb
->Format
);
758 const GLboolean dstInteger
= _mesa_is_enum_format_integer(format
);
759 if (dstInteger
!= srcInteger
) {
760 _mesa_error(ctx
, GL_INVALID_OPERATION
,
761 "glReadPixels(integer / non-integer format mismatch");
766 if (_mesa_is_user_fbo(ctx
->ReadBuffer
) &&
767 ctx
->ReadBuffer
->Visual
.samples
> 0) {
768 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glReadPixels(multisample FBO)");
772 if (!_mesa_source_buffer_exists(ctx
, format
)) {
773 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glReadPixels(no readbuffer)");
777 if (width
== 0 || height
== 0)
778 return; /* nothing to do */
780 if (!_mesa_validate_pbo_access(2, &ctx
->Pack
, width
, height
, 1,
781 format
, type
, bufSize
, pixels
)) {
782 if (_mesa_is_bufferobj(ctx
->Pack
.BufferObj
)) {
783 _mesa_error(ctx
, GL_INVALID_OPERATION
,
784 "glReadPixels(out of bounds PBO access)");
786 _mesa_error(ctx
, GL_INVALID_OPERATION
,
787 "glReadnPixelsARB(out of bounds access:"
788 " bufSize (%d) is too small)", bufSize
);
793 if (_mesa_is_bufferobj(ctx
->Pack
.BufferObj
) &&
794 _mesa_bufferobj_mapped(ctx
->Pack
.BufferObj
)) {
795 /* buffer is mapped - that's an error */
796 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glReadPixels(PBO is mapped)");
800 ctx
->Driver
.ReadPixels(ctx
, x
, y
, width
, height
,
801 format
, type
, &ctx
->Pack
, pixels
);
805 _mesa_ReadPixels( GLint x
, GLint y
, GLsizei width
, GLsizei height
,
806 GLenum format
, GLenum type
, GLvoid
*pixels
)
808 _mesa_ReadnPixelsARB(x
, y
, width
, height
, format
, type
, INT_MAX
, pixels
);