readpix.c revision 627b435dfe17698a1c69e9a259838fc6f2e6bd4e
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 */
45static GLboolean
46fast_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 */
101static void
102read_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 */
156static void
157read_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
199static GLboolean
200fast_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
239static void
240slow_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
285done:
286   ctx->Driver.UnmapRenderbuffer(ctx, rb);
287}
288
289/*
290 * Read R, G, B, A, RGB, L, or LA pixels.
291 */
292static void
293read_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 */
328static GLboolean
329fast_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 */
372static GLboolean
373fast_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
424static void
425slow_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 */
491static void
492read_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 */
535void
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/**
579 * Do error checking of the format/type parameters to glReadPixels and
580 * glDrawPixels.
581 * \param drawing if GL_TRUE do checking for DrawPixels, else do checking
582 *                for ReadPixels.
583 * \return GL_TRUE if error detected, GL_FALSE if no errors
584 */
585GLboolean
586_mesa_error_check_format_type(struct gl_context *ctx, GLenum format,
587                              GLenum type, GLboolean drawing)
588{
589   const char *readDraw = drawing ? "Draw" : "Read";
590   const GLboolean reading = !drawing;
591   GLenum err;
592
593   /* state validation should have already been done */
594   ASSERT(ctx->NewState == 0x0);
595
596   if (ctx->Extensions.EXT_packed_depth_stencil
597       && type == GL_UNSIGNED_INT_24_8_EXT
598       && format != GL_DEPTH_STENCIL_EXT) {
599      _mesa_error(ctx, GL_INVALID_OPERATION,
600                  "gl%sPixels(format is not GL_DEPTH_STENCIL_EXT)", readDraw);
601      return GL_TRUE;
602   }
603
604   if (ctx->Extensions.ARB_depth_buffer_float
605       && type == GL_FLOAT_32_UNSIGNED_INT_24_8_REV
606       && format != GL_DEPTH_STENCIL_EXT) {
607      _mesa_error(ctx, GL_INVALID_OPERATION,
608                  "gl%sPixels(format is not GL_DEPTH_STENCIL_EXT)", readDraw);
609      return GL_TRUE;
610   }
611
612   /* basic combinations test */
613   err = _mesa_error_check_format_and_type(ctx, format, type);
614   if (err != GL_NO_ERROR) {
615      _mesa_error(ctx, err, "gl%sPixels(format or type)", readDraw);
616      return GL_TRUE;
617   }
618
619   /* additional checks */
620   switch (format) {
621   case GL_RG:
622   case GL_RED:
623   case GL_GREEN:
624   case GL_BLUE:
625   case GL_ALPHA:
626   case GL_LUMINANCE:
627   case GL_LUMINANCE_ALPHA:
628   case GL_RGB:
629   case GL_BGR:
630   case GL_RGBA:
631   case GL_BGRA:
632   case GL_ABGR_EXT:
633   case GL_RED_INTEGER_EXT:
634   case GL_GREEN_INTEGER_EXT:
635   case GL_BLUE_INTEGER_EXT:
636   case GL_ALPHA_INTEGER_EXT:
637   case GL_RGB_INTEGER_EXT:
638   case GL_RGBA_INTEGER_EXT:
639   case GL_BGR_INTEGER_EXT:
640   case GL_BGRA_INTEGER_EXT:
641   case GL_LUMINANCE_INTEGER_EXT:
642   case GL_LUMINANCE_ALPHA_INTEGER_EXT:
643      if (!drawing) {
644         /* reading */
645         if (!_mesa_source_buffer_exists(ctx, GL_COLOR)) {
646            _mesa_error(ctx, GL_INVALID_OPERATION,
647                        "glReadPixels(no color buffer)");
648            return GL_TRUE;
649         }
650      }
651      break;
652   case GL_COLOR_INDEX:
653      if (drawing) {
654         if (ctx->PixelMaps.ItoR.Size == 0 ||
655	     ctx->PixelMaps.ItoG.Size == 0 ||
656	     ctx->PixelMaps.ItoB.Size == 0) {
657            _mesa_error(ctx, GL_INVALID_OPERATION,
658                   "glDrawPixels(drawing color index pixels into RGB buffer)");
659            return GL_TRUE;
660         }
661      }
662      else {
663         /* reading */
664         if (!_mesa_source_buffer_exists(ctx, GL_COLOR)) {
665            _mesa_error(ctx, GL_INVALID_OPERATION,
666                        "glReadPixels(no color buffer)");
667            return GL_TRUE;
668         }
669         /* We no longer support CI-mode color buffers so trying to read
670          * GL_COLOR_INDEX pixels is always an error.
671          */
672         _mesa_error(ctx, GL_INVALID_OPERATION,
673                     "glReadPixels(color buffer is RGB)");
674         return GL_TRUE;
675      }
676      break;
677   case GL_STENCIL_INDEX:
678      if ((drawing && !_mesa_dest_buffer_exists(ctx, format)) ||
679          (reading && !_mesa_source_buffer_exists(ctx, format))) {
680         _mesa_error(ctx, GL_INVALID_OPERATION,
681                     "gl%sPixels(no stencil buffer)", readDraw);
682         return GL_TRUE;
683      }
684      break;
685   case GL_DEPTH_COMPONENT:
686      if ((drawing && !_mesa_dest_buffer_exists(ctx, format))) {
687         _mesa_error(ctx, GL_INVALID_OPERATION,
688                     "gl%sPixels(no depth buffer)", readDraw);
689         return GL_TRUE;
690      }
691      break;
692   case GL_DEPTH_STENCIL_EXT:
693      /* Check validity of the type first. */
694      switch (type) {
695         case GL_UNSIGNED_INT_24_8_EXT:
696            if (!ctx->Extensions.EXT_packed_depth_stencil) {
697               _mesa_error(ctx, GL_INVALID_ENUM, "gl%sPixels(type)", readDraw);
698               return GL_TRUE;
699            }
700            break;
701         case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
702            if (!ctx->Extensions.ARB_depth_buffer_float) {
703               _mesa_error(ctx, GL_INVALID_ENUM, "gl%sPixels(type)", readDraw);
704               return GL_TRUE;
705            }
706            break;
707         default:
708            _mesa_error(ctx, GL_INVALID_ENUM, "gl%sPixels(type)", readDraw);
709            return GL_TRUE;
710      }
711      if ((drawing && !_mesa_dest_buffer_exists(ctx, format)) ||
712          (reading && !_mesa_source_buffer_exists(ctx, format))) {
713         _mesa_error(ctx, GL_INVALID_OPERATION,
714                     "gl%sPixels(no depth or stencil buffer)", readDraw);
715         return GL_TRUE;
716      }
717      break;
718   default:
719      /* this should have been caught in _mesa_error_check_format_type() */
720      _mesa_problem(ctx, "unexpected format in _mesa_%sPixels", readDraw);
721      return GL_TRUE;
722   }
723
724   /* no errors */
725   return GL_FALSE;
726}
727
728
729
730void GLAPIENTRY
731_mesa_ReadnPixelsARB( GLint x, GLint y, GLsizei width, GLsizei height,
732		      GLenum format, GLenum type, GLsizei bufSize,
733                      GLvoid *pixels )
734{
735   GET_CURRENT_CONTEXT(ctx);
736   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
737
738   FLUSH_CURRENT(ctx, 0);
739
740   if (MESA_VERBOSE & VERBOSE_API)
741      _mesa_debug(ctx, "glReadPixels(%d, %d, %s, %s, %p)\n",
742                  width, height,
743                  _mesa_lookup_enum_by_nr(format),
744                  _mesa_lookup_enum_by_nr(type),
745                  pixels);
746
747   if (width < 0 || height < 0) {
748      _mesa_error( ctx, GL_INVALID_VALUE,
749                   "glReadPixels(width=%d height=%d)", width, height );
750      return;
751   }
752
753   if (ctx->NewState)
754      _mesa_update_state(ctx);
755
756   if (_mesa_error_check_format_type(ctx, format, type, GL_FALSE)) {
757      /* found an error */
758      return;
759   }
760
761   /* Check that the destination format and source buffer are both
762    * integer-valued or both non-integer-valued.
763    */
764   if (ctx->Extensions.EXT_texture_integer && _mesa_is_color_format(format)) {
765      const struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorReadBuffer;
766      const GLboolean srcInteger = _mesa_is_format_integer_color(rb->Format);
767      const GLboolean dstInteger = _mesa_is_integer_format(format);
768      if (dstInteger != srcInteger) {
769         _mesa_error(ctx, GL_INVALID_OPERATION,
770                     "glReadPixels(integer / non-integer format mismatch");
771         return;
772      }
773   }
774
775   if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
776      _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
777                  "glReadPixels(incomplete framebuffer)" );
778      return;
779   }
780
781   if (ctx->ReadBuffer->Name != 0 && ctx->ReadBuffer->Visual.samples > 0) {
782      _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(multisample FBO)");
783      return;
784   }
785
786   if (!_mesa_source_buffer_exists(ctx, format)) {
787      _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(no readbuffer)");
788      return;
789   }
790
791   if (width == 0 || height == 0)
792      return; /* nothing to do */
793
794   if (!_mesa_validate_pbo_access(2, &ctx->Pack, width, height, 1,
795                                  format, type, bufSize, pixels)) {
796      if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
797         _mesa_error(ctx, GL_INVALID_OPERATION,
798                     "glReadPixels(out of bounds PBO access)");
799      } else {
800         _mesa_error(ctx, GL_INVALID_OPERATION,
801                     "glReadnPixelsARB(out of bounds access:"
802                     " bufSize (%d) is too small)", bufSize);
803      }
804      return;
805   }
806
807   if (_mesa_is_bufferobj(ctx->Pack.BufferObj) &&
808       _mesa_bufferobj_mapped(ctx->Pack.BufferObj)) {
809      /* buffer is mapped - that's an error */
810      _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(PBO is mapped)");
811      return;
812   }
813
814   ctx->Driver.ReadPixels(ctx, x, y, width, height,
815			  format, type, &ctx->Pack, pixels);
816}
817
818void GLAPIENTRY
819_mesa_ReadPixels( GLint x, GLint y, GLsizei width, GLsizei height,
820		  GLenum format, GLenum type, GLvoid *pixels )
821{
822   _mesa_ReadnPixelsARB(x, y, width, height, format, type, INT_MAX, pixels);
823}
824