mesa: add common format-independent memcpy-based ReadPixels path
[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 * Return true if the conversion L=R+G+B is needed.
45 */
46 static GLboolean
47 need_rgb_to_luminance_conversion(gl_format texFormat, GLenum format)
48 {
49 GLenum baseTexFormat = _mesa_get_format_base_format(texFormat);
50
51 return (baseTexFormat == GL_RG ||
52 baseTexFormat == GL_RGB ||
53 baseTexFormat == GL_RGBA) &&
54 (format == GL_LUMINANCE || format == GL_LUMINANCE_ALPHA);
55 }
56
57
58 /**
59 * Return transfer op flags for this ReadPixels operation.
60 */
61 static GLbitfield
62 get_readpixels_transfer_ops(const struct gl_context *ctx, gl_format texFormat,
63 GLenum format, GLenum type, GLboolean uses_blit)
64 {
65 GLbitfield transferOps = ctx->_ImageTransferState;
66
67 if (format == GL_DEPTH_COMPONENT ||
68 format == GL_DEPTH_STENCIL ||
69 format == GL_STENCIL_INDEX) {
70 return 0;
71 }
72
73 /* Pixel transfer ops (scale, bias, table lookup) do not apply
74 * to integer formats.
75 */
76 if (_mesa_is_enum_format_integer(format)) {
77 return 0;
78 }
79
80 if (uses_blit) {
81 /* For blit-based ReadPixels packing, the clamping is done automatically
82 * unless the type is float. */
83 if (ctx->Color._ClampReadColor == GL_TRUE &&
84 (type == GL_FLOAT || type == GL_HALF_FLOAT)) {
85 transferOps |= IMAGE_CLAMP_BIT;
86 }
87 }
88 else {
89 /* For CPU-based ReadPixels packing, the clamping must always be done
90 * for non-float types, */
91 if (ctx->Color._ClampReadColor == GL_TRUE ||
92 (type != GL_FLOAT && type != GL_HALF_FLOAT)) {
93 transferOps |= IMAGE_CLAMP_BIT;
94 }
95 }
96
97 /* If the format is unsigned normalized, we can ignore clamping
98 * because the values are already in the range [0,1] so it won't
99 * have any effect anyway.
100 */
101 if (_mesa_get_format_datatype(texFormat) == GL_UNSIGNED_NORMALIZED &&
102 !need_rgb_to_luminance_conversion(texFormat, format)) {
103 transferOps &= ~IMAGE_CLAMP_BIT;
104 }
105
106 return transferOps;
107 }
108
109
110 /**
111 * Return true if memcpy cannot be used for ReadPixels.
112 *
113 * If uses_blit is true, the function returns true if a simple 3D engine blit
114 * cannot be used for ReadPixels packing.
115 *
116 * NOTE: This doesn't take swizzling and format conversions between
117 * the readbuffer and the pixel pack buffer into account.
118 */
119 GLboolean
120 _mesa_readpixels_needs_slow_path(const struct gl_context *ctx, GLenum format,
121 GLenum type, GLboolean uses_blit)
122 {
123 struct gl_renderbuffer *rb =
124 _mesa_get_read_renderbuffer_for_format(ctx, format);
125 GLenum srcType;
126
127 ASSERT(rb);
128
129 /* There are different rules depending on the base format. */
130 switch (format) {
131 case GL_DEPTH_STENCIL:
132 return !_mesa_has_depthstencil_combined(ctx->ReadBuffer) ||
133 ctx->Pixel.DepthScale != 1.0f || ctx->Pixel.DepthBias != 0.0f ||
134 ctx->Pixel.IndexShift || ctx->Pixel.IndexOffset ||
135 ctx->Pixel.MapStencilFlag;
136
137 case GL_DEPTH_COMPONENT:
138 return ctx->Pixel.DepthScale != 1.0f || ctx->Pixel.DepthBias != 0.0f;
139
140 case GL_STENCIL_INDEX:
141 return ctx->Pixel.IndexShift || ctx->Pixel.IndexOffset ||
142 ctx->Pixel.MapStencilFlag;
143
144 default:
145 /* Color formats. */
146 if (need_rgb_to_luminance_conversion(rb->Format, format)) {
147 return GL_TRUE;
148 }
149
150 /* Conversion between signed and unsigned integers needs masking
151 * (it isn't just memcpy). */
152 srcType = _mesa_get_format_datatype(rb->Format);
153
154 if ((srcType == GL_INT &&
155 (type == GL_UNSIGNED_INT ||
156 type == GL_UNSIGNED_SHORT ||
157 type == GL_UNSIGNED_BYTE)) ||
158 (srcType == GL_UNSIGNED_INT &&
159 (type == GL_INT ||
160 type == GL_SHORT ||
161 type == GL_BYTE))) {
162 return GL_TRUE;
163 }
164
165 /* And finally, see if there are any transfer ops. */
166 return get_readpixels_transfer_ops(ctx, rb->Format, format, type,
167 uses_blit) != 0;
168 }
169 return GL_FALSE;
170 }
171
172
173 static GLboolean
174 readpixels_can_use_memcpy(const struct gl_context *ctx, GLenum format, GLenum type,
175 const struct gl_pixelstore_attrib *packing)
176 {
177 struct gl_renderbuffer *rb =
178 _mesa_get_read_renderbuffer_for_format(ctx, format);
179
180 ASSERT(rb);
181
182 if (_mesa_readpixels_needs_slow_path(ctx, format, type, GL_FALSE)) {
183 return GL_FALSE;
184 }
185
186 /* The base internal format and the base Mesa format must match. */
187 if (rb->_BaseFormat != _mesa_get_format_base_format(rb->Format)) {
188 return GL_FALSE;
189 }
190
191 /* The Mesa format must match the input format and type. */
192 if (!_mesa_format_matches_format_and_type(rb->Format, format, type,
193 packing->SwapBytes)) {
194 return GL_FALSE;
195 }
196
197 return GL_TRUE;
198 }
199
200
201 static GLboolean
202 readpixels_memcpy(struct gl_context *ctx,
203 GLint x, GLint y,
204 GLsizei width, GLsizei height,
205 GLenum format, GLenum type,
206 GLvoid *pixels,
207 const struct gl_pixelstore_attrib *packing)
208 {
209 struct gl_renderbuffer *rb =
210 _mesa_get_read_renderbuffer_for_format(ctx, format);
211 GLubyte *dst, *map;
212 int dstStride, stride, j, texelBytes;
213
214 /* Fail if memcpy cannot be used. */
215 if (!readpixels_can_use_memcpy(ctx, format, type, packing)) {
216 return GL_FALSE;
217 }
218
219 dstStride = _mesa_image_row_stride(packing, width, format, type);
220 dst = (GLubyte *) _mesa_image_address2d(packing, pixels, width, height,
221 format, type, 0, 0);
222
223 ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT,
224 &map, &stride);
225 if (!map) {
226 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
227 return GL_TRUE; /* don't bother trying the slow path */
228 }
229
230 texelBytes = _mesa_get_format_bytes(rb->Format);
231
232 /* memcpy*/
233 for (j = 0; j < height; j++) {
234 memcpy(dst, map, width * texelBytes);
235 dst += dstStride;
236 map += stride;
237 }
238
239 ctx->Driver.UnmapRenderbuffer(ctx, rb);
240 return GL_TRUE;
241 }
242
243
244 /**
245 * Optimized path for conversion of depth values to GL_DEPTH_COMPONENT,
246 * GL_UNSIGNED_INT.
247 */
248 static GLboolean
249 read_uint_depth_pixels( struct gl_context *ctx,
250 GLint x, GLint y,
251 GLsizei width, GLsizei height,
252 GLenum type, GLvoid *pixels,
253 const struct gl_pixelstore_attrib *packing )
254 {
255 struct gl_framebuffer *fb = ctx->ReadBuffer;
256 struct gl_renderbuffer *rb = fb->Attachment[BUFFER_DEPTH].Renderbuffer;
257 GLubyte *map, *dst;
258 int stride, dstStride, j;
259
260 if (ctx->Pixel.DepthScale != 1.0 || ctx->Pixel.DepthBias != 0.0)
261 return GL_FALSE;
262
263 if (packing->SwapBytes)
264 return GL_FALSE;
265
266 if (_mesa_get_format_datatype(rb->Format) != GL_UNSIGNED_NORMALIZED)
267 return GL_FALSE;
268
269 ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT,
270 &map, &stride);
271
272 if (!map) {
273 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
274 return GL_TRUE; /* don't bother trying the slow path */
275 }
276
277 dstStride = _mesa_image_row_stride(packing, width, GL_DEPTH_COMPONENT, type);
278 dst = (GLubyte *) _mesa_image_address2d(packing, pixels, width, height,
279 GL_DEPTH_COMPONENT, type, 0, 0);
280
281 for (j = 0; j < height; j++) {
282 _mesa_unpack_uint_z_row(rb->Format, width, map, (GLuint *)dst);
283
284 map += stride;
285 dst += dstStride;
286 }
287 ctx->Driver.UnmapRenderbuffer(ctx, rb);
288
289 return GL_TRUE;
290 }
291
292 /**
293 * Read pixels for format=GL_DEPTH_COMPONENT.
294 */
295 static void
296 read_depth_pixels( struct gl_context *ctx,
297 GLint x, GLint y,
298 GLsizei width, GLsizei height,
299 GLenum type, GLvoid *pixels,
300 const struct gl_pixelstore_attrib *packing )
301 {
302 struct gl_framebuffer *fb = ctx->ReadBuffer;
303 struct gl_renderbuffer *rb = fb->Attachment[BUFFER_DEPTH].Renderbuffer;
304 GLint j;
305 GLubyte *dst, *map;
306 int dstStride, stride;
307 GLfloat *depthValues;
308
309 if (!rb)
310 return;
311
312 /* clipping should have been done already */
313 ASSERT(x >= 0);
314 ASSERT(y >= 0);
315 ASSERT(x + width <= (GLint) rb->Width);
316 ASSERT(y + height <= (GLint) rb->Height);
317
318 if (type == GL_UNSIGNED_INT &&
319 read_uint_depth_pixels(ctx, x, y, width, height, type, pixels, packing)) {
320 return;
321 }
322
323 dstStride = _mesa_image_row_stride(packing, width, GL_DEPTH_COMPONENT, type);
324 dst = (GLubyte *) _mesa_image_address2d(packing, pixels, width, height,
325 GL_DEPTH_COMPONENT, type, 0, 0);
326
327 ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT,
328 &map, &stride);
329 if (!map) {
330 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
331 return;
332 }
333
334 depthValues = malloc(width * sizeof(GLfloat));
335
336 if (depthValues) {
337 /* General case (slower) */
338 for (j = 0; j < height; j++, y++) {
339 _mesa_unpack_float_z_row(rb->Format, width, map, depthValues);
340 _mesa_pack_depth_span(ctx, width, dst, type, depthValues, packing);
341
342 dst += dstStride;
343 map += stride;
344 }
345 }
346 else {
347 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
348 }
349
350 free(depthValues);
351
352 ctx->Driver.UnmapRenderbuffer(ctx, rb);
353 }
354
355
356 /**
357 * Read pixels for format=GL_STENCIL_INDEX.
358 */
359 static void
360 read_stencil_pixels( struct gl_context *ctx,
361 GLint x, GLint y,
362 GLsizei width, GLsizei height,
363 GLenum type, GLvoid *pixels,
364 const struct gl_pixelstore_attrib *packing )
365 {
366 struct gl_framebuffer *fb = ctx->ReadBuffer;
367 struct gl_renderbuffer *rb = fb->Attachment[BUFFER_STENCIL].Renderbuffer;
368 GLint j;
369 GLubyte *map, *stencil;
370 GLint stride;
371
372 if (!rb)
373 return;
374
375 ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT,
376 &map, &stride);
377 if (!map) {
378 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
379 return;
380 }
381
382 stencil = malloc(width * sizeof(GLubyte));
383
384 if (stencil) {
385 /* process image row by row */
386 for (j = 0; j < height; j++) {
387 GLvoid *dest;
388
389 _mesa_unpack_ubyte_stencil_row(rb->Format, width, map, stencil);
390 dest = _mesa_image_address2d(packing, pixels, width, height,
391 GL_STENCIL_INDEX, type, j, 0);
392
393 _mesa_pack_stencil_span(ctx, width, type, dest, stencil, packing);
394
395 map += stride;
396 }
397 }
398 else {
399 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
400 }
401
402 free(stencil);
403
404 ctx->Driver.UnmapRenderbuffer(ctx, rb);
405 }
406
407
408 /**
409 * Try to do glReadPixels of RGBA data using swizzle.
410 * \return GL_TRUE if successful, GL_FALSE otherwise (use the slow path)
411 */
412 static GLboolean
413 read_rgba_pixels_swizzle(struct gl_context *ctx,
414 GLint x, GLint y,
415 GLsizei width, GLsizei height,
416 GLenum format, GLenum type,
417 GLvoid *pixels,
418 const struct gl_pixelstore_attrib *packing)
419 {
420 struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorReadBuffer;
421 GLubyte *dst, *map;
422 int dstStride, stride, j;
423 GLboolean swizzle_rb = GL_FALSE, copy_xrgb = GL_FALSE;
424
425 /* XXX we could check for other swizzle/special cases here as needed */
426 if (rb->Format == MESA_FORMAT_RGBA8888_REV &&
427 format == GL_BGRA &&
428 type == GL_UNSIGNED_INT_8_8_8_8_REV &&
429 !ctx->Pack.SwapBytes) {
430 swizzle_rb = GL_TRUE;
431 }
432 else if (rb->Format == MESA_FORMAT_XRGB8888 &&
433 format == GL_BGRA &&
434 type == GL_UNSIGNED_INT_8_8_8_8_REV &&
435 !ctx->Pack.SwapBytes) {
436 copy_xrgb = GL_TRUE;
437 }
438 else {
439 return GL_FALSE;
440 }
441
442 dstStride = _mesa_image_row_stride(packing, width, format, type);
443 dst = (GLubyte *) _mesa_image_address2d(packing, pixels, width, height,
444 format, type, 0, 0);
445
446 ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT,
447 &map, &stride);
448 if (!map) {
449 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
450 return GL_TRUE; /* don't bother trying the slow path */
451 }
452
453 if (swizzle_rb) {
454 /* swap R/B */
455 for (j = 0; j < height; j++) {
456 int i;
457 for (i = 0; i < width; i++) {
458 GLuint *dst4 = (GLuint *) dst, *map4 = (GLuint *) map;
459 GLuint pixel = map4[i];
460 dst4[i] = (pixel & 0xff00ff00)
461 | ((pixel & 0x00ff0000) >> 16)
462 | ((pixel & 0x000000ff) << 16);
463 }
464 dst += dstStride;
465 map += stride;
466 }
467 } else if (copy_xrgb) {
468 /* convert xrgb -> argb */
469 for (j = 0; j < height; j++) {
470 GLuint *dst4 = (GLuint *) dst, *map4 = (GLuint *) map;
471 int i;
472 for (i = 0; i < width; i++) {
473 dst4[i] = map4[i] | 0xff000000; /* set A=0xff */
474 }
475 dst += dstStride;
476 map += stride;
477 }
478 }
479
480 ctx->Driver.UnmapRenderbuffer(ctx, rb);
481
482 return GL_TRUE;
483 }
484
485 static void
486 slow_read_rgba_pixels( struct gl_context *ctx,
487 GLint x, GLint y,
488 GLsizei width, GLsizei height,
489 GLenum format, GLenum type,
490 GLvoid *pixels,
491 const struct gl_pixelstore_attrib *packing,
492 GLbitfield transferOps )
493 {
494 struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorReadBuffer;
495 const gl_format rbFormat = _mesa_get_srgb_format_linear(rb->Format);
496 void *rgba;
497 GLubyte *dst, *map;
498 int dstStride, stride, j;
499 GLboolean dst_is_integer = _mesa_is_enum_format_integer(format);
500 GLboolean dst_is_uint = _mesa_is_format_unsigned(rbFormat);
501
502 dstStride = _mesa_image_row_stride(packing, width, format, type);
503 dst = (GLubyte *) _mesa_image_address2d(packing, pixels, width, height,
504 format, type, 0, 0);
505
506 ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT,
507 &map, &stride);
508 if (!map) {
509 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
510 return;
511 }
512
513 rgba = malloc(width * MAX_PIXEL_BYTES);
514 if (!rgba)
515 goto done;
516
517 for (j = 0; j < height; j++) {
518 if (dst_is_integer) {
519 _mesa_unpack_uint_rgba_row(rbFormat, width, map, (GLuint (*)[4]) rgba);
520 _mesa_rebase_rgba_uint(width, (GLuint (*)[4]) rgba,
521 rb->_BaseFormat);
522 if (dst_is_uint) {
523 _mesa_pack_rgba_span_from_uints(ctx, width, (GLuint (*)[4]) rgba, format,
524 type, dst);
525 } else {
526 _mesa_pack_rgba_span_from_ints(ctx, width, (GLint (*)[4]) rgba, format,
527 type, dst);
528 }
529 } else {
530 _mesa_unpack_rgba_row(rbFormat, width, map, (GLfloat (*)[4]) rgba);
531 _mesa_rebase_rgba_float(width, (GLfloat (*)[4]) rgba,
532 rb->_BaseFormat);
533 _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba, format,
534 type, dst, packing, transferOps);
535 }
536 dst += dstStride;
537 map += stride;
538 }
539
540 free(rgba);
541
542 done:
543 ctx->Driver.UnmapRenderbuffer(ctx, rb);
544 }
545
546 /*
547 * Read R, G, B, A, RGB, L, or LA pixels.
548 */
549 static void
550 read_rgba_pixels( struct gl_context *ctx,
551 GLint x, GLint y,
552 GLsizei width, GLsizei height,
553 GLenum format, GLenum type, GLvoid *pixels,
554 const struct gl_pixelstore_attrib *packing )
555 {
556 GLbitfield transferOps;
557 struct gl_framebuffer *fb = ctx->ReadBuffer;
558 struct gl_renderbuffer *rb = fb->_ColorReadBuffer;
559
560 if (!rb)
561 return;
562
563 transferOps = get_readpixels_transfer_ops(ctx, rb->Format, format, type,
564 GL_FALSE);
565
566 /* Try the optimized paths first. */
567 if (!transferOps &&
568 read_rgba_pixels_swizzle(ctx, x, y, width, height,
569 format, type, pixels, packing)) {
570 return;
571 }
572
573 slow_read_rgba_pixels(ctx, x, y, width, height,
574 format, type, pixels, packing, transferOps);
575 }
576
577 /**
578 * For a packed depth/stencil buffer being read as depth/stencil, just memcpy the
579 * data (possibly swapping 8/24 vs 24/8 as we go).
580 */
581 static GLboolean
582 fast_read_depth_stencil_pixels(struct gl_context *ctx,
583 GLint x, GLint y,
584 GLsizei width, GLsizei height,
585 GLubyte *dst, int dstStride)
586 {
587 struct gl_framebuffer *fb = ctx->ReadBuffer;
588 struct gl_renderbuffer *rb = fb->Attachment[BUFFER_DEPTH].Renderbuffer;
589 struct gl_renderbuffer *stencilRb = fb->Attachment[BUFFER_STENCIL].Renderbuffer;
590 GLubyte *map;
591 int stride, i;
592
593 if (rb != stencilRb)
594 return GL_FALSE;
595
596 if (rb->Format != MESA_FORMAT_Z24_S8 &&
597 rb->Format != MESA_FORMAT_S8_Z24)
598 return GL_FALSE;
599
600 ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT,
601 &map, &stride);
602 if (!map) {
603 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
604 return GL_TRUE; /* don't bother trying the slow path */
605 }
606
607 for (i = 0; i < height; i++) {
608 _mesa_unpack_uint_24_8_depth_stencil_row(rb->Format, width,
609 map, (GLuint *)dst);
610 map += stride;
611 dst += dstStride;
612 }
613
614 ctx->Driver.UnmapRenderbuffer(ctx, rb);
615
616 return GL_TRUE;
617 }
618
619
620 /**
621 * For non-float-depth and stencil buffers being read as 24/8 depth/stencil,
622 * copy the integer data directly instead of converting depth to float and
623 * re-packing.
624 */
625 static GLboolean
626 fast_read_depth_stencil_pixels_separate(struct gl_context *ctx,
627 GLint x, GLint y,
628 GLsizei width, GLsizei height,
629 uint32_t *dst, int dstStride)
630 {
631 struct gl_framebuffer *fb = ctx->ReadBuffer;
632 struct gl_renderbuffer *depthRb = fb->Attachment[BUFFER_DEPTH].Renderbuffer;
633 struct gl_renderbuffer *stencilRb = fb->Attachment[BUFFER_STENCIL].Renderbuffer;
634 GLubyte *depthMap, *stencilMap, *stencilVals;
635 int depthStride, stencilStride, i, j;
636
637 if (_mesa_get_format_datatype(depthRb->Format) != GL_UNSIGNED_NORMALIZED)
638 return GL_FALSE;
639
640 ctx->Driver.MapRenderbuffer(ctx, depthRb, x, y, width, height,
641 GL_MAP_READ_BIT, &depthMap, &depthStride);
642 if (!depthMap) {
643 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
644 return GL_TRUE; /* don't bother trying the slow path */
645 }
646
647 ctx->Driver.MapRenderbuffer(ctx, stencilRb, x, y, width, height,
648 GL_MAP_READ_BIT, &stencilMap, &stencilStride);
649 if (!stencilMap) {
650 ctx->Driver.UnmapRenderbuffer(ctx, depthRb);
651 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
652 return GL_TRUE; /* don't bother trying the slow path */
653 }
654
655 stencilVals = malloc(width * sizeof(GLubyte));
656
657 if (stencilVals) {
658 for (j = 0; j < height; j++) {
659 _mesa_unpack_uint_z_row(depthRb->Format, width, depthMap, dst);
660 _mesa_unpack_ubyte_stencil_row(stencilRb->Format, width,
661 stencilMap, stencilVals);
662
663 for (i = 0; i < width; i++) {
664 dst[i] = (dst[i] & 0xffffff00) | stencilVals[i];
665 }
666
667 depthMap += depthStride;
668 stencilMap += stencilStride;
669 dst += dstStride / 4;
670 }
671 }
672 else {
673 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
674 }
675
676 free(stencilVals);
677
678 ctx->Driver.UnmapRenderbuffer(ctx, depthRb);
679 ctx->Driver.UnmapRenderbuffer(ctx, stencilRb);
680
681 return GL_TRUE;
682 }
683
684 static void
685 slow_read_depth_stencil_pixels_separate(struct gl_context *ctx,
686 GLint x, GLint y,
687 GLsizei width, GLsizei height,
688 GLenum type,
689 const struct gl_pixelstore_attrib *packing,
690 GLubyte *dst, int dstStride)
691 {
692 struct gl_framebuffer *fb = ctx->ReadBuffer;
693 struct gl_renderbuffer *depthRb = fb->Attachment[BUFFER_DEPTH].Renderbuffer;
694 struct gl_renderbuffer *stencilRb = fb->Attachment[BUFFER_STENCIL].Renderbuffer;
695 GLubyte *depthMap, *stencilMap;
696 int depthStride, stencilStride, j;
697 GLubyte *stencilVals;
698 GLfloat *depthVals;
699
700
701 /* The depth and stencil buffers might be separate, or a single buffer.
702 * If one buffer, only map it once.
703 */
704 ctx->Driver.MapRenderbuffer(ctx, depthRb, x, y, width, height,
705 GL_MAP_READ_BIT, &depthMap, &depthStride);
706 if (!depthMap) {
707 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
708 return;
709 }
710
711 if (stencilRb != depthRb) {
712 ctx->Driver.MapRenderbuffer(ctx, stencilRb, x, y, width, height,
713 GL_MAP_READ_BIT, &stencilMap,
714 &stencilStride);
715 if (!stencilMap) {
716 ctx->Driver.UnmapRenderbuffer(ctx, depthRb);
717 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
718 return;
719 }
720 }
721 else {
722 stencilMap = depthMap;
723 stencilStride = depthStride;
724 }
725
726 stencilVals = malloc(width * sizeof(GLubyte));
727 depthVals = malloc(width * sizeof(GLfloat));
728
729 if (stencilVals && depthVals) {
730 for (j = 0; j < height; j++) {
731 _mesa_unpack_float_z_row(depthRb->Format, width, depthMap, depthVals);
732 _mesa_unpack_ubyte_stencil_row(stencilRb->Format, width,
733 stencilMap, stencilVals);
734
735 _mesa_pack_depth_stencil_span(ctx, width, type, (GLuint *)dst,
736 depthVals, stencilVals, packing);
737
738 depthMap += depthStride;
739 stencilMap += stencilStride;
740 dst += dstStride;
741 }
742 }
743 else {
744 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
745 }
746
747 free(stencilVals);
748 free(depthVals);
749
750 ctx->Driver.UnmapRenderbuffer(ctx, depthRb);
751 if (stencilRb != depthRb) {
752 ctx->Driver.UnmapRenderbuffer(ctx, stencilRb);
753 }
754 }
755
756
757 /**
758 * Read combined depth/stencil values.
759 * We'll have already done error checking to be sure the expected
760 * depth and stencil buffers really exist.
761 */
762 static void
763 read_depth_stencil_pixels(struct gl_context *ctx,
764 GLint x, GLint y,
765 GLsizei width, GLsizei height,
766 GLenum type, GLvoid *pixels,
767 const struct gl_pixelstore_attrib *packing )
768 {
769 const GLboolean scaleOrBias
770 = ctx->Pixel.DepthScale != 1.0 || ctx->Pixel.DepthBias != 0.0;
771 const GLboolean stencilTransfer = ctx->Pixel.IndexShift
772 || ctx->Pixel.IndexOffset || ctx->Pixel.MapStencilFlag;
773 GLubyte *dst;
774 int dstStride;
775
776 dst = (GLubyte *) _mesa_image_address2d(packing, pixels,
777 width, height,
778 GL_DEPTH_STENCIL_EXT,
779 type, 0, 0);
780 dstStride = _mesa_image_row_stride(packing, width,
781 GL_DEPTH_STENCIL_EXT, type);
782
783 /* Fast 24/8 reads. */
784 if (type == GL_UNSIGNED_INT_24_8 &&
785 !scaleOrBias && !stencilTransfer && !packing->SwapBytes) {
786 if (fast_read_depth_stencil_pixels(ctx, x, y, width, height,
787 dst, dstStride))
788 return;
789
790 if (fast_read_depth_stencil_pixels_separate(ctx, x, y, width, height,
791 (uint32_t *)dst, dstStride))
792 return;
793 }
794
795 slow_read_depth_stencil_pixels_separate(ctx, x, y, width, height,
796 type, packing,
797 dst, dstStride);
798 }
799
800
801
802 /**
803 * Software fallback routine for ctx->Driver.ReadPixels().
804 * By time we get here, all error checking will have been done.
805 */
806 void
807 _mesa_readpixels(struct gl_context *ctx,
808 GLint x, GLint y, GLsizei width, GLsizei height,
809 GLenum format, GLenum type,
810 const struct gl_pixelstore_attrib *packing,
811 GLvoid *pixels)
812 {
813 struct gl_pixelstore_attrib clippedPacking = *packing;
814
815 if (ctx->NewState)
816 _mesa_update_state(ctx);
817
818 /* Do all needed clipping here, so that we can forget about it later */
819 if (_mesa_clip_readpixels(ctx, &x, &y, &width, &height, &clippedPacking)) {
820
821 pixels = _mesa_map_pbo_dest(ctx, &clippedPacking, pixels);
822
823 if (pixels) {
824 /* Try memcpy first. */
825 if (readpixels_memcpy(ctx, x, y, width, height, format, type,
826 pixels, packing)) {
827 _mesa_unmap_pbo_dest(ctx, &clippedPacking);
828 return;
829 }
830
831 /* Otherwise take the slow path. */
832 switch (format) {
833 case GL_STENCIL_INDEX:
834 read_stencil_pixels(ctx, x, y, width, height, type, pixels,
835 &clippedPacking);
836 break;
837 case GL_DEPTH_COMPONENT:
838 read_depth_pixels(ctx, x, y, width, height, type, pixels,
839 &clippedPacking);
840 break;
841 case GL_DEPTH_STENCIL_EXT:
842 read_depth_stencil_pixels(ctx, x, y, width, height, type, pixels,
843 &clippedPacking);
844 break;
845 default:
846 /* all other formats should be color formats */
847 read_rgba_pixels(ctx, x, y, width, height, format, type, pixels,
848 &clippedPacking);
849 }
850
851 _mesa_unmap_pbo_dest(ctx, &clippedPacking);
852 }
853 }
854 }
855
856
857 static GLenum
858 read_pixels_es3_error_check(GLenum format, GLenum type,
859 const struct gl_renderbuffer *rb)
860 {
861 const GLenum internalFormat = rb->InternalFormat;
862 const GLenum data_type = _mesa_get_format_datatype(rb->Format);
863 GLboolean is_unsigned_int = GL_FALSE;
864 GLboolean is_signed_int = GL_FALSE;
865
866 if (!_mesa_is_color_format(internalFormat)) {
867 return GL_INVALID_OPERATION;
868 }
869
870 is_unsigned_int = _mesa_is_enum_format_unsigned_int(internalFormat);
871 if (!is_unsigned_int) {
872 is_signed_int = _mesa_is_enum_format_signed_int(internalFormat);
873 }
874
875 switch (format) {
876 case GL_RGBA:
877 if (type == GL_FLOAT && data_type == GL_FLOAT)
878 return GL_NO_ERROR; /* EXT_color_buffer_float */
879 if (type == GL_UNSIGNED_BYTE && data_type == GL_UNSIGNED_NORMALIZED)
880 return GL_NO_ERROR;
881 if (internalFormat == GL_RGB10_A2 &&
882 type == GL_UNSIGNED_INT_2_10_10_10_REV)
883 return GL_NO_ERROR;
884 if (internalFormat == GL_RGB10_A2UI && type == GL_UNSIGNED_BYTE)
885 return GL_NO_ERROR;
886 break;
887 case GL_BGRA:
888 /* GL_EXT_read_format_bgra */
889 if (type == GL_UNSIGNED_BYTE ||
890 type == GL_UNSIGNED_SHORT_4_4_4_4_REV ||
891 type == GL_UNSIGNED_SHORT_1_5_5_5_REV)
892 return GL_NO_ERROR;
893 break;
894 case GL_RGBA_INTEGER:
895 if ((is_signed_int && type == GL_INT) ||
896 (is_unsigned_int && type == GL_UNSIGNED_INT))
897 return GL_NO_ERROR;
898 break;
899 }
900
901 return GL_INVALID_OPERATION;
902 }
903
904
905 void GLAPIENTRY
906 _mesa_ReadnPixelsARB( GLint x, GLint y, GLsizei width, GLsizei height,
907 GLenum format, GLenum type, GLsizei bufSize,
908 GLvoid *pixels )
909 {
910 GLenum err = GL_NO_ERROR;
911 struct gl_renderbuffer *rb;
912
913 GET_CURRENT_CONTEXT(ctx);
914
915 FLUSH_VERTICES(ctx, 0);
916 FLUSH_CURRENT(ctx, 0);
917
918 if (MESA_VERBOSE & VERBOSE_API)
919 _mesa_debug(ctx, "glReadPixels(%d, %d, %s, %s, %p)\n",
920 width, height,
921 _mesa_lookup_enum_by_nr(format),
922 _mesa_lookup_enum_by_nr(type),
923 pixels);
924
925 if (width < 0 || height < 0) {
926 _mesa_error( ctx, GL_INVALID_VALUE,
927 "glReadPixels(width=%d height=%d)", width, height );
928 return;
929 }
930
931 if (ctx->NewState)
932 _mesa_update_state(ctx);
933
934 if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
935 _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
936 "glReadPixels(incomplete framebuffer)" );
937 return;
938 }
939
940 rb = _mesa_get_read_renderbuffer_for_format(ctx, format);
941 if (rb == NULL) {
942 _mesa_error(ctx, GL_INVALID_OPERATION,
943 "glReadPixels(read buffer)");
944 return;
945 }
946
947 /* OpenGL ES 1.x and OpenGL ES 2.0 impose additional restrictions on the
948 * combinations of format and type that can be used.
949 *
950 * Technically, only two combinations are actually allowed:
951 * GL_RGBA/GL_UNSIGNED_BYTE, and some implementation-specific internal
952 * preferred combination. This code doesn't know what that preferred
953 * combination is, and Mesa can handle anything valid. Just work instead.
954 */
955 if (_mesa_is_gles(ctx)) {
956 if (ctx->API == API_OPENGLES2 &&
957 _mesa_is_color_format(format) &&
958 _mesa_get_color_read_format(ctx) == format &&
959 _mesa_get_color_read_type(ctx) == type) {
960 err = GL_NO_ERROR;
961 } else if (ctx->Version < 30) {
962 err = _mesa_es_error_check_format_and_type(format, type, 2);
963 if (err == GL_NO_ERROR) {
964 if (type == GL_FLOAT || type == GL_HALF_FLOAT_OES) {
965 err = GL_INVALID_OPERATION;
966 }
967 }
968 } else {
969 err = read_pixels_es3_error_check(format, type, rb);
970 }
971
972 if (err == GL_NO_ERROR && (format == GL_DEPTH_COMPONENT
973 || format == GL_DEPTH_STENCIL)) {
974 err = GL_INVALID_ENUM;
975 }
976
977 if (err != GL_NO_ERROR) {
978 _mesa_error(ctx, err, "glReadPixels(invalid format %s and/or type %s)",
979 _mesa_lookup_enum_by_nr(format),
980 _mesa_lookup_enum_by_nr(type));
981 return;
982 }
983 }
984
985 err = _mesa_error_check_format_and_type(ctx, format, type);
986 if (err != GL_NO_ERROR) {
987 _mesa_error(ctx, err, "glReadPixels(invalid format %s and/or type %s)",
988 _mesa_lookup_enum_by_nr(format),
989 _mesa_lookup_enum_by_nr(type));
990 return;
991 }
992
993 if (_mesa_is_user_fbo(ctx->ReadBuffer) &&
994 ctx->ReadBuffer->Visual.samples > 0) {
995 _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(multisample FBO)");
996 return;
997 }
998
999 if (!_mesa_source_buffer_exists(ctx, format)) {
1000 _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(no readbuffer)");
1001 return;
1002 }
1003
1004 /* Check that the destination format and source buffer are both
1005 * integer-valued or both non-integer-valued.
1006 */
1007 if (ctx->Extensions.EXT_texture_integer && _mesa_is_color_format(format)) {
1008 const struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorReadBuffer;
1009 const GLboolean srcInteger = _mesa_is_format_integer_color(rb->Format);
1010 const GLboolean dstInteger = _mesa_is_enum_format_integer(format);
1011 if (dstInteger != srcInteger) {
1012 _mesa_error(ctx, GL_INVALID_OPERATION,
1013 "glReadPixels(integer / non-integer format mismatch");
1014 return;
1015 }
1016 }
1017
1018 if (width == 0 || height == 0)
1019 return; /* nothing to do */
1020
1021 if (!_mesa_validate_pbo_access(2, &ctx->Pack, width, height, 1,
1022 format, type, bufSize, pixels)) {
1023 if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
1024 _mesa_error(ctx, GL_INVALID_OPERATION,
1025 "glReadPixels(out of bounds PBO access)");
1026 } else {
1027 _mesa_error(ctx, GL_INVALID_OPERATION,
1028 "glReadnPixelsARB(out of bounds access:"
1029 " bufSize (%d) is too small)", bufSize);
1030 }
1031 return;
1032 }
1033
1034 if (_mesa_is_bufferobj(ctx->Pack.BufferObj) &&
1035 _mesa_bufferobj_mapped(ctx->Pack.BufferObj)) {
1036 /* buffer is mapped - that's an error */
1037 _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(PBO is mapped)");
1038 return;
1039 }
1040
1041 ctx->Driver.ReadPixels(ctx, x, y, width, height,
1042 format, type, &ctx->Pack, pixels);
1043 }
1044
1045 void GLAPIENTRY
1046 _mesa_ReadPixels( GLint x, GLint y, GLsizei width, GLsizei height,
1047 GLenum format, GLenum type, GLvoid *pixels )
1048 {
1049 _mesa_ReadnPixelsARB(x, y, width, height, format, type, INT_MAX, pixels);
1050 }