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"
42 * Tries to implement glReadPixels() of GL_DEPTH_COMPONENT using memcpy of the
46 fast_read_depth_pixels( struct gl_context
*ctx
,
48 GLsizei width
, GLsizei height
,
49 GLenum type
, GLvoid
*pixels
,
50 const struct gl_pixelstore_attrib
*packing
)
52 struct gl_framebuffer
*fb
= ctx
->ReadBuffer
;
53 struct gl_renderbuffer
*rb
= fb
->Attachment
[BUFFER_DEPTH
].Renderbuffer
;
55 int stride
, dstStride
, j
;
57 if (ctx
->Pixel
.DepthScale
!= 1.0 || ctx
->Pixel
.DepthBias
!= 0.0)
60 if (packing
->SwapBytes
)
63 if (_mesa_get_format_datatype(rb
->Format
) != GL_UNSIGNED_INT
)
66 if (!((type
== GL_UNSIGNED_SHORT
&& rb
->Format
== MESA_FORMAT_Z16
) ||
67 type
== GL_UNSIGNED_INT
))
70 ctx
->Driver
.MapRenderbuffer(ctx
, rb
, x
, y
, width
, height
, GL_MAP_READ_BIT
,
73 dstStride
= _mesa_image_row_stride(packing
, width
, GL_DEPTH_COMPONENT
, type
);
74 dst
= (GLubyte
*) _mesa_image_address2d(packing
, pixels
, width
, height
,
75 GL_DEPTH_COMPONENT
, type
, 0, 0);
77 for (j
= 0; j
< height
; j
++) {
78 if (type
== GL_UNSIGNED_INT
) {
79 _mesa_unpack_uint_z_row(rb
->Format
, width
, map
, (GLuint
*)dst
);
81 ASSERT(type
== GL_UNSIGNED_SHORT
&& rb
->Format
== MESA_FORMAT_Z16
);
82 memcpy(dst
, map
, width
* 2);
88 ctx
->Driver
.UnmapRenderbuffer(ctx
, rb
);
94 * Read pixels for format=GL_DEPTH_COMPONENT.
97 read_depth_pixels( struct gl_context
*ctx
,
99 GLsizei width
, GLsizei height
,
100 GLenum type
, GLvoid
*pixels
,
101 const struct gl_pixelstore_attrib
*packing
)
103 struct gl_framebuffer
*fb
= ctx
->ReadBuffer
;
104 struct gl_renderbuffer
*rb
= fb
->Attachment
[BUFFER_DEPTH
].Renderbuffer
;
107 int dstStride
, stride
;
112 /* clipping should have been done already */
115 ASSERT(x
+ width
<= (GLint
) rb
->Width
);
116 ASSERT(y
+ height
<= (GLint
) rb
->Height
);
117 /* width should never be > MAX_WIDTH since we did clipping earlier */
118 ASSERT(width
<= MAX_WIDTH
);
120 if (fast_read_depth_pixels(ctx
, x
, y
, width
, height
, type
, pixels
, packing
))
123 dstStride
= _mesa_image_row_stride(packing
, width
, GL_DEPTH_COMPONENT
, type
);
124 dst
= (GLubyte
*) _mesa_image_address2d(packing
, pixels
, width
, height
,
125 GL_DEPTH_COMPONENT
, type
, 0, 0);
127 ctx
->Driver
.MapRenderbuffer(ctx
, rb
, x
, y
, width
, height
, GL_MAP_READ_BIT
,
130 /* General case (slower) */
131 for (j
= 0; j
< height
; j
++, y
++) {
132 GLfloat depthValues
[MAX_WIDTH
];
133 _mesa_unpack_float_z_row(rb
->Format
, width
, map
, depthValues
);
134 _mesa_pack_depth_span(ctx
, width
, dst
, type
, depthValues
, packing
);
140 ctx
->Driver
.UnmapRenderbuffer(ctx
, rb
);
145 * Read pixels for format=GL_STENCIL_INDEX.
148 read_stencil_pixels( struct gl_context
*ctx
,
150 GLsizei width
, GLsizei height
,
151 GLenum type
, GLvoid
*pixels
,
152 const struct gl_pixelstore_attrib
*packing
)
154 struct gl_framebuffer
*fb
= ctx
->ReadBuffer
;
155 struct gl_renderbuffer
*rb
= fb
->Attachment
[BUFFER_STENCIL
].Renderbuffer
;
163 /* width should never be > MAX_WIDTH since we did clipping earlier */
164 ASSERT(width
<= MAX_WIDTH
);
166 ctx
->Driver
.MapRenderbuffer(ctx
, rb
, x
, y
, width
, height
, GL_MAP_READ_BIT
,
169 /* process image row by row */
170 for (j
= 0; j
< height
; j
++) {
172 GLubyte stencil
[MAX_WIDTH
];
174 _mesa_unpack_ubyte_stencil_row(rb
->Format
, width
, map
, stencil
);
175 dest
= _mesa_image_address2d(packing
, pixels
, width
, height
,
176 GL_STENCIL_INDEX
, type
, j
, 0);
178 _mesa_pack_stencil_span(ctx
, width
, type
, dest
, stencil
, packing
);
183 ctx
->Driver
.UnmapRenderbuffer(ctx
, rb
);
187 fast_read_rgba_pixels_memcpy( struct gl_context
*ctx
,
189 GLsizei width
, GLsizei height
,
190 GLenum format
, GLenum type
,
192 const struct gl_pixelstore_attrib
*packing
,
193 GLbitfield transferOps
)
195 struct gl_renderbuffer
*rb
= ctx
->ReadBuffer
->_ColorReadBuffer
;
197 int dstStride
, stride
, j
, texelBytes
;
199 if (!_mesa_format_matches_format_and_type(rb
->Format
, format
, type
))
202 /* check for things we can't handle here */
203 if (packing
->SwapBytes
||
208 dstStride
= _mesa_image_row_stride(packing
, width
, format
, type
);
209 dst
= (GLubyte
*) _mesa_image_address2d(packing
, pixels
, width
, height
,
212 ctx
->Driver
.MapRenderbuffer(ctx
, rb
, x
, y
, width
, height
, GL_MAP_READ_BIT
,
215 texelBytes
= _mesa_get_format_bytes(rb
->Format
);
216 for (j
= 0; j
< height
; j
++) {
217 memcpy(dst
, map
, width
* texelBytes
);
222 ctx
->Driver
.UnmapRenderbuffer(ctx
, rb
);
228 slow_read_rgba_pixels( struct gl_context
*ctx
,
230 GLsizei width
, GLsizei height
,
231 GLenum format
, GLenum type
,
233 const struct gl_pixelstore_attrib
*packing
,
234 GLbitfield transferOps
)
236 struct gl_renderbuffer
*rb
= ctx
->ReadBuffer
->_ColorReadBuffer
;
237 const gl_format rbFormat
= _mesa_get_srgb_format_linear(rb
->Format
);
239 float f
[MAX_WIDTH
][4];
240 unsigned int i
[MAX_WIDTH
][4];
243 int dstStride
, stride
, j
;
245 dstStride
= _mesa_image_row_stride(packing
, width
, format
, type
);
246 dst
= (GLubyte
*) _mesa_image_address2d(packing
, pixels
, width
, height
,
249 ctx
->Driver
.MapRenderbuffer(ctx
, rb
, x
, y
, width
, height
, GL_MAP_READ_BIT
,
252 for (j
= 0; j
< height
; j
++) {
253 if (_mesa_is_integer_format(format
)) {
254 _mesa_unpack_int_rgba_row(rbFormat
, width
, map
, rgba
.i
);
255 _mesa_pack_rgba_span_int(ctx
, width
, rgba
.i
, format
, type
, dst
);
257 _mesa_unpack_rgba_row(rbFormat
, width
, map
, rgba
.f
);
258 _mesa_pack_rgba_span_float(ctx
, width
, rgba
.f
, format
, type
, dst
,
259 packing
, transferOps
);
265 ctx
->Driver
.UnmapRenderbuffer(ctx
, rb
);
271 * Read R, G, B, A, RGB, L, or LA pixels.
274 read_rgba_pixels( struct gl_context
*ctx
,
276 GLsizei width
, GLsizei height
,
277 GLenum format
, GLenum type
, GLvoid
*pixels
,
278 const struct gl_pixelstore_attrib
*packing
)
280 GLbitfield transferOps
= ctx
->_ImageTransferState
;
281 struct gl_framebuffer
*fb
= ctx
->ReadBuffer
;
282 struct gl_renderbuffer
*rb
= fb
->_ColorReadBuffer
;
287 if ((ctx
->Color
._ClampReadColor
== GL_TRUE
|| type
!= GL_FLOAT
) &&
288 !_mesa_is_integer_format(format
)) {
289 transferOps
|= IMAGE_CLAMP_BIT
;
293 /* Try the optimized paths first. */
294 if (fast_read_rgba_pixels_memcpy(ctx
, x
, y
, width
, height
,
295 format
, type
, pixels
, packing
,
301 slow_read_rgba_pixels(ctx
, x
, y
, width
, height
,
302 format
, type
, pixels
, packing
, transferOps
);
306 * For a packed depth/stencil buffer being read as depth/stencil, just memcpy the
307 * data (possibly swapping 8/24 vs 24/8 as we go).
310 fast_read_depth_stencil_pixels(struct gl_context
*ctx
,
312 GLsizei width
, GLsizei height
,
313 GLubyte
*dst
, int dstStride
)
315 struct gl_framebuffer
*fb
= ctx
->ReadBuffer
;
316 struct gl_renderbuffer
*rb
= fb
->Attachment
[BUFFER_DEPTH
].Renderbuffer
;
317 struct gl_renderbuffer
*stencilRb
= fb
->Attachment
[BUFFER_STENCIL
].Renderbuffer
;
324 if (rb
->Format
!= MESA_FORMAT_Z24_S8
&&
325 rb
->Format
!= MESA_FORMAT_S8_Z24
)
328 ctx
->Driver
.MapRenderbuffer(ctx
, rb
, x
, y
, width
, height
, GL_MAP_READ_BIT
,
331 for (i
= 0; i
< height
; i
++) {
332 _mesa_unpack_uint_24_8_depth_stencil_row(rb
->Format
, width
,
338 ctx
->Driver
.UnmapRenderbuffer(ctx
, rb
);
345 * For non-float-depth and stencil buffers being read as 24/8 depth/stencil,
346 * copy the integer data directly instead of converting depth to float and
350 fast_read_depth_stencil_pixels_separate(struct gl_context
*ctx
,
352 GLsizei width
, GLsizei height
,
353 uint32_t *dst
, int dstStride
)
355 struct gl_framebuffer
*fb
= ctx
->ReadBuffer
;
356 struct gl_renderbuffer
*depthRb
= fb
->Attachment
[BUFFER_DEPTH
].Renderbuffer
;
357 struct gl_renderbuffer
*stencilRb
= fb
->Attachment
[BUFFER_STENCIL
].Renderbuffer
;
358 GLubyte
*depthMap
, *stencilMap
;
359 int depthStride
, stencilStride
, i
, j
;
361 if (_mesa_get_format_datatype(depthRb
->Format
) != GL_UNSIGNED_INT
)
364 ctx
->Driver
.MapRenderbuffer(ctx
, depthRb
, x
, y
, width
, height
,
365 GL_MAP_READ_BIT
, &depthMap
, &depthStride
);
366 ctx
->Driver
.MapRenderbuffer(ctx
, stencilRb
, x
, y
, width
, height
,
367 GL_MAP_READ_BIT
, &stencilMap
, &stencilStride
);
369 for (j
= 0; j
< height
; j
++) {
370 GLubyte stencilVals
[MAX_WIDTH
];
372 _mesa_unpack_uint_z_row(depthRb
->Format
, width
, depthMap
, dst
);
373 _mesa_unpack_ubyte_stencil_row(stencilRb
->Format
, width
,
374 stencilMap
, stencilVals
);
376 for (i
= 0; i
< width
; i
++) {
377 dst
[i
] = (dst
[i
] & 0xffffff00) | stencilVals
[i
];
380 depthMap
+= depthStride
;
381 stencilMap
+= stencilStride
;
382 dst
+= dstStride
/ 4;
385 ctx
->Driver
.UnmapRenderbuffer(ctx
, depthRb
);
386 ctx
->Driver
.UnmapRenderbuffer(ctx
, stencilRb
);
392 slow_read_depth_stencil_pixels_separate(struct gl_context
*ctx
,
394 GLsizei width
, GLsizei height
,
396 const struct gl_pixelstore_attrib
*packing
,
397 GLubyte
*dst
, int dstStride
)
399 struct gl_framebuffer
*fb
= ctx
->ReadBuffer
;
400 struct gl_renderbuffer
*depthRb
= fb
->Attachment
[BUFFER_DEPTH
].Renderbuffer
;
401 struct gl_renderbuffer
*stencilRb
= fb
->Attachment
[BUFFER_STENCIL
].Renderbuffer
;
402 GLubyte
*depthMap
, *stencilMap
;
403 int depthStride
, stencilStride
, j
;
405 /* The depth and stencil buffers might be separate, or a single buffer.
406 * If one buffer, only map it once.
408 ctx
->Driver
.MapRenderbuffer(ctx
, depthRb
, x
, y
, width
, height
,
409 GL_MAP_READ_BIT
, &depthMap
, &depthStride
);
410 if (stencilRb
!= depthRb
) {
411 ctx
->Driver
.MapRenderbuffer(ctx
, stencilRb
, x
, y
, width
, height
,
412 GL_MAP_READ_BIT
, &stencilMap
,
416 for (j
= 0; j
< height
; j
++) {
417 GLubyte stencilVals
[MAX_WIDTH
];
418 GLfloat depthVals
[MAX_WIDTH
];
420 _mesa_unpack_float_z_row(depthRb
->Format
, width
, depthMap
, depthVals
);
421 _mesa_unpack_ubyte_stencil_row(stencilRb
->Format
, width
,
422 stencilMap
, stencilVals
);
424 _mesa_pack_depth_stencil_span(ctx
, width
, type
, (GLuint
*)dst
,
425 depthVals
, stencilVals
, packing
);
427 depthMap
+= depthStride
;
428 stencilMap
+= stencilStride
;
432 ctx
->Driver
.UnmapRenderbuffer(ctx
, depthRb
);
433 if (stencilRb
!= depthRb
) {
434 ctx
->Driver
.UnmapRenderbuffer(ctx
, stencilRb
);
440 * Read combined depth/stencil values.
441 * We'll have already done error checking to be sure the expected
442 * depth and stencil buffers really exist.
445 read_depth_stencil_pixels(struct gl_context
*ctx
,
447 GLsizei width
, GLsizei height
,
448 GLenum type
, GLvoid
*pixels
,
449 const struct gl_pixelstore_attrib
*packing
)
451 const GLboolean scaleOrBias
452 = ctx
->Pixel
.DepthScale
!= 1.0 || ctx
->Pixel
.DepthBias
!= 0.0;
453 const GLboolean stencilTransfer
= ctx
->Pixel
.IndexShift
454 || ctx
->Pixel
.IndexOffset
|| ctx
->Pixel
.MapStencilFlag
;
458 dst
= (GLubyte
*) _mesa_image_address2d(packing
, pixels
,
460 GL_DEPTH_STENCIL_EXT
,
462 dstStride
= _mesa_image_row_stride(packing
, width
,
463 GL_DEPTH_STENCIL_EXT
, type
);
465 /* Fast 24/8 reads. */
466 if (type
== GL_UNSIGNED_INT_24_8
&&
467 !scaleOrBias
&& !stencilTransfer
&& !packing
->SwapBytes
) {
468 if (fast_read_depth_stencil_pixels(ctx
, x
, y
, width
, height
,
472 if (fast_read_depth_stencil_pixels_separate(ctx
, x
, y
, width
, height
,
473 (uint32_t *)dst
, dstStride
))
477 slow_read_depth_stencil_pixels_separate(ctx
, x
, y
, width
, height
,
485 * Software fallback routine for ctx->Driver.ReadPixels().
486 * By time we get here, all error checking will have been done.
489 _mesa_readpixels(struct gl_context
*ctx
,
490 GLint x
, GLint y
, GLsizei width
, GLsizei height
,
491 GLenum format
, GLenum type
,
492 const struct gl_pixelstore_attrib
*packing
,
495 struct gl_pixelstore_attrib clippedPacking
= *packing
;
498 _mesa_update_state(ctx
);
500 /* Do all needed clipping here, so that we can forget about it later */
501 if (_mesa_clip_readpixels(ctx
, &x
, &y
, &width
, &height
, &clippedPacking
)) {
503 pixels
= _mesa_map_pbo_dest(ctx
, &clippedPacking
, pixels
);
507 case GL_STENCIL_INDEX
:
508 read_stencil_pixels(ctx
, x
, y
, width
, height
, type
, pixels
,
511 case GL_DEPTH_COMPONENT
:
512 read_depth_pixels(ctx
, x
, y
, width
, height
, type
, pixels
,
515 case GL_DEPTH_STENCIL_EXT
:
516 read_depth_stencil_pixels(ctx
, x
, y
, width
, height
, type
, pixels
,
520 /* all other formats should be color formats */
521 read_rgba_pixels(ctx
, x
, y
, width
, height
, format
, type
, pixels
,
525 _mesa_unmap_pbo_dest(ctx
, &clippedPacking
);
532 * Do error checking of the format/type parameters to glReadPixels and
534 * \param drawing if GL_TRUE do checking for DrawPixels, else do checking
536 * \return GL_TRUE if error detected, GL_FALSE if no errors
539 _mesa_error_check_format_type(struct gl_context
*ctx
, GLenum format
,
540 GLenum type
, GLboolean drawing
)
542 const char *readDraw
= drawing
? "Draw" : "Read";
543 const GLboolean reading
= !drawing
;
545 /* state validation should have already been done */
546 ASSERT(ctx
->NewState
== 0x0);
548 if (ctx
->Extensions
.EXT_packed_depth_stencil
549 && type
== GL_UNSIGNED_INT_24_8_EXT
550 && format
!= GL_DEPTH_STENCIL_EXT
) {
551 _mesa_error(ctx
, GL_INVALID_OPERATION
,
552 "gl%sPixels(format is not GL_DEPTH_STENCIL_EXT)", readDraw
);
556 if (ctx
->Extensions
.ARB_depth_buffer_float
557 && type
== GL_FLOAT_32_UNSIGNED_INT_24_8_REV
558 && format
!= GL_DEPTH_STENCIL_EXT
) {
559 _mesa_error(ctx
, GL_INVALID_OPERATION
,
560 "gl%sPixels(format is not GL_DEPTH_STENCIL_EXT)", readDraw
);
564 /* basic combinations test */
565 if (!_mesa_is_legal_format_and_type(ctx
, format
, type
)) {
566 _mesa_error(ctx
, GL_INVALID_ENUM
,
567 "gl%sPixels(format or type)", readDraw
);
571 /* additional checks */
579 case GL_LUMINANCE_ALPHA
:
585 case GL_RED_INTEGER_EXT
:
586 case GL_GREEN_INTEGER_EXT
:
587 case GL_BLUE_INTEGER_EXT
:
588 case GL_ALPHA_INTEGER_EXT
:
589 case GL_RGB_INTEGER_EXT
:
590 case GL_RGBA_INTEGER_EXT
:
591 case GL_BGR_INTEGER_EXT
:
592 case GL_BGRA_INTEGER_EXT
:
593 case GL_LUMINANCE_INTEGER_EXT
:
594 case GL_LUMINANCE_ALPHA_INTEGER_EXT
:
597 if (!_mesa_source_buffer_exists(ctx
, GL_COLOR
)) {
598 _mesa_error(ctx
, GL_INVALID_OPERATION
,
599 "glReadPixels(no color buffer)");
606 if (ctx
->PixelMaps
.ItoR
.Size
== 0 ||
607 ctx
->PixelMaps
.ItoG
.Size
== 0 ||
608 ctx
->PixelMaps
.ItoB
.Size
== 0) {
609 _mesa_error(ctx
, GL_INVALID_OPERATION
,
610 "glDrawPixels(drawing color index pixels into RGB buffer)");
616 if (!_mesa_source_buffer_exists(ctx
, GL_COLOR
)) {
617 _mesa_error(ctx
, GL_INVALID_OPERATION
,
618 "glReadPixels(no color buffer)");
621 /* We no longer support CI-mode color buffers so trying to read
622 * GL_COLOR_INDEX pixels is always an error.
624 _mesa_error(ctx
, GL_INVALID_OPERATION
,
625 "glReadPixels(color buffer is RGB)");
629 case GL_STENCIL_INDEX
:
630 if ((drawing
&& !_mesa_dest_buffer_exists(ctx
, format
)) ||
631 (reading
&& !_mesa_source_buffer_exists(ctx
, format
))) {
632 _mesa_error(ctx
, GL_INVALID_OPERATION
,
633 "gl%sPixels(no stencil buffer)", readDraw
);
637 case GL_DEPTH_COMPONENT
:
638 if ((drawing
&& !_mesa_dest_buffer_exists(ctx
, format
))) {
639 _mesa_error(ctx
, GL_INVALID_OPERATION
,
640 "gl%sPixels(no depth buffer)", readDraw
);
644 case GL_DEPTH_STENCIL_EXT
:
645 /* Check validity of the type first. */
647 case GL_UNSIGNED_INT_24_8_EXT
:
648 if (!ctx
->Extensions
.EXT_packed_depth_stencil
) {
649 _mesa_error(ctx
, GL_INVALID_ENUM
, "gl%sPixels(type)", readDraw
);
653 case GL_FLOAT_32_UNSIGNED_INT_24_8_REV
:
654 if (!ctx
->Extensions
.ARB_depth_buffer_float
) {
655 _mesa_error(ctx
, GL_INVALID_ENUM
, "gl%sPixels(type)", readDraw
);
660 _mesa_error(ctx
, GL_INVALID_ENUM
, "gl%sPixels(type)", readDraw
);
663 if ((drawing
&& !_mesa_dest_buffer_exists(ctx
, format
)) ||
664 (reading
&& !_mesa_source_buffer_exists(ctx
, format
))) {
665 _mesa_error(ctx
, GL_INVALID_OPERATION
,
666 "gl%sPixels(no depth or stencil buffer)", readDraw
);
671 /* this should have been caught in _mesa_is_legal_format_type() */
672 _mesa_problem(ctx
, "unexpected format in _mesa_%sPixels", readDraw
);
683 _mesa_ReadnPixelsARB( GLint x
, GLint y
, GLsizei width
, GLsizei height
,
684 GLenum format
, GLenum type
, GLsizei bufSize
,
687 GET_CURRENT_CONTEXT(ctx
);
688 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
690 FLUSH_CURRENT(ctx
, 0);
692 if (MESA_VERBOSE
& VERBOSE_API
)
693 _mesa_debug(ctx
, "glReadPixels(%d, %d, %s, %s, %p)\n",
695 _mesa_lookup_enum_by_nr(format
),
696 _mesa_lookup_enum_by_nr(type
),
699 if (width
< 0 || height
< 0) {
700 _mesa_error( ctx
, GL_INVALID_VALUE
,
701 "glReadPixels(width=%d height=%d)", width
, height
);
706 _mesa_update_state(ctx
);
708 if (_mesa_error_check_format_type(ctx
, format
, type
, GL_FALSE
)) {
713 /* Check that the destination format and source buffer are both
714 * integer-valued or both non-integer-valued.
716 if (ctx
->Extensions
.EXT_texture_integer
&& _mesa_is_color_format(format
)) {
717 const struct gl_renderbuffer
*rb
= ctx
->ReadBuffer
->_ColorReadBuffer
;
718 const GLboolean srcInteger
= _mesa_is_format_integer_color(rb
->Format
);
719 const GLboolean dstInteger
= _mesa_is_integer_format(format
);
720 if (dstInteger
!= srcInteger
) {
721 _mesa_error(ctx
, GL_INVALID_OPERATION
,
722 "glReadPixels(integer / non-integer format mismatch");
727 if (ctx
->ReadBuffer
->_Status
!= GL_FRAMEBUFFER_COMPLETE_EXT
) {
728 _mesa_error(ctx
, GL_INVALID_FRAMEBUFFER_OPERATION_EXT
,
729 "glReadPixels(incomplete framebuffer)" );
733 if (!_mesa_source_buffer_exists(ctx
, format
)) {
734 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glReadPixels(no readbuffer)");
738 if (width
== 0 || height
== 0)
739 return; /* nothing to do */
741 if (!_mesa_validate_pbo_access(2, &ctx
->Pack
, width
, height
, 1,
742 format
, type
, bufSize
, pixels
)) {
743 if (_mesa_is_bufferobj(ctx
->Pack
.BufferObj
)) {
744 _mesa_error(ctx
, GL_INVALID_OPERATION
,
745 "glReadPixels(out of bounds PBO access)");
747 _mesa_error(ctx
, GL_INVALID_OPERATION
,
748 "glReadnPixelsARB(out of bounds access:"
749 " bufSize (%d) is too small)", bufSize
);
754 if (_mesa_is_bufferobj(ctx
->Pack
.BufferObj
) &&
755 _mesa_bufferobj_mapped(ctx
->Pack
.BufferObj
)) {
756 /* buffer is mapped - that's an error */
757 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glReadPixels(PBO is mapped)");
761 ctx
->Driver
.ReadPixels(ctx
, x
, y
, width
, height
,
762 format
, type
, &ctx
->Pack
, pixels
);
766 _mesa_ReadPixels( GLint x
, GLint y
, GLsizei width
, GLsizei height
,
767 GLenum format
, GLenum type
, GLvoid
*pixels
)
769 _mesa_ReadnPixelsARB(x
, y
, width
, height
, format
, type
, INT_MAX
, pixels
);