128876dd511ec2c9d5f5500499201df2588e8c7f1Brian Paul/* 228876dd511ec2c9d5f5500499201df2588e8c7f1Brian Paul * Mesa 3-D graphics library 328876dd511ec2c9d5f5500499201df2588e8c7f1Brian Paul * Version: 7.1 428876dd511ec2c9d5f5500499201df2588e8c7f1Brian Paul * 528876dd511ec2c9d5f5500499201df2588e8c7f1Brian Paul * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. 628876dd511ec2c9d5f5500499201df2588e8c7f1Brian Paul * 728876dd511ec2c9d5f5500499201df2588e8c7f1Brian Paul * Permission is hereby granted, free of charge, to any person obtaining a 828876dd511ec2c9d5f5500499201df2588e8c7f1Brian Paul * copy of this software and associated documentation files (the "Software"), 928876dd511ec2c9d5f5500499201df2588e8c7f1Brian Paul * to deal in the Software without restriction, including without limitation 1028876dd511ec2c9d5f5500499201df2588e8c7f1Brian Paul * the rights to use, copy, modify, merge, publish, distribute, sublicense, 1128876dd511ec2c9d5f5500499201df2588e8c7f1Brian Paul * and/or sell copies of the Software, and to permit persons to whom the 1228876dd511ec2c9d5f5500499201df2588e8c7f1Brian Paul * Software is furnished to do so, subject to the following conditions: 1328876dd511ec2c9d5f5500499201df2588e8c7f1Brian Paul * 1428876dd511ec2c9d5f5500499201df2588e8c7f1Brian Paul * The above copyright notice and this permission notice shall be included 1528876dd511ec2c9d5f5500499201df2588e8c7f1Brian Paul * in all copies or substantial portions of the Software. 1628876dd511ec2c9d5f5500499201df2588e8c7f1Brian Paul * 1728876dd511ec2c9d5f5500499201df2588e8c7f1Brian Paul * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 1828876dd511ec2c9d5f5500499201df2588e8c7f1Brian Paul * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1928876dd511ec2c9d5f5500499201df2588e8c7f1Brian Paul * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 2028876dd511ec2c9d5f5500499201df2588e8c7f1Brian Paul * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 2128876dd511ec2c9d5f5500499201df2588e8c7f1Brian Paul * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 2228876dd511ec2c9d5f5500499201df2588e8c7f1Brian Paul * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 2328876dd511ec2c9d5f5500499201df2588e8c7f1Brian Paul */ 2428876dd511ec2c9d5f5500499201df2588e8c7f1Brian Paul 2528876dd511ec2c9d5f5500499201df2588e8c7f1Brian Paul#include "glheader.h" 2628876dd511ec2c9d5f5500499201df2588e8c7f1Brian Paul#include "imports.h" 2728876dd511ec2c9d5f5500499201df2588e8c7f1Brian Paul#include "bufferobj.h" 2828876dd511ec2c9d5f5500499201df2588e8c7f1Brian Paul#include "context.h" 296364d75008b4fa580c1cb47c59ba1cf3e0caa6cdBrian Paul#include "enums.h" 3028876dd511ec2c9d5f5500499201df2588e8c7f1Brian Paul#include "readpix.h" 3128876dd511ec2c9d5f5500499201df2588e8c7f1Brian Paul#include "framebuffer.h" 32751e10fc0106e929a54d055de7427b3d87a6ffa6Brian Paul#include "formats.h" 33d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul#include "format_unpack.h" 3428876dd511ec2c9d5f5500499201df2588e8c7f1Brian Paul#include "image.h" 350117da40cd7edd3d165bb28569c289b37eca12b9Vinson Lee#include "mtypes.h" 36d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul#include "pack.h" 37b70610b9823fc7dc3672735c11be1a75fbb1a2a4Brian Paul#include "pbo.h" 3828876dd511ec2c9d5f5500499201df2588e8c7f1Brian Paul#include "state.h" 399ad8f431b2a47060bf05517246ab0fa8d249c800Jordan Justen#include "glformats.h" 40284ad9c3b29a6d6f0bade050ea9e949d67967983Paul Berry#include "fbobject.h" 41b7c7e5e45a14ed78eda104ebca25072172730645Ian Romanick#include "teximage.h" 4228876dd511ec2c9d5f5500499201df2588e8c7f1Brian Paul 43b7c7e5e45a14ed78eda104ebca25072172730645Ian Romanick/* Inexplicably, GL_HALF_FLOAT_OES has a different value than GL_HALF_FLOAT. 44b7c7e5e45a14ed78eda104ebca25072172730645Ian Romanick */ 45b7c7e5e45a14ed78eda104ebca25072172730645Ian Romanick#ifndef GL_HALF_FLOAT_OES 46b7c7e5e45a14ed78eda104ebca25072172730645Ian Romanick#define GL_HALF_FLOAT_OES 0x8D61 47b7c7e5e45a14ed78eda104ebca25072172730645Ian Romanick#endif 4828876dd511ec2c9d5f5500499201df2588e8c7f1Brian Paul 4928876dd511ec2c9d5f5500499201df2588e8c7f1Brian Paul/** 50d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul * Tries to implement glReadPixels() of GL_DEPTH_COMPONENT using memcpy of the 51d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul * mapping. 52d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul */ 53d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paulstatic GLboolean 54d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paulfast_read_depth_pixels( struct gl_context *ctx, 55d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul GLint x, GLint y, 56d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul GLsizei width, GLsizei height, 57d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul GLenum type, GLvoid *pixels, 58d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul const struct gl_pixelstore_attrib *packing ) 59d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul{ 60d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul struct gl_framebuffer *fb = ctx->ReadBuffer; 61d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul struct gl_renderbuffer *rb = fb->Attachment[BUFFER_DEPTH].Renderbuffer; 62d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul GLubyte *map, *dst; 63d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul int stride, dstStride, j; 64d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 65d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul if (ctx->Pixel.DepthScale != 1.0 || ctx->Pixel.DepthBias != 0.0) 66d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul return GL_FALSE; 67d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 68d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul if (packing->SwapBytes) 69d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul return GL_FALSE; 70d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 71755f0a0a02c5cf3be7e69ad51b411711fcc0bc27Eric Anholt if (_mesa_get_format_datatype(rb->Format) != GL_UNSIGNED_NORMALIZED) 72d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul return GL_FALSE; 73d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 74d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul if (!((type == GL_UNSIGNED_SHORT && rb->Format == MESA_FORMAT_Z16) || 75d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul type == GL_UNSIGNED_INT)) 76d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul return GL_FALSE; 77d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 78d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT, 79d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul &map, &stride); 80d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 81038a7dfcaaa7a8e5e108e247b2ffd786b3b015a3Brian Paul if (!map) { 82038a7dfcaaa7a8e5e108e247b2ffd786b3b015a3Brian Paul _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels"); 83038a7dfcaaa7a8e5e108e247b2ffd786b3b015a3Brian Paul return GL_TRUE; /* don't bother trying the slow path */ 84038a7dfcaaa7a8e5e108e247b2ffd786b3b015a3Brian Paul } 85038a7dfcaaa7a8e5e108e247b2ffd786b3b015a3Brian Paul 86d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul dstStride = _mesa_image_row_stride(packing, width, GL_DEPTH_COMPONENT, type); 87d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul dst = (GLubyte *) _mesa_image_address2d(packing, pixels, width, height, 88d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul GL_DEPTH_COMPONENT, type, 0, 0); 89d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 90d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul for (j = 0; j < height; j++) { 91d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul if (type == GL_UNSIGNED_INT) { 92d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul _mesa_unpack_uint_z_row(rb->Format, width, map, (GLuint *)dst); 93d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul } else { 94d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul ASSERT(type == GL_UNSIGNED_SHORT && rb->Format == MESA_FORMAT_Z16); 95d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul memcpy(dst, map, width * 2); 96d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul } 97d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 98d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul map += stride; 99d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul dst += dstStride; 100d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul } 101d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul ctx->Driver.UnmapRenderbuffer(ctx, rb); 102d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 103d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul return GL_TRUE; 104d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul} 105d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 106d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul/** 107d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul * Read pixels for format=GL_DEPTH_COMPONENT. 108d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul */ 109d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paulstatic void 110d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paulread_depth_pixels( struct gl_context *ctx, 111d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul GLint x, GLint y, 112d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul GLsizei width, GLsizei height, 113d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul GLenum type, GLvoid *pixels, 114d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul const struct gl_pixelstore_attrib *packing ) 115d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul{ 116d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul struct gl_framebuffer *fb = ctx->ReadBuffer; 117d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul struct gl_renderbuffer *rb = fb->Attachment[BUFFER_DEPTH].Renderbuffer; 118d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul GLint j; 119d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul GLubyte *dst, *map; 120d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul int dstStride, stride; 121531eaca41b574071fd1a3c3b51f90082601867aeBrian Paul GLfloat *depthValues; 122d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 123d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul if (!rb) 124d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul return; 125d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 126d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul /* clipping should have been done already */ 127d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul ASSERT(x >= 0); 128d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul ASSERT(y >= 0); 129d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul ASSERT(x + width <= (GLint) rb->Width); 130d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul ASSERT(y + height <= (GLint) rb->Height); 131d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 132d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul if (fast_read_depth_pixels(ctx, x, y, width, height, type, pixels, packing)) 133d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul return; 134d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 135d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul dstStride = _mesa_image_row_stride(packing, width, GL_DEPTH_COMPONENT, type); 136d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul dst = (GLubyte *) _mesa_image_address2d(packing, pixels, width, height, 137d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul GL_DEPTH_COMPONENT, type, 0, 0); 138d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 139d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT, 140d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul &map, &stride); 141038a7dfcaaa7a8e5e108e247b2ffd786b3b015a3Brian Paul if (!map) { 142038a7dfcaaa7a8e5e108e247b2ffd786b3b015a3Brian Paul _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels"); 143038a7dfcaaa7a8e5e108e247b2ffd786b3b015a3Brian Paul return; 144038a7dfcaaa7a8e5e108e247b2ffd786b3b015a3Brian Paul } 145d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 146531eaca41b574071fd1a3c3b51f90082601867aeBrian Paul depthValues = (GLfloat *) malloc(width * sizeof(GLfloat)); 147d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 148531eaca41b574071fd1a3c3b51f90082601867aeBrian Paul if (depthValues) { 149531eaca41b574071fd1a3c3b51f90082601867aeBrian Paul /* General case (slower) */ 150531eaca41b574071fd1a3c3b51f90082601867aeBrian Paul for (j = 0; j < height; j++, y++) { 151531eaca41b574071fd1a3c3b51f90082601867aeBrian Paul _mesa_unpack_float_z_row(rb->Format, width, map, depthValues); 152531eaca41b574071fd1a3c3b51f90082601867aeBrian Paul _mesa_pack_depth_span(ctx, width, dst, type, depthValues, packing); 153531eaca41b574071fd1a3c3b51f90082601867aeBrian Paul 154531eaca41b574071fd1a3c3b51f90082601867aeBrian Paul dst += dstStride; 155531eaca41b574071fd1a3c3b51f90082601867aeBrian Paul map += stride; 156531eaca41b574071fd1a3c3b51f90082601867aeBrian Paul } 157531eaca41b574071fd1a3c3b51f90082601867aeBrian Paul } 158531eaca41b574071fd1a3c3b51f90082601867aeBrian Paul else { 159531eaca41b574071fd1a3c3b51f90082601867aeBrian Paul _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels"); 160d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul } 161d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 162531eaca41b574071fd1a3c3b51f90082601867aeBrian Paul free(depthValues); 163531eaca41b574071fd1a3c3b51f90082601867aeBrian Paul 164d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul ctx->Driver.UnmapRenderbuffer(ctx, rb); 165d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul} 166d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 167d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 168d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul/** 169d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul * Read pixels for format=GL_STENCIL_INDEX. 170d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul */ 171d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paulstatic void 172d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paulread_stencil_pixels( struct gl_context *ctx, 173d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul GLint x, GLint y, 174d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul GLsizei width, GLsizei height, 175d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul GLenum type, GLvoid *pixels, 176d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul const struct gl_pixelstore_attrib *packing ) 177d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul{ 178d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul struct gl_framebuffer *fb = ctx->ReadBuffer; 179d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul struct gl_renderbuffer *rb = fb->Attachment[BUFFER_STENCIL].Renderbuffer; 180d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul GLint j; 181531eaca41b574071fd1a3c3b51f90082601867aeBrian Paul GLubyte *map, *stencil; 182d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul GLint stride; 183d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 184d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul if (!rb) 185d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul return; 186d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 187d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT, 188d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul &map, &stride); 189038a7dfcaaa7a8e5e108e247b2ffd786b3b015a3Brian Paul if (!map) { 190038a7dfcaaa7a8e5e108e247b2ffd786b3b015a3Brian Paul _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels"); 191038a7dfcaaa7a8e5e108e247b2ffd786b3b015a3Brian Paul return; 192038a7dfcaaa7a8e5e108e247b2ffd786b3b015a3Brian Paul } 193d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 194531eaca41b574071fd1a3c3b51f90082601867aeBrian Paul stencil = (GLubyte *) malloc(width * sizeof(GLubyte)); 195d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 196531eaca41b574071fd1a3c3b51f90082601867aeBrian Paul if (stencil) { 197531eaca41b574071fd1a3c3b51f90082601867aeBrian Paul /* process image row by row */ 198531eaca41b574071fd1a3c3b51f90082601867aeBrian Paul for (j = 0; j < height; j++) { 199531eaca41b574071fd1a3c3b51f90082601867aeBrian Paul GLvoid *dest; 200d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 201531eaca41b574071fd1a3c3b51f90082601867aeBrian Paul _mesa_unpack_ubyte_stencil_row(rb->Format, width, map, stencil); 202531eaca41b574071fd1a3c3b51f90082601867aeBrian Paul dest = _mesa_image_address2d(packing, pixels, width, height, 203531eaca41b574071fd1a3c3b51f90082601867aeBrian Paul GL_STENCIL_INDEX, type, j, 0); 204d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 205531eaca41b574071fd1a3c3b51f90082601867aeBrian Paul _mesa_pack_stencil_span(ctx, width, type, dest, stencil, packing); 206531eaca41b574071fd1a3c3b51f90082601867aeBrian Paul 207531eaca41b574071fd1a3c3b51f90082601867aeBrian Paul map += stride; 208531eaca41b574071fd1a3c3b51f90082601867aeBrian Paul } 209531eaca41b574071fd1a3c3b51f90082601867aeBrian Paul } 210531eaca41b574071fd1a3c3b51f90082601867aeBrian Paul else { 211531eaca41b574071fd1a3c3b51f90082601867aeBrian Paul _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels"); 212d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul } 213d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 214531eaca41b574071fd1a3c3b51f90082601867aeBrian Paul free(stencil); 215531eaca41b574071fd1a3c3b51f90082601867aeBrian Paul 216d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul ctx->Driver.UnmapRenderbuffer(ctx, rb); 217d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul} 218d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 219a5e95a419e4f6ad93e35a960113d97ae2de27476Brian Paul 220a5e95a419e4f6ad93e35a960113d97ae2de27476Brian Paul/** 221a5e95a419e4f6ad93e35a960113d97ae2de27476Brian Paul * Try to do glReadPixels of RGBA data using a simple memcpy or swizzle. 222a5e95a419e4f6ad93e35a960113d97ae2de27476Brian Paul * \return GL_TRUE if successful, GL_FALSE otherwise (use the slow path) 223a5e95a419e4f6ad93e35a960113d97ae2de27476Brian Paul */ 224d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paulstatic GLboolean 225d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paulfast_read_rgba_pixels_memcpy( struct gl_context *ctx, 226d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul GLint x, GLint y, 227d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul GLsizei width, GLsizei height, 228d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul GLenum format, GLenum type, 229d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul GLvoid *pixels, 230d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul const struct gl_pixelstore_attrib *packing, 231d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul GLbitfield transferOps ) 232d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul{ 233d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorReadBuffer; 234d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul GLubyte *dst, *map; 235d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul int dstStride, stride, j, texelBytes; 236a5e95a419e4f6ad93e35a960113d97ae2de27476Brian Paul GLboolean swizzle_rb = GL_FALSE, copy_xrgb = GL_FALSE; 237a5e95a419e4f6ad93e35a960113d97ae2de27476Brian Paul 238a5e95a419e4f6ad93e35a960113d97ae2de27476Brian Paul /* XXX we could check for other swizzle/special cases here as needed */ 239a5e95a419e4f6ad93e35a960113d97ae2de27476Brian Paul if (rb->Format == MESA_FORMAT_RGBA8888_REV && 240a5e95a419e4f6ad93e35a960113d97ae2de27476Brian Paul format == GL_BGRA && 241a5e95a419e4f6ad93e35a960113d97ae2de27476Brian Paul type == GL_UNSIGNED_INT_8_8_8_8_REV && 242a5e95a419e4f6ad93e35a960113d97ae2de27476Brian Paul !ctx->Pack.SwapBytes) { 243a5e95a419e4f6ad93e35a960113d97ae2de27476Brian Paul swizzle_rb = GL_TRUE; 244a5e95a419e4f6ad93e35a960113d97ae2de27476Brian Paul } 245a5e95a419e4f6ad93e35a960113d97ae2de27476Brian Paul else if (rb->Format == MESA_FORMAT_XRGB8888 && 246a5e95a419e4f6ad93e35a960113d97ae2de27476Brian Paul format == GL_BGRA && 247a5e95a419e4f6ad93e35a960113d97ae2de27476Brian Paul type == GL_UNSIGNED_INT_8_8_8_8_REV && 248a5e95a419e4f6ad93e35a960113d97ae2de27476Brian Paul !ctx->Pack.SwapBytes) { 249a5e95a419e4f6ad93e35a960113d97ae2de27476Brian Paul copy_xrgb = GL_TRUE; 250a5e95a419e4f6ad93e35a960113d97ae2de27476Brian Paul } 251a5e95a419e4f6ad93e35a960113d97ae2de27476Brian Paul else if (!_mesa_format_matches_format_and_type(rb->Format, format, type, 252a5e95a419e4f6ad93e35a960113d97ae2de27476Brian Paul ctx->Pack.SwapBytes)) 253d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul return GL_FALSE; 254d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 255d9c42097770f173804c7c7c40bf8bc6c4400673bNeil Roberts /* If the format is unsigned normalized then we can ignore clamping 256d9c42097770f173804c7c7c40bf8bc6c4400673bNeil Roberts * because the values are already in the range [0,1] so it won't 257d9c42097770f173804c7c7c40bf8bc6c4400673bNeil Roberts * have any effect anyway. 258d9c42097770f173804c7c7c40bf8bc6c4400673bNeil Roberts */ 259d9c42097770f173804c7c7c40bf8bc6c4400673bNeil Roberts if (_mesa_get_format_datatype(rb->Format) == GL_UNSIGNED_NORMALIZED) 260d9c42097770f173804c7c7c40bf8bc6c4400673bNeil Roberts transferOps &= ~IMAGE_CLAMP_BIT; 261d9c42097770f173804c7c7c40bf8bc6c4400673bNeil Roberts 262d9c42097770f173804c7c7c40bf8bc6c4400673bNeil Roberts if (transferOps) 263d9c42097770f173804c7c7c40bf8bc6c4400673bNeil Roberts return GL_FALSE; 264d9c42097770f173804c7c7c40bf8bc6c4400673bNeil Roberts 265d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul dstStride = _mesa_image_row_stride(packing, width, format, type); 266d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul dst = (GLubyte *) _mesa_image_address2d(packing, pixels, width, height, 267d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul format, type, 0, 0); 268d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 269d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT, 270d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul &map, &stride); 271038a7dfcaaa7a8e5e108e247b2ffd786b3b015a3Brian Paul if (!map) { 272038a7dfcaaa7a8e5e108e247b2ffd786b3b015a3Brian Paul _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels"); 273038a7dfcaaa7a8e5e108e247b2ffd786b3b015a3Brian Paul return GL_TRUE; /* don't bother trying the slow path */ 274038a7dfcaaa7a8e5e108e247b2ffd786b3b015a3Brian Paul } 275d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 276d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul texelBytes = _mesa_get_format_bytes(rb->Format); 277a5e95a419e4f6ad93e35a960113d97ae2de27476Brian Paul 278a5e95a419e4f6ad93e35a960113d97ae2de27476Brian Paul if (swizzle_rb) { 279a5e95a419e4f6ad93e35a960113d97ae2de27476Brian Paul /* swap R/B */ 280a5e95a419e4f6ad93e35a960113d97ae2de27476Brian Paul for (j = 0; j < height; j++) { 281a5e95a419e4f6ad93e35a960113d97ae2de27476Brian Paul int i; 282a5e95a419e4f6ad93e35a960113d97ae2de27476Brian Paul for (i = 0; i < width; i++) { 283a5e95a419e4f6ad93e35a960113d97ae2de27476Brian Paul GLuint *dst4 = (GLuint *) dst, *map4 = (GLuint *) map; 284a5e95a419e4f6ad93e35a960113d97ae2de27476Brian Paul GLuint pixel = map4[i]; 285a5e95a419e4f6ad93e35a960113d97ae2de27476Brian Paul dst4[i] = (pixel & 0xff00ff00) 286a5e95a419e4f6ad93e35a960113d97ae2de27476Brian Paul | ((pixel & 0x00ff0000) >> 16) 287a5e95a419e4f6ad93e35a960113d97ae2de27476Brian Paul | ((pixel & 0x000000ff) << 16); 288a5e95a419e4f6ad93e35a960113d97ae2de27476Brian Paul } 289a5e95a419e4f6ad93e35a960113d97ae2de27476Brian Paul dst += dstStride; 290a5e95a419e4f6ad93e35a960113d97ae2de27476Brian Paul map += stride; 291a5e95a419e4f6ad93e35a960113d97ae2de27476Brian Paul } 292a5e95a419e4f6ad93e35a960113d97ae2de27476Brian Paul } else if (copy_xrgb) { 293a5e95a419e4f6ad93e35a960113d97ae2de27476Brian Paul /* convert xrgb -> argb */ 294a5e95a419e4f6ad93e35a960113d97ae2de27476Brian Paul for (j = 0; j < height; j++) { 295a5e95a419e4f6ad93e35a960113d97ae2de27476Brian Paul GLuint *dst4 = (GLuint *) dst, *map4 = (GLuint *) map; 296a5e95a419e4f6ad93e35a960113d97ae2de27476Brian Paul int i; 297a5e95a419e4f6ad93e35a960113d97ae2de27476Brian Paul for (i = 0; i < width; i++) { 298a5e95a419e4f6ad93e35a960113d97ae2de27476Brian Paul dst4[i] = map4[i] | 0xff000000; /* set A=0xff */ 299a5e95a419e4f6ad93e35a960113d97ae2de27476Brian Paul } 300a5e95a419e4f6ad93e35a960113d97ae2de27476Brian Paul dst += dstStride; 301a5e95a419e4f6ad93e35a960113d97ae2de27476Brian Paul map += stride; 302a5e95a419e4f6ad93e35a960113d97ae2de27476Brian Paul } 303a5e95a419e4f6ad93e35a960113d97ae2de27476Brian Paul } else { 304a5e95a419e4f6ad93e35a960113d97ae2de27476Brian Paul /* just memcpy */ 305a5e95a419e4f6ad93e35a960113d97ae2de27476Brian Paul for (j = 0; j < height; j++) { 306a5e95a419e4f6ad93e35a960113d97ae2de27476Brian Paul memcpy(dst, map, width * texelBytes); 307a5e95a419e4f6ad93e35a960113d97ae2de27476Brian Paul dst += dstStride; 308a5e95a419e4f6ad93e35a960113d97ae2de27476Brian Paul map += stride; 309a5e95a419e4f6ad93e35a960113d97ae2de27476Brian Paul } 310d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul } 311d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 312d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul ctx->Driver.UnmapRenderbuffer(ctx, rb); 313d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 314d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul return GL_TRUE; 315d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul} 316d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 31772fb25cefbf58d477d99ce2c986a703f1178cf59Brian Paulstatic void 318d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paulslow_read_rgba_pixels( struct gl_context *ctx, 319d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul GLint x, GLint y, 320d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul GLsizei width, GLsizei height, 321d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul GLenum format, GLenum type, 322d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul GLvoid *pixels, 323d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul const struct gl_pixelstore_attrib *packing, 324d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul GLbitfield transferOps ) 325d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul{ 326d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorReadBuffer; 327d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul const gl_format rbFormat = _mesa_get_srgb_format_linear(rb->Format); 328bf6aac24c1d77979280068787b5443dd5c049269Brian Paul void *rgba; 329d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul GLubyte *dst, *map; 330d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul int dstStride, stride, j; 3316671d0dad300e591ac7c0e5110c6778373d0149aJordan Justen GLboolean dst_is_integer = _mesa_is_enum_format_integer(format); 3326671d0dad300e591ac7c0e5110c6778373d0149aJordan Justen GLboolean dst_is_uint = _mesa_is_format_unsigned(rbFormat); 333d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 334d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul dstStride = _mesa_image_row_stride(packing, width, format, type); 335d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul dst = (GLubyte *) _mesa_image_address2d(packing, pixels, width, height, 336d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul format, type, 0, 0); 337d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 338d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT, 339d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul &map, &stride); 340038a7dfcaaa7a8e5e108e247b2ffd786b3b015a3Brian Paul if (!map) { 341038a7dfcaaa7a8e5e108e247b2ffd786b3b015a3Brian Paul _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels"); 342038a7dfcaaa7a8e5e108e247b2ffd786b3b015a3Brian Paul return; 343038a7dfcaaa7a8e5e108e247b2ffd786b3b015a3Brian Paul } 344d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 345bf6aac24c1d77979280068787b5443dd5c049269Brian Paul rgba = malloc(width * MAX_PIXEL_BYTES); 346bf6aac24c1d77979280068787b5443dd5c049269Brian Paul if (!rgba) 347bf6aac24c1d77979280068787b5443dd5c049269Brian Paul goto done; 348bf6aac24c1d77979280068787b5443dd5c049269Brian Paul 349d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul for (j = 0; j < height; j++) { 3506671d0dad300e591ac7c0e5110c6778373d0149aJordan Justen if (dst_is_integer) { 351301fba54452c01673bb9f105fbc3e68a704ad18aBrian Paul _mesa_unpack_uint_rgba_row(rbFormat, width, map, (GLuint (*)[4]) rgba); 352ad897fff7730298c21289768d9b1b55f3d166ac5Brian Paul _mesa_rebase_rgba_uint(width, (GLuint (*)[4]) rgba, 353ad897fff7730298c21289768d9b1b55f3d166ac5Brian Paul rb->_BaseFormat); 3546671d0dad300e591ac7c0e5110c6778373d0149aJordan Justen if (dst_is_uint) { 3556671d0dad300e591ac7c0e5110c6778373d0149aJordan Justen _mesa_pack_rgba_span_from_uints(ctx, width, (GLuint (*)[4]) rgba, format, 3566671d0dad300e591ac7c0e5110c6778373d0149aJordan Justen type, dst); 3576671d0dad300e591ac7c0e5110c6778373d0149aJordan Justen } else { 3586671d0dad300e591ac7c0e5110c6778373d0149aJordan Justen _mesa_pack_rgba_span_from_ints(ctx, width, (GLint (*)[4]) rgba, format, 3596671d0dad300e591ac7c0e5110c6778373d0149aJordan Justen type, dst); 3606671d0dad300e591ac7c0e5110c6778373d0149aJordan Justen } 361d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul } else { 362bf6aac24c1d77979280068787b5443dd5c049269Brian Paul _mesa_unpack_rgba_row(rbFormat, width, map, (GLfloat (*)[4]) rgba); 363ad897fff7730298c21289768d9b1b55f3d166ac5Brian Paul _mesa_rebase_rgba_float(width, (GLfloat (*)[4]) rgba, 364ad897fff7730298c21289768d9b1b55f3d166ac5Brian Paul rb->_BaseFormat); 365bf6aac24c1d77979280068787b5443dd5c049269Brian Paul _mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba, format, 366bf6aac24c1d77979280068787b5443dd5c049269Brian Paul type, dst, packing, transferOps); 367d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul } 368d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul dst += dstStride; 369d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul map += stride; 370d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul } 371d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 372bf6aac24c1d77979280068787b5443dd5c049269Brian Paul free(rgba); 373bf6aac24c1d77979280068787b5443dd5c049269Brian Paul 374bf6aac24c1d77979280068787b5443dd5c049269Brian Pauldone: 375d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul ctx->Driver.UnmapRenderbuffer(ctx, rb); 376d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul} 377d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 378d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul/* 379d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul * Read R, G, B, A, RGB, L, or LA pixels. 380d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul */ 381d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paulstatic void 382d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paulread_rgba_pixels( struct gl_context *ctx, 383d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul GLint x, GLint y, 384d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul GLsizei width, GLsizei height, 385d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul GLenum format, GLenum type, GLvoid *pixels, 386d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul const struct gl_pixelstore_attrib *packing ) 387d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul{ 388d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul GLbitfield transferOps = ctx->_ImageTransferState; 389d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul struct gl_framebuffer *fb = ctx->ReadBuffer; 390d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul struct gl_renderbuffer *rb = fb->_ColorReadBuffer; 391d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 392d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul if (!rb) 393d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul return; 394d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 395d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul if ((ctx->Color._ClampReadColor == GL_TRUE || type != GL_FLOAT) && 3969ad8f431b2a47060bf05517246ab0fa8d249c800Jordan Justen !_mesa_is_enum_format_integer(format)) { 397d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul transferOps |= IMAGE_CLAMP_BIT; 398d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul } 399d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 400d9c42097770f173804c7c7c40bf8bc6c4400673bNeil Roberts /* Try the optimized paths first. */ 401d9c42097770f173804c7c7c40bf8bc6c4400673bNeil Roberts if (fast_read_rgba_pixels_memcpy(ctx, x, y, width, height, 402d9c42097770f173804c7c7c40bf8bc6c4400673bNeil Roberts format, type, pixels, packing, 403d9c42097770f173804c7c7c40bf8bc6c4400673bNeil Roberts transferOps)) { 404d9c42097770f173804c7c7c40bf8bc6c4400673bNeil Roberts return; 405d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul } 406d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 407d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul slow_read_rgba_pixels(ctx, x, y, width, height, 408d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul format, type, pixels, packing, transferOps); 409d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul} 410d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 411d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul/** 412d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul * For a packed depth/stencil buffer being read as depth/stencil, just memcpy the 413d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul * data (possibly swapping 8/24 vs 24/8 as we go). 414d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul */ 415d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paulstatic GLboolean 416d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paulfast_read_depth_stencil_pixels(struct gl_context *ctx, 417d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul GLint x, GLint y, 418d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul GLsizei width, GLsizei height, 419d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul GLubyte *dst, int dstStride) 420d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul{ 421d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul struct gl_framebuffer *fb = ctx->ReadBuffer; 422d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul struct gl_renderbuffer *rb = fb->Attachment[BUFFER_DEPTH].Renderbuffer; 423d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul struct gl_renderbuffer *stencilRb = fb->Attachment[BUFFER_STENCIL].Renderbuffer; 424d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul GLubyte *map; 425d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul int stride, i; 426d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 427d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul if (rb != stencilRb) 428d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul return GL_FALSE; 429d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 430d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul if (rb->Format != MESA_FORMAT_Z24_S8 && 431d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul rb->Format != MESA_FORMAT_S8_Z24) 432d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul return GL_FALSE; 433d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 434d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT, 435d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul &map, &stride); 436038a7dfcaaa7a8e5e108e247b2ffd786b3b015a3Brian Paul if (!map) { 437038a7dfcaaa7a8e5e108e247b2ffd786b3b015a3Brian Paul _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels"); 438038a7dfcaaa7a8e5e108e247b2ffd786b3b015a3Brian Paul return GL_TRUE; /* don't bother trying the slow path */ 439038a7dfcaaa7a8e5e108e247b2ffd786b3b015a3Brian Paul } 440d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 441d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul for (i = 0; i < height; i++) { 442d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul _mesa_unpack_uint_24_8_depth_stencil_row(rb->Format, width, 443d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul map, (GLuint *)dst); 444d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul map += stride; 445d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul dst += dstStride; 446d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul } 447d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 448d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul ctx->Driver.UnmapRenderbuffer(ctx, rb); 449d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 450d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul return GL_TRUE; 451d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul} 452d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 453d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 454d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul/** 455d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul * For non-float-depth and stencil buffers being read as 24/8 depth/stencil, 456d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul * copy the integer data directly instead of converting depth to float and 457d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul * re-packing. 458d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul */ 459d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paulstatic GLboolean 460d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paulfast_read_depth_stencil_pixels_separate(struct gl_context *ctx, 461d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul GLint x, GLint y, 462d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul GLsizei width, GLsizei height, 463d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul uint32_t *dst, int dstStride) 464d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul{ 465d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul struct gl_framebuffer *fb = ctx->ReadBuffer; 466d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul struct gl_renderbuffer *depthRb = fb->Attachment[BUFFER_DEPTH].Renderbuffer; 467d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul struct gl_renderbuffer *stencilRb = fb->Attachment[BUFFER_STENCIL].Renderbuffer; 468531eaca41b574071fd1a3c3b51f90082601867aeBrian Paul GLubyte *depthMap, *stencilMap, *stencilVals; 469d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul int depthStride, stencilStride, i, j; 470d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 471755f0a0a02c5cf3be7e69ad51b411711fcc0bc27Eric Anholt if (_mesa_get_format_datatype(depthRb->Format) != GL_UNSIGNED_NORMALIZED) 472d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul return GL_FALSE; 473d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 474d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul ctx->Driver.MapRenderbuffer(ctx, depthRb, x, y, width, height, 475d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul GL_MAP_READ_BIT, &depthMap, &depthStride); 476038a7dfcaaa7a8e5e108e247b2ffd786b3b015a3Brian Paul if (!depthMap) { 477038a7dfcaaa7a8e5e108e247b2ffd786b3b015a3Brian Paul _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels"); 478038a7dfcaaa7a8e5e108e247b2ffd786b3b015a3Brian Paul return GL_TRUE; /* don't bother trying the slow path */ 479038a7dfcaaa7a8e5e108e247b2ffd786b3b015a3Brian Paul } 480038a7dfcaaa7a8e5e108e247b2ffd786b3b015a3Brian Paul 481d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul ctx->Driver.MapRenderbuffer(ctx, stencilRb, x, y, width, height, 482d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul GL_MAP_READ_BIT, &stencilMap, &stencilStride); 483038a7dfcaaa7a8e5e108e247b2ffd786b3b015a3Brian Paul if (!stencilMap) { 484038a7dfcaaa7a8e5e108e247b2ffd786b3b015a3Brian Paul ctx->Driver.UnmapRenderbuffer(ctx, depthRb); 485038a7dfcaaa7a8e5e108e247b2ffd786b3b015a3Brian Paul _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels"); 486038a7dfcaaa7a8e5e108e247b2ffd786b3b015a3Brian Paul return GL_TRUE; /* don't bother trying the slow path */ 487038a7dfcaaa7a8e5e108e247b2ffd786b3b015a3Brian Paul } 488d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 489531eaca41b574071fd1a3c3b51f90082601867aeBrian Paul stencilVals = (GLubyte *) malloc(width * sizeof(GLubyte)); 490d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 491531eaca41b574071fd1a3c3b51f90082601867aeBrian Paul if (stencilVals) { 492531eaca41b574071fd1a3c3b51f90082601867aeBrian Paul for (j = 0; j < height; j++) { 493531eaca41b574071fd1a3c3b51f90082601867aeBrian Paul _mesa_unpack_uint_z_row(depthRb->Format, width, depthMap, dst); 494531eaca41b574071fd1a3c3b51f90082601867aeBrian Paul _mesa_unpack_ubyte_stencil_row(stencilRb->Format, width, 495531eaca41b574071fd1a3c3b51f90082601867aeBrian Paul stencilMap, stencilVals); 496d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 497531eaca41b574071fd1a3c3b51f90082601867aeBrian Paul for (i = 0; i < width; i++) { 498531eaca41b574071fd1a3c3b51f90082601867aeBrian Paul dst[i] = (dst[i] & 0xffffff00) | stencilVals[i]; 499531eaca41b574071fd1a3c3b51f90082601867aeBrian Paul } 500d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 501531eaca41b574071fd1a3c3b51f90082601867aeBrian Paul depthMap += depthStride; 502531eaca41b574071fd1a3c3b51f90082601867aeBrian Paul stencilMap += stencilStride; 503531eaca41b574071fd1a3c3b51f90082601867aeBrian Paul dst += dstStride / 4; 504531eaca41b574071fd1a3c3b51f90082601867aeBrian Paul } 505d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul } 506531eaca41b574071fd1a3c3b51f90082601867aeBrian Paul else { 507531eaca41b574071fd1a3c3b51f90082601867aeBrian Paul _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels"); 508531eaca41b574071fd1a3c3b51f90082601867aeBrian Paul } 509531eaca41b574071fd1a3c3b51f90082601867aeBrian Paul 510531eaca41b574071fd1a3c3b51f90082601867aeBrian Paul free(stencilVals); 511d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 512d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul ctx->Driver.UnmapRenderbuffer(ctx, depthRb); 513d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul ctx->Driver.UnmapRenderbuffer(ctx, stencilRb); 514d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 515d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul return GL_TRUE; 516d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul} 517d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 518d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paulstatic void 519d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paulslow_read_depth_stencil_pixels_separate(struct gl_context *ctx, 520d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul GLint x, GLint y, 521d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul GLsizei width, GLsizei height, 522d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul GLenum type, 523d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul const struct gl_pixelstore_attrib *packing, 524d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul GLubyte *dst, int dstStride) 525d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul{ 526d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul struct gl_framebuffer *fb = ctx->ReadBuffer; 527d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul struct gl_renderbuffer *depthRb = fb->Attachment[BUFFER_DEPTH].Renderbuffer; 528d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul struct gl_renderbuffer *stencilRb = fb->Attachment[BUFFER_STENCIL].Renderbuffer; 529d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul GLubyte *depthMap, *stencilMap; 530d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul int depthStride, stencilStride, j; 531531eaca41b574071fd1a3c3b51f90082601867aeBrian Paul GLubyte *stencilVals; 532531eaca41b574071fd1a3c3b51f90082601867aeBrian Paul GLfloat *depthVals; 533531eaca41b574071fd1a3c3b51f90082601867aeBrian Paul 534d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 535f6a50c0b1ff620d1b721968144a56452c0bd6d85Brian Paul /* The depth and stencil buffers might be separate, or a single buffer. 536f6a50c0b1ff620d1b721968144a56452c0bd6d85Brian Paul * If one buffer, only map it once. 537f6a50c0b1ff620d1b721968144a56452c0bd6d85Brian Paul */ 538d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul ctx->Driver.MapRenderbuffer(ctx, depthRb, x, y, width, height, 539d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul GL_MAP_READ_BIT, &depthMap, &depthStride); 540038a7dfcaaa7a8e5e108e247b2ffd786b3b015a3Brian Paul if (!depthMap) { 541038a7dfcaaa7a8e5e108e247b2ffd786b3b015a3Brian Paul _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels"); 542038a7dfcaaa7a8e5e108e247b2ffd786b3b015a3Brian Paul return; 543038a7dfcaaa7a8e5e108e247b2ffd786b3b015a3Brian Paul } 544038a7dfcaaa7a8e5e108e247b2ffd786b3b015a3Brian Paul 545f6a50c0b1ff620d1b721968144a56452c0bd6d85Brian Paul if (stencilRb != depthRb) { 546f6a50c0b1ff620d1b721968144a56452c0bd6d85Brian Paul ctx->Driver.MapRenderbuffer(ctx, stencilRb, x, y, width, height, 547f6a50c0b1ff620d1b721968144a56452c0bd6d85Brian Paul GL_MAP_READ_BIT, &stencilMap, 548f6a50c0b1ff620d1b721968144a56452c0bd6d85Brian Paul &stencilStride); 549038a7dfcaaa7a8e5e108e247b2ffd786b3b015a3Brian Paul if (!stencilMap) { 550038a7dfcaaa7a8e5e108e247b2ffd786b3b015a3Brian Paul ctx->Driver.UnmapRenderbuffer(ctx, depthRb); 551038a7dfcaaa7a8e5e108e247b2ffd786b3b015a3Brian Paul _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels"); 552038a7dfcaaa7a8e5e108e247b2ffd786b3b015a3Brian Paul return; 553038a7dfcaaa7a8e5e108e247b2ffd786b3b015a3Brian Paul } 554f6a50c0b1ff620d1b721968144a56452c0bd6d85Brian Paul } 555f4c03da3276bee39802236c21a0b5a31f05e2541Brian Paul else { 556f4c03da3276bee39802236c21a0b5a31f05e2541Brian Paul stencilMap = depthMap; 557f4c03da3276bee39802236c21a0b5a31f05e2541Brian Paul stencilStride = depthStride; 558f4c03da3276bee39802236c21a0b5a31f05e2541Brian Paul } 559d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 560531eaca41b574071fd1a3c3b51f90082601867aeBrian Paul stencilVals = (GLubyte *) malloc(width * sizeof(GLubyte)); 561531eaca41b574071fd1a3c3b51f90082601867aeBrian Paul depthVals = (GLfloat *) malloc(width * sizeof(GLfloat)); 562d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 563531eaca41b574071fd1a3c3b51f90082601867aeBrian Paul if (stencilVals && depthVals) { 564531eaca41b574071fd1a3c3b51f90082601867aeBrian Paul for (j = 0; j < height; j++) { 565531eaca41b574071fd1a3c3b51f90082601867aeBrian Paul _mesa_unpack_float_z_row(depthRb->Format, width, depthMap, depthVals); 566531eaca41b574071fd1a3c3b51f90082601867aeBrian Paul _mesa_unpack_ubyte_stencil_row(stencilRb->Format, width, 567531eaca41b574071fd1a3c3b51f90082601867aeBrian Paul stencilMap, stencilVals); 568d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 569531eaca41b574071fd1a3c3b51f90082601867aeBrian Paul _mesa_pack_depth_stencil_span(ctx, width, type, (GLuint *)dst, 570531eaca41b574071fd1a3c3b51f90082601867aeBrian Paul depthVals, stencilVals, packing); 571d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 572531eaca41b574071fd1a3c3b51f90082601867aeBrian Paul depthMap += depthStride; 573531eaca41b574071fd1a3c3b51f90082601867aeBrian Paul stencilMap += stencilStride; 574531eaca41b574071fd1a3c3b51f90082601867aeBrian Paul dst += dstStride; 575531eaca41b574071fd1a3c3b51f90082601867aeBrian Paul } 576d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul } 577531eaca41b574071fd1a3c3b51f90082601867aeBrian Paul else { 578531eaca41b574071fd1a3c3b51f90082601867aeBrian Paul _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels"); 579531eaca41b574071fd1a3c3b51f90082601867aeBrian Paul } 580531eaca41b574071fd1a3c3b51f90082601867aeBrian Paul 581531eaca41b574071fd1a3c3b51f90082601867aeBrian Paul free(stencilVals); 582531eaca41b574071fd1a3c3b51f90082601867aeBrian Paul free(depthVals); 583d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 584d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul ctx->Driver.UnmapRenderbuffer(ctx, depthRb); 585f6a50c0b1ff620d1b721968144a56452c0bd6d85Brian Paul if (stencilRb != depthRb) { 586f6a50c0b1ff620d1b721968144a56452c0bd6d85Brian Paul ctx->Driver.UnmapRenderbuffer(ctx, stencilRb); 587f6a50c0b1ff620d1b721968144a56452c0bd6d85Brian Paul } 588d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul} 589d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 590d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 591d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul/** 592d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul * Read combined depth/stencil values. 593d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul * We'll have already done error checking to be sure the expected 594d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul * depth and stencil buffers really exist. 595d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul */ 596d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paulstatic void 597d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paulread_depth_stencil_pixels(struct gl_context *ctx, 598d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul GLint x, GLint y, 599d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul GLsizei width, GLsizei height, 600d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul GLenum type, GLvoid *pixels, 601d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul const struct gl_pixelstore_attrib *packing ) 602d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul{ 603d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul const GLboolean scaleOrBias 604d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul = ctx->Pixel.DepthScale != 1.0 || ctx->Pixel.DepthBias != 0.0; 605d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul const GLboolean stencilTransfer = ctx->Pixel.IndexShift 606d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul || ctx->Pixel.IndexOffset || ctx->Pixel.MapStencilFlag; 607d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul GLubyte *dst; 608d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul int dstStride; 609d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 610d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul dst = (GLubyte *) _mesa_image_address2d(packing, pixels, 611d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul width, height, 612d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul GL_DEPTH_STENCIL_EXT, 613d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul type, 0, 0); 614d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul dstStride = _mesa_image_row_stride(packing, width, 615d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul GL_DEPTH_STENCIL_EXT, type); 616d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 617d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul /* Fast 24/8 reads. */ 618d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul if (type == GL_UNSIGNED_INT_24_8 && 619d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul !scaleOrBias && !stencilTransfer && !packing->SwapBytes) { 620d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul if (fast_read_depth_stencil_pixels(ctx, x, y, width, height, 621d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul dst, dstStride)) 622d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul return; 623d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 624d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul if (fast_read_depth_stencil_pixels_separate(ctx, x, y, width, height, 625d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul (uint32_t *)dst, dstStride)) 626d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul return; 627d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul } 628d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 629d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul slow_read_depth_stencil_pixels_separate(ctx, x, y, width, height, 630d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul type, packing, 631d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul dst, dstStride); 632d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul} 633d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 634d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 635d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 636d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul/** 637d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul * Software fallback routine for ctx->Driver.ReadPixels(). 638d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul * By time we get here, all error checking will have been done. 639d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul */ 640d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paulvoid 641d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul_mesa_readpixels(struct gl_context *ctx, 642d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul GLint x, GLint y, GLsizei width, GLsizei height, 643d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul GLenum format, GLenum type, 644d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul const struct gl_pixelstore_attrib *packing, 645d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul GLvoid *pixels) 646d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul{ 647d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul struct gl_pixelstore_attrib clippedPacking = *packing; 648d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 649d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul if (ctx->NewState) 650d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul _mesa_update_state(ctx); 651d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 652d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul /* Do all needed clipping here, so that we can forget about it later */ 653d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul if (_mesa_clip_readpixels(ctx, &x, &y, &width, &height, &clippedPacking)) { 654d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 655d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul pixels = _mesa_map_pbo_dest(ctx, &clippedPacking, pixels); 656d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 657d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul if (pixels) { 658d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul switch (format) { 659d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul case GL_STENCIL_INDEX: 660d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul read_stencil_pixels(ctx, x, y, width, height, type, pixels, 661d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul &clippedPacking); 662d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul break; 663d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul case GL_DEPTH_COMPONENT: 664d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul read_depth_pixels(ctx, x, y, width, height, type, pixels, 665d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul &clippedPacking); 666d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul break; 667d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul case GL_DEPTH_STENCIL_EXT: 668d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul read_depth_stencil_pixels(ctx, x, y, width, height, type, pixels, 669d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul &clippedPacking); 670d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul break; 671d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul default: 672d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul /* all other formats should be color formats */ 673d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul read_rgba_pixels(ctx, x, y, width, height, format, type, pixels, 674d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul &clippedPacking); 675d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul } 676d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 677d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul _mesa_unmap_pbo_dest(ctx, &clippedPacking); 678d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul } 679d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul } 680d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul} 681d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 682d2a23d4ded958ceb480c97a303003ea009d5fd41Brian Paul 68328876dd511ec2c9d5f5500499201df2588e8c7f1Brian Paulvoid GLAPIENTRY 6846b329b9274b18c50f4177eef7ee087d50ebc1525Brian Paul_mesa_ReadnPixelsARB( GLint x, GLint y, GLsizei width, GLsizei height, 6856b329b9274b18c50f4177eef7ee087d50ebc1525Brian Paul GLenum format, GLenum type, GLsizei bufSize, 6866b329b9274b18c50f4177eef7ee087d50ebc1525Brian Paul GLvoid *pixels ) 68728876dd511ec2c9d5f5500499201df2588e8c7f1Brian Paul{ 688b8f7eef4ef84d53d32d08a70dc7daec623cf7eabBrian Paul GLenum err; 689b8f7eef4ef84d53d32d08a70dc7daec623cf7eabBrian Paul 69028876dd511ec2c9d5f5500499201df2588e8c7f1Brian Paul GET_CURRENT_CONTEXT(ctx); 69128876dd511ec2c9d5f5500499201df2588e8c7f1Brian Paul ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 69228876dd511ec2c9d5f5500499201df2588e8c7f1Brian Paul 69328876dd511ec2c9d5f5500499201df2588e8c7f1Brian Paul FLUSH_CURRENT(ctx, 0); 69428876dd511ec2c9d5f5500499201df2588e8c7f1Brian Paul 6956364d75008b4fa580c1cb47c59ba1cf3e0caa6cdBrian Paul if (MESA_VERBOSE & VERBOSE_API) 6966364d75008b4fa580c1cb47c59ba1cf3e0caa6cdBrian Paul _mesa_debug(ctx, "glReadPixels(%d, %d, %s, %s, %p)\n", 6976364d75008b4fa580c1cb47c59ba1cf3e0caa6cdBrian Paul width, height, 6986364d75008b4fa580c1cb47c59ba1cf3e0caa6cdBrian Paul _mesa_lookup_enum_by_nr(format), 6996364d75008b4fa580c1cb47c59ba1cf3e0caa6cdBrian Paul _mesa_lookup_enum_by_nr(type), 7006364d75008b4fa580c1cb47c59ba1cf3e0caa6cdBrian Paul pixels); 7016364d75008b4fa580c1cb47c59ba1cf3e0caa6cdBrian Paul 70228876dd511ec2c9d5f5500499201df2588e8c7f1Brian Paul if (width < 0 || height < 0) { 70328876dd511ec2c9d5f5500499201df2588e8c7f1Brian Paul _mesa_error( ctx, GL_INVALID_VALUE, 70428876dd511ec2c9d5f5500499201df2588e8c7f1Brian Paul "glReadPixels(width=%d height=%d)", width, height ); 70528876dd511ec2c9d5f5500499201df2588e8c7f1Brian Paul return; 70628876dd511ec2c9d5f5500499201df2588e8c7f1Brian Paul } 70728876dd511ec2c9d5f5500499201df2588e8c7f1Brian Paul 708b7c7e5e45a14ed78eda104ebca25072172730645Ian Romanick /* OpenGL ES 1.x and OpenGL ES 2.0 impose additional restrictions on the 709b7c7e5e45a14ed78eda104ebca25072172730645Ian Romanick * combinations of format and type that can be used. 710b7c7e5e45a14ed78eda104ebca25072172730645Ian Romanick * 711b7c7e5e45a14ed78eda104ebca25072172730645Ian Romanick * Technically, only two combinations are actually allowed: 712b7c7e5e45a14ed78eda104ebca25072172730645Ian Romanick * GL_RGBA/GL_UNSIGNED_BYTE, and some implementation-specific internal 713b7c7e5e45a14ed78eda104ebca25072172730645Ian Romanick * preferred combination. This code doesn't know what that preferred 714b7c7e5e45a14ed78eda104ebca25072172730645Ian Romanick * combination is, and Mesa can handle anything valid. Just work instead. 715b7c7e5e45a14ed78eda104ebca25072172730645Ian Romanick */ 716b7c7e5e45a14ed78eda104ebca25072172730645Ian Romanick if (_mesa_is_gles(ctx) && ctx->Version < 30) { 717b7c7e5e45a14ed78eda104ebca25072172730645Ian Romanick err = _mesa_es_error_check_format_and_type(format, type, 2); 718b7c7e5e45a14ed78eda104ebca25072172730645Ian Romanick if (err == GL_NO_ERROR) { 719b7c7e5e45a14ed78eda104ebca25072172730645Ian Romanick if (type == GL_FLOAT || type == GL_HALF_FLOAT_OES) { 720b7c7e5e45a14ed78eda104ebca25072172730645Ian Romanick err = GL_INVALID_OPERATION; 721b7c7e5e45a14ed78eda104ebca25072172730645Ian Romanick } else if (format == GL_DEPTH_COMPONENT 722b7c7e5e45a14ed78eda104ebca25072172730645Ian Romanick || format == GL_DEPTH_STENCIL) { 723b7c7e5e45a14ed78eda104ebca25072172730645Ian Romanick err = GL_INVALID_ENUM; 724b7c7e5e45a14ed78eda104ebca25072172730645Ian Romanick } 725b7c7e5e45a14ed78eda104ebca25072172730645Ian Romanick } 726b7c7e5e45a14ed78eda104ebca25072172730645Ian Romanick 727b7c7e5e45a14ed78eda104ebca25072172730645Ian Romanick if (err != GL_NO_ERROR) { 728b7c7e5e45a14ed78eda104ebca25072172730645Ian Romanick _mesa_error(ctx, err, "glReadPixels(invalid format %s and/or type %s)", 729b7c7e5e45a14ed78eda104ebca25072172730645Ian Romanick _mesa_lookup_enum_by_nr(format), 730b7c7e5e45a14ed78eda104ebca25072172730645Ian Romanick _mesa_lookup_enum_by_nr(type)); 731b7c7e5e45a14ed78eda104ebca25072172730645Ian Romanick return; 732b7c7e5e45a14ed78eda104ebca25072172730645Ian Romanick } 733b7c7e5e45a14ed78eda104ebca25072172730645Ian Romanick } 734b7c7e5e45a14ed78eda104ebca25072172730645Ian Romanick 73528876dd511ec2c9d5f5500499201df2588e8c7f1Brian Paul if (ctx->NewState) 73628876dd511ec2c9d5f5500499201df2588e8c7f1Brian Paul _mesa_update_state(ctx); 73728876dd511ec2c9d5f5500499201df2588e8c7f1Brian Paul 738b8f7eef4ef84d53d32d08a70dc7daec623cf7eabBrian Paul err = _mesa_error_check_format_and_type(ctx, format, type); 739b8f7eef4ef84d53d32d08a70dc7daec623cf7eabBrian Paul if (err != GL_NO_ERROR) { 740b8f7eef4ef84d53d32d08a70dc7daec623cf7eabBrian Paul _mesa_error(ctx, err, "glReadPixels(invalid format %s and/or type %s)", 741b8f7eef4ef84d53d32d08a70dc7daec623cf7eabBrian Paul _mesa_lookup_enum_by_nr(format), 742b8f7eef4ef84d53d32d08a70dc7daec623cf7eabBrian Paul _mesa_lookup_enum_by_nr(type)); 74328876dd511ec2c9d5f5500499201df2588e8c7f1Brian Paul return; 74428876dd511ec2c9d5f5500499201df2588e8c7f1Brian Paul } 74528876dd511ec2c9d5f5500499201df2588e8c7f1Brian Paul 7465a827d9a2b5d698fed98a5d62ff0292b48bdd6c7Eric Anholt if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { 7475a827d9a2b5d698fed98a5d62ff0292b48bdd6c7Eric Anholt _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, 7485a827d9a2b5d698fed98a5d62ff0292b48bdd6c7Eric Anholt "glReadPixels(incomplete framebuffer)" ); 7495a827d9a2b5d698fed98a5d62ff0292b48bdd6c7Eric Anholt return; 7505a827d9a2b5d698fed98a5d62ff0292b48bdd6c7Eric Anholt } 7515a827d9a2b5d698fed98a5d62ff0292b48bdd6c7Eric Anholt 752b683891fdabda6b8dcec655652c0709419d4922cEric Anholt if (_mesa_is_user_fbo(ctx->ReadBuffer) && 753b683891fdabda6b8dcec655652c0709419d4922cEric Anholt ctx->ReadBuffer->Visual.samples > 0) { 754b683891fdabda6b8dcec655652c0709419d4922cEric Anholt _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(multisample FBO)"); 755b683891fdabda6b8dcec655652c0709419d4922cEric Anholt return; 756b683891fdabda6b8dcec655652c0709419d4922cEric Anholt } 757b683891fdabda6b8dcec655652c0709419d4922cEric Anholt 758b683891fdabda6b8dcec655652c0709419d4922cEric Anholt if (!_mesa_source_buffer_exists(ctx, format)) { 759b683891fdabda6b8dcec655652c0709419d4922cEric Anholt _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(no readbuffer)"); 760b683891fdabda6b8dcec655652c0709419d4922cEric Anholt return; 761b683891fdabda6b8dcec655652c0709419d4922cEric Anholt } 762b683891fdabda6b8dcec655652c0709419d4922cEric Anholt 763751e10fc0106e929a54d055de7427b3d87a6ffa6Brian Paul /* Check that the destination format and source buffer are both 764751e10fc0106e929a54d055de7427b3d87a6ffa6Brian Paul * integer-valued or both non-integer-valued. 765751e10fc0106e929a54d055de7427b3d87a6ffa6Brian Paul */ 766751e10fc0106e929a54d055de7427b3d87a6ffa6Brian Paul if (ctx->Extensions.EXT_texture_integer && _mesa_is_color_format(format)) { 767751e10fc0106e929a54d055de7427b3d87a6ffa6Brian Paul const struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorReadBuffer; 768412b9608838b872bc294569b3ee913343a7e66f6Brian Paul const GLboolean srcInteger = _mesa_is_format_integer_color(rb->Format); 7699ad8f431b2a47060bf05517246ab0fa8d249c800Jordan Justen const GLboolean dstInteger = _mesa_is_enum_format_integer(format); 770751e10fc0106e929a54d055de7427b3d87a6ffa6Brian Paul if (dstInteger != srcInteger) { 771751e10fc0106e929a54d055de7427b3d87a6ffa6Brian Paul _mesa_error(ctx, GL_INVALID_OPERATION, 772751e10fc0106e929a54d055de7427b3d87a6ffa6Brian Paul "glReadPixels(integer / non-integer format mismatch"); 773751e10fc0106e929a54d055de7427b3d87a6ffa6Brian Paul return; 774751e10fc0106e929a54d055de7427b3d87a6ffa6Brian Paul } 775751e10fc0106e929a54d055de7427b3d87a6ffa6Brian Paul } 776751e10fc0106e929a54d055de7427b3d87a6ffa6Brian Paul 7777b9bf395433b5fa9d5a95186891a29d49e0b47c0Brian Paul if (width == 0 || height == 0) 7787b9bf395433b5fa9d5a95186891a29d49e0b47c0Brian Paul return; /* nothing to do */ 7797b9bf395433b5fa9d5a95186891a29d49e0b47c0Brian Paul 7806b329b9274b18c50f4177eef7ee087d50ebc1525Brian Paul if (!_mesa_validate_pbo_access(2, &ctx->Pack, width, height, 1, 7816b329b9274b18c50f4177eef7ee087d50ebc1525Brian Paul format, type, bufSize, pixels)) { 7826b329b9274b18c50f4177eef7ee087d50ebc1525Brian Paul if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { 78328876dd511ec2c9d5f5500499201df2588e8c7f1Brian Paul _mesa_error(ctx, GL_INVALID_OPERATION, 7846b329b9274b18c50f4177eef7ee087d50ebc1525Brian Paul "glReadPixels(out of bounds PBO access)"); 7856b329b9274b18c50f4177eef7ee087d50ebc1525Brian Paul } else { 7866b329b9274b18c50f4177eef7ee087d50ebc1525Brian Paul _mesa_error(ctx, GL_INVALID_OPERATION, 7876b329b9274b18c50f4177eef7ee087d50ebc1525Brian Paul "glReadnPixelsARB(out of bounds access:" 7886b329b9274b18c50f4177eef7ee087d50ebc1525Brian Paul " bufSize (%d) is too small)", bufSize); 78928876dd511ec2c9d5f5500499201df2588e8c7f1Brian Paul } 7906b329b9274b18c50f4177eef7ee087d50ebc1525Brian Paul return; 7916b329b9274b18c50f4177eef7ee087d50ebc1525Brian Paul } 79228876dd511ec2c9d5f5500499201df2588e8c7f1Brian Paul 7936b329b9274b18c50f4177eef7ee087d50ebc1525Brian Paul if (_mesa_is_bufferobj(ctx->Pack.BufferObj) && 7946b329b9274b18c50f4177eef7ee087d50ebc1525Brian Paul _mesa_bufferobj_mapped(ctx->Pack.BufferObj)) { 7956b329b9274b18c50f4177eef7ee087d50ebc1525Brian Paul /* buffer is mapped - that's an error */ 7966b329b9274b18c50f4177eef7ee087d50ebc1525Brian Paul _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(PBO is mapped)"); 7976b329b9274b18c50f4177eef7ee087d50ebc1525Brian Paul return; 79828876dd511ec2c9d5f5500499201df2588e8c7f1Brian Paul } 79928876dd511ec2c9d5f5500499201df2588e8c7f1Brian Paul 80028876dd511ec2c9d5f5500499201df2588e8c7f1Brian Paul ctx->Driver.ReadPixels(ctx, x, y, width, height, 80128876dd511ec2c9d5f5500499201df2588e8c7f1Brian Paul format, type, &ctx->Pack, pixels); 80228876dd511ec2c9d5f5500499201df2588e8c7f1Brian Paul} 8036b329b9274b18c50f4177eef7ee087d50ebc1525Brian Paul 8046b329b9274b18c50f4177eef7ee087d50ebc1525Brian Paulvoid GLAPIENTRY 8056b329b9274b18c50f4177eef7ee087d50ebc1525Brian Paul_mesa_ReadPixels( GLint x, GLint y, GLsizei width, GLsizei height, 8066b329b9274b18c50f4177eef7ee087d50ebc1525Brian Paul GLenum format, GLenum type, GLvoid *pixels ) 8076b329b9274b18c50f4177eef7ee087d50ebc1525Brian Paul{ 8086b329b9274b18c50f4177eef7ee087d50ebc1525Brian Paul _mesa_ReadnPixelsARB(x, y, width, height, format, type, INT_MAX, pixels); 8096b329b9274b18c50f4177eef7ee087d50ebc1525Brian Paul} 810