2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2007 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.
26 #include "main/glheader.h"
27 #include "main/colormac.h"
28 #include "main/feedback.h"
29 #include "main/formats.h"
30 #include "main/format_unpack.h"
31 #include "main/image.h"
32 #include "main/imports.h"
33 #include "main/macros.h"
34 #include "main/pack.h"
36 #include "main/state.h"
38 #include "s_context.h"
41 #include "s_stencil.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_INT
)
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
,
75 dstStride
= _mesa_image_row_stride(packing
, width
, GL_DEPTH_COMPONENT
, type
);
76 dst
= (GLubyte
*) _mesa_image_address2d(packing
, pixels
, width
, height
,
77 GL_DEPTH_COMPONENT
, type
, 0, 0);
79 for (j
= 0; j
< height
; j
++) {
80 if (type
== GL_UNSIGNED_INT
) {
81 _mesa_unpack_uint_z_row(rb
->Format
, width
, map
, (GLuint
*)dst
);
83 ASSERT(type
== GL_UNSIGNED_SHORT
&& rb
->Format
== MESA_FORMAT_Z16
);
84 memcpy(dst
, map
, width
* 2);
90 ctx
->Driver
.UnmapRenderbuffer(ctx
, rb
);
96 * Read pixels for format=GL_DEPTH_COMPONENT.
99 read_depth_pixels( struct gl_context
*ctx
,
101 GLsizei width
, GLsizei height
,
102 GLenum type
, GLvoid
*pixels
,
103 const struct gl_pixelstore_attrib
*packing
)
105 struct gl_framebuffer
*fb
= ctx
->ReadBuffer
;
106 struct gl_renderbuffer
*rb
= fb
->Attachment
[BUFFER_DEPTH
].Renderbuffer
;
109 int dstStride
, stride
;
114 /* clipping should have been done already */
117 ASSERT(x
+ width
<= (GLint
) rb
->Width
);
118 ASSERT(y
+ height
<= (GLint
) rb
->Height
);
119 /* width should never be > MAX_WIDTH since we did clipping earlier */
120 ASSERT(width
<= MAX_WIDTH
);
122 if (fast_read_depth_pixels(ctx
, x
, y
, width
, height
, type
, pixels
, packing
))
125 dstStride
= _mesa_image_row_stride(packing
, width
, GL_DEPTH_COMPONENT
, type
);
126 dst
= (GLubyte
*) _mesa_image_address2d(packing
, pixels
, width
, height
,
127 GL_DEPTH_COMPONENT
, type
, 0, 0);
129 ctx
->Driver
.MapRenderbuffer(ctx
, rb
, x
, y
, width
, height
, GL_MAP_READ_BIT
,
132 /* General case (slower) */
133 for (j
= 0; j
< height
; j
++, y
++) {
134 GLfloat depthValues
[MAX_WIDTH
];
135 _mesa_unpack_float_z_row(rb
->Format
, width
, map
, depthValues
);
136 _mesa_pack_depth_span(ctx
, width
, dst
, type
, depthValues
, packing
);
142 ctx
->Driver
.UnmapRenderbuffer(ctx
, rb
);
147 * Read pixels for format=GL_STENCIL_INDEX.
150 read_stencil_pixels( struct gl_context
*ctx
,
152 GLsizei width
, GLsizei height
,
153 GLenum type
, GLvoid
*pixels
,
154 const struct gl_pixelstore_attrib
*packing
)
156 struct gl_framebuffer
*fb
= ctx
->ReadBuffer
;
157 struct gl_renderbuffer
*rb
= fb
->Attachment
[BUFFER_STENCIL
].Renderbuffer
;
165 /* width should never be > MAX_WIDTH since we did clipping earlier */
166 ASSERT(width
<= MAX_WIDTH
);
168 ctx
->Driver
.MapRenderbuffer(ctx
, rb
, x
, y
, width
, height
, GL_MAP_READ_BIT
,
171 /* process image row by row */
172 for (j
= 0; j
< height
; j
++) {
174 GLstencil stencil
[MAX_WIDTH
];
176 _mesa_unpack_ubyte_stencil_row(rb
->Format
, width
, map
, stencil
);
177 dest
= _mesa_image_address2d(packing
, pixels
, width
, height
,
178 GL_STENCIL_INDEX
, type
, j
, 0);
180 _mesa_pack_stencil_span(ctx
, width
, type
, dest
, stencil
, packing
);
185 ctx
->Driver
.UnmapRenderbuffer(ctx
, rb
);
191 * Optimized glReadPixels for particular pixel formats when pixel
192 * scaling, biasing, mapping, etc. are disabled.
193 * \return GL_TRUE if success, GL_FALSE if unable to do the readpixels
196 fast_read_rgba_pixels( struct gl_context
*ctx
,
198 GLsizei width
, GLsizei height
,
199 GLenum format
, GLenum type
,
201 const struct gl_pixelstore_attrib
*packing
,
202 GLbitfield transferOps
)
204 struct gl_renderbuffer
*rb
= ctx
->ReadBuffer
->_ColorReadBuffer
;
209 ASSERT(rb
->_BaseFormat
== GL_RGBA
||
210 rb
->_BaseFormat
== GL_RGB
||
211 rb
->_BaseFormat
== GL_RG
||
212 rb
->_BaseFormat
== GL_RED
||
213 rb
->_BaseFormat
== GL_LUMINANCE
||
214 rb
->_BaseFormat
== GL_INTENSITY
||
215 rb
->_BaseFormat
== GL_LUMINANCE_ALPHA
||
216 rb
->_BaseFormat
== GL_ALPHA
);
218 /* clipping should have already been done */
219 ASSERT(x
+ width
<= (GLint
) rb
->Width
);
220 ASSERT(y
+ height
<= (GLint
) rb
->Height
);
222 /* check for things we can't handle here */
224 packing
->SwapBytes
||
229 if (format
== GL_RGBA
&& rb
->DataType
== type
) {
230 const GLint dstStride
= _mesa_image_row_stride(packing
, width
,
233 = (GLubyte
*) _mesa_image_address2d(packing
, pixels
, width
, height
,
237 for (row
= 0; row
< height
; row
++) {
238 rb
->GetRow(ctx
, rb
, width
, x
, y
+ row
, dest
);
244 if (format
== GL_RGB
&&
245 rb
->DataType
== GL_UNSIGNED_BYTE
&&
246 type
== GL_UNSIGNED_BYTE
) {
247 const GLint dstStride
= _mesa_image_row_stride(packing
, width
,
250 = (GLubyte
*) _mesa_image_address2d(packing
, pixels
, width
, height
,
254 for (row
= 0; row
< height
; row
++) {
255 GLubyte tempRow
[MAX_WIDTH
][4];
257 rb
->GetRow(ctx
, rb
, width
, x
, y
+ row
, tempRow
);
258 /* convert RGBA to RGB */
259 for (col
= 0; col
< width
; col
++) {
260 dest
[col
* 3 + 0] = tempRow
[col
][0];
261 dest
[col
* 3 + 1] = tempRow
[col
][1];
262 dest
[col
* 3 + 2] = tempRow
[col
][2];
274 fast_read_rgba_pixels_memcpy( struct gl_context
*ctx
,
276 GLsizei width
, GLsizei height
,
277 GLenum format
, GLenum type
,
279 const struct gl_pixelstore_attrib
*packing
,
280 GLbitfield transferOps
)
282 struct gl_renderbuffer
*rb
= ctx
->ReadBuffer
->_ColorReadBuffer
;
284 int dstStride
, stride
, j
, texelBytes
;
286 if (!_mesa_format_matches_format_and_type(rb
->Format
, format
, type
))
289 /* check for things we can't handle here */
290 if (packing
->SwapBytes
||
295 dstStride
= _mesa_image_row_stride(packing
, width
, format
, type
);
296 dst
= (GLubyte
*) _mesa_image_address2d(packing
, pixels
, width
, height
,
299 ctx
->Driver
.MapRenderbuffer(ctx
, rb
, x
, y
, width
, height
, GL_MAP_READ_BIT
,
302 texelBytes
= _mesa_get_format_bytes(rb
->Format
);
303 for (j
= 0; j
< height
; j
++) {
304 memcpy(dst
, map
, width
* texelBytes
);
309 ctx
->Driver
.UnmapRenderbuffer(ctx
, rb
);
316 * When we're using a low-precision color buffer (like 16-bit 5/6/5)
317 * we have to adjust our color values a bit to pass conformance.
318 * The problem is when a 5 or 6-bit color value is converted to an 8-bit
319 * value and then a floating point value, the floating point values don't
320 * increment uniformly as the 5 or 6-bit value is incremented.
322 * This function adjusts floating point values to compensate.
325 adjust_colors(const struct gl_framebuffer
*fb
, GLuint n
, GLfloat rgba
[][4])
327 const GLuint rShift
= 8 - fb
->Visual
.redBits
;
328 const GLuint gShift
= 8 - fb
->Visual
.greenBits
;
329 const GLuint bShift
= 8 - fb
->Visual
.blueBits
;
330 GLfloat rScale
= 1.0F
/ (GLfloat
) ((1 << fb
->Visual
.redBits
) - 1);
331 GLfloat gScale
= 1.0F
/ (GLfloat
) ((1 << fb
->Visual
.greenBits
) - 1);
332 GLfloat bScale
= 1.0F
/ (GLfloat
) ((1 << fb
->Visual
.blueBits
) - 1);
335 if (fb
->Visual
.redBits
== 0)
337 if (fb
->Visual
.greenBits
== 0)
339 if (fb
->Visual
.blueBits
== 0)
342 for (i
= 0; i
< n
; i
++) {
344 /* convert float back to ubyte */
345 CLAMPED_FLOAT_TO_UBYTE(r
, rgba
[i
][RCOMP
]);
346 CLAMPED_FLOAT_TO_UBYTE(g
, rgba
[i
][GCOMP
]);
347 CLAMPED_FLOAT_TO_UBYTE(b
, rgba
[i
][BCOMP
]);
348 /* using only the N most significant bits of the ubyte value, convert to
351 rgba
[i
][RCOMP
] = (GLfloat
) (r
>> rShift
) * rScale
;
352 rgba
[i
][GCOMP
] = (GLfloat
) (g
>> gShift
) * gScale
;
353 rgba
[i
][BCOMP
] = (GLfloat
) (b
>> bShift
) * bScale
;
360 * Read R, G, B, A, RGB, L, or LA pixels.
363 read_rgba_pixels( struct gl_context
*ctx
,
365 GLsizei width
, GLsizei height
,
366 GLenum format
, GLenum type
, GLvoid
*pixels
,
367 const struct gl_pixelstore_attrib
*packing
)
369 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
370 GLbitfield transferOps
= ctx
->_ImageTransferState
;
371 struct gl_framebuffer
*fb
= ctx
->ReadBuffer
;
372 struct gl_renderbuffer
*rb
= fb
->_ColorReadBuffer
;
377 if ((ctx
->Color
._ClampReadColor
== GL_TRUE
|| type
!= GL_FLOAT
) &&
378 !_mesa_is_integer_format(format
)) {
379 transferOps
|= IMAGE_CLAMP_BIT
;
383 /* Try the optimized paths first. */
384 if (fast_read_rgba_pixels_memcpy(ctx
, x
, y
, width
, height
,
385 format
, type
, pixels
, packing
,
390 if (fast_read_rgba_pixels(ctx
, x
, y
, width
, height
,
391 format
, type
, pixels
, packing
, transferOps
)) {
396 /* width should never be > MAX_WIDTH since we did clipping earlier */
397 ASSERT(width
<= MAX_WIDTH
);
400 const GLint dstStride
401 = _mesa_image_row_stride(packing
, width
, format
, type
);
402 GLfloat (*rgba
)[4] = swrast
->SpanArrays
->attribs
[FRAG_ATTRIB_COL0
];
405 = (GLubyte
*) _mesa_image_address2d(packing
, pixels
, width
, height
,
408 for (row
= 0; row
< height
; row
++, y
++) {
410 /* Get float rgba pixels */
411 _swrast_read_rgba_span(ctx
, rb
, width
, x
, y
, GL_FLOAT
, rgba
);
413 /* apply fudge factor for shallow color buffers */
414 if ((fb
->Visual
.redBits
< 8 && fb
->Visual
.redBits
!= 0) ||
415 (fb
->Visual
.greenBits
< 8 && fb
->Visual
.greenBits
!= 0) ||
416 (fb
->Visual
.blueBits
< 8 && fb
->Visual
.blueBits
!= 0)) {
417 adjust_colors(fb
, width
, rgba
);
420 /* pack the row of RGBA pixels into user's buffer */
421 _mesa_pack_rgba_span_float(ctx
, width
, rgba
, format
, type
, dst
,
422 packing
, transferOps
);
430 * For a packed depth/stencil buffer being read as depth/stencil, just memcpy the
431 * data (possibly swapping 8/24 vs 24/8 as we go).
434 fast_read_depth_stencil_pixels(struct gl_context
*ctx
,
436 GLsizei width
, GLsizei height
,
437 GLvoid
*dst
, int dstStride
)
439 struct gl_framebuffer
*fb
= ctx
->ReadBuffer
;
440 struct gl_renderbuffer
*rb
= fb
->Attachment
[BUFFER_DEPTH
].Renderbuffer
;
441 struct gl_renderbuffer
*stencilRb
= fb
->Attachment
[BUFFER_STENCIL
].Renderbuffer
;
448 if (rb
->Format
!= MESA_FORMAT_Z24_S8
&&
449 rb
->Format
!= MESA_FORMAT_S8_Z24
)
452 ctx
->Driver
.MapRenderbuffer(ctx
, rb
, x
, y
, width
, height
, GL_MAP_READ_BIT
,
455 for (i
= 0; i
< height
; i
++) {
456 _mesa_unpack_uint_24_8_depth_stencil_row(rb
->Format
, width
,
462 ctx
->Driver
.UnmapRenderbuffer(ctx
, rb
);
469 * For non-float-depth and stencil buffers being read as 24/8 depth/stencil,
470 * copy the integer data directly instead of converting depth to float and
474 fast_read_depth_stencil_pixels_separate(struct gl_context
*ctx
,
476 GLsizei width
, GLsizei height
,
477 uint32_t *dst
, int dstStride
)
479 struct gl_framebuffer
*fb
= ctx
->ReadBuffer
;
480 struct gl_renderbuffer
*depthRb
= fb
->Attachment
[BUFFER_DEPTH
].Renderbuffer
;
481 struct gl_renderbuffer
*stencilRb
= fb
->Attachment
[BUFFER_STENCIL
].Renderbuffer
;
482 GLubyte
*depthMap
, *stencilMap
;
483 int depthStride
, stencilStride
, i
, j
;
485 if (_mesa_get_format_datatype(depthRb
->Format
) != GL_UNSIGNED_INT
)
488 ctx
->Driver
.MapRenderbuffer(ctx
, depthRb
, x
, y
, width
, height
,
489 GL_MAP_READ_BIT
, &depthMap
, &depthStride
);
490 ctx
->Driver
.MapRenderbuffer(ctx
, stencilRb
, x
, y
, width
, height
,
491 GL_MAP_READ_BIT
, &stencilMap
, &stencilStride
);
493 for (j
= 0; j
< height
; j
++) {
494 GLstencil stencilVals
[MAX_WIDTH
];
496 _mesa_unpack_uint_z_row(depthRb
->Format
, width
, depthMap
, dst
);
497 _mesa_unpack_ubyte_stencil_row(stencilRb
->Format
, width
,
498 stencilMap
, stencilVals
);
500 for (i
= 0; i
< width
; i
++) {
501 dst
[i
] = (dst
[i
] & 0xffffff00) | stencilVals
[i
];
504 depthMap
+= depthStride
;
505 stencilMap
+= stencilStride
;
506 dst
+= dstStride
/ 4;
509 ctx
->Driver
.UnmapRenderbuffer(ctx
, depthRb
);
510 ctx
->Driver
.UnmapRenderbuffer(ctx
, stencilRb
);
516 slow_read_depth_stencil_pixels_separate(struct gl_context
*ctx
,
518 GLsizei width
, GLsizei height
,
520 const struct gl_pixelstore_attrib
*packing
,
521 GLubyte
*dst
, int dstStride
)
523 struct gl_framebuffer
*fb
= ctx
->ReadBuffer
;
524 struct gl_renderbuffer
*depthRb
= fb
->Attachment
[BUFFER_DEPTH
].Renderbuffer
;
525 struct gl_renderbuffer
*stencilRb
= fb
->Attachment
[BUFFER_STENCIL
].Renderbuffer
;
526 GLubyte
*depthMap
, *stencilMap
;
527 int depthStride
, stencilStride
, j
;
529 ctx
->Driver
.MapRenderbuffer(ctx
, depthRb
, x
, y
, width
, height
,
530 GL_MAP_READ_BIT
, &depthMap
, &depthStride
);
531 ctx
->Driver
.MapRenderbuffer(ctx
, stencilRb
, x
, y
, width
, height
,
532 GL_MAP_READ_BIT
, &stencilMap
, &stencilStride
);
534 for (j
= 0; j
< height
; j
++) {
535 GLstencil stencilVals
[MAX_WIDTH
];
536 GLfloat depthVals
[MAX_WIDTH
];
538 _mesa_unpack_float_z_row(depthRb
->Format
, width
, depthMap
, depthVals
);
539 _mesa_unpack_ubyte_stencil_row(stencilRb
->Format
, width
,
540 stencilMap
, stencilVals
);
542 _mesa_pack_depth_stencil_span(ctx
, width
, type
, (GLuint
*)dst
,
543 depthVals
, stencilVals
, packing
);
545 depthMap
+= depthStride
;
546 stencilMap
+= stencilStride
;
550 ctx
->Driver
.UnmapRenderbuffer(ctx
, depthRb
);
551 ctx
->Driver
.UnmapRenderbuffer(ctx
, stencilRb
);
556 * Read combined depth/stencil values.
557 * We'll have already done error checking to be sure the expected
558 * depth and stencil buffers really exist.
561 read_depth_stencil_pixels(struct gl_context
*ctx
,
563 GLsizei width
, GLsizei height
,
564 GLenum type
, GLvoid
*pixels
,
565 const struct gl_pixelstore_attrib
*packing
)
567 const GLboolean scaleOrBias
568 = ctx
->Pixel
.DepthScale
!= 1.0 || ctx
->Pixel
.DepthBias
!= 0.0;
569 const GLboolean stencilTransfer
= ctx
->Pixel
.IndexShift
570 || ctx
->Pixel
.IndexOffset
|| ctx
->Pixel
.MapStencilFlag
;
574 dst
= (GLubyte
*) _mesa_image_address2d(packing
, pixels
,
576 GL_DEPTH_STENCIL_EXT
,
578 dstStride
= _mesa_image_row_stride(packing
, width
,
579 GL_DEPTH_STENCIL_EXT
, type
);
581 /* Fast 24/8 reads. */
582 if (type
== GL_UNSIGNED_INT_24_8
&&
583 !scaleOrBias
&& !stencilTransfer
&& !packing
->SwapBytes
) {
584 if (fast_read_depth_stencil_pixels(ctx
, x
, y
, width
, height
,
588 if (fast_read_depth_stencil_pixels_separate(ctx
, x
, y
, width
, height
,
589 (uint32_t *)dst
, dstStride
))
593 slow_read_depth_stencil_pixels_separate(ctx
, x
, y
, width
, height
,
601 * Software fallback routine for ctx->Driver.ReadPixels().
602 * By time we get here, all error checking will have been done.
605 _swrast_ReadPixels( struct gl_context
*ctx
,
606 GLint x
, GLint y
, GLsizei width
, GLsizei height
,
607 GLenum format
, GLenum type
,
608 const struct gl_pixelstore_attrib
*packing
,
611 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
612 struct gl_pixelstore_attrib clippedPacking
= *packing
;
615 _mesa_update_state(ctx
);
617 /* Need to do swrast_render_start() before clipping or anything else
618 * since this is where a driver may grab the hw lock and get an updated
621 swrast_render_start(ctx
);
623 if (swrast
->NewState
)
624 _swrast_validate_derived( ctx
);
626 /* Do all needed clipping here, so that we can forget about it later */
627 if (_mesa_clip_readpixels(ctx
, &x
, &y
, &width
, &height
, &clippedPacking
)) {
629 pixels
= _mesa_map_pbo_dest(ctx
, &clippedPacking
, pixels
);
633 case GL_STENCIL_INDEX
:
634 read_stencil_pixels(ctx
, x
, y
, width
, height
, type
, pixels
,
637 case GL_DEPTH_COMPONENT
:
638 read_depth_pixels(ctx
, x
, y
, width
, height
, type
, pixels
,
641 case GL_DEPTH_STENCIL_EXT
:
642 read_depth_stencil_pixels(ctx
, x
, y
, width
, height
, type
, pixels
,
646 /* all other formats should be color formats */
647 read_rgba_pixels(ctx
, x
, y
, width
, height
, format
, type
, pixels
,
651 _mesa_unmap_pbo_dest(ctx
, &clippedPacking
);
655 swrast_render_finish(ctx
);