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