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