• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Mesa 3-D graphics library
3  *
4  * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included
14  * in all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22  * OTHER DEALINGS IN THE SOFTWARE.
23  */
24 
25 #include "glheader.h"
26 #include "imports.h"
27 #include "blend.h"
28 #include "bufferobj.h"
29 #include "context.h"
30 #include "enums.h"
31 #include "readpix.h"
32 #include "framebuffer.h"
33 #include "formats.h"
34 #include "format_unpack.h"
35 #include "image.h"
36 #include "mtypes.h"
37 #include "pack.h"
38 #include "pbo.h"
39 #include "state.h"
40 #include "glformats.h"
41 #include "fbobject.h"
42 #include "format_utils.h"
43 #include "pixeltransfer.h"
44 
45 
46 /**
47  * Return true if the conversion L=R+G+B is needed.
48  */
49 GLboolean
_mesa_need_rgb_to_luminance_conversion(GLenum srcBaseFormat,GLenum dstBaseFormat)50 _mesa_need_rgb_to_luminance_conversion(GLenum srcBaseFormat,
51                                        GLenum dstBaseFormat)
52 {
53    return (srcBaseFormat == GL_RG ||
54            srcBaseFormat == GL_RGB ||
55            srcBaseFormat == GL_RGBA) &&
56           (dstBaseFormat == GL_LUMINANCE ||
57            dstBaseFormat == GL_LUMINANCE_ALPHA);
58 }
59 
60 /**
61  * Return true if the conversion L,I to RGB conversion is needed.
62  */
63 GLboolean
_mesa_need_luminance_to_rgb_conversion(GLenum srcBaseFormat,GLenum dstBaseFormat)64 _mesa_need_luminance_to_rgb_conversion(GLenum srcBaseFormat,
65                                        GLenum dstBaseFormat)
66 {
67    return (srcBaseFormat == GL_LUMINANCE ||
68            srcBaseFormat == GL_LUMINANCE_ALPHA ||
69            srcBaseFormat == GL_INTENSITY) &&
70           (dstBaseFormat == GL_GREEN ||
71            dstBaseFormat == GL_BLUE ||
72            dstBaseFormat == GL_RG ||
73            dstBaseFormat == GL_RGB ||
74            dstBaseFormat == GL_BGR ||
75            dstBaseFormat == GL_RGBA ||
76            dstBaseFormat == GL_BGRA);
77 }
78 
79 /**
80  * Return transfer op flags for this ReadPixels operation.
81  */
82 GLbitfield
_mesa_get_readpixels_transfer_ops(const struct gl_context * ctx,mesa_format texFormat,GLenum format,GLenum type,GLboolean uses_blit)83 _mesa_get_readpixels_transfer_ops(const struct gl_context *ctx,
84                                   mesa_format texFormat,
85                                   GLenum format, GLenum type,
86                                   GLboolean uses_blit)
87 {
88    GLbitfield transferOps = ctx->_ImageTransferState;
89    GLenum srcBaseFormat = _mesa_get_format_base_format(texFormat);
90    GLenum dstBaseFormat = _mesa_unpack_format_to_base_format(format);
91 
92    if (format == GL_DEPTH_COMPONENT ||
93        format == GL_DEPTH_STENCIL ||
94        format == GL_STENCIL_INDEX) {
95       return 0;
96    }
97 
98    /* Pixel transfer ops (scale, bias, table lookup) do not apply
99     * to integer formats.
100     */
101    if (_mesa_is_enum_format_integer(format)) {
102       return 0;
103    }
104 
105    if (uses_blit) {
106       /* For blit-based ReadPixels packing, the clamping is done automatically
107        * unless the type is float. */
108       if (_mesa_get_clamp_read_color(ctx, ctx->ReadBuffer) &&
109           (type == GL_FLOAT || type == GL_HALF_FLOAT)) {
110          transferOps |= IMAGE_CLAMP_BIT;
111       }
112    }
113    else {
114       /* For CPU-based ReadPixels packing, the clamping must always be done
115        * for non-float types, */
116       if (_mesa_get_clamp_read_color(ctx, ctx->ReadBuffer) ||
117           (type != GL_FLOAT && type != GL_HALF_FLOAT)) {
118          transferOps |= IMAGE_CLAMP_BIT;
119       }
120    }
121 
122    /* If the format is unsigned normalized, we can ignore clamping
123     * because the values are already in the range [0,1] so it won't
124     * have any effect anyway.
125     */
126    if (_mesa_get_format_datatype(texFormat) == GL_UNSIGNED_NORMALIZED &&
127        !_mesa_need_rgb_to_luminance_conversion(srcBaseFormat, dstBaseFormat)) {
128       transferOps &= ~IMAGE_CLAMP_BIT;
129    }
130 
131    return transferOps;
132 }
133 
134 
135 /**
136  * Return true if memcpy cannot be used for ReadPixels.
137  *
138  * If uses_blit is true, the function returns true if a simple 3D engine blit
139  * cannot be used for ReadPixels packing.
140  *
141  * NOTE: This doesn't take swizzling and format conversions between
142  *       the readbuffer and the pixel pack buffer into account.
143  */
144 GLboolean
_mesa_readpixels_needs_slow_path(const struct gl_context * ctx,GLenum format,GLenum type,GLboolean uses_blit)145 _mesa_readpixels_needs_slow_path(const struct gl_context *ctx, GLenum format,
146                                  GLenum type, GLboolean uses_blit)
147 {
148    struct gl_renderbuffer *rb =
149          _mesa_get_read_renderbuffer_for_format(ctx, format);
150    GLenum dstBaseFormat = _mesa_unpack_format_to_base_format(format);
151 
152    assert(rb);
153 
154    /* There are different rules depending on the base format. */
155    switch (format) {
156    case GL_DEPTH_STENCIL:
157       return !_mesa_has_depthstencil_combined(ctx->ReadBuffer) ||
158              ctx->Pixel.DepthScale != 1.0f || ctx->Pixel.DepthBias != 0.0f ||
159              ctx->Pixel.IndexShift || ctx->Pixel.IndexOffset ||
160              ctx->Pixel.MapStencilFlag;
161 
162    case GL_DEPTH_COMPONENT:
163       return ctx->Pixel.DepthScale != 1.0f || ctx->Pixel.DepthBias != 0.0f;
164 
165    case GL_STENCIL_INDEX:
166       return ctx->Pixel.IndexShift || ctx->Pixel.IndexOffset ||
167              ctx->Pixel.MapStencilFlag;
168 
169    default:
170       /* Color formats. */
171       if (_mesa_need_rgb_to_luminance_conversion(rb->_BaseFormat,
172                                                  dstBaseFormat)) {
173          return GL_TRUE;
174       }
175 
176       /* And finally, see if there are any transfer ops. */
177       return _mesa_get_readpixels_transfer_ops(ctx, rb->Format, format, type,
178                                                uses_blit) != 0;
179    }
180    return GL_FALSE;
181 }
182 
183 
184 static GLboolean
readpixels_can_use_memcpy(const struct gl_context * ctx,GLenum format,GLenum type,const struct gl_pixelstore_attrib * packing)185 readpixels_can_use_memcpy(const struct gl_context *ctx, GLenum format, GLenum type,
186                           const struct gl_pixelstore_attrib *packing)
187 {
188    struct gl_renderbuffer *rb =
189          _mesa_get_read_renderbuffer_for_format(ctx, format);
190 
191    assert(rb);
192 
193    if (_mesa_readpixels_needs_slow_path(ctx, format, type, GL_FALSE)) {
194       return GL_FALSE;
195    }
196 
197    /* The base internal format and the base Mesa format must match. */
198    if (rb->_BaseFormat != _mesa_get_format_base_format(rb->Format)) {
199       return GL_FALSE;
200    }
201 
202    /* The Mesa format must match the input format and type. */
203    if (!_mesa_format_matches_format_and_type(rb->Format, format, type,
204                                              packing->SwapBytes, NULL)) {
205       return GL_FALSE;
206    }
207 
208    return GL_TRUE;
209 }
210 
211 
212 static GLboolean
readpixels_memcpy(struct gl_context * ctx,GLint x,GLint y,GLsizei width,GLsizei height,GLenum format,GLenum type,GLvoid * pixels,const struct gl_pixelstore_attrib * packing)213 readpixels_memcpy(struct gl_context *ctx,
214                   GLint x, GLint y,
215                   GLsizei width, GLsizei height,
216                   GLenum format, GLenum type,
217                   GLvoid *pixels,
218                   const struct gl_pixelstore_attrib *packing)
219 {
220    struct gl_renderbuffer *rb =
221          _mesa_get_read_renderbuffer_for_format(ctx, format);
222    GLubyte *dst, *map;
223    int dstStride, stride, j, texelBytes;
224 
225    /* Fail if memcpy cannot be used. */
226    if (!readpixels_can_use_memcpy(ctx, format, type, packing)) {
227       return GL_FALSE;
228    }
229 
230    dstStride = _mesa_image_row_stride(packing, width, format, type);
231    dst = (GLubyte *) _mesa_image_address2d(packing, pixels, width, height,
232 					   format, type, 0, 0);
233 
234    ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT,
235 			       &map, &stride);
236    if (!map) {
237       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
238       return GL_TRUE;  /* don't bother trying the slow path */
239    }
240 
241    texelBytes = _mesa_get_format_bytes(rb->Format);
242 
243    /* memcpy*/
244    for (j = 0; j < height; j++) {
245       memcpy(dst, map, width * texelBytes);
246       dst += dstStride;
247       map += stride;
248    }
249 
250    ctx->Driver.UnmapRenderbuffer(ctx, rb);
251    return GL_TRUE;
252 }
253 
254 
255 /**
256  * Optimized path for conversion of depth values to GL_DEPTH_COMPONENT,
257  * GL_UNSIGNED_INT.
258  */
259 static GLboolean
read_uint_depth_pixels(struct gl_context * ctx,GLint x,GLint y,GLsizei width,GLsizei height,GLenum type,GLvoid * pixels,const struct gl_pixelstore_attrib * packing)260 read_uint_depth_pixels( struct gl_context *ctx,
261 			GLint x, GLint y,
262 			GLsizei width, GLsizei height,
263 			GLenum type, GLvoid *pixels,
264 			const struct gl_pixelstore_attrib *packing )
265 {
266    struct gl_framebuffer *fb = ctx->ReadBuffer;
267    struct gl_renderbuffer *rb = fb->Attachment[BUFFER_DEPTH].Renderbuffer;
268    GLubyte *map, *dst;
269    int stride, dstStride, j;
270 
271    if (ctx->Pixel.DepthScale != 1.0F || ctx->Pixel.DepthBias != 0.0F)
272       return GL_FALSE;
273 
274    if (packing->SwapBytes)
275       return GL_FALSE;
276 
277    if (_mesa_get_format_datatype(rb->Format) != GL_UNSIGNED_NORMALIZED)
278       return GL_FALSE;
279 
280    ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT,
281 			       &map, &stride);
282 
283    if (!map) {
284       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
285       return GL_TRUE;  /* don't bother trying the slow path */
286    }
287 
288    dstStride = _mesa_image_row_stride(packing, width, GL_DEPTH_COMPONENT, type);
289    dst = (GLubyte *) _mesa_image_address2d(packing, pixels, width, height,
290 					   GL_DEPTH_COMPONENT, type, 0, 0);
291 
292    for (j = 0; j < height; j++) {
293       _mesa_unpack_uint_z_row(rb->Format, width, map, (GLuint *)dst);
294 
295       map += stride;
296       dst += dstStride;
297    }
298    ctx->Driver.UnmapRenderbuffer(ctx, rb);
299 
300    return GL_TRUE;
301 }
302 
303 /**
304  * Read pixels for format=GL_DEPTH_COMPONENT.
305  */
306 static void
read_depth_pixels(struct gl_context * ctx,GLint x,GLint y,GLsizei width,GLsizei height,GLenum type,GLvoid * pixels,const struct gl_pixelstore_attrib * packing)307 read_depth_pixels( struct gl_context *ctx,
308                    GLint x, GLint y,
309                    GLsizei width, GLsizei height,
310                    GLenum type, GLvoid *pixels,
311                    const struct gl_pixelstore_attrib *packing )
312 {
313    struct gl_framebuffer *fb = ctx->ReadBuffer;
314    struct gl_renderbuffer *rb = fb->Attachment[BUFFER_DEPTH].Renderbuffer;
315    GLint j;
316    GLubyte *dst, *map;
317    int dstStride, stride;
318    GLfloat *depthValues;
319 
320    if (!rb)
321       return;
322 
323    /* clipping should have been done already */
324    assert(x >= 0);
325    assert(y >= 0);
326    assert(x + width <= (GLint) rb->Width);
327    assert(y + height <= (GLint) rb->Height);
328 
329    if (type == GL_UNSIGNED_INT &&
330        read_uint_depth_pixels(ctx, x, y, width, height, type, pixels, packing)) {
331       return;
332    }
333 
334    dstStride = _mesa_image_row_stride(packing, width, GL_DEPTH_COMPONENT, type);
335    dst = (GLubyte *) _mesa_image_address2d(packing, pixels, width, height,
336 					   GL_DEPTH_COMPONENT, type, 0, 0);
337 
338    ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT,
339 			       &map, &stride);
340    if (!map) {
341       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
342       return;
343    }
344 
345    depthValues = malloc(width * sizeof(GLfloat));
346 
347    if (depthValues) {
348       /* General case (slower) */
349       for (j = 0; j < height; j++, y++) {
350          _mesa_unpack_float_z_row(rb->Format, width, map, depthValues);
351          _mesa_pack_depth_span(ctx, width, dst, type, depthValues, packing);
352 
353          dst += dstStride;
354          map += stride;
355       }
356    }
357    else {
358       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
359    }
360 
361    free(depthValues);
362 
363    ctx->Driver.UnmapRenderbuffer(ctx, rb);
364 }
365 
366 
367 /**
368  * Read pixels for format=GL_STENCIL_INDEX.
369  */
370 static void
read_stencil_pixels(struct gl_context * ctx,GLint x,GLint y,GLsizei width,GLsizei height,GLenum type,GLvoid * pixels,const struct gl_pixelstore_attrib * packing)371 read_stencil_pixels( struct gl_context *ctx,
372                      GLint x, GLint y,
373                      GLsizei width, GLsizei height,
374                      GLenum type, GLvoid *pixels,
375                      const struct gl_pixelstore_attrib *packing )
376 {
377    struct gl_framebuffer *fb = ctx->ReadBuffer;
378    struct gl_renderbuffer *rb = fb->Attachment[BUFFER_STENCIL].Renderbuffer;
379    GLint j;
380    GLubyte *map, *stencil;
381    GLint stride;
382 
383    if (!rb)
384       return;
385 
386    ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT,
387 			       &map, &stride);
388    if (!map) {
389       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
390       return;
391    }
392 
393    stencil = malloc(width * sizeof(GLubyte));
394 
395    if (stencil) {
396       /* process image row by row */
397       for (j = 0; j < height; j++) {
398          GLvoid *dest;
399 
400          _mesa_unpack_ubyte_stencil_row(rb->Format, width, map, stencil);
401          dest = _mesa_image_address2d(packing, pixels, width, height,
402                                       GL_STENCIL_INDEX, type, j, 0);
403 
404          _mesa_pack_stencil_span(ctx, width, type, dest, stencil, packing);
405 
406          map += stride;
407       }
408    }
409    else {
410       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
411    }
412 
413    free(stencil);
414 
415    ctx->Driver.UnmapRenderbuffer(ctx, rb);
416 }
417 
418 /*
419  * Read R, G, B, A, RGB, L, or LA pixels.
420  */
421 static void
read_rgba_pixels(struct gl_context * ctx,GLint x,GLint y,GLsizei width,GLsizei height,GLenum format,GLenum type,GLvoid * pixels,const struct gl_pixelstore_attrib * packing)422 read_rgba_pixels( struct gl_context *ctx,
423                   GLint x, GLint y,
424                   GLsizei width, GLsizei height,
425                   GLenum format, GLenum type, GLvoid *pixels,
426                   const struct gl_pixelstore_attrib *packing )
427 {
428    GLbitfield transferOps;
429    bool dst_is_integer, convert_rgb_to_lum, needs_rebase;
430    int dst_stride, src_stride, rb_stride;
431    uint32_t dst_format, src_format;
432    GLubyte *dst, *map;
433    mesa_format rb_format;
434    bool needs_rgba;
435    void *rgba, *src;
436    bool src_is_uint = false;
437    uint8_t rebase_swizzle[4];
438    struct gl_framebuffer *fb = ctx->ReadBuffer;
439    struct gl_renderbuffer *rb = fb->_ColorReadBuffer;
440    GLenum dstBaseFormat = _mesa_unpack_format_to_base_format(format);
441 
442    if (!rb)
443       return;
444 
445    transferOps = _mesa_get_readpixels_transfer_ops(ctx, rb->Format, format,
446                                                    type, GL_FALSE);
447    /* Describe the dst format */
448    dst_is_integer = _mesa_is_enum_format_integer(format);
449    dst_stride = _mesa_image_row_stride(packing, width, format, type);
450    dst_format = _mesa_format_from_format_and_type(format, type);
451    convert_rgb_to_lum =
452       _mesa_need_rgb_to_luminance_conversion(rb->_BaseFormat, dstBaseFormat);
453    dst = (GLubyte *) _mesa_image_address2d(packing, pixels, width, height,
454                                            format, type, 0, 0);
455 
456    /* Map the source render buffer */
457    ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT,
458                                &map, &rb_stride);
459    if (!map) {
460       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
461       return;
462    }
463    rb_format = _mesa_get_srgb_format_linear(rb->Format);
464 
465    /*
466     * Depending on the base formats involved in the conversion we might need to
467     * rebase some values, so for these formats we compute a rebase swizzle.
468     */
469    if (rb->_BaseFormat == GL_LUMINANCE || rb->_BaseFormat == GL_INTENSITY) {
470       needs_rebase = true;
471       rebase_swizzle[0] = MESA_FORMAT_SWIZZLE_X;
472       rebase_swizzle[1] = MESA_FORMAT_SWIZZLE_ZERO;
473       rebase_swizzle[2] = MESA_FORMAT_SWIZZLE_ZERO;
474       rebase_swizzle[3] = MESA_FORMAT_SWIZZLE_ONE;
475    } else if (rb->_BaseFormat == GL_LUMINANCE_ALPHA) {
476       needs_rebase = true;
477       rebase_swizzle[0] = MESA_FORMAT_SWIZZLE_X;
478       rebase_swizzle[1] = MESA_FORMAT_SWIZZLE_ZERO;
479       rebase_swizzle[2] = MESA_FORMAT_SWIZZLE_ZERO;
480       rebase_swizzle[3] = MESA_FORMAT_SWIZZLE_W;
481    } else if (_mesa_get_format_base_format(rb_format) != rb->_BaseFormat) {
482       needs_rebase =
483          _mesa_compute_rgba2base2rgba_component_mapping(rb->_BaseFormat,
484                                                         rebase_swizzle);
485    } else {
486       needs_rebase = false;
487    }
488 
489    /* Since _mesa_format_convert does not handle transferOps we need to handle
490     * them before we call the function. This requires to convert to RGBA float
491     * first so we can call _mesa_apply_rgba_transfer_ops. If the dst format is
492     * integer transferOps do not apply.
493     *
494     * Converting to luminance also requires converting to RGBA first, so we can
495     * then compute luminance values as L=R+G+B. Notice that this is different
496     * from GetTexImage, where we compute L=R.
497     */
498    assert(!transferOps || (transferOps && !dst_is_integer));
499 
500    needs_rgba = transferOps || convert_rgb_to_lum;
501    rgba = NULL;
502    if (needs_rgba) {
503       uint32_t rgba_format;
504       int rgba_stride;
505       bool need_convert;
506 
507       /* Convert to RGBA float or int/uint depending on the type of the src */
508       if (dst_is_integer) {
509          src_is_uint = _mesa_is_format_unsigned(rb_format);
510          if (src_is_uint) {
511             rgba_format = RGBA32_UINT;
512             rgba_stride = width * 4 * sizeof(GLuint);
513          } else {
514             rgba_format = RGBA32_INT;
515             rgba_stride = width * 4 * sizeof(GLint);
516          }
517       } else {
518          rgba_format = RGBA32_FLOAT;
519          rgba_stride = width * 4 * sizeof(GLfloat);
520       }
521 
522       /* If we are lucky and the dst format matches the RGBA format we need to
523        * convert to, then we can convert directly into the dst buffer and avoid
524        * the final conversion/copy from the rgba buffer to the dst buffer.
525        */
526       if (dst_format == rgba_format &&
527           dst_stride == rgba_stride) {
528          need_convert = false;
529          rgba = dst;
530       } else {
531          need_convert = true;
532          rgba = malloc(height * rgba_stride);
533          if (!rgba) {
534             _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
535             goto done_unmap;
536          }
537       }
538 
539       /* Convert to RGBA now */
540       _mesa_format_convert(rgba, rgba_format, rgba_stride,
541                            map, rb_format, rb_stride,
542                            width, height,
543                            needs_rebase ? rebase_swizzle : NULL);
544 
545       /* Handle transfer ops if necessary */
546       if (transferOps)
547          _mesa_apply_rgba_transfer_ops(ctx, transferOps, width * height, rgba);
548 
549       /* If we had to rebase, we have already taken care of that */
550       needs_rebase = false;
551 
552       /* If we were lucky and our RGBA conversion matches the dst format, then
553        * we are done.
554        */
555       if (!need_convert)
556          goto done_swap;
557 
558       /* Otherwise, we need to convert from RGBA to dst next */
559       src = rgba;
560       src_format = rgba_format;
561       src_stride = rgba_stride;
562    } else {
563       /* No RGBA conversion needed, convert directly to dst */
564       src = map;
565       src_format = rb_format;
566       src_stride = rb_stride;
567    }
568 
569    /* Do the conversion.
570     *
571     * If the dst format is Luminance, we need to do the conversion by computing
572     * L=R+G+B values.
573     */
574    if (!convert_rgb_to_lum) {
575       _mesa_format_convert(dst, dst_format, dst_stride,
576                            src, src_format, src_stride,
577                            width, height,
578                            needs_rebase ? rebase_swizzle : NULL);
579    } else if (!dst_is_integer) {
580       /* Compute float Luminance values from RGBA float */
581       int luminance_stride, luminance_bytes;
582       void *luminance;
583       uint32_t luminance_format;
584 
585       luminance_stride = width * sizeof(GLfloat);
586       if (format == GL_LUMINANCE_ALPHA)
587          luminance_stride *= 2;
588       luminance_bytes = height * luminance_stride;
589       luminance = malloc(luminance_bytes);
590       if (!luminance) {
591          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
592          free(rgba);
593          goto done_unmap;
594       }
595       _mesa_pack_luminance_from_rgba_float(width * height, src,
596                                            luminance, format, transferOps);
597 
598       /* Convert from Luminance float to dst (this will hadle type conversion
599        * from float to the type of dst if necessary)
600        */
601       luminance_format = _mesa_format_from_format_and_type(format, GL_FLOAT);
602       _mesa_format_convert(dst, dst_format, dst_stride,
603                            luminance, luminance_format, luminance_stride,
604                            width, height, NULL);
605       free(luminance);
606    } else {
607       _mesa_pack_luminance_from_rgba_integer(width * height, src, !src_is_uint,
608                                              dst, format, type);
609    }
610 
611    free(rgba);
612 
613 done_swap:
614    /* Handle byte swapping if required */
615    if (packing->SwapBytes) {
616       _mesa_swap_bytes_2d_image(format, type, packing,
617                                 width, height, dst, dst);
618    }
619 
620 done_unmap:
621    ctx->Driver.UnmapRenderbuffer(ctx, rb);
622 }
623 
624 /**
625  * For a packed depth/stencil buffer being read as depth/stencil, just memcpy the
626  * data (possibly swapping 8/24 vs 24/8 as we go).
627  */
628 static GLboolean
fast_read_depth_stencil_pixels(struct gl_context * ctx,GLint x,GLint y,GLsizei width,GLsizei height,GLubyte * dst,int dstStride)629 fast_read_depth_stencil_pixels(struct gl_context *ctx,
630 			       GLint x, GLint y,
631 			       GLsizei width, GLsizei height,
632 			       GLubyte *dst, int dstStride)
633 {
634    struct gl_framebuffer *fb = ctx->ReadBuffer;
635    struct gl_renderbuffer *rb = fb->Attachment[BUFFER_DEPTH].Renderbuffer;
636    struct gl_renderbuffer *stencilRb = fb->Attachment[BUFFER_STENCIL].Renderbuffer;
637    GLubyte *map;
638    int stride, i;
639 
640    if (rb != stencilRb)
641       return GL_FALSE;
642 
643    if (rb->Format != MESA_FORMAT_S8_UINT_Z24_UNORM &&
644        rb->Format != MESA_FORMAT_Z24_UNORM_S8_UINT)
645       return GL_FALSE;
646 
647    ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT,
648 			       &map, &stride);
649    if (!map) {
650       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
651       return GL_TRUE;  /* don't bother trying the slow path */
652    }
653 
654    for (i = 0; i < height; i++) {
655       _mesa_unpack_uint_24_8_depth_stencil_row(rb->Format, width,
656 					       map, (GLuint *)dst);
657       map += stride;
658       dst += dstStride;
659    }
660 
661    ctx->Driver.UnmapRenderbuffer(ctx, rb);
662 
663    return GL_TRUE;
664 }
665 
666 
667 /**
668  * For non-float-depth and stencil buffers being read as 24/8 depth/stencil,
669  * copy the integer data directly instead of converting depth to float and
670  * re-packing.
671  */
672 static GLboolean
fast_read_depth_stencil_pixels_separate(struct gl_context * ctx,GLint x,GLint y,GLsizei width,GLsizei height,uint32_t * dst,int dstStride)673 fast_read_depth_stencil_pixels_separate(struct gl_context *ctx,
674 					GLint x, GLint y,
675 					GLsizei width, GLsizei height,
676 					uint32_t *dst, int dstStride)
677 {
678    struct gl_framebuffer *fb = ctx->ReadBuffer;
679    struct gl_renderbuffer *depthRb = fb->Attachment[BUFFER_DEPTH].Renderbuffer;
680    struct gl_renderbuffer *stencilRb = fb->Attachment[BUFFER_STENCIL].Renderbuffer;
681    GLubyte *depthMap, *stencilMap, *stencilVals;
682    int depthStride, stencilStride, i, j;
683 
684    if (_mesa_get_format_datatype(depthRb->Format) != GL_UNSIGNED_NORMALIZED)
685       return GL_FALSE;
686 
687    ctx->Driver.MapRenderbuffer(ctx, depthRb, x, y, width, height,
688 			       GL_MAP_READ_BIT, &depthMap, &depthStride);
689    if (!depthMap) {
690       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
691       return GL_TRUE;  /* don't bother trying the slow path */
692    }
693 
694    ctx->Driver.MapRenderbuffer(ctx, stencilRb, x, y, width, height,
695 			       GL_MAP_READ_BIT, &stencilMap, &stencilStride);
696    if (!stencilMap) {
697       ctx->Driver.UnmapRenderbuffer(ctx, depthRb);
698       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
699       return GL_TRUE;  /* don't bother trying the slow path */
700    }
701 
702    stencilVals = malloc(width * sizeof(GLubyte));
703 
704    if (stencilVals) {
705       for (j = 0; j < height; j++) {
706          _mesa_unpack_uint_z_row(depthRb->Format, width, depthMap, dst);
707          _mesa_unpack_ubyte_stencil_row(stencilRb->Format, width,
708                                         stencilMap, stencilVals);
709 
710          for (i = 0; i < width; i++) {
711             dst[i] = (dst[i] & 0xffffff00) | stencilVals[i];
712          }
713 
714          depthMap += depthStride;
715          stencilMap += stencilStride;
716          dst += dstStride / 4;
717       }
718    }
719    else {
720       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
721    }
722 
723    free(stencilVals);
724 
725    ctx->Driver.UnmapRenderbuffer(ctx, depthRb);
726    ctx->Driver.UnmapRenderbuffer(ctx, stencilRb);
727 
728    return GL_TRUE;
729 }
730 
731 static void
slow_read_depth_stencil_pixels_separate(struct gl_context * ctx,GLint x,GLint y,GLsizei width,GLsizei height,GLenum type,const struct gl_pixelstore_attrib * packing,GLubyte * dst,int dstStride)732 slow_read_depth_stencil_pixels_separate(struct gl_context *ctx,
733 					GLint x, GLint y,
734 					GLsizei width, GLsizei height,
735 					GLenum type,
736 					const struct gl_pixelstore_attrib *packing,
737 					GLubyte *dst, int dstStride)
738 {
739    struct gl_framebuffer *fb = ctx->ReadBuffer;
740    struct gl_renderbuffer *depthRb = fb->Attachment[BUFFER_DEPTH].Renderbuffer;
741    struct gl_renderbuffer *stencilRb = fb->Attachment[BUFFER_STENCIL].Renderbuffer;
742    GLubyte *depthMap, *stencilMap;
743    int depthStride, stencilStride, j;
744    GLubyte *stencilVals;
745    GLfloat *depthVals;
746 
747 
748    /* The depth and stencil buffers might be separate, or a single buffer.
749     * If one buffer, only map it once.
750     */
751    ctx->Driver.MapRenderbuffer(ctx, depthRb, x, y, width, height,
752 			       GL_MAP_READ_BIT, &depthMap, &depthStride);
753    if (!depthMap) {
754       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
755       return;
756    }
757 
758    if (stencilRb != depthRb) {
759       ctx->Driver.MapRenderbuffer(ctx, stencilRb, x, y, width, height,
760                                   GL_MAP_READ_BIT, &stencilMap,
761                                   &stencilStride);
762       if (!stencilMap) {
763          ctx->Driver.UnmapRenderbuffer(ctx, depthRb);
764          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
765          return;
766       }
767    }
768    else {
769       stencilMap = depthMap;
770       stencilStride = depthStride;
771    }
772 
773    stencilVals = malloc(width * sizeof(GLubyte));
774    depthVals = malloc(width * sizeof(GLfloat));
775 
776    if (stencilVals && depthVals) {
777       for (j = 0; j < height; j++) {
778          _mesa_unpack_float_z_row(depthRb->Format, width, depthMap, depthVals);
779          _mesa_unpack_ubyte_stencil_row(stencilRb->Format, width,
780                                         stencilMap, stencilVals);
781 
782          _mesa_pack_depth_stencil_span(ctx, width, type, (GLuint *)dst,
783                                        depthVals, stencilVals, packing);
784 
785          depthMap += depthStride;
786          stencilMap += stencilStride;
787          dst += dstStride;
788       }
789    }
790    else {
791       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
792    }
793 
794    free(stencilVals);
795    free(depthVals);
796 
797    ctx->Driver.UnmapRenderbuffer(ctx, depthRb);
798    if (stencilRb != depthRb) {
799       ctx->Driver.UnmapRenderbuffer(ctx, stencilRb);
800    }
801 }
802 
803 
804 /**
805  * Read combined depth/stencil values.
806  * We'll have already done error checking to be sure the expected
807  * depth and stencil buffers really exist.
808  */
809 static void
read_depth_stencil_pixels(struct gl_context * ctx,GLint x,GLint y,GLsizei width,GLsizei height,GLenum type,GLvoid * pixels,const struct gl_pixelstore_attrib * packing)810 read_depth_stencil_pixels(struct gl_context *ctx,
811                           GLint x, GLint y,
812                           GLsizei width, GLsizei height,
813                           GLenum type, GLvoid *pixels,
814                           const struct gl_pixelstore_attrib *packing )
815 {
816    const GLboolean scaleOrBias
817       = ctx->Pixel.DepthScale != 1.0F || ctx->Pixel.DepthBias != 0.0F;
818    const GLboolean stencilTransfer = ctx->Pixel.IndexShift
819       || ctx->Pixel.IndexOffset || ctx->Pixel.MapStencilFlag;
820    GLubyte *dst;
821    int dstStride;
822 
823    dst = (GLubyte *) _mesa_image_address2d(packing, pixels,
824 					   width, height,
825 					   GL_DEPTH_STENCIL_EXT,
826 					   type, 0, 0);
827    dstStride = _mesa_image_row_stride(packing, width,
828 				      GL_DEPTH_STENCIL_EXT, type);
829 
830    /* Fast 24/8 reads. */
831    if (type == GL_UNSIGNED_INT_24_8 &&
832        !scaleOrBias && !stencilTransfer && !packing->SwapBytes) {
833       if (fast_read_depth_stencil_pixels(ctx, x, y, width, height,
834 					 dst, dstStride))
835 	 return;
836 
837       if (fast_read_depth_stencil_pixels_separate(ctx, x, y, width, height,
838 						  (uint32_t *)dst, dstStride))
839 	 return;
840    }
841 
842    slow_read_depth_stencil_pixels_separate(ctx, x, y, width, height,
843 					   type, packing,
844 					   dst, dstStride);
845 }
846 
847 
848 
849 /**
850  * Software fallback routine for ctx->Driver.ReadPixels().
851  * By time we get here, all error checking will have been done.
852  */
853 void
_mesa_readpixels(struct gl_context * ctx,GLint x,GLint y,GLsizei width,GLsizei height,GLenum format,GLenum type,const struct gl_pixelstore_attrib * packing,GLvoid * pixels)854 _mesa_readpixels(struct gl_context *ctx,
855                  GLint x, GLint y, GLsizei width, GLsizei height,
856                  GLenum format, GLenum type,
857                  const struct gl_pixelstore_attrib *packing,
858                  GLvoid *pixels)
859 {
860    if (ctx->NewState)
861       _mesa_update_state(ctx);
862 
863    pixels = _mesa_map_pbo_dest(ctx, packing, pixels);
864 
865    if (pixels) {
866       /* Try memcpy first. */
867       if (readpixels_memcpy(ctx, x, y, width, height, format, type,
868                             pixels, packing)) {
869          _mesa_unmap_pbo_dest(ctx, packing);
870          return;
871       }
872 
873       /* Otherwise take the slow path. */
874       switch (format) {
875       case GL_STENCIL_INDEX:
876          read_stencil_pixels(ctx, x, y, width, height, type, pixels,
877                              packing);
878          break;
879       case GL_DEPTH_COMPONENT:
880          read_depth_pixels(ctx, x, y, width, height, type, pixels,
881                            packing);
882          break;
883       case GL_DEPTH_STENCIL_EXT:
884          read_depth_stencil_pixels(ctx, x, y, width, height, type, pixels,
885                                    packing);
886          break;
887       default:
888          /* all other formats should be color formats */
889          read_rgba_pixels(ctx, x, y, width, height, format, type, pixels,
890                           packing);
891       }
892 
893       _mesa_unmap_pbo_dest(ctx, packing);
894    }
895 }
896 
897 
898 static GLenum
read_pixels_es3_error_check(GLenum format,GLenum type,const struct gl_renderbuffer * rb)899 read_pixels_es3_error_check(GLenum format, GLenum type,
900                             const struct gl_renderbuffer *rb)
901 {
902    const GLenum internalFormat = rb->InternalFormat;
903    const GLenum data_type = _mesa_get_format_datatype(rb->Format);
904    GLboolean is_unsigned_int = GL_FALSE;
905    GLboolean is_signed_int = GL_FALSE;
906    GLboolean is_float_depth = (internalFormat == GL_DEPTH_COMPONENT32F) ||
907          (internalFormat == GL_DEPTH32F_STENCIL8);
908 
909    is_unsigned_int = _mesa_is_enum_format_unsigned_int(internalFormat);
910    if (!is_unsigned_int) {
911       is_signed_int = _mesa_is_enum_format_signed_int(internalFormat);
912    }
913 
914    switch (format) {
915    case GL_RGBA:
916       if (type == GL_FLOAT && data_type == GL_FLOAT)
917          return GL_NO_ERROR; /* EXT_color_buffer_float */
918       if (type == GL_UNSIGNED_BYTE && data_type == GL_UNSIGNED_NORMALIZED)
919          return GL_NO_ERROR;
920       if (internalFormat == GL_RGB10_A2 &&
921           type == GL_UNSIGNED_INT_2_10_10_10_REV)
922          return GL_NO_ERROR;
923       if (internalFormat == GL_RGB10_A2UI && type == GL_UNSIGNED_BYTE)
924          return GL_NO_ERROR;
925       break;
926    case GL_BGRA:
927       /* GL_EXT_read_format_bgra */
928       if (type == GL_UNSIGNED_BYTE ||
929           type == GL_UNSIGNED_SHORT_4_4_4_4_REV ||
930           type == GL_UNSIGNED_SHORT_1_5_5_5_REV)
931          return GL_NO_ERROR;
932       break;
933    case GL_RGBA_INTEGER:
934       if ((is_signed_int && type == GL_INT) ||
935           (is_unsigned_int && type == GL_UNSIGNED_INT))
936          return GL_NO_ERROR;
937       break;
938    case GL_DEPTH_STENCIL:
939       switch (type) {
940       case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
941          if (is_float_depth)
942             return GL_NO_ERROR;
943          break;
944       case GL_UNSIGNED_INT_24_8:
945          if (!is_float_depth)
946             return GL_NO_ERROR;
947          break;
948       default:
949          return GL_INVALID_ENUM;
950       }
951       break;
952    case GL_DEPTH_COMPONENT:
953       switch (type) {
954       case GL_FLOAT:
955          if (is_float_depth)
956             return GL_NO_ERROR;
957          break;
958       case GL_UNSIGNED_SHORT:
959       case GL_UNSIGNED_INT:
960       case GL_UNSIGNED_INT_24_8:
961          if (!is_float_depth)
962             return GL_NO_ERROR;
963          break;
964       default:
965          return GL_INVALID_ENUM;
966       }
967       break;
968    case GL_STENCIL_INDEX:
969       switch (type) {
970       case GL_UNSIGNED_BYTE:
971          return GL_NO_ERROR;
972       default:
973          return GL_INVALID_ENUM;
974       }
975       break;
976    }
977 
978    return GL_INVALID_OPERATION;
979 }
980 
981 
982 void GLAPIENTRY
_mesa_ReadnPixelsARB(GLint x,GLint y,GLsizei width,GLsizei height,GLenum format,GLenum type,GLsizei bufSize,GLvoid * pixels)983 _mesa_ReadnPixelsARB( GLint x, GLint y, GLsizei width, GLsizei height,
984 		      GLenum format, GLenum type, GLsizei bufSize,
985                       GLvoid *pixels )
986 {
987    GLenum err = GL_NO_ERROR;
988    struct gl_renderbuffer *rb;
989    struct gl_pixelstore_attrib clippedPacking;
990 
991    GET_CURRENT_CONTEXT(ctx);
992 
993    FLUSH_VERTICES(ctx, 0);
994    FLUSH_CURRENT(ctx, 0);
995 
996    if (MESA_VERBOSE & VERBOSE_API)
997       _mesa_debug(ctx, "glReadPixels(%d, %d, %s, %s, %p)\n",
998                   width, height,
999                   _mesa_enum_to_string(format),
1000                   _mesa_enum_to_string(type),
1001                   pixels);
1002 
1003    if (width < 0 || height < 0) {
1004       _mesa_error( ctx, GL_INVALID_VALUE,
1005                    "glReadPixels(width=%d height=%d)", width, height );
1006       return;
1007    }
1008 
1009    if (ctx->NewState)
1010       _mesa_update_state(ctx);
1011 
1012    if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
1013       _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
1014                   "glReadPixels(incomplete framebuffer)" );
1015       return;
1016    }
1017 
1018    rb = _mesa_get_read_renderbuffer_for_format(ctx, format);
1019    if (rb == NULL) {
1020       _mesa_error(ctx, GL_INVALID_OPERATION,
1021                   "glReadPixels(read buffer)");
1022       return;
1023    }
1024 
1025    /* OpenGL ES 1.x and OpenGL ES 2.0 impose additional restrictions on the
1026     * combinations of format and type that can be used.
1027     *
1028     * Technically, only two combinations are actually allowed:
1029     * GL_RGBA/GL_UNSIGNED_BYTE, and some implementation-specific internal
1030     * preferred combination.  This code doesn't know what that preferred
1031     * combination is, and Mesa can handle anything valid.  Just work instead.
1032     */
1033    if (_mesa_is_gles(ctx)) {
1034       if (ctx->API == API_OPENGLES2 &&
1035           _mesa_is_color_format(format) &&
1036           _mesa_get_color_read_format(ctx) == format &&
1037           _mesa_get_color_read_type(ctx) == type) {
1038          err = GL_NO_ERROR;
1039       } else if (ctx->Version < 30) {
1040          err = _mesa_es_error_check_format_and_type(ctx, format, type, 2);
1041          if (err == GL_NO_ERROR) {
1042             if (type == GL_FLOAT || type == GL_HALF_FLOAT_OES) {
1043                err = GL_INVALID_OPERATION;
1044             }
1045          }
1046       } else {
1047          err = read_pixels_es3_error_check(format, type, rb);
1048       }
1049 
1050       if (err != GL_NO_ERROR) {
1051          _mesa_error(ctx, err, "glReadPixels(invalid format %s and/or type %s)",
1052                      _mesa_enum_to_string(format),
1053                      _mesa_enum_to_string(type));
1054          return;
1055       }
1056    }
1057 
1058    err = _mesa_error_check_format_and_type(ctx, format, type);
1059    if (err != GL_NO_ERROR) {
1060       _mesa_error(ctx, err, "glReadPixels(invalid format %s and/or type %s)",
1061                   _mesa_enum_to_string(format),
1062                   _mesa_enum_to_string(type));
1063       return;
1064    }
1065 
1066    if (_mesa_is_user_fbo(ctx->ReadBuffer) &&
1067        ctx->ReadBuffer->Visual.samples > 0) {
1068       _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(multisample FBO)");
1069       return;
1070    }
1071 
1072    if (!_mesa_source_buffer_exists(ctx, format)) {
1073       _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(no readbuffer)");
1074       return;
1075    }
1076 
1077    /* Check that the destination format and source buffer are both
1078     * integer-valued or both non-integer-valued.
1079     */
1080    if (ctx->Extensions.EXT_texture_integer && _mesa_is_color_format(format)) {
1081       const struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorReadBuffer;
1082       const GLboolean srcInteger = _mesa_is_format_integer_color(rb->Format);
1083       const GLboolean dstInteger = _mesa_is_enum_format_integer(format);
1084       if (dstInteger != srcInteger) {
1085          _mesa_error(ctx, GL_INVALID_OPERATION,
1086                      "glReadPixels(integer / non-integer format mismatch");
1087          return;
1088       }
1089    }
1090 
1091    /* Do all needed clipping here, so that we can forget about it later */
1092    clippedPacking = ctx->Pack;
1093    if (!_mesa_clip_readpixels(ctx, &x, &y, &width, &height, &clippedPacking))
1094       return; /* nothing to do */
1095 
1096    if (!_mesa_validate_pbo_access(2, &ctx->Pack, width, height, 1,
1097                                   format, type, bufSize, pixels)) {
1098       if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) {
1099          _mesa_error(ctx, GL_INVALID_OPERATION,
1100                      "glReadPixels(out of bounds PBO access)");
1101       } else {
1102          _mesa_error(ctx, GL_INVALID_OPERATION,
1103                      "glReadnPixelsARB(out of bounds access:"
1104                      " bufSize (%d) is too small)", bufSize);
1105       }
1106       return;
1107    }
1108 
1109    if (_mesa_is_bufferobj(ctx->Pack.BufferObj) &&
1110        _mesa_check_disallowed_mapping(ctx->Pack.BufferObj)) {
1111       /* buffer is mapped - that's an error */
1112       _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(PBO is mapped)");
1113       return;
1114    }
1115 
1116    ctx->Driver.ReadPixels(ctx, x, y, width, height,
1117                           format, type, &clippedPacking, pixels);
1118 }
1119 
1120 void GLAPIENTRY
_mesa_ReadPixels(GLint x,GLint y,GLsizei width,GLsizei height,GLenum format,GLenum type,GLvoid * pixels)1121 _mesa_ReadPixels( GLint x, GLint y, GLsizei width, GLsizei height,
1122 		  GLenum format, GLenum type, GLvoid *pixels )
1123 {
1124    _mesa_ReadnPixelsARB(x, y, width, height, format, type, INT_MAX, pixels);
1125 }
1126