readpix: add error checking for GLES3
[mesa.git] / src / mesa / main / readpix.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 7.1
4 *
5 * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25 #include "glheader.h"
26 #include "imports.h"
27 #include "bufferobj.h"
28 #include "context.h"
29 #include "enums.h"
30 #include "readpix.h"
31 #include "framebuffer.h"
32 #include "formats.h"
33 #include "format_unpack.h"
34 #include "image.h"
35 #include "mtypes.h"
36 #include "pack.h"
37 #include "pbo.h"
38 #include "state.h"
39 #include "glformats.h"
40 #include "fbobject.h"
41
42
43 /**
44 * Tries to implement glReadPixels() of GL_DEPTH_COMPONENT using memcpy of the
45 * mapping.
46 */
47 static GLboolean
48 fast_read_depth_pixels( struct gl_context *ctx,
49 GLint x, GLint y,
50 GLsizei width, GLsizei height,
51 GLenum type, GLvoid *pixels,
52 const struct gl_pixelstore_attrib *packing )
53 {
54 struct gl_framebuffer *fb = ctx->ReadBuffer;
55 struct gl_renderbuffer *rb = fb->Attachment[BUFFER_DEPTH].Renderbuffer;
56 GLubyte *map, *dst;
57 int stride, dstStride, j;
58
59 if (ctx->Pixel.DepthScale != 1.0 || ctx->Pixel.DepthBias != 0.0)
60 return GL_FALSE;
61
62 if (packing->SwapBytes)
63 return GL_FALSE;
64
65 if (_mesa_get_format_datatype(rb->Format) != GL_UNSIGNED_NORMALIZED)
66 return GL_FALSE;
67
68 if (!((type == GL_UNSIGNED_SHORT && rb->Format == MESA_FORMAT_Z16) ||
69 type == GL_UNSIGNED_INT))
70 return GL_FALSE;
71
72 ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT,
73 &map, &stride);
74
75 if (!map) {
76 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
77 return GL_TRUE; /* don't bother trying the slow path */
78 }
79
80 dstStride = _mesa_image_row_stride(packing, width, GL_DEPTH_COMPONENT, type);
81 dst = (GLubyte *) _mesa_image_address2d(packing, pixels, width, height,
82 GL_DEPTH_COMPONENT, type, 0, 0);
83
84 for (j = 0; j < height; j++) {
85 if (type == GL_UNSIGNED_INT) {
86 _mesa_unpack_uint_z_row(rb->Format, width, map, (GLuint *)dst);
87 } else {
88 ASSERT(type == GL_UNSIGNED_SHORT && rb->Format == MESA_FORMAT_Z16);
89 memcpy(dst, map, width * 2);
90 }
91
92 map += stride;
93 dst += dstStride;
94 }
95 ctx->Driver.UnmapRenderbuffer(ctx, rb);
96
97 return GL_TRUE;
98 }
99
100 /**
101 * Read pixels for format=GL_DEPTH_COMPONENT.
102 */
103 static void
104 read_depth_pixels( struct gl_context *ctx,
105 GLint x, GLint y,
106 GLsizei width, GLsizei height,
107 GLenum type, GLvoid *pixels,
108 const struct gl_pixelstore_attrib *packing )
109 {
110 struct gl_framebuffer *fb = ctx->ReadBuffer;
111 struct gl_renderbuffer *rb = fb->Attachment[BUFFER_DEPTH].Renderbuffer;
112 GLint j;
113 GLubyte *dst, *map;
114 int dstStride, stride;
115 GLfloat *depthValues;
116
117 if (!rb)
118 return;
119
120 /* clipping should have been done already */
121 ASSERT(x >= 0);
122 ASSERT(y >= 0);
123 ASSERT(x + width <= (GLint) rb->Width);
124 ASSERT(y + height <= (GLint) rb->Height);
125
126 if (fast_read_depth_pixels(ctx, x, y, width, height, type, pixels, packing))
127 return;
128
129 dstStride = _mesa_image_row_stride(packing, width, GL_DEPTH_COMPONENT, type);
130 dst = (GLubyte *) _mesa_image_address2d(packing, pixels, width, height,
131 GL_DEPTH_COMPONENT, type, 0, 0);
132
133 ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT,
134 &map, &stride);
135 if (!map) {
136 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
137 return;
138 }
139
140 depthValues = malloc(width * sizeof(GLfloat));
141
142 if (depthValues) {
143 /* General case (slower) */
144 for (j = 0; j < height; j++, y++) {
145 _mesa_unpack_float_z_row(rb->Format, width, map, depthValues);
146 _mesa_pack_depth_span(ctx, width, dst, type, depthValues, packing);
147
148 dst += dstStride;
149 map += stride;
150 }
151 }
152 else {
153 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
154 }
155
156 free(depthValues);
157
158 ctx->Driver.UnmapRenderbuffer(ctx, rb);
159 }
160
161
162 /**
163 * Read pixels for format=GL_STENCIL_INDEX.
164 */
165 static void
166 read_stencil_pixels( struct gl_context *ctx,
167 GLint x, GLint y,
168 GLsizei width, GLsizei height,
169 GLenum type, GLvoid *pixels,
170 const struct gl_pixelstore_attrib *packing )
171 {
172 struct gl_framebuffer *fb = ctx->ReadBuffer;
173 struct gl_renderbuffer *rb = fb->Attachment[BUFFER_STENCIL].Renderbuffer;
174 GLint j;
175 GLubyte *map, *stencil;
176 GLint stride;
177
178 if (!rb)
179 return;
180
181 ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT,
182 &map, &stride);
183 if (!map) {
184 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
185 return;
186 }
187
188 stencil = malloc(width * sizeof(GLubyte));
189
190 if (stencil) {
191 /* process image row by row */
192 for (j = 0; j < height; j++) {
193 GLvoid *dest;
194
195 _mesa_unpack_ubyte_stencil_row(rb->Format, width, map, stencil);
196 dest = _mesa_image_address2d(packing, pixels, width, height,
197 GL_STENCIL_INDEX, type, j, 0);
198
199 _mesa_pack_stencil_span(ctx, width, type, dest, stencil, packing);
200
201 map += stride;
202 }
203 }
204 else {
205 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
206 }
207
208 free(stencil);
209
210 ctx->Driver.UnmapRenderbuffer(ctx, rb);
211 }
212
213
214 /**
215 * Try to do glReadPixels of RGBA data using a simple memcpy or swizzle.
216 * \return GL_TRUE if successful, GL_FALSE otherwise (use the slow path)
217 */
218 static GLboolean
219 fast_read_rgba_pixels_memcpy( struct gl_context *ctx,
220 GLint x, GLint y,
221 GLsizei width, GLsizei height,
222 GLenum format, GLenum type,
223 GLvoid *pixels,
224 const struct gl_pixelstore_attrib *packing,
225 GLbitfield transferOps )
226 {
227 struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorReadBuffer;
228 GLubyte *dst, *map;
229 int dstStride, stride, j, texelBytes;
230 GLboolean swizzle_rb = GL_FALSE, copy_xrgb = GL_FALSE;
231
232 /* XXX we could check for other swizzle/special cases here as needed */
233 if (rb->Format == MESA_FORMAT_RGBA8888_REV &&
234 format == GL_BGRA &&
235 type == GL_UNSIGNED_INT_8_8_8_8_REV &&
236 !ctx->Pack.SwapBytes) {
237 swizzle_rb = GL_TRUE;
238 }
239 else if (rb->Format == MESA_FORMAT_XRGB8888 &&
240 format == GL_BGRA &&
241 type == GL_UNSIGNED_INT_8_8_8_8_REV &&
242 !ctx->Pack.SwapBytes) {
243 copy_xrgb = GL_TRUE;
244 }
245 else if (!_mesa_format_matches_format_and_type(rb->Format, format, type,
246 ctx->Pack.SwapBytes))
247 return GL_FALSE;
248
249 /* If the format is unsigned normalized then we can ignore clamping
250 * because the values are already in the range [0,1] so it won't
251 * have any effect anyway.
252 */
253 if (_mesa_get_format_datatype(rb->Format) == GL_UNSIGNED_NORMALIZED)
254 transferOps &= ~IMAGE_CLAMP_BIT;
255
256 if (transferOps)
257 return GL_FALSE;
258
259 dstStride = _mesa_image_row_stride(packing, width, format, type);
260 dst = (GLubyte *) _mesa_image_address2d(packing, pixels, width, height,
261 format, type, 0, 0);
262
263 ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT,
264 &map, &stride);
265 if (!map) {
266 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
267 return GL_TRUE; /* don't bother trying the slow path */
268 }
269
270 texelBytes = _mesa_get_format_bytes(rb->Format);
271
272 if (swizzle_rb) {
273 /* swap R/B */
274 for (j = 0; j < height; j++) {
275 int i;
276 for (i = 0; i < width; i++) {
277 GLuint *dst4 = (GLuint *) dst, *map4 = (GLuint *) map;
278 GLuint pixel = map4[i];
279 dst4[i] = (pixel & 0xff00ff00)
280 | ((pixel & 0x00ff0000) >> 16)
281 | ((pixel & 0x000000ff) << 16);
282 }
283 dst += dstStride;
284 map += stride;
285 }
286 } else if (copy_xrgb) {
287 /* convert xrgb -> argb */
288 for (j = 0; j < height; j++) {
289 GLuint *dst4 = (GLuint *) dst, *map4 = (GLuint *) map;
290 int i;
291 for (i = 0; i < width; i++) {
292 dst4[i] = map4[i] | 0xff000000; /* set A=0xff */
293 }
294 dst += dstStride;
295 map += stride;
296 }
297 } else {
298 /* just memcpy */
299 for (j = 0; j < height; j++) {
300 memcpy(dst, map, width * texelBytes);
301 dst += dstStride;
302 map += stride;
303 }
304 }
305
306 ctx->Driver.UnmapRenderbuffer(ctx, rb);
307
308 return GL_TRUE;
309 }
310
311 static void
312 slow_read_rgba_pixels( struct gl_context *ctx,
313 GLint x, GLint y,
314 GLsizei width, GLsizei height,
315 GLenum format, GLenum type,
316 GLvoid *pixels,
317 const struct gl_pixelstore_attrib *packing,
318 GLbitfield transferOps )
319 {
320 struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorReadBuffer;
321 const gl_format rbFormat = _mesa_get_srgb_format_linear(rb->Format);
322 void *rgba;
323 GLubyte *dst, *map;
324 int dstStride, stride, j;
325 GLboolean dst_is_integer = _mesa_is_enum_format_integer(format);
326 GLboolean dst_is_uint = _mesa_is_format_unsigned(rbFormat);
327
328 dstStride = _mesa_image_row_stride(packing, width, format, type);
329 dst = (GLubyte *) _mesa_image_address2d(packing, pixels, width, height,
330 format, type, 0, 0);
331
332 ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT,
333 &map, &stride);
334 if (!map) {
335 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
336 return;
337 }
338
339 rgba = malloc(width * MAX_PIXEL_BYTES);
340 if (!rgba)
341 goto done;
342
343 for (j = 0; j < height; j++) {
344 if (dst_is_integer) {
345 _mesa_unpack_uint_rgba_row(rbFormat, width, map, (GLuint (*)[4]) rgba);
346 _mesa_rebase_rgba_uint(width, (GLuint (*)[4]) rgba,
347 rb->_BaseFormat);
348 if (dst_is_uint) {
349 _mesa_pack_rgba_span_from_uints(ctx, width, (GLuint (*)[4]) rgba, format,
350 type, dst);
351 } else {
352 _mesa_pack_rgba_span_from_ints(ctx, width, (GLint (*)[4]) rgba, format,
353 type, dst);
354 }
355 } else {
356 _mesa_unpack_rgba_row(rbFormat, width, map, (GLfloat (*)[4]) rgba);
357 _mesa_rebase_rgba_float(width, (GLfloat (*)[4]) rgba,
358 rb->_BaseFormat);
359 _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba, format,
360 type, dst, packing, transferOps);
361 }
362 dst += dstStride;
363 map += stride;
364 }
365
366 free(rgba);
367
368 done:
369 ctx->Driver.UnmapRenderbuffer(ctx, rb);
370 }
371
372 /*
373 * Read R, G, B, A, RGB, L, or LA pixels.
374 */
375 static void
376 read_rgba_pixels( struct gl_context *ctx,
377 GLint x, GLint y,
378 GLsizei width, GLsizei height,
379 GLenum format, GLenum type, GLvoid *pixels,
380 const struct gl_pixelstore_attrib *packing )
381 {
382 GLbitfield transferOps = ctx->_ImageTransferState;
383 struct gl_framebuffer *fb = ctx->ReadBuffer;
384 struct gl_renderbuffer *rb = fb->_ColorReadBuffer;
385
386 if (!rb)
387 return;
388
389 if ((ctx->Color._ClampReadColor == GL_TRUE || type != GL_FLOAT) &&
390 !_mesa_is_enum_format_integer(format)) {
391 transferOps |= IMAGE_CLAMP_BIT;
392 }
393
394 /* Try the optimized paths first. */
395 if (fast_read_rgba_pixels_memcpy(ctx, x, y, width, height,
396 format, type, pixels, packing,
397 transferOps)) {
398 return;
399 }
400
401 slow_read_rgba_pixels(ctx, x, y, width, height,
402 format, type, pixels, packing, transferOps);
403 }
404
405 /**
406 * For a packed depth/stencil buffer being read as depth/stencil, just memcpy the
407 * data (possibly swapping 8/24 vs 24/8 as we go).
408 */
409 static GLboolean
410 fast_read_depth_stencil_pixels(struct gl_context *ctx,
411 GLint x, GLint y,
412 GLsizei width, GLsizei height,
413 GLubyte *dst, int dstStride)
414 {
415 struct gl_framebuffer *fb = ctx->ReadBuffer;
416 struct gl_renderbuffer *rb = fb->Attachment[BUFFER_DEPTH].Renderbuffer;
417 struct gl_renderbuffer *stencilRb = fb->Attachment[BUFFER_STENCIL].Renderbuffer;
418 GLubyte *map;
419 int stride, i;
420
421 if (rb != stencilRb)
422 return GL_FALSE;
423
424 if (rb->Format != MESA_FORMAT_Z24_S8 &&
425 rb->Format != MESA_FORMAT_S8_Z24)
426 return GL_FALSE;
427
428 ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT,
429 &map, &stride);
430 if (!map) {
431 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
432 return GL_TRUE; /* don't bother trying the slow path */
433 }
434
435 for (i = 0; i < height; i++) {
436 _mesa_unpack_uint_24_8_depth_stencil_row(rb->Format, width,
437 map, (GLuint *)dst);
438 map += stride;
439 dst += dstStride;
440 }
441
442 ctx->Driver.UnmapRenderbuffer(ctx, rb);
443
444 return GL_TRUE;
445 }
446
447
448 /**
449 * For non-float-depth and stencil buffers being read as 24/8 depth/stencil,
450 * copy the integer data directly instead of converting depth to float and
451 * re-packing.
452 */
453 static GLboolean
454 fast_read_depth_stencil_pixels_separate(struct gl_context *ctx,
455 GLint x, GLint y,
456 GLsizei width, GLsizei height,
457 uint32_t *dst, int dstStride)
458 {
459 struct gl_framebuffer *fb = ctx->ReadBuffer;
460 struct gl_renderbuffer *depthRb = fb->Attachment[BUFFER_DEPTH].Renderbuffer;
461 struct gl_renderbuffer *stencilRb = fb->Attachment[BUFFER_STENCIL].Renderbuffer;
462 GLubyte *depthMap, *stencilMap, *stencilVals;
463 int depthStride, stencilStride, i, j;
464
465 if (_mesa_get_format_datatype(depthRb->Format) != GL_UNSIGNED_NORMALIZED)
466 return GL_FALSE;
467
468 ctx->Driver.MapRenderbuffer(ctx, depthRb, x, y, width, height,
469 GL_MAP_READ_BIT, &depthMap, &depthStride);
470 if (!depthMap) {
471 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
472 return GL_TRUE; /* don't bother trying the slow path */
473 }
474
475 ctx->Driver.MapRenderbuffer(ctx, stencilRb, x, y, width, height,
476 GL_MAP_READ_BIT, &stencilMap, &stencilStride);
477 if (!stencilMap) {
478 ctx->Driver.UnmapRenderbuffer(ctx, depthRb);
479 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
480 return GL_TRUE; /* don't bother trying the slow path */
481 }
482
483 stencilVals = malloc(width * sizeof(GLubyte));
484
485 if (stencilVals) {
486 for (j = 0; j < height; j++) {
487 _mesa_unpack_uint_z_row(depthRb->Format, width, depthMap, dst);
488 _mesa_unpack_ubyte_stencil_row(stencilRb->Format, width,
489 stencilMap, stencilVals);
490
491 for (i = 0; i < width; i++) {
492 dst[i] = (dst[i] & 0xffffff00) | stencilVals[i];
493 }
494
495 depthMap += depthStride;
496 stencilMap += stencilStride;
497 dst += dstStride / 4;
498 }
499 }
500 else {
501 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
502 }
503
504 free(stencilVals);
505
506 ctx->Driver.UnmapRenderbuffer(ctx, depthRb);
507 ctx->Driver.UnmapRenderbuffer(ctx, stencilRb);
508
509 return GL_TRUE;
510 }
511
512 static void
513 slow_read_depth_stencil_pixels_separate(struct gl_context *ctx,
514 GLint x, GLint y,
515 GLsizei width, GLsizei height,
516 GLenum type,
517 const struct gl_pixelstore_attrib *packing,
518 GLubyte *dst, int dstStride)
519 {
520 struct gl_framebuffer *fb = ctx->ReadBuffer;
521 struct gl_renderbuffer *depthRb = fb->Attachment[BUFFER_DEPTH].Renderbuffer;
522 struct gl_renderbuffer *stencilRb = fb->Attachment[BUFFER_STENCIL].Renderbuffer;
523 GLubyte *depthMap, *stencilMap;
524 int depthStride, stencilStride, j;
525 GLubyte *stencilVals;
526 GLfloat *depthVals;
527
528
529 /* The depth and stencil buffers might be separate, or a single buffer.
530 * If one buffer, only map it once.
531 */
532 ctx->Driver.MapRenderbuffer(ctx, depthRb, x, y, width, height,
533 GL_MAP_READ_BIT, &depthMap, &depthStride);
534 if (!depthMap) {
535 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
536 return;
537 }
538
539 if (stencilRb != depthRb) {
540 ctx->Driver.MapRenderbuffer(ctx, stencilRb, x, y, width, height,
541 GL_MAP_READ_BIT, &stencilMap,
542 &stencilStride);
543 if (!stencilMap) {
544 ctx->Driver.UnmapRenderbuffer(ctx, depthRb);
545 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
546 return;
547 }
548 }
549 else {
550 stencilMap = depthMap;
551 stencilStride = depthStride;
552 }
553
554 stencilVals = malloc(width * sizeof(GLubyte));
555 depthVals = malloc(width * sizeof(GLfloat));
556
557 if (stencilVals && depthVals) {
558 for (j = 0; j < height; j++) {
559 _mesa_unpack_float_z_row(depthRb->Format, width, depthMap, depthVals);
560 _mesa_unpack_ubyte_stencil_row(stencilRb->Format, width,
561 stencilMap, stencilVals);
562
563 _mesa_pack_depth_stencil_span(ctx, width, type, (GLuint *)dst,
564 depthVals, stencilVals, packing);
565
566 depthMap += depthStride;
567 stencilMap += stencilStride;
568 dst += dstStride;
569 }
570 }
571 else {
572 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
573 }
574
575 free(stencilVals);
576 free(depthVals);
577
578 ctx->Driver.UnmapRenderbuffer(ctx, depthRb);
579 if (stencilRb != depthRb) {
580 ctx->Driver.UnmapRenderbuffer(ctx, stencilRb);
581 }
582 }
583
584
585 /**
586 * Read combined depth/stencil values.
587 * We'll have already done error checking to be sure the expected
588 * depth and stencil buffers really exist.
589 */
590 static void
591 read_depth_stencil_pixels(struct gl_context *ctx,
592 GLint x, GLint y,
593 GLsizei width, GLsizei height,
594 GLenum type, GLvoid *pixels,
595 const struct gl_pixelstore_attrib *packing )
596 {
597 const GLboolean scaleOrBias
598 = ctx->Pixel.DepthScale != 1.0 || ctx->Pixel.DepthBias != 0.0;
599 const GLboolean stencilTransfer = ctx->Pixel.IndexShift
600 || ctx->Pixel.IndexOffset || ctx->Pixel.MapStencilFlag;
601 GLubyte *dst;
602 int dstStride;
603
604 dst = (GLubyte *) _mesa_image_address2d(packing, pixels,
605 width, height,
606 GL_DEPTH_STENCIL_EXT,
607 type, 0, 0);
608 dstStride = _mesa_image_row_stride(packing, width,
609 GL_DEPTH_STENCIL_EXT, type);
610
611 /* Fast 24/8 reads. */
612 if (type == GL_UNSIGNED_INT_24_8 &&
613 !scaleOrBias && !stencilTransfer && !packing->SwapBytes) {
614 if (fast_read_depth_stencil_pixels(ctx, x, y, width, height,
615 dst, dstStride))
616 return;
617
618 if (fast_read_depth_stencil_pixels_separate(ctx, x, y, width, height,
619 (uint32_t *)dst, dstStride))
620 return;
621 }
622
623 slow_read_depth_stencil_pixels_separate(ctx, x, y, width, height,
624 type, packing,
625 dst, dstStride);
626 }
627
628
629
630 /**
631 * Software fallback routine for ctx->Driver.ReadPixels().
632 * By time we get here, all error checking will have been done.
633 */
634 void
635 _mesa_readpixels(struct gl_context *ctx,
636 GLint x, GLint y, GLsizei width, GLsizei height,
637 GLenum format, GLenum type,
638 const struct gl_pixelstore_attrib *packing,
639 GLvoid *pixels)
640 {
641 struct gl_pixelstore_attrib clippedPacking = *packing;
642
643 if (ctx->NewState)
644 _mesa_update_state(ctx);
645
646 /* Do all needed clipping here, so that we can forget about it later */
647 if (_mesa_clip_readpixels(ctx, &x, &y, &width, &height, &clippedPacking)) {
648
649 pixels = _mesa_map_pbo_dest(ctx, &clippedPacking, pixels);
650
651 if (pixels) {
652 switch (format) {
653 case GL_STENCIL_INDEX:
654 read_stencil_pixels(ctx, x, y, width, height, type, pixels,
655 &clippedPacking);
656 break;
657 case GL_DEPTH_COMPONENT:
658 read_depth_pixels(ctx, x, y, width, height, type, pixels,
659 &clippedPacking);
660 break;
661 case GL_DEPTH_STENCIL_EXT:
662 read_depth_stencil_pixels(ctx, x, y, width, height, type, pixels,
663 &clippedPacking);
664 break;
665 default:
666 /* all other formats should be color formats */
667 read_rgba_pixels(ctx, x, y, width, height, format, type, pixels,
668 &clippedPacking);
669 }
670
671 _mesa_unmap_pbo_dest(ctx, &clippedPacking);
672 }
673 }
674 }
675
676
677 static GLenum
678 read_pixels_es3_error_check(GLenum format, GLenum type,
679 const struct gl_renderbuffer *rb)
680 {
681 const GLenum internalFormat = rb->InternalFormat;
682 const GLenum data_type = _mesa_get_format_datatype(rb->Format);
683 GLboolean is_unsigned_int = GL_FALSE;
684 GLboolean is_signed_int = GL_FALSE;
685
686 if (!_mesa_is_color_format(internalFormat)) {
687 return GL_INVALID_OPERATION;
688 }
689
690 is_unsigned_int = _mesa_is_enum_format_unsigned_int(internalFormat);
691 if (!is_unsigned_int) {
692 is_signed_int = _mesa_is_enum_format_signed_int(internalFormat);
693 }
694
695 switch (format) {
696 case GL_RGBA:
697 if (type == GL_UNSIGNED_BYTE && data_type == GL_UNSIGNED_NORMALIZED)
698 return GL_NO_ERROR;
699 if (internalFormat == GL_RGB10_A2 &&
700 type == GL_UNSIGNED_INT_2_10_10_10_REV)
701 return GL_NO_ERROR;
702 if (internalFormat == GL_RGB10_A2UI && type == GL_UNSIGNED_BYTE)
703 return GL_NO_ERROR;
704 break;
705 case GL_BGRA:
706 /* GL_EXT_read_format_bgra */
707 if (type == GL_UNSIGNED_BYTE ||
708 type == GL_UNSIGNED_SHORT_4_4_4_4_REV ||
709 type == GL_UNSIGNED_SHORT_1_5_5_5_REV)
710 return GL_NO_ERROR;
711 break;
712 case GL_RGBA_INTEGER:
713 if ((is_signed_int && type == GL_INT) ||
714 (is_unsigned_int && type == GL_UNSIGNED_INT))
715 return GL_NO_ERROR;
716 break;
717 }
718
719 return GL_INVALID_OPERATION;
720 }
721
722
723 void GLAPIENTRY
724 _mesa_ReadnPixelsARB( GLint x, GLint y, GLsizei width, GLsizei height,
725 GLenum format, GLenum type, GLsizei bufSize,
726 GLvoid *pixels )
727 {
728 GLenum err = GL_NO_ERROR;
729 struct gl_renderbuffer *rb;
730
731 GET_CURRENT_CONTEXT(ctx);
732 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
733
734 FLUSH_CURRENT(ctx, 0);
735
736 if (MESA_VERBOSE & VERBOSE_API)
737 _mesa_debug(ctx, "glReadPixels(%d, %d, %s, %s, %p)\n",
738 width, height,
739 _mesa_lookup_enum_by_nr(format),
740 _mesa_lookup_enum_by_nr(type),
741 pixels);
742
743 if (width < 0 || height < 0) {
744 _mesa_error( ctx, GL_INVALID_VALUE,
745 "glReadPixels(width=%d height=%d)", width, height );
746 return;
747 }
748
749 rb = _mesa_get_read_renderbuffer_for_format(ctx, format);
750 if (rb == NULL) {
751 _mesa_error(ctx, GL_INVALID_OPERATION,
752 "glReadPixels(read buffer)");
753 return;
754 }
755
756 /* OpenGL ES 1.x and OpenGL ES 2.0 impose additional restrictions on the
757 * combinations of format and type that can be used.
758 *
759 * Technically, only two combinations are actually allowed:
760 * GL_RGBA/GL_UNSIGNED_BYTE, and some implementation-specific internal
761 * preferred combination. This code doesn't know what that preferred
762 * combination is, and Mesa can handle anything valid. Just work instead.
763 */
764 if (_mesa_is_gles(ctx)) {
765 if (ctx->Version < 30) {
766 err = _mesa_es_error_check_format_and_type(format, type, 2);
767 if (err == GL_NO_ERROR) {
768 if (type == GL_FLOAT || type == GL_HALF_FLOAT_OES) {
769 err = GL_INVALID_OPERATION;
770 }
771 }
772 } else {
773 err = read_pixels_es3_error_check(format, type, rb);
774 }
775
776 if (err == GL_NO_ERROR && (format == GL_DEPTH_COMPONENT
777 || format == GL_DEPTH_STENCIL)) {
778 err = GL_INVALID_ENUM;
779 }
780
781 if (err != GL_NO_ERROR) {
782 _mesa_error(ctx, err, "glReadPixels(invalid format %s and/or type %s)",
783 _mesa_lookup_enum_by_nr(format),
784 _mesa_lookup_enum_by_nr(type));
785 return;
786 }
787 }
788
789 if (ctx->NewState)
790 _mesa_update_state(ctx);
791
792 err = _mesa_error_check_format_and_type(ctx, format, type);
793 if (err != GL_NO_ERROR) {
794 _mesa_error(ctx, err, "glReadPixels(invalid format %s and/or type %s)",
795 _mesa_lookup_enum_by_nr(format),
796 _mesa_lookup_enum_by_nr(type));
797 return;
798 }
799
800 if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
801 _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
802 "glReadPixels(incomplete framebuffer)" );
803 return;
804 }
805
806 if (_mesa_is_user_fbo(ctx->ReadBuffer) &&
807 ctx->ReadBuffer->Visual.samples > 0) {
808 _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(multisample FBO)");
809 return;
810 }
811
812 if (!_mesa_source_buffer_exists(ctx, format)) {
813 _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(no readbuffer)");
814 return;
815 }
816
817 /* Check that the destination format and source buffer are both
818 * integer-valued or both non-integer-valued.
819 */
820 if (ctx->Extensions.EXT_texture_integer && _mesa_is_color_format(format)) {
821 const struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorReadBuffer;
822 const GLboolean srcInteger = _mesa_is_format_integer_color(rb->Format);
823 const GLboolean dstInteger = _mesa_is_enum_format_integer(format);
824 if (dstInteger != srcInteger) {
825 _mesa_error(ctx, GL_INVALID_OPERATION,
826 "glReadPixels(integer / non-integer format mismatch");
827 return;
828 }
829 }
830
831 if (width == 0 || height == 0)
832 return; /* nothing to do */
833
834 if (!_mesa_validate_pbo_access(2, &ctx->Pack, width, height, 1,
835 format, type, bufSize, pixels)) {
836 if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
837 _mesa_error(ctx, GL_INVALID_OPERATION,
838 "glReadPixels(out of bounds PBO access)");
839 } else {
840 _mesa_error(ctx, GL_INVALID_OPERATION,
841 "glReadnPixelsARB(out of bounds access:"
842 " bufSize (%d) is too small)", bufSize);
843 }
844 return;
845 }
846
847 if (_mesa_is_bufferobj(ctx->Pack.BufferObj) &&
848 _mesa_bufferobj_mapped(ctx->Pack.BufferObj)) {
849 /* buffer is mapped - that's an error */
850 _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(PBO is mapped)");
851 return;
852 }
853
854 ctx->Driver.ReadPixels(ctx, x, y, width, height,
855 format, type, &ctx->Pack, pixels);
856 }
857
858 void GLAPIENTRY
859 _mesa_ReadPixels( GLint x, GLint y, GLsizei width, GLsizei height,
860 GLenum format, GLenum type, GLvoid *pixels )
861 {
862 _mesa_ReadnPixelsARB(x, y, width, height, format, type, INT_MAX, pixels);
863 }