blob: 5f9b4b9d159a57e14dc957bef2d569094d4fa795 [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"
Dylan Baker8e369612018-09-14 12:57:32 -070026
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) &&
Gert Wollnye695a352018-04-27 18:04:01 +0200109 (type == GL_FLOAT || type == GL_HALF_FLOAT ||
110 type == GL_UNSIGNED_INT_10F_11F_11F_REV)) {
Marek Olšák2dc20662013-03-14 13:15:54 +0100111 transferOps |= IMAGE_CLAMP_BIT;
112 }
113 }
114 else {
115 /* For CPU-based ReadPixels packing, the clamping must always be done
116 * for non-float types, */
Laura Ekstrand39be0c52015-03-03 15:05:16 -0800117 if (_mesa_get_clamp_read_color(ctx, ctx->ReadBuffer) ||
Gert Wollnye695a352018-04-27 18:04:01 +0200118 (type != GL_FLOAT && type != GL_HALF_FLOAT &&
119 type != GL_UNSIGNED_INT_10F_11F_11F_REV)) {
Marek Olšák2dc20662013-03-14 13:15:54 +0100120 transferOps |= IMAGE_CLAMP_BIT;
121 }
122 }
123
124 /* If the format is unsigned normalized, we can ignore clamping
125 * because the values are already in the range [0,1] so it won't
126 * have any effect anyway.
127 */
128 if (_mesa_get_format_datatype(texFormat) == GL_UNSIGNED_NORMALIZED &&
Anuj Phogat4b874562015-06-12 14:42:57 -0700129 !_mesa_need_rgb_to_luminance_conversion(srcBaseFormat, dstBaseFormat)) {
Marek Olšák2dc20662013-03-14 13:15:54 +0100130 transferOps &= ~IMAGE_CLAMP_BIT;
131 }
132
133 return transferOps;
134}
135
136
137/**
Marek Olšákd702c672013-03-14 15:20:27 +0100138 * Return true if memcpy cannot be used for ReadPixels.
139 *
140 * If uses_blit is true, the function returns true if a simple 3D engine blit
141 * cannot be used for ReadPixels packing.
142 *
143 * NOTE: This doesn't take swizzling and format conversions between
144 * the readbuffer and the pixel pack buffer into account.
145 */
146GLboolean
147_mesa_readpixels_needs_slow_path(const struct gl_context *ctx, GLenum format,
148 GLenum type, GLboolean uses_blit)
149{
150 struct gl_renderbuffer *rb =
151 _mesa_get_read_renderbuffer_for_format(ctx, format);
Anuj Phogat4b874562015-06-12 14:42:57 -0700152 GLenum dstBaseFormat = _mesa_unpack_format_to_base_format(format);
Marek Olšákd702c672013-03-14 15:20:27 +0100153
Matt Turnerbfcdb842015-02-20 20:18:47 -0800154 assert(rb);
Marek Olšákd702c672013-03-14 15:20:27 +0100155
156 /* There are different rules depending on the base format. */
157 switch (format) {
158 case GL_DEPTH_STENCIL:
159 return !_mesa_has_depthstencil_combined(ctx->ReadBuffer) ||
160 ctx->Pixel.DepthScale != 1.0f || ctx->Pixel.DepthBias != 0.0f ||
161 ctx->Pixel.IndexShift || ctx->Pixel.IndexOffset ||
162 ctx->Pixel.MapStencilFlag;
163
164 case GL_DEPTH_COMPONENT:
165 return ctx->Pixel.DepthScale != 1.0f || ctx->Pixel.DepthBias != 0.0f;
166
167 case GL_STENCIL_INDEX:
168 return ctx->Pixel.IndexShift || ctx->Pixel.IndexOffset ||
169 ctx->Pixel.MapStencilFlag;
170
171 default:
172 /* Color formats. */
Anuj Phogat4b874562015-06-12 14:42:57 -0700173 if (_mesa_need_rgb_to_luminance_conversion(rb->_BaseFormat,
174 dstBaseFormat)) {
Marek Olšákd702c672013-03-14 15:20:27 +0100175 return GL_TRUE;
176 }
177
Marek Olšákd702c672013-03-14 15:20:27 +0100178 /* And finally, see if there are any transfer ops. */
Anuj Phogat7974e232015-05-19 17:44:52 -0700179 return _mesa_get_readpixels_transfer_ops(ctx, rb->Format, format, type,
180 uses_blit) != 0;
Marek Olšákd702c672013-03-14 15:20:27 +0100181 }
182 return GL_FALSE;
183}
184
185
186static GLboolean
187readpixels_can_use_memcpy(const struct gl_context *ctx, GLenum format, GLenum type,
188 const struct gl_pixelstore_attrib *packing)
189{
190 struct gl_renderbuffer *rb =
191 _mesa_get_read_renderbuffer_for_format(ctx, format);
192
Matt Turnerbfcdb842015-02-20 20:18:47 -0800193 assert(rb);
Marek Olšákd702c672013-03-14 15:20:27 +0100194
195 if (_mesa_readpixels_needs_slow_path(ctx, format, type, GL_FALSE)) {
196 return GL_FALSE;
197 }
198
199 /* The base internal format and the base Mesa format must match. */
200 if (rb->_BaseFormat != _mesa_get_format_base_format(rb->Format)) {
201 return GL_FALSE;
202 }
203
204 /* The Mesa format must match the input format and type. */
205 if (!_mesa_format_matches_format_and_type(rb->Format, format, type,
Nanley Chery26c549e2015-07-31 10:26:36 -0700206 packing->SwapBytes, NULL)) {
Marek Olšákd702c672013-03-14 15:20:27 +0100207 return GL_FALSE;
208 }
209
210 return GL_TRUE;
211}
212
213
214static GLboolean
215readpixels_memcpy(struct gl_context *ctx,
216 GLint x, GLint y,
217 GLsizei width, GLsizei height,
218 GLenum format, GLenum type,
219 GLvoid *pixels,
220 const struct gl_pixelstore_attrib *packing)
221{
222 struct gl_renderbuffer *rb =
223 _mesa_get_read_renderbuffer_for_format(ctx, format);
224 GLubyte *dst, *map;
Bartosz Tomczyka4019a82017-04-10 12:31:00 -0600225 int dstStride, stride, j, texelBytes, bytesPerRow;
Marek Olšákd702c672013-03-14 15:20:27 +0100226
227 /* Fail if memcpy cannot be used. */
228 if (!readpixels_can_use_memcpy(ctx, format, type, packing)) {
229 return GL_FALSE;
230 }
231
232 dstStride = _mesa_image_row_stride(packing, width, format, type);
233 dst = (GLubyte *) _mesa_image_address2d(packing, pixels, width, height,
234 format, type, 0, 0);
235
236 ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT,
Fritz Koenig318c2652018-07-23 10:10:54 -0700237 &map, &stride, ctx->ReadBuffer->FlipY);
Marek Olšákd702c672013-03-14 15:20:27 +0100238 if (!map) {
239 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
240 return GL_TRUE; /* don't bother trying the slow path */
241 }
242
243 texelBytes = _mesa_get_format_bytes(rb->Format);
Bartosz Tomczyka4019a82017-04-10 12:31:00 -0600244 bytesPerRow = texelBytes * width;
Marek Olšákd702c672013-03-14 15:20:27 +0100245
246 /* memcpy*/
Bartosz Tomczyka4019a82017-04-10 12:31:00 -0600247 if (dstStride == stride && dstStride == bytesPerRow) {
248 memcpy(dst, map, bytesPerRow * height);
249 } else {
250 for (j = 0; j < height; j++) {
251 memcpy(dst, map, bytesPerRow);
252 dst += dstStride;
253 map += stride;
254 }
Marek Olšákd702c672013-03-14 15:20:27 +0100255 }
256
257 ctx->Driver.UnmapRenderbuffer(ctx, rb);
258 return GL_TRUE;
259}
260
261
262/**
263 * Optimized path for conversion of depth values to GL_DEPTH_COMPONENT,
264 * GL_UNSIGNED_INT.
Brian Pauld2a23d42011-11-12 11:50:31 -0700265 */
266static GLboolean
Marek Olšákd702c672013-03-14 15:20:27 +0100267read_uint_depth_pixels( struct gl_context *ctx,
Brian Pauld2a23d42011-11-12 11:50:31 -0700268 GLint x, GLint y,
269 GLsizei width, GLsizei height,
270 GLenum type, GLvoid *pixels,
271 const struct gl_pixelstore_attrib *packing )
272{
273 struct gl_framebuffer *fb = ctx->ReadBuffer;
274 struct gl_renderbuffer *rb = fb->Attachment[BUFFER_DEPTH].Renderbuffer;
275 GLubyte *map, *dst;
276 int stride, dstStride, j;
277
Matt Turnera5623132015-07-12 23:15:42 -0700278 if (ctx->Pixel.DepthScale != 1.0F || ctx->Pixel.DepthBias != 0.0F)
Brian Pauld2a23d42011-11-12 11:50:31 -0700279 return GL_FALSE;
280
281 if (packing->SwapBytes)
282 return GL_FALSE;
283
Eric Anholt755f0a02011-11-17 13:56:30 -0800284 if (_mesa_get_format_datatype(rb->Format) != GL_UNSIGNED_NORMALIZED)
Brian Pauld2a23d42011-11-12 11:50:31 -0700285 return GL_FALSE;
286
Brian Pauld2a23d42011-11-12 11:50:31 -0700287 ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT,
Fritz Koenig318c2652018-07-23 10:10:54 -0700288 &map, &stride, fb->FlipY);
Brian Pauld2a23d42011-11-12 11:50:31 -0700289
Brian Paul038a7df2011-11-17 17:20:05 -0700290 if (!map) {
291 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
292 return GL_TRUE; /* don't bother trying the slow path */
293 }
294
Brian Pauld2a23d42011-11-12 11:50:31 -0700295 dstStride = _mesa_image_row_stride(packing, width, GL_DEPTH_COMPONENT, type);
296 dst = (GLubyte *) _mesa_image_address2d(packing, pixels, width, height,
297 GL_DEPTH_COMPONENT, type, 0, 0);
298
299 for (j = 0; j < height; j++) {
Marek Olšákd702c672013-03-14 15:20:27 +0100300 _mesa_unpack_uint_z_row(rb->Format, width, map, (GLuint *)dst);
Brian Pauld2a23d42011-11-12 11:50:31 -0700301
302 map += stride;
303 dst += dstStride;
304 }
305 ctx->Driver.UnmapRenderbuffer(ctx, rb);
306
307 return GL_TRUE;
308}
309
310/**
311 * Read pixels for format=GL_DEPTH_COMPONENT.
312 */
313static void
314read_depth_pixels( struct gl_context *ctx,
315 GLint x, GLint y,
316 GLsizei width, GLsizei height,
317 GLenum type, GLvoid *pixels,
318 const struct gl_pixelstore_attrib *packing )
319{
320 struct gl_framebuffer *fb = ctx->ReadBuffer;
321 struct gl_renderbuffer *rb = fb->Attachment[BUFFER_DEPTH].Renderbuffer;
322 GLint j;
323 GLubyte *dst, *map;
324 int dstStride, stride;
Brian Paul531eaca2012-02-19 20:08:51 -0700325 GLfloat *depthValues;
Brian Pauld2a23d42011-11-12 11:50:31 -0700326
327 if (!rb)
328 return;
329
330 /* clipping should have been done already */
Matt Turnerbfcdb842015-02-20 20:18:47 -0800331 assert(x >= 0);
332 assert(y >= 0);
333 assert(x + width <= (GLint) rb->Width);
334 assert(y + height <= (GLint) rb->Height);
Brian Pauld2a23d42011-11-12 11:50:31 -0700335
Marek Olšákd702c672013-03-14 15:20:27 +0100336 if (type == GL_UNSIGNED_INT &&
337 read_uint_depth_pixels(ctx, x, y, width, height, type, pixels, packing)) {
Brian Pauld2a23d42011-11-12 11:50:31 -0700338 return;
Marek Olšákd702c672013-03-14 15:20:27 +0100339 }
Brian Pauld2a23d42011-11-12 11:50:31 -0700340
341 dstStride = _mesa_image_row_stride(packing, width, GL_DEPTH_COMPONENT, type);
342 dst = (GLubyte *) _mesa_image_address2d(packing, pixels, width, height,
343 GL_DEPTH_COMPONENT, type, 0, 0);
344
345 ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT,
Fritz Koenig318c2652018-07-23 10:10:54 -0700346 &map, &stride, fb->FlipY);
Brian Paul038a7df2011-11-17 17:20:05 -0700347 if (!map) {
348 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
349 return;
350 }
Brian Pauld2a23d42011-11-12 11:50:31 -0700351
Matt Turner2b7a9722012-09-03 19:44:00 -0700352 depthValues = malloc(width * sizeof(GLfloat));
Brian Pauld2a23d42011-11-12 11:50:31 -0700353
Brian Paul531eaca2012-02-19 20:08:51 -0700354 if (depthValues) {
355 /* General case (slower) */
356 for (j = 0; j < height; j++, y++) {
357 _mesa_unpack_float_z_row(rb->Format, width, map, depthValues);
358 _mesa_pack_depth_span(ctx, width, dst, type, depthValues, packing);
359
360 dst += dstStride;
361 map += stride;
362 }
Brian Pauld2a23d42011-11-12 11:50:31 -0700363 }
Brian Paul531eaca2012-02-19 20:08:51 -0700364 else {
365 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
366 }
367
368 free(depthValues);
Brian Pauld2a23d42011-11-12 11:50:31 -0700369
370 ctx->Driver.UnmapRenderbuffer(ctx, rb);
371}
372
373
374/**
375 * Read pixels for format=GL_STENCIL_INDEX.
376 */
377static void
378read_stencil_pixels( struct gl_context *ctx,
379 GLint x, GLint y,
380 GLsizei width, GLsizei height,
381 GLenum type, GLvoid *pixels,
382 const struct gl_pixelstore_attrib *packing )
383{
384 struct gl_framebuffer *fb = ctx->ReadBuffer;
385 struct gl_renderbuffer *rb = fb->Attachment[BUFFER_STENCIL].Renderbuffer;
386 GLint j;
Brian Paul531eaca2012-02-19 20:08:51 -0700387 GLubyte *map, *stencil;
Brian Pauld2a23d42011-11-12 11:50:31 -0700388 GLint stride;
389
390 if (!rb)
391 return;
392
Brian Pauld2a23d42011-11-12 11:50:31 -0700393 ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT,
Fritz Koenig318c2652018-07-23 10:10:54 -0700394 &map, &stride, fb->FlipY);
Brian Paul038a7df2011-11-17 17:20:05 -0700395 if (!map) {
396 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
397 return;
398 }
Brian Pauld2a23d42011-11-12 11:50:31 -0700399
Matt Turner2b7a9722012-09-03 19:44:00 -0700400 stencil = malloc(width * sizeof(GLubyte));
Brian Pauld2a23d42011-11-12 11:50:31 -0700401
Brian Paul531eaca2012-02-19 20:08:51 -0700402 if (stencil) {
403 /* process image row by row */
404 for (j = 0; j < height; j++) {
405 GLvoid *dest;
Brian Pauld2a23d42011-11-12 11:50:31 -0700406
Brian Paul531eaca2012-02-19 20:08:51 -0700407 _mesa_unpack_ubyte_stencil_row(rb->Format, width, map, stencil);
408 dest = _mesa_image_address2d(packing, pixels, width, height,
409 GL_STENCIL_INDEX, type, j, 0);
Brian Pauld2a23d42011-11-12 11:50:31 -0700410
Brian Paul531eaca2012-02-19 20:08:51 -0700411 _mesa_pack_stencil_span(ctx, width, type, dest, stencil, packing);
412
413 map += stride;
414 }
Brian Pauld2a23d42011-11-12 11:50:31 -0700415 }
Brian Paul531eaca2012-02-19 20:08:51 -0700416 else {
417 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
418 }
419
420 free(stencil);
Brian Pauld2a23d42011-11-12 11:50:31 -0700421
422 ctx->Driver.UnmapRenderbuffer(ctx, rb);
423}
424
Brian Pauld2a23d42011-11-12 11:50:31 -0700425/*
426 * Read R, G, B, A, RGB, L, or LA pixels.
427 */
428static void
429read_rgba_pixels( struct gl_context *ctx,
430 GLint x, GLint y,
431 GLsizei width, GLsizei height,
432 GLenum format, GLenum type, GLvoid *pixels,
433 const struct gl_pixelstore_attrib *packing )
434{
Marek Olšák2dc20662013-03-14 13:15:54 +0100435 GLbitfield transferOps;
Anuj Phogat0b13adc2015-04-30 23:36:18 -0700436 bool dst_is_integer, convert_rgb_to_lum, needs_rebase;
Iago Toral Quiroga5038d832014-10-23 10:04:56 +0200437 int dst_stride, src_stride, rb_stride;
438 uint32_t dst_format, src_format;
439 GLubyte *dst, *map;
440 mesa_format rb_format;
441 bool needs_rgba;
442 void *rgba, *src;
443 bool src_is_uint = false;
444 uint8_t rebase_swizzle[4];
Brian Pauld2a23d42011-11-12 11:50:31 -0700445 struct gl_framebuffer *fb = ctx->ReadBuffer;
446 struct gl_renderbuffer *rb = fb->_ColorReadBuffer;
Anuj Phogat4b874562015-06-12 14:42:57 -0700447 GLenum dstBaseFormat = _mesa_unpack_format_to_base_format(format);
Brian Pauld2a23d42011-11-12 11:50:31 -0700448
449 if (!rb)
450 return;
451
Anuj Phogat7974e232015-05-19 17:44:52 -0700452 transferOps = _mesa_get_readpixels_transfer_ops(ctx, rb->Format, format,
453 type, GL_FALSE);
Iago Toral Quiroga5038d832014-10-23 10:04:56 +0200454 /* Describe the dst format */
455 dst_is_integer = _mesa_is_enum_format_integer(format);
456 dst_stride = _mesa_image_row_stride(packing, width, format, type);
457 dst_format = _mesa_format_from_format_and_type(format, type);
Anuj Phogatba2b1f82015-05-01 00:05:18 -0700458 convert_rgb_to_lum =
Anuj Phogat4b874562015-06-12 14:42:57 -0700459 _mesa_need_rgb_to_luminance_conversion(rb->_BaseFormat, dstBaseFormat);
Iago Toral Quiroga5038d832014-10-23 10:04:56 +0200460 dst = (GLubyte *) _mesa_image_address2d(packing, pixels, width, height,
461 format, type, 0, 0);
Brian Pauld2a23d42011-11-12 11:50:31 -0700462
Iago Toral Quiroga5038d832014-10-23 10:04:56 +0200463 /* Map the source render buffer */
464 ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT,
Fritz Koenig318c2652018-07-23 10:10:54 -0700465 &map, &rb_stride, fb->FlipY);
Iago Toral Quiroga5038d832014-10-23 10:04:56 +0200466 if (!map) {
467 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
Neil Robertsd9c420972012-02-26 01:33:40 +0000468 return;
Brian Pauld2a23d42011-11-12 11:50:31 -0700469 }
Iago Toral Quiroga5038d832014-10-23 10:04:56 +0200470 rb_format = _mesa_get_srgb_format_linear(rb->Format);
Brian Pauld2a23d42011-11-12 11:50:31 -0700471
Iago Toral Quiroga5038d832014-10-23 10:04:56 +0200472 /*
473 * Depending on the base formats involved in the conversion we might need to
474 * rebase some values, so for these formats we compute a rebase swizzle.
475 */
476 if (rb->_BaseFormat == GL_LUMINANCE || rb->_BaseFormat == GL_INTENSITY) {
477 needs_rebase = true;
478 rebase_swizzle[0] = MESA_FORMAT_SWIZZLE_X;
479 rebase_swizzle[1] = MESA_FORMAT_SWIZZLE_ZERO;
480 rebase_swizzle[2] = MESA_FORMAT_SWIZZLE_ZERO;
481 rebase_swizzle[3] = MESA_FORMAT_SWIZZLE_ONE;
482 } else if (rb->_BaseFormat == GL_LUMINANCE_ALPHA) {
483 needs_rebase = true;
484 rebase_swizzle[0] = MESA_FORMAT_SWIZZLE_X;
485 rebase_swizzle[1] = MESA_FORMAT_SWIZZLE_ZERO;
486 rebase_swizzle[2] = MESA_FORMAT_SWIZZLE_ZERO;
487 rebase_swizzle[3] = MESA_FORMAT_SWIZZLE_W;
488 } else if (_mesa_get_format_base_format(rb_format) != rb->_BaseFormat) {
489 needs_rebase =
490 _mesa_compute_rgba2base2rgba_component_mapping(rb->_BaseFormat,
491 rebase_swizzle);
492 } else {
493 needs_rebase = false;
494 }
495
496 /* Since _mesa_format_convert does not handle transferOps we need to handle
497 * them before we call the function. This requires to convert to RGBA float
498 * first so we can call _mesa_apply_rgba_transfer_ops. If the dst format is
499 * integer transferOps do not apply.
500 *
501 * Converting to luminance also requires converting to RGBA first, so we can
502 * then compute luminance values as L=R+G+B. Notice that this is different
503 * from GetTexImage, where we compute L=R.
504 */
505 assert(!transferOps || (transferOps && !dst_is_integer));
506
Anuj Phogat0b13adc2015-04-30 23:36:18 -0700507 needs_rgba = transferOps || convert_rgb_to_lum;
Iago Toral Quiroga5038d832014-10-23 10:04:56 +0200508 rgba = NULL;
509 if (needs_rgba) {
510 uint32_t rgba_format;
511 int rgba_stride;
512 bool need_convert;
513
514 /* Convert to RGBA float or int/uint depending on the type of the src */
515 if (dst_is_integer) {
516 src_is_uint = _mesa_is_format_unsigned(rb_format);
517 if (src_is_uint) {
Iago Toral Quirogac6a26282015-01-13 08:33:19 +0100518 rgba_format = RGBA32_UINT;
Iago Toral Quiroga5038d832014-10-23 10:04:56 +0200519 rgba_stride = width * 4 * sizeof(GLuint);
520 } else {
Iago Toral Quirogac6a26282015-01-13 08:33:19 +0100521 rgba_format = RGBA32_INT;
Iago Toral Quiroga5038d832014-10-23 10:04:56 +0200522 rgba_stride = width * 4 * sizeof(GLint);
523 }
524 } else {
Iago Toral Quirogac6a26282015-01-13 08:33:19 +0100525 rgba_format = RGBA32_FLOAT;
Iago Toral Quiroga5038d832014-10-23 10:04:56 +0200526 rgba_stride = width * 4 * sizeof(GLfloat);
527 }
528
529 /* If we are lucky and the dst format matches the RGBA format we need to
530 * convert to, then we can convert directly into the dst buffer and avoid
531 * the final conversion/copy from the rgba buffer to the dst buffer.
532 */
Dave Airlie32769ac2015-09-01 15:57:02 +1000533 if (dst_format == rgba_format &&
534 dst_stride == rgba_stride) {
Iago Toral Quiroga5038d832014-10-23 10:04:56 +0200535 need_convert = false;
536 rgba = dst;
537 } else {
538 need_convert = true;
539 rgba = malloc(height * rgba_stride);
540 if (!rgba) {
541 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
542 goto done_unmap;
543 }
544 }
545
546 /* Convert to RGBA now */
547 _mesa_format_convert(rgba, rgba_format, rgba_stride,
548 map, rb_format, rb_stride,
549 width, height,
550 needs_rebase ? rebase_swizzle : NULL);
551
552 /* Handle transfer ops if necessary */
553 if (transferOps)
554 _mesa_apply_rgba_transfer_ops(ctx, transferOps, width * height, rgba);
555
556 /* If we had to rebase, we have already taken care of that */
557 needs_rebase = false;
558
559 /* If we were lucky and our RGBA conversion matches the dst format, then
560 * we are done.
561 */
562 if (!need_convert)
563 goto done_swap;
564
565 /* Otherwise, we need to convert from RGBA to dst next */
566 src = rgba;
567 src_format = rgba_format;
568 src_stride = rgba_stride;
569 } else {
570 /* No RGBA conversion needed, convert directly to dst */
571 src = map;
572 src_format = rb_format;
573 src_stride = rb_stride;
574 }
575
576 /* Do the conversion.
577 *
578 * If the dst format is Luminance, we need to do the conversion by computing
579 * L=R+G+B values.
580 */
Anuj Phogat0b13adc2015-04-30 23:36:18 -0700581 if (!convert_rgb_to_lum) {
Iago Toral Quiroga5038d832014-10-23 10:04:56 +0200582 _mesa_format_convert(dst, dst_format, dst_stride,
583 src, src_format, src_stride,
584 width, height,
585 needs_rebase ? rebase_swizzle : NULL);
586 } else if (!dst_is_integer) {
587 /* Compute float Luminance values from RGBA float */
588 int luminance_stride, luminance_bytes;
589 void *luminance;
590 uint32_t luminance_format;
591
Thomas Hindoe Paaboel Andersen18078062016-02-22 15:58:00 -0700592 luminance_stride = width * sizeof(GLfloat);
Iago Toral Quiroga5038d832014-10-23 10:04:56 +0200593 if (format == GL_LUMINANCE_ALPHA)
594 luminance_stride *= 2;
595 luminance_bytes = height * luminance_stride;
596 luminance = malloc(luminance_bytes);
597 if (!luminance) {
598 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
599 free(rgba);
600 goto done_unmap;
601 }
602 _mesa_pack_luminance_from_rgba_float(width * height, src,
603 luminance, format, transferOps);
604
605 /* Convert from Luminance float to dst (this will hadle type conversion
606 * from float to the type of dst if necessary)
607 */
608 luminance_format = _mesa_format_from_format_and_type(format, GL_FLOAT);
609 _mesa_format_convert(dst, dst_format, dst_stride,
610 luminance, luminance_format, luminance_stride,
611 width, height, NULL);
Matt Turner87109ac2015-02-28 11:08:17 -0800612 free(luminance);
Iago Toral Quiroga5038d832014-10-23 10:04:56 +0200613 } else {
614 _mesa_pack_luminance_from_rgba_integer(width * height, src, !src_is_uint,
615 dst, format, type);
616 }
617
Thomas Hindoe Paaboel Andersen76a423e2016-05-04 06:15:37 +0200618 free(rgba);
Iago Toral Quiroga5038d832014-10-23 10:04:56 +0200619
620done_swap:
621 /* Handle byte swapping if required */
622 if (packing->SwapBytes) {
Dave Airlie0ad3a472015-08-25 14:36:01 +1000623 _mesa_swap_bytes_2d_image(format, type, packing,
624 width, height, dst, dst);
Iago Toral Quiroga5038d832014-10-23 10:04:56 +0200625 }
626
627done_unmap:
628 ctx->Driver.UnmapRenderbuffer(ctx, rb);
Brian Pauld2a23d42011-11-12 11:50:31 -0700629}
630
631/**
632 * For a packed depth/stencil buffer being read as depth/stencil, just memcpy the
633 * data (possibly swapping 8/24 vs 24/8 as we go).
634 */
635static GLboolean
636fast_read_depth_stencil_pixels(struct gl_context *ctx,
637 GLint x, GLint y,
638 GLsizei width, GLsizei height,
639 GLubyte *dst, int dstStride)
640{
641 struct gl_framebuffer *fb = ctx->ReadBuffer;
642 struct gl_renderbuffer *rb = fb->Attachment[BUFFER_DEPTH].Renderbuffer;
643 struct gl_renderbuffer *stencilRb = fb->Attachment[BUFFER_STENCIL].Renderbuffer;
644 GLubyte *map;
645 int stride, i;
646
647 if (rb != stencilRb)
648 return GL_FALSE;
649
Mark Muellereeed49f2014-01-26 15:12:56 -0800650 if (rb->Format != MESA_FORMAT_S8_UINT_Z24_UNORM &&
Kenneth Graunkea487ef82014-02-07 21:53:18 -0800651 rb->Format != MESA_FORMAT_Z24_UNORM_S8_UINT)
Brian Pauld2a23d42011-11-12 11:50:31 -0700652 return GL_FALSE;
653
654 ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT,
Fritz Koenig318c2652018-07-23 10:10:54 -0700655 &map, &stride, fb->FlipY);
Brian Paul038a7df2011-11-17 17:20:05 -0700656 if (!map) {
657 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
658 return GL_TRUE; /* don't bother trying the slow path */
659 }
Brian Pauld2a23d42011-11-12 11:50:31 -0700660
661 for (i = 0; i < height; i++) {
662 _mesa_unpack_uint_24_8_depth_stencil_row(rb->Format, width,
663 map, (GLuint *)dst);
664 map += stride;
665 dst += dstStride;
666 }
667
668 ctx->Driver.UnmapRenderbuffer(ctx, rb);
669
670 return GL_TRUE;
671}
672
673
674/**
675 * For non-float-depth and stencil buffers being read as 24/8 depth/stencil,
676 * copy the integer data directly instead of converting depth to float and
677 * re-packing.
678 */
679static GLboolean
680fast_read_depth_stencil_pixels_separate(struct gl_context *ctx,
681 GLint x, GLint y,
682 GLsizei width, GLsizei height,
683 uint32_t *dst, int dstStride)
684{
685 struct gl_framebuffer *fb = ctx->ReadBuffer;
686 struct gl_renderbuffer *depthRb = fb->Attachment[BUFFER_DEPTH].Renderbuffer;
687 struct gl_renderbuffer *stencilRb = fb->Attachment[BUFFER_STENCIL].Renderbuffer;
Brian Paul531eaca2012-02-19 20:08:51 -0700688 GLubyte *depthMap, *stencilMap, *stencilVals;
Brian Pauld2a23d42011-11-12 11:50:31 -0700689 int depthStride, stencilStride, i, j;
690
Eric Anholt755f0a02011-11-17 13:56:30 -0800691 if (_mesa_get_format_datatype(depthRb->Format) != GL_UNSIGNED_NORMALIZED)
Brian Pauld2a23d42011-11-12 11:50:31 -0700692 return GL_FALSE;
693
694 ctx->Driver.MapRenderbuffer(ctx, depthRb, x, y, width, height,
Fritz Koenig318c2652018-07-23 10:10:54 -0700695 GL_MAP_READ_BIT, &depthMap, &depthStride, fb->FlipY);
Brian Paul038a7df2011-11-17 17:20:05 -0700696 if (!depthMap) {
697 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
698 return GL_TRUE; /* don't bother trying the slow path */
699 }
700
Brian Pauld2a23d42011-11-12 11:50:31 -0700701 ctx->Driver.MapRenderbuffer(ctx, stencilRb, x, y, width, height,
Fritz Koenig318c2652018-07-23 10:10:54 -0700702 GL_MAP_READ_BIT, &stencilMap, &stencilStride, fb->FlipY);
Brian Paul038a7df2011-11-17 17:20:05 -0700703 if (!stencilMap) {
704 ctx->Driver.UnmapRenderbuffer(ctx, depthRb);
705 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
706 return GL_TRUE; /* don't bother trying the slow path */
707 }
Brian Pauld2a23d42011-11-12 11:50:31 -0700708
Matt Turner2b7a9722012-09-03 19:44:00 -0700709 stencilVals = malloc(width * sizeof(GLubyte));
Brian Pauld2a23d42011-11-12 11:50:31 -0700710
Brian Paul531eaca2012-02-19 20:08:51 -0700711 if (stencilVals) {
712 for (j = 0; j < height; j++) {
713 _mesa_unpack_uint_z_row(depthRb->Format, width, depthMap, dst);
714 _mesa_unpack_ubyte_stencil_row(stencilRb->Format, width,
715 stencilMap, stencilVals);
Brian Pauld2a23d42011-11-12 11:50:31 -0700716
Brian Paul531eaca2012-02-19 20:08:51 -0700717 for (i = 0; i < width; i++) {
718 dst[i] = (dst[i] & 0xffffff00) | stencilVals[i];
719 }
720
721 depthMap += depthStride;
722 stencilMap += stencilStride;
723 dst += dstStride / 4;
Brian Pauld2a23d42011-11-12 11:50:31 -0700724 }
Brian Pauld2a23d42011-11-12 11:50:31 -0700725 }
Brian Paul531eaca2012-02-19 20:08:51 -0700726 else {
727 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
728 }
729
730 free(stencilVals);
Brian Pauld2a23d42011-11-12 11:50:31 -0700731
732 ctx->Driver.UnmapRenderbuffer(ctx, depthRb);
733 ctx->Driver.UnmapRenderbuffer(ctx, stencilRb);
734
735 return GL_TRUE;
736}
737
738static void
739slow_read_depth_stencil_pixels_separate(struct gl_context *ctx,
740 GLint x, GLint y,
741 GLsizei width, GLsizei height,
742 GLenum type,
743 const struct gl_pixelstore_attrib *packing,
744 GLubyte *dst, int dstStride)
745{
746 struct gl_framebuffer *fb = ctx->ReadBuffer;
747 struct gl_renderbuffer *depthRb = fb->Attachment[BUFFER_DEPTH].Renderbuffer;
748 struct gl_renderbuffer *stencilRb = fb->Attachment[BUFFER_STENCIL].Renderbuffer;
749 GLubyte *depthMap, *stencilMap;
750 int depthStride, stencilStride, j;
Brian Paul531eaca2012-02-19 20:08:51 -0700751 GLubyte *stencilVals;
752 GLfloat *depthVals;
753
Brian Pauld2a23d42011-11-12 11:50:31 -0700754
Brian Paulf6a50c02011-11-16 07:47:51 -0700755 /* The depth and stencil buffers might be separate, or a single buffer.
756 * If one buffer, only map it once.
757 */
Brian Pauld2a23d42011-11-12 11:50:31 -0700758 ctx->Driver.MapRenderbuffer(ctx, depthRb, x, y, width, height,
Fritz Koenig318c2652018-07-23 10:10:54 -0700759 GL_MAP_READ_BIT, &depthMap, &depthStride, fb->FlipY);
Brian Paul038a7df2011-11-17 17:20:05 -0700760 if (!depthMap) {
761 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
762 return;
763 }
764
Brian Paulf6a50c02011-11-16 07:47:51 -0700765 if (stencilRb != depthRb) {
766 ctx->Driver.MapRenderbuffer(ctx, stencilRb, x, y, width, height,
767 GL_MAP_READ_BIT, &stencilMap,
Fritz Koenig318c2652018-07-23 10:10:54 -0700768 &stencilStride, fb->FlipY);
Brian Paul038a7df2011-11-17 17:20:05 -0700769 if (!stencilMap) {
770 ctx->Driver.UnmapRenderbuffer(ctx, depthRb);
771 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
772 return;
773 }
Brian Paulf6a50c02011-11-16 07:47:51 -0700774 }
Brian Paulf4c03da2011-11-16 09:58:45 -0700775 else {
776 stencilMap = depthMap;
777 stencilStride = depthStride;
778 }
Brian Pauld2a23d42011-11-12 11:50:31 -0700779
Matt Turner2b7a9722012-09-03 19:44:00 -0700780 stencilVals = malloc(width * sizeof(GLubyte));
781 depthVals = malloc(width * sizeof(GLfloat));
Brian Pauld2a23d42011-11-12 11:50:31 -0700782
Brian Paul531eaca2012-02-19 20:08:51 -0700783 if (stencilVals && depthVals) {
784 for (j = 0; j < height; j++) {
785 _mesa_unpack_float_z_row(depthRb->Format, width, depthMap, depthVals);
786 _mesa_unpack_ubyte_stencil_row(stencilRb->Format, width,
787 stencilMap, stencilVals);
Brian Pauld2a23d42011-11-12 11:50:31 -0700788
Brian Paul531eaca2012-02-19 20:08:51 -0700789 _mesa_pack_depth_stencil_span(ctx, width, type, (GLuint *)dst,
790 depthVals, stencilVals, packing);
Brian Pauld2a23d42011-11-12 11:50:31 -0700791
Brian Paul531eaca2012-02-19 20:08:51 -0700792 depthMap += depthStride;
793 stencilMap += stencilStride;
794 dst += dstStride;
795 }
Brian Pauld2a23d42011-11-12 11:50:31 -0700796 }
Brian Paul531eaca2012-02-19 20:08:51 -0700797 else {
798 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
799 }
800
801 free(stencilVals);
802 free(depthVals);
Brian Pauld2a23d42011-11-12 11:50:31 -0700803
804 ctx->Driver.UnmapRenderbuffer(ctx, depthRb);
Brian Paulf6a50c02011-11-16 07:47:51 -0700805 if (stencilRb != depthRb) {
806 ctx->Driver.UnmapRenderbuffer(ctx, stencilRb);
807 }
Brian Pauld2a23d42011-11-12 11:50:31 -0700808}
809
810
811/**
812 * Read combined depth/stencil values.
813 * We'll have already done error checking to be sure the expected
814 * depth and stencil buffers really exist.
815 */
816static void
817read_depth_stencil_pixels(struct gl_context *ctx,
818 GLint x, GLint y,
819 GLsizei width, GLsizei height,
820 GLenum type, GLvoid *pixels,
821 const struct gl_pixelstore_attrib *packing )
822{
823 const GLboolean scaleOrBias
Matt Turnera5623132015-07-12 23:15:42 -0700824 = ctx->Pixel.DepthScale != 1.0F || ctx->Pixel.DepthBias != 0.0F;
Brian Pauld2a23d42011-11-12 11:50:31 -0700825 const GLboolean stencilTransfer = ctx->Pixel.IndexShift
826 || ctx->Pixel.IndexOffset || ctx->Pixel.MapStencilFlag;
827 GLubyte *dst;
828 int dstStride;
829
830 dst = (GLubyte *) _mesa_image_address2d(packing, pixels,
831 width, height,
832 GL_DEPTH_STENCIL_EXT,
833 type, 0, 0);
834 dstStride = _mesa_image_row_stride(packing, width,
835 GL_DEPTH_STENCIL_EXT, type);
836
837 /* Fast 24/8 reads. */
838 if (type == GL_UNSIGNED_INT_24_8 &&
839 !scaleOrBias && !stencilTransfer && !packing->SwapBytes) {
840 if (fast_read_depth_stencil_pixels(ctx, x, y, width, height,
841 dst, dstStride))
842 return;
843
844 if (fast_read_depth_stencil_pixels_separate(ctx, x, y, width, height,
845 (uint32_t *)dst, dstStride))
846 return;
847 }
848
849 slow_read_depth_stencil_pixels_separate(ctx, x, y, width, height,
850 type, packing,
851 dst, dstStride);
852}
853
854
855
856/**
857 * Software fallback routine for ctx->Driver.ReadPixels().
858 * By time we get here, all error checking will have been done.
859 */
860void
861_mesa_readpixels(struct gl_context *ctx,
862 GLint x, GLint y, GLsizei width, GLsizei height,
863 GLenum format, GLenum type,
864 const struct gl_pixelstore_attrib *packing,
865 GLvoid *pixels)
866{
Brian Pauld2a23d42011-11-12 11:50:31 -0700867 if (ctx->NewState)
868 _mesa_update_state(ctx);
869
Nanley Cheryc6242412016-02-05 16:25:28 -0800870 pixels = _mesa_map_pbo_dest(ctx, packing, pixels);
Brian Pauld2a23d42011-11-12 11:50:31 -0700871
Nanley Cheryc6242412016-02-05 16:25:28 -0800872 if (pixels) {
873 /* Try memcpy first. */
874 if (readpixels_memcpy(ctx, x, y, width, height, format, type,
875 pixels, packing)) {
Nanley Cheryb89a8a12016-02-05 16:25:01 -0800876 _mesa_unmap_pbo_dest(ctx, packing);
Nanley Cheryc6242412016-02-05 16:25:28 -0800877 return;
Brian Pauld2a23d42011-11-12 11:50:31 -0700878 }
Nanley Cheryc6242412016-02-05 16:25:28 -0800879
880 /* Otherwise take the slow path. */
881 switch (format) {
882 case GL_STENCIL_INDEX:
883 read_stencil_pixels(ctx, x, y, width, height, type, pixels,
884 packing);
885 break;
886 case GL_DEPTH_COMPONENT:
887 read_depth_pixels(ctx, x, y, width, height, type, pixels,
888 packing);
889 break;
890 case GL_DEPTH_STENCIL_EXT:
891 read_depth_stencil_pixels(ctx, x, y, width, height, type, pixels,
892 packing);
893 break;
894 default:
895 /* all other formats should be color formats */
896 read_rgba_pixels(ctx, x, y, width, height, format, type, pixels,
897 packing);
898 }
899
900 _mesa_unmap_pbo_dest(ctx, packing);
901 }
Brian Pauld2a23d42011-11-12 11:50:31 -0700902}
903
904
Jordan Justen8b0bc9d2012-12-28 11:24:37 -0800905static GLenum
Tapani Pälli7f467d42018-04-06 10:57:57 +0300906read_pixels_es3_error_check(struct gl_context *ctx, GLenum format, GLenum type,
Jordan Justen8b0bc9d2012-12-28 11:24:37 -0800907 const struct gl_renderbuffer *rb)
908{
909 const GLenum internalFormat = rb->InternalFormat;
910 const GLenum data_type = _mesa_get_format_datatype(rb->Format);
911 GLboolean is_unsigned_int = GL_FALSE;
912 GLboolean is_signed_int = GL_FALSE;
Nanley Chery5b83eb02020-11-05 15:45:44 -0800913 GLboolean is_float_depth = _mesa_has_depth_float_channel(internalFormat);
Jordan Justen8b0bc9d2012-12-28 11:24:37 -0800914
915 is_unsigned_int = _mesa_is_enum_format_unsigned_int(internalFormat);
916 if (!is_unsigned_int) {
917 is_signed_int = _mesa_is_enum_format_signed_int(internalFormat);
918 }
919
920 switch (format) {
921 case GL_RGBA:
Jordan Justen119002a2013-01-10 17:29:27 -0800922 if (type == GL_FLOAT && data_type == GL_FLOAT)
923 return GL_NO_ERROR; /* EXT_color_buffer_float */
Jordan Justen8b0bc9d2012-12-28 11:24:37 -0800924 if (type == GL_UNSIGNED_BYTE && data_type == GL_UNSIGNED_NORMALIZED)
925 return GL_NO_ERROR;
926 if (internalFormat == GL_RGB10_A2 &&
927 type == GL_UNSIGNED_INT_2_10_10_10_REV)
928 return GL_NO_ERROR;
929 if (internalFormat == GL_RGB10_A2UI && type == GL_UNSIGNED_BYTE)
930 return GL_NO_ERROR;
Tapani Pälli7f467d42018-04-06 10:57:57 +0300931 if (type == GL_UNSIGNED_SHORT) {
932 switch (internalFormat) {
933 case GL_R16:
934 case GL_RG16:
935 case GL_RGB16:
936 case GL_RGBA16:
937 if (_mesa_has_EXT_texture_norm16(ctx))
938 return GL_NO_ERROR;
939 }
940 }
Tapani Pälli0d356cf2018-05-24 14:05:27 +0300941 if (type == GL_SHORT) {
942 switch (internalFormat) {
943 case GL_R16_SNORM:
944 case GL_RG16_SNORM:
945 case GL_RGBA16_SNORM:
946 if (_mesa_has_EXT_texture_norm16(ctx) &&
947 _mesa_has_EXT_render_snorm(ctx))
948 return GL_NO_ERROR;
949 }
950 }
951 if (type == GL_BYTE) {
952 switch (internalFormat) {
953 case GL_R8_SNORM:
954 case GL_RG8_SNORM:
955 case GL_RGBA8_SNORM:
956 if (_mesa_has_EXT_render_snorm(ctx))
957 return GL_NO_ERROR;
958 }
959 }
Tapani Pällia72dbc42018-08-27 14:40:41 +0300960 if (type == GL_UNSIGNED_BYTE) {
961 switch (internalFormat) {
962 case GL_R8_SNORM:
963 case GL_RG8_SNORM:
964 case GL_RGBA8_SNORM:
965 if (_mesa_has_EXT_render_snorm(ctx))
966 return GL_NO_ERROR;
967 }
968 }
Jordan Justen8b0bc9d2012-12-28 11:24:37 -0800969 break;
970 case GL_BGRA:
971 /* GL_EXT_read_format_bgra */
972 if (type == GL_UNSIGNED_BYTE ||
973 type == GL_UNSIGNED_SHORT_4_4_4_4_REV ||
974 type == GL_UNSIGNED_SHORT_1_5_5_5_REV)
975 return GL_NO_ERROR;
976 break;
977 case GL_RGBA_INTEGER:
978 if ((is_signed_int && type == GL_INT) ||
979 (is_unsigned_int && type == GL_UNSIGNED_INT))
980 return GL_NO_ERROR;
981 break;
Rob Clark81d2fd92015-08-10 06:58:37 -0400982 case GL_DEPTH_STENCIL:
983 switch (type) {
984 case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
985 if (is_float_depth)
986 return GL_NO_ERROR;
987 break;
988 case GL_UNSIGNED_INT_24_8:
989 if (!is_float_depth)
990 return GL_NO_ERROR;
991 break;
992 default:
993 return GL_INVALID_ENUM;
994 }
995 break;
996 case GL_DEPTH_COMPONENT:
997 switch (type) {
998 case GL_FLOAT:
999 if (is_float_depth)
1000 return GL_NO_ERROR;
1001 break;
1002 case GL_UNSIGNED_SHORT:
Tapani Pälliafa1efd2015-09-15 09:17:20 +03001003 case GL_UNSIGNED_INT:
Rob Clark81d2fd92015-08-10 06:58:37 -04001004 case GL_UNSIGNED_INT_24_8:
1005 if (!is_float_depth)
1006 return GL_NO_ERROR;
1007 break;
1008 default:
1009 return GL_INVALID_ENUM;
1010 }
1011 break;
1012 case GL_STENCIL_INDEX:
1013 switch (type) {
1014 case GL_UNSIGNED_BYTE:
1015 return GL_NO_ERROR;
1016 default:
1017 return GL_INVALID_ENUM;
1018 }
1019 break;
Jordan Justen8b0bc9d2012-12-28 11:24:37 -08001020 }
1021
1022 return GL_INVALID_OPERATION;
1023}
1024
1025
Samuel Pitoiset333663f2017-07-18 17:26:34 +02001026static ALWAYS_INLINE void
1027read_pixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format,
1028 GLenum type, GLsizei bufSize, GLvoid *pixels, bool no_error)
Brian Paul28876dd2008-06-09 14:22:15 -06001029{
Matt Turner112e3022012-11-30 15:07:54 -08001030 GLenum err = GL_NO_ERROR;
Jordan Justen8b0bc9d2012-12-28 11:24:37 -08001031 struct gl_renderbuffer *rb;
Nanley Chery60583272016-02-05 16:21:33 -08001032 struct gl_pixelstore_attrib clippedPacking;
Brian Paulb8f7eef2012-02-07 07:42:33 -07001033
Brian Paul28876dd2008-06-09 14:22:15 -06001034 GET_CURRENT_CONTEXT(ctx);
Brian Paul28876dd2008-06-09 14:22:15 -06001035
Eric Anholta9754792013-01-16 16:20:38 -08001036 FLUSH_VERTICES(ctx, 0);
Brian Paul28876dd2008-06-09 14:22:15 -06001037
Brian Paul6364d752011-02-18 09:53:29 -07001038 if (MESA_VERBOSE & VERBOSE_API)
1039 _mesa_debug(ctx, "glReadPixels(%d, %d, %s, %s, %p)\n",
1040 width, height,
Kenneth Graunke2f11e922015-07-18 01:22:00 -07001041 _mesa_enum_to_string(format),
1042 _mesa_enum_to_string(type),
Brian Paul6364d752011-02-18 09:53:29 -07001043 pixels);
1044
Samuel Pitoiset333663f2017-07-18 17:26:34 +02001045 if (!no_error && (width < 0 || height < 0)) {
Brian Paul28876dd2008-06-09 14:22:15 -06001046 _mesa_error( ctx, GL_INVALID_VALUE,
1047 "glReadPixels(width=%d height=%d)", width, height );
1048 return;
1049 }
1050
Jordan Justence9118c2012-12-28 11:27:04 -08001051 if (ctx->NewState)
1052 _mesa_update_state(ctx);
1053
Samuel Pitoiset333663f2017-07-18 17:26:34 +02001054 if (!no_error && ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
Jordan Justence9118c2012-12-28 11:27:04 -08001055 _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
1056 "glReadPixels(incomplete framebuffer)" );
1057 return;
1058 }
1059
Jordan Justen8b0bc9d2012-12-28 11:24:37 -08001060 rb = _mesa_get_read_renderbuffer_for_format(ctx, format);
Samuel Pitoiset333663f2017-07-18 17:26:34 +02001061 if (!no_error) {
1062 if (rb == NULL) {
1063 _mesa_error(ctx, GL_INVALID_OPERATION,
1064 "glReadPixels(read buffer)");
1065 return;
Ian Romanickb7c7e5e2012-07-27 12:24:24 -07001066 }
1067
Samuel Pitoiset333663f2017-07-18 17:26:34 +02001068 /* OpenGL ES 1.x and OpenGL ES 2.0 impose additional restrictions on the
1069 * combinations of format and type that can be used.
1070 *
1071 * Technically, only two combinations are actually allowed:
1072 * GL_RGBA/GL_UNSIGNED_BYTE, and some implementation-specific internal
1073 * preferred combination. This code doesn't know what that preferred
1074 * combination is, and Mesa can handle anything valid. Just work instead.
1075 */
1076 if (_mesa_is_gles(ctx)) {
1077 if (ctx->API == API_OPENGLES2 &&
1078 _mesa_is_color_format(format) &&
1079 _mesa_get_color_read_format(ctx, NULL, "glReadPixels") == format &&
1080 _mesa_get_color_read_type(ctx, NULL, "glReadPixels") == type) {
1081 err = GL_NO_ERROR;
1082 } else if (ctx->Version < 30) {
1083 err = _mesa_es_error_check_format_and_type(ctx, format, type, 2);
1084 if (err == GL_NO_ERROR) {
1085 if (type == GL_FLOAT || type == GL_HALF_FLOAT_OES) {
1086 err = GL_INVALID_OPERATION;
1087 }
1088 }
1089 } else {
Tapani Pälli7f467d42018-04-06 10:57:57 +03001090 err = read_pixels_es3_error_check(ctx, format, type, rb);
Samuel Pitoiset333663f2017-07-18 17:26:34 +02001091 }
1092
1093 if (err != GL_NO_ERROR) {
1094 _mesa_error(ctx, err, "glReadPixels(invalid format %s and/or type %s)",
1095 _mesa_enum_to_string(format),
1096 _mesa_enum_to_string(type));
1097 return;
1098 }
1099 }
1100
1101 err = _mesa_error_check_format_and_type(ctx, format, type);
Ian Romanickb7c7e5e2012-07-27 12:24:24 -07001102 if (err != GL_NO_ERROR) {
1103 _mesa_error(ctx, err, "glReadPixels(invalid format %s and/or type %s)",
Kenneth Graunke2f11e922015-07-18 01:22:00 -07001104 _mesa_enum_to_string(format),
1105 _mesa_enum_to_string(type));
Ian Romanickb7c7e5e2012-07-27 12:24:24 -07001106 return;
1107 }
Ian Romanickb7c7e5e2012-07-27 12:24:24 -07001108
Samuel Pitoiset333663f2017-07-18 17:26:34 +02001109 if (_mesa_is_user_fbo(ctx->ReadBuffer) &&
1110 ctx->ReadBuffer->Visual.samples > 0) {
1111 _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(multisample FBO)");
Brian Paul751e10f2010-10-25 19:07:33 -06001112 return;
1113 }
Samuel Pitoiset333663f2017-07-18 17:26:34 +02001114
1115 if (!_mesa_source_buffer_exists(ctx, format)) {
1116 _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(no readbuffer)");
1117 return;
1118 }
1119
1120 /* Check that the destination format and source buffer are both
1121 * integer-valued or both non-integer-valued.
1122 */
1123 if (ctx->Extensions.EXT_texture_integer && _mesa_is_color_format(format)) {
1124 const struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorReadBuffer;
1125 const GLboolean srcInteger = _mesa_is_format_integer_color(rb->Format);
1126 const GLboolean dstInteger = _mesa_is_enum_format_integer(format);
1127 if (dstInteger != srcInteger) {
1128 _mesa_error(ctx, GL_INVALID_OPERATION,
1129 "glReadPixels(integer / non-integer format mismatch");
1130 return;
1131 }
1132 }
Brian Paul751e10f2010-10-25 19:07:33 -06001133 }
1134
Nanley Chery60583272016-02-05 16:21:33 -08001135 /* Do all needed clipping here, so that we can forget about it later */
1136 clippedPacking = ctx->Pack;
1137 if (!_mesa_clip_readpixels(ctx, &x, &y, &width, &height, &clippedPacking))
Brian Paul7b9bf392009-04-02 13:05:55 -06001138 return; /* nothing to do */
1139
Samuel Pitoiset333663f2017-07-18 17:26:34 +02001140 if (!no_error) {
1141 if (!_mesa_validate_pbo_access(2, &ctx->Pack, width, height, 1,
1142 format, type, bufSize, pixels)) {
Marek Olšák10beee82020-03-21 23:56:07 -04001143 if (ctx->Pack.BufferObj) {
Samuel Pitoiset333663f2017-07-18 17:26:34 +02001144 _mesa_error(ctx, GL_INVALID_OPERATION,
1145 "glReadPixels(out of bounds PBO access)");
1146 } else {
1147 _mesa_error(ctx, GL_INVALID_OPERATION,
1148 "glReadnPixelsARB(out of bounds access:"
1149 " bufSize (%d) is too small)", bufSize);
1150 }
1151 return;
Brian Paul28876dd2008-06-09 14:22:15 -06001152 }
1153
Marek Olšák10beee82020-03-21 23:56:07 -04001154 if (ctx->Pack.BufferObj &&
Samuel Pitoiset333663f2017-07-18 17:26:34 +02001155 _mesa_check_disallowed_mapping(ctx->Pack.BufferObj)) {
1156 /* buffer is mapped - that's an error */
1157 _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(PBO is mapped)");
1158 return;
1159 }
Brian Paul28876dd2008-06-09 14:22:15 -06001160 }
1161
1162 ctx->Driver.ReadPixels(ctx, x, y, width, height,
Nanley Chery60583272016-02-05 16:21:33 -08001163 format, type, &clippedPacking, pixels);
Brian Paul28876dd2008-06-09 14:22:15 -06001164}
Brian Paul6b329b92011-04-26 14:54:41 -06001165
1166void GLAPIENTRY
Samuel Pitoisetfee507b2017-07-18 17:30:54 +02001167_mesa_ReadnPixelsARB_no_error(GLint x, GLint y, GLsizei width, GLsizei height,
1168 GLenum format, GLenum type, GLsizei bufSize,
1169 GLvoid *pixels)
1170{
1171 read_pixels(x, y, width, height, format, type, bufSize, pixels, true);
1172}
1173
1174void GLAPIENTRY
Samuel Pitoiset333663f2017-07-18 17:26:34 +02001175_mesa_ReadnPixelsARB(GLint x, GLint y, GLsizei width, GLsizei height,
1176 GLenum format, GLenum type, GLsizei bufSize,
1177 GLvoid *pixels)
1178{
1179 read_pixels(x, y, width, height, format, type, bufSize, pixels, false);
1180}
1181
1182void GLAPIENTRY
Samuel Pitoisetfee507b2017-07-18 17:30:54 +02001183_mesa_ReadPixels_no_error(GLint x, GLint y, GLsizei width, GLsizei height,
1184 GLenum format, GLenum type, GLvoid *pixels)
1185{
1186 _mesa_ReadnPixelsARB_no_error(x, y, width, height, format, type, INT_MAX,
1187 pixels);
1188}
1189
1190void GLAPIENTRY
Samuel Pitoiset333663f2017-07-18 17:26:34 +02001191_mesa_ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height,
1192 GLenum format, GLenum type, GLvoid *pixels)
Brian Paul6b329b92011-04-26 14:54:41 -06001193{
1194 _mesa_ReadnPixelsARB(x, y, width, height, format, type, INT_MAX, pixels);
1195}