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_NORMALIZED
)
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
,
74 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glReadPixels");
75 return GL_TRUE
; /* don't bother trying the slow path */
78 dstStride
= _mesa_image_row_stride(packing
, width
, GL_DEPTH_COMPONENT
, type
);
79 dst
= (GLubyte
*) _mesa_image_address2d(packing
, pixels
, width
, height
,
80 GL_DEPTH_COMPONENT
, type
, 0, 0);
82 for (j
= 0; j
< height
; j
++) {
83 if (type
== GL_UNSIGNED_INT
) {
84 _mesa_unpack_uint_z_row(rb
->Format
, width
, map
, (GLuint
*)dst
);
86 ASSERT(type
== GL_UNSIGNED_SHORT
&& rb
->Format
== MESA_FORMAT_Z16
);
87 memcpy(dst
, map
, width
* 2);
93 ctx
->Driver
.UnmapRenderbuffer(ctx
, rb
);
99 * Read pixels for format=GL_DEPTH_COMPONENT.
102 read_depth_pixels( struct gl_context
*ctx
,
104 GLsizei width
, GLsizei height
,
105 GLenum type
, GLvoid
*pixels
,
106 const struct gl_pixelstore_attrib
*packing
)
108 struct gl_framebuffer
*fb
= ctx
->ReadBuffer
;
109 struct gl_renderbuffer
*rb
= fb
->Attachment
[BUFFER_DEPTH
].Renderbuffer
;
112 int dstStride
, stride
;
117 /* clipping should have been done already */
120 ASSERT(x
+ width
<= (GLint
) rb
->Width
);
121 ASSERT(y
+ height
<= (GLint
) rb
->Height
);
122 /* width should never be > MAX_WIDTH since we did clipping earlier */
123 ASSERT(width
<= MAX_WIDTH
);
125 if (fast_read_depth_pixels(ctx
, x
, y
, width
, height
, type
, pixels
, packing
))
128 dstStride
= _mesa_image_row_stride(packing
, width
, GL_DEPTH_COMPONENT
, type
);
129 dst
= (GLubyte
*) _mesa_image_address2d(packing
, pixels
, width
, height
,
130 GL_DEPTH_COMPONENT
, type
, 0, 0);
132 ctx
->Driver
.MapRenderbuffer(ctx
, rb
, x
, y
, width
, height
, GL_MAP_READ_BIT
,
135 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glReadPixels");
139 /* General case (slower) */
140 for (j
= 0; j
< height
; j
++, y
++) {
141 GLfloat depthValues
[MAX_WIDTH
];
142 _mesa_unpack_float_z_row(rb
->Format
, width
, map
, depthValues
);
143 _mesa_pack_depth_span(ctx
, width
, dst
, type
, depthValues
, packing
);
149 ctx
->Driver
.UnmapRenderbuffer(ctx
, rb
);
154 * Read pixels for format=GL_STENCIL_INDEX.
157 read_stencil_pixels( struct gl_context
*ctx
,
159 GLsizei width
, GLsizei height
,
160 GLenum type
, GLvoid
*pixels
,
161 const struct gl_pixelstore_attrib
*packing
)
163 struct gl_framebuffer
*fb
= ctx
->ReadBuffer
;
164 struct gl_renderbuffer
*rb
= fb
->Attachment
[BUFFER_STENCIL
].Renderbuffer
;
172 /* width should never be > MAX_WIDTH since we did clipping earlier */
173 ASSERT(width
<= MAX_WIDTH
);
175 ctx
->Driver
.MapRenderbuffer(ctx
, rb
, x
, y
, width
, height
, GL_MAP_READ_BIT
,
178 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glReadPixels");
182 /* process image row by row */
183 for (j
= 0; j
< height
; j
++) {
185 GLubyte stencil
[MAX_WIDTH
];
187 _mesa_unpack_ubyte_stencil_row(rb
->Format
, width
, map
, stencil
);
188 dest
= _mesa_image_address2d(packing
, pixels
, width
, height
,
189 GL_STENCIL_INDEX
, type
, j
, 0);
191 _mesa_pack_stencil_span(ctx
, width
, type
, dest
, stencil
, packing
);
196 ctx
->Driver
.UnmapRenderbuffer(ctx
, rb
);
201 * Try to do glReadPixels of RGBA data using a simple memcpy or swizzle.
202 * \return GL_TRUE if successful, GL_FALSE otherwise (use the slow path)
205 fast_read_rgba_pixels_memcpy( struct gl_context
*ctx
,
207 GLsizei width
, GLsizei height
,
208 GLenum format
, GLenum type
,
210 const struct gl_pixelstore_attrib
*packing
,
211 GLbitfield transferOps
)
213 struct gl_renderbuffer
*rb
= ctx
->ReadBuffer
->_ColorReadBuffer
;
215 int dstStride
, stride
, j
, texelBytes
;
216 GLboolean swizzle_rb
= GL_FALSE
, copy_xrgb
= GL_FALSE
;
218 /* XXX we could check for other swizzle/special cases here as needed */
219 if (rb
->Format
== MESA_FORMAT_RGBA8888_REV
&&
221 type
== GL_UNSIGNED_INT_8_8_8_8_REV
) {
222 swizzle_rb
= GL_TRUE
;
224 else if (rb
->Format
== MESA_FORMAT_XRGB8888
&&
226 type
== GL_UNSIGNED_INT_8_8_8_8_REV
) {
229 else if (!_mesa_format_matches_format_and_type(rb
->Format
, format
, type
))
232 /* check for things we can't handle here */
233 if (packing
->SwapBytes
) {
237 /* If the format is unsigned normalized then we can ignore clamping
238 * because the values are already in the range [0,1] so it won't
239 * have any effect anyway.
241 if (_mesa_get_format_datatype(rb
->Format
) == GL_UNSIGNED_NORMALIZED
)
242 transferOps
&= ~IMAGE_CLAMP_BIT
;
247 dstStride
= _mesa_image_row_stride(packing
, width
, format
, type
);
248 dst
= (GLubyte
*) _mesa_image_address2d(packing
, pixels
, width
, height
,
251 ctx
->Driver
.MapRenderbuffer(ctx
, rb
, x
, y
, width
, height
, GL_MAP_READ_BIT
,
254 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glReadPixels");
255 return GL_TRUE
; /* don't bother trying the slow path */
258 texelBytes
= _mesa_get_format_bytes(rb
->Format
);
262 for (j
= 0; j
< height
; j
++) {
264 for (i
= 0; i
< width
; i
++) {
265 GLuint
*dst4
= (GLuint
*) dst
, *map4
= (GLuint
*) map
;
266 GLuint pixel
= map4
[i
];
267 dst4
[i
] = (pixel
& 0xff00ff00)
268 | ((pixel
& 0x00ff0000) >> 16)
269 | ((pixel
& 0x000000ff) << 16);
274 } else if (copy_xrgb
) {
275 /* convert xrgb -> argb */
276 for (j
= 0; j
< height
; j
++) {
277 GLuint
*dst4
= (GLuint
*) dst
, *map4
= (GLuint
*) map
;
279 for (i
= 0; i
< width
; i
++) {
280 dst4
[i
] = map4
[i
] | 0xff000000; /* set A=0xff */
287 for (j
= 0; j
< height
; j
++) {
288 memcpy(dst
, map
, width
* texelBytes
);
294 ctx
->Driver
.UnmapRenderbuffer(ctx
, rb
);
300 slow_read_rgba_pixels( struct gl_context
*ctx
,
302 GLsizei width
, GLsizei height
,
303 GLenum format
, GLenum type
,
305 const struct gl_pixelstore_attrib
*packing
,
306 GLbitfield transferOps
)
308 struct gl_renderbuffer
*rb
= ctx
->ReadBuffer
->_ColorReadBuffer
;
309 const gl_format rbFormat
= _mesa_get_srgb_format_linear(rb
->Format
);
312 int dstStride
, stride
, j
;
314 dstStride
= _mesa_image_row_stride(packing
, width
, format
, type
);
315 dst
= (GLubyte
*) _mesa_image_address2d(packing
, pixels
, width
, height
,
318 ctx
->Driver
.MapRenderbuffer(ctx
, rb
, x
, y
, width
, height
, GL_MAP_READ_BIT
,
321 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glReadPixels");
325 rgba
= malloc(width
* MAX_PIXEL_BYTES
);
329 for (j
= 0; j
< height
; j
++) {
330 if (_mesa_is_integer_format(format
)) {
331 _mesa_unpack_uint_rgba_row(rbFormat
, width
, map
, (GLuint (*)[4]) rgba
);
332 _mesa_rebase_rgba_uint(width
, (GLuint (*)[4]) rgba
,
334 _mesa_pack_rgba_span_int(ctx
, width
, (GLuint (*)[4]) rgba
, format
,
337 _mesa_unpack_rgba_row(rbFormat
, width
, map
, (GLfloat (*)[4]) rgba
);
338 _mesa_rebase_rgba_float(width
, (GLfloat (*)[4]) rgba
,
340 _mesa_pack_rgba_span_float(ctx
, width
, (GLfloat (*)[4]) rgba
, format
,
341 type
, dst
, packing
, transferOps
);
350 ctx
->Driver
.UnmapRenderbuffer(ctx
, rb
);
354 * Read R, G, B, A, RGB, L, or LA pixels.
357 read_rgba_pixels( struct gl_context
*ctx
,
359 GLsizei width
, GLsizei height
,
360 GLenum format
, GLenum type
, GLvoid
*pixels
,
361 const struct gl_pixelstore_attrib
*packing
)
363 GLbitfield transferOps
= ctx
->_ImageTransferState
;
364 struct gl_framebuffer
*fb
= ctx
->ReadBuffer
;
365 struct gl_renderbuffer
*rb
= fb
->_ColorReadBuffer
;
370 if ((ctx
->Color
._ClampReadColor
== GL_TRUE
|| type
!= GL_FLOAT
) &&
371 !_mesa_is_integer_format(format
)) {
372 transferOps
|= IMAGE_CLAMP_BIT
;
375 /* Try the optimized paths first. */
376 if (fast_read_rgba_pixels_memcpy(ctx
, x
, y
, width
, height
,
377 format
, type
, pixels
, packing
,
382 slow_read_rgba_pixels(ctx
, x
, y
, width
, height
,
383 format
, type
, pixels
, packing
, transferOps
);
387 * For a packed depth/stencil buffer being read as depth/stencil, just memcpy the
388 * data (possibly swapping 8/24 vs 24/8 as we go).
391 fast_read_depth_stencil_pixels(struct gl_context
*ctx
,
393 GLsizei width
, GLsizei height
,
394 GLubyte
*dst
, int dstStride
)
396 struct gl_framebuffer
*fb
= ctx
->ReadBuffer
;
397 struct gl_renderbuffer
*rb
= fb
->Attachment
[BUFFER_DEPTH
].Renderbuffer
;
398 struct gl_renderbuffer
*stencilRb
= fb
->Attachment
[BUFFER_STENCIL
].Renderbuffer
;
405 if (rb
->Format
!= MESA_FORMAT_Z24_S8
&&
406 rb
->Format
!= MESA_FORMAT_S8_Z24
)
409 ctx
->Driver
.MapRenderbuffer(ctx
, rb
, x
, y
, width
, height
, GL_MAP_READ_BIT
,
412 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glReadPixels");
413 return GL_TRUE
; /* don't bother trying the slow path */
416 for (i
= 0; i
< height
; i
++) {
417 _mesa_unpack_uint_24_8_depth_stencil_row(rb
->Format
, width
,
423 ctx
->Driver
.UnmapRenderbuffer(ctx
, rb
);
430 * For non-float-depth and stencil buffers being read as 24/8 depth/stencil,
431 * copy the integer data directly instead of converting depth to float and
435 fast_read_depth_stencil_pixels_separate(struct gl_context
*ctx
,
437 GLsizei width
, GLsizei height
,
438 uint32_t *dst
, int dstStride
)
440 struct gl_framebuffer
*fb
= ctx
->ReadBuffer
;
441 struct gl_renderbuffer
*depthRb
= fb
->Attachment
[BUFFER_DEPTH
].Renderbuffer
;
442 struct gl_renderbuffer
*stencilRb
= fb
->Attachment
[BUFFER_STENCIL
].Renderbuffer
;
443 GLubyte
*depthMap
, *stencilMap
;
444 int depthStride
, stencilStride
, i
, j
;
446 if (_mesa_get_format_datatype(depthRb
->Format
) != GL_UNSIGNED_NORMALIZED
)
449 ctx
->Driver
.MapRenderbuffer(ctx
, depthRb
, x
, y
, width
, height
,
450 GL_MAP_READ_BIT
, &depthMap
, &depthStride
);
452 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glReadPixels");
453 return GL_TRUE
; /* don't bother trying the slow path */
456 ctx
->Driver
.MapRenderbuffer(ctx
, stencilRb
, x
, y
, width
, height
,
457 GL_MAP_READ_BIT
, &stencilMap
, &stencilStride
);
459 ctx
->Driver
.UnmapRenderbuffer(ctx
, depthRb
);
460 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glReadPixels");
461 return GL_TRUE
; /* don't bother trying the slow path */
464 for (j
= 0; j
< height
; j
++) {
465 GLubyte stencilVals
[MAX_WIDTH
];
467 _mesa_unpack_uint_z_row(depthRb
->Format
, width
, depthMap
, dst
);
468 _mesa_unpack_ubyte_stencil_row(stencilRb
->Format
, width
,
469 stencilMap
, stencilVals
);
471 for (i
= 0; i
< width
; i
++) {
472 dst
[i
] = (dst
[i
] & 0xffffff00) | stencilVals
[i
];
475 depthMap
+= depthStride
;
476 stencilMap
+= stencilStride
;
477 dst
+= dstStride
/ 4;
480 ctx
->Driver
.UnmapRenderbuffer(ctx
, depthRb
);
481 ctx
->Driver
.UnmapRenderbuffer(ctx
, stencilRb
);
487 slow_read_depth_stencil_pixels_separate(struct gl_context
*ctx
,
489 GLsizei width
, GLsizei height
,
491 const struct gl_pixelstore_attrib
*packing
,
492 GLubyte
*dst
, int dstStride
)
494 struct gl_framebuffer
*fb
= ctx
->ReadBuffer
;
495 struct gl_renderbuffer
*depthRb
= fb
->Attachment
[BUFFER_DEPTH
].Renderbuffer
;
496 struct gl_renderbuffer
*stencilRb
= fb
->Attachment
[BUFFER_STENCIL
].Renderbuffer
;
497 GLubyte
*depthMap
, *stencilMap
;
498 int depthStride
, stencilStride
, j
;
500 /* The depth and stencil buffers might be separate, or a single buffer.
501 * If one buffer, only map it once.
503 ctx
->Driver
.MapRenderbuffer(ctx
, depthRb
, x
, y
, width
, height
,
504 GL_MAP_READ_BIT
, &depthMap
, &depthStride
);
506 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glReadPixels");
510 if (stencilRb
!= depthRb
) {
511 ctx
->Driver
.MapRenderbuffer(ctx
, stencilRb
, x
, y
, width
, height
,
512 GL_MAP_READ_BIT
, &stencilMap
,
515 ctx
->Driver
.UnmapRenderbuffer(ctx
, depthRb
);
516 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glReadPixels");
521 stencilMap
= depthMap
;
522 stencilStride
= depthStride
;
525 for (j
= 0; j
< height
; j
++) {
526 GLubyte stencilVals
[MAX_WIDTH
];
527 GLfloat depthVals
[MAX_WIDTH
];
529 _mesa_unpack_float_z_row(depthRb
->Format
, width
, depthMap
, depthVals
);
530 _mesa_unpack_ubyte_stencil_row(stencilRb
->Format
, width
,
531 stencilMap
, stencilVals
);
533 _mesa_pack_depth_stencil_span(ctx
, width
, type
, (GLuint
*)dst
,
534 depthVals
, stencilVals
, packing
);
536 depthMap
+= depthStride
;
537 stencilMap
+= stencilStride
;
541 ctx
->Driver
.UnmapRenderbuffer(ctx
, depthRb
);
542 if (stencilRb
!= depthRb
) {
543 ctx
->Driver
.UnmapRenderbuffer(ctx
, stencilRb
);
549 * Read combined depth/stencil values.
550 * We'll have already done error checking to be sure the expected
551 * depth and stencil buffers really exist.
554 read_depth_stencil_pixels(struct gl_context
*ctx
,
556 GLsizei width
, GLsizei height
,
557 GLenum type
, GLvoid
*pixels
,
558 const struct gl_pixelstore_attrib
*packing
)
560 const GLboolean scaleOrBias
561 = ctx
->Pixel
.DepthScale
!= 1.0 || ctx
->Pixel
.DepthBias
!= 0.0;
562 const GLboolean stencilTransfer
= ctx
->Pixel
.IndexShift
563 || ctx
->Pixel
.IndexOffset
|| ctx
->Pixel
.MapStencilFlag
;
567 dst
= (GLubyte
*) _mesa_image_address2d(packing
, pixels
,
569 GL_DEPTH_STENCIL_EXT
,
571 dstStride
= _mesa_image_row_stride(packing
, width
,
572 GL_DEPTH_STENCIL_EXT
, type
);
574 /* Fast 24/8 reads. */
575 if (type
== GL_UNSIGNED_INT_24_8
&&
576 !scaleOrBias
&& !stencilTransfer
&& !packing
->SwapBytes
) {
577 if (fast_read_depth_stencil_pixels(ctx
, x
, y
, width
, height
,
581 if (fast_read_depth_stencil_pixels_separate(ctx
, x
, y
, width
, height
,
582 (uint32_t *)dst
, dstStride
))
586 slow_read_depth_stencil_pixels_separate(ctx
, x
, y
, width
, height
,
594 * Software fallback routine for ctx->Driver.ReadPixels().
595 * By time we get here, all error checking will have been done.
598 _mesa_readpixels(struct gl_context
*ctx
,
599 GLint x
, GLint y
, GLsizei width
, GLsizei height
,
600 GLenum format
, GLenum type
,
601 const struct gl_pixelstore_attrib
*packing
,
604 struct gl_pixelstore_attrib clippedPacking
= *packing
;
607 _mesa_update_state(ctx
);
609 /* Do all needed clipping here, so that we can forget about it later */
610 if (_mesa_clip_readpixels(ctx
, &x
, &y
, &width
, &height
, &clippedPacking
)) {
612 pixels
= _mesa_map_pbo_dest(ctx
, &clippedPacking
, pixels
);
616 case GL_STENCIL_INDEX
:
617 read_stencil_pixels(ctx
, x
, y
, width
, height
, type
, pixels
,
620 case GL_DEPTH_COMPONENT
:
621 read_depth_pixels(ctx
, x
, y
, width
, height
, type
, pixels
,
624 case GL_DEPTH_STENCIL_EXT
:
625 read_depth_stencil_pixels(ctx
, x
, y
, width
, height
, type
, pixels
,
629 /* all other formats should be color formats */
630 read_rgba_pixels(ctx
, x
, y
, width
, height
, format
, type
, pixels
,
634 _mesa_unmap_pbo_dest(ctx
, &clippedPacking
);
641 * Do error checking of the format/type parameters to glReadPixels and
643 * \param drawing if GL_TRUE do checking for DrawPixels, else do checking
645 * \return GL_TRUE if error detected, GL_FALSE if no errors
648 _mesa_error_check_format_type(struct gl_context
*ctx
, GLenum format
,
649 GLenum type
, GLboolean drawing
)
651 const char *readDraw
= drawing
? "Draw" : "Read";
652 const GLboolean reading
= !drawing
;
655 /* state validation should have already been done */
656 ASSERT(ctx
->NewState
== 0x0);
658 if (ctx
->Extensions
.EXT_packed_depth_stencil
659 && type
== GL_UNSIGNED_INT_24_8_EXT
660 && format
!= GL_DEPTH_STENCIL_EXT
) {
661 _mesa_error(ctx
, GL_INVALID_OPERATION
,
662 "gl%sPixels(format is not GL_DEPTH_STENCIL_EXT)", readDraw
);
666 if (ctx
->Extensions
.ARB_depth_buffer_float
667 && type
== GL_FLOAT_32_UNSIGNED_INT_24_8_REV
668 && format
!= GL_DEPTH_STENCIL_EXT
) {
669 _mesa_error(ctx
, GL_INVALID_OPERATION
,
670 "gl%sPixels(format is not GL_DEPTH_STENCIL_EXT)", readDraw
);
674 /* basic combinations test */
675 err
= _mesa_error_check_format_and_type(ctx
, format
, type
);
676 if (err
!= GL_NO_ERROR
) {
677 _mesa_error(ctx
, err
, "gl%sPixels(format or type)", readDraw
);
681 /* additional checks */
689 case GL_LUMINANCE_ALPHA
:
695 case GL_RED_INTEGER_EXT
:
696 case GL_GREEN_INTEGER_EXT
:
697 case GL_BLUE_INTEGER_EXT
:
698 case GL_ALPHA_INTEGER_EXT
:
699 case GL_RGB_INTEGER_EXT
:
700 case GL_RGBA_INTEGER_EXT
:
701 case GL_BGR_INTEGER_EXT
:
702 case GL_BGRA_INTEGER_EXT
:
703 case GL_LUMINANCE_INTEGER_EXT
:
704 case GL_LUMINANCE_ALPHA_INTEGER_EXT
:
707 if (!_mesa_source_buffer_exists(ctx
, GL_COLOR
)) {
708 _mesa_error(ctx
, GL_INVALID_OPERATION
,
709 "glReadPixels(no color buffer)");
716 if (ctx
->PixelMaps
.ItoR
.Size
== 0 ||
717 ctx
->PixelMaps
.ItoG
.Size
== 0 ||
718 ctx
->PixelMaps
.ItoB
.Size
== 0) {
719 _mesa_error(ctx
, GL_INVALID_OPERATION
,
720 "glDrawPixels(drawing color index pixels into RGB buffer)");
726 if (!_mesa_source_buffer_exists(ctx
, GL_COLOR
)) {
727 _mesa_error(ctx
, GL_INVALID_OPERATION
,
728 "glReadPixels(no color buffer)");
731 /* We no longer support CI-mode color buffers so trying to read
732 * GL_COLOR_INDEX pixels is always an error.
734 _mesa_error(ctx
, GL_INVALID_OPERATION
,
735 "glReadPixels(color buffer is RGB)");
739 case GL_STENCIL_INDEX
:
740 if ((drawing
&& !_mesa_dest_buffer_exists(ctx
, format
)) ||
741 (reading
&& !_mesa_source_buffer_exists(ctx
, format
))) {
742 _mesa_error(ctx
, GL_INVALID_OPERATION
,
743 "gl%sPixels(no stencil buffer)", readDraw
);
747 case GL_DEPTH_COMPONENT
:
748 if ((drawing
&& !_mesa_dest_buffer_exists(ctx
, format
))) {
749 _mesa_error(ctx
, GL_INVALID_OPERATION
,
750 "gl%sPixels(no depth buffer)", readDraw
);
754 case GL_DEPTH_STENCIL_EXT
:
755 /* Check validity of the type first. */
757 case GL_UNSIGNED_INT_24_8_EXT
:
758 if (!ctx
->Extensions
.EXT_packed_depth_stencil
) {
759 _mesa_error(ctx
, GL_INVALID_ENUM
, "gl%sPixels(type)", readDraw
);
763 case GL_FLOAT_32_UNSIGNED_INT_24_8_REV
:
764 if (!ctx
->Extensions
.ARB_depth_buffer_float
) {
765 _mesa_error(ctx
, GL_INVALID_ENUM
, "gl%sPixels(type)", readDraw
);
770 _mesa_error(ctx
, GL_INVALID_ENUM
, "gl%sPixels(type)", readDraw
);
773 if ((drawing
&& !_mesa_dest_buffer_exists(ctx
, format
)) ||
774 (reading
&& !_mesa_source_buffer_exists(ctx
, format
))) {
775 _mesa_error(ctx
, GL_INVALID_OPERATION
,
776 "gl%sPixels(no depth or stencil buffer)", readDraw
);
781 /* this should have been caught in _mesa_error_check_format_type() */
782 _mesa_problem(ctx
, "unexpected format in _mesa_%sPixels", readDraw
);
793 _mesa_ReadnPixelsARB( GLint x
, GLint y
, GLsizei width
, GLsizei height
,
794 GLenum format
, GLenum type
, GLsizei bufSize
,
797 GET_CURRENT_CONTEXT(ctx
);
798 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx
);
800 FLUSH_CURRENT(ctx
, 0);
802 if (MESA_VERBOSE
& VERBOSE_API
)
803 _mesa_debug(ctx
, "glReadPixels(%d, %d, %s, %s, %p)\n",
805 _mesa_lookup_enum_by_nr(format
),
806 _mesa_lookup_enum_by_nr(type
),
809 if (width
< 0 || height
< 0) {
810 _mesa_error( ctx
, GL_INVALID_VALUE
,
811 "glReadPixels(width=%d height=%d)", width
, height
);
816 _mesa_update_state(ctx
);
818 if (_mesa_error_check_format_type(ctx
, format
, type
, GL_FALSE
)) {
823 if (ctx
->ReadBuffer
->_Status
!= GL_FRAMEBUFFER_COMPLETE_EXT
) {
824 _mesa_error(ctx
, GL_INVALID_FRAMEBUFFER_OPERATION_EXT
,
825 "glReadPixels(incomplete framebuffer)" );
829 /* Check that the destination format and source buffer are both
830 * integer-valued or both non-integer-valued.
832 if (ctx
->Extensions
.EXT_texture_integer
&& _mesa_is_color_format(format
)) {
833 const struct gl_renderbuffer
*rb
= ctx
->ReadBuffer
->_ColorReadBuffer
;
834 const GLboolean srcInteger
= _mesa_is_format_integer_color(rb
->Format
);
835 const GLboolean dstInteger
= _mesa_is_integer_format(format
);
836 if (dstInteger
!= srcInteger
) {
837 _mesa_error(ctx
, GL_INVALID_OPERATION
,
838 "glReadPixels(integer / non-integer format mismatch");
843 if (ctx
->ReadBuffer
->Name
!= 0 && ctx
->ReadBuffer
->Visual
.samples
> 0) {
844 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glReadPixels(multisample FBO)");
848 if (!_mesa_source_buffer_exists(ctx
, format
)) {
849 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glReadPixels(no readbuffer)");
853 if (width
== 0 || height
== 0)
854 return; /* nothing to do */
856 if (!_mesa_validate_pbo_access(2, &ctx
->Pack
, width
, height
, 1,
857 format
, type
, bufSize
, pixels
)) {
858 if (_mesa_is_bufferobj(ctx
->Pack
.BufferObj
)) {
859 _mesa_error(ctx
, GL_INVALID_OPERATION
,
860 "glReadPixels(out of bounds PBO access)");
862 _mesa_error(ctx
, GL_INVALID_OPERATION
,
863 "glReadnPixelsARB(out of bounds access:"
864 " bufSize (%d) is too small)", bufSize
);
869 if (_mesa_is_bufferobj(ctx
->Pack
.BufferObj
) &&
870 _mesa_bufferobj_mapped(ctx
->Pack
.BufferObj
)) {
871 /* buffer is mapped - that's an error */
872 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glReadPixels(PBO is mapped)");
876 ctx
->Driver
.ReadPixels(ctx
, x
, y
, width
, height
,
877 format
, type
, &ctx
->Pack
, pixels
);
881 _mesa_ReadPixels( GLint x
, GLint y
, GLsizei width
, GLsizei height
,
882 GLenum format
, GLenum type
, GLvoid
*pixels
)
884 _mesa_ReadnPixelsARB(x
, y
, width
, height
, format
, type
, INT_MAX
, pixels
);