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