2 * Mesa 3-D graphics library
4 * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
28 #include "bufferobj.h"
32 #include "framebuffer.h"
34 #include "format_unpack.h"
40 #include "glformats.h"
42 #include "format_utils.h"
43 #include "pixeltransfer.h"
47 * Return true if the conversion L=R+G+B is needed.
50 need_rgb_to_luminance_conversion(mesa_format texFormat
, GLenum format
)
52 GLenum baseTexFormat
= _mesa_get_format_base_format(texFormat
);
54 return (baseTexFormat
== GL_RG
||
55 baseTexFormat
== GL_RGB
||
56 baseTexFormat
== GL_RGBA
) &&
57 (format
== GL_LUMINANCE
||
58 format
== GL_LUMINANCE_ALPHA
||
59 format
== GL_LUMINANCE_INTEGER_EXT
||
60 format
== GL_LUMINANCE_ALPHA_INTEGER_EXT
);
65 * Return transfer op flags for this ReadPixels operation.
68 get_readpixels_transfer_ops(const struct gl_context
*ctx
, mesa_format texFormat
,
69 GLenum format
, GLenum type
, GLboolean uses_blit
)
71 GLbitfield transferOps
= ctx
->_ImageTransferState
;
73 if (format
== GL_DEPTH_COMPONENT
||
74 format
== GL_DEPTH_STENCIL
||
75 format
== GL_STENCIL_INDEX
) {
79 /* Pixel transfer ops (scale, bias, table lookup) do not apply
82 if (_mesa_is_enum_format_integer(format
)) {
87 /* For blit-based ReadPixels packing, the clamping is done automatically
88 * unless the type is float. */
89 if (_mesa_get_clamp_read_color(ctx
, ctx
->ReadBuffer
) &&
90 (type
== GL_FLOAT
|| type
== GL_HALF_FLOAT
)) {
91 transferOps
|= IMAGE_CLAMP_BIT
;
95 /* For CPU-based ReadPixels packing, the clamping must always be done
96 * for non-float types, */
97 if (_mesa_get_clamp_read_color(ctx
, ctx
->ReadBuffer
) ||
98 (type
!= GL_FLOAT
&& type
!= GL_HALF_FLOAT
)) {
99 transferOps
|= IMAGE_CLAMP_BIT
;
103 /* If the format is unsigned normalized, we can ignore clamping
104 * because the values are already in the range [0,1] so it won't
105 * have any effect anyway.
107 if (_mesa_get_format_datatype(texFormat
) == GL_UNSIGNED_NORMALIZED
&&
108 !need_rgb_to_luminance_conversion(texFormat
, format
)) {
109 transferOps
&= ~IMAGE_CLAMP_BIT
;
117 * Return true if memcpy cannot be used for ReadPixels.
119 * If uses_blit is true, the function returns true if a simple 3D engine blit
120 * cannot be used for ReadPixels packing.
122 * NOTE: This doesn't take swizzling and format conversions between
123 * the readbuffer and the pixel pack buffer into account.
126 _mesa_readpixels_needs_slow_path(const struct gl_context
*ctx
, GLenum format
,
127 GLenum type
, GLboolean uses_blit
)
129 struct gl_renderbuffer
*rb
=
130 _mesa_get_read_renderbuffer_for_format(ctx
, format
);
135 /* There are different rules depending on the base format. */
137 case GL_DEPTH_STENCIL
:
138 return !_mesa_has_depthstencil_combined(ctx
->ReadBuffer
) ||
139 ctx
->Pixel
.DepthScale
!= 1.0f
|| ctx
->Pixel
.DepthBias
!= 0.0f
||
140 ctx
->Pixel
.IndexShift
|| ctx
->Pixel
.IndexOffset
||
141 ctx
->Pixel
.MapStencilFlag
;
143 case GL_DEPTH_COMPONENT
:
144 return ctx
->Pixel
.DepthScale
!= 1.0f
|| ctx
->Pixel
.DepthBias
!= 0.0f
;
146 case GL_STENCIL_INDEX
:
147 return ctx
->Pixel
.IndexShift
|| ctx
->Pixel
.IndexOffset
||
148 ctx
->Pixel
.MapStencilFlag
;
152 if (need_rgb_to_luminance_conversion(rb
->Format
, format
)) {
156 /* Conversion between signed and unsigned integers needs masking
157 * (it isn't just memcpy). */
158 srcType
= _mesa_get_format_datatype(rb
->Format
);
160 if ((srcType
== GL_INT
&&
161 (type
== GL_UNSIGNED_INT
||
162 type
== GL_UNSIGNED_SHORT
||
163 type
== GL_UNSIGNED_BYTE
)) ||
164 (srcType
== GL_UNSIGNED_INT
&&
171 /* And finally, see if there are any transfer ops. */
172 return get_readpixels_transfer_ops(ctx
, rb
->Format
, format
, type
,
180 readpixels_can_use_memcpy(const struct gl_context
*ctx
, GLenum format
, GLenum type
,
181 const struct gl_pixelstore_attrib
*packing
)
183 struct gl_renderbuffer
*rb
=
184 _mesa_get_read_renderbuffer_for_format(ctx
, format
);
188 if (_mesa_readpixels_needs_slow_path(ctx
, format
, type
, GL_FALSE
)) {
192 /* The base internal format and the base Mesa format must match. */
193 if (rb
->_BaseFormat
!= _mesa_get_format_base_format(rb
->Format
)) {
197 /* The Mesa format must match the input format and type. */
198 if (!_mesa_format_matches_format_and_type(rb
->Format
, format
, type
,
199 packing
->SwapBytes
)) {
208 readpixels_memcpy(struct gl_context
*ctx
,
210 GLsizei width
, GLsizei height
,
211 GLenum format
, GLenum type
,
213 const struct gl_pixelstore_attrib
*packing
)
215 struct gl_renderbuffer
*rb
=
216 _mesa_get_read_renderbuffer_for_format(ctx
, format
);
218 int dstStride
, stride
, j
, texelBytes
;
220 /* Fail if memcpy cannot be used. */
221 if (!readpixels_can_use_memcpy(ctx
, format
, type
, packing
)) {
225 dstStride
= _mesa_image_row_stride(packing
, width
, format
, type
);
226 dst
= (GLubyte
*) _mesa_image_address2d(packing
, pixels
, width
, height
,
229 ctx
->Driver
.MapRenderbuffer(ctx
, rb
, x
, y
, width
, height
, GL_MAP_READ_BIT
,
232 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glReadPixels");
233 return GL_TRUE
; /* don't bother trying the slow path */
236 texelBytes
= _mesa_get_format_bytes(rb
->Format
);
239 for (j
= 0; j
< height
; j
++) {
240 memcpy(dst
, map
, width
* texelBytes
);
245 ctx
->Driver
.UnmapRenderbuffer(ctx
, rb
);
251 * Optimized path for conversion of depth values to GL_DEPTH_COMPONENT,
255 read_uint_depth_pixels( struct gl_context
*ctx
,
257 GLsizei width
, GLsizei height
,
258 GLenum type
, GLvoid
*pixels
,
259 const struct gl_pixelstore_attrib
*packing
)
261 struct gl_framebuffer
*fb
= ctx
->ReadBuffer
;
262 struct gl_renderbuffer
*rb
= fb
->Attachment
[BUFFER_DEPTH
].Renderbuffer
;
264 int stride
, dstStride
, j
;
266 if (ctx
->Pixel
.DepthScale
!= 1.0 || ctx
->Pixel
.DepthBias
!= 0.0)
269 if (packing
->SwapBytes
)
272 if (_mesa_get_format_datatype(rb
->Format
) != GL_UNSIGNED_NORMALIZED
)
275 ctx
->Driver
.MapRenderbuffer(ctx
, rb
, x
, y
, width
, height
, GL_MAP_READ_BIT
,
279 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glReadPixels");
280 return GL_TRUE
; /* don't bother trying the slow path */
283 dstStride
= _mesa_image_row_stride(packing
, width
, GL_DEPTH_COMPONENT
, type
);
284 dst
= (GLubyte
*) _mesa_image_address2d(packing
, pixels
, width
, height
,
285 GL_DEPTH_COMPONENT
, type
, 0, 0);
287 for (j
= 0; j
< height
; j
++) {
288 _mesa_unpack_uint_z_row(rb
->Format
, width
, map
, (GLuint
*)dst
);
293 ctx
->Driver
.UnmapRenderbuffer(ctx
, rb
);
299 * Read pixels for format=GL_DEPTH_COMPONENT.
302 read_depth_pixels( struct gl_context
*ctx
,
304 GLsizei width
, GLsizei height
,
305 GLenum type
, GLvoid
*pixels
,
306 const struct gl_pixelstore_attrib
*packing
)
308 struct gl_framebuffer
*fb
= ctx
->ReadBuffer
;
309 struct gl_renderbuffer
*rb
= fb
->Attachment
[BUFFER_DEPTH
].Renderbuffer
;
312 int dstStride
, stride
;
313 GLfloat
*depthValues
;
318 /* clipping should have been done already */
321 assert(x
+ width
<= (GLint
) rb
->Width
);
322 assert(y
+ height
<= (GLint
) rb
->Height
);
324 if (type
== GL_UNSIGNED_INT
&&
325 read_uint_depth_pixels(ctx
, x
, y
, width
, height
, type
, pixels
, packing
)) {
329 dstStride
= _mesa_image_row_stride(packing
, width
, GL_DEPTH_COMPONENT
, type
);
330 dst
= (GLubyte
*) _mesa_image_address2d(packing
, pixels
, width
, height
,
331 GL_DEPTH_COMPONENT
, type
, 0, 0);
333 ctx
->Driver
.MapRenderbuffer(ctx
, rb
, x
, y
, width
, height
, GL_MAP_READ_BIT
,
336 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glReadPixels");
340 depthValues
= malloc(width
* sizeof(GLfloat
));
343 /* General case (slower) */
344 for (j
= 0; j
< height
; j
++, y
++) {
345 _mesa_unpack_float_z_row(rb
->Format
, width
, map
, depthValues
);
346 _mesa_pack_depth_span(ctx
, width
, dst
, type
, depthValues
, packing
);
353 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glReadPixels");
358 ctx
->Driver
.UnmapRenderbuffer(ctx
, rb
);
363 * Read pixels for format=GL_STENCIL_INDEX.
366 read_stencil_pixels( struct gl_context
*ctx
,
368 GLsizei width
, GLsizei height
,
369 GLenum type
, GLvoid
*pixels
,
370 const struct gl_pixelstore_attrib
*packing
)
372 struct gl_framebuffer
*fb
= ctx
->ReadBuffer
;
373 struct gl_renderbuffer
*rb
= fb
->Attachment
[BUFFER_STENCIL
].Renderbuffer
;
375 GLubyte
*map
, *stencil
;
381 ctx
->Driver
.MapRenderbuffer(ctx
, rb
, x
, y
, width
, height
, GL_MAP_READ_BIT
,
384 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glReadPixels");
388 stencil
= malloc(width
* sizeof(GLubyte
));
391 /* process image row by row */
392 for (j
= 0; j
< height
; j
++) {
395 _mesa_unpack_ubyte_stencil_row(rb
->Format
, width
, map
, stencil
);
396 dest
= _mesa_image_address2d(packing
, pixels
, width
, height
,
397 GL_STENCIL_INDEX
, type
, j
, 0);
399 _mesa_pack_stencil_span(ctx
, width
, type
, dest
, stencil
, packing
);
405 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glReadPixels");
410 ctx
->Driver
.UnmapRenderbuffer(ctx
, rb
);
414 * Read R, G, B, A, RGB, L, or LA pixels.
417 read_rgba_pixels( struct gl_context
*ctx
,
419 GLsizei width
, GLsizei height
,
420 GLenum format
, GLenum type
, GLvoid
*pixels
,
421 const struct gl_pixelstore_attrib
*packing
)
423 GLbitfield transferOps
;
424 bool dst_is_integer
, dst_is_luminance
, needs_rebase
;
425 int dst_stride
, src_stride
, rb_stride
;
426 uint32_t dst_format
, src_format
;
428 mesa_format rb_format
;
431 bool src_is_uint
= false;
432 uint8_t rebase_swizzle
[4];
433 struct gl_framebuffer
*fb
= ctx
->ReadBuffer
;
434 struct gl_renderbuffer
*rb
= fb
->_ColorReadBuffer
;
439 transferOps
= get_readpixels_transfer_ops(ctx
, rb
->Format
, format
, type
,
441 /* Describe the dst format */
442 dst_is_integer
= _mesa_is_enum_format_integer(format
);
443 dst_stride
= _mesa_image_row_stride(packing
, width
, format
, type
);
444 dst_format
= _mesa_format_from_format_and_type(format
, type
);
445 dst_is_luminance
= format
== GL_LUMINANCE
||
446 format
== GL_LUMINANCE_ALPHA
||
447 format
== GL_LUMINANCE_INTEGER_EXT
||
448 format
== GL_LUMINANCE_ALPHA_INTEGER_EXT
;
449 dst
= (GLubyte
*) _mesa_image_address2d(packing
, pixels
, width
, height
,
452 /* Map the source render buffer */
453 ctx
->Driver
.MapRenderbuffer(ctx
, rb
, x
, y
, width
, height
, GL_MAP_READ_BIT
,
456 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glReadPixels");
459 rb_format
= _mesa_get_srgb_format_linear(rb
->Format
);
462 * Depending on the base formats involved in the conversion we might need to
463 * rebase some values, so for these formats we compute a rebase swizzle.
465 if (rb
->_BaseFormat
== GL_LUMINANCE
|| rb
->_BaseFormat
== GL_INTENSITY
) {
467 rebase_swizzle
[0] = MESA_FORMAT_SWIZZLE_X
;
468 rebase_swizzle
[1] = MESA_FORMAT_SWIZZLE_ZERO
;
469 rebase_swizzle
[2] = MESA_FORMAT_SWIZZLE_ZERO
;
470 rebase_swizzle
[3] = MESA_FORMAT_SWIZZLE_ONE
;
471 } else if (rb
->_BaseFormat
== GL_LUMINANCE_ALPHA
) {
473 rebase_swizzle
[0] = MESA_FORMAT_SWIZZLE_X
;
474 rebase_swizzle
[1] = MESA_FORMAT_SWIZZLE_ZERO
;
475 rebase_swizzle
[2] = MESA_FORMAT_SWIZZLE_ZERO
;
476 rebase_swizzle
[3] = MESA_FORMAT_SWIZZLE_W
;
477 } else if (_mesa_get_format_base_format(rb_format
) != rb
->_BaseFormat
) {
479 _mesa_compute_rgba2base2rgba_component_mapping(rb
->_BaseFormat
,
482 needs_rebase
= false;
485 /* Since _mesa_format_convert does not handle transferOps we need to handle
486 * them before we call the function. This requires to convert to RGBA float
487 * first so we can call _mesa_apply_rgba_transfer_ops. If the dst format is
488 * integer transferOps do not apply.
490 * Converting to luminance also requires converting to RGBA first, so we can
491 * then compute luminance values as L=R+G+B. Notice that this is different
492 * from GetTexImage, where we compute L=R.
494 assert(!transferOps
|| (transferOps
&& !dst_is_integer
));
496 needs_rgba
= transferOps
|| dst_is_luminance
;
499 uint32_t rgba_format
;
503 /* Convert to RGBA float or int/uint depending on the type of the src */
504 if (dst_is_integer
) {
505 src_is_uint
= _mesa_is_format_unsigned(rb_format
);
507 rgba_format
= RGBA32_UINT
;
508 rgba_stride
= width
* 4 * sizeof(GLuint
);
510 rgba_format
= RGBA32_INT
;
511 rgba_stride
= width
* 4 * sizeof(GLint
);
514 rgba_format
= RGBA32_FLOAT
;
515 rgba_stride
= width
* 4 * sizeof(GLfloat
);
518 /* If we are lucky and the dst format matches the RGBA format we need to
519 * convert to, then we can convert directly into the dst buffer and avoid
520 * the final conversion/copy from the rgba buffer to the dst buffer.
522 if (dst_format
== rgba_format
) {
523 need_convert
= false;
527 rgba
= malloc(height
* rgba_stride
);
529 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glReadPixels");
534 /* Convert to RGBA now */
535 _mesa_format_convert(rgba
, rgba_format
, rgba_stride
,
536 map
, rb_format
, rb_stride
,
538 needs_rebase
? rebase_swizzle
: NULL
);
540 /* Handle transfer ops if necessary */
542 _mesa_apply_rgba_transfer_ops(ctx
, transferOps
, width
* height
, rgba
);
544 /* If we had to rebase, we have already taken care of that */
545 needs_rebase
= false;
547 /* If we were lucky and our RGBA conversion matches the dst format, then
553 /* Otherwise, we need to convert from RGBA to dst next */
555 src_format
= rgba_format
;
556 src_stride
= rgba_stride
;
558 /* No RGBA conversion needed, convert directly to dst */
560 src_format
= rb_format
;
561 src_stride
= rb_stride
;
564 /* Do the conversion.
566 * If the dst format is Luminance, we need to do the conversion by computing
569 if (!dst_is_luminance
) {
570 _mesa_format_convert(dst
, dst_format
, dst_stride
,
571 src
, src_format
, src_stride
,
573 needs_rebase
? rebase_swizzle
: NULL
);
574 } else if (!dst_is_integer
) {
575 /* Compute float Luminance values from RGBA float */
576 int luminance_stride
, luminance_bytes
;
578 uint32_t luminance_format
;
580 luminance_stride
= width
* sizeof(GL_FLOAT
);
581 if (format
== GL_LUMINANCE_ALPHA
)
582 luminance_stride
*= 2;
583 luminance_bytes
= height
* luminance_stride
;
584 luminance
= malloc(luminance_bytes
);
586 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glReadPixels");
590 _mesa_pack_luminance_from_rgba_float(width
* height
, src
,
591 luminance
, format
, transferOps
);
593 /* Convert from Luminance float to dst (this will hadle type conversion
594 * from float to the type of dst if necessary)
596 luminance_format
= _mesa_format_from_format_and_type(format
, GL_FLOAT
);
597 _mesa_format_convert(dst
, dst_format
, dst_stride
,
598 luminance
, luminance_format
, luminance_stride
,
599 width
, height
, NULL
);
602 _mesa_pack_luminance_from_rgba_integer(width
* height
, src
, !src_is_uint
,
610 /* Handle byte swapping if required */
611 if (packing
->SwapBytes
) {
612 GLint swapSize
= _mesa_sizeof_packed_type(type
);
613 if (swapSize
== 2 || swapSize
== 4) {
614 int swapsPerPixel
= _mesa_bytes_per_pixel(format
, type
) / swapSize
;
615 assert(_mesa_bytes_per_pixel(format
, type
) % swapSize
== 0);
617 _mesa_swap2((GLushort
*) dst
, width
* height
* swapsPerPixel
);
618 else if (swapSize
== 4)
619 _mesa_swap4((GLuint
*) dst
, width
* height
* swapsPerPixel
);
624 ctx
->Driver
.UnmapRenderbuffer(ctx
, rb
);
628 * For a packed depth/stencil buffer being read as depth/stencil, just memcpy the
629 * data (possibly swapping 8/24 vs 24/8 as we go).
632 fast_read_depth_stencil_pixels(struct gl_context
*ctx
,
634 GLsizei width
, GLsizei height
,
635 GLubyte
*dst
, int dstStride
)
637 struct gl_framebuffer
*fb
= ctx
->ReadBuffer
;
638 struct gl_renderbuffer
*rb
= fb
->Attachment
[BUFFER_DEPTH
].Renderbuffer
;
639 struct gl_renderbuffer
*stencilRb
= fb
->Attachment
[BUFFER_STENCIL
].Renderbuffer
;
646 if (rb
->Format
!= MESA_FORMAT_S8_UINT_Z24_UNORM
&&
647 rb
->Format
!= MESA_FORMAT_Z24_UNORM_S8_UINT
)
650 ctx
->Driver
.MapRenderbuffer(ctx
, rb
, x
, y
, width
, height
, GL_MAP_READ_BIT
,
653 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glReadPixels");
654 return GL_TRUE
; /* don't bother trying the slow path */
657 for (i
= 0; i
< height
; i
++) {
658 _mesa_unpack_uint_24_8_depth_stencil_row(rb
->Format
, width
,
664 ctx
->Driver
.UnmapRenderbuffer(ctx
, rb
);
671 * For non-float-depth and stencil buffers being read as 24/8 depth/stencil,
672 * copy the integer data directly instead of converting depth to float and
676 fast_read_depth_stencil_pixels_separate(struct gl_context
*ctx
,
678 GLsizei width
, GLsizei height
,
679 uint32_t *dst
, int dstStride
)
681 struct gl_framebuffer
*fb
= ctx
->ReadBuffer
;
682 struct gl_renderbuffer
*depthRb
= fb
->Attachment
[BUFFER_DEPTH
].Renderbuffer
;
683 struct gl_renderbuffer
*stencilRb
= fb
->Attachment
[BUFFER_STENCIL
].Renderbuffer
;
684 GLubyte
*depthMap
, *stencilMap
, *stencilVals
;
685 int depthStride
, stencilStride
, i
, j
;
687 if (_mesa_get_format_datatype(depthRb
->Format
) != GL_UNSIGNED_NORMALIZED
)
690 ctx
->Driver
.MapRenderbuffer(ctx
, depthRb
, x
, y
, width
, height
,
691 GL_MAP_READ_BIT
, &depthMap
, &depthStride
);
693 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glReadPixels");
694 return GL_TRUE
; /* don't bother trying the slow path */
697 ctx
->Driver
.MapRenderbuffer(ctx
, stencilRb
, x
, y
, width
, height
,
698 GL_MAP_READ_BIT
, &stencilMap
, &stencilStride
);
700 ctx
->Driver
.UnmapRenderbuffer(ctx
, depthRb
);
701 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glReadPixels");
702 return GL_TRUE
; /* don't bother trying the slow path */
705 stencilVals
= malloc(width
* sizeof(GLubyte
));
708 for (j
= 0; j
< height
; j
++) {
709 _mesa_unpack_uint_z_row(depthRb
->Format
, width
, depthMap
, dst
);
710 _mesa_unpack_ubyte_stencil_row(stencilRb
->Format
, width
,
711 stencilMap
, stencilVals
);
713 for (i
= 0; i
< width
; i
++) {
714 dst
[i
] = (dst
[i
] & 0xffffff00) | stencilVals
[i
];
717 depthMap
+= depthStride
;
718 stencilMap
+= stencilStride
;
719 dst
+= dstStride
/ 4;
723 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glReadPixels");
728 ctx
->Driver
.UnmapRenderbuffer(ctx
, depthRb
);
729 ctx
->Driver
.UnmapRenderbuffer(ctx
, stencilRb
);
735 slow_read_depth_stencil_pixels_separate(struct gl_context
*ctx
,
737 GLsizei width
, GLsizei height
,
739 const struct gl_pixelstore_attrib
*packing
,
740 GLubyte
*dst
, int dstStride
)
742 struct gl_framebuffer
*fb
= ctx
->ReadBuffer
;
743 struct gl_renderbuffer
*depthRb
= fb
->Attachment
[BUFFER_DEPTH
].Renderbuffer
;
744 struct gl_renderbuffer
*stencilRb
= fb
->Attachment
[BUFFER_STENCIL
].Renderbuffer
;
745 GLubyte
*depthMap
, *stencilMap
;
746 int depthStride
, stencilStride
, j
;
747 GLubyte
*stencilVals
;
751 /* The depth and stencil buffers might be separate, or a single buffer.
752 * If one buffer, only map it once.
754 ctx
->Driver
.MapRenderbuffer(ctx
, depthRb
, x
, y
, width
, height
,
755 GL_MAP_READ_BIT
, &depthMap
, &depthStride
);
757 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glReadPixels");
761 if (stencilRb
!= depthRb
) {
762 ctx
->Driver
.MapRenderbuffer(ctx
, stencilRb
, x
, y
, width
, height
,
763 GL_MAP_READ_BIT
, &stencilMap
,
766 ctx
->Driver
.UnmapRenderbuffer(ctx
, depthRb
);
767 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glReadPixels");
772 stencilMap
= depthMap
;
773 stencilStride
= depthStride
;
776 stencilVals
= malloc(width
* sizeof(GLubyte
));
777 depthVals
= malloc(width
* sizeof(GLfloat
));
779 if (stencilVals
&& depthVals
) {
780 for (j
= 0; j
< height
; j
++) {
781 _mesa_unpack_float_z_row(depthRb
->Format
, width
, depthMap
, depthVals
);
782 _mesa_unpack_ubyte_stencil_row(stencilRb
->Format
, width
,
783 stencilMap
, stencilVals
);
785 _mesa_pack_depth_stencil_span(ctx
, width
, type
, (GLuint
*)dst
,
786 depthVals
, stencilVals
, packing
);
788 depthMap
+= depthStride
;
789 stencilMap
+= stencilStride
;
794 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glReadPixels");
800 ctx
->Driver
.UnmapRenderbuffer(ctx
, depthRb
);
801 if (stencilRb
!= depthRb
) {
802 ctx
->Driver
.UnmapRenderbuffer(ctx
, stencilRb
);
808 * Read combined depth/stencil values.
809 * We'll have already done error checking to be sure the expected
810 * depth and stencil buffers really exist.
813 read_depth_stencil_pixels(struct gl_context
*ctx
,
815 GLsizei width
, GLsizei height
,
816 GLenum type
, GLvoid
*pixels
,
817 const struct gl_pixelstore_attrib
*packing
)
819 const GLboolean scaleOrBias
820 = ctx
->Pixel
.DepthScale
!= 1.0 || ctx
->Pixel
.DepthBias
!= 0.0;
821 const GLboolean stencilTransfer
= ctx
->Pixel
.IndexShift
822 || ctx
->Pixel
.IndexOffset
|| ctx
->Pixel
.MapStencilFlag
;
826 dst
= (GLubyte
*) _mesa_image_address2d(packing
, pixels
,
828 GL_DEPTH_STENCIL_EXT
,
830 dstStride
= _mesa_image_row_stride(packing
, width
,
831 GL_DEPTH_STENCIL_EXT
, type
);
833 /* Fast 24/8 reads. */
834 if (type
== GL_UNSIGNED_INT_24_8
&&
835 !scaleOrBias
&& !stencilTransfer
&& !packing
->SwapBytes
) {
836 if (fast_read_depth_stencil_pixels(ctx
, x
, y
, width
, height
,
840 if (fast_read_depth_stencil_pixels_separate(ctx
, x
, y
, width
, height
,
841 (uint32_t *)dst
, dstStride
))
845 slow_read_depth_stencil_pixels_separate(ctx
, x
, y
, width
, height
,
853 * Software fallback routine for ctx->Driver.ReadPixels().
854 * By time we get here, all error checking will have been done.
857 _mesa_readpixels(struct gl_context
*ctx
,
858 GLint x
, GLint y
, GLsizei width
, GLsizei height
,
859 GLenum format
, GLenum type
,
860 const struct gl_pixelstore_attrib
*packing
,
863 struct gl_pixelstore_attrib clippedPacking
= *packing
;
866 _mesa_update_state(ctx
);
868 /* Do all needed clipping here, so that we can forget about it later */
869 if (_mesa_clip_readpixels(ctx
, &x
, &y
, &width
, &height
, &clippedPacking
)) {
871 pixels
= _mesa_map_pbo_dest(ctx
, &clippedPacking
, pixels
);
874 /* Try memcpy first. */
875 if (readpixels_memcpy(ctx
, x
, y
, width
, height
, format
, type
,
877 _mesa_unmap_pbo_dest(ctx
, &clippedPacking
);
881 /* Otherwise take the slow path. */
883 case GL_STENCIL_INDEX
:
884 read_stencil_pixels(ctx
, x
, y
, width
, height
, type
, pixels
,
887 case GL_DEPTH_COMPONENT
:
888 read_depth_pixels(ctx
, x
, y
, width
, height
, type
, pixels
,
891 case GL_DEPTH_STENCIL_EXT
:
892 read_depth_stencil_pixels(ctx
, x
, y
, width
, height
, type
, pixels
,
896 /* all other formats should be color formats */
897 read_rgba_pixels(ctx
, x
, y
, width
, height
, format
, type
, pixels
,
901 _mesa_unmap_pbo_dest(ctx
, &clippedPacking
);
908 read_pixels_es3_error_check(GLenum format
, GLenum type
,
909 const struct gl_renderbuffer
*rb
)
911 const GLenum internalFormat
= rb
->InternalFormat
;
912 const GLenum data_type
= _mesa_get_format_datatype(rb
->Format
);
913 GLboolean is_unsigned_int
= GL_FALSE
;
914 GLboolean is_signed_int
= GL_FALSE
;
916 if (!_mesa_is_color_format(internalFormat
)) {
917 return GL_INVALID_OPERATION
;
920 is_unsigned_int
= _mesa_is_enum_format_unsigned_int(internalFormat
);
921 if (!is_unsigned_int
) {
922 is_signed_int
= _mesa_is_enum_format_signed_int(internalFormat
);
927 if (type
== GL_FLOAT
&& data_type
== GL_FLOAT
)
928 return GL_NO_ERROR
; /* EXT_color_buffer_float */
929 if (type
== GL_UNSIGNED_BYTE
&& data_type
== GL_UNSIGNED_NORMALIZED
)
931 if (internalFormat
== GL_RGB10_A2
&&
932 type
== GL_UNSIGNED_INT_2_10_10_10_REV
)
934 if (internalFormat
== GL_RGB10_A2UI
&& type
== GL_UNSIGNED_BYTE
)
938 /* GL_EXT_read_format_bgra */
939 if (type
== GL_UNSIGNED_BYTE
||
940 type
== GL_UNSIGNED_SHORT_4_4_4_4_REV
||
941 type
== GL_UNSIGNED_SHORT_1_5_5_5_REV
)
944 case GL_RGBA_INTEGER
:
945 if ((is_signed_int
&& type
== GL_INT
) ||
946 (is_unsigned_int
&& type
== GL_UNSIGNED_INT
))
951 return GL_INVALID_OPERATION
;
956 _mesa_ReadnPixelsARB( GLint x
, GLint y
, GLsizei width
, GLsizei height
,
957 GLenum format
, GLenum type
, GLsizei bufSize
,
960 GLenum err
= GL_NO_ERROR
;
961 struct gl_renderbuffer
*rb
;
963 GET_CURRENT_CONTEXT(ctx
);
965 FLUSH_VERTICES(ctx
, 0);
966 FLUSH_CURRENT(ctx
, 0);
968 if (MESA_VERBOSE
& VERBOSE_API
)
969 _mesa_debug(ctx
, "glReadPixels(%d, %d, %s, %s, %p)\n",
971 _mesa_lookup_enum_by_nr(format
),
972 _mesa_lookup_enum_by_nr(type
),
975 if (width
< 0 || height
< 0) {
976 _mesa_error( ctx
, GL_INVALID_VALUE
,
977 "glReadPixels(width=%d height=%d)", width
, height
);
982 _mesa_update_state(ctx
);
984 if (ctx
->ReadBuffer
->_Status
!= GL_FRAMEBUFFER_COMPLETE_EXT
) {
985 _mesa_error(ctx
, GL_INVALID_FRAMEBUFFER_OPERATION_EXT
,
986 "glReadPixels(incomplete framebuffer)" );
990 rb
= _mesa_get_read_renderbuffer_for_format(ctx
, format
);
992 _mesa_error(ctx
, GL_INVALID_OPERATION
,
993 "glReadPixels(read buffer)");
997 /* OpenGL ES 1.x and OpenGL ES 2.0 impose additional restrictions on the
998 * combinations of format and type that can be used.
1000 * Technically, only two combinations are actually allowed:
1001 * GL_RGBA/GL_UNSIGNED_BYTE, and some implementation-specific internal
1002 * preferred combination. This code doesn't know what that preferred
1003 * combination is, and Mesa can handle anything valid. Just work instead.
1005 if (_mesa_is_gles(ctx
)) {
1006 if (ctx
->API
== API_OPENGLES2
&&
1007 _mesa_is_color_format(format
) &&
1008 _mesa_get_color_read_format(ctx
) == format
&&
1009 _mesa_get_color_read_type(ctx
) == type
) {
1011 } else if (ctx
->Version
< 30) {
1012 err
= _mesa_es_error_check_format_and_type(format
, type
, 2);
1013 if (err
== GL_NO_ERROR
) {
1014 if (type
== GL_FLOAT
|| type
== GL_HALF_FLOAT_OES
) {
1015 err
= GL_INVALID_OPERATION
;
1019 err
= read_pixels_es3_error_check(format
, type
, rb
);
1022 if (err
== GL_NO_ERROR
&& (format
== GL_DEPTH_COMPONENT
1023 || format
== GL_DEPTH_STENCIL
)) {
1024 err
= GL_INVALID_ENUM
;
1027 if (err
!= GL_NO_ERROR
) {
1028 _mesa_error(ctx
, err
, "glReadPixels(invalid format %s and/or type %s)",
1029 _mesa_lookup_enum_by_nr(format
),
1030 _mesa_lookup_enum_by_nr(type
));
1035 err
= _mesa_error_check_format_and_type(ctx
, format
, type
);
1036 if (err
!= GL_NO_ERROR
) {
1037 _mesa_error(ctx
, err
, "glReadPixels(invalid format %s and/or type %s)",
1038 _mesa_lookup_enum_by_nr(format
),
1039 _mesa_lookup_enum_by_nr(type
));
1043 if (_mesa_is_user_fbo(ctx
->ReadBuffer
) &&
1044 ctx
->ReadBuffer
->Visual
.samples
> 0) {
1045 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glReadPixels(multisample FBO)");
1049 if (!_mesa_source_buffer_exists(ctx
, format
)) {
1050 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glReadPixels(no readbuffer)");
1054 /* Check that the destination format and source buffer are both
1055 * integer-valued or both non-integer-valued.
1057 if (ctx
->Extensions
.EXT_texture_integer
&& _mesa_is_color_format(format
)) {
1058 const struct gl_renderbuffer
*rb
= ctx
->ReadBuffer
->_ColorReadBuffer
;
1059 const GLboolean srcInteger
= _mesa_is_format_integer_color(rb
->Format
);
1060 const GLboolean dstInteger
= _mesa_is_enum_format_integer(format
);
1061 if (dstInteger
!= srcInteger
) {
1062 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1063 "glReadPixels(integer / non-integer format mismatch");
1068 if (width
== 0 || height
== 0)
1069 return; /* nothing to do */
1071 if (!_mesa_validate_pbo_access(2, &ctx
->Pack
, width
, height
, 1,
1072 format
, type
, bufSize
, pixels
)) {
1073 if (_mesa_is_bufferobj(ctx
->Pack
.BufferObj
)) {
1074 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1075 "glReadPixels(out of bounds PBO access)");
1077 _mesa_error(ctx
, GL_INVALID_OPERATION
,
1078 "glReadnPixelsARB(out of bounds access:"
1079 " bufSize (%d) is too small)", bufSize
);
1084 if (_mesa_is_bufferobj(ctx
->Pack
.BufferObj
) &&
1085 _mesa_check_disallowed_mapping(ctx
->Pack
.BufferObj
)) {
1086 /* buffer is mapped - that's an error */
1087 _mesa_error(ctx
, GL_INVALID_OPERATION
, "glReadPixels(PBO is mapped)");
1091 ctx
->Driver
.ReadPixels(ctx
, x
, y
, width
, height
,
1092 format
, type
, &ctx
->Pack
, pixels
);
1096 _mesa_ReadPixels( GLint x
, GLint y
, GLsizei width
, GLsizei height
,
1097 GLenum format
, GLenum type
, GLvoid
*pixels
)
1099 _mesa_ReadnPixelsARB(x
, y
, width
, height
, format
, type
, INT_MAX
, pixels
);