blob: 470182ab23d7796abd373c0258a4c40fd937a59d [file] [log] [blame]
Brian Paul28876dd2008-06-09 14:22:15 -06001/*
2 * Mesa 3-D graphics library
Brian Paul28876dd2008-06-09 14:22:15 -06003 *
4 * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
Kenneth Graunke3d8d5b22013-04-21 13:46:48 -070019 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
Brian Paul28876dd2008-06-09 14:22:15 -060023 */
24
25#include "glheader.h"
26#include "imports.h"
Marek Olšák21d407c2013-03-28 01:50:21 +010027#include "blend.h"
Brian Paul28876dd2008-06-09 14:22:15 -060028#include "bufferobj.h"
29#include "context.h"
Brian Paul6364d752011-02-18 09:53:29 -070030#include "enums.h"
Brian Paul28876dd2008-06-09 14:22:15 -060031#include "readpix.h"
32#include "framebuffer.h"
Brian Paul751e10f2010-10-25 19:07:33 -060033#include "formats.h"
Brian Pauld2a23d42011-11-12 11:50:31 -070034#include "format_unpack.h"
Brian Paul28876dd2008-06-09 14:22:15 -060035#include "image.h"
Vinson Lee0117da42011-01-05 23:11:54 -080036#include "mtypes.h"
Brian Pauld2a23d42011-11-12 11:50:31 -070037#include "pack.h"
Brian Paulb70610b2011-02-28 18:24:35 -070038#include "pbo.h"
Brian Paul28876dd2008-06-09 14:22:15 -060039#include "state.h"
Jordan Justen9ad8f432012-06-25 10:52:39 -070040#include "glformats.h"
Paul Berry284ad9c2012-07-18 12:54:48 -070041#include "fbobject.h"
Iago Toral Quiroga5038d832014-10-23 10:04:56 +020042#include "format_utils.h"
43#include "pixeltransfer.h"
Brian Paul28876dd2008-06-09 14:22:15 -060044
45
46/**
Marek Olšák2dc20662013-03-14 13:15:54 +010047 * Return true if the conversion L=R+G+B is needed.
48 */
Anuj Phogatba2b1f82015-05-01 00:05:18 -070049GLboolean
Anuj Phogat4b874562015-06-12 14:42:57 -070050_mesa_need_rgb_to_luminance_conversion(GLenum srcBaseFormat,
51 GLenum dstBaseFormat)
Marek Olšák2dc20662013-03-14 13:15:54 +010052{
Anuj Phogat4b874562015-06-12 14:42:57 -070053 return (srcBaseFormat == GL_RG ||
54 srcBaseFormat == GL_RGB ||
55 srcBaseFormat == GL_RGBA) &&
56 (dstBaseFormat == GL_LUMINANCE ||
57 dstBaseFormat == GL_LUMINANCE_ALPHA);
Marek Olšák2dc20662013-03-14 13:15:54 +010058}
59
Anuj Phogatc59c0f82015-06-11 16:48:26 -070060/**
61 * Return true if the conversion L,I to RGB conversion is needed.
62 */
63GLboolean
64_mesa_need_luminance_to_rgb_conversion(GLenum srcBaseFormat,
65 GLenum dstBaseFormat)
66{
67 return (srcBaseFormat == GL_LUMINANCE ||
68 srcBaseFormat == GL_LUMINANCE_ALPHA ||
69 srcBaseFormat == GL_INTENSITY) &&
70 (dstBaseFormat == GL_GREEN ||
71 dstBaseFormat == GL_BLUE ||
72 dstBaseFormat == GL_RG ||
73 dstBaseFormat == GL_RGB ||
74 dstBaseFormat == GL_BGR ||
75 dstBaseFormat == GL_RGBA ||
76 dstBaseFormat == GL_BGRA);
77}
Marek Olšák2dc20662013-03-14 13:15:54 +010078
79/**
80 * Return transfer op flags for this ReadPixels operation.
81 */
Anuj Phogat7974e232015-05-19 17:44:52 -070082GLbitfield
83_mesa_get_readpixels_transfer_ops(const struct gl_context *ctx,
84 mesa_format texFormat,
85 GLenum format, GLenum type,
86 GLboolean uses_blit)
Marek Olšák2dc20662013-03-14 13:15:54 +010087{
88 GLbitfield transferOps = ctx->_ImageTransferState;
Anuj Phogat4b874562015-06-12 14:42:57 -070089 GLenum srcBaseFormat = _mesa_get_format_base_format(texFormat);
90 GLenum dstBaseFormat = _mesa_unpack_format_to_base_format(format);
Marek Olšák2dc20662013-03-14 13:15:54 +010091
92 if (format == GL_DEPTH_COMPONENT ||
93 format == GL_DEPTH_STENCIL ||
94 format == GL_STENCIL_INDEX) {
95 return 0;
96 }
97
98 /* Pixel transfer ops (scale, bias, table lookup) do not apply
99 * to integer formats.
100 */
101 if (_mesa_is_enum_format_integer(format)) {
102 return 0;
103 }
104
105 if (uses_blit) {
106 /* For blit-based ReadPixels packing, the clamping is done automatically
107 * unless the type is float. */
Laura Ekstrand39be0c52015-03-03 15:05:16 -0800108 if (_mesa_get_clamp_read_color(ctx, ctx->ReadBuffer) &&
Marek Olšák2dc20662013-03-14 13:15:54 +0100109 (type == GL_FLOAT || type == GL_HALF_FLOAT)) {
110 transferOps |= IMAGE_CLAMP_BIT;
111 }
112 }
113 else {
114 /* For CPU-based ReadPixels packing, the clamping must always be done
115 * for non-float types, */
Laura Ekstrand39be0c52015-03-03 15:05:16 -0800116 if (_mesa_get_clamp_read_color(ctx, ctx->ReadBuffer) ||
Marek Olšák2dc20662013-03-14 13:15:54 +0100117 (type != GL_FLOAT && type != GL_HALF_FLOAT)) {
118 transferOps |= IMAGE_CLAMP_BIT;
119 }
120 }
121
122 /* If the format is unsigned normalized, we can ignore clamping
123 * because the values are already in the range [0,1] so it won't
124 * have any effect anyway.
125 */
126 if (_mesa_get_format_datatype(texFormat) == GL_UNSIGNED_NORMALIZED &&
Anuj Phogat4b874562015-06-12 14:42:57 -0700127 !_mesa_need_rgb_to_luminance_conversion(srcBaseFormat, dstBaseFormat)) {
Marek Olšák2dc20662013-03-14 13:15:54 +0100128 transferOps &= ~IMAGE_CLAMP_BIT;
129 }
130
131 return transferOps;
132}
133
134
135/**
Marek Olšákd702c672013-03-14 15:20:27 +0100136 * Return true if memcpy cannot be used for ReadPixels.
137 *
138 * If uses_blit is true, the function returns true if a simple 3D engine blit
139 * cannot be used for ReadPixels packing.
140 *
141 * NOTE: This doesn't take swizzling and format conversions between
142 * the readbuffer and the pixel pack buffer into account.
143 */
144GLboolean
145_mesa_readpixels_needs_slow_path(const struct gl_context *ctx, GLenum format,
146 GLenum type, GLboolean uses_blit)
147{
148 struct gl_renderbuffer *rb =
149 _mesa_get_read_renderbuffer_for_format(ctx, format);
Anuj Phogat4b874562015-06-12 14:42:57 -0700150 GLenum dstBaseFormat = _mesa_unpack_format_to_base_format(format);
Marek Olšákd702c672013-03-14 15:20:27 +0100151
Matt Turnerbfcdb842015-02-20 20:18:47 -0800152 assert(rb);
Marek Olšákd702c672013-03-14 15:20:27 +0100153
154 /* There are different rules depending on the base format. */
155 switch (format) {
156 case GL_DEPTH_STENCIL:
157 return !_mesa_has_depthstencil_combined(ctx->ReadBuffer) ||
158 ctx->Pixel.DepthScale != 1.0f || ctx->Pixel.DepthBias != 0.0f ||
159 ctx->Pixel.IndexShift || ctx->Pixel.IndexOffset ||
160 ctx->Pixel.MapStencilFlag;
161
162 case GL_DEPTH_COMPONENT:
163 return ctx->Pixel.DepthScale != 1.0f || ctx->Pixel.DepthBias != 0.0f;
164
165 case GL_STENCIL_INDEX:
166 return ctx->Pixel.IndexShift || ctx->Pixel.IndexOffset ||
167 ctx->Pixel.MapStencilFlag;
168
169 default:
170 /* Color formats. */
Anuj Phogat4b874562015-06-12 14:42:57 -0700171 if (_mesa_need_rgb_to_luminance_conversion(rb->_BaseFormat,
172 dstBaseFormat)) {
Marek Olšákd702c672013-03-14 15:20:27 +0100173 return GL_TRUE;
174 }
175
Marek Olšákd702c672013-03-14 15:20:27 +0100176 /* And finally, see if there are any transfer ops. */
Anuj Phogat7974e232015-05-19 17:44:52 -0700177 return _mesa_get_readpixels_transfer_ops(ctx, rb->Format, format, type,
178 uses_blit) != 0;
Marek Olšákd702c672013-03-14 15:20:27 +0100179 }
180 return GL_FALSE;
181}
182
183
184static GLboolean
185readpixels_can_use_memcpy(const struct gl_context *ctx, GLenum format, GLenum type,
186 const struct gl_pixelstore_attrib *packing)
187{
188 struct gl_renderbuffer *rb =
189 _mesa_get_read_renderbuffer_for_format(ctx, format);
190
Matt Turnerbfcdb842015-02-20 20:18:47 -0800191 assert(rb);
Marek Olšákd702c672013-03-14 15:20:27 +0100192
193 if (_mesa_readpixels_needs_slow_path(ctx, format, type, GL_FALSE)) {
194 return GL_FALSE;
195 }
196
197 /* The base internal format and the base Mesa format must match. */
198 if (rb->_BaseFormat != _mesa_get_format_base_format(rb->Format)) {
199 return GL_FALSE;
200 }
201
202 /* The Mesa format must match the input format and type. */
203 if (!_mesa_format_matches_format_and_type(rb->Format, format, type,
Nanley Chery26c549e2015-07-31 10:26:36 -0700204 packing->SwapBytes, NULL)) {
Marek Olšákd702c672013-03-14 15:20:27 +0100205 return GL_FALSE;
206 }
207
208 return GL_TRUE;
209}
210
211
212static GLboolean
213readpixels_memcpy(struct gl_context *ctx,
214 GLint x, GLint y,
215 GLsizei width, GLsizei height,
216 GLenum format, GLenum type,
217 GLvoid *pixels,
218 const struct gl_pixelstore_attrib *packing)
219{
220 struct gl_renderbuffer *rb =
221 _mesa_get_read_renderbuffer_for_format(ctx, format);
222 GLubyte *dst, *map;
223 int dstStride, stride, j, texelBytes;
224
225 /* Fail if memcpy cannot be used. */
226 if (!readpixels_can_use_memcpy(ctx, format, type, packing)) {
227 return GL_FALSE;
228 }
229
230 dstStride = _mesa_image_row_stride(packing, width, format, type);
231 dst = (GLubyte *) _mesa_image_address2d(packing, pixels, width, height,
232 format, type, 0, 0);
233
234 ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT,
235 &map, &stride);
236 if (!map) {
237 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
238 return GL_TRUE; /* don't bother trying the slow path */
239 }
240
241 texelBytes = _mesa_get_format_bytes(rb->Format);
242
243 /* memcpy*/
244 for (j = 0; j < height; j++) {
245 memcpy(dst, map, width * texelBytes);
246 dst += dstStride;
247 map += stride;
248 }
249
250 ctx->Driver.UnmapRenderbuffer(ctx, rb);
251 return GL_TRUE;
252}
253
254
255/**
256 * Optimized path for conversion of depth values to GL_DEPTH_COMPONENT,
257 * GL_UNSIGNED_INT.
Brian Pauld2a23d42011-11-12 11:50:31 -0700258 */
259static GLboolean
Marek Olšákd702c672013-03-14 15:20:27 +0100260read_uint_depth_pixels( struct gl_context *ctx,
Brian Pauld2a23d42011-11-12 11:50:31 -0700261 GLint x, GLint y,
262 GLsizei width, GLsizei height,
263 GLenum type, GLvoid *pixels,
264 const struct gl_pixelstore_attrib *packing )
265{
266 struct gl_framebuffer *fb = ctx->ReadBuffer;
267 struct gl_renderbuffer *rb = fb->Attachment[BUFFER_DEPTH].Renderbuffer;
268 GLubyte *map, *dst;
269 int stride, dstStride, j;
270
Matt Turnera5623132015-07-12 23:15:42 -0700271 if (ctx->Pixel.DepthScale != 1.0F || ctx->Pixel.DepthBias != 0.0F)
Brian Pauld2a23d42011-11-12 11:50:31 -0700272 return GL_FALSE;
273
274 if (packing->SwapBytes)
275 return GL_FALSE;
276
Eric Anholt755f0a02011-11-17 13:56:30 -0800277 if (_mesa_get_format_datatype(rb->Format) != GL_UNSIGNED_NORMALIZED)
Brian Pauld2a23d42011-11-12 11:50:31 -0700278 return GL_FALSE;
279
Brian Pauld2a23d42011-11-12 11:50:31 -0700280 ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT,
281 &map, &stride);
282
Brian Paul038a7df2011-11-17 17:20:05 -0700283 if (!map) {
284 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
285 return GL_TRUE; /* don't bother trying the slow path */
286 }
287
Brian Pauld2a23d42011-11-12 11:50:31 -0700288 dstStride = _mesa_image_row_stride(packing, width, GL_DEPTH_COMPONENT, type);
289 dst = (GLubyte *) _mesa_image_address2d(packing, pixels, width, height,
290 GL_DEPTH_COMPONENT, type, 0, 0);
291
292 for (j = 0; j < height; j++) {
Marek Olšákd702c672013-03-14 15:20:27 +0100293 _mesa_unpack_uint_z_row(rb->Format, width, map, (GLuint *)dst);
Brian Pauld2a23d42011-11-12 11:50:31 -0700294
295 map += stride;
296 dst += dstStride;
297 }
298 ctx->Driver.UnmapRenderbuffer(ctx, rb);
299
300 return GL_TRUE;
301}
302
303/**
304 * Read pixels for format=GL_DEPTH_COMPONENT.
305 */
306static void
307read_depth_pixels( struct gl_context *ctx,
308 GLint x, GLint y,
309 GLsizei width, GLsizei height,
310 GLenum type, GLvoid *pixels,
311 const struct gl_pixelstore_attrib *packing )
312{
313 struct gl_framebuffer *fb = ctx->ReadBuffer;
314 struct gl_renderbuffer *rb = fb->Attachment[BUFFER_DEPTH].Renderbuffer;
315 GLint j;
316 GLubyte *dst, *map;
317 int dstStride, stride;
Brian Paul531eaca2012-02-19 20:08:51 -0700318 GLfloat *depthValues;
Brian Pauld2a23d42011-11-12 11:50:31 -0700319
320 if (!rb)
321 return;
322
323 /* clipping should have been done already */
Matt Turnerbfcdb842015-02-20 20:18:47 -0800324 assert(x >= 0);
325 assert(y >= 0);
326 assert(x + width <= (GLint) rb->Width);
327 assert(y + height <= (GLint) rb->Height);
Brian Pauld2a23d42011-11-12 11:50:31 -0700328
Marek Olšákd702c672013-03-14 15:20:27 +0100329 if (type == GL_UNSIGNED_INT &&
330 read_uint_depth_pixels(ctx, x, y, width, height, type, pixels, packing)) {
Brian Pauld2a23d42011-11-12 11:50:31 -0700331 return;
Marek Olšákd702c672013-03-14 15:20:27 +0100332 }
Brian Pauld2a23d42011-11-12 11:50:31 -0700333
334 dstStride = _mesa_image_row_stride(packing, width, GL_DEPTH_COMPONENT, type);
335 dst = (GLubyte *) _mesa_image_address2d(packing, pixels, width, height,
336 GL_DEPTH_COMPONENT, type, 0, 0);
337
338 ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT,
339 &map, &stride);
Brian Paul038a7df2011-11-17 17:20:05 -0700340 if (!map) {
341 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
342 return;
343 }
Brian Pauld2a23d42011-11-12 11:50:31 -0700344
Matt Turner2b7a9722012-09-03 19:44:00 -0700345 depthValues = malloc(width * sizeof(GLfloat));
Brian Pauld2a23d42011-11-12 11:50:31 -0700346
Brian Paul531eaca2012-02-19 20:08:51 -0700347 if (depthValues) {
348 /* General case (slower) */
349 for (j = 0; j < height; j++, y++) {
350 _mesa_unpack_float_z_row(rb->Format, width, map, depthValues);
351 _mesa_pack_depth_span(ctx, width, dst, type, depthValues, packing);
352
353 dst += dstStride;
354 map += stride;
355 }
Brian Pauld2a23d42011-11-12 11:50:31 -0700356 }
Brian Paul531eaca2012-02-19 20:08:51 -0700357 else {
358 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
359 }
360
361 free(depthValues);
Brian Pauld2a23d42011-11-12 11:50:31 -0700362
363 ctx->Driver.UnmapRenderbuffer(ctx, rb);
364}
365
366
367/**
368 * Read pixels for format=GL_STENCIL_INDEX.
369 */
370static void
371read_stencil_pixels( struct gl_context *ctx,
372 GLint x, GLint y,
373 GLsizei width, GLsizei height,
374 GLenum type, GLvoid *pixels,
375 const struct gl_pixelstore_attrib *packing )
376{
377 struct gl_framebuffer *fb = ctx->ReadBuffer;
378 struct gl_renderbuffer *rb = fb->Attachment[BUFFER_STENCIL].Renderbuffer;
379 GLint j;
Brian Paul531eaca2012-02-19 20:08:51 -0700380 GLubyte *map, *stencil;
Brian Pauld2a23d42011-11-12 11:50:31 -0700381 GLint stride;
382
383 if (!rb)
384 return;
385
Brian Pauld2a23d42011-11-12 11:50:31 -0700386 ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT,
387 &map, &stride);
Brian Paul038a7df2011-11-17 17:20:05 -0700388 if (!map) {
389 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
390 return;
391 }
Brian Pauld2a23d42011-11-12 11:50:31 -0700392
Matt Turner2b7a9722012-09-03 19:44:00 -0700393 stencil = malloc(width * sizeof(GLubyte));
Brian Pauld2a23d42011-11-12 11:50:31 -0700394
Brian Paul531eaca2012-02-19 20:08:51 -0700395 if (stencil) {
396 /* process image row by row */
397 for (j = 0; j < height; j++) {
398 GLvoid *dest;
Brian Pauld2a23d42011-11-12 11:50:31 -0700399
Brian Paul531eaca2012-02-19 20:08:51 -0700400 _mesa_unpack_ubyte_stencil_row(rb->Format, width, map, stencil);
401 dest = _mesa_image_address2d(packing, pixels, width, height,
402 GL_STENCIL_INDEX, type, j, 0);
Brian Pauld2a23d42011-11-12 11:50:31 -0700403
Brian Paul531eaca2012-02-19 20:08:51 -0700404 _mesa_pack_stencil_span(ctx, width, type, dest, stencil, packing);
405
406 map += stride;
407 }
Brian Pauld2a23d42011-11-12 11:50:31 -0700408 }
Brian Paul531eaca2012-02-19 20:08:51 -0700409 else {
410 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
411 }
412
413 free(stencil);
Brian Pauld2a23d42011-11-12 11:50:31 -0700414
415 ctx->Driver.UnmapRenderbuffer(ctx, rb);
416}
417
Brian Pauld2a23d42011-11-12 11:50:31 -0700418/*
419 * Read R, G, B, A, RGB, L, or LA pixels.
420 */
421static void
422read_rgba_pixels( struct gl_context *ctx,
423 GLint x, GLint y,
424 GLsizei width, GLsizei height,
425 GLenum format, GLenum type, GLvoid *pixels,
426 const struct gl_pixelstore_attrib *packing )
427{
Marek Olšák2dc20662013-03-14 13:15:54 +0100428 GLbitfield transferOps;
Anuj Phogat0b13adc2015-04-30 23:36:18 -0700429 bool dst_is_integer, convert_rgb_to_lum, needs_rebase;
Iago Toral Quiroga5038d832014-10-23 10:04:56 +0200430 int dst_stride, src_stride, rb_stride;
431 uint32_t dst_format, src_format;
432 GLubyte *dst, *map;
433 mesa_format rb_format;
434 bool needs_rgba;
435 void *rgba, *src;
436 bool src_is_uint = false;
437 uint8_t rebase_swizzle[4];
Brian Pauld2a23d42011-11-12 11:50:31 -0700438 struct gl_framebuffer *fb = ctx->ReadBuffer;
439 struct gl_renderbuffer *rb = fb->_ColorReadBuffer;
Anuj Phogat4b874562015-06-12 14:42:57 -0700440 GLenum dstBaseFormat = _mesa_unpack_format_to_base_format(format);
Brian Pauld2a23d42011-11-12 11:50:31 -0700441
442 if (!rb)
443 return;
444
Anuj Phogat7974e232015-05-19 17:44:52 -0700445 transferOps = _mesa_get_readpixels_transfer_ops(ctx, rb->Format, format,
446 type, GL_FALSE);
Iago Toral Quiroga5038d832014-10-23 10:04:56 +0200447 /* Describe the dst format */
448 dst_is_integer = _mesa_is_enum_format_integer(format);
449 dst_stride = _mesa_image_row_stride(packing, width, format, type);
450 dst_format = _mesa_format_from_format_and_type(format, type);
Anuj Phogatba2b1f82015-05-01 00:05:18 -0700451 convert_rgb_to_lum =
Anuj Phogat4b874562015-06-12 14:42:57 -0700452 _mesa_need_rgb_to_luminance_conversion(rb->_BaseFormat, dstBaseFormat);
Iago Toral Quiroga5038d832014-10-23 10:04:56 +0200453 dst = (GLubyte *) _mesa_image_address2d(packing, pixels, width, height,
454 format, type, 0, 0);
Brian Pauld2a23d42011-11-12 11:50:31 -0700455
Iago Toral Quiroga5038d832014-10-23 10:04:56 +0200456 /* Map the source render buffer */
457 ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT,
458 &map, &rb_stride);
459 if (!map) {
460 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
Neil Robertsd9c420972012-02-26 01:33:40 +0000461 return;
Brian Pauld2a23d42011-11-12 11:50:31 -0700462 }
Iago Toral Quiroga5038d832014-10-23 10:04:56 +0200463 rb_format = _mesa_get_srgb_format_linear(rb->Format);
Brian Pauld2a23d42011-11-12 11:50:31 -0700464
Iago Toral Quiroga5038d832014-10-23 10:04:56 +0200465 /*
466 * Depending on the base formats involved in the conversion we might need to
467 * rebase some values, so for these formats we compute a rebase swizzle.
468 */
469 if (rb->_BaseFormat == GL_LUMINANCE || rb->_BaseFormat == GL_INTENSITY) {
470 needs_rebase = true;
471 rebase_swizzle[0] = MESA_FORMAT_SWIZZLE_X;
472 rebase_swizzle[1] = MESA_FORMAT_SWIZZLE_ZERO;
473 rebase_swizzle[2] = MESA_FORMAT_SWIZZLE_ZERO;
474 rebase_swizzle[3] = MESA_FORMAT_SWIZZLE_ONE;
475 } else if (rb->_BaseFormat == GL_LUMINANCE_ALPHA) {
476 needs_rebase = true;
477 rebase_swizzle[0] = MESA_FORMAT_SWIZZLE_X;
478 rebase_swizzle[1] = MESA_FORMAT_SWIZZLE_ZERO;
479 rebase_swizzle[2] = MESA_FORMAT_SWIZZLE_ZERO;
480 rebase_swizzle[3] = MESA_FORMAT_SWIZZLE_W;
481 } else if (_mesa_get_format_base_format(rb_format) != rb->_BaseFormat) {
482 needs_rebase =
483 _mesa_compute_rgba2base2rgba_component_mapping(rb->_BaseFormat,
484 rebase_swizzle);
485 } else {
486 needs_rebase = false;
487 }
488
489 /* Since _mesa_format_convert does not handle transferOps we need to handle
490 * them before we call the function. This requires to convert to RGBA float
491 * first so we can call _mesa_apply_rgba_transfer_ops. If the dst format is
492 * integer transferOps do not apply.
493 *
494 * Converting to luminance also requires converting to RGBA first, so we can
495 * then compute luminance values as L=R+G+B. Notice that this is different
496 * from GetTexImage, where we compute L=R.
497 */
498 assert(!transferOps || (transferOps && !dst_is_integer));
499
Anuj Phogat0b13adc2015-04-30 23:36:18 -0700500 needs_rgba = transferOps || convert_rgb_to_lum;
Iago Toral Quiroga5038d832014-10-23 10:04:56 +0200501 rgba = NULL;
502 if (needs_rgba) {
503 uint32_t rgba_format;
504 int rgba_stride;
505 bool need_convert;
506
507 /* Convert to RGBA float or int/uint depending on the type of the src */
508 if (dst_is_integer) {
509 src_is_uint = _mesa_is_format_unsigned(rb_format);
510 if (src_is_uint) {
Iago Toral Quirogac6a26282015-01-13 08:33:19 +0100511 rgba_format = RGBA32_UINT;
Iago Toral Quiroga5038d832014-10-23 10:04:56 +0200512 rgba_stride = width * 4 * sizeof(GLuint);
513 } else {
Iago Toral Quirogac6a26282015-01-13 08:33:19 +0100514 rgba_format = RGBA32_INT;
Iago Toral Quiroga5038d832014-10-23 10:04:56 +0200515 rgba_stride = width * 4 * sizeof(GLint);
516 }
517 } else {
Iago Toral Quirogac6a26282015-01-13 08:33:19 +0100518 rgba_format = RGBA32_FLOAT;
Iago Toral Quiroga5038d832014-10-23 10:04:56 +0200519 rgba_stride = width * 4 * sizeof(GLfloat);
520 }
521
522 /* If we are lucky and the dst format matches the RGBA format we need to
523 * convert to, then we can convert directly into the dst buffer and avoid
524 * the final conversion/copy from the rgba buffer to the dst buffer.
525 */
Dave Airlie32769ac2015-09-01 15:57:02 +1000526 if (dst_format == rgba_format &&
527 dst_stride == rgba_stride) {
Iago Toral Quiroga5038d832014-10-23 10:04:56 +0200528 need_convert = false;
529 rgba = dst;
530 } else {
531 need_convert = true;
532 rgba = malloc(height * rgba_stride);
533 if (!rgba) {
534 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
535 goto done_unmap;
536 }
537 }
538
539 /* Convert to RGBA now */
540 _mesa_format_convert(rgba, rgba_format, rgba_stride,
541 map, rb_format, rb_stride,
542 width, height,
543 needs_rebase ? rebase_swizzle : NULL);
544
545 /* Handle transfer ops if necessary */
546 if (transferOps)
547 _mesa_apply_rgba_transfer_ops(ctx, transferOps, width * height, rgba);
548
549 /* If we had to rebase, we have already taken care of that */
550 needs_rebase = false;
551
552 /* If we were lucky and our RGBA conversion matches the dst format, then
553 * we are done.
554 */
555 if (!need_convert)
556 goto done_swap;
557
558 /* Otherwise, we need to convert from RGBA to dst next */
559 src = rgba;
560 src_format = rgba_format;
561 src_stride = rgba_stride;
562 } else {
563 /* No RGBA conversion needed, convert directly to dst */
564 src = map;
565 src_format = rb_format;
566 src_stride = rb_stride;
567 }
568
569 /* Do the conversion.
570 *
571 * If the dst format is Luminance, we need to do the conversion by computing
572 * L=R+G+B values.
573 */
Anuj Phogat0b13adc2015-04-30 23:36:18 -0700574 if (!convert_rgb_to_lum) {
Iago Toral Quiroga5038d832014-10-23 10:04:56 +0200575 _mesa_format_convert(dst, dst_format, dst_stride,
576 src, src_format, src_stride,
577 width, height,
578 needs_rebase ? rebase_swizzle : NULL);
579 } else if (!dst_is_integer) {
580 /* Compute float Luminance values from RGBA float */
581 int luminance_stride, luminance_bytes;
582 void *luminance;
583 uint32_t luminance_format;
584
585 luminance_stride = width * sizeof(GL_FLOAT);
586 if (format == GL_LUMINANCE_ALPHA)
587 luminance_stride *= 2;
588 luminance_bytes = height * luminance_stride;
589 luminance = malloc(luminance_bytes);
590 if (!luminance) {
591 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
592 free(rgba);
593 goto done_unmap;
594 }
595 _mesa_pack_luminance_from_rgba_float(width * height, src,
596 luminance, format, transferOps);
597
598 /* Convert from Luminance float to dst (this will hadle type conversion
599 * from float to the type of dst if necessary)
600 */
601 luminance_format = _mesa_format_from_format_and_type(format, GL_FLOAT);
602 _mesa_format_convert(dst, dst_format, dst_stride,
603 luminance, luminance_format, luminance_stride,
604 width, height, NULL);
Matt Turner87109ac2015-02-28 11:08:17 -0800605 free(luminance);
Iago Toral Quiroga5038d832014-10-23 10:04:56 +0200606 } else {
607 _mesa_pack_luminance_from_rgba_integer(width * height, src, !src_is_uint,
608 dst, format, type);
609 }
610
611 if (rgba)
612 free(rgba);
613
614done_swap:
615 /* Handle byte swapping if required */
616 if (packing->SwapBytes) {
Dave Airlie0ad3a472015-08-25 14:36:01 +1000617 _mesa_swap_bytes_2d_image(format, type, packing,
618 width, height, dst, dst);
Iago Toral Quiroga5038d832014-10-23 10:04:56 +0200619 }
620
621done_unmap:
622 ctx->Driver.UnmapRenderbuffer(ctx, rb);
Brian Pauld2a23d42011-11-12 11:50:31 -0700623}
624
625/**
626 * For a packed depth/stencil buffer being read as depth/stencil, just memcpy the
627 * data (possibly swapping 8/24 vs 24/8 as we go).
628 */
629static GLboolean
630fast_read_depth_stencil_pixels(struct gl_context *ctx,
631 GLint x, GLint y,
632 GLsizei width, GLsizei height,
633 GLubyte *dst, int dstStride)
634{
635 struct gl_framebuffer *fb = ctx->ReadBuffer;
636 struct gl_renderbuffer *rb = fb->Attachment[BUFFER_DEPTH].Renderbuffer;
637 struct gl_renderbuffer *stencilRb = fb->Attachment[BUFFER_STENCIL].Renderbuffer;
638 GLubyte *map;
639 int stride, i;
640
641 if (rb != stencilRb)
642 return GL_FALSE;
643
Mark Muellereeed49f2014-01-26 15:12:56 -0800644 if (rb->Format != MESA_FORMAT_S8_UINT_Z24_UNORM &&
Kenneth Graunkea487ef82014-02-07 21:53:18 -0800645 rb->Format != MESA_FORMAT_Z24_UNORM_S8_UINT)
Brian Pauld2a23d42011-11-12 11:50:31 -0700646 return GL_FALSE;
647
648 ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT,
649 &map, &stride);
Brian Paul038a7df2011-11-17 17:20:05 -0700650 if (!map) {
651 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
652 return GL_TRUE; /* don't bother trying the slow path */
653 }
Brian Pauld2a23d42011-11-12 11:50:31 -0700654
655 for (i = 0; i < height; i++) {
656 _mesa_unpack_uint_24_8_depth_stencil_row(rb->Format, width,
657 map, (GLuint *)dst);
658 map += stride;
659 dst += dstStride;
660 }
661
662 ctx->Driver.UnmapRenderbuffer(ctx, rb);
663
664 return GL_TRUE;
665}
666
667
668/**
669 * For non-float-depth and stencil buffers being read as 24/8 depth/stencil,
670 * copy the integer data directly instead of converting depth to float and
671 * re-packing.
672 */
673static GLboolean
674fast_read_depth_stencil_pixels_separate(struct gl_context *ctx,
675 GLint x, GLint y,
676 GLsizei width, GLsizei height,
677 uint32_t *dst, int dstStride)
678{
679 struct gl_framebuffer *fb = ctx->ReadBuffer;
680 struct gl_renderbuffer *depthRb = fb->Attachment[BUFFER_DEPTH].Renderbuffer;
681 struct gl_renderbuffer *stencilRb = fb->Attachment[BUFFER_STENCIL].Renderbuffer;
Brian Paul531eaca2012-02-19 20:08:51 -0700682 GLubyte *depthMap, *stencilMap, *stencilVals;
Brian Pauld2a23d42011-11-12 11:50:31 -0700683 int depthStride, stencilStride, i, j;
684
Eric Anholt755f0a02011-11-17 13:56:30 -0800685 if (_mesa_get_format_datatype(depthRb->Format) != GL_UNSIGNED_NORMALIZED)
Brian Pauld2a23d42011-11-12 11:50:31 -0700686 return GL_FALSE;
687
688 ctx->Driver.MapRenderbuffer(ctx, depthRb, x, y, width, height,
689 GL_MAP_READ_BIT, &depthMap, &depthStride);
Brian Paul038a7df2011-11-17 17:20:05 -0700690 if (!depthMap) {
691 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
692 return GL_TRUE; /* don't bother trying the slow path */
693 }
694
Brian Pauld2a23d42011-11-12 11:50:31 -0700695 ctx->Driver.MapRenderbuffer(ctx, stencilRb, x, y, width, height,
696 GL_MAP_READ_BIT, &stencilMap, &stencilStride);
Brian Paul038a7df2011-11-17 17:20:05 -0700697 if (!stencilMap) {
698 ctx->Driver.UnmapRenderbuffer(ctx, depthRb);
699 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
700 return GL_TRUE; /* don't bother trying the slow path */
701 }
Brian Pauld2a23d42011-11-12 11:50:31 -0700702
Matt Turner2b7a9722012-09-03 19:44:00 -0700703 stencilVals = malloc(width * sizeof(GLubyte));
Brian Pauld2a23d42011-11-12 11:50:31 -0700704
Brian Paul531eaca2012-02-19 20:08:51 -0700705 if (stencilVals) {
706 for (j = 0; j < height; j++) {
707 _mesa_unpack_uint_z_row(depthRb->Format, width, depthMap, dst);
708 _mesa_unpack_ubyte_stencil_row(stencilRb->Format, width,
709 stencilMap, stencilVals);
Brian Pauld2a23d42011-11-12 11:50:31 -0700710
Brian Paul531eaca2012-02-19 20:08:51 -0700711 for (i = 0; i < width; i++) {
712 dst[i] = (dst[i] & 0xffffff00) | stencilVals[i];
713 }
714
715 depthMap += depthStride;
716 stencilMap += stencilStride;
717 dst += dstStride / 4;
Brian Pauld2a23d42011-11-12 11:50:31 -0700718 }
Brian Pauld2a23d42011-11-12 11:50:31 -0700719 }
Brian Paul531eaca2012-02-19 20:08:51 -0700720 else {
721 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
722 }
723
724 free(stencilVals);
Brian Pauld2a23d42011-11-12 11:50:31 -0700725
726 ctx->Driver.UnmapRenderbuffer(ctx, depthRb);
727 ctx->Driver.UnmapRenderbuffer(ctx, stencilRb);
728
729 return GL_TRUE;
730}
731
732static void
733slow_read_depth_stencil_pixels_separate(struct gl_context *ctx,
734 GLint x, GLint y,
735 GLsizei width, GLsizei height,
736 GLenum type,
737 const struct gl_pixelstore_attrib *packing,
738 GLubyte *dst, int dstStride)
739{
740 struct gl_framebuffer *fb = ctx->ReadBuffer;
741 struct gl_renderbuffer *depthRb = fb->Attachment[BUFFER_DEPTH].Renderbuffer;
742 struct gl_renderbuffer *stencilRb = fb->Attachment[BUFFER_STENCIL].Renderbuffer;
743 GLubyte *depthMap, *stencilMap;
744 int depthStride, stencilStride, j;
Brian Paul531eaca2012-02-19 20:08:51 -0700745 GLubyte *stencilVals;
746 GLfloat *depthVals;
747
Brian Pauld2a23d42011-11-12 11:50:31 -0700748
Brian Paulf6a50c02011-11-16 07:47:51 -0700749 /* The depth and stencil buffers might be separate, or a single buffer.
750 * If one buffer, only map it once.
751 */
Brian Pauld2a23d42011-11-12 11:50:31 -0700752 ctx->Driver.MapRenderbuffer(ctx, depthRb, x, y, width, height,
753 GL_MAP_READ_BIT, &depthMap, &depthStride);
Brian Paul038a7df2011-11-17 17:20:05 -0700754 if (!depthMap) {
755 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
756 return;
757 }
758
Brian Paulf6a50c02011-11-16 07:47:51 -0700759 if (stencilRb != depthRb) {
760 ctx->Driver.MapRenderbuffer(ctx, stencilRb, x, y, width, height,
761 GL_MAP_READ_BIT, &stencilMap,
762 &stencilStride);
Brian Paul038a7df2011-11-17 17:20:05 -0700763 if (!stencilMap) {
764 ctx->Driver.UnmapRenderbuffer(ctx, depthRb);
765 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
766 return;
767 }
Brian Paulf6a50c02011-11-16 07:47:51 -0700768 }
Brian Paulf4c03da2011-11-16 09:58:45 -0700769 else {
770 stencilMap = depthMap;
771 stencilStride = depthStride;
772 }
Brian Pauld2a23d42011-11-12 11:50:31 -0700773
Matt Turner2b7a9722012-09-03 19:44:00 -0700774 stencilVals = malloc(width * sizeof(GLubyte));
775 depthVals = malloc(width * sizeof(GLfloat));
Brian Pauld2a23d42011-11-12 11:50:31 -0700776
Brian Paul531eaca2012-02-19 20:08:51 -0700777 if (stencilVals && depthVals) {
778 for (j = 0; j < height; j++) {
779 _mesa_unpack_float_z_row(depthRb->Format, width, depthMap, depthVals);
780 _mesa_unpack_ubyte_stencil_row(stencilRb->Format, width,
781 stencilMap, stencilVals);
Brian Pauld2a23d42011-11-12 11:50:31 -0700782
Brian Paul531eaca2012-02-19 20:08:51 -0700783 _mesa_pack_depth_stencil_span(ctx, width, type, (GLuint *)dst,
784 depthVals, stencilVals, packing);
Brian Pauld2a23d42011-11-12 11:50:31 -0700785
Brian Paul531eaca2012-02-19 20:08:51 -0700786 depthMap += depthStride;
787 stencilMap += stencilStride;
788 dst += dstStride;
789 }
Brian Pauld2a23d42011-11-12 11:50:31 -0700790 }
Brian Paul531eaca2012-02-19 20:08:51 -0700791 else {
792 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
793 }
794
795 free(stencilVals);
796 free(depthVals);
Brian Pauld2a23d42011-11-12 11:50:31 -0700797
798 ctx->Driver.UnmapRenderbuffer(ctx, depthRb);
Brian Paulf6a50c02011-11-16 07:47:51 -0700799 if (stencilRb != depthRb) {
800 ctx->Driver.UnmapRenderbuffer(ctx, stencilRb);
801 }
Brian Pauld2a23d42011-11-12 11:50:31 -0700802}
803
804
805/**
806 * Read combined depth/stencil values.
807 * We'll have already done error checking to be sure the expected
808 * depth and stencil buffers really exist.
809 */
810static void
811read_depth_stencil_pixels(struct gl_context *ctx,
812 GLint x, GLint y,
813 GLsizei width, GLsizei height,
814 GLenum type, GLvoid *pixels,
815 const struct gl_pixelstore_attrib *packing )
816{
817 const GLboolean scaleOrBias
Matt Turnera5623132015-07-12 23:15:42 -0700818 = ctx->Pixel.DepthScale != 1.0F || ctx->Pixel.DepthBias != 0.0F;
Brian Pauld2a23d42011-11-12 11:50:31 -0700819 const GLboolean stencilTransfer = ctx->Pixel.IndexShift
820 || ctx->Pixel.IndexOffset || ctx->Pixel.MapStencilFlag;
821 GLubyte *dst;
822 int dstStride;
823
824 dst = (GLubyte *) _mesa_image_address2d(packing, pixels,
825 width, height,
826 GL_DEPTH_STENCIL_EXT,
827 type, 0, 0);
828 dstStride = _mesa_image_row_stride(packing, width,
829 GL_DEPTH_STENCIL_EXT, type);
830
831 /* Fast 24/8 reads. */
832 if (type == GL_UNSIGNED_INT_24_8 &&
833 !scaleOrBias && !stencilTransfer && !packing->SwapBytes) {
834 if (fast_read_depth_stencil_pixels(ctx, x, y, width, height,
835 dst, dstStride))
836 return;
837
838 if (fast_read_depth_stencil_pixels_separate(ctx, x, y, width, height,
839 (uint32_t *)dst, dstStride))
840 return;
841 }
842
843 slow_read_depth_stencil_pixels_separate(ctx, x, y, width, height,
844 type, packing,
845 dst, dstStride);
846}
847
848
849
850/**
851 * Software fallback routine for ctx->Driver.ReadPixels().
852 * By time we get here, all error checking will have been done.
853 */
854void
855_mesa_readpixels(struct gl_context *ctx,
856 GLint x, GLint y, GLsizei width, GLsizei height,
857 GLenum format, GLenum type,
858 const struct gl_pixelstore_attrib *packing,
859 GLvoid *pixels)
860{
Brian Pauld2a23d42011-11-12 11:50:31 -0700861 if (ctx->NewState)
862 _mesa_update_state(ctx);
863
Nanley Cheryc6242412016-02-05 16:25:28 -0800864 pixels = _mesa_map_pbo_dest(ctx, packing, pixels);
Brian Pauld2a23d42011-11-12 11:50:31 -0700865
Nanley Cheryc6242412016-02-05 16:25:28 -0800866 if (pixels) {
867 /* Try memcpy first. */
868 if (readpixels_memcpy(ctx, x, y, width, height, format, type,
869 pixels, packing)) {
Nanley Cheryb89a8a12016-02-05 16:25:01 -0800870 _mesa_unmap_pbo_dest(ctx, packing);
Nanley Cheryc6242412016-02-05 16:25:28 -0800871 return;
Brian Pauld2a23d42011-11-12 11:50:31 -0700872 }
Nanley Cheryc6242412016-02-05 16:25:28 -0800873
874 /* Otherwise take the slow path. */
875 switch (format) {
876 case GL_STENCIL_INDEX:
877 read_stencil_pixels(ctx, x, y, width, height, type, pixels,
878 packing);
879 break;
880 case GL_DEPTH_COMPONENT:
881 read_depth_pixels(ctx, x, y, width, height, type, pixels,
882 packing);
883 break;
884 case GL_DEPTH_STENCIL_EXT:
885 read_depth_stencil_pixels(ctx, x, y, width, height, type, pixels,
886 packing);
887 break;
888 default:
889 /* all other formats should be color formats */
890 read_rgba_pixels(ctx, x, y, width, height, format, type, pixels,
891 packing);
892 }
893
894 _mesa_unmap_pbo_dest(ctx, packing);
895 }
Brian Pauld2a23d42011-11-12 11:50:31 -0700896}
897
898
Jordan Justen8b0bc9d2012-12-28 11:24:37 -0800899static GLenum
900read_pixels_es3_error_check(GLenum format, GLenum type,
901 const struct gl_renderbuffer *rb)
902{
903 const GLenum internalFormat = rb->InternalFormat;
904 const GLenum data_type = _mesa_get_format_datatype(rb->Format);
905 GLboolean is_unsigned_int = GL_FALSE;
906 GLboolean is_signed_int = GL_FALSE;
Rob Clark81d2fd92015-08-10 06:58:37 -0400907 GLboolean is_float_depth = (internalFormat == GL_DEPTH_COMPONENT32F) ||
908 (internalFormat == GL_DEPTH32F_STENCIL8);
Jordan Justen8b0bc9d2012-12-28 11:24:37 -0800909
910 is_unsigned_int = _mesa_is_enum_format_unsigned_int(internalFormat);
911 if (!is_unsigned_int) {
912 is_signed_int = _mesa_is_enum_format_signed_int(internalFormat);
913 }
914
915 switch (format) {
916 case GL_RGBA:
Jordan Justen119002a2013-01-10 17:29:27 -0800917 if (type == GL_FLOAT && data_type == GL_FLOAT)
918 return GL_NO_ERROR; /* EXT_color_buffer_float */
Jordan Justen8b0bc9d2012-12-28 11:24:37 -0800919 if (type == GL_UNSIGNED_BYTE && data_type == GL_UNSIGNED_NORMALIZED)
920 return GL_NO_ERROR;
921 if (internalFormat == GL_RGB10_A2 &&
922 type == GL_UNSIGNED_INT_2_10_10_10_REV)
923 return GL_NO_ERROR;
924 if (internalFormat == GL_RGB10_A2UI && type == GL_UNSIGNED_BYTE)
925 return GL_NO_ERROR;
926 break;
927 case GL_BGRA:
928 /* GL_EXT_read_format_bgra */
929 if (type == GL_UNSIGNED_BYTE ||
930 type == GL_UNSIGNED_SHORT_4_4_4_4_REV ||
931 type == GL_UNSIGNED_SHORT_1_5_5_5_REV)
932 return GL_NO_ERROR;
933 break;
934 case GL_RGBA_INTEGER:
935 if ((is_signed_int && type == GL_INT) ||
936 (is_unsigned_int && type == GL_UNSIGNED_INT))
937 return GL_NO_ERROR;
938 break;
Rob Clark81d2fd92015-08-10 06:58:37 -0400939 case GL_DEPTH_STENCIL:
940 switch (type) {
941 case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
942 if (is_float_depth)
943 return GL_NO_ERROR;
944 break;
945 case GL_UNSIGNED_INT_24_8:
946 if (!is_float_depth)
947 return GL_NO_ERROR;
948 break;
949 default:
950 return GL_INVALID_ENUM;
951 }
952 break;
953 case GL_DEPTH_COMPONENT:
954 switch (type) {
955 case GL_FLOAT:
956 if (is_float_depth)
957 return GL_NO_ERROR;
958 break;
959 case GL_UNSIGNED_SHORT:
Tapani Pälliafa1efd2015-09-15 09:17:20 +0300960 case GL_UNSIGNED_INT:
Rob Clark81d2fd92015-08-10 06:58:37 -0400961 case GL_UNSIGNED_INT_24_8:
962 if (!is_float_depth)
963 return GL_NO_ERROR;
964 break;
965 default:
966 return GL_INVALID_ENUM;
967 }
968 break;
969 case GL_STENCIL_INDEX:
970 switch (type) {
971 case GL_UNSIGNED_BYTE:
972 return GL_NO_ERROR;
973 default:
974 return GL_INVALID_ENUM;
975 }
976 break;
Jordan Justen8b0bc9d2012-12-28 11:24:37 -0800977 }
978
979 return GL_INVALID_OPERATION;
980}
981
982
Brian Paul28876dd2008-06-09 14:22:15 -0600983void GLAPIENTRY
Brian Paul6b329b92011-04-26 14:54:41 -0600984_mesa_ReadnPixelsARB( GLint x, GLint y, GLsizei width, GLsizei height,
985 GLenum format, GLenum type, GLsizei bufSize,
986 GLvoid *pixels )
Brian Paul28876dd2008-06-09 14:22:15 -0600987{
Matt Turner112e3022012-11-30 15:07:54 -0800988 GLenum err = GL_NO_ERROR;
Jordan Justen8b0bc9d2012-12-28 11:24:37 -0800989 struct gl_renderbuffer *rb;
Nanley Chery60583272016-02-05 16:21:33 -0800990 struct gl_pixelstore_attrib clippedPacking;
Brian Paulb8f7eef2012-02-07 07:42:33 -0700991
Brian Paul28876dd2008-06-09 14:22:15 -0600992 GET_CURRENT_CONTEXT(ctx);
Brian Paul28876dd2008-06-09 14:22:15 -0600993
Eric Anholta9754792013-01-16 16:20:38 -0800994 FLUSH_VERTICES(ctx, 0);
Brian Paul28876dd2008-06-09 14:22:15 -0600995 FLUSH_CURRENT(ctx, 0);
996
Brian Paul6364d752011-02-18 09:53:29 -0700997 if (MESA_VERBOSE & VERBOSE_API)
998 _mesa_debug(ctx, "glReadPixels(%d, %d, %s, %s, %p)\n",
999 width, height,
Kenneth Graunke2f11e922015-07-18 01:22:00 -07001000 _mesa_enum_to_string(format),
1001 _mesa_enum_to_string(type),
Brian Paul6364d752011-02-18 09:53:29 -07001002 pixels);
1003
Brian Paul28876dd2008-06-09 14:22:15 -06001004 if (width < 0 || height < 0) {
1005 _mesa_error( ctx, GL_INVALID_VALUE,
1006 "glReadPixels(width=%d height=%d)", width, height );
1007 return;
1008 }
1009
Jordan Justence9118c2012-12-28 11:27:04 -08001010 if (ctx->NewState)
1011 _mesa_update_state(ctx);
1012
1013 if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
1014 _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
1015 "glReadPixels(incomplete framebuffer)" );
1016 return;
1017 }
1018
Jordan Justen8b0bc9d2012-12-28 11:24:37 -08001019 rb = _mesa_get_read_renderbuffer_for_format(ctx, format);
1020 if (rb == NULL) {
1021 _mesa_error(ctx, GL_INVALID_OPERATION,
1022 "glReadPixels(read buffer)");
1023 return;
1024 }
1025
Ian Romanickb7c7e5e2012-07-27 12:24:24 -07001026 /* OpenGL ES 1.x and OpenGL ES 2.0 impose additional restrictions on the
1027 * combinations of format and type that can be used.
1028 *
1029 * Technically, only two combinations are actually allowed:
1030 * GL_RGBA/GL_UNSIGNED_BYTE, and some implementation-specific internal
1031 * preferred combination. This code doesn't know what that preferred
1032 * combination is, and Mesa can handle anything valid. Just work instead.
1033 */
Matt Turner112e3022012-11-30 15:07:54 -08001034 if (_mesa_is_gles(ctx)) {
Jordan Justenffdffd82013-01-12 01:05:44 -08001035 if (ctx->API == API_OPENGLES2 &&
1036 _mesa_is_color_format(format) &&
1037 _mesa_get_color_read_format(ctx) == format &&
1038 _mesa_get_color_read_type(ctx) == type) {
1039 err = GL_NO_ERROR;
1040 } else if (ctx->Version < 30) {
Ilia Mirkin0396eaa2015-11-26 10:32:57 -05001041 err = _mesa_es_error_check_format_and_type(ctx, format, type, 2);
Matt Turner112e3022012-11-30 15:07:54 -08001042 if (err == GL_NO_ERROR) {
1043 if (type == GL_FLOAT || type == GL_HALF_FLOAT_OES) {
1044 err = GL_INVALID_OPERATION;
1045 }
Ian Romanickb7c7e5e2012-07-27 12:24:24 -07001046 }
Jordan Justen8b0bc9d2012-12-28 11:24:37 -08001047 } else {
1048 err = read_pixels_es3_error_check(format, type, rb);
Ian Romanickb7c7e5e2012-07-27 12:24:24 -07001049 }
1050
1051 if (err != GL_NO_ERROR) {
1052 _mesa_error(ctx, err, "glReadPixels(invalid format %s and/or type %s)",
Kenneth Graunke2f11e922015-07-18 01:22:00 -07001053 _mesa_enum_to_string(format),
1054 _mesa_enum_to_string(type));
Ian Romanickb7c7e5e2012-07-27 12:24:24 -07001055 return;
1056 }
1057 }
1058
Brian Paulb8f7eef2012-02-07 07:42:33 -07001059 err = _mesa_error_check_format_and_type(ctx, format, type);
1060 if (err != GL_NO_ERROR) {
1061 _mesa_error(ctx, err, "glReadPixels(invalid format %s and/or type %s)",
Kenneth Graunke2f11e922015-07-18 01:22:00 -07001062 _mesa_enum_to_string(format),
1063 _mesa_enum_to_string(type));
Brian Paul28876dd2008-06-09 14:22:15 -06001064 return;
1065 }
1066
Eric Anholt5c996972012-11-13 13:39:37 -08001067 if (_mesa_is_user_fbo(ctx->ReadBuffer) &&
1068 ctx->ReadBuffer->Visual.samples > 0) {
1069 _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(multisample FBO)");
1070 return;
1071 }
1072
1073 if (!_mesa_source_buffer_exists(ctx, format)) {
1074 _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(no readbuffer)");
1075 return;
1076 }
1077
Brian Paul751e10f2010-10-25 19:07:33 -06001078 /* Check that the destination format and source buffer are both
1079 * integer-valued or both non-integer-valued.
1080 */
1081 if (ctx->Extensions.EXT_texture_integer && _mesa_is_color_format(format)) {
1082 const struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorReadBuffer;
Brian Paul412b9602010-10-26 20:30:40 -06001083 const GLboolean srcInteger = _mesa_is_format_integer_color(rb->Format);
Jordan Justen9ad8f432012-06-25 10:52:39 -07001084 const GLboolean dstInteger = _mesa_is_enum_format_integer(format);
Brian Paul751e10f2010-10-25 19:07:33 -06001085 if (dstInteger != srcInteger) {
1086 _mesa_error(ctx, GL_INVALID_OPERATION,
1087 "glReadPixels(integer / non-integer format mismatch");
1088 return;
1089 }
1090 }
1091
Nanley Chery60583272016-02-05 16:21:33 -08001092 /* Do all needed clipping here, so that we can forget about it later */
1093 clippedPacking = ctx->Pack;
1094 if (!_mesa_clip_readpixels(ctx, &x, &y, &width, &height, &clippedPacking))
Brian Paul7b9bf392009-04-02 13:05:55 -06001095 return; /* nothing to do */
1096
Brian Paul6b329b92011-04-26 14:54:41 -06001097 if (!_mesa_validate_pbo_access(2, &ctx->Pack, width, height, 1,
1098 format, type, bufSize, pixels)) {
1099 if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
Brian Paul28876dd2008-06-09 14:22:15 -06001100 _mesa_error(ctx, GL_INVALID_OPERATION,
Brian Paul6b329b92011-04-26 14:54:41 -06001101 "glReadPixels(out of bounds PBO access)");
1102 } else {
1103 _mesa_error(ctx, GL_INVALID_OPERATION,
1104 "glReadnPixelsARB(out of bounds access:"
1105 " bufSize (%d) is too small)", bufSize);
Brian Paul28876dd2008-06-09 14:22:15 -06001106 }
Brian Paul6b329b92011-04-26 14:54:41 -06001107 return;
1108 }
Brian Paul28876dd2008-06-09 14:22:15 -06001109
Brian Paul6b329b92011-04-26 14:54:41 -06001110 if (_mesa_is_bufferobj(ctx->Pack.BufferObj) &&
Marek Olšákd26a0652014-01-27 21:36:53 +01001111 _mesa_check_disallowed_mapping(ctx->Pack.BufferObj)) {
Brian Paul6b329b92011-04-26 14:54:41 -06001112 /* buffer is mapped - that's an error */
1113 _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(PBO is mapped)");
1114 return;
Brian Paul28876dd2008-06-09 14:22:15 -06001115 }
1116
1117 ctx->Driver.ReadPixels(ctx, x, y, width, height,
Nanley Chery60583272016-02-05 16:21:33 -08001118 format, type, &clippedPacking, pixels);
Brian Paul28876dd2008-06-09 14:22:15 -06001119}
Brian Paul6b329b92011-04-26 14:54:41 -06001120
1121void GLAPIENTRY
1122_mesa_ReadPixels( GLint x, GLint y, GLsizei width, GLsizei height,
1123 GLenum format, GLenum type, GLvoid *pixels )
1124{
1125 _mesa_ReadnPixelsARB(x, y, width, height, format, type, INT_MAX, pixels);
1126}