xref: /aosp_15_r20/external/mesa3d/src/mesa/main/readpix.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker  * Mesa 3-D graphics library
3*61046927SAndroid Build Coastguard Worker  *
4*61046927SAndroid Build Coastguard Worker  * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved.
5*61046927SAndroid Build Coastguard Worker  *
6*61046927SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a
7*61046927SAndroid Build Coastguard Worker  * copy of this software and associated documentation files (the "Software"),
8*61046927SAndroid Build Coastguard Worker  * to deal in the Software without restriction, including without limitation
9*61046927SAndroid Build Coastguard Worker  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10*61046927SAndroid Build Coastguard Worker  * and/or sell copies of the Software, and to permit persons to whom the
11*61046927SAndroid Build Coastguard Worker  * Software is furnished to do so, subject to the following conditions:
12*61046927SAndroid Build Coastguard Worker  *
13*61046927SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice shall be included
14*61046927SAndroid Build Coastguard Worker  * in all copies or substantial portions of the Software.
15*61046927SAndroid Build Coastguard Worker  *
16*61046927SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17*61046927SAndroid Build Coastguard Worker  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18*61046927SAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19*61046927SAndroid Build Coastguard Worker  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20*61046927SAndroid Build Coastguard Worker  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21*61046927SAndroid Build Coastguard Worker  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22*61046927SAndroid Build Coastguard Worker  * OTHER DEALINGS IN THE SOFTWARE.
23*61046927SAndroid Build Coastguard Worker  */
24*61046927SAndroid Build Coastguard Worker 
25*61046927SAndroid Build Coastguard Worker #include "util/glheader.h"
26*61046927SAndroid Build Coastguard Worker 
27*61046927SAndroid Build Coastguard Worker #include "blend.h"
28*61046927SAndroid Build Coastguard Worker #include "bufferobj.h"
29*61046927SAndroid Build Coastguard Worker #include "context.h"
30*61046927SAndroid Build Coastguard Worker #include "enums.h"
31*61046927SAndroid Build Coastguard Worker #include "readpix.h"
32*61046927SAndroid Build Coastguard Worker #include "framebuffer.h"
33*61046927SAndroid Build Coastguard Worker #include "formats.h"
34*61046927SAndroid Build Coastguard Worker #include "format_unpack.h"
35*61046927SAndroid Build Coastguard Worker #include "image.h"
36*61046927SAndroid Build Coastguard Worker #include "mtypes.h"
37*61046927SAndroid Build Coastguard Worker #include "pack.h"
38*61046927SAndroid Build Coastguard Worker #include "pbo.h"
39*61046927SAndroid Build Coastguard Worker #include "pixel.h"
40*61046927SAndroid Build Coastguard Worker #include "renderbuffer.h"
41*61046927SAndroid Build Coastguard Worker #include "state.h"
42*61046927SAndroid Build Coastguard Worker #include "glformats.h"
43*61046927SAndroid Build Coastguard Worker #include "fbobject.h"
44*61046927SAndroid Build Coastguard Worker #include "format_utils.h"
45*61046927SAndroid Build Coastguard Worker #include "pixeltransfer.h"
46*61046927SAndroid Build Coastguard Worker #include "api_exec_decl.h"
47*61046927SAndroid Build Coastguard Worker 
48*61046927SAndroid Build Coastguard Worker #include "state_tracker/st_cb_readpixels.h"
49*61046927SAndroid Build Coastguard Worker 
50*61046927SAndroid Build Coastguard Worker /**
51*61046927SAndroid Build Coastguard Worker  * Return true if the conversion L=R+G+B is needed.
52*61046927SAndroid Build Coastguard Worker  */
53*61046927SAndroid Build Coastguard Worker GLboolean
_mesa_need_rgb_to_luminance_conversion(GLenum srcBaseFormat,GLenum dstBaseFormat)54*61046927SAndroid Build Coastguard Worker _mesa_need_rgb_to_luminance_conversion(GLenum srcBaseFormat,
55*61046927SAndroid Build Coastguard Worker                                        GLenum dstBaseFormat)
56*61046927SAndroid Build Coastguard Worker {
57*61046927SAndroid Build Coastguard Worker    return (srcBaseFormat == GL_RG ||
58*61046927SAndroid Build Coastguard Worker            srcBaseFormat == GL_RGB ||
59*61046927SAndroid Build Coastguard Worker            srcBaseFormat == GL_RGBA) &&
60*61046927SAndroid Build Coastguard Worker           (dstBaseFormat == GL_LUMINANCE ||
61*61046927SAndroid Build Coastguard Worker            dstBaseFormat == GL_LUMINANCE_ALPHA);
62*61046927SAndroid Build Coastguard Worker }
63*61046927SAndroid Build Coastguard Worker 
64*61046927SAndroid Build Coastguard Worker /**
65*61046927SAndroid Build Coastguard Worker  * Return true if the conversion L,I to RGB conversion is needed.
66*61046927SAndroid Build Coastguard Worker  */
67*61046927SAndroid Build Coastguard Worker GLboolean
_mesa_need_luminance_to_rgb_conversion(GLenum srcBaseFormat,GLenum dstBaseFormat)68*61046927SAndroid Build Coastguard Worker _mesa_need_luminance_to_rgb_conversion(GLenum srcBaseFormat,
69*61046927SAndroid Build Coastguard Worker                                        GLenum dstBaseFormat)
70*61046927SAndroid Build Coastguard Worker {
71*61046927SAndroid Build Coastguard Worker    return (srcBaseFormat == GL_LUMINANCE ||
72*61046927SAndroid Build Coastguard Worker            srcBaseFormat == GL_LUMINANCE_ALPHA ||
73*61046927SAndroid Build Coastguard Worker            srcBaseFormat == GL_INTENSITY) &&
74*61046927SAndroid Build Coastguard Worker           (dstBaseFormat == GL_GREEN ||
75*61046927SAndroid Build Coastguard Worker            dstBaseFormat == GL_BLUE ||
76*61046927SAndroid Build Coastguard Worker            dstBaseFormat == GL_RG ||
77*61046927SAndroid Build Coastguard Worker            dstBaseFormat == GL_RGB ||
78*61046927SAndroid Build Coastguard Worker            dstBaseFormat == GL_BGR ||
79*61046927SAndroid Build Coastguard Worker            dstBaseFormat == GL_RGBA ||
80*61046927SAndroid Build Coastguard Worker            dstBaseFormat == GL_BGRA);
81*61046927SAndroid Build Coastguard Worker }
82*61046927SAndroid Build Coastguard Worker 
83*61046927SAndroid Build Coastguard Worker /**
84*61046927SAndroid Build Coastguard Worker  * Return transfer op flags for this ReadPixels operation.
85*61046927SAndroid Build Coastguard Worker  */
86*61046927SAndroid Build Coastguard Worker GLbitfield
_mesa_get_readpixels_transfer_ops(const struct gl_context * ctx,mesa_format texFormat,GLenum format,GLenum type,GLboolean uses_blit)87*61046927SAndroid Build Coastguard Worker _mesa_get_readpixels_transfer_ops(const struct gl_context *ctx,
88*61046927SAndroid Build Coastguard Worker                                   mesa_format texFormat,
89*61046927SAndroid Build Coastguard Worker                                   GLenum format, GLenum type,
90*61046927SAndroid Build Coastguard Worker                                   GLboolean uses_blit)
91*61046927SAndroid Build Coastguard Worker {
92*61046927SAndroid Build Coastguard Worker    GLbitfield transferOps = ctx->_ImageTransferState;
93*61046927SAndroid Build Coastguard Worker    GLenum srcBaseFormat = _mesa_get_format_base_format(texFormat);
94*61046927SAndroid Build Coastguard Worker    GLenum dstBaseFormat = _mesa_unpack_format_to_base_format(format);
95*61046927SAndroid Build Coastguard Worker 
96*61046927SAndroid Build Coastguard Worker    if (format == GL_DEPTH_COMPONENT ||
97*61046927SAndroid Build Coastguard Worker        format == GL_DEPTH_STENCIL ||
98*61046927SAndroid Build Coastguard Worker        format == GL_STENCIL_INDEX) {
99*61046927SAndroid Build Coastguard Worker       return 0;
100*61046927SAndroid Build Coastguard Worker    }
101*61046927SAndroid Build Coastguard Worker 
102*61046927SAndroid Build Coastguard Worker    /* Pixel transfer ops (scale, bias, table lookup) do not apply
103*61046927SAndroid Build Coastguard Worker     * to integer formats.
104*61046927SAndroid Build Coastguard Worker     */
105*61046927SAndroid Build Coastguard Worker    if (_mesa_is_enum_format_integer(format)) {
106*61046927SAndroid Build Coastguard Worker       return 0;
107*61046927SAndroid Build Coastguard Worker    }
108*61046927SAndroid Build Coastguard Worker 
109*61046927SAndroid Build Coastguard Worker    /* If on OpenGL ES with GL_EXT_render_snorm, negative values should
110*61046927SAndroid Build Coastguard Worker     * not be clamped.
111*61046927SAndroid Build Coastguard Worker     */
112*61046927SAndroid Build Coastguard Worker    bool gles_snorm =
113*61046927SAndroid Build Coastguard Worker       _mesa_has_EXT_render_snorm(ctx) &&
114*61046927SAndroid Build Coastguard Worker       _mesa_get_format_datatype(texFormat) == GL_SIGNED_NORMALIZED;
115*61046927SAndroid Build Coastguard Worker 
116*61046927SAndroid Build Coastguard Worker    if (uses_blit) {
117*61046927SAndroid Build Coastguard Worker       /* For blit-based ReadPixels packing, the clamping is done automatically
118*61046927SAndroid Build Coastguard Worker        * unless the type is float. Disable clamping when on ES using snorm.
119*61046927SAndroid Build Coastguard Worker        */
120*61046927SAndroid Build Coastguard Worker       if (_mesa_get_clamp_read_color(ctx, ctx->ReadBuffer) &&
121*61046927SAndroid Build Coastguard Worker           !gles_snorm &&
122*61046927SAndroid Build Coastguard Worker           (type == GL_FLOAT || type == GL_HALF_FLOAT ||
123*61046927SAndroid Build Coastguard Worker            type == GL_UNSIGNED_INT_10F_11F_11F_REV)) {
124*61046927SAndroid Build Coastguard Worker          transferOps |= IMAGE_CLAMP_BIT;
125*61046927SAndroid Build Coastguard Worker       }
126*61046927SAndroid Build Coastguard Worker    }
127*61046927SAndroid Build Coastguard Worker    else {
128*61046927SAndroid Build Coastguard Worker       /* For CPU-based ReadPixels packing, the clamping must always be done
129*61046927SAndroid Build Coastguard Worker        * for non-float types, except on ES when using snorm types.
130*61046927SAndroid Build Coastguard Worker        */
131*61046927SAndroid Build Coastguard Worker       if ((_mesa_get_clamp_read_color(ctx, ctx->ReadBuffer) ||
132*61046927SAndroid Build Coastguard Worker            (type != GL_FLOAT && type != GL_HALF_FLOAT &&
133*61046927SAndroid Build Coastguard Worker             type != GL_UNSIGNED_INT_10F_11F_11F_REV)) && !gles_snorm) {
134*61046927SAndroid Build Coastguard Worker          transferOps |= IMAGE_CLAMP_BIT;
135*61046927SAndroid Build Coastguard Worker       }
136*61046927SAndroid Build Coastguard Worker 
137*61046927SAndroid Build Coastguard Worker       /* For SNORM formats we only clamp if `type` is signed and clamp is `true`
138*61046927SAndroid Build Coastguard Worker        * and when not on ES using snorm types.
139*61046927SAndroid Build Coastguard Worker        */
140*61046927SAndroid Build Coastguard Worker       if (!_mesa_get_clamp_read_color(ctx, ctx->ReadBuffer) &&
141*61046927SAndroid Build Coastguard Worker           !gles_snorm &&
142*61046927SAndroid Build Coastguard Worker           _mesa_get_format_datatype(texFormat) == GL_SIGNED_NORMALIZED &&
143*61046927SAndroid Build Coastguard Worker           (type == GL_BYTE || type == GL_SHORT || type == GL_INT)) {
144*61046927SAndroid Build Coastguard Worker          transferOps &= ~IMAGE_CLAMP_BIT;
145*61046927SAndroid Build Coastguard Worker       }
146*61046927SAndroid Build Coastguard Worker    }
147*61046927SAndroid Build Coastguard Worker 
148*61046927SAndroid Build Coastguard Worker    /* If the format is unsigned normalized, we can ignore clamping
149*61046927SAndroid Build Coastguard Worker     * because the values are already in the range [0,1] so it won't
150*61046927SAndroid Build Coastguard Worker     * have any effect anyway.
151*61046927SAndroid Build Coastguard Worker     */
152*61046927SAndroid Build Coastguard Worker    if (_mesa_get_format_datatype(texFormat) == GL_UNSIGNED_NORMALIZED &&
153*61046927SAndroid Build Coastguard Worker        !_mesa_need_rgb_to_luminance_conversion(srcBaseFormat, dstBaseFormat)) {
154*61046927SAndroid Build Coastguard Worker       transferOps &= ~IMAGE_CLAMP_BIT;
155*61046927SAndroid Build Coastguard Worker    }
156*61046927SAndroid Build Coastguard Worker 
157*61046927SAndroid Build Coastguard Worker    return transferOps;
158*61046927SAndroid Build Coastguard Worker }
159*61046927SAndroid Build Coastguard Worker 
160*61046927SAndroid Build Coastguard Worker 
161*61046927SAndroid Build Coastguard Worker /**
162*61046927SAndroid Build Coastguard Worker  * Return true if memcpy cannot be used for ReadPixels.
163*61046927SAndroid Build Coastguard Worker  *
164*61046927SAndroid Build Coastguard Worker  * If uses_blit is true, the function returns true if a simple 3D engine blit
165*61046927SAndroid Build Coastguard Worker  * cannot be used for ReadPixels packing.
166*61046927SAndroid Build Coastguard Worker  *
167*61046927SAndroid Build Coastguard Worker  * NOTE: This doesn't take swizzling and format conversions between
168*61046927SAndroid Build Coastguard Worker  *       the readbuffer and the pixel pack buffer into account.
169*61046927SAndroid Build Coastguard Worker  */
170*61046927SAndroid Build Coastguard Worker GLboolean
_mesa_readpixels_needs_slow_path(const struct gl_context * ctx,GLenum format,GLenum type,GLboolean uses_blit)171*61046927SAndroid Build Coastguard Worker _mesa_readpixels_needs_slow_path(const struct gl_context *ctx, GLenum format,
172*61046927SAndroid Build Coastguard Worker                                  GLenum type, GLboolean uses_blit)
173*61046927SAndroid Build Coastguard Worker {
174*61046927SAndroid Build Coastguard Worker    struct gl_renderbuffer *rb =
175*61046927SAndroid Build Coastguard Worker          _mesa_get_read_renderbuffer_for_format(ctx, format);
176*61046927SAndroid Build Coastguard Worker    GLenum dstBaseFormat = _mesa_unpack_format_to_base_format(format);
177*61046927SAndroid Build Coastguard Worker 
178*61046927SAndroid Build Coastguard Worker    assert(rb);
179*61046927SAndroid Build Coastguard Worker 
180*61046927SAndroid Build Coastguard Worker    /* There are different rules depending on the base format. */
181*61046927SAndroid Build Coastguard Worker    switch (format) {
182*61046927SAndroid Build Coastguard Worker    case GL_DEPTH_STENCIL:
183*61046927SAndroid Build Coastguard Worker       return !_mesa_has_depthstencil_combined(ctx->ReadBuffer) ||
184*61046927SAndroid Build Coastguard Worker              ctx->Pixel.DepthScale != 1.0f || ctx->Pixel.DepthBias != 0.0f ||
185*61046927SAndroid Build Coastguard Worker              ctx->Pixel.IndexShift || ctx->Pixel.IndexOffset ||
186*61046927SAndroid Build Coastguard Worker              ctx->Pixel.MapStencilFlag;
187*61046927SAndroid Build Coastguard Worker 
188*61046927SAndroid Build Coastguard Worker    case GL_DEPTH_COMPONENT:
189*61046927SAndroid Build Coastguard Worker       return ctx->Pixel.DepthScale != 1.0f || ctx->Pixel.DepthBias != 0.0f;
190*61046927SAndroid Build Coastguard Worker 
191*61046927SAndroid Build Coastguard Worker    case GL_STENCIL_INDEX:
192*61046927SAndroid Build Coastguard Worker       return ctx->Pixel.IndexShift || ctx->Pixel.IndexOffset ||
193*61046927SAndroid Build Coastguard Worker              ctx->Pixel.MapStencilFlag;
194*61046927SAndroid Build Coastguard Worker 
195*61046927SAndroid Build Coastguard Worker    default:
196*61046927SAndroid Build Coastguard Worker       /* Color formats. */
197*61046927SAndroid Build Coastguard Worker       if (_mesa_need_rgb_to_luminance_conversion(rb->_BaseFormat,
198*61046927SAndroid Build Coastguard Worker                                                  dstBaseFormat)) {
199*61046927SAndroid Build Coastguard Worker          return GL_TRUE;
200*61046927SAndroid Build Coastguard Worker       }
201*61046927SAndroid Build Coastguard Worker 
202*61046927SAndroid Build Coastguard Worker       /* And finally, see if there are any transfer ops. */
203*61046927SAndroid Build Coastguard Worker       return _mesa_get_readpixels_transfer_ops(ctx, rb->Format, format, type,
204*61046927SAndroid Build Coastguard Worker                                                uses_blit) != 0;
205*61046927SAndroid Build Coastguard Worker    }
206*61046927SAndroid Build Coastguard Worker    return GL_FALSE;
207*61046927SAndroid Build Coastguard Worker }
208*61046927SAndroid Build Coastguard Worker 
209*61046927SAndroid Build Coastguard Worker 
210*61046927SAndroid Build Coastguard Worker static GLboolean
readpixels_can_use_memcpy(const struct gl_context * ctx,GLenum format,GLenum type,const struct gl_pixelstore_attrib * packing)211*61046927SAndroid Build Coastguard Worker readpixels_can_use_memcpy(const struct gl_context *ctx, GLenum format, GLenum type,
212*61046927SAndroid Build Coastguard Worker                           const struct gl_pixelstore_attrib *packing)
213*61046927SAndroid Build Coastguard Worker {
214*61046927SAndroid Build Coastguard Worker    struct gl_renderbuffer *rb =
215*61046927SAndroid Build Coastguard Worker          _mesa_get_read_renderbuffer_for_format(ctx, format);
216*61046927SAndroid Build Coastguard Worker 
217*61046927SAndroid Build Coastguard Worker    assert(rb);
218*61046927SAndroid Build Coastguard Worker 
219*61046927SAndroid Build Coastguard Worker    if (_mesa_readpixels_needs_slow_path(ctx, format, type, GL_FALSE)) {
220*61046927SAndroid Build Coastguard Worker       return GL_FALSE;
221*61046927SAndroid Build Coastguard Worker    }
222*61046927SAndroid Build Coastguard Worker 
223*61046927SAndroid Build Coastguard Worker    /* The base internal format and the base Mesa format must match. */
224*61046927SAndroid Build Coastguard Worker    if (rb->_BaseFormat != _mesa_get_format_base_format(rb->Format)) {
225*61046927SAndroid Build Coastguard Worker       return GL_FALSE;
226*61046927SAndroid Build Coastguard Worker    }
227*61046927SAndroid Build Coastguard Worker 
228*61046927SAndroid Build Coastguard Worker    /* The Mesa format must match the input format and type. */
229*61046927SAndroid Build Coastguard Worker    if (!_mesa_format_matches_format_and_type(rb->Format, format, type,
230*61046927SAndroid Build Coastguard Worker                                              packing->SwapBytes, NULL)) {
231*61046927SAndroid Build Coastguard Worker       return GL_FALSE;
232*61046927SAndroid Build Coastguard Worker    }
233*61046927SAndroid Build Coastguard Worker 
234*61046927SAndroid Build Coastguard Worker    return GL_TRUE;
235*61046927SAndroid Build Coastguard Worker }
236*61046927SAndroid Build Coastguard Worker 
237*61046927SAndroid Build Coastguard Worker 
238*61046927SAndroid Build Coastguard Worker static GLboolean
readpixels_memcpy(struct gl_context * ctx,GLint x,GLint y,GLsizei width,GLsizei height,GLenum format,GLenum type,GLvoid * pixels,const struct gl_pixelstore_attrib * packing)239*61046927SAndroid Build Coastguard Worker readpixels_memcpy(struct gl_context *ctx,
240*61046927SAndroid Build Coastguard Worker                   GLint x, GLint y,
241*61046927SAndroid Build Coastguard Worker                   GLsizei width, GLsizei height,
242*61046927SAndroid Build Coastguard Worker                   GLenum format, GLenum type,
243*61046927SAndroid Build Coastguard Worker                   GLvoid *pixels,
244*61046927SAndroid Build Coastguard Worker                   const struct gl_pixelstore_attrib *packing)
245*61046927SAndroid Build Coastguard Worker {
246*61046927SAndroid Build Coastguard Worker    struct gl_renderbuffer *rb =
247*61046927SAndroid Build Coastguard Worker          _mesa_get_read_renderbuffer_for_format(ctx, format);
248*61046927SAndroid Build Coastguard Worker    GLubyte *dst, *map;
249*61046927SAndroid Build Coastguard Worker    int dstStride, stride, j, texelBytes, bytesPerRow;
250*61046927SAndroid Build Coastguard Worker 
251*61046927SAndroid Build Coastguard Worker    /* Fail if memcpy cannot be used. */
252*61046927SAndroid Build Coastguard Worker    if (!readpixels_can_use_memcpy(ctx, format, type, packing)) {
253*61046927SAndroid Build Coastguard Worker       return GL_FALSE;
254*61046927SAndroid Build Coastguard Worker    }
255*61046927SAndroid Build Coastguard Worker 
256*61046927SAndroid Build Coastguard Worker    dstStride = _mesa_image_row_stride(packing, width, format, type);
257*61046927SAndroid Build Coastguard Worker    dst = (GLubyte *) _mesa_image_address2d(packing, pixels, width, height,
258*61046927SAndroid Build Coastguard Worker 					   format, type, 0, 0);
259*61046927SAndroid Build Coastguard Worker 
260*61046927SAndroid Build Coastguard Worker    _mesa_map_renderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT,
261*61046927SAndroid Build Coastguard Worker                       &map, &stride, ctx->ReadBuffer->FlipY);
262*61046927SAndroid Build Coastguard Worker    if (!map) {
263*61046927SAndroid Build Coastguard Worker       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
264*61046927SAndroid Build Coastguard Worker       return GL_TRUE;  /* don't bother trying the slow path */
265*61046927SAndroid Build Coastguard Worker    }
266*61046927SAndroid Build Coastguard Worker 
267*61046927SAndroid Build Coastguard Worker    texelBytes = _mesa_get_format_bytes(rb->Format);
268*61046927SAndroid Build Coastguard Worker    bytesPerRow = texelBytes * width;
269*61046927SAndroid Build Coastguard Worker 
270*61046927SAndroid Build Coastguard Worker    /* memcpy*/
271*61046927SAndroid Build Coastguard Worker    if (dstStride == stride && dstStride == bytesPerRow) {
272*61046927SAndroid Build Coastguard Worker       memcpy(dst, map, bytesPerRow * height);
273*61046927SAndroid Build Coastguard Worker    } else {
274*61046927SAndroid Build Coastguard Worker       for (j = 0; j < height; j++) {
275*61046927SAndroid Build Coastguard Worker          memcpy(dst, map, bytesPerRow);
276*61046927SAndroid Build Coastguard Worker          dst += dstStride;
277*61046927SAndroid Build Coastguard Worker          map += stride;
278*61046927SAndroid Build Coastguard Worker       }
279*61046927SAndroid Build Coastguard Worker    }
280*61046927SAndroid Build Coastguard Worker 
281*61046927SAndroid Build Coastguard Worker    _mesa_unmap_renderbuffer(ctx, rb);
282*61046927SAndroid Build Coastguard Worker    return GL_TRUE;
283*61046927SAndroid Build Coastguard Worker }
284*61046927SAndroid Build Coastguard Worker 
285*61046927SAndroid Build Coastguard Worker 
286*61046927SAndroid Build Coastguard Worker /**
287*61046927SAndroid Build Coastguard Worker  * Optimized path for conversion of depth values to GL_DEPTH_COMPONENT,
288*61046927SAndroid Build Coastguard Worker  * GL_UNSIGNED_INT.
289*61046927SAndroid Build Coastguard Worker  */
290*61046927SAndroid Build Coastguard Worker static GLboolean
read_uint_depth_pixels(struct gl_context * ctx,GLint x,GLint y,GLsizei width,GLsizei height,GLenum type,GLvoid * pixels,const struct gl_pixelstore_attrib * packing)291*61046927SAndroid Build Coastguard Worker read_uint_depth_pixels( struct gl_context *ctx,
292*61046927SAndroid Build Coastguard Worker 			GLint x, GLint y,
293*61046927SAndroid Build Coastguard Worker 			GLsizei width, GLsizei height,
294*61046927SAndroid Build Coastguard Worker 			GLenum type, GLvoid *pixels,
295*61046927SAndroid Build Coastguard Worker 			const struct gl_pixelstore_attrib *packing )
296*61046927SAndroid Build Coastguard Worker {
297*61046927SAndroid Build Coastguard Worker    struct gl_framebuffer *fb = ctx->ReadBuffer;
298*61046927SAndroid Build Coastguard Worker    struct gl_renderbuffer *rb = fb->Attachment[BUFFER_DEPTH].Renderbuffer;
299*61046927SAndroid Build Coastguard Worker    GLubyte *map, *dst;
300*61046927SAndroid Build Coastguard Worker    int stride, dstStride, j;
301*61046927SAndroid Build Coastguard Worker 
302*61046927SAndroid Build Coastguard Worker    if (ctx->Pixel.DepthScale != 1.0F || ctx->Pixel.DepthBias != 0.0F)
303*61046927SAndroid Build Coastguard Worker       return GL_FALSE;
304*61046927SAndroid Build Coastguard Worker 
305*61046927SAndroid Build Coastguard Worker    if (packing->SwapBytes)
306*61046927SAndroid Build Coastguard Worker       return GL_FALSE;
307*61046927SAndroid Build Coastguard Worker 
308*61046927SAndroid Build Coastguard Worker    if (_mesa_get_format_datatype(rb->Format) != GL_UNSIGNED_NORMALIZED)
309*61046927SAndroid Build Coastguard Worker       return GL_FALSE;
310*61046927SAndroid Build Coastguard Worker 
311*61046927SAndroid Build Coastguard Worker    _mesa_map_renderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT,
312*61046927SAndroid Build Coastguard Worker                       &map, &stride, fb->FlipY);
313*61046927SAndroid Build Coastguard Worker 
314*61046927SAndroid Build Coastguard Worker    if (!map) {
315*61046927SAndroid Build Coastguard Worker       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
316*61046927SAndroid Build Coastguard Worker       return GL_TRUE;  /* don't bother trying the slow path */
317*61046927SAndroid Build Coastguard Worker    }
318*61046927SAndroid Build Coastguard Worker 
319*61046927SAndroid Build Coastguard Worker    dstStride = _mesa_image_row_stride(packing, width, GL_DEPTH_COMPONENT, type);
320*61046927SAndroid Build Coastguard Worker    dst = (GLubyte *) _mesa_image_address2d(packing, pixels, width, height,
321*61046927SAndroid Build Coastguard Worker 					   GL_DEPTH_COMPONENT, type, 0, 0);
322*61046927SAndroid Build Coastguard Worker 
323*61046927SAndroid Build Coastguard Worker    for (j = 0; j < height; j++) {
324*61046927SAndroid Build Coastguard Worker       _mesa_unpack_uint_z_row(rb->Format, width, map, (GLuint *)dst);
325*61046927SAndroid Build Coastguard Worker 
326*61046927SAndroid Build Coastguard Worker       map += stride;
327*61046927SAndroid Build Coastguard Worker       dst += dstStride;
328*61046927SAndroid Build Coastguard Worker    }
329*61046927SAndroid Build Coastguard Worker    _mesa_unmap_renderbuffer(ctx, rb);
330*61046927SAndroid Build Coastguard Worker 
331*61046927SAndroid Build Coastguard Worker    return GL_TRUE;
332*61046927SAndroid Build Coastguard Worker }
333*61046927SAndroid Build Coastguard Worker 
334*61046927SAndroid Build Coastguard Worker /**
335*61046927SAndroid Build Coastguard Worker  * Read pixels for format=GL_DEPTH_COMPONENT.
336*61046927SAndroid Build Coastguard Worker  */
337*61046927SAndroid Build Coastguard Worker static void
read_depth_pixels(struct gl_context * ctx,GLint x,GLint y,GLsizei width,GLsizei height,GLenum type,GLvoid * pixels,const struct gl_pixelstore_attrib * packing)338*61046927SAndroid Build Coastguard Worker read_depth_pixels( struct gl_context *ctx,
339*61046927SAndroid Build Coastguard Worker                    GLint x, GLint y,
340*61046927SAndroid Build Coastguard Worker                    GLsizei width, GLsizei height,
341*61046927SAndroid Build Coastguard Worker                    GLenum type, GLvoid *pixels,
342*61046927SAndroid Build Coastguard Worker                    const struct gl_pixelstore_attrib *packing )
343*61046927SAndroid Build Coastguard Worker {
344*61046927SAndroid Build Coastguard Worker    struct gl_framebuffer *fb = ctx->ReadBuffer;
345*61046927SAndroid Build Coastguard Worker    struct gl_renderbuffer *rb = fb->Attachment[BUFFER_DEPTH].Renderbuffer;
346*61046927SAndroid Build Coastguard Worker    GLint j;
347*61046927SAndroid Build Coastguard Worker    GLubyte *dst, *map;
348*61046927SAndroid Build Coastguard Worker    int dstStride, stride;
349*61046927SAndroid Build Coastguard Worker    GLfloat *depthValues;
350*61046927SAndroid Build Coastguard Worker 
351*61046927SAndroid Build Coastguard Worker    if (!rb)
352*61046927SAndroid Build Coastguard Worker       return;
353*61046927SAndroid Build Coastguard Worker 
354*61046927SAndroid Build Coastguard Worker    /* clipping should have been done already */
355*61046927SAndroid Build Coastguard Worker    assert(x >= 0);
356*61046927SAndroid Build Coastguard Worker    assert(y >= 0);
357*61046927SAndroid Build Coastguard Worker    assert(x + width <= (GLint) rb->Width);
358*61046927SAndroid Build Coastguard Worker    assert(y + height <= (GLint) rb->Height);
359*61046927SAndroid Build Coastguard Worker 
360*61046927SAndroid Build Coastguard Worker    if (type == GL_UNSIGNED_INT &&
361*61046927SAndroid Build Coastguard Worker        read_uint_depth_pixels(ctx, x, y, width, height, type, pixels, packing)) {
362*61046927SAndroid Build Coastguard Worker       return;
363*61046927SAndroid Build Coastguard Worker    }
364*61046927SAndroid Build Coastguard Worker 
365*61046927SAndroid Build Coastguard Worker    dstStride = _mesa_image_row_stride(packing, width, GL_DEPTH_COMPONENT, type);
366*61046927SAndroid Build Coastguard Worker    dst = (GLubyte *) _mesa_image_address2d(packing, pixels, width, height,
367*61046927SAndroid Build Coastguard Worker 					   GL_DEPTH_COMPONENT, type, 0, 0);
368*61046927SAndroid Build Coastguard Worker 
369*61046927SAndroid Build Coastguard Worker    _mesa_map_renderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT,
370*61046927SAndroid Build Coastguard Worker                       &map, &stride, fb->FlipY);
371*61046927SAndroid Build Coastguard Worker    if (!map) {
372*61046927SAndroid Build Coastguard Worker       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
373*61046927SAndroid Build Coastguard Worker       return;
374*61046927SAndroid Build Coastguard Worker    }
375*61046927SAndroid Build Coastguard Worker 
376*61046927SAndroid Build Coastguard Worker    depthValues = malloc(width * sizeof(GLfloat));
377*61046927SAndroid Build Coastguard Worker 
378*61046927SAndroid Build Coastguard Worker    if (depthValues) {
379*61046927SAndroid Build Coastguard Worker       /* General case (slower) */
380*61046927SAndroid Build Coastguard Worker       for (j = 0; j < height; j++, y++) {
381*61046927SAndroid Build Coastguard Worker          _mesa_unpack_float_z_row(rb->Format, width, map, depthValues);
382*61046927SAndroid Build Coastguard Worker          _mesa_pack_depth_span(ctx, width, dst, type, depthValues, packing);
383*61046927SAndroid Build Coastguard Worker 
384*61046927SAndroid Build Coastguard Worker          dst += dstStride;
385*61046927SAndroid Build Coastguard Worker          map += stride;
386*61046927SAndroid Build Coastguard Worker       }
387*61046927SAndroid Build Coastguard Worker    }
388*61046927SAndroid Build Coastguard Worker    else {
389*61046927SAndroid Build Coastguard Worker       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
390*61046927SAndroid Build Coastguard Worker    }
391*61046927SAndroid Build Coastguard Worker 
392*61046927SAndroid Build Coastguard Worker    free(depthValues);
393*61046927SAndroid Build Coastguard Worker 
394*61046927SAndroid Build Coastguard Worker    _mesa_unmap_renderbuffer(ctx, rb);
395*61046927SAndroid Build Coastguard Worker }
396*61046927SAndroid Build Coastguard Worker 
397*61046927SAndroid Build Coastguard Worker 
398*61046927SAndroid Build Coastguard Worker /**
399*61046927SAndroid Build Coastguard Worker  * Read pixels for format=GL_STENCIL_INDEX.
400*61046927SAndroid Build Coastguard Worker  */
401*61046927SAndroid Build Coastguard Worker static void
read_stencil_pixels(struct gl_context * ctx,GLint x,GLint y,GLsizei width,GLsizei height,GLenum type,GLvoid * pixels,const struct gl_pixelstore_attrib * packing)402*61046927SAndroid Build Coastguard Worker read_stencil_pixels( struct gl_context *ctx,
403*61046927SAndroid Build Coastguard Worker                      GLint x, GLint y,
404*61046927SAndroid Build Coastguard Worker                      GLsizei width, GLsizei height,
405*61046927SAndroid Build Coastguard Worker                      GLenum type, GLvoid *pixels,
406*61046927SAndroid Build Coastguard Worker                      const struct gl_pixelstore_attrib *packing )
407*61046927SAndroid Build Coastguard Worker {
408*61046927SAndroid Build Coastguard Worker    struct gl_framebuffer *fb = ctx->ReadBuffer;
409*61046927SAndroid Build Coastguard Worker    struct gl_renderbuffer *rb = fb->Attachment[BUFFER_STENCIL].Renderbuffer;
410*61046927SAndroid Build Coastguard Worker    GLint j;
411*61046927SAndroid Build Coastguard Worker    GLubyte *map, *stencil;
412*61046927SAndroid Build Coastguard Worker    GLint stride;
413*61046927SAndroid Build Coastguard Worker 
414*61046927SAndroid Build Coastguard Worker    if (!rb)
415*61046927SAndroid Build Coastguard Worker       return;
416*61046927SAndroid Build Coastguard Worker 
417*61046927SAndroid Build Coastguard Worker    _mesa_map_renderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT,
418*61046927SAndroid Build Coastguard Worker                       &map, &stride, fb->FlipY);
419*61046927SAndroid Build Coastguard Worker    if (!map) {
420*61046927SAndroid Build Coastguard Worker       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
421*61046927SAndroid Build Coastguard Worker       return;
422*61046927SAndroid Build Coastguard Worker    }
423*61046927SAndroid Build Coastguard Worker 
424*61046927SAndroid Build Coastguard Worker    stencil = malloc(width * sizeof(GLubyte));
425*61046927SAndroid Build Coastguard Worker 
426*61046927SAndroid Build Coastguard Worker    if (stencil) {
427*61046927SAndroid Build Coastguard Worker       /* process image row by row */
428*61046927SAndroid Build Coastguard Worker       for (j = 0; j < height; j++) {
429*61046927SAndroid Build Coastguard Worker          GLvoid *dest;
430*61046927SAndroid Build Coastguard Worker 
431*61046927SAndroid Build Coastguard Worker          _mesa_unpack_ubyte_stencil_row(rb->Format, width, map, stencil);
432*61046927SAndroid Build Coastguard Worker          dest = _mesa_image_address2d(packing, pixels, width, height,
433*61046927SAndroid Build Coastguard Worker                                       GL_STENCIL_INDEX, type, j, 0);
434*61046927SAndroid Build Coastguard Worker 
435*61046927SAndroid Build Coastguard Worker          _mesa_pack_stencil_span(ctx, width, type, dest, stencil, packing);
436*61046927SAndroid Build Coastguard Worker 
437*61046927SAndroid Build Coastguard Worker          map += stride;
438*61046927SAndroid Build Coastguard Worker       }
439*61046927SAndroid Build Coastguard Worker    }
440*61046927SAndroid Build Coastguard Worker    else {
441*61046927SAndroid Build Coastguard Worker       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
442*61046927SAndroid Build Coastguard Worker    }
443*61046927SAndroid Build Coastguard Worker 
444*61046927SAndroid Build Coastguard Worker    free(stencil);
445*61046927SAndroid Build Coastguard Worker 
446*61046927SAndroid Build Coastguard Worker    _mesa_unmap_renderbuffer(ctx, rb);
447*61046927SAndroid Build Coastguard Worker }
448*61046927SAndroid Build Coastguard Worker 
449*61046927SAndroid Build Coastguard Worker /*
450*61046927SAndroid Build Coastguard Worker  * Read R, G, B, A, RGB, L, or LA pixels.
451*61046927SAndroid Build Coastguard Worker  */
452*61046927SAndroid Build Coastguard Worker static void
read_rgba_pixels(struct gl_context * ctx,GLint x,GLint y,GLsizei width,GLsizei height,GLenum format,GLenum type,GLvoid * pixels,const struct gl_pixelstore_attrib * packing)453*61046927SAndroid Build Coastguard Worker read_rgba_pixels( struct gl_context *ctx,
454*61046927SAndroid Build Coastguard Worker                   GLint x, GLint y,
455*61046927SAndroid Build Coastguard Worker                   GLsizei width, GLsizei height,
456*61046927SAndroid Build Coastguard Worker                   GLenum format, GLenum type, GLvoid *pixels,
457*61046927SAndroid Build Coastguard Worker                   const struct gl_pixelstore_attrib *packing )
458*61046927SAndroid Build Coastguard Worker {
459*61046927SAndroid Build Coastguard Worker    GLbitfield transferOps;
460*61046927SAndroid Build Coastguard Worker    bool dst_is_integer, convert_rgb_to_lum, needs_rebase;
461*61046927SAndroid Build Coastguard Worker    int dst_stride, src_stride, rb_stride;
462*61046927SAndroid Build Coastguard Worker    uint32_t dst_format, src_format;
463*61046927SAndroid Build Coastguard Worker    GLubyte *dst, *map;
464*61046927SAndroid Build Coastguard Worker    mesa_format rb_format;
465*61046927SAndroid Build Coastguard Worker    bool needs_rgba;
466*61046927SAndroid Build Coastguard Worker    void *rgba, *src;
467*61046927SAndroid Build Coastguard Worker    bool src_is_uint = false;
468*61046927SAndroid Build Coastguard Worker    uint8_t rebase_swizzle[4];
469*61046927SAndroid Build Coastguard Worker    struct gl_framebuffer *fb = ctx->ReadBuffer;
470*61046927SAndroid Build Coastguard Worker    struct gl_renderbuffer *rb = fb->_ColorReadBuffer;
471*61046927SAndroid Build Coastguard Worker    GLenum dstBaseFormat = _mesa_unpack_format_to_base_format(format);
472*61046927SAndroid Build Coastguard Worker 
473*61046927SAndroid Build Coastguard Worker    if (!rb)
474*61046927SAndroid Build Coastguard Worker       return;
475*61046927SAndroid Build Coastguard Worker 
476*61046927SAndroid Build Coastguard Worker    transferOps = _mesa_get_readpixels_transfer_ops(ctx, rb->Format, format,
477*61046927SAndroid Build Coastguard Worker                                                    type, GL_FALSE);
478*61046927SAndroid Build Coastguard Worker    /* Describe the dst format */
479*61046927SAndroid Build Coastguard Worker    dst_is_integer = _mesa_is_enum_format_integer(format);
480*61046927SAndroid Build Coastguard Worker    dst_stride = _mesa_image_row_stride(packing, width, format, type);
481*61046927SAndroid Build Coastguard Worker    dst_format = _mesa_format_from_format_and_type(format, type);
482*61046927SAndroid Build Coastguard Worker    convert_rgb_to_lum =
483*61046927SAndroid Build Coastguard Worker       _mesa_need_rgb_to_luminance_conversion(rb->_BaseFormat, dstBaseFormat);
484*61046927SAndroid Build Coastguard Worker    dst = (GLubyte *) _mesa_image_address2d(packing, pixels, width, height,
485*61046927SAndroid Build Coastguard Worker                                            format, type, 0, 0);
486*61046927SAndroid Build Coastguard Worker 
487*61046927SAndroid Build Coastguard Worker    /* Map the source render buffer */
488*61046927SAndroid Build Coastguard Worker    _mesa_map_renderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT,
489*61046927SAndroid Build Coastguard Worker                       &map, &rb_stride, fb->FlipY);
490*61046927SAndroid Build Coastguard Worker    if (!map) {
491*61046927SAndroid Build Coastguard Worker       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
492*61046927SAndroid Build Coastguard Worker       return;
493*61046927SAndroid Build Coastguard Worker    }
494*61046927SAndroid Build Coastguard Worker    rb_format = _mesa_get_srgb_format_linear(rb->Format);
495*61046927SAndroid Build Coastguard Worker 
496*61046927SAndroid Build Coastguard Worker    /*
497*61046927SAndroid Build Coastguard Worker     * Depending on the base formats involved in the conversion we might need to
498*61046927SAndroid Build Coastguard Worker     * rebase some values, so for these formats we compute a rebase swizzle.
499*61046927SAndroid Build Coastguard Worker     */
500*61046927SAndroid Build Coastguard Worker    if (rb->_BaseFormat == GL_LUMINANCE || rb->_BaseFormat == GL_INTENSITY) {
501*61046927SAndroid Build Coastguard Worker       needs_rebase = true;
502*61046927SAndroid Build Coastguard Worker       rebase_swizzle[0] = MESA_FORMAT_SWIZZLE_X;
503*61046927SAndroid Build Coastguard Worker       rebase_swizzle[1] = MESA_FORMAT_SWIZZLE_ZERO;
504*61046927SAndroid Build Coastguard Worker       rebase_swizzle[2] = MESA_FORMAT_SWIZZLE_ZERO;
505*61046927SAndroid Build Coastguard Worker       rebase_swizzle[3] = MESA_FORMAT_SWIZZLE_ONE;
506*61046927SAndroid Build Coastguard Worker    } else if (rb->_BaseFormat == GL_LUMINANCE_ALPHA) {
507*61046927SAndroid Build Coastguard Worker       needs_rebase = true;
508*61046927SAndroid Build Coastguard Worker       rebase_swizzle[0] = MESA_FORMAT_SWIZZLE_X;
509*61046927SAndroid Build Coastguard Worker       rebase_swizzle[1] = MESA_FORMAT_SWIZZLE_ZERO;
510*61046927SAndroid Build Coastguard Worker       rebase_swizzle[2] = MESA_FORMAT_SWIZZLE_ZERO;
511*61046927SAndroid Build Coastguard Worker       rebase_swizzle[3] = MESA_FORMAT_SWIZZLE_W;
512*61046927SAndroid Build Coastguard Worker    } else if (_mesa_get_format_base_format(rb_format) != rb->_BaseFormat) {
513*61046927SAndroid Build Coastguard Worker       needs_rebase =
514*61046927SAndroid Build Coastguard Worker          _mesa_compute_rgba2base2rgba_component_mapping(rb->_BaseFormat,
515*61046927SAndroid Build Coastguard Worker                                                         rebase_swizzle);
516*61046927SAndroid Build Coastguard Worker    } else {
517*61046927SAndroid Build Coastguard Worker       needs_rebase = false;
518*61046927SAndroid Build Coastguard Worker    }
519*61046927SAndroid Build Coastguard Worker 
520*61046927SAndroid Build Coastguard Worker    /* Since _mesa_format_convert does not handle transferOps we need to handle
521*61046927SAndroid Build Coastguard Worker     * them before we call the function. This requires to convert to RGBA float
522*61046927SAndroid Build Coastguard Worker     * first so we can call _mesa_apply_rgba_transfer_ops. If the dst format is
523*61046927SAndroid Build Coastguard Worker     * integer transferOps do not apply.
524*61046927SAndroid Build Coastguard Worker     *
525*61046927SAndroid Build Coastguard Worker     * Converting to luminance also requires converting to RGBA first, so we can
526*61046927SAndroid Build Coastguard Worker     * then compute luminance values as L=R+G+B. Notice that this is different
527*61046927SAndroid Build Coastguard Worker     * from GetTexImage, where we compute L=R.
528*61046927SAndroid Build Coastguard Worker     */
529*61046927SAndroid Build Coastguard Worker    assert(!transferOps || (transferOps && !dst_is_integer));
530*61046927SAndroid Build Coastguard Worker 
531*61046927SAndroid Build Coastguard Worker    needs_rgba = transferOps || convert_rgb_to_lum;
532*61046927SAndroid Build Coastguard Worker    rgba = NULL;
533*61046927SAndroid Build Coastguard Worker    if (needs_rgba) {
534*61046927SAndroid Build Coastguard Worker       uint32_t rgba_format;
535*61046927SAndroid Build Coastguard Worker       int rgba_stride;
536*61046927SAndroid Build Coastguard Worker       bool need_convert;
537*61046927SAndroid Build Coastguard Worker 
538*61046927SAndroid Build Coastguard Worker       /* Convert to RGBA float or int/uint depending on the type of the src */
539*61046927SAndroid Build Coastguard Worker       if (dst_is_integer) {
540*61046927SAndroid Build Coastguard Worker          src_is_uint = _mesa_is_format_unsigned(rb_format);
541*61046927SAndroid Build Coastguard Worker          if (src_is_uint) {
542*61046927SAndroid Build Coastguard Worker             rgba_format = RGBA32_UINT;
543*61046927SAndroid Build Coastguard Worker             rgba_stride = width * 4 * sizeof(GLuint);
544*61046927SAndroid Build Coastguard Worker          } else {
545*61046927SAndroid Build Coastguard Worker             rgba_format = RGBA32_INT;
546*61046927SAndroid Build Coastguard Worker             rgba_stride = width * 4 * sizeof(GLint);
547*61046927SAndroid Build Coastguard Worker          }
548*61046927SAndroid Build Coastguard Worker       } else {
549*61046927SAndroid Build Coastguard Worker          rgba_format = RGBA32_FLOAT;
550*61046927SAndroid Build Coastguard Worker          rgba_stride = width * 4 * sizeof(GLfloat);
551*61046927SAndroid Build Coastguard Worker       }
552*61046927SAndroid Build Coastguard Worker 
553*61046927SAndroid Build Coastguard Worker       /* If we are lucky and the dst format matches the RGBA format we need to
554*61046927SAndroid Build Coastguard Worker        * convert to, then we can convert directly into the dst buffer and avoid
555*61046927SAndroid Build Coastguard Worker        * the final conversion/copy from the rgba buffer to the dst buffer.
556*61046927SAndroid Build Coastguard Worker        */
557*61046927SAndroid Build Coastguard Worker       if (dst_format == rgba_format &&
558*61046927SAndroid Build Coastguard Worker           dst_stride == rgba_stride) {
559*61046927SAndroid Build Coastguard Worker          need_convert = false;
560*61046927SAndroid Build Coastguard Worker          rgba = dst;
561*61046927SAndroid Build Coastguard Worker       } else {
562*61046927SAndroid Build Coastguard Worker          need_convert = true;
563*61046927SAndroid Build Coastguard Worker          rgba = malloc(height * rgba_stride);
564*61046927SAndroid Build Coastguard Worker          if (!rgba) {
565*61046927SAndroid Build Coastguard Worker             _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
566*61046927SAndroid Build Coastguard Worker             goto done_unmap;
567*61046927SAndroid Build Coastguard Worker          }
568*61046927SAndroid Build Coastguard Worker       }
569*61046927SAndroid Build Coastguard Worker 
570*61046927SAndroid Build Coastguard Worker       /* Convert to RGBA now */
571*61046927SAndroid Build Coastguard Worker       _mesa_format_convert(rgba, rgba_format, rgba_stride,
572*61046927SAndroid Build Coastguard Worker                            map, rb_format, rb_stride,
573*61046927SAndroid Build Coastguard Worker                            width, height,
574*61046927SAndroid Build Coastguard Worker                            needs_rebase ? rebase_swizzle : NULL);
575*61046927SAndroid Build Coastguard Worker 
576*61046927SAndroid Build Coastguard Worker       /* Handle transfer ops if necessary */
577*61046927SAndroid Build Coastguard Worker       if (transferOps)
578*61046927SAndroid Build Coastguard Worker          _mesa_apply_rgba_transfer_ops(ctx, transferOps, width * height, rgba);
579*61046927SAndroid Build Coastguard Worker 
580*61046927SAndroid Build Coastguard Worker       /* If we had to rebase, we have already taken care of that */
581*61046927SAndroid Build Coastguard Worker       needs_rebase = false;
582*61046927SAndroid Build Coastguard Worker 
583*61046927SAndroid Build Coastguard Worker       /* If we were lucky and our RGBA conversion matches the dst format, then
584*61046927SAndroid Build Coastguard Worker        * we are done.
585*61046927SAndroid Build Coastguard Worker        */
586*61046927SAndroid Build Coastguard Worker       if (!need_convert)
587*61046927SAndroid Build Coastguard Worker          goto done_swap;
588*61046927SAndroid Build Coastguard Worker 
589*61046927SAndroid Build Coastguard Worker       /* Otherwise, we need to convert from RGBA to dst next */
590*61046927SAndroid Build Coastguard Worker       src = rgba;
591*61046927SAndroid Build Coastguard Worker       src_format = rgba_format;
592*61046927SAndroid Build Coastguard Worker       src_stride = rgba_stride;
593*61046927SAndroid Build Coastguard Worker    } else {
594*61046927SAndroid Build Coastguard Worker       /* No RGBA conversion needed, convert directly to dst */
595*61046927SAndroid Build Coastguard Worker       src = map;
596*61046927SAndroid Build Coastguard Worker       src_format = rb_format;
597*61046927SAndroid Build Coastguard Worker       src_stride = rb_stride;
598*61046927SAndroid Build Coastguard Worker    }
599*61046927SAndroid Build Coastguard Worker 
600*61046927SAndroid Build Coastguard Worker    /* Do the conversion.
601*61046927SAndroid Build Coastguard Worker     *
602*61046927SAndroid Build Coastguard Worker     * If the dst format is Luminance, we need to do the conversion by computing
603*61046927SAndroid Build Coastguard Worker     * L=R+G+B values.
604*61046927SAndroid Build Coastguard Worker     */
605*61046927SAndroid Build Coastguard Worker    if (!convert_rgb_to_lum) {
606*61046927SAndroid Build Coastguard Worker       _mesa_format_convert(dst, dst_format, dst_stride,
607*61046927SAndroid Build Coastguard Worker                            src, src_format, src_stride,
608*61046927SAndroid Build Coastguard Worker                            width, height,
609*61046927SAndroid Build Coastguard Worker                            needs_rebase ? rebase_swizzle : NULL);
610*61046927SAndroid Build Coastguard Worker    } else if (!dst_is_integer) {
611*61046927SAndroid Build Coastguard Worker       /* Compute float Luminance values from RGBA float */
612*61046927SAndroid Build Coastguard Worker       int luminance_stride, luminance_bytes;
613*61046927SAndroid Build Coastguard Worker       void *luminance;
614*61046927SAndroid Build Coastguard Worker       uint32_t luminance_format;
615*61046927SAndroid Build Coastguard Worker 
616*61046927SAndroid Build Coastguard Worker       luminance_stride = width * sizeof(GLfloat);
617*61046927SAndroid Build Coastguard Worker       if (format == GL_LUMINANCE_ALPHA)
618*61046927SAndroid Build Coastguard Worker          luminance_stride *= 2;
619*61046927SAndroid Build Coastguard Worker       luminance_bytes = height * luminance_stride;
620*61046927SAndroid Build Coastguard Worker       luminance = malloc(luminance_bytes);
621*61046927SAndroid Build Coastguard Worker       if (!luminance) {
622*61046927SAndroid Build Coastguard Worker          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
623*61046927SAndroid Build Coastguard Worker          free(rgba);
624*61046927SAndroid Build Coastguard Worker          goto done_unmap;
625*61046927SAndroid Build Coastguard Worker       }
626*61046927SAndroid Build Coastguard Worker       _mesa_pack_luminance_from_rgba_float(width * height, src,
627*61046927SAndroid Build Coastguard Worker                                            luminance, format, transferOps);
628*61046927SAndroid Build Coastguard Worker 
629*61046927SAndroid Build Coastguard Worker       /* Convert from Luminance float to dst (this will hadle type conversion
630*61046927SAndroid Build Coastguard Worker        * from float to the type of dst if necessary)
631*61046927SAndroid Build Coastguard Worker        */
632*61046927SAndroid Build Coastguard Worker       luminance_format = _mesa_format_from_format_and_type(format, GL_FLOAT);
633*61046927SAndroid Build Coastguard Worker       _mesa_format_convert(dst, dst_format, dst_stride,
634*61046927SAndroid Build Coastguard Worker                            luminance, luminance_format, luminance_stride,
635*61046927SAndroid Build Coastguard Worker                            width, height, NULL);
636*61046927SAndroid Build Coastguard Worker       free(luminance);
637*61046927SAndroid Build Coastguard Worker    } else {
638*61046927SAndroid Build Coastguard Worker       _mesa_pack_luminance_from_rgba_integer(width * height, src, !src_is_uint,
639*61046927SAndroid Build Coastguard Worker                                              dst, format, type);
640*61046927SAndroid Build Coastguard Worker    }
641*61046927SAndroid Build Coastguard Worker 
642*61046927SAndroid Build Coastguard Worker    free(rgba);
643*61046927SAndroid Build Coastguard Worker 
644*61046927SAndroid Build Coastguard Worker done_swap:
645*61046927SAndroid Build Coastguard Worker    /* Handle byte swapping if required */
646*61046927SAndroid Build Coastguard Worker    if (packing->SwapBytes) {
647*61046927SAndroid Build Coastguard Worker       _mesa_swap_bytes_2d_image(format, type, packing,
648*61046927SAndroid Build Coastguard Worker                                 width, height, dst, dst);
649*61046927SAndroid Build Coastguard Worker    }
650*61046927SAndroid Build Coastguard Worker 
651*61046927SAndroid Build Coastguard Worker done_unmap:
652*61046927SAndroid Build Coastguard Worker    _mesa_unmap_renderbuffer(ctx, rb);
653*61046927SAndroid Build Coastguard Worker }
654*61046927SAndroid Build Coastguard Worker 
655*61046927SAndroid Build Coastguard Worker /**
656*61046927SAndroid Build Coastguard Worker  * For a packed depth/stencil buffer being read as depth/stencil, just memcpy the
657*61046927SAndroid Build Coastguard Worker  * data (possibly swapping 8/24 vs 24/8 as we go).
658*61046927SAndroid Build Coastguard Worker  */
659*61046927SAndroid Build Coastguard Worker static GLboolean
fast_read_depth_stencil_pixels(struct gl_context * ctx,GLint x,GLint y,GLsizei width,GLsizei height,GLubyte * dst,int dstStride)660*61046927SAndroid Build Coastguard Worker fast_read_depth_stencil_pixels(struct gl_context *ctx,
661*61046927SAndroid Build Coastguard Worker 			       GLint x, GLint y,
662*61046927SAndroid Build Coastguard Worker 			       GLsizei width, GLsizei height,
663*61046927SAndroid Build Coastguard Worker 			       GLubyte *dst, int dstStride)
664*61046927SAndroid Build Coastguard Worker {
665*61046927SAndroid Build Coastguard Worker    struct gl_framebuffer *fb = ctx->ReadBuffer;
666*61046927SAndroid Build Coastguard Worker    struct gl_renderbuffer *rb = fb->Attachment[BUFFER_DEPTH].Renderbuffer;
667*61046927SAndroid Build Coastguard Worker    struct gl_renderbuffer *stencilRb = fb->Attachment[BUFFER_STENCIL].Renderbuffer;
668*61046927SAndroid Build Coastguard Worker    GLubyte *map;
669*61046927SAndroid Build Coastguard Worker    int stride, i;
670*61046927SAndroid Build Coastguard Worker 
671*61046927SAndroid Build Coastguard Worker    if (rb != stencilRb)
672*61046927SAndroid Build Coastguard Worker       return GL_FALSE;
673*61046927SAndroid Build Coastguard Worker 
674*61046927SAndroid Build Coastguard Worker    if (rb->Format != MESA_FORMAT_S8_UINT_Z24_UNORM &&
675*61046927SAndroid Build Coastguard Worker        rb->Format != MESA_FORMAT_Z24_UNORM_S8_UINT)
676*61046927SAndroid Build Coastguard Worker       return GL_FALSE;
677*61046927SAndroid Build Coastguard Worker 
678*61046927SAndroid Build Coastguard Worker    _mesa_map_renderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT,
679*61046927SAndroid Build Coastguard Worker                       &map, &stride, fb->FlipY);
680*61046927SAndroid Build Coastguard Worker    if (!map) {
681*61046927SAndroid Build Coastguard Worker       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
682*61046927SAndroid Build Coastguard Worker       return GL_TRUE;  /* don't bother trying the slow path */
683*61046927SAndroid Build Coastguard Worker    }
684*61046927SAndroid Build Coastguard Worker 
685*61046927SAndroid Build Coastguard Worker    for (i = 0; i < height; i++) {
686*61046927SAndroid Build Coastguard Worker       _mesa_unpack_uint_24_8_depth_stencil_row(rb->Format, width,
687*61046927SAndroid Build Coastguard Worker 					       map, (GLuint *)dst);
688*61046927SAndroid Build Coastguard Worker       map += stride;
689*61046927SAndroid Build Coastguard Worker       dst += dstStride;
690*61046927SAndroid Build Coastguard Worker    }
691*61046927SAndroid Build Coastguard Worker 
692*61046927SAndroid Build Coastguard Worker    _mesa_unmap_renderbuffer(ctx, rb);
693*61046927SAndroid Build Coastguard Worker 
694*61046927SAndroid Build Coastguard Worker    return GL_TRUE;
695*61046927SAndroid Build Coastguard Worker }
696*61046927SAndroid Build Coastguard Worker 
697*61046927SAndroid Build Coastguard Worker 
698*61046927SAndroid Build Coastguard Worker /**
699*61046927SAndroid Build Coastguard Worker  * For non-float-depth and stencil buffers being read as 24/8 depth/stencil,
700*61046927SAndroid Build Coastguard Worker  * copy the integer data directly instead of converting depth to float and
701*61046927SAndroid Build Coastguard Worker  * re-packing.
702*61046927SAndroid Build Coastguard Worker  */
703*61046927SAndroid Build Coastguard Worker static GLboolean
fast_read_depth_stencil_pixels_separate(struct gl_context * ctx,GLint x,GLint y,GLsizei width,GLsizei height,uint32_t * dst,int dstStride)704*61046927SAndroid Build Coastguard Worker fast_read_depth_stencil_pixels_separate(struct gl_context *ctx,
705*61046927SAndroid Build Coastguard Worker 					GLint x, GLint y,
706*61046927SAndroid Build Coastguard Worker 					GLsizei width, GLsizei height,
707*61046927SAndroid Build Coastguard Worker 					uint32_t *dst, int dstStride)
708*61046927SAndroid Build Coastguard Worker {
709*61046927SAndroid Build Coastguard Worker    struct gl_framebuffer *fb = ctx->ReadBuffer;
710*61046927SAndroid Build Coastguard Worker    struct gl_renderbuffer *depthRb = fb->Attachment[BUFFER_DEPTH].Renderbuffer;
711*61046927SAndroid Build Coastguard Worker    struct gl_renderbuffer *stencilRb = fb->Attachment[BUFFER_STENCIL].Renderbuffer;
712*61046927SAndroid Build Coastguard Worker    GLubyte *depthMap, *stencilMap, *stencilVals;
713*61046927SAndroid Build Coastguard Worker    int depthStride, stencilStride, i, j;
714*61046927SAndroid Build Coastguard Worker 
715*61046927SAndroid Build Coastguard Worker    if (_mesa_get_format_datatype(depthRb->Format) != GL_UNSIGNED_NORMALIZED)
716*61046927SAndroid Build Coastguard Worker       return GL_FALSE;
717*61046927SAndroid Build Coastguard Worker 
718*61046927SAndroid Build Coastguard Worker    _mesa_map_renderbuffer(ctx, depthRb, x, y, width, height,
719*61046927SAndroid Build Coastguard Worker                       GL_MAP_READ_BIT, &depthMap, &depthStride, fb->FlipY);
720*61046927SAndroid Build Coastguard Worker    if (!depthMap) {
721*61046927SAndroid Build Coastguard Worker       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
722*61046927SAndroid Build Coastguard Worker       return GL_TRUE;  /* don't bother trying the slow path */
723*61046927SAndroid Build Coastguard Worker    }
724*61046927SAndroid Build Coastguard Worker 
725*61046927SAndroid Build Coastguard Worker    _mesa_map_renderbuffer(ctx, stencilRb, x, y, width, height,
726*61046927SAndroid Build Coastguard Worker                       GL_MAP_READ_BIT, &stencilMap, &stencilStride, fb->FlipY);
727*61046927SAndroid Build Coastguard Worker    if (!stencilMap) {
728*61046927SAndroid Build Coastguard Worker       _mesa_unmap_renderbuffer(ctx, depthRb);
729*61046927SAndroid Build Coastguard Worker       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
730*61046927SAndroid Build Coastguard Worker       return GL_TRUE;  /* don't bother trying the slow path */
731*61046927SAndroid Build Coastguard Worker    }
732*61046927SAndroid Build Coastguard Worker 
733*61046927SAndroid Build Coastguard Worker    stencilVals = malloc(width * sizeof(GLubyte));
734*61046927SAndroid Build Coastguard Worker 
735*61046927SAndroid Build Coastguard Worker    if (stencilVals) {
736*61046927SAndroid Build Coastguard Worker       for (j = 0; j < height; j++) {
737*61046927SAndroid Build Coastguard Worker          _mesa_unpack_uint_z_row(depthRb->Format, width, depthMap, dst);
738*61046927SAndroid Build Coastguard Worker          _mesa_unpack_ubyte_stencil_row(stencilRb->Format, width,
739*61046927SAndroid Build Coastguard Worker                                         stencilMap, stencilVals);
740*61046927SAndroid Build Coastguard Worker 
741*61046927SAndroid Build Coastguard Worker          for (i = 0; i < width; i++) {
742*61046927SAndroid Build Coastguard Worker             dst[i] = (dst[i] & 0xffffff00) | stencilVals[i];
743*61046927SAndroid Build Coastguard Worker          }
744*61046927SAndroid Build Coastguard Worker 
745*61046927SAndroid Build Coastguard Worker          depthMap += depthStride;
746*61046927SAndroid Build Coastguard Worker          stencilMap += stencilStride;
747*61046927SAndroid Build Coastguard Worker          dst += dstStride / 4;
748*61046927SAndroid Build Coastguard Worker       }
749*61046927SAndroid Build Coastguard Worker    }
750*61046927SAndroid Build Coastguard Worker    else {
751*61046927SAndroid Build Coastguard Worker       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
752*61046927SAndroid Build Coastguard Worker    }
753*61046927SAndroid Build Coastguard Worker 
754*61046927SAndroid Build Coastguard Worker    free(stencilVals);
755*61046927SAndroid Build Coastguard Worker 
756*61046927SAndroid Build Coastguard Worker    _mesa_unmap_renderbuffer(ctx, depthRb);
757*61046927SAndroid Build Coastguard Worker    _mesa_unmap_renderbuffer(ctx, stencilRb);
758*61046927SAndroid Build Coastguard Worker 
759*61046927SAndroid Build Coastguard Worker    return GL_TRUE;
760*61046927SAndroid Build Coastguard Worker }
761*61046927SAndroid Build Coastguard Worker 
762*61046927SAndroid Build Coastguard Worker static void
slow_read_depth_stencil_pixels_separate(struct gl_context * ctx,GLint x,GLint y,GLsizei width,GLsizei height,GLenum type,const struct gl_pixelstore_attrib * packing,GLubyte * dst,int dstStride)763*61046927SAndroid Build Coastguard Worker slow_read_depth_stencil_pixels_separate(struct gl_context *ctx,
764*61046927SAndroid Build Coastguard Worker 					GLint x, GLint y,
765*61046927SAndroid Build Coastguard Worker 					GLsizei width, GLsizei height,
766*61046927SAndroid Build Coastguard Worker 					GLenum type,
767*61046927SAndroid Build Coastguard Worker 					const struct gl_pixelstore_attrib *packing,
768*61046927SAndroid Build Coastguard Worker 					GLubyte *dst, int dstStride)
769*61046927SAndroid Build Coastguard Worker {
770*61046927SAndroid Build Coastguard Worker    struct gl_framebuffer *fb = ctx->ReadBuffer;
771*61046927SAndroid Build Coastguard Worker    struct gl_renderbuffer *depthRb = fb->Attachment[BUFFER_DEPTH].Renderbuffer;
772*61046927SAndroid Build Coastguard Worker    struct gl_renderbuffer *stencilRb = fb->Attachment[BUFFER_STENCIL].Renderbuffer;
773*61046927SAndroid Build Coastguard Worker    GLubyte *depthMap, *stencilMap;
774*61046927SAndroid Build Coastguard Worker    int depthStride, stencilStride, j;
775*61046927SAndroid Build Coastguard Worker    GLubyte *stencilVals;
776*61046927SAndroid Build Coastguard Worker    GLfloat *depthVals;
777*61046927SAndroid Build Coastguard Worker 
778*61046927SAndroid Build Coastguard Worker 
779*61046927SAndroid Build Coastguard Worker    /* The depth and stencil buffers might be separate, or a single buffer.
780*61046927SAndroid Build Coastguard Worker     * If one buffer, only map it once.
781*61046927SAndroid Build Coastguard Worker     */
782*61046927SAndroid Build Coastguard Worker    _mesa_map_renderbuffer(ctx, depthRb, x, y, width, height,
783*61046927SAndroid Build Coastguard Worker                       GL_MAP_READ_BIT, &depthMap, &depthStride, fb->FlipY);
784*61046927SAndroid Build Coastguard Worker    if (!depthMap) {
785*61046927SAndroid Build Coastguard Worker       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
786*61046927SAndroid Build Coastguard Worker       return;
787*61046927SAndroid Build Coastguard Worker    }
788*61046927SAndroid Build Coastguard Worker 
789*61046927SAndroid Build Coastguard Worker    if (stencilRb != depthRb) {
790*61046927SAndroid Build Coastguard Worker       _mesa_map_renderbuffer(ctx, stencilRb, x, y, width, height,
791*61046927SAndroid Build Coastguard Worker                          GL_MAP_READ_BIT, &stencilMap,
792*61046927SAndroid Build Coastguard Worker                          &stencilStride, fb->FlipY);
793*61046927SAndroid Build Coastguard Worker       if (!stencilMap) {
794*61046927SAndroid Build Coastguard Worker          _mesa_unmap_renderbuffer(ctx, depthRb);
795*61046927SAndroid Build Coastguard Worker          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
796*61046927SAndroid Build Coastguard Worker          return;
797*61046927SAndroid Build Coastguard Worker       }
798*61046927SAndroid Build Coastguard Worker    }
799*61046927SAndroid Build Coastguard Worker    else {
800*61046927SAndroid Build Coastguard Worker       stencilMap = depthMap;
801*61046927SAndroid Build Coastguard Worker       stencilStride = depthStride;
802*61046927SAndroid Build Coastguard Worker    }
803*61046927SAndroid Build Coastguard Worker 
804*61046927SAndroid Build Coastguard Worker    stencilVals = malloc(width * sizeof(GLubyte));
805*61046927SAndroid Build Coastguard Worker    depthVals = malloc(width * sizeof(GLfloat));
806*61046927SAndroid Build Coastguard Worker 
807*61046927SAndroid Build Coastguard Worker    if (stencilVals && depthVals) {
808*61046927SAndroid Build Coastguard Worker       for (j = 0; j < height; j++) {
809*61046927SAndroid Build Coastguard Worker          _mesa_unpack_float_z_row(depthRb->Format, width, depthMap, depthVals);
810*61046927SAndroid Build Coastguard Worker          _mesa_unpack_ubyte_stencil_row(stencilRb->Format, width,
811*61046927SAndroid Build Coastguard Worker                                         stencilMap, stencilVals);
812*61046927SAndroid Build Coastguard Worker 
813*61046927SAndroid Build Coastguard Worker          _mesa_pack_depth_stencil_span(ctx, width, type, (GLuint *)dst,
814*61046927SAndroid Build Coastguard Worker                                        depthVals, stencilVals, packing);
815*61046927SAndroid Build Coastguard Worker 
816*61046927SAndroid Build Coastguard Worker          depthMap += depthStride;
817*61046927SAndroid Build Coastguard Worker          stencilMap += stencilStride;
818*61046927SAndroid Build Coastguard Worker          dst += dstStride;
819*61046927SAndroid Build Coastguard Worker       }
820*61046927SAndroid Build Coastguard Worker    }
821*61046927SAndroid Build Coastguard Worker    else {
822*61046927SAndroid Build Coastguard Worker       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
823*61046927SAndroid Build Coastguard Worker    }
824*61046927SAndroid Build Coastguard Worker 
825*61046927SAndroid Build Coastguard Worker    free(stencilVals);
826*61046927SAndroid Build Coastguard Worker    free(depthVals);
827*61046927SAndroid Build Coastguard Worker 
828*61046927SAndroid Build Coastguard Worker    _mesa_unmap_renderbuffer(ctx, depthRb);
829*61046927SAndroid Build Coastguard Worker    if (stencilRb != depthRb) {
830*61046927SAndroid Build Coastguard Worker       _mesa_unmap_renderbuffer(ctx, stencilRb);
831*61046927SAndroid Build Coastguard Worker    }
832*61046927SAndroid Build Coastguard Worker }
833*61046927SAndroid Build Coastguard Worker 
834*61046927SAndroid Build Coastguard Worker 
835*61046927SAndroid Build Coastguard Worker /**
836*61046927SAndroid Build Coastguard Worker  * Read combined depth/stencil values.
837*61046927SAndroid Build Coastguard Worker  * We'll have already done error checking to be sure the expected
838*61046927SAndroid Build Coastguard Worker  * depth and stencil buffers really exist.
839*61046927SAndroid Build Coastguard Worker  */
840*61046927SAndroid Build Coastguard Worker static void
read_depth_stencil_pixels(struct gl_context * ctx,GLint x,GLint y,GLsizei width,GLsizei height,GLenum type,GLvoid * pixels,const struct gl_pixelstore_attrib * packing)841*61046927SAndroid Build Coastguard Worker read_depth_stencil_pixels(struct gl_context *ctx,
842*61046927SAndroid Build Coastguard Worker                           GLint x, GLint y,
843*61046927SAndroid Build Coastguard Worker                           GLsizei width, GLsizei height,
844*61046927SAndroid Build Coastguard Worker                           GLenum type, GLvoid *pixels,
845*61046927SAndroid Build Coastguard Worker                           const struct gl_pixelstore_attrib *packing )
846*61046927SAndroid Build Coastguard Worker {
847*61046927SAndroid Build Coastguard Worker    const GLboolean scaleOrBias
848*61046927SAndroid Build Coastguard Worker       = ctx->Pixel.DepthScale != 1.0F || ctx->Pixel.DepthBias != 0.0F;
849*61046927SAndroid Build Coastguard Worker    const GLboolean stencilTransfer = ctx->Pixel.IndexShift
850*61046927SAndroid Build Coastguard Worker       || ctx->Pixel.IndexOffset || ctx->Pixel.MapStencilFlag;
851*61046927SAndroid Build Coastguard Worker    GLubyte *dst;
852*61046927SAndroid Build Coastguard Worker    int dstStride;
853*61046927SAndroid Build Coastguard Worker 
854*61046927SAndroid Build Coastguard Worker    dst = (GLubyte *) _mesa_image_address2d(packing, pixels,
855*61046927SAndroid Build Coastguard Worker 					   width, height,
856*61046927SAndroid Build Coastguard Worker 					   GL_DEPTH_STENCIL_EXT,
857*61046927SAndroid Build Coastguard Worker 					   type, 0, 0);
858*61046927SAndroid Build Coastguard Worker    dstStride = _mesa_image_row_stride(packing, width,
859*61046927SAndroid Build Coastguard Worker 				      GL_DEPTH_STENCIL_EXT, type);
860*61046927SAndroid Build Coastguard Worker 
861*61046927SAndroid Build Coastguard Worker    /* Fast 24/8 reads. */
862*61046927SAndroid Build Coastguard Worker    if (type == GL_UNSIGNED_INT_24_8 &&
863*61046927SAndroid Build Coastguard Worker        !scaleOrBias && !stencilTransfer && !packing->SwapBytes) {
864*61046927SAndroid Build Coastguard Worker       if (fast_read_depth_stencil_pixels(ctx, x, y, width, height,
865*61046927SAndroid Build Coastguard Worker 					 dst, dstStride))
866*61046927SAndroid Build Coastguard Worker 	 return;
867*61046927SAndroid Build Coastguard Worker 
868*61046927SAndroid Build Coastguard Worker       if (fast_read_depth_stencil_pixels_separate(ctx, x, y, width, height,
869*61046927SAndroid Build Coastguard Worker 						  (uint32_t *)dst, dstStride))
870*61046927SAndroid Build Coastguard Worker 	 return;
871*61046927SAndroid Build Coastguard Worker    }
872*61046927SAndroid Build Coastguard Worker 
873*61046927SAndroid Build Coastguard Worker    slow_read_depth_stencil_pixels_separate(ctx, x, y, width, height,
874*61046927SAndroid Build Coastguard Worker 					   type, packing,
875*61046927SAndroid Build Coastguard Worker 					   dst, dstStride);
876*61046927SAndroid Build Coastguard Worker }
877*61046927SAndroid Build Coastguard Worker 
878*61046927SAndroid Build Coastguard Worker 
879*61046927SAndroid Build Coastguard Worker 
880*61046927SAndroid Build Coastguard Worker /**
881*61046927SAndroid Build Coastguard Worker  * Software fallback routine.
882*61046927SAndroid Build Coastguard Worker  * By time we get here, all error checking will have been done.
883*61046927SAndroid Build Coastguard Worker  */
884*61046927SAndroid Build Coastguard Worker void
_mesa_readpixels(struct gl_context * ctx,GLint x,GLint y,GLsizei width,GLsizei height,GLenum format,GLenum type,const struct gl_pixelstore_attrib * packing,GLvoid * pixels)885*61046927SAndroid Build Coastguard Worker _mesa_readpixels(struct gl_context *ctx,
886*61046927SAndroid Build Coastguard Worker                  GLint x, GLint y, GLsizei width, GLsizei height,
887*61046927SAndroid Build Coastguard Worker                  GLenum format, GLenum type,
888*61046927SAndroid Build Coastguard Worker                  const struct gl_pixelstore_attrib *packing,
889*61046927SAndroid Build Coastguard Worker                  GLvoid *pixels)
890*61046927SAndroid Build Coastguard Worker {
891*61046927SAndroid Build Coastguard Worker    if (ctx->NewState)
892*61046927SAndroid Build Coastguard Worker       _mesa_update_state(ctx);
893*61046927SAndroid Build Coastguard Worker 
894*61046927SAndroid Build Coastguard Worker    pixels = _mesa_map_pbo_dest(ctx, packing, pixels);
895*61046927SAndroid Build Coastguard Worker 
896*61046927SAndroid Build Coastguard Worker    if (pixels) {
897*61046927SAndroid Build Coastguard Worker       /* Try memcpy first. */
898*61046927SAndroid Build Coastguard Worker       if (readpixels_memcpy(ctx, x, y, width, height, format, type,
899*61046927SAndroid Build Coastguard Worker                             pixels, packing)) {
900*61046927SAndroid Build Coastguard Worker          _mesa_unmap_pbo_dest(ctx, packing);
901*61046927SAndroid Build Coastguard Worker          return;
902*61046927SAndroid Build Coastguard Worker       }
903*61046927SAndroid Build Coastguard Worker 
904*61046927SAndroid Build Coastguard Worker       /* Otherwise take the slow path. */
905*61046927SAndroid Build Coastguard Worker       switch (format) {
906*61046927SAndroid Build Coastguard Worker       case GL_STENCIL_INDEX:
907*61046927SAndroid Build Coastguard Worker          read_stencil_pixels(ctx, x, y, width, height, type, pixels,
908*61046927SAndroid Build Coastguard Worker                              packing);
909*61046927SAndroid Build Coastguard Worker          break;
910*61046927SAndroid Build Coastguard Worker       case GL_DEPTH_COMPONENT:
911*61046927SAndroid Build Coastguard Worker          read_depth_pixels(ctx, x, y, width, height, type, pixels,
912*61046927SAndroid Build Coastguard Worker                            packing);
913*61046927SAndroid Build Coastguard Worker          break;
914*61046927SAndroid Build Coastguard Worker       case GL_DEPTH_STENCIL_EXT:
915*61046927SAndroid Build Coastguard Worker          read_depth_stencil_pixels(ctx, x, y, width, height, type, pixels,
916*61046927SAndroid Build Coastguard Worker                                    packing);
917*61046927SAndroid Build Coastguard Worker          break;
918*61046927SAndroid Build Coastguard Worker       default:
919*61046927SAndroid Build Coastguard Worker          /* all other formats should be color formats */
920*61046927SAndroid Build Coastguard Worker          read_rgba_pixels(ctx, x, y, width, height, format, type, pixels,
921*61046927SAndroid Build Coastguard Worker                           packing);
922*61046927SAndroid Build Coastguard Worker       }
923*61046927SAndroid Build Coastguard Worker 
924*61046927SAndroid Build Coastguard Worker       _mesa_unmap_pbo_dest(ctx, packing);
925*61046927SAndroid Build Coastguard Worker    }
926*61046927SAndroid Build Coastguard Worker }
927*61046927SAndroid Build Coastguard Worker 
928*61046927SAndroid Build Coastguard Worker 
929*61046927SAndroid Build Coastguard Worker static GLenum
read_pixels_es3_error_check(struct gl_context * ctx,GLenum format,GLenum type,const struct gl_renderbuffer * rb)930*61046927SAndroid Build Coastguard Worker read_pixels_es3_error_check(struct gl_context *ctx, GLenum format, GLenum type,
931*61046927SAndroid Build Coastguard Worker                             const struct gl_renderbuffer *rb)
932*61046927SAndroid Build Coastguard Worker {
933*61046927SAndroid Build Coastguard Worker    const GLenum internalFormat = rb->InternalFormat;
934*61046927SAndroid Build Coastguard Worker    const GLenum data_type = _mesa_get_format_datatype(rb->Format);
935*61046927SAndroid Build Coastguard Worker    GLboolean is_unsigned_int = GL_FALSE;
936*61046927SAndroid Build Coastguard Worker    GLboolean is_signed_int = GL_FALSE;
937*61046927SAndroid Build Coastguard Worker    GLboolean is_float_depth = _mesa_has_depth_float_channel(internalFormat);
938*61046927SAndroid Build Coastguard Worker 
939*61046927SAndroid Build Coastguard Worker    is_unsigned_int = _mesa_is_enum_format_unsigned_int(internalFormat);
940*61046927SAndroid Build Coastguard Worker    if (!is_unsigned_int) {
941*61046927SAndroid Build Coastguard Worker       is_signed_int = _mesa_is_enum_format_signed_int(internalFormat);
942*61046927SAndroid Build Coastguard Worker    }
943*61046927SAndroid Build Coastguard Worker 
944*61046927SAndroid Build Coastguard Worker    switch (format) {
945*61046927SAndroid Build Coastguard Worker    case GL_RGBA:
946*61046927SAndroid Build Coastguard Worker       if (type == GL_FLOAT && data_type == GL_FLOAT)
947*61046927SAndroid Build Coastguard Worker          return GL_NO_ERROR; /* EXT_color_buffer_float */
948*61046927SAndroid Build Coastguard Worker       if (type == GL_UNSIGNED_BYTE && data_type == GL_UNSIGNED_NORMALIZED)
949*61046927SAndroid Build Coastguard Worker          return GL_NO_ERROR;
950*61046927SAndroid Build Coastguard Worker       if (internalFormat == GL_RGB10_A2 &&
951*61046927SAndroid Build Coastguard Worker           type == GL_UNSIGNED_INT_2_10_10_10_REV)
952*61046927SAndroid Build Coastguard Worker          return GL_NO_ERROR;
953*61046927SAndroid Build Coastguard Worker       if (internalFormat == GL_RGB10_A2UI && type == GL_UNSIGNED_BYTE)
954*61046927SAndroid Build Coastguard Worker          return GL_NO_ERROR;
955*61046927SAndroid Build Coastguard Worker       if (type == GL_UNSIGNED_SHORT) {
956*61046927SAndroid Build Coastguard Worker          switch (internalFormat) {
957*61046927SAndroid Build Coastguard Worker          case GL_R16:
958*61046927SAndroid Build Coastguard Worker          case GL_RG16:
959*61046927SAndroid Build Coastguard Worker          case GL_RGB16:
960*61046927SAndroid Build Coastguard Worker          case GL_RGBA16:
961*61046927SAndroid Build Coastguard Worker             if (_mesa_has_EXT_texture_norm16(ctx))
962*61046927SAndroid Build Coastguard Worker                return GL_NO_ERROR;
963*61046927SAndroid Build Coastguard Worker          }
964*61046927SAndroid Build Coastguard Worker       }
965*61046927SAndroid Build Coastguard Worker       if (type == GL_SHORT) {
966*61046927SAndroid Build Coastguard Worker          switch (internalFormat) {
967*61046927SAndroid Build Coastguard Worker          case GL_R16_SNORM:
968*61046927SAndroid Build Coastguard Worker          case GL_RG16_SNORM:
969*61046927SAndroid Build Coastguard Worker          case GL_RGBA16_SNORM:
970*61046927SAndroid Build Coastguard Worker             if (_mesa_has_EXT_texture_norm16(ctx) &&
971*61046927SAndroid Build Coastguard Worker                 _mesa_has_EXT_render_snorm(ctx))
972*61046927SAndroid Build Coastguard Worker                return GL_NO_ERROR;
973*61046927SAndroid Build Coastguard Worker          }
974*61046927SAndroid Build Coastguard Worker       }
975*61046927SAndroid Build Coastguard Worker       if (type == GL_BYTE) {
976*61046927SAndroid Build Coastguard Worker          switch (internalFormat) {
977*61046927SAndroid Build Coastguard Worker          case GL_R8_SNORM:
978*61046927SAndroid Build Coastguard Worker          case GL_RG8_SNORM:
979*61046927SAndroid Build Coastguard Worker          case GL_RGBA8_SNORM:
980*61046927SAndroid Build Coastguard Worker             if (_mesa_has_EXT_render_snorm(ctx))
981*61046927SAndroid Build Coastguard Worker                return GL_NO_ERROR;
982*61046927SAndroid Build Coastguard Worker          }
983*61046927SAndroid Build Coastguard Worker       }
984*61046927SAndroid Build Coastguard Worker       break;
985*61046927SAndroid Build Coastguard Worker    case GL_BGRA:
986*61046927SAndroid Build Coastguard Worker       /* GL_EXT_read_format_bgra */
987*61046927SAndroid Build Coastguard Worker       if (type == GL_UNSIGNED_BYTE ||
988*61046927SAndroid Build Coastguard Worker           type == GL_UNSIGNED_SHORT_4_4_4_4_REV ||
989*61046927SAndroid Build Coastguard Worker           type == GL_UNSIGNED_SHORT_1_5_5_5_REV)
990*61046927SAndroid Build Coastguard Worker          return GL_NO_ERROR;
991*61046927SAndroid Build Coastguard Worker       break;
992*61046927SAndroid Build Coastguard Worker    case GL_RGBA_INTEGER:
993*61046927SAndroid Build Coastguard Worker       if ((is_signed_int && type == GL_INT) ||
994*61046927SAndroid Build Coastguard Worker           (is_unsigned_int && type == GL_UNSIGNED_INT))
995*61046927SAndroid Build Coastguard Worker          return GL_NO_ERROR;
996*61046927SAndroid Build Coastguard Worker       break;
997*61046927SAndroid Build Coastguard Worker    case GL_DEPTH_STENCIL:
998*61046927SAndroid Build Coastguard Worker       switch (type) {
999*61046927SAndroid Build Coastguard Worker       case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
1000*61046927SAndroid Build Coastguard Worker          if (is_float_depth)
1001*61046927SAndroid Build Coastguard Worker             return GL_NO_ERROR;
1002*61046927SAndroid Build Coastguard Worker          break;
1003*61046927SAndroid Build Coastguard Worker       case GL_UNSIGNED_INT_24_8:
1004*61046927SAndroid Build Coastguard Worker          if (!is_float_depth)
1005*61046927SAndroid Build Coastguard Worker             return GL_NO_ERROR;
1006*61046927SAndroid Build Coastguard Worker          break;
1007*61046927SAndroid Build Coastguard Worker       default:
1008*61046927SAndroid Build Coastguard Worker          return GL_INVALID_ENUM;
1009*61046927SAndroid Build Coastguard Worker       }
1010*61046927SAndroid Build Coastguard Worker       break;
1011*61046927SAndroid Build Coastguard Worker    case GL_DEPTH_COMPONENT:
1012*61046927SAndroid Build Coastguard Worker       switch (type) {
1013*61046927SAndroid Build Coastguard Worker       case GL_FLOAT:
1014*61046927SAndroid Build Coastguard Worker          if (is_float_depth)
1015*61046927SAndroid Build Coastguard Worker             return GL_NO_ERROR;
1016*61046927SAndroid Build Coastguard Worker          break;
1017*61046927SAndroid Build Coastguard Worker       case GL_UNSIGNED_SHORT:
1018*61046927SAndroid Build Coastguard Worker       case GL_UNSIGNED_INT:
1019*61046927SAndroid Build Coastguard Worker       case GL_UNSIGNED_INT_24_8:
1020*61046927SAndroid Build Coastguard Worker          if (!is_float_depth)
1021*61046927SAndroid Build Coastguard Worker             return GL_NO_ERROR;
1022*61046927SAndroid Build Coastguard Worker          break;
1023*61046927SAndroid Build Coastguard Worker       default:
1024*61046927SAndroid Build Coastguard Worker          return GL_INVALID_ENUM;
1025*61046927SAndroid Build Coastguard Worker       }
1026*61046927SAndroid Build Coastguard Worker       break;
1027*61046927SAndroid Build Coastguard Worker    case GL_STENCIL_INDEX:
1028*61046927SAndroid Build Coastguard Worker       switch (type) {
1029*61046927SAndroid Build Coastguard Worker       case GL_UNSIGNED_BYTE:
1030*61046927SAndroid Build Coastguard Worker          return GL_NO_ERROR;
1031*61046927SAndroid Build Coastguard Worker       default:
1032*61046927SAndroid Build Coastguard Worker          return GL_INVALID_ENUM;
1033*61046927SAndroid Build Coastguard Worker       }
1034*61046927SAndroid Build Coastguard Worker       break;
1035*61046927SAndroid Build Coastguard Worker    }
1036*61046927SAndroid Build Coastguard Worker 
1037*61046927SAndroid Build Coastguard Worker    return GL_INVALID_OPERATION;
1038*61046927SAndroid Build Coastguard Worker }
1039*61046927SAndroid Build Coastguard Worker 
1040*61046927SAndroid Build Coastguard Worker 
1041*61046927SAndroid Build Coastguard Worker static ALWAYS_INLINE void
read_pixels(GLint x,GLint y,GLsizei width,GLsizei height,GLenum format,GLenum type,GLsizei bufSize,GLvoid * pixels,bool no_error)1042*61046927SAndroid Build Coastguard Worker read_pixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format,
1043*61046927SAndroid Build Coastguard Worker             GLenum type, GLsizei bufSize, GLvoid *pixels, bool no_error)
1044*61046927SAndroid Build Coastguard Worker {
1045*61046927SAndroid Build Coastguard Worker    GLenum err = GL_NO_ERROR;
1046*61046927SAndroid Build Coastguard Worker    struct gl_renderbuffer *rb;
1047*61046927SAndroid Build Coastguard Worker    struct gl_pixelstore_attrib clippedPacking;
1048*61046927SAndroid Build Coastguard Worker 
1049*61046927SAndroid Build Coastguard Worker    GET_CURRENT_CONTEXT(ctx);
1050*61046927SAndroid Build Coastguard Worker 
1051*61046927SAndroid Build Coastguard Worker    FLUSH_VERTICES(ctx, 0, 0);
1052*61046927SAndroid Build Coastguard Worker 
1053*61046927SAndroid Build Coastguard Worker    if (MESA_VERBOSE & VERBOSE_API)
1054*61046927SAndroid Build Coastguard Worker       _mesa_debug(ctx, "glReadPixels(%d, %d, %s, %s, %p)\n",
1055*61046927SAndroid Build Coastguard Worker                   width, height,
1056*61046927SAndroid Build Coastguard Worker                   _mesa_enum_to_string(format),
1057*61046927SAndroid Build Coastguard Worker                   _mesa_enum_to_string(type),
1058*61046927SAndroid Build Coastguard Worker                   pixels);
1059*61046927SAndroid Build Coastguard Worker 
1060*61046927SAndroid Build Coastguard Worker    if (!no_error && (width < 0 || height < 0)) {
1061*61046927SAndroid Build Coastguard Worker       _mesa_error( ctx, GL_INVALID_VALUE,
1062*61046927SAndroid Build Coastguard Worker                    "glReadPixels(width=%d height=%d)", width, height );
1063*61046927SAndroid Build Coastguard Worker       return;
1064*61046927SAndroid Build Coastguard Worker    }
1065*61046927SAndroid Build Coastguard Worker 
1066*61046927SAndroid Build Coastguard Worker    _mesa_update_pixel(ctx);
1067*61046927SAndroid Build Coastguard Worker 
1068*61046927SAndroid Build Coastguard Worker    if (ctx->NewState)
1069*61046927SAndroid Build Coastguard Worker       _mesa_update_state(ctx);
1070*61046927SAndroid Build Coastguard Worker 
1071*61046927SAndroid Build Coastguard Worker    if (!no_error && ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
1072*61046927SAndroid Build Coastguard Worker       _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
1073*61046927SAndroid Build Coastguard Worker                   "glReadPixels(incomplete framebuffer)" );
1074*61046927SAndroid Build Coastguard Worker       return;
1075*61046927SAndroid Build Coastguard Worker    }
1076*61046927SAndroid Build Coastguard Worker 
1077*61046927SAndroid Build Coastguard Worker    rb = _mesa_get_read_renderbuffer_for_format(ctx, format);
1078*61046927SAndroid Build Coastguard Worker    if (!no_error) {
1079*61046927SAndroid Build Coastguard Worker       if (rb == NULL) {
1080*61046927SAndroid Build Coastguard Worker          _mesa_error(ctx, GL_INVALID_OPERATION,
1081*61046927SAndroid Build Coastguard Worker                      "glReadPixels(read buffer)");
1082*61046927SAndroid Build Coastguard Worker          return;
1083*61046927SAndroid Build Coastguard Worker       }
1084*61046927SAndroid Build Coastguard Worker 
1085*61046927SAndroid Build Coastguard Worker       /* OpenGL ES 1.x and OpenGL ES 2.0 impose additional restrictions on the
1086*61046927SAndroid Build Coastguard Worker        * combinations of format and type that can be used.
1087*61046927SAndroid Build Coastguard Worker        *
1088*61046927SAndroid Build Coastguard Worker        * Technically, only two combinations are actually allowed:
1089*61046927SAndroid Build Coastguard Worker        * GL_RGBA/GL_UNSIGNED_BYTE, and some implementation-specific internal
1090*61046927SAndroid Build Coastguard Worker        * preferred combination.  This code doesn't know what that preferred
1091*61046927SAndroid Build Coastguard Worker        * combination is, and Mesa can handle anything valid.  Just work instead.
1092*61046927SAndroid Build Coastguard Worker        */
1093*61046927SAndroid Build Coastguard Worker       if (_mesa_is_gles(ctx)) {
1094*61046927SAndroid Build Coastguard Worker          if (_mesa_is_gles2(ctx) &&
1095*61046927SAndroid Build Coastguard Worker              _mesa_is_color_format(format) &&
1096*61046927SAndroid Build Coastguard Worker              _mesa_get_color_read_format(ctx, NULL, "glReadPixels") == format &&
1097*61046927SAndroid Build Coastguard Worker              _mesa_get_color_read_type(ctx, NULL, "glReadPixels") == type) {
1098*61046927SAndroid Build Coastguard Worker             err = GL_NO_ERROR;
1099*61046927SAndroid Build Coastguard Worker          } else if (ctx->Version < 30) {
1100*61046927SAndroid Build Coastguard Worker             err = _mesa_es_error_check_format_and_type(ctx, format, type, 2);
1101*61046927SAndroid Build Coastguard Worker             if (err == GL_NO_ERROR) {
1102*61046927SAndroid Build Coastguard Worker                if (type == GL_FLOAT || type == GL_HALF_FLOAT_OES) {
1103*61046927SAndroid Build Coastguard Worker                   err = GL_INVALID_OPERATION;
1104*61046927SAndroid Build Coastguard Worker                }
1105*61046927SAndroid Build Coastguard Worker             }
1106*61046927SAndroid Build Coastguard Worker          } else {
1107*61046927SAndroid Build Coastguard Worker             err = read_pixels_es3_error_check(ctx, format, type, rb);
1108*61046927SAndroid Build Coastguard Worker          }
1109*61046927SAndroid Build Coastguard Worker 
1110*61046927SAndroid Build Coastguard Worker          if (err != GL_NO_ERROR) {
1111*61046927SAndroid Build Coastguard Worker             _mesa_error(ctx, err, "glReadPixels(invalid format %s and/or type %s)",
1112*61046927SAndroid Build Coastguard Worker                         _mesa_enum_to_string(format),
1113*61046927SAndroid Build Coastguard Worker                         _mesa_enum_to_string(type));
1114*61046927SAndroid Build Coastguard Worker             return;
1115*61046927SAndroid Build Coastguard Worker          }
1116*61046927SAndroid Build Coastguard Worker       }
1117*61046927SAndroid Build Coastguard Worker 
1118*61046927SAndroid Build Coastguard Worker       err = _mesa_error_check_format_and_type(ctx, format, type);
1119*61046927SAndroid Build Coastguard Worker       if (err != GL_NO_ERROR) {
1120*61046927SAndroid Build Coastguard Worker          _mesa_error(ctx, err, "glReadPixels(invalid format %s and/or type %s)",
1121*61046927SAndroid Build Coastguard Worker                      _mesa_enum_to_string(format),
1122*61046927SAndroid Build Coastguard Worker                      _mesa_enum_to_string(type));
1123*61046927SAndroid Build Coastguard Worker          return;
1124*61046927SAndroid Build Coastguard Worker       }
1125*61046927SAndroid Build Coastguard Worker 
1126*61046927SAndroid Build Coastguard Worker       /**
1127*61046927SAndroid Build Coastguard Worker        * From the GL_EXT_multisampled_render_to_texture spec:
1128*61046927SAndroid Build Coastguard Worker        *
1129*61046927SAndroid Build Coastguard Worker        * Similarly, for ReadPixels:
1130*61046927SAndroid Build Coastguard Worker        * "An INVALID_OPERATION error is generated if the value of READ_-
1131*61046927SAndroid Build Coastguard Worker        *  FRAMEBUFFER_BINDING (see section 9) is non-zero, the read framebuffer
1132*61046927SAndroid Build Coastguard Worker        *  is framebuffer complete, and the value of SAMPLE_BUFFERS for the read
1133*61046927SAndroid Build Coastguard Worker        *  framebuffer is one."
1134*61046927SAndroid Build Coastguard Worker        *
1135*61046927SAndroid Build Coastguard Worker        * These errors do not apply to textures and renderbuffers that have
1136*61046927SAndroid Build Coastguard Worker        * associated multisample data specified by the mechanisms described in
1137*61046927SAndroid Build Coastguard Worker        * this extension, i.e., the above operations are allowed even when
1138*61046927SAndroid Build Coastguard Worker        * SAMPLE_BUFFERS is non-zero for renderbuffers created via Renderbuffer-
1139*61046927SAndroid Build Coastguard Worker        * StorageMultisampleEXT or textures attached via FramebufferTexture2D-
1140*61046927SAndroid Build Coastguard Worker        * MultisampleEXT.
1141*61046927SAndroid Build Coastguard Worker        */
1142*61046927SAndroid Build Coastguard Worker       if (_mesa_is_user_fbo(ctx->ReadBuffer) &&
1143*61046927SAndroid Build Coastguard Worker           ctx->ReadBuffer->Visual.samples > 0 &&
1144*61046927SAndroid Build Coastguard Worker           !_mesa_has_rtt_samples(ctx->ReadBuffer)) {
1145*61046927SAndroid Build Coastguard Worker          _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(multisample FBO)");
1146*61046927SAndroid Build Coastguard Worker          return;
1147*61046927SAndroid Build Coastguard Worker       }
1148*61046927SAndroid Build Coastguard Worker 
1149*61046927SAndroid Build Coastguard Worker       if (!_mesa_source_buffer_exists(ctx, format)) {
1150*61046927SAndroid Build Coastguard Worker          _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(no readbuffer)");
1151*61046927SAndroid Build Coastguard Worker          return;
1152*61046927SAndroid Build Coastguard Worker       }
1153*61046927SAndroid Build Coastguard Worker 
1154*61046927SAndroid Build Coastguard Worker       /* Check that the destination format and source buffer are both
1155*61046927SAndroid Build Coastguard Worker        * integer-valued or both non-integer-valued.
1156*61046927SAndroid Build Coastguard Worker        */
1157*61046927SAndroid Build Coastguard Worker       if (ctx->Extensions.EXT_texture_integer && _mesa_is_color_format(format)) {
1158*61046927SAndroid Build Coastguard Worker          const struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorReadBuffer;
1159*61046927SAndroid Build Coastguard Worker          const GLboolean srcInteger = _mesa_is_format_integer_color(rb->Format);
1160*61046927SAndroid Build Coastguard Worker          const GLboolean dstInteger = _mesa_is_enum_format_integer(format);
1161*61046927SAndroid Build Coastguard Worker          if (dstInteger != srcInteger) {
1162*61046927SAndroid Build Coastguard Worker             _mesa_error(ctx, GL_INVALID_OPERATION,
1163*61046927SAndroid Build Coastguard Worker                         "glReadPixels(integer / non-integer format mismatch");
1164*61046927SAndroid Build Coastguard Worker             return;
1165*61046927SAndroid Build Coastguard Worker          }
1166*61046927SAndroid Build Coastguard Worker       }
1167*61046927SAndroid Build Coastguard Worker    }
1168*61046927SAndroid Build Coastguard Worker 
1169*61046927SAndroid Build Coastguard Worker    /* Do all needed clipping here, so that we can forget about it later */
1170*61046927SAndroid Build Coastguard Worker    clippedPacking = ctx->Pack;
1171*61046927SAndroid Build Coastguard Worker    if (!_mesa_clip_readpixels(ctx, &x, &y, &width, &height, &clippedPacking))
1172*61046927SAndroid Build Coastguard Worker       return; /* nothing to do */
1173*61046927SAndroid Build Coastguard Worker 
1174*61046927SAndroid Build Coastguard Worker    if (!no_error) {
1175*61046927SAndroid Build Coastguard Worker       if (!_mesa_validate_pbo_access(2, &ctx->Pack, width, height, 1,
1176*61046927SAndroid Build Coastguard Worker                                      format, type, bufSize, pixels)) {
1177*61046927SAndroid Build Coastguard Worker          if (ctx->Pack.BufferObj) {
1178*61046927SAndroid Build Coastguard Worker             _mesa_error(ctx, GL_INVALID_OPERATION,
1179*61046927SAndroid Build Coastguard Worker                         "glReadPixels(out of bounds PBO access)");
1180*61046927SAndroid Build Coastguard Worker          } else {
1181*61046927SAndroid Build Coastguard Worker             _mesa_error(ctx, GL_INVALID_OPERATION,
1182*61046927SAndroid Build Coastguard Worker                         "glReadnPixelsARB(out of bounds access:"
1183*61046927SAndroid Build Coastguard Worker                         " bufSize (%d) is too small)", bufSize);
1184*61046927SAndroid Build Coastguard Worker          }
1185*61046927SAndroid Build Coastguard Worker          return;
1186*61046927SAndroid Build Coastguard Worker       }
1187*61046927SAndroid Build Coastguard Worker 
1188*61046927SAndroid Build Coastguard Worker       if (ctx->Pack.BufferObj &&
1189*61046927SAndroid Build Coastguard Worker           _mesa_check_disallowed_mapping(ctx->Pack.BufferObj)) {
1190*61046927SAndroid Build Coastguard Worker          /* buffer is mapped - that's an error */
1191*61046927SAndroid Build Coastguard Worker          _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(PBO is mapped)");
1192*61046927SAndroid Build Coastguard Worker          return;
1193*61046927SAndroid Build Coastguard Worker       }
1194*61046927SAndroid Build Coastguard Worker    }
1195*61046927SAndroid Build Coastguard Worker 
1196*61046927SAndroid Build Coastguard Worker    if (ctx->Pack.BufferObj)
1197*61046927SAndroid Build Coastguard Worker       ctx->Pack.BufferObj->UsageHistory |= USAGE_PIXEL_PACK_BUFFER;
1198*61046927SAndroid Build Coastguard Worker 
1199*61046927SAndroid Build Coastguard Worker    st_ReadPixels(ctx, x, y, width, height,
1200*61046927SAndroid Build Coastguard Worker                  format, type, &clippedPacking, pixels);
1201*61046927SAndroid Build Coastguard Worker }
1202*61046927SAndroid Build Coastguard Worker 
1203*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_ReadnPixelsARB_no_error(GLint x,GLint y,GLsizei width,GLsizei height,GLenum format,GLenum type,GLsizei bufSize,GLvoid * pixels)1204*61046927SAndroid Build Coastguard Worker _mesa_ReadnPixelsARB_no_error(GLint x, GLint y, GLsizei width, GLsizei height,
1205*61046927SAndroid Build Coastguard Worker                               GLenum format, GLenum type, GLsizei bufSize,
1206*61046927SAndroid Build Coastguard Worker                               GLvoid *pixels)
1207*61046927SAndroid Build Coastguard Worker {
1208*61046927SAndroid Build Coastguard Worker    read_pixels(x, y, width, height, format, type, bufSize, pixels, true);
1209*61046927SAndroid Build Coastguard Worker }
1210*61046927SAndroid Build Coastguard Worker 
1211*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_ReadnPixelsARB(GLint x,GLint y,GLsizei width,GLsizei height,GLenum format,GLenum type,GLsizei bufSize,GLvoid * pixels)1212*61046927SAndroid Build Coastguard Worker _mesa_ReadnPixelsARB(GLint x, GLint y, GLsizei width, GLsizei height,
1213*61046927SAndroid Build Coastguard Worker                      GLenum format, GLenum type, GLsizei bufSize,
1214*61046927SAndroid Build Coastguard Worker                      GLvoid *pixels)
1215*61046927SAndroid Build Coastguard Worker {
1216*61046927SAndroid Build Coastguard Worker    read_pixels(x, y, width, height, format, type, bufSize, pixels, false);
1217*61046927SAndroid Build Coastguard Worker }
1218*61046927SAndroid Build Coastguard Worker 
1219*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_ReadPixels_no_error(GLint x,GLint y,GLsizei width,GLsizei height,GLenum format,GLenum type,GLvoid * pixels)1220*61046927SAndroid Build Coastguard Worker _mesa_ReadPixels_no_error(GLint x, GLint y, GLsizei width, GLsizei height,
1221*61046927SAndroid Build Coastguard Worker                           GLenum format, GLenum type, GLvoid *pixels)
1222*61046927SAndroid Build Coastguard Worker {
1223*61046927SAndroid Build Coastguard Worker    _mesa_ReadnPixelsARB_no_error(x, y, width, height, format, type, INT_MAX,
1224*61046927SAndroid Build Coastguard Worker                                  pixels);
1225*61046927SAndroid Build Coastguard Worker }
1226*61046927SAndroid Build Coastguard Worker 
1227*61046927SAndroid Build Coastguard Worker void GLAPIENTRY
_mesa_ReadPixels(GLint x,GLint y,GLsizei width,GLsizei height,GLenum format,GLenum type,GLvoid * pixels)1228*61046927SAndroid Build Coastguard Worker _mesa_ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height,
1229*61046927SAndroid Build Coastguard Worker                  GLenum format, GLenum type, GLvoid *pixels)
1230*61046927SAndroid Build Coastguard Worker {
1231*61046927SAndroid Build Coastguard Worker    _mesa_ReadnPixelsARB(x, y, width, height, format, type, INT_MAX, pixels);
1232*61046927SAndroid Build Coastguard Worker }
1233