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