1848b8605Smrg/*
2848b8605Smrg * Mesa 3-D graphics library
3848b8605Smrg *
4848b8605Smrg * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved.
5848b8605Smrg *
6848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a
7848b8605Smrg * copy of this software and associated documentation files (the "Software"),
8848b8605Smrg * to deal in the Software without restriction, including without limitation
9848b8605Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the
11848b8605Smrg * Software is furnished to do so, subject to the following conditions:
12848b8605Smrg *
13848b8605Smrg * The above copyright notice and this permission notice shall be included
14848b8605Smrg * in all copies or substantial portions of the Software.
15848b8605Smrg *
16848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19848b8605Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20848b8605Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21848b8605Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22848b8605Smrg * OTHER DEALINGS IN THE SOFTWARE.
23848b8605Smrg */
24848b8605Smrg
25848b8605Smrg#include "glheader.h"
26848b8605Smrg#include "imports.h"
27848b8605Smrg#include "blend.h"
28848b8605Smrg#include "bufferobj.h"
29848b8605Smrg#include "context.h"
30848b8605Smrg#include "enums.h"
31848b8605Smrg#include "readpix.h"
32848b8605Smrg#include "framebuffer.h"
33848b8605Smrg#include "formats.h"
34848b8605Smrg#include "format_unpack.h"
35848b8605Smrg#include "image.h"
36848b8605Smrg#include "mtypes.h"
37848b8605Smrg#include "pack.h"
38848b8605Smrg#include "pbo.h"
39848b8605Smrg#include "state.h"
40848b8605Smrg#include "glformats.h"
41848b8605Smrg#include "fbobject.h"
42b8e80941Smrg#include "format_utils.h"
43b8e80941Smrg#include "pixeltransfer.h"
44848b8605Smrg
45848b8605Smrg
46848b8605Smrg/**
47848b8605Smrg * Return true if the conversion L=R+G+B is needed.
48848b8605Smrg */
49b8e80941SmrgGLboolean
50b8e80941Smrg_mesa_need_rgb_to_luminance_conversion(GLenum srcBaseFormat,
51b8e80941Smrg                                       GLenum dstBaseFormat)
52848b8605Smrg{
53b8e80941Smrg   return (srcBaseFormat == GL_RG ||
54b8e80941Smrg           srcBaseFormat == GL_RGB ||
55b8e80941Smrg           srcBaseFormat == GL_RGBA) &&
56b8e80941Smrg          (dstBaseFormat == GL_LUMINANCE ||
57b8e80941Smrg           dstBaseFormat == GL_LUMINANCE_ALPHA);
58848b8605Smrg}
59848b8605Smrg
60b8e80941Smrg/**
61b8e80941Smrg * Return true if the conversion L,I to RGB conversion is needed.
62b8e80941Smrg */
63b8e80941SmrgGLboolean
64b8e80941Smrg_mesa_need_luminance_to_rgb_conversion(GLenum srcBaseFormat,
65b8e80941Smrg                                       GLenum dstBaseFormat)
66b8e80941Smrg{
67b8e80941Smrg   return (srcBaseFormat == GL_LUMINANCE ||
68b8e80941Smrg           srcBaseFormat == GL_LUMINANCE_ALPHA ||
69b8e80941Smrg           srcBaseFormat == GL_INTENSITY) &&
70b8e80941Smrg          (dstBaseFormat == GL_GREEN ||
71b8e80941Smrg           dstBaseFormat == GL_BLUE ||
72b8e80941Smrg           dstBaseFormat == GL_RG ||
73b8e80941Smrg           dstBaseFormat == GL_RGB ||
74b8e80941Smrg           dstBaseFormat == GL_BGR ||
75b8e80941Smrg           dstBaseFormat == GL_RGBA ||
76b8e80941Smrg           dstBaseFormat == GL_BGRA);
77b8e80941Smrg}
78848b8605Smrg
79848b8605Smrg/**
80848b8605Smrg * Return transfer op flags for this ReadPixels operation.
81848b8605Smrg */
82b8e80941SmrgGLbitfield
83b8e80941Smrg_mesa_get_readpixels_transfer_ops(const struct gl_context *ctx,
84b8e80941Smrg                                  mesa_format texFormat,
85b8e80941Smrg                                  GLenum format, GLenum type,
86b8e80941Smrg                                  GLboolean uses_blit)
87848b8605Smrg{
88848b8605Smrg   GLbitfield transferOps = ctx->_ImageTransferState;
89b8e80941Smrg   GLenum srcBaseFormat = _mesa_get_format_base_format(texFormat);
90b8e80941Smrg   GLenum dstBaseFormat = _mesa_unpack_format_to_base_format(format);
91848b8605Smrg
92848b8605Smrg   if (format == GL_DEPTH_COMPONENT ||
93848b8605Smrg       format == GL_DEPTH_STENCIL ||
94848b8605Smrg       format == GL_STENCIL_INDEX) {
95848b8605Smrg      return 0;
96848b8605Smrg   }
97848b8605Smrg
98848b8605Smrg   /* Pixel transfer ops (scale, bias, table lookup) do not apply
99848b8605Smrg    * to integer formats.
100848b8605Smrg    */
101848b8605Smrg   if (_mesa_is_enum_format_integer(format)) {
102848b8605Smrg      return 0;
103848b8605Smrg   }
104848b8605Smrg
105848b8605Smrg   if (uses_blit) {
106848b8605Smrg      /* For blit-based ReadPixels packing, the clamping is done automatically
107848b8605Smrg       * unless the type is float. */
108b8e80941Smrg      if (_mesa_get_clamp_read_color(ctx, ctx->ReadBuffer) &&
109b8e80941Smrg          (type == GL_FLOAT || type == GL_HALF_FLOAT ||
110b8e80941Smrg           type == GL_UNSIGNED_INT_10F_11F_11F_REV)) {
111848b8605Smrg         transferOps |= IMAGE_CLAMP_BIT;
112848b8605Smrg      }
113848b8605Smrg   }
114848b8605Smrg   else {
115848b8605Smrg      /* For CPU-based ReadPixels packing, the clamping must always be done
116848b8605Smrg       * for non-float types, */
117b8e80941Smrg      if (_mesa_get_clamp_read_color(ctx, ctx->ReadBuffer) ||
118b8e80941Smrg          (type != GL_FLOAT && type != GL_HALF_FLOAT &&
119b8e80941Smrg           type != GL_UNSIGNED_INT_10F_11F_11F_REV)) {
120848b8605Smrg         transferOps |= IMAGE_CLAMP_BIT;
121848b8605Smrg      }
122848b8605Smrg   }
123848b8605Smrg
124848b8605Smrg   /* If the format is unsigned normalized, we can ignore clamping
125848b8605Smrg    * because the values are already in the range [0,1] so it won't
126848b8605Smrg    * have any effect anyway.
127848b8605Smrg    */
128848b8605Smrg   if (_mesa_get_format_datatype(texFormat) == GL_UNSIGNED_NORMALIZED &&
129b8e80941Smrg       !_mesa_need_rgb_to_luminance_conversion(srcBaseFormat, dstBaseFormat)) {
130848b8605Smrg      transferOps &= ~IMAGE_CLAMP_BIT;
131848b8605Smrg   }
132848b8605Smrg
133848b8605Smrg   return transferOps;
134848b8605Smrg}
135848b8605Smrg
136848b8605Smrg
137848b8605Smrg/**
138848b8605Smrg * Return true if memcpy cannot be used for ReadPixels.
139848b8605Smrg *
140848b8605Smrg * If uses_blit is true, the function returns true if a simple 3D engine blit
141848b8605Smrg * cannot be used for ReadPixels packing.
142848b8605Smrg *
143848b8605Smrg * NOTE: This doesn't take swizzling and format conversions between
144848b8605Smrg *       the readbuffer and the pixel pack buffer into account.
145848b8605Smrg */
146848b8605SmrgGLboolean
147848b8605Smrg_mesa_readpixels_needs_slow_path(const struct gl_context *ctx, GLenum format,
148848b8605Smrg                                 GLenum type, GLboolean uses_blit)
149848b8605Smrg{
150848b8605Smrg   struct gl_renderbuffer *rb =
151848b8605Smrg         _mesa_get_read_renderbuffer_for_format(ctx, format);
152b8e80941Smrg   GLenum dstBaseFormat = _mesa_unpack_format_to_base_format(format);
153848b8605Smrg
154b8e80941Smrg   assert(rb);
155848b8605Smrg
156848b8605Smrg   /* There are different rules depending on the base format. */
157848b8605Smrg   switch (format) {
158848b8605Smrg   case GL_DEPTH_STENCIL:
159848b8605Smrg      return !_mesa_has_depthstencil_combined(ctx->ReadBuffer) ||
160848b8605Smrg             ctx->Pixel.DepthScale != 1.0f || ctx->Pixel.DepthBias != 0.0f ||
161848b8605Smrg             ctx->Pixel.IndexShift || ctx->Pixel.IndexOffset ||
162848b8605Smrg             ctx->Pixel.MapStencilFlag;
163848b8605Smrg
164848b8605Smrg   case GL_DEPTH_COMPONENT:
165848b8605Smrg      return ctx->Pixel.DepthScale != 1.0f || ctx->Pixel.DepthBias != 0.0f;
166848b8605Smrg
167848b8605Smrg   case GL_STENCIL_INDEX:
168848b8605Smrg      return ctx->Pixel.IndexShift || ctx->Pixel.IndexOffset ||
169848b8605Smrg             ctx->Pixel.MapStencilFlag;
170848b8605Smrg
171848b8605Smrg   default:
172848b8605Smrg      /* Color formats. */
173b8e80941Smrg      if (_mesa_need_rgb_to_luminance_conversion(rb->_BaseFormat,
174b8e80941Smrg                                                 dstBaseFormat)) {
175848b8605Smrg         return GL_TRUE;
176848b8605Smrg      }
177848b8605Smrg
178848b8605Smrg      /* And finally, see if there are any transfer ops. */
179b8e80941Smrg      return _mesa_get_readpixels_transfer_ops(ctx, rb->Format, format, type,
180b8e80941Smrg                                               uses_blit) != 0;
181848b8605Smrg   }
182848b8605Smrg   return GL_FALSE;
183848b8605Smrg}
184848b8605Smrg
185848b8605Smrg
186848b8605Smrgstatic GLboolean
187848b8605Smrgreadpixels_can_use_memcpy(const struct gl_context *ctx, GLenum format, GLenum type,
188848b8605Smrg                          const struct gl_pixelstore_attrib *packing)
189848b8605Smrg{
190848b8605Smrg   struct gl_renderbuffer *rb =
191848b8605Smrg         _mesa_get_read_renderbuffer_for_format(ctx, format);
192848b8605Smrg
193b8e80941Smrg   assert(rb);
194848b8605Smrg
195848b8605Smrg   if (_mesa_readpixels_needs_slow_path(ctx, format, type, GL_FALSE)) {
196848b8605Smrg      return GL_FALSE;
197848b8605Smrg   }
198848b8605Smrg
199848b8605Smrg   /* The base internal format and the base Mesa format must match. */
200848b8605Smrg   if (rb->_BaseFormat != _mesa_get_format_base_format(rb->Format)) {
201848b8605Smrg      return GL_FALSE;
202848b8605Smrg   }
203848b8605Smrg
204848b8605Smrg   /* The Mesa format must match the input format and type. */
205848b8605Smrg   if (!_mesa_format_matches_format_and_type(rb->Format, format, type,
206b8e80941Smrg                                             packing->SwapBytes, NULL)) {
207848b8605Smrg      return GL_FALSE;
208848b8605Smrg   }
209848b8605Smrg
210848b8605Smrg   return GL_TRUE;
211848b8605Smrg}
212848b8605Smrg
213848b8605Smrg
214848b8605Smrgstatic GLboolean
215848b8605Smrgreadpixels_memcpy(struct gl_context *ctx,
216848b8605Smrg                  GLint x, GLint y,
217848b8605Smrg                  GLsizei width, GLsizei height,
218848b8605Smrg                  GLenum format, GLenum type,
219848b8605Smrg                  GLvoid *pixels,
220848b8605Smrg                  const struct gl_pixelstore_attrib *packing)
221848b8605Smrg{
222848b8605Smrg   struct gl_renderbuffer *rb =
223848b8605Smrg         _mesa_get_read_renderbuffer_for_format(ctx, format);
224848b8605Smrg   GLubyte *dst, *map;
225b8e80941Smrg   int dstStride, stride, j, texelBytes, bytesPerRow;
226848b8605Smrg
227848b8605Smrg   /* Fail if memcpy cannot be used. */
228848b8605Smrg   if (!readpixels_can_use_memcpy(ctx, format, type, packing)) {
229848b8605Smrg      return GL_FALSE;
230848b8605Smrg   }
231848b8605Smrg
232848b8605Smrg   dstStride = _mesa_image_row_stride(packing, width, format, type);
233848b8605Smrg   dst = (GLubyte *) _mesa_image_address2d(packing, pixels, width, height,
234848b8605Smrg					   format, type, 0, 0);
235848b8605Smrg
236848b8605Smrg   ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT,
237b8e80941Smrg			       &map, &stride, ctx->ReadBuffer->FlipY);
238848b8605Smrg   if (!map) {
239848b8605Smrg      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
240848b8605Smrg      return GL_TRUE;  /* don't bother trying the slow path */
241848b8605Smrg   }
242848b8605Smrg
243848b8605Smrg   texelBytes = _mesa_get_format_bytes(rb->Format);
244b8e80941Smrg   bytesPerRow = texelBytes * width;
245848b8605Smrg
246848b8605Smrg   /* memcpy*/
247b8e80941Smrg   if (dstStride == stride && dstStride == bytesPerRow) {
248b8e80941Smrg      memcpy(dst, map, bytesPerRow * height);
249b8e80941Smrg   } else {
250b8e80941Smrg      for (j = 0; j < height; j++) {
251b8e80941Smrg         memcpy(dst, map, bytesPerRow);
252b8e80941Smrg         dst += dstStride;
253b8e80941Smrg         map += stride;
254b8e80941Smrg      }
255848b8605Smrg   }
256848b8605Smrg
257848b8605Smrg   ctx->Driver.UnmapRenderbuffer(ctx, rb);
258848b8605Smrg   return GL_TRUE;
259848b8605Smrg}
260848b8605Smrg
261848b8605Smrg
262848b8605Smrg/**
263848b8605Smrg * Optimized path for conversion of depth values to GL_DEPTH_COMPONENT,
264848b8605Smrg * GL_UNSIGNED_INT.
265848b8605Smrg */
266848b8605Smrgstatic GLboolean
267848b8605Smrgread_uint_depth_pixels( struct gl_context *ctx,
268848b8605Smrg			GLint x, GLint y,
269848b8605Smrg			GLsizei width, GLsizei height,
270848b8605Smrg			GLenum type, GLvoid *pixels,
271848b8605Smrg			const struct gl_pixelstore_attrib *packing )
272848b8605Smrg{
273848b8605Smrg   struct gl_framebuffer *fb = ctx->ReadBuffer;
274848b8605Smrg   struct gl_renderbuffer *rb = fb->Attachment[BUFFER_DEPTH].Renderbuffer;
275848b8605Smrg   GLubyte *map, *dst;
276848b8605Smrg   int stride, dstStride, j;
277848b8605Smrg
278b8e80941Smrg   if (ctx->Pixel.DepthScale != 1.0F || ctx->Pixel.DepthBias != 0.0F)
279848b8605Smrg      return GL_FALSE;
280848b8605Smrg
281848b8605Smrg   if (packing->SwapBytes)
282848b8605Smrg      return GL_FALSE;
283848b8605Smrg
284848b8605Smrg   if (_mesa_get_format_datatype(rb->Format) != GL_UNSIGNED_NORMALIZED)
285848b8605Smrg      return GL_FALSE;
286848b8605Smrg
287848b8605Smrg   ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT,
288b8e80941Smrg			       &map, &stride, fb->FlipY);
289848b8605Smrg
290848b8605Smrg   if (!map) {
291848b8605Smrg      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
292848b8605Smrg      return GL_TRUE;  /* don't bother trying the slow path */
293848b8605Smrg   }
294848b8605Smrg
295848b8605Smrg   dstStride = _mesa_image_row_stride(packing, width, GL_DEPTH_COMPONENT, type);
296848b8605Smrg   dst = (GLubyte *) _mesa_image_address2d(packing, pixels, width, height,
297848b8605Smrg					   GL_DEPTH_COMPONENT, type, 0, 0);
298848b8605Smrg
299848b8605Smrg   for (j = 0; j < height; j++) {
300848b8605Smrg      _mesa_unpack_uint_z_row(rb->Format, width, map, (GLuint *)dst);
301848b8605Smrg
302848b8605Smrg      map += stride;
303848b8605Smrg      dst += dstStride;
304848b8605Smrg   }
305848b8605Smrg   ctx->Driver.UnmapRenderbuffer(ctx, rb);
306848b8605Smrg
307848b8605Smrg   return GL_TRUE;
308848b8605Smrg}
309848b8605Smrg
310848b8605Smrg/**
311848b8605Smrg * Read pixels for format=GL_DEPTH_COMPONENT.
312848b8605Smrg */
313848b8605Smrgstatic void
314848b8605Smrgread_depth_pixels( struct gl_context *ctx,
315848b8605Smrg                   GLint x, GLint y,
316848b8605Smrg                   GLsizei width, GLsizei height,
317848b8605Smrg                   GLenum type, GLvoid *pixels,
318848b8605Smrg                   const struct gl_pixelstore_attrib *packing )
319848b8605Smrg{
320848b8605Smrg   struct gl_framebuffer *fb = ctx->ReadBuffer;
321848b8605Smrg   struct gl_renderbuffer *rb = fb->Attachment[BUFFER_DEPTH].Renderbuffer;
322848b8605Smrg   GLint j;
323848b8605Smrg   GLubyte *dst, *map;
324848b8605Smrg   int dstStride, stride;
325848b8605Smrg   GLfloat *depthValues;
326848b8605Smrg
327848b8605Smrg   if (!rb)
328848b8605Smrg      return;
329848b8605Smrg
330848b8605Smrg   /* clipping should have been done already */
331b8e80941Smrg   assert(x >= 0);
332b8e80941Smrg   assert(y >= 0);
333b8e80941Smrg   assert(x + width <= (GLint) rb->Width);
334b8e80941Smrg   assert(y + height <= (GLint) rb->Height);
335848b8605Smrg
336848b8605Smrg   if (type == GL_UNSIGNED_INT &&
337848b8605Smrg       read_uint_depth_pixels(ctx, x, y, width, height, type, pixels, packing)) {
338848b8605Smrg      return;
339848b8605Smrg   }
340848b8605Smrg
341848b8605Smrg   dstStride = _mesa_image_row_stride(packing, width, GL_DEPTH_COMPONENT, type);
342848b8605Smrg   dst = (GLubyte *) _mesa_image_address2d(packing, pixels, width, height,
343848b8605Smrg					   GL_DEPTH_COMPONENT, type, 0, 0);
344848b8605Smrg
345848b8605Smrg   ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT,
346b8e80941Smrg			       &map, &stride, fb->FlipY);
347848b8605Smrg   if (!map) {
348848b8605Smrg      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
349848b8605Smrg      return;
350848b8605Smrg   }
351848b8605Smrg
352848b8605Smrg   depthValues = malloc(width * sizeof(GLfloat));
353848b8605Smrg
354848b8605Smrg   if (depthValues) {
355848b8605Smrg      /* General case (slower) */
356848b8605Smrg      for (j = 0; j < height; j++, y++) {
357848b8605Smrg         _mesa_unpack_float_z_row(rb->Format, width, map, depthValues);
358848b8605Smrg         _mesa_pack_depth_span(ctx, width, dst, type, depthValues, packing);
359848b8605Smrg
360848b8605Smrg         dst += dstStride;
361848b8605Smrg         map += stride;
362848b8605Smrg      }
363848b8605Smrg   }
364848b8605Smrg   else {
365848b8605Smrg      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
366848b8605Smrg   }
367848b8605Smrg
368848b8605Smrg   free(depthValues);
369848b8605Smrg
370848b8605Smrg   ctx->Driver.UnmapRenderbuffer(ctx, rb);
371848b8605Smrg}
372848b8605Smrg
373848b8605Smrg
374848b8605Smrg/**
375848b8605Smrg * Read pixels for format=GL_STENCIL_INDEX.
376848b8605Smrg */
377848b8605Smrgstatic void
378848b8605Smrgread_stencil_pixels( struct gl_context *ctx,
379848b8605Smrg                     GLint x, GLint y,
380848b8605Smrg                     GLsizei width, GLsizei height,
381848b8605Smrg                     GLenum type, GLvoid *pixels,
382848b8605Smrg                     const struct gl_pixelstore_attrib *packing )
383848b8605Smrg{
384848b8605Smrg   struct gl_framebuffer *fb = ctx->ReadBuffer;
385848b8605Smrg   struct gl_renderbuffer *rb = fb->Attachment[BUFFER_STENCIL].Renderbuffer;
386848b8605Smrg   GLint j;
387848b8605Smrg   GLubyte *map, *stencil;
388848b8605Smrg   GLint stride;
389848b8605Smrg
390848b8605Smrg   if (!rb)
391848b8605Smrg      return;
392848b8605Smrg
393848b8605Smrg   ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT,
394b8e80941Smrg			       &map, &stride, fb->FlipY);
395848b8605Smrg   if (!map) {
396848b8605Smrg      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
397848b8605Smrg      return;
398848b8605Smrg   }
399848b8605Smrg
400848b8605Smrg   stencil = malloc(width * sizeof(GLubyte));
401848b8605Smrg
402848b8605Smrg   if (stencil) {
403848b8605Smrg      /* process image row by row */
404848b8605Smrg      for (j = 0; j < height; j++) {
405848b8605Smrg         GLvoid *dest;
406848b8605Smrg
407848b8605Smrg         _mesa_unpack_ubyte_stencil_row(rb->Format, width, map, stencil);
408848b8605Smrg         dest = _mesa_image_address2d(packing, pixels, width, height,
409848b8605Smrg                                      GL_STENCIL_INDEX, type, j, 0);
410848b8605Smrg
411848b8605Smrg         _mesa_pack_stencil_span(ctx, width, type, dest, stencil, packing);
412848b8605Smrg
413848b8605Smrg         map += stride;
414848b8605Smrg      }
415848b8605Smrg   }
416848b8605Smrg   else {
417848b8605Smrg      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
418848b8605Smrg   }
419848b8605Smrg
420848b8605Smrg   free(stencil);
421848b8605Smrg
422848b8605Smrg   ctx->Driver.UnmapRenderbuffer(ctx, rb);
423848b8605Smrg}
424848b8605Smrg
425b8e80941Smrg/*
426b8e80941Smrg * Read R, G, B, A, RGB, L, or LA pixels.
427848b8605Smrg */
428b8e80941Smrgstatic void
429b8e80941Smrgread_rgba_pixels( struct gl_context *ctx,
430b8e80941Smrg                  GLint x, GLint y,
431b8e80941Smrg                  GLsizei width, GLsizei height,
432b8e80941Smrg                  GLenum format, GLenum type, GLvoid *pixels,
433b8e80941Smrg                  const struct gl_pixelstore_attrib *packing )
434848b8605Smrg{
435b8e80941Smrg   GLbitfield transferOps;
436b8e80941Smrg   bool dst_is_integer, convert_rgb_to_lum, needs_rebase;
437b8e80941Smrg   int dst_stride, src_stride, rb_stride;
438b8e80941Smrg   uint32_t dst_format, src_format;
439848b8605Smrg   GLubyte *dst, *map;
440b8e80941Smrg   mesa_format rb_format;
441b8e80941Smrg   bool needs_rgba;
442b8e80941Smrg   void *rgba, *src;
443b8e80941Smrg   bool src_is_uint = false;
444b8e80941Smrg   uint8_t rebase_swizzle[4];
445b8e80941Smrg   struct gl_framebuffer *fb = ctx->ReadBuffer;
446b8e80941Smrg   struct gl_renderbuffer *rb = fb->_ColorReadBuffer;
447b8e80941Smrg   GLenum dstBaseFormat = _mesa_unpack_format_to_base_format(format);
448848b8605Smrg
449b8e80941Smrg   if (!rb)
450b8e80941Smrg      return;
451b8e80941Smrg
452b8e80941Smrg   transferOps = _mesa_get_readpixels_transfer_ops(ctx, rb->Format, format,
453b8e80941Smrg                                                   type, GL_FALSE);
454b8e80941Smrg   /* Describe the dst format */
455b8e80941Smrg   dst_is_integer = _mesa_is_enum_format_integer(format);
456b8e80941Smrg   dst_stride = _mesa_image_row_stride(packing, width, format, type);
457b8e80941Smrg   dst_format = _mesa_format_from_format_and_type(format, type);
458b8e80941Smrg   convert_rgb_to_lum =
459b8e80941Smrg      _mesa_need_rgb_to_luminance_conversion(rb->_BaseFormat, dstBaseFormat);
460848b8605Smrg   dst = (GLubyte *) _mesa_image_address2d(packing, pixels, width, height,
461b8e80941Smrg                                           format, type, 0, 0);
462848b8605Smrg
463b8e80941Smrg   /* Map the source render buffer */
464848b8605Smrg   ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT,
465b8e80941Smrg                               &map, &rb_stride, fb->FlipY);
466848b8605Smrg   if (!map) {
467848b8605Smrg      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
468b8e80941Smrg      return;
469848b8605Smrg   }
470b8e80941Smrg   rb_format = _mesa_get_srgb_format_linear(rb->Format);
471848b8605Smrg
472b8e80941Smrg   /*
473b8e80941Smrg    * Depending on the base formats involved in the conversion we might need to
474b8e80941Smrg    * rebase some values, so for these formats we compute a rebase swizzle.
475b8e80941Smrg    */
476b8e80941Smrg   if (rb->_BaseFormat == GL_LUMINANCE || rb->_BaseFormat == GL_INTENSITY) {
477b8e80941Smrg      needs_rebase = true;
478b8e80941Smrg      rebase_swizzle[0] = MESA_FORMAT_SWIZZLE_X;
479b8e80941Smrg      rebase_swizzle[1] = MESA_FORMAT_SWIZZLE_ZERO;
480b8e80941Smrg      rebase_swizzle[2] = MESA_FORMAT_SWIZZLE_ZERO;
481b8e80941Smrg      rebase_swizzle[3] = MESA_FORMAT_SWIZZLE_ONE;
482b8e80941Smrg   } else if (rb->_BaseFormat == GL_LUMINANCE_ALPHA) {
483b8e80941Smrg      needs_rebase = true;
484b8e80941Smrg      rebase_swizzle[0] = MESA_FORMAT_SWIZZLE_X;
485b8e80941Smrg      rebase_swizzle[1] = MESA_FORMAT_SWIZZLE_ZERO;
486b8e80941Smrg      rebase_swizzle[2] = MESA_FORMAT_SWIZZLE_ZERO;
487b8e80941Smrg      rebase_swizzle[3] = MESA_FORMAT_SWIZZLE_W;
488b8e80941Smrg   } else if (_mesa_get_format_base_format(rb_format) != rb->_BaseFormat) {
489b8e80941Smrg      needs_rebase =
490b8e80941Smrg         _mesa_compute_rgba2base2rgba_component_mapping(rb->_BaseFormat,
491b8e80941Smrg                                                        rebase_swizzle);
492b8e80941Smrg   } else {
493b8e80941Smrg      needs_rebase = false;
494848b8605Smrg   }
495848b8605Smrg
496b8e80941Smrg   /* Since _mesa_format_convert does not handle transferOps we need to handle
497b8e80941Smrg    * them before we call the function. This requires to convert to RGBA float
498b8e80941Smrg    * first so we can call _mesa_apply_rgba_transfer_ops. If the dst format is
499b8e80941Smrg    * integer transferOps do not apply.
500b8e80941Smrg    *
501b8e80941Smrg    * Converting to luminance also requires converting to RGBA first, so we can
502b8e80941Smrg    * then compute luminance values as L=R+G+B. Notice that this is different
503b8e80941Smrg    * from GetTexImage, where we compute L=R.
504b8e80941Smrg    */
505b8e80941Smrg   assert(!transferOps || (transferOps && !dst_is_integer));
506848b8605Smrg
507b8e80941Smrg   needs_rgba = transferOps || convert_rgb_to_lum;
508b8e80941Smrg   rgba = NULL;
509b8e80941Smrg   if (needs_rgba) {
510b8e80941Smrg      uint32_t rgba_format;
511b8e80941Smrg      int rgba_stride;
512b8e80941Smrg      bool need_convert;
513848b8605Smrg
514b8e80941Smrg      /* Convert to RGBA float or int/uint depending on the type of the src */
515848b8605Smrg      if (dst_is_integer) {
516b8e80941Smrg         src_is_uint = _mesa_is_format_unsigned(rb_format);
517b8e80941Smrg         if (src_is_uint) {
518b8e80941Smrg            rgba_format = RGBA32_UINT;
519b8e80941Smrg            rgba_stride = width * 4 * sizeof(GLuint);
520848b8605Smrg         } else {
521b8e80941Smrg            rgba_format = RGBA32_INT;
522b8e80941Smrg            rgba_stride = width * 4 * sizeof(GLint);
523848b8605Smrg         }
524848b8605Smrg      } else {
525b8e80941Smrg         rgba_format = RGBA32_FLOAT;
526b8e80941Smrg         rgba_stride = width * 4 * sizeof(GLfloat);
527848b8605Smrg      }
528848b8605Smrg
529b8e80941Smrg      /* If we are lucky and the dst format matches the RGBA format we need to
530b8e80941Smrg       * convert to, then we can convert directly into the dst buffer and avoid
531b8e80941Smrg       * the final conversion/copy from the rgba buffer to the dst buffer.
532b8e80941Smrg       */
533b8e80941Smrg      if (dst_format == rgba_format &&
534b8e80941Smrg          dst_stride == rgba_stride) {
535b8e80941Smrg         need_convert = false;
536b8e80941Smrg         rgba = dst;
537b8e80941Smrg      } else {
538b8e80941Smrg         need_convert = true;
539b8e80941Smrg         rgba = malloc(height * rgba_stride);
540b8e80941Smrg         if (!rgba) {
541b8e80941Smrg            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
542b8e80941Smrg            goto done_unmap;
543b8e80941Smrg         }
544b8e80941Smrg      }
545848b8605Smrg
546b8e80941Smrg      /* Convert to RGBA now */
547b8e80941Smrg      _mesa_format_convert(rgba, rgba_format, rgba_stride,
548b8e80941Smrg                           map, rb_format, rb_stride,
549b8e80941Smrg                           width, height,
550b8e80941Smrg                           needs_rebase ? rebase_swizzle : NULL);
551b8e80941Smrg
552b8e80941Smrg      /* Handle transfer ops if necessary */
553b8e80941Smrg      if (transferOps)
554b8e80941Smrg         _mesa_apply_rgba_transfer_ops(ctx, transferOps, width * height, rgba);
555b8e80941Smrg
556b8e80941Smrg      /* If we had to rebase, we have already taken care of that */
557b8e80941Smrg      needs_rebase = false;
558b8e80941Smrg
559b8e80941Smrg      /* If we were lucky and our RGBA conversion matches the dst format, then
560b8e80941Smrg       * we are done.
561b8e80941Smrg       */
562b8e80941Smrg      if (!need_convert)
563b8e80941Smrg         goto done_swap;
564b8e80941Smrg
565b8e80941Smrg      /* Otherwise, we need to convert from RGBA to dst next */
566b8e80941Smrg      src = rgba;
567b8e80941Smrg      src_format = rgba_format;
568b8e80941Smrg      src_stride = rgba_stride;
569b8e80941Smrg   } else {
570b8e80941Smrg      /* No RGBA conversion needed, convert directly to dst */
571b8e80941Smrg      src = map;
572b8e80941Smrg      src_format = rb_format;
573b8e80941Smrg      src_stride = rb_stride;
574b8e80941Smrg   }
575848b8605Smrg
576b8e80941Smrg   /* Do the conversion.
577b8e80941Smrg    *
578b8e80941Smrg    * If the dst format is Luminance, we need to do the conversion by computing
579b8e80941Smrg    * L=R+G+B values.
580b8e80941Smrg    */
581b8e80941Smrg   if (!convert_rgb_to_lum) {
582b8e80941Smrg      _mesa_format_convert(dst, dst_format, dst_stride,
583b8e80941Smrg                           src, src_format, src_stride,
584b8e80941Smrg                           width, height,
585b8e80941Smrg                           needs_rebase ? rebase_swizzle : NULL);
586b8e80941Smrg   } else if (!dst_is_integer) {
587b8e80941Smrg      /* Compute float Luminance values from RGBA float */
588b8e80941Smrg      int luminance_stride, luminance_bytes;
589b8e80941Smrg      void *luminance;
590b8e80941Smrg      uint32_t luminance_format;
591b8e80941Smrg
592b8e80941Smrg      luminance_stride = width * sizeof(GLfloat);
593b8e80941Smrg      if (format == GL_LUMINANCE_ALPHA)
594b8e80941Smrg         luminance_stride *= 2;
595b8e80941Smrg      luminance_bytes = height * luminance_stride;
596b8e80941Smrg      luminance = malloc(luminance_bytes);
597b8e80941Smrg      if (!luminance) {
598b8e80941Smrg         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
599b8e80941Smrg         free(rgba);
600b8e80941Smrg         goto done_unmap;
601b8e80941Smrg      }
602b8e80941Smrg      _mesa_pack_luminance_from_rgba_float(width * height, src,
603b8e80941Smrg                                           luminance, format, transferOps);
604b8e80941Smrg
605b8e80941Smrg      /* Convert from Luminance float to dst (this will hadle type conversion
606b8e80941Smrg       * from float to the type of dst if necessary)
607b8e80941Smrg       */
608b8e80941Smrg      luminance_format = _mesa_format_from_format_and_type(format, GL_FLOAT);
609b8e80941Smrg      _mesa_format_convert(dst, dst_format, dst_stride,
610b8e80941Smrg                           luminance, luminance_format, luminance_stride,
611b8e80941Smrg                           width, height, NULL);
612b8e80941Smrg      free(luminance);
613b8e80941Smrg   } else {
614b8e80941Smrg      _mesa_pack_luminance_from_rgba_integer(width * height, src, !src_is_uint,
615b8e80941Smrg                                             dst, format, type);
616b8e80941Smrg   }
617848b8605Smrg
618b8e80941Smrg   free(rgba);
619848b8605Smrg
620b8e80941Smrgdone_swap:
621b8e80941Smrg   /* Handle byte swapping if required */
622b8e80941Smrg   if (packing->SwapBytes) {
623b8e80941Smrg      _mesa_swap_bytes_2d_image(format, type, packing,
624b8e80941Smrg                                width, height, dst, dst);
625848b8605Smrg   }
626848b8605Smrg
627b8e80941Smrgdone_unmap:
628b8e80941Smrg   ctx->Driver.UnmapRenderbuffer(ctx, rb);
629848b8605Smrg}
630848b8605Smrg
631848b8605Smrg/**
632848b8605Smrg * For a packed depth/stencil buffer being read as depth/stencil, just memcpy the
633848b8605Smrg * data (possibly swapping 8/24 vs 24/8 as we go).
634848b8605Smrg */
635848b8605Smrgstatic GLboolean
636848b8605Smrgfast_read_depth_stencil_pixels(struct gl_context *ctx,
637848b8605Smrg			       GLint x, GLint y,
638848b8605Smrg			       GLsizei width, GLsizei height,
639848b8605Smrg			       GLubyte *dst, int dstStride)
640848b8605Smrg{
641848b8605Smrg   struct gl_framebuffer *fb = ctx->ReadBuffer;
642848b8605Smrg   struct gl_renderbuffer *rb = fb->Attachment[BUFFER_DEPTH].Renderbuffer;
643848b8605Smrg   struct gl_renderbuffer *stencilRb = fb->Attachment[BUFFER_STENCIL].Renderbuffer;
644848b8605Smrg   GLubyte *map;
645848b8605Smrg   int stride, i;
646848b8605Smrg
647848b8605Smrg   if (rb != stencilRb)
648848b8605Smrg      return GL_FALSE;
649848b8605Smrg
650848b8605Smrg   if (rb->Format != MESA_FORMAT_S8_UINT_Z24_UNORM &&
651848b8605Smrg       rb->Format != MESA_FORMAT_Z24_UNORM_S8_UINT)
652848b8605Smrg      return GL_FALSE;
653848b8605Smrg
654848b8605Smrg   ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT,
655b8e80941Smrg			       &map, &stride, fb->FlipY);
656848b8605Smrg   if (!map) {
657848b8605Smrg      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
658848b8605Smrg      return GL_TRUE;  /* don't bother trying the slow path */
659848b8605Smrg   }
660848b8605Smrg
661848b8605Smrg   for (i = 0; i < height; i++) {
662848b8605Smrg      _mesa_unpack_uint_24_8_depth_stencil_row(rb->Format, width,
663848b8605Smrg					       map, (GLuint *)dst);
664848b8605Smrg      map += stride;
665848b8605Smrg      dst += dstStride;
666848b8605Smrg   }
667848b8605Smrg
668848b8605Smrg   ctx->Driver.UnmapRenderbuffer(ctx, rb);
669848b8605Smrg
670848b8605Smrg   return GL_TRUE;
671848b8605Smrg}
672848b8605Smrg
673848b8605Smrg
674848b8605Smrg/**
675848b8605Smrg * For non-float-depth and stencil buffers being read as 24/8 depth/stencil,
676848b8605Smrg * copy the integer data directly instead of converting depth to float and
677848b8605Smrg * re-packing.
678848b8605Smrg */
679848b8605Smrgstatic GLboolean
680848b8605Smrgfast_read_depth_stencil_pixels_separate(struct gl_context *ctx,
681848b8605Smrg					GLint x, GLint y,
682848b8605Smrg					GLsizei width, GLsizei height,
683848b8605Smrg					uint32_t *dst, int dstStride)
684848b8605Smrg{
685848b8605Smrg   struct gl_framebuffer *fb = ctx->ReadBuffer;
686848b8605Smrg   struct gl_renderbuffer *depthRb = fb->Attachment[BUFFER_DEPTH].Renderbuffer;
687848b8605Smrg   struct gl_renderbuffer *stencilRb = fb->Attachment[BUFFER_STENCIL].Renderbuffer;
688848b8605Smrg   GLubyte *depthMap, *stencilMap, *stencilVals;
689848b8605Smrg   int depthStride, stencilStride, i, j;
690848b8605Smrg
691848b8605Smrg   if (_mesa_get_format_datatype(depthRb->Format) != GL_UNSIGNED_NORMALIZED)
692848b8605Smrg      return GL_FALSE;
693848b8605Smrg
694848b8605Smrg   ctx->Driver.MapRenderbuffer(ctx, depthRb, x, y, width, height,
695b8e80941Smrg			       GL_MAP_READ_BIT, &depthMap, &depthStride, fb->FlipY);
696848b8605Smrg   if (!depthMap) {
697848b8605Smrg      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
698848b8605Smrg      return GL_TRUE;  /* don't bother trying the slow path */
699848b8605Smrg   }
700848b8605Smrg
701848b8605Smrg   ctx->Driver.MapRenderbuffer(ctx, stencilRb, x, y, width, height,
702b8e80941Smrg			       GL_MAP_READ_BIT, &stencilMap, &stencilStride, fb->FlipY);
703848b8605Smrg   if (!stencilMap) {
704848b8605Smrg      ctx->Driver.UnmapRenderbuffer(ctx, depthRb);
705848b8605Smrg      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
706848b8605Smrg      return GL_TRUE;  /* don't bother trying the slow path */
707848b8605Smrg   }
708848b8605Smrg
709848b8605Smrg   stencilVals = malloc(width * sizeof(GLubyte));
710848b8605Smrg
711848b8605Smrg   if (stencilVals) {
712848b8605Smrg      for (j = 0; j < height; j++) {
713848b8605Smrg         _mesa_unpack_uint_z_row(depthRb->Format, width, depthMap, dst);
714848b8605Smrg         _mesa_unpack_ubyte_stencil_row(stencilRb->Format, width,
715848b8605Smrg                                        stencilMap, stencilVals);
716848b8605Smrg
717848b8605Smrg         for (i = 0; i < width; i++) {
718848b8605Smrg            dst[i] = (dst[i] & 0xffffff00) | stencilVals[i];
719848b8605Smrg         }
720848b8605Smrg
721848b8605Smrg         depthMap += depthStride;
722848b8605Smrg         stencilMap += stencilStride;
723848b8605Smrg         dst += dstStride / 4;
724848b8605Smrg      }
725848b8605Smrg   }
726848b8605Smrg   else {
727848b8605Smrg      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
728848b8605Smrg   }
729848b8605Smrg
730848b8605Smrg   free(stencilVals);
731848b8605Smrg
732848b8605Smrg   ctx->Driver.UnmapRenderbuffer(ctx, depthRb);
733848b8605Smrg   ctx->Driver.UnmapRenderbuffer(ctx, stencilRb);
734848b8605Smrg
735848b8605Smrg   return GL_TRUE;
736848b8605Smrg}
737848b8605Smrg
738848b8605Smrgstatic void
739848b8605Smrgslow_read_depth_stencil_pixels_separate(struct gl_context *ctx,
740848b8605Smrg					GLint x, GLint y,
741848b8605Smrg					GLsizei width, GLsizei height,
742848b8605Smrg					GLenum type,
743848b8605Smrg					const struct gl_pixelstore_attrib *packing,
744848b8605Smrg					GLubyte *dst, int dstStride)
745848b8605Smrg{
746848b8605Smrg   struct gl_framebuffer *fb = ctx->ReadBuffer;
747848b8605Smrg   struct gl_renderbuffer *depthRb = fb->Attachment[BUFFER_DEPTH].Renderbuffer;
748848b8605Smrg   struct gl_renderbuffer *stencilRb = fb->Attachment[BUFFER_STENCIL].Renderbuffer;
749848b8605Smrg   GLubyte *depthMap, *stencilMap;
750848b8605Smrg   int depthStride, stencilStride, j;
751848b8605Smrg   GLubyte *stencilVals;
752848b8605Smrg   GLfloat *depthVals;
753848b8605Smrg
754848b8605Smrg
755848b8605Smrg   /* The depth and stencil buffers might be separate, or a single buffer.
756848b8605Smrg    * If one buffer, only map it once.
757848b8605Smrg    */
758848b8605Smrg   ctx->Driver.MapRenderbuffer(ctx, depthRb, x, y, width, height,
759b8e80941Smrg			       GL_MAP_READ_BIT, &depthMap, &depthStride, fb->FlipY);
760848b8605Smrg   if (!depthMap) {
761848b8605Smrg      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
762848b8605Smrg      return;
763848b8605Smrg   }
764848b8605Smrg
765848b8605Smrg   if (stencilRb != depthRb) {
766848b8605Smrg      ctx->Driver.MapRenderbuffer(ctx, stencilRb, x, y, width, height,
767848b8605Smrg                                  GL_MAP_READ_BIT, &stencilMap,
768b8e80941Smrg                                  &stencilStride, fb->FlipY);
769848b8605Smrg      if (!stencilMap) {
770848b8605Smrg         ctx->Driver.UnmapRenderbuffer(ctx, depthRb);
771848b8605Smrg         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
772848b8605Smrg         return;
773848b8605Smrg      }
774848b8605Smrg   }
775848b8605Smrg   else {
776848b8605Smrg      stencilMap = depthMap;
777848b8605Smrg      stencilStride = depthStride;
778848b8605Smrg   }
779848b8605Smrg
780848b8605Smrg   stencilVals = malloc(width * sizeof(GLubyte));
781848b8605Smrg   depthVals = malloc(width * sizeof(GLfloat));
782848b8605Smrg
783848b8605Smrg   if (stencilVals && depthVals) {
784848b8605Smrg      for (j = 0; j < height; j++) {
785848b8605Smrg         _mesa_unpack_float_z_row(depthRb->Format, width, depthMap, depthVals);
786848b8605Smrg         _mesa_unpack_ubyte_stencil_row(stencilRb->Format, width,
787848b8605Smrg                                        stencilMap, stencilVals);
788848b8605Smrg
789848b8605Smrg         _mesa_pack_depth_stencil_span(ctx, width, type, (GLuint *)dst,
790848b8605Smrg                                       depthVals, stencilVals, packing);
791848b8605Smrg
792848b8605Smrg         depthMap += depthStride;
793848b8605Smrg         stencilMap += stencilStride;
794848b8605Smrg         dst += dstStride;
795848b8605Smrg      }
796848b8605Smrg   }
797848b8605Smrg   else {
798848b8605Smrg      _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
799848b8605Smrg   }
800848b8605Smrg
801848b8605Smrg   free(stencilVals);
802848b8605Smrg   free(depthVals);
803848b8605Smrg
804848b8605Smrg   ctx->Driver.UnmapRenderbuffer(ctx, depthRb);
805848b8605Smrg   if (stencilRb != depthRb) {
806848b8605Smrg      ctx->Driver.UnmapRenderbuffer(ctx, stencilRb);
807848b8605Smrg   }
808848b8605Smrg}
809848b8605Smrg
810848b8605Smrg
811848b8605Smrg/**
812848b8605Smrg * Read combined depth/stencil values.
813848b8605Smrg * We'll have already done error checking to be sure the expected
814848b8605Smrg * depth and stencil buffers really exist.
815848b8605Smrg */
816848b8605Smrgstatic void
817848b8605Smrgread_depth_stencil_pixels(struct gl_context *ctx,
818848b8605Smrg                          GLint x, GLint y,
819848b8605Smrg                          GLsizei width, GLsizei height,
820848b8605Smrg                          GLenum type, GLvoid *pixels,
821848b8605Smrg                          const struct gl_pixelstore_attrib *packing )
822848b8605Smrg{
823848b8605Smrg   const GLboolean scaleOrBias
824b8e80941Smrg      = ctx->Pixel.DepthScale != 1.0F || ctx->Pixel.DepthBias != 0.0F;
825848b8605Smrg   const GLboolean stencilTransfer = ctx->Pixel.IndexShift
826848b8605Smrg      || ctx->Pixel.IndexOffset || ctx->Pixel.MapStencilFlag;
827848b8605Smrg   GLubyte *dst;
828848b8605Smrg   int dstStride;
829848b8605Smrg
830848b8605Smrg   dst = (GLubyte *) _mesa_image_address2d(packing, pixels,
831848b8605Smrg					   width, height,
832848b8605Smrg					   GL_DEPTH_STENCIL_EXT,
833848b8605Smrg					   type, 0, 0);
834848b8605Smrg   dstStride = _mesa_image_row_stride(packing, width,
835848b8605Smrg				      GL_DEPTH_STENCIL_EXT, type);
836848b8605Smrg
837848b8605Smrg   /* Fast 24/8 reads. */
838848b8605Smrg   if (type == GL_UNSIGNED_INT_24_8 &&
839848b8605Smrg       !scaleOrBias && !stencilTransfer && !packing->SwapBytes) {
840848b8605Smrg      if (fast_read_depth_stencil_pixels(ctx, x, y, width, height,
841848b8605Smrg					 dst, dstStride))
842848b8605Smrg	 return;
843848b8605Smrg
844848b8605Smrg      if (fast_read_depth_stencil_pixels_separate(ctx, x, y, width, height,
845848b8605Smrg						  (uint32_t *)dst, dstStride))
846848b8605Smrg	 return;
847848b8605Smrg   }
848848b8605Smrg
849848b8605Smrg   slow_read_depth_stencil_pixels_separate(ctx, x, y, width, height,
850848b8605Smrg					   type, packing,
851848b8605Smrg					   dst, dstStride);
852848b8605Smrg}
853848b8605Smrg
854848b8605Smrg
855848b8605Smrg
856848b8605Smrg/**
857848b8605Smrg * Software fallback routine for ctx->Driver.ReadPixels().
858848b8605Smrg * By time we get here, all error checking will have been done.
859848b8605Smrg */
860848b8605Smrgvoid
861848b8605Smrg_mesa_readpixels(struct gl_context *ctx,
862848b8605Smrg                 GLint x, GLint y, GLsizei width, GLsizei height,
863848b8605Smrg                 GLenum format, GLenum type,
864848b8605Smrg                 const struct gl_pixelstore_attrib *packing,
865848b8605Smrg                 GLvoid *pixels)
866848b8605Smrg{
867848b8605Smrg   if (ctx->NewState)
868848b8605Smrg      _mesa_update_state(ctx);
869848b8605Smrg
870b8e80941Smrg   pixels = _mesa_map_pbo_dest(ctx, packing, pixels);
871848b8605Smrg
872b8e80941Smrg   if (pixels) {
873b8e80941Smrg      /* Try memcpy first. */
874b8e80941Smrg      if (readpixels_memcpy(ctx, x, y, width, height, format, type,
875b8e80941Smrg                            pixels, packing)) {
876b8e80941Smrg         _mesa_unmap_pbo_dest(ctx, packing);
877b8e80941Smrg         return;
878b8e80941Smrg      }
879848b8605Smrg
880b8e80941Smrg      /* Otherwise take the slow path. */
881b8e80941Smrg      switch (format) {
882b8e80941Smrg      case GL_STENCIL_INDEX:
883b8e80941Smrg         read_stencil_pixels(ctx, x, y, width, height, type, pixels,
884b8e80941Smrg                             packing);
885b8e80941Smrg         break;
886b8e80941Smrg      case GL_DEPTH_COMPONENT:
887b8e80941Smrg         read_depth_pixels(ctx, x, y, width, height, type, pixels,
888b8e80941Smrg                           packing);
889b8e80941Smrg         break;
890b8e80941Smrg      case GL_DEPTH_STENCIL_EXT:
891b8e80941Smrg         read_depth_stencil_pixels(ctx, x, y, width, height, type, pixels,
892b8e80941Smrg                                   packing);
893b8e80941Smrg         break;
894b8e80941Smrg      default:
895b8e80941Smrg         /* all other formats should be color formats */
896b8e80941Smrg         read_rgba_pixels(ctx, x, y, width, height, format, type, pixels,
897b8e80941Smrg                          packing);
898848b8605Smrg      }
899b8e80941Smrg
900b8e80941Smrg      _mesa_unmap_pbo_dest(ctx, packing);
901848b8605Smrg   }
902848b8605Smrg}
903848b8605Smrg
904848b8605Smrg
905848b8605Smrgstatic GLenum
906b8e80941Smrgread_pixels_es3_error_check(struct gl_context *ctx, GLenum format, GLenum type,
907848b8605Smrg                            const struct gl_renderbuffer *rb)
908848b8605Smrg{
909848b8605Smrg   const GLenum internalFormat = rb->InternalFormat;
910848b8605Smrg   const GLenum data_type = _mesa_get_format_datatype(rb->Format);
911848b8605Smrg   GLboolean is_unsigned_int = GL_FALSE;
912848b8605Smrg   GLboolean is_signed_int = GL_FALSE;
913b8e80941Smrg   GLboolean is_float_depth = (internalFormat == GL_DEPTH_COMPONENT32F) ||
914b8e80941Smrg         (internalFormat == GL_DEPTH32F_STENCIL8);
915848b8605Smrg
916848b8605Smrg   is_unsigned_int = _mesa_is_enum_format_unsigned_int(internalFormat);
917848b8605Smrg   if (!is_unsigned_int) {
918848b8605Smrg      is_signed_int = _mesa_is_enum_format_signed_int(internalFormat);
919848b8605Smrg   }
920848b8605Smrg
921848b8605Smrg   switch (format) {
922848b8605Smrg   case GL_RGBA:
923848b8605Smrg      if (type == GL_FLOAT && data_type == GL_FLOAT)
924848b8605Smrg         return GL_NO_ERROR; /* EXT_color_buffer_float */
925848b8605Smrg      if (type == GL_UNSIGNED_BYTE && data_type == GL_UNSIGNED_NORMALIZED)
926848b8605Smrg         return GL_NO_ERROR;
927848b8605Smrg      if (internalFormat == GL_RGB10_A2 &&
928848b8605Smrg          type == GL_UNSIGNED_INT_2_10_10_10_REV)
929848b8605Smrg         return GL_NO_ERROR;
930848b8605Smrg      if (internalFormat == GL_RGB10_A2UI && type == GL_UNSIGNED_BYTE)
931848b8605Smrg         return GL_NO_ERROR;
932b8e80941Smrg      if (type == GL_UNSIGNED_SHORT) {
933b8e80941Smrg         switch (internalFormat) {
934b8e80941Smrg         case GL_R16:
935b8e80941Smrg         case GL_RG16:
936b8e80941Smrg         case GL_RGB16:
937b8e80941Smrg         case GL_RGBA16:
938b8e80941Smrg            if (_mesa_has_EXT_texture_norm16(ctx))
939b8e80941Smrg               return GL_NO_ERROR;
940b8e80941Smrg         }
941b8e80941Smrg      }
942b8e80941Smrg      if (type == GL_SHORT) {
943b8e80941Smrg         switch (internalFormat) {
944b8e80941Smrg         case GL_R16_SNORM:
945b8e80941Smrg         case GL_RG16_SNORM:
946b8e80941Smrg         case GL_RGBA16_SNORM:
947b8e80941Smrg            if (_mesa_has_EXT_texture_norm16(ctx) &&
948b8e80941Smrg                _mesa_has_EXT_render_snorm(ctx))
949b8e80941Smrg               return GL_NO_ERROR;
950b8e80941Smrg         }
951b8e80941Smrg      }
952b8e80941Smrg      if (type == GL_BYTE) {
953b8e80941Smrg         switch (internalFormat) {
954b8e80941Smrg         case GL_R8_SNORM:
955b8e80941Smrg         case GL_RG8_SNORM:
956b8e80941Smrg         case GL_RGBA8_SNORM:
957b8e80941Smrg            if (_mesa_has_EXT_render_snorm(ctx))
958b8e80941Smrg               return GL_NO_ERROR;
959b8e80941Smrg         }
960b8e80941Smrg      }
961b8e80941Smrg      if (type == GL_UNSIGNED_BYTE) {
962b8e80941Smrg         switch (internalFormat) {
963b8e80941Smrg         case GL_R8_SNORM:
964b8e80941Smrg         case GL_RG8_SNORM:
965b8e80941Smrg         case GL_RGBA8_SNORM:
966b8e80941Smrg            if (_mesa_has_EXT_render_snorm(ctx))
967b8e80941Smrg               return GL_NO_ERROR;
968b8e80941Smrg         }
969b8e80941Smrg      }
970848b8605Smrg      break;
971848b8605Smrg   case GL_BGRA:
972848b8605Smrg      /* GL_EXT_read_format_bgra */
973848b8605Smrg      if (type == GL_UNSIGNED_BYTE ||
974848b8605Smrg          type == GL_UNSIGNED_SHORT_4_4_4_4_REV ||
975848b8605Smrg          type == GL_UNSIGNED_SHORT_1_5_5_5_REV)
976848b8605Smrg         return GL_NO_ERROR;
977848b8605Smrg      break;
978848b8605Smrg   case GL_RGBA_INTEGER:
979848b8605Smrg      if ((is_signed_int && type == GL_INT) ||
980848b8605Smrg          (is_unsigned_int && type == GL_UNSIGNED_INT))
981848b8605Smrg         return GL_NO_ERROR;
982848b8605Smrg      break;
983b8e80941Smrg   case GL_DEPTH_STENCIL:
984b8e80941Smrg      switch (type) {
985b8e80941Smrg      case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
986b8e80941Smrg         if (is_float_depth)
987b8e80941Smrg            return GL_NO_ERROR;
988b8e80941Smrg         break;
989b8e80941Smrg      case GL_UNSIGNED_INT_24_8:
990b8e80941Smrg         if (!is_float_depth)
991b8e80941Smrg            return GL_NO_ERROR;
992b8e80941Smrg         break;
993b8e80941Smrg      default:
994b8e80941Smrg         return GL_INVALID_ENUM;
995b8e80941Smrg      }
996b8e80941Smrg      break;
997b8e80941Smrg   case GL_DEPTH_COMPONENT:
998b8e80941Smrg      switch (type) {
999b8e80941Smrg      case GL_FLOAT:
1000b8e80941Smrg         if (is_float_depth)
1001b8e80941Smrg            return GL_NO_ERROR;
1002b8e80941Smrg         break;
1003b8e80941Smrg      case GL_UNSIGNED_SHORT:
1004b8e80941Smrg      case GL_UNSIGNED_INT:
1005b8e80941Smrg      case GL_UNSIGNED_INT_24_8:
1006b8e80941Smrg         if (!is_float_depth)
1007b8e80941Smrg            return GL_NO_ERROR;
1008b8e80941Smrg         break;
1009b8e80941Smrg      default:
1010b8e80941Smrg         return GL_INVALID_ENUM;
1011b8e80941Smrg      }
1012b8e80941Smrg      break;
1013b8e80941Smrg   case GL_STENCIL_INDEX:
1014b8e80941Smrg      switch (type) {
1015b8e80941Smrg      case GL_UNSIGNED_BYTE:
1016b8e80941Smrg         return GL_NO_ERROR;
1017b8e80941Smrg      default:
1018b8e80941Smrg         return GL_INVALID_ENUM;
1019b8e80941Smrg      }
1020b8e80941Smrg      break;
1021848b8605Smrg   }
1022848b8605Smrg
1023848b8605Smrg   return GL_INVALID_OPERATION;
1024848b8605Smrg}
1025848b8605Smrg
1026848b8605Smrg
1027b8e80941Smrgstatic ALWAYS_INLINE void
1028b8e80941Smrgread_pixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format,
1029b8e80941Smrg            GLenum type, GLsizei bufSize, GLvoid *pixels, bool no_error)
1030848b8605Smrg{
1031848b8605Smrg   GLenum err = GL_NO_ERROR;
1032848b8605Smrg   struct gl_renderbuffer *rb;
1033b8e80941Smrg   struct gl_pixelstore_attrib clippedPacking;
1034848b8605Smrg
1035848b8605Smrg   GET_CURRENT_CONTEXT(ctx);
1036848b8605Smrg
1037848b8605Smrg   FLUSH_VERTICES(ctx, 0);
1038848b8605Smrg   FLUSH_CURRENT(ctx, 0);
1039848b8605Smrg
1040848b8605Smrg   if (MESA_VERBOSE & VERBOSE_API)
1041848b8605Smrg      _mesa_debug(ctx, "glReadPixels(%d, %d, %s, %s, %p)\n",
1042848b8605Smrg                  width, height,
1043b8e80941Smrg                  _mesa_enum_to_string(format),
1044b8e80941Smrg                  _mesa_enum_to_string(type),
1045848b8605Smrg                  pixels);
1046848b8605Smrg
1047b8e80941Smrg   if (!no_error && (width < 0 || height < 0)) {
1048848b8605Smrg      _mesa_error( ctx, GL_INVALID_VALUE,
1049848b8605Smrg                   "glReadPixels(width=%d height=%d)", width, height );
1050848b8605Smrg      return;
1051848b8605Smrg   }
1052848b8605Smrg
1053848b8605Smrg   if (ctx->NewState)
1054848b8605Smrg      _mesa_update_state(ctx);
1055848b8605Smrg
1056b8e80941Smrg   if (!no_error && ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
1057848b8605Smrg      _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
1058848b8605Smrg                  "glReadPixels(incomplete framebuffer)" );
1059848b8605Smrg      return;
1060848b8605Smrg   }
1061848b8605Smrg
1062848b8605Smrg   rb = _mesa_get_read_renderbuffer_for_format(ctx, format);
1063b8e80941Smrg   if (!no_error) {
1064b8e80941Smrg      if (rb == NULL) {
1065b8e80941Smrg         _mesa_error(ctx, GL_INVALID_OPERATION,
1066b8e80941Smrg                     "glReadPixels(read buffer)");
1067b8e80941Smrg         return;
1068b8e80941Smrg      }
1069848b8605Smrg
1070b8e80941Smrg      /* OpenGL ES 1.x and OpenGL ES 2.0 impose additional restrictions on the
1071b8e80941Smrg       * combinations of format and type that can be used.
1072b8e80941Smrg       *
1073b8e80941Smrg       * Technically, only two combinations are actually allowed:
1074b8e80941Smrg       * GL_RGBA/GL_UNSIGNED_BYTE, and some implementation-specific internal
1075b8e80941Smrg       * preferred combination.  This code doesn't know what that preferred
1076b8e80941Smrg       * combination is, and Mesa can handle anything valid.  Just work instead.
1077b8e80941Smrg       */
1078b8e80941Smrg      if (_mesa_is_gles(ctx)) {
1079b8e80941Smrg         if (ctx->API == API_OPENGLES2 &&
1080b8e80941Smrg             _mesa_is_color_format(format) &&
1081b8e80941Smrg             _mesa_get_color_read_format(ctx, NULL, "glReadPixels") == format &&
1082b8e80941Smrg             _mesa_get_color_read_type(ctx, NULL, "glReadPixels") == type) {
1083b8e80941Smrg            err = GL_NO_ERROR;
1084b8e80941Smrg         } else if (ctx->Version < 30) {
1085b8e80941Smrg            err = _mesa_es_error_check_format_and_type(ctx, format, type, 2);
1086b8e80941Smrg            if (err == GL_NO_ERROR) {
1087b8e80941Smrg               if (type == GL_FLOAT || type == GL_HALF_FLOAT_OES) {
1088b8e80941Smrg                  err = GL_INVALID_OPERATION;
1089b8e80941Smrg               }
1090848b8605Smrg            }
1091b8e80941Smrg         } else {
1092b8e80941Smrg            err = read_pixels_es3_error_check(ctx, format, type, rb);
1093848b8605Smrg         }
1094848b8605Smrg
1095b8e80941Smrg         if (err != GL_NO_ERROR) {
1096b8e80941Smrg            _mesa_error(ctx, err, "glReadPixels(invalid format %s and/or type %s)",
1097b8e80941Smrg                        _mesa_enum_to_string(format),
1098b8e80941Smrg                        _mesa_enum_to_string(type));
1099b8e80941Smrg            return;
1100b8e80941Smrg         }
1101848b8605Smrg      }
1102848b8605Smrg
1103b8e80941Smrg      err = _mesa_error_check_format_and_type(ctx, format, type);
1104848b8605Smrg      if (err != GL_NO_ERROR) {
1105848b8605Smrg         _mesa_error(ctx, err, "glReadPixels(invalid format %s and/or type %s)",
1106b8e80941Smrg                     _mesa_enum_to_string(format),
1107b8e80941Smrg                     _mesa_enum_to_string(type));
1108848b8605Smrg         return;
1109848b8605Smrg      }
1110848b8605Smrg
1111b8e80941Smrg      if (_mesa_is_user_fbo(ctx->ReadBuffer) &&
1112b8e80941Smrg          ctx->ReadBuffer->Visual.samples > 0) {
1113b8e80941Smrg         _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(multisample FBO)");
1114b8e80941Smrg         return;
1115b8e80941Smrg      }
1116848b8605Smrg
1117b8e80941Smrg      if (!_mesa_source_buffer_exists(ctx, format)) {
1118b8e80941Smrg         _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(no readbuffer)");
1119848b8605Smrg         return;
1120848b8605Smrg      }
1121b8e80941Smrg
1122b8e80941Smrg      /* Check that the destination format and source buffer are both
1123b8e80941Smrg       * integer-valued or both non-integer-valued.
1124b8e80941Smrg       */
1125b8e80941Smrg      if (ctx->Extensions.EXT_texture_integer && _mesa_is_color_format(format)) {
1126b8e80941Smrg         const struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorReadBuffer;
1127b8e80941Smrg         const GLboolean srcInteger = _mesa_is_format_integer_color(rb->Format);
1128b8e80941Smrg         const GLboolean dstInteger = _mesa_is_enum_format_integer(format);
1129b8e80941Smrg         if (dstInteger != srcInteger) {
1130b8e80941Smrg            _mesa_error(ctx, GL_INVALID_OPERATION,
1131b8e80941Smrg                        "glReadPixels(integer / non-integer format mismatch");
1132b8e80941Smrg            return;
1133b8e80941Smrg         }
1134b8e80941Smrg      }
1135848b8605Smrg   }
1136848b8605Smrg
1137b8e80941Smrg   /* Do all needed clipping here, so that we can forget about it later */
1138b8e80941Smrg   clippedPacking = ctx->Pack;
1139b8e80941Smrg   if (!_mesa_clip_readpixels(ctx, &x, &y, &width, &height, &clippedPacking))
1140848b8605Smrg      return; /* nothing to do */
1141848b8605Smrg
1142b8e80941Smrg   if (!no_error) {
1143b8e80941Smrg      if (!_mesa_validate_pbo_access(2, &ctx->Pack, width, height, 1,
1144b8e80941Smrg                                     format, type, bufSize, pixels)) {
1145b8e80941Smrg         if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
1146b8e80941Smrg            _mesa_error(ctx, GL_INVALID_OPERATION,
1147b8e80941Smrg                        "glReadPixels(out of bounds PBO access)");
1148b8e80941Smrg         } else {
1149b8e80941Smrg            _mesa_error(ctx, GL_INVALID_OPERATION,
1150b8e80941Smrg                        "glReadnPixelsARB(out of bounds access:"
1151b8e80941Smrg                        " bufSize (%d) is too small)", bufSize);
1152b8e80941Smrg         }
1153b8e80941Smrg         return;
1154848b8605Smrg      }
1155848b8605Smrg
1156b8e80941Smrg      if (_mesa_is_bufferobj(ctx->Pack.BufferObj) &&
1157b8e80941Smrg          _mesa_check_disallowed_mapping(ctx->Pack.BufferObj)) {
1158b8e80941Smrg         /* buffer is mapped - that's an error */
1159b8e80941Smrg         _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(PBO is mapped)");
1160b8e80941Smrg         return;
1161b8e80941Smrg      }
1162848b8605Smrg   }
1163848b8605Smrg
1164848b8605Smrg   ctx->Driver.ReadPixels(ctx, x, y, width, height,
1165b8e80941Smrg                          format, type, &clippedPacking, pixels);
1166b8e80941Smrg}
1167b8e80941Smrg
1168b8e80941Smrgvoid GLAPIENTRY
1169b8e80941Smrg_mesa_ReadnPixelsARB_no_error(GLint x, GLint y, GLsizei width, GLsizei height,
1170b8e80941Smrg                              GLenum format, GLenum type, GLsizei bufSize,
1171b8e80941Smrg                              GLvoid *pixels)
1172b8e80941Smrg{
1173b8e80941Smrg   read_pixels(x, y, width, height, format, type, bufSize, pixels, true);
1174b8e80941Smrg}
1175b8e80941Smrg
1176b8e80941Smrgvoid GLAPIENTRY
1177b8e80941Smrg_mesa_ReadnPixelsARB(GLint x, GLint y, GLsizei width, GLsizei height,
1178b8e80941Smrg                     GLenum format, GLenum type, GLsizei bufSize,
1179b8e80941Smrg                     GLvoid *pixels)
1180b8e80941Smrg{
1181b8e80941Smrg   read_pixels(x, y, width, height, format, type, bufSize, pixels, false);
1182b8e80941Smrg}
1183b8e80941Smrg
1184b8e80941Smrgvoid GLAPIENTRY
1185b8e80941Smrg_mesa_ReadPixels_no_error(GLint x, GLint y, GLsizei width, GLsizei height,
1186b8e80941Smrg                          GLenum format, GLenum type, GLvoid *pixels)
1187b8e80941Smrg{
1188b8e80941Smrg   _mesa_ReadnPixelsARB_no_error(x, y, width, height, format, type, INT_MAX,
1189b8e80941Smrg                                 pixels);
1190848b8605Smrg}
1191848b8605Smrg
1192848b8605Smrgvoid GLAPIENTRY
1193b8e80941Smrg_mesa_ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height,
1194b8e80941Smrg                 GLenum format, GLenum type, GLvoid *pixels)
1195848b8605Smrg{
1196848b8605Smrg   _mesa_ReadnPixelsARB(x, y, width, height, format, type, INT_MAX, pixels);
1197848b8605Smrg}
1198