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