mesa: remove unused _mesa_error_check_format_type() function
[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
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 static GLboolean
200 fast_read_rgba_pixels_memcpy( struct gl_context *ctx,
201 GLint x, GLint y,
202 GLsizei width, GLsizei height,
203 GLenum format, GLenum type,
204 GLvoid *pixels,
205 const struct gl_pixelstore_attrib *packing,
206 GLbitfield transferOps )
207 {
208 struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorReadBuffer;
209 GLubyte *dst, *map;
210 int dstStride, stride, j, texelBytes;
211
212 if (!_mesa_format_matches_format_and_type(rb->Format, format, type,
213 ctx->Pack.SwapBytes))
214 return GL_FALSE;
215
216 dstStride = _mesa_image_row_stride(packing, width, format, type);
217 dst = (GLubyte *) _mesa_image_address2d(packing, pixels, width, height,
218 format, type, 0, 0);
219
220 ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT,
221 &map, &stride);
222 if (!map) {
223 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
224 return GL_TRUE; /* don't bother trying the slow path */
225 }
226
227 texelBytes = _mesa_get_format_bytes(rb->Format);
228 for (j = 0; j < height; j++) {
229 memcpy(dst, map, width * texelBytes);
230 dst += dstStride;
231 map += stride;
232 }
233
234 ctx->Driver.UnmapRenderbuffer(ctx, rb);
235
236 return GL_TRUE;
237 }
238
239 static void
240 slow_read_rgba_pixels( struct gl_context *ctx,
241 GLint x, GLint y,
242 GLsizei width, GLsizei height,
243 GLenum format, GLenum type,
244 GLvoid *pixels,
245 const struct gl_pixelstore_attrib *packing,
246 GLbitfield transferOps )
247 {
248 struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorReadBuffer;
249 const gl_format rbFormat = _mesa_get_srgb_format_linear(rb->Format);
250 void *rgba;
251 GLubyte *dst, *map;
252 int dstStride, stride, j;
253
254 dstStride = _mesa_image_row_stride(packing, width, format, type);
255 dst = (GLubyte *) _mesa_image_address2d(packing, pixels, width, height,
256 format, type, 0, 0);
257
258 ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT,
259 &map, &stride);
260 if (!map) {
261 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
262 return;
263 }
264
265 rgba = malloc(width * MAX_PIXEL_BYTES);
266 if (!rgba)
267 goto done;
268
269 for (j = 0; j < height; j++) {
270 if (_mesa_is_integer_format(format)) {
271 _mesa_unpack_uint_rgba_row(rbFormat, width, map, (GLuint (*)[4]) rgba);
272 _mesa_pack_rgba_span_int(ctx, width, (GLuint (*)[4]) rgba, format,
273 type, dst);
274 } else {
275 _mesa_unpack_rgba_row(rbFormat, width, map, (GLfloat (*)[4]) rgba);
276 _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba, format,
277 type, dst, packing, transferOps);
278 }
279 dst += dstStride;
280 map += stride;
281 }
282
283 free(rgba);
284
285 done:
286 ctx->Driver.UnmapRenderbuffer(ctx, rb);
287 }
288
289 /*
290 * Read R, G, B, A, RGB, L, or LA pixels.
291 */
292 static void
293 read_rgba_pixels( struct gl_context *ctx,
294 GLint x, GLint y,
295 GLsizei width, GLsizei height,
296 GLenum format, GLenum type, GLvoid *pixels,
297 const struct gl_pixelstore_attrib *packing )
298 {
299 GLbitfield transferOps = ctx->_ImageTransferState;
300 struct gl_framebuffer *fb = ctx->ReadBuffer;
301 struct gl_renderbuffer *rb = fb->_ColorReadBuffer;
302
303 if (!rb)
304 return;
305
306 if ((ctx->Color._ClampReadColor == GL_TRUE || type != GL_FLOAT) &&
307 !_mesa_is_integer_format(format)) {
308 transferOps |= IMAGE_CLAMP_BIT;
309 }
310
311 if (!transferOps) {
312 /* Try the optimized paths first. */
313 if (fast_read_rgba_pixels_memcpy(ctx, x, y, width, height,
314 format, type, pixels, packing,
315 transferOps)) {
316 return;
317 }
318 }
319
320 slow_read_rgba_pixels(ctx, x, y, width, height,
321 format, type, pixels, packing, transferOps);
322 }
323
324 /**
325 * For a packed depth/stencil buffer being read as depth/stencil, just memcpy the
326 * data (possibly swapping 8/24 vs 24/8 as we go).
327 */
328 static GLboolean
329 fast_read_depth_stencil_pixels(struct gl_context *ctx,
330 GLint x, GLint y,
331 GLsizei width, GLsizei height,
332 GLubyte *dst, int dstStride)
333 {
334 struct gl_framebuffer *fb = ctx->ReadBuffer;
335 struct gl_renderbuffer *rb = fb->Attachment[BUFFER_DEPTH].Renderbuffer;
336 struct gl_renderbuffer *stencilRb = fb->Attachment[BUFFER_STENCIL].Renderbuffer;
337 GLubyte *map;
338 int stride, i;
339
340 if (rb != stencilRb)
341 return GL_FALSE;
342
343 if (rb->Format != MESA_FORMAT_Z24_S8 &&
344 rb->Format != MESA_FORMAT_S8_Z24)
345 return GL_FALSE;
346
347 ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT,
348 &map, &stride);
349 if (!map) {
350 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
351 return GL_TRUE; /* don't bother trying the slow path */
352 }
353
354 for (i = 0; i < height; i++) {
355 _mesa_unpack_uint_24_8_depth_stencil_row(rb->Format, width,
356 map, (GLuint *)dst);
357 map += stride;
358 dst += dstStride;
359 }
360
361 ctx->Driver.UnmapRenderbuffer(ctx, rb);
362
363 return GL_TRUE;
364 }
365
366
367 /**
368 * For non-float-depth and stencil buffers being read as 24/8 depth/stencil,
369 * copy the integer data directly instead of converting depth to float and
370 * re-packing.
371 */
372 static GLboolean
373 fast_read_depth_stencil_pixels_separate(struct gl_context *ctx,
374 GLint x, GLint y,
375 GLsizei width, GLsizei height,
376 uint32_t *dst, int dstStride)
377 {
378 struct gl_framebuffer *fb = ctx->ReadBuffer;
379 struct gl_renderbuffer *depthRb = fb->Attachment[BUFFER_DEPTH].Renderbuffer;
380 struct gl_renderbuffer *stencilRb = fb->Attachment[BUFFER_STENCIL].Renderbuffer;
381 GLubyte *depthMap, *stencilMap;
382 int depthStride, stencilStride, i, j;
383
384 if (_mesa_get_format_datatype(depthRb->Format) != GL_UNSIGNED_NORMALIZED)
385 return GL_FALSE;
386
387 ctx->Driver.MapRenderbuffer(ctx, depthRb, x, y, width, height,
388 GL_MAP_READ_BIT, &depthMap, &depthStride);
389 if (!depthMap) {
390 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
391 return GL_TRUE; /* don't bother trying the slow path */
392 }
393
394 ctx->Driver.MapRenderbuffer(ctx, stencilRb, x, y, width, height,
395 GL_MAP_READ_BIT, &stencilMap, &stencilStride);
396 if (!stencilMap) {
397 ctx->Driver.UnmapRenderbuffer(ctx, depthRb);
398 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
399 return GL_TRUE; /* don't bother trying the slow path */
400 }
401
402 for (j = 0; j < height; j++) {
403 GLubyte stencilVals[MAX_WIDTH];
404
405 _mesa_unpack_uint_z_row(depthRb->Format, width, depthMap, dst);
406 _mesa_unpack_ubyte_stencil_row(stencilRb->Format, width,
407 stencilMap, stencilVals);
408
409 for (i = 0; i < width; i++) {
410 dst[i] = (dst[i] & 0xffffff00) | stencilVals[i];
411 }
412
413 depthMap += depthStride;
414 stencilMap += stencilStride;
415 dst += dstStride / 4;
416 }
417
418 ctx->Driver.UnmapRenderbuffer(ctx, depthRb);
419 ctx->Driver.UnmapRenderbuffer(ctx, stencilRb);
420
421 return GL_TRUE;
422 }
423
424 static void
425 slow_read_depth_stencil_pixels_separate(struct gl_context *ctx,
426 GLint x, GLint y,
427 GLsizei width, GLsizei height,
428 GLenum type,
429 const struct gl_pixelstore_attrib *packing,
430 GLubyte *dst, int dstStride)
431 {
432 struct gl_framebuffer *fb = ctx->ReadBuffer;
433 struct gl_renderbuffer *depthRb = fb->Attachment[BUFFER_DEPTH].Renderbuffer;
434 struct gl_renderbuffer *stencilRb = fb->Attachment[BUFFER_STENCIL].Renderbuffer;
435 GLubyte *depthMap, *stencilMap;
436 int depthStride, stencilStride, j;
437
438 /* The depth and stencil buffers might be separate, or a single buffer.
439 * If one buffer, only map it once.
440 */
441 ctx->Driver.MapRenderbuffer(ctx, depthRb, x, y, width, height,
442 GL_MAP_READ_BIT, &depthMap, &depthStride);
443 if (!depthMap) {
444 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
445 return;
446 }
447
448 if (stencilRb != depthRb) {
449 ctx->Driver.MapRenderbuffer(ctx, stencilRb, x, y, width, height,
450 GL_MAP_READ_BIT, &stencilMap,
451 &stencilStride);
452 if (!stencilMap) {
453 ctx->Driver.UnmapRenderbuffer(ctx, depthRb);
454 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
455 return;
456 }
457 }
458 else {
459 stencilMap = depthMap;
460 stencilStride = depthStride;
461 }
462
463 for (j = 0; j < height; j++) {
464 GLubyte stencilVals[MAX_WIDTH];
465 GLfloat depthVals[MAX_WIDTH];
466
467 _mesa_unpack_float_z_row(depthRb->Format, width, depthMap, depthVals);
468 _mesa_unpack_ubyte_stencil_row(stencilRb->Format, width,
469 stencilMap, stencilVals);
470
471 _mesa_pack_depth_stencil_span(ctx, width, type, (GLuint *)dst,
472 depthVals, stencilVals, packing);
473
474 depthMap += depthStride;
475 stencilMap += stencilStride;
476 dst += dstStride;
477 }
478
479 ctx->Driver.UnmapRenderbuffer(ctx, depthRb);
480 if (stencilRb != depthRb) {
481 ctx->Driver.UnmapRenderbuffer(ctx, stencilRb);
482 }
483 }
484
485
486 /**
487 * Read combined depth/stencil values.
488 * We'll have already done error checking to be sure the expected
489 * depth and stencil buffers really exist.
490 */
491 static void
492 read_depth_stencil_pixels(struct gl_context *ctx,
493 GLint x, GLint y,
494 GLsizei width, GLsizei height,
495 GLenum type, GLvoid *pixels,
496 const struct gl_pixelstore_attrib *packing )
497 {
498 const GLboolean scaleOrBias
499 = ctx->Pixel.DepthScale != 1.0 || ctx->Pixel.DepthBias != 0.0;
500 const GLboolean stencilTransfer = ctx->Pixel.IndexShift
501 || ctx->Pixel.IndexOffset || ctx->Pixel.MapStencilFlag;
502 GLubyte *dst;
503 int dstStride;
504
505 dst = (GLubyte *) _mesa_image_address2d(packing, pixels,
506 width, height,
507 GL_DEPTH_STENCIL_EXT,
508 type, 0, 0);
509 dstStride = _mesa_image_row_stride(packing, width,
510 GL_DEPTH_STENCIL_EXT, type);
511
512 /* Fast 24/8 reads. */
513 if (type == GL_UNSIGNED_INT_24_8 &&
514 !scaleOrBias && !stencilTransfer && !packing->SwapBytes) {
515 if (fast_read_depth_stencil_pixels(ctx, x, y, width, height,
516 dst, dstStride))
517 return;
518
519 if (fast_read_depth_stencil_pixels_separate(ctx, x, y, width, height,
520 (uint32_t *)dst, dstStride))
521 return;
522 }
523
524 slow_read_depth_stencil_pixels_separate(ctx, x, y, width, height,
525 type, packing,
526 dst, dstStride);
527 }
528
529
530
531 /**
532 * Software fallback routine for ctx->Driver.ReadPixels().
533 * By time we get here, all error checking will have been done.
534 */
535 void
536 _mesa_readpixels(struct gl_context *ctx,
537 GLint x, GLint y, GLsizei width, GLsizei height,
538 GLenum format, GLenum type,
539 const struct gl_pixelstore_attrib *packing,
540 GLvoid *pixels)
541 {
542 struct gl_pixelstore_attrib clippedPacking = *packing;
543
544 if (ctx->NewState)
545 _mesa_update_state(ctx);
546
547 /* Do all needed clipping here, so that we can forget about it later */
548 if (_mesa_clip_readpixels(ctx, &x, &y, &width, &height, &clippedPacking)) {
549
550 pixels = _mesa_map_pbo_dest(ctx, &clippedPacking, pixels);
551
552 if (pixels) {
553 switch (format) {
554 case GL_STENCIL_INDEX:
555 read_stencil_pixels(ctx, x, y, width, height, type, pixels,
556 &clippedPacking);
557 break;
558 case GL_DEPTH_COMPONENT:
559 read_depth_pixels(ctx, x, y, width, height, type, pixels,
560 &clippedPacking);
561 break;
562 case GL_DEPTH_STENCIL_EXT:
563 read_depth_stencil_pixels(ctx, x, y, width, height, type, pixels,
564 &clippedPacking);
565 break;
566 default:
567 /* all other formats should be color formats */
568 read_rgba_pixels(ctx, x, y, width, height, format, type, pixels,
569 &clippedPacking);
570 }
571
572 _mesa_unmap_pbo_dest(ctx, &clippedPacking);
573 }
574 }
575 }
576
577
578 void GLAPIENTRY
579 _mesa_ReadnPixelsARB( GLint x, GLint y, GLsizei width, GLsizei height,
580 GLenum format, GLenum type, GLsizei bufSize,
581 GLvoid *pixels )
582 {
583 GLenum err;
584
585 GET_CURRENT_CONTEXT(ctx);
586 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
587
588 FLUSH_CURRENT(ctx, 0);
589
590 if (MESA_VERBOSE & VERBOSE_API)
591 _mesa_debug(ctx, "glReadPixels(%d, %d, %s, %s, %p)\n",
592 width, height,
593 _mesa_lookup_enum_by_nr(format),
594 _mesa_lookup_enum_by_nr(type),
595 pixels);
596
597 if (width < 0 || height < 0) {
598 _mesa_error( ctx, GL_INVALID_VALUE,
599 "glReadPixels(width=%d height=%d)", width, height );
600 return;
601 }
602
603 if (ctx->NewState)
604 _mesa_update_state(ctx);
605
606 err = _mesa_error_check_format_and_type(ctx, format, type);
607 if (err != GL_NO_ERROR) {
608 _mesa_error(ctx, err, "glReadPixels(invalid format %s and/or type %s)",
609 _mesa_lookup_enum_by_nr(format),
610 _mesa_lookup_enum_by_nr(type));
611 return;
612 }
613
614 /* Check that the destination format and source buffer are both
615 * integer-valued or both non-integer-valued.
616 */
617 if (ctx->Extensions.EXT_texture_integer && _mesa_is_color_format(format)) {
618 const struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorReadBuffer;
619 const GLboolean srcInteger = _mesa_is_format_integer_color(rb->Format);
620 const GLboolean dstInteger = _mesa_is_integer_format(format);
621 if (dstInteger != srcInteger) {
622 _mesa_error(ctx, GL_INVALID_OPERATION,
623 "glReadPixels(integer / non-integer format mismatch");
624 return;
625 }
626 }
627
628 if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
629 _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
630 "glReadPixels(incomplete framebuffer)" );
631 return;
632 }
633
634 if (ctx->ReadBuffer->Name != 0 && ctx->ReadBuffer->Visual.samples > 0) {
635 _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(multisample FBO)");
636 return;
637 }
638
639 if (!_mesa_source_buffer_exists(ctx, format)) {
640 _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(no readbuffer)");
641 return;
642 }
643
644 if (width == 0 || height == 0)
645 return; /* nothing to do */
646
647 if (!_mesa_validate_pbo_access(2, &ctx->Pack, width, height, 1,
648 format, type, bufSize, pixels)) {
649 if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
650 _mesa_error(ctx, GL_INVALID_OPERATION,
651 "glReadPixels(out of bounds PBO access)");
652 } else {
653 _mesa_error(ctx, GL_INVALID_OPERATION,
654 "glReadnPixelsARB(out of bounds access:"
655 " bufSize (%d) is too small)", bufSize);
656 }
657 return;
658 }
659
660 if (_mesa_is_bufferobj(ctx->Pack.BufferObj) &&
661 _mesa_bufferobj_mapped(ctx->Pack.BufferObj)) {
662 /* buffer is mapped - that's an error */
663 _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(PBO is mapped)");
664 return;
665 }
666
667 ctx->Driver.ReadPixels(ctx, x, y, width, height,
668 format, type, &ctx->Pack, pixels);
669 }
670
671 void GLAPIENTRY
672 _mesa_ReadPixels( GLint x, GLint y, GLsizei width, GLsizei height,
673 GLenum format, GLenum type, GLvoid *pixels )
674 {
675 _mesa_ReadnPixelsARB(x, y, width, height, format, type, INT_MAX, pixels);
676 }