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 * Tries to implement glReadPixels() of GL_DEPTH_COMPONENT using memcpy of the
48 fast_read_depth_pixels( struct gl_context
*ctx
,
50 GLsizei width
, GLsizei height
,
51 GLenum type
, GLvoid
*pixels
,
52 const struct gl_pixelstore_attrib
*packing
)
54 struct gl_framebuffer
*fb
= ctx
->ReadBuffer
;
55 struct gl_renderbuffer
*rb
= fb
->Attachment
[BUFFER_DEPTH
].Renderbuffer
;
57 int stride
, dstStride
, j
;
59 if (ctx
->Pixel
.DepthScale
!= 1.0 || ctx
->Pixel
.DepthBias
!= 0.0)
62 if (packing
->SwapBytes
)
65 if (_mesa_get_format_datatype(rb
->Format
) != GL_UNSIGNED_NORMALIZED
)
68 if (!((type
== GL_UNSIGNED_SHORT
&& rb
->Format
== MESA_FORMAT_Z16
) ||
69 type
== GL_UNSIGNED_INT
))
72 ctx
->Driver
.MapRenderbuffer(ctx
, rb
, x
, y
, width
, height
, GL_MAP_READ_BIT
,
76 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glReadPixels");
77 return GL_TRUE
; /* don't bother trying the slow path */
80 dstStride
= _mesa_image_row_stride(packing
, width
, GL_DEPTH_COMPONENT
, type
);
81 dst
= (GLubyte
*) _mesa_image_address2d(packing
, pixels
, width
, height
,
82 GL_DEPTH_COMPONENT
, type
, 0, 0);
84 for (j
= 0; j
< height
; j
++) {
85 if (type
== GL_UNSIGNED_INT
) {
86 _mesa_unpack_uint_z_row(rb
->Format
, width
, map
, (GLuint
*)dst
);
88 ASSERT(type
== GL_UNSIGNED_SHORT
&& rb
->Format
== MESA_FORMAT_Z16
);
89 memcpy(dst
, map
, width
* 2);
95 ctx
->Driver
.UnmapRenderbuffer(ctx
, rb
);
101 * Read pixels for format=GL_DEPTH_COMPONENT.
104 read_depth_pixels( struct gl_context
*ctx
,
106 GLsizei width
, GLsizei height
,
107 GLenum type
, GLvoid
*pixels
,
108 const struct gl_pixelstore_attrib
*packing
)
110 struct gl_framebuffer
*fb
= ctx
->ReadBuffer
;
111 struct gl_renderbuffer
*rb
= fb
->Attachment
[BUFFER_DEPTH
].Renderbuffer
;
114 int dstStride
, stride
;
115 GLfloat
*depthValues
;
120 /* clipping should have been done already */
123 ASSERT(x
+ width
<= (GLint
) rb
->Width
);
124 ASSERT(y
+ height
<= (GLint
) rb
->Height
);
126 if (fast_read_depth_pixels(ctx
, x
, y
, width
, height
, type
, pixels
, packing
))
129 dstStride
= _mesa_image_row_stride(packing
, width
, GL_DEPTH_COMPONENT
, type
);
130 dst
= (GLubyte
*) _mesa_image_address2d(packing
, pixels
, width
, height
,
131 GL_DEPTH_COMPONENT
, type
, 0, 0);
133 ctx
->Driver
.MapRenderbuffer(ctx
, rb
, x
, y
, width
, height
, GL_MAP_READ_BIT
,
136 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glReadPixels");
140 depthValues
= malloc(width
* sizeof(GLfloat
));
143 /* General case (slower) */
144 for (j
= 0; j
< height
; j
++, y
++) {
145 _mesa_unpack_float_z_row(rb
->Format
, width
, map
, depthValues
);
146 _mesa_pack_depth_span(ctx
, width
, dst
, type
, depthValues
, packing
);
153 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glReadPixels");
158 ctx
->Driver
.UnmapRenderbuffer(ctx
, rb
);
163 * Read pixels for format=GL_STENCIL_INDEX.
166 read_stencil_pixels( struct gl_context
*ctx
,
168 GLsizei width
, GLsizei height
,
169 GLenum type
, GLvoid
*pixels
,
170 const struct gl_pixelstore_attrib
*packing
)
172 struct gl_framebuffer
*fb
= ctx
->ReadBuffer
;
173 struct gl_renderbuffer
*rb
= fb
->Attachment
[BUFFER_STENCIL
].Renderbuffer
;
175 GLubyte
*map
, *stencil
;
181 ctx
->Driver
.MapRenderbuffer(ctx
, rb
, x
, y
, width
, height
, GL_MAP_READ_BIT
,
184 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glReadPixels");
188 stencil
= malloc(width
* sizeof(GLubyte
));
191 /* process image row by row */
192 for (j
= 0; j
< height
; j
++) {
195 _mesa_unpack_ubyte_stencil_row(rb
->Format
, width
, map
, stencil
);
196 dest
= _mesa_image_address2d(packing
, pixels
, width
, height
,
197 GL_STENCIL_INDEX
, type
, j
, 0);
199 _mesa_pack_stencil_span(ctx
, width
, type
, dest
, stencil
, packing
);
205 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glReadPixels");
210 ctx
->Driver
.UnmapRenderbuffer(ctx
, rb
);
215 * Try to do glReadPixels of RGBA data using a simple memcpy or swizzle.
216 * \return GL_TRUE if successful, GL_FALSE otherwise (use the slow path)
219 fast_read_rgba_pixels_memcpy( struct gl_context
*ctx
,
221 GLsizei width
, GLsizei height
,
222 GLenum format
, GLenum type
,
224 const struct gl_pixelstore_attrib
*packing
,
225 GLbitfield transferOps
)
227 struct gl_renderbuffer
*rb
= ctx
->ReadBuffer
->_ColorReadBuffer
;
229 int dstStride
, stride
, j
, texelBytes
;
230 GLboolean swizzle_rb
= GL_FALSE
, copy_xrgb
= GL_FALSE
;
232 /* XXX we could check for other swizzle/special cases here as needed */
233 if (rb
->Format
== MESA_FORMAT_RGBA8888_REV
&&
235 type
== GL_UNSIGNED_INT_8_8_8_8_REV
&&
236 !ctx
->Pack
.SwapBytes
) {
237 swizzle_rb
= GL_TRUE
;
239 else if (rb
->Format
== MESA_FORMAT_XRGB8888
&&
241 type
== GL_UNSIGNED_INT_8_8_8_8_REV
&&
242 !ctx
->Pack
.SwapBytes
) {
245 else if (!_mesa_format_matches_format_and_type(rb
->Format
, format
, type
,
246 ctx
->Pack
.SwapBytes
))
249 /* If the format is unsigned normalized then we can ignore clamping
250 * because the values are already in the range [0,1] so it won't
251 * have any effect anyway.
253 if (_mesa_get_format_datatype(rb
->Format
) == GL_UNSIGNED_NORMALIZED
)
254 transferOps
&= ~IMAGE_CLAMP_BIT
;
259 dstStride
= _mesa_image_row_stride(packing
, width
, format
, type
);
260 dst
= (GLubyte
*) _mesa_image_address2d(packing
, pixels
, width
, height
,
263 ctx
->Driver
.MapRenderbuffer(ctx
, rb
, x
, y
, width
, height
, GL_MAP_READ_BIT
,
266 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glReadPixels");
267 return GL_TRUE
; /* don't bother trying the slow path */
270 texelBytes
= _mesa_get_format_bytes(rb
->Format
);
274 for (j
= 0; j
< height
; j
++) {
276 for (i
= 0; i
< width
; i
++) {
277 GLuint
*dst4
= (GLuint
*) dst
, *map4
= (GLuint
*) map
;
278 GLuint pixel
= map4
[i
];
279 dst4
[i
] = (pixel
& 0xff00ff00)
280 | ((pixel
& 0x00ff0000) >> 16)
281 | ((pixel
& 0x000000ff) << 16);
286 } else if (copy_xrgb
) {
287 /* convert xrgb -> argb */
288 for (j
= 0; j
< height
; j
++) {
289 GLuint
*dst4
= (GLuint
*) dst
, *map4
= (GLuint
*) map
;
291 for (i
= 0; i
< width
; i
++) {
292 dst4
[i
] = map4
[i
] | 0xff000000; /* set A=0xff */
299 for (j
= 0; j
< height
; j
++) {
300 memcpy(dst
, map
, width
* texelBytes
);
306 ctx
->Driver
.UnmapRenderbuffer(ctx
, rb
);
312 slow_read_rgba_pixels( struct gl_context
*ctx
,
314 GLsizei width
, GLsizei height
,
315 GLenum format
, GLenum type
,
317 const struct gl_pixelstore_attrib
*packing
,
318 GLbitfield transferOps
)
320 struct gl_renderbuffer
*rb
= ctx
->ReadBuffer
->_ColorReadBuffer
;
321 const gl_format rbFormat
= _mesa_get_srgb_format_linear(rb
->Format
);
324 int dstStride
, stride
, j
;
325 GLboolean dst_is_integer
= _mesa_is_enum_format_integer(format
);
326 GLboolean dst_is_uint
= _mesa_is_format_unsigned(rbFormat
);
328 dstStride
= _mesa_image_row_stride(packing
, width
, format
, type
);
329 dst
= (GLubyte
*) _mesa_image_address2d(packing
, pixels
, width
, height
,
332 ctx
->Driver
.MapRenderbuffer(ctx
, rb
, x
, y
, width
, height
, GL_MAP_READ_BIT
,
335 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glReadPixels");
339 rgba
= malloc(width
* MAX_PIXEL_BYTES
);
343 for (j
= 0; j
< height
; j
++) {
344 if (dst_is_integer
) {
345 _mesa_unpack_uint_rgba_row(rbFormat
, width
, map
, (GLuint (*)[4]) rgba
);
346 _mesa_rebase_rgba_uint(width
, (GLuint (*)[4]) rgba
,
349 _mesa_pack_rgba_span_from_uints(ctx
, width
, (GLuint (*)[4]) rgba
, format
,
352 _mesa_pack_rgba_span_from_ints(ctx
, width
, (GLint (*)[4]) rgba
, format
,
356 _mesa_unpack_rgba_row(rbFormat
, width
, map
, (GLfloat (*)[4]) rgba
);
357 _mesa_rebase_rgba_float(width
, (GLfloat (*)[4]) rgba
,
359 _mesa_pack_rgba_span_float(ctx
, width
, (GLfloat (*)[4]) rgba
, format
,
360 type
, dst
, packing
, transferOps
);
369 ctx
->Driver
.UnmapRenderbuffer(ctx
, rb
);
373 * Read R, G, B, A, RGB, L, or LA pixels.
376 read_rgba_pixels( struct gl_context
*ctx
,
378 GLsizei width
, GLsizei height
,
379 GLenum format
, GLenum type
, GLvoid
*pixels
,
380 const struct gl_pixelstore_attrib
*packing
)
382 GLbitfield transferOps
= ctx
->_ImageTransferState
;
383 struct gl_framebuffer
*fb
= ctx
->ReadBuffer
;
384 struct gl_renderbuffer
*rb
= fb
->_ColorReadBuffer
;
389 if ((ctx
->Color
._ClampReadColor
== GL_TRUE
|| type
!= GL_FLOAT
) &&
390 !_mesa_is_enum_format_integer(format
)) {
391 transferOps
|= IMAGE_CLAMP_BIT
;
394 /* Try the optimized paths first. */
395 if (fast_read_rgba_pixels_memcpy(ctx
, x
, y
, width
, height
,
396 format
, type
, pixels
, packing
,
401 slow_read_rgba_pixels(ctx
, x
, y
, width
, height
,
402 format
, type
, pixels
, packing
, transferOps
);
406 * For a packed depth/stencil buffer being read as depth/stencil, just memcpy the
407 * data (possibly swapping 8/24 vs 24/8 as we go).
410 fast_read_depth_stencil_pixels(struct gl_context
*ctx
,
412 GLsizei width
, GLsizei height
,
413 GLubyte
*dst
, int dstStride
)
415 struct gl_framebuffer
*fb
= ctx
->ReadBuffer
;
416 struct gl_renderbuffer
*rb
= fb
->Attachment
[BUFFER_DEPTH
].Renderbuffer
;
417 struct gl_renderbuffer
*stencilRb
= fb
->Attachment
[BUFFER_STENCIL
].Renderbuffer
;
424 if (rb
->Format
!= MESA_FORMAT_Z24_S8
&&
425 rb
->Format
!= MESA_FORMAT_S8_Z24
)
428 ctx
->Driver
.MapRenderbuffer(ctx
, rb
, x
, y
, width
, height
, GL_MAP_READ_BIT
,
431 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glReadPixels");
432 return GL_TRUE
; /* don't bother trying the slow path */
435 for (i
= 0; i
< height
; i
++) {
436 _mesa_unpack_uint_24_8_depth_stencil_row(rb
->Format
, width
,
442 ctx
->Driver
.UnmapRenderbuffer(ctx
, rb
);
449 * For non-float-depth and stencil buffers being read as 24/8 depth/stencil,
450 * copy the integer data directly instead of converting depth to float and
454 fast_read_depth_stencil_pixels_separate(struct gl_context
*ctx
,
456 GLsizei width
, GLsizei height
,
457 uint32_t *dst
, int dstStride
)
459 struct gl_framebuffer
*fb
= ctx
->ReadBuffer
;
460 struct gl_renderbuffer
*depthRb
= fb
->Attachment
[BUFFER_DEPTH
].Renderbuffer
;
461 struct gl_renderbuffer
*stencilRb
= fb
->Attachment
[BUFFER_STENCIL
].Renderbuffer
;
462 GLubyte
*depthMap
, *stencilMap
, *stencilVals
;
463 int depthStride
, stencilStride
, i
, j
;
465 if (_mesa_get_format_datatype(depthRb
->Format
) != GL_UNSIGNED_NORMALIZED
)
468 ctx
->Driver
.MapRenderbuffer(ctx
, depthRb
, x
, y
, width
, height
,
469 GL_MAP_READ_BIT
, &depthMap
, &depthStride
);
471 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glReadPixels");
472 return GL_TRUE
; /* don't bother trying the slow path */
475 ctx
->Driver
.MapRenderbuffer(ctx
, stencilRb
, x
, y
, width
, height
,
476 GL_MAP_READ_BIT
, &stencilMap
, &stencilStride
);
478 ctx
->Driver
.UnmapRenderbuffer(ctx
, depthRb
);
479 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glReadPixels");
480 return GL_TRUE
; /* don't bother trying the slow path */
483 stencilVals
= malloc(width
* sizeof(GLubyte
));
486 for (j
= 0; j
< height
; j
++) {
487 _mesa_unpack_uint_z_row(depthRb
->Format
, width
, depthMap
, dst
);
488 _mesa_unpack_ubyte_stencil_row(stencilRb
->Format
, width
,
489 stencilMap
, stencilVals
);
491 for (i
= 0; i
< width
; i
++) {
492 dst
[i
] = (dst
[i
] & 0xffffff00) | stencilVals
[i
];
495 depthMap
+= depthStride
;
496 stencilMap
+= stencilStride
;
497 dst
+= dstStride
/ 4;
501 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glReadPixels");
506 ctx
->Driver
.UnmapRenderbuffer(ctx
, depthRb
);
507 ctx
->Driver
.UnmapRenderbuffer(ctx
, stencilRb
);
513 slow_read_depth_stencil_pixels_separate(struct gl_context
*ctx
,
515 GLsizei width
, GLsizei height
,
517 const struct gl_pixelstore_attrib
*packing
,
518 GLubyte
*dst
, int dstStride
)
520 struct gl_framebuffer
*fb
= ctx
->ReadBuffer
;
521 struct gl_renderbuffer
*depthRb
= fb
->Attachment
[BUFFER_DEPTH
].Renderbuffer
;
522 struct gl_renderbuffer
*stencilRb
= fb
->Attachment
[BUFFER_STENCIL
].Renderbuffer
;
523 GLubyte
*depthMap
, *stencilMap
;
524 int depthStride
, stencilStride
, j
;
525 GLubyte
*stencilVals
;
529 /* The depth and stencil buffers might be separate, or a single buffer.
530 * If one buffer, only map it once.
532 ctx
->Driver
.MapRenderbuffer(ctx
, depthRb
, x
, y
, width
, height
,
533 GL_MAP_READ_BIT
, &depthMap
, &depthStride
);
535 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glReadPixels");
539 if (stencilRb
!= depthRb
) {
540 ctx
->Driver
.MapRenderbuffer(ctx
, stencilRb
, x
, y
, width
, height
,
541 GL_MAP_READ_BIT
, &stencilMap
,
544 ctx
->Driver
.UnmapRenderbuffer(ctx
, depthRb
);
545 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glReadPixels");
550 stencilMap
= depthMap
;
551 stencilStride
= depthStride
;
554 stencilVals
= malloc(width
* sizeof(GLubyte
));
555 depthVals
= malloc(width
* sizeof(GLfloat
));
557 if (stencilVals
&& depthVals
) {
558 for (j
= 0; j
< height
; j
++) {
559 _mesa_unpack_float_z_row(depthRb
->Format
, width
, depthMap
, depthVals
);
560 _mesa_unpack_ubyte_stencil_row(stencilRb
->Format
, width
,
561 stencilMap
, stencilVals
);
563 _mesa_pack_depth_stencil_span(ctx
, width
, type
, (GLuint
*)dst
,
564 depthVals
, stencilVals
, packing
);
566 depthMap
+= depthStride
;
567 stencilMap
+= stencilStride
;
572 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glReadPixels");
578 ctx
->Driver
.UnmapRenderbuffer(ctx
, depthRb
);
579 if (stencilRb
!= depthRb
) {
580 ctx
->Driver
.UnmapRenderbuffer(ctx
, stencilRb
);
586 * Read combined depth/stencil values.
587 * We'll have already done error checking to be sure the expected
588 * depth and stencil buffers really exist.
591 read_depth_stencil_pixels(struct gl_context
*ctx
,
593 GLsizei width
, GLsizei height
,
594 GLenum type
, GLvoid
*pixels
,
595 const struct gl_pixelstore_attrib
*packing
)
597 const GLboolean scaleOrBias
598 = ctx
->Pixel
.DepthScale
!= 1.0 || ctx
->Pixel
.DepthBias
!= 0.0;
599 const GLboolean stencilTransfer
= ctx
->Pixel
.IndexShift
600 || ctx
->Pixel
.IndexOffset
|| ctx
->Pixel
.MapStencilFlag
;
604 dst
= (GLubyte
*) _mesa_image_address2d(packing
, pixels
,
606 GL_DEPTH_STENCIL_EXT
,
608 dstStride
= _mesa_image_row_stride(packing
, width
,
609 GL_DEPTH_STENCIL_EXT
, type
);
611 /* Fast 24/8 reads. */
612 if (type
== GL_UNSIGNED_INT_24_8
&&
613 !scaleOrBias
&& !stencilTransfer
&& !packing
->SwapBytes
) {
614 if (fast_read_depth_stencil_pixels(ctx
, x
, y
, width
, height
,
618 if (fast_read_depth_stencil_pixels_separate(ctx
, x
, y
, width
, height
,
619 (uint32_t *)dst
, dstStride
))
623 slow_read_depth_stencil_pixels_separate(ctx
, x
, y
, width
, height
,
631 * Software fallback routine for ctx->Driver.ReadPixels().
632 * By time we get here, all error checking will have been done.
635 _mesa_readpixels(struct gl_context
*ctx
,
636 GLint x
, GLint y
, GLsizei width
, GLsizei height
,
637 GLenum format
, GLenum type
,
638 const struct gl_pixelstore_attrib
*packing
,
641 struct gl_pixelstore_attrib clippedPacking
= *packing
;
644 _mesa_update_state(ctx
);
646 /* Do all needed clipping here, so that we can forget about it later */
647 if (_mesa_clip_readpixels(ctx
, &x
, &y
, &width
, &height
, &clippedPacking
)) {
649 pixels
= _mesa_map_pbo_dest(ctx
, &clippedPacking
, pixels
);
653 case GL_STENCIL_INDEX
:
654 read_stencil_pixels(ctx
, x
, y
, width
, height
, type
, pixels
,
657 case GL_DEPTH_COMPONENT
:
658 read_depth_pixels(ctx
, x
, y
, width
, height
, type
, pixels
,
661 case GL_DEPTH_STENCIL_EXT
:
662 read_depth_stencil_pixels(ctx
, x
, y
, width
, height
, type
, pixels
,
666 /* all other formats should be color formats */
667 read_rgba_pixels(ctx
, x
, y
, width
, height
, format
, type
, pixels
,
671 _mesa_unmap_pbo_dest(ctx
, &clippedPacking
);
678 read_pixels_es3_error_check(GLenum format
, GLenum type
,
679 const struct gl_renderbuffer
*rb
)
681 const GLenum internalFormat
= rb
->InternalFormat
;
682 const GLenum data_type
= _mesa_get_format_datatype(rb
->Format
);
683 GLboolean is_unsigned_int
= GL_FALSE
;
684 GLboolean is_signed_int
= GL_FALSE
;
686 if (!_mesa_is_color_format(internalFormat
)) {
687 return GL_INVALID_OPERATION
;
690 is_unsigned_int
= _mesa_is_enum_format_unsigned_int(internalFormat
);
691 if (!is_unsigned_int
) {
692 is_signed_int
= _mesa_is_enum_format_signed_int(internalFormat
);
697 if (type
== GL_FLOAT
&& data_type
== GL_FLOAT
)
698 return GL_NO_ERROR
; /* EXT_color_buffer_float */
699 if (type
== GL_UNSIGNED_BYTE
&& data_type
== GL_UNSIGNED_NORMALIZED
)
701 if (internalFormat
== GL_RGB10_A2
&&
702 type
== GL_UNSIGNED_INT_2_10_10_10_REV
)
704 if (internalFormat
== GL_RGB10_A2UI
&& type
== GL_UNSIGNED_BYTE
)
708 /* GL_EXT_read_format_bgra */
709 if (type
== GL_UNSIGNED_BYTE
||
710 type
== GL_UNSIGNED_SHORT_4_4_4_4_REV
||
711 type
== GL_UNSIGNED_SHORT_1_5_5_5_REV
)
714 case GL_RGBA_INTEGER
:
715 if ((is_signed_int
&& type
== GL_INT
) ||
716 (is_unsigned_int
&& type
== GL_UNSIGNED_INT
))
721 return GL_INVALID_OPERATION
;
726 _mesa_ReadnPixelsARB( GLint x
, GLint y
, GLsizei width
, GLsizei height
,
727 GLenum format
, GLenum type
, GLsizei bufSize
,
730 GLenum err
= GL_NO_ERROR
;
731 struct gl_renderbuffer
*rb
;
733 GET_CURRENT_CONTEXT(ctx
);
735 FLUSH_VERTICES(ctx
, 0);
736 FLUSH_CURRENT(ctx
, 0);
738 if (MESA_VERBOSE
& VERBOSE_API
)
739 _mesa_debug(ctx
, "glReadPixels(%d, %d, %s, %s, %p)\n",
741 _mesa_lookup_enum_by_nr(format
),
742 _mesa_lookup_enum_by_nr(type
),
745 if (width
< 0 || height
< 0) {
746 _mesa_error( ctx
, GL_INVALID_VALUE
,
747 "glReadPixels(width=%d height=%d)", width
, height
);
752 _mesa_update_state(ctx
);
754 if (ctx
->ReadBuffer
->_Status
!= GL_FRAMEBUFFER_COMPLETE_EXT
) {
755 _mesa_error(ctx
, GL_INVALID_FRAMEBUFFER_OPERATION_EXT
,
756 "glReadPixels(incomplete framebuffer)" );
760 rb
= _mesa_get_read_renderbuffer_for_format(ctx
, format
);
762 _mesa_error(ctx
, GL_INVALID_OPERATION
,
763 "glReadPixels(read buffer)");
767 /* OpenGL ES 1.x and OpenGL ES 2.0 impose additional restrictions on the
768 * combinations of format and type that can be used.
770 * Technically, only two combinations are actually allowed:
771 * GL_RGBA/GL_UNSIGNED_BYTE, and some implementation-specific internal
772 * preferred combination. This code doesn't know what that preferred
773 * combination is, and Mesa can handle anything valid. Just work instead.
775 if (_mesa_is_gles(ctx
)) {
776 if (ctx
->API
== API_OPENGLES2
&&
777 _mesa_is_color_format(format
) &&
778 _mesa_get_color_read_format(ctx
) == format
&&
779 _mesa_get_color_read_type(ctx
) == type
) {
781 } else if (ctx
->Version
< 30) {
782 err
= _mesa_es_error_check_format_and_type(format
, type
, 2);
783 if (err
== GL_NO_ERROR
) {
784 if (type
== GL_FLOAT
|| type
== GL_HALF_FLOAT_OES
) {
785 err
= GL_INVALID_OPERATION
;
789 err
= read_pixels_es3_error_check(format
, type
, rb
);
792 if (err
== GL_NO_ERROR
&& (format
== GL_DEPTH_COMPONENT
793 || format
== GL_DEPTH_STENCIL
)) {
794 err
= GL_INVALID_ENUM
;
797 if (err
!= GL_NO_ERROR
) {
798 _mesa_error(ctx
, err
, "glReadPixels(invalid format %s and/or type %s)",
799 _mesa_lookup_enum_by_nr(format
),
800 _mesa_lookup_enum_by_nr(type
));
805 err
= _mesa_error_check_format_and_type(ctx
, format
, type
);
806 if (err
!= GL_NO_ERROR
) {
807 _mesa_error(ctx
, err
, "glReadPixels(invalid format %s and/or type %s)",
808 _mesa_lookup_enum_by_nr(format
),
809 _mesa_lookup_enum_by_nr(type
));
813 if (_mesa_is_user_fbo(ctx
->ReadBuffer
) &&
814 ctx
->ReadBuffer
->Visual
.samples
> 0) {
815 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glReadPixels(multisample FBO)");
819 if (!_mesa_source_buffer_exists(ctx
, format
)) {
820 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glReadPixels(no readbuffer)");
824 /* Check that the destination format and source buffer are both
825 * integer-valued or both non-integer-valued.
827 if (ctx
->Extensions
.EXT_texture_integer
&& _mesa_is_color_format(format
)) {
828 const struct gl_renderbuffer
*rb
= ctx
->ReadBuffer
->_ColorReadBuffer
;
829 const GLboolean srcInteger
= _mesa_is_format_integer_color(rb
->Format
);
830 const GLboolean dstInteger
= _mesa_is_enum_format_integer(format
);
831 if (dstInteger
!= srcInteger
) {
832 _mesa_error(ctx
, GL_INVALID_OPERATION
,
833 "glReadPixels(integer / non-integer format mismatch");
838 if (width
== 0 || height
== 0)
839 return; /* nothing to do */
841 if (!_mesa_validate_pbo_access(2, &ctx
->Pack
, width
, height
, 1,
842 format
, type
, bufSize
, pixels
)) {
843 if (_mesa_is_bufferobj(ctx
->Pack
.BufferObj
)) {
844 _mesa_error(ctx
, GL_INVALID_OPERATION
,
845 "glReadPixels(out of bounds PBO access)");
847 _mesa_error(ctx
, GL_INVALID_OPERATION
,
848 "glReadnPixelsARB(out of bounds access:"
849 " bufSize (%d) is too small)", bufSize
);
854 if (_mesa_is_bufferobj(ctx
->Pack
.BufferObj
) &&
855 _mesa_bufferobj_mapped(ctx
->Pack
.BufferObj
)) {
856 /* buffer is mapped - that's an error */
857 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glReadPixels(PBO is mapped)");
861 ctx
->Driver
.ReadPixels(ctx
, x
, y
, width
, height
,
862 format
, type
, &ctx
->Pack
, pixels
);
866 _mesa_ReadPixels( GLint x
, GLint y
, GLsizei width
, GLsizei height
,
867 GLenum format
, GLenum type
, GLvoid
*pixels
)
869 _mesa_ReadnPixelsARB(x
, y
, width
, height
, format
, type
, INT_MAX
, pixels
);