X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fmain%2Freadpix.c;h=b09cf54994a638c27e29da96b07640e62cd427f1;hb=de42431a9d761305c9911f30b5880a9a049a2d60;hp=7dc758152ec0973d81bce4387d15617a5cf555bc;hpb=b7c7e5e45a14ed78eda104ebca25072172730645;p=mesa.git diff --git a/src/mesa/main/readpix.c b/src/mesa/main/readpix.c index 7dc758152ec..b09cf54994a 100644 --- a/src/mesa/main/readpix.c +++ b/src/mesa/main/readpix.c @@ -1,6 +1,5 @@ /* * Mesa 3-D graphics library - * Version: 7.1 * * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. * @@ -17,13 +16,15 @@ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN - * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. */ #include "glheader.h" #include "imports.h" +#include "blend.h" #include "bufferobj.h" #include "context.h" #include "enums.h" @@ -38,20 +39,215 @@ #include "state.h" #include "glformats.h" #include "fbobject.h" -#include "teximage.h" -/* Inexplicably, GL_HALF_FLOAT_OES has a different value than GL_HALF_FLOAT. + +/** + * Return true if the conversion L=R+G+B is needed. */ -#ifndef GL_HALF_FLOAT_OES -#define GL_HALF_FLOAT_OES 0x8D61 -#endif +static GLboolean +need_rgb_to_luminance_conversion(mesa_format texFormat, GLenum format) +{ + GLenum baseTexFormat = _mesa_get_format_base_format(texFormat); + + return (baseTexFormat == GL_RG || + baseTexFormat == GL_RGB || + baseTexFormat == GL_RGBA) && + (format == GL_LUMINANCE || format == GL_LUMINANCE_ALPHA); +} + + +/** + * Return transfer op flags for this ReadPixels operation. + */ +static GLbitfield +get_readpixels_transfer_ops(const struct gl_context *ctx, mesa_format texFormat, + GLenum format, GLenum type, GLboolean uses_blit) +{ + GLbitfield transferOps = ctx->_ImageTransferState; + + if (format == GL_DEPTH_COMPONENT || + format == GL_DEPTH_STENCIL || + format == GL_STENCIL_INDEX) { + return 0; + } + + /* Pixel transfer ops (scale, bias, table lookup) do not apply + * to integer formats. + */ + if (_mesa_is_enum_format_integer(format)) { + return 0; + } + + if (uses_blit) { + /* For blit-based ReadPixels packing, the clamping is done automatically + * unless the type is float. */ + if (_mesa_get_clamp_read_color(ctx) && + (type == GL_FLOAT || type == GL_HALF_FLOAT)) { + transferOps |= IMAGE_CLAMP_BIT; + } + } + else { + /* For CPU-based ReadPixels packing, the clamping must always be done + * for non-float types, */ + if (_mesa_get_clamp_read_color(ctx) || + (type != GL_FLOAT && type != GL_HALF_FLOAT)) { + transferOps |= IMAGE_CLAMP_BIT; + } + } + + /* If the format is unsigned normalized, we can ignore clamping + * because the values are already in the range [0,1] so it won't + * have any effect anyway. + */ + if (_mesa_get_format_datatype(texFormat) == GL_UNSIGNED_NORMALIZED && + !need_rgb_to_luminance_conversion(texFormat, format)) { + transferOps &= ~IMAGE_CLAMP_BIT; + } + + return transferOps; +} + + +/** + * Return true if memcpy cannot be used for ReadPixels. + * + * If uses_blit is true, the function returns true if a simple 3D engine blit + * cannot be used for ReadPixels packing. + * + * NOTE: This doesn't take swizzling and format conversions between + * the readbuffer and the pixel pack buffer into account. + */ +GLboolean +_mesa_readpixels_needs_slow_path(const struct gl_context *ctx, GLenum format, + GLenum type, GLboolean uses_blit) +{ + struct gl_renderbuffer *rb = + _mesa_get_read_renderbuffer_for_format(ctx, format); + GLenum srcType; + + ASSERT(rb); + + /* There are different rules depending on the base format. */ + switch (format) { + case GL_DEPTH_STENCIL: + return !_mesa_has_depthstencil_combined(ctx->ReadBuffer) || + ctx->Pixel.DepthScale != 1.0f || ctx->Pixel.DepthBias != 0.0f || + ctx->Pixel.IndexShift || ctx->Pixel.IndexOffset || + ctx->Pixel.MapStencilFlag; + + case GL_DEPTH_COMPONENT: + return ctx->Pixel.DepthScale != 1.0f || ctx->Pixel.DepthBias != 0.0f; + + case GL_STENCIL_INDEX: + return ctx->Pixel.IndexShift || ctx->Pixel.IndexOffset || + ctx->Pixel.MapStencilFlag; + + default: + /* Color formats. */ + if (need_rgb_to_luminance_conversion(rb->Format, format)) { + return GL_TRUE; + } + + /* Conversion between signed and unsigned integers needs masking + * (it isn't just memcpy). */ + srcType = _mesa_get_format_datatype(rb->Format); + + if ((srcType == GL_INT && + (type == GL_UNSIGNED_INT || + type == GL_UNSIGNED_SHORT || + type == GL_UNSIGNED_BYTE)) || + (srcType == GL_UNSIGNED_INT && + (type == GL_INT || + type == GL_SHORT || + type == GL_BYTE))) { + return GL_TRUE; + } + + /* And finally, see if there are any transfer ops. */ + return get_readpixels_transfer_ops(ctx, rb->Format, format, type, + uses_blit) != 0; + } + return GL_FALSE; +} + + +static GLboolean +readpixels_can_use_memcpy(const struct gl_context *ctx, GLenum format, GLenum type, + const struct gl_pixelstore_attrib *packing) +{ + struct gl_renderbuffer *rb = + _mesa_get_read_renderbuffer_for_format(ctx, format); + + ASSERT(rb); + + if (_mesa_readpixels_needs_slow_path(ctx, format, type, GL_FALSE)) { + return GL_FALSE; + } + + /* The base internal format and the base Mesa format must match. */ + if (rb->_BaseFormat != _mesa_get_format_base_format(rb->Format)) { + return GL_FALSE; + } + + /* The Mesa format must match the input format and type. */ + if (!_mesa_format_matches_format_and_type(rb->Format, format, type, + packing->SwapBytes)) { + return GL_FALSE; + } + + return GL_TRUE; +} + + +static GLboolean +readpixels_memcpy(struct gl_context *ctx, + GLint x, GLint y, + GLsizei width, GLsizei height, + GLenum format, GLenum type, + GLvoid *pixels, + const struct gl_pixelstore_attrib *packing) +{ + struct gl_renderbuffer *rb = + _mesa_get_read_renderbuffer_for_format(ctx, format); + GLubyte *dst, *map; + int dstStride, stride, j, texelBytes; + + /* Fail if memcpy cannot be used. */ + if (!readpixels_can_use_memcpy(ctx, format, type, packing)) { + return GL_FALSE; + } + + dstStride = _mesa_image_row_stride(packing, width, format, type); + dst = (GLubyte *) _mesa_image_address2d(packing, pixels, width, height, + format, type, 0, 0); + + ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT, + &map, &stride); + if (!map) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels"); + return GL_TRUE; /* don't bother trying the slow path */ + } + + texelBytes = _mesa_get_format_bytes(rb->Format); + + /* memcpy*/ + for (j = 0; j < height; j++) { + memcpy(dst, map, width * texelBytes); + dst += dstStride; + map += stride; + } + + ctx->Driver.UnmapRenderbuffer(ctx, rb); + return GL_TRUE; +} + /** - * Tries to implement glReadPixels() of GL_DEPTH_COMPONENT using memcpy of the - * mapping. + * Optimized path for conversion of depth values to GL_DEPTH_COMPONENT, + * GL_UNSIGNED_INT. */ static GLboolean -fast_read_depth_pixels( struct gl_context *ctx, +read_uint_depth_pixels( struct gl_context *ctx, GLint x, GLint y, GLsizei width, GLsizei height, GLenum type, GLvoid *pixels, @@ -71,10 +267,6 @@ fast_read_depth_pixels( struct gl_context *ctx, if (_mesa_get_format_datatype(rb->Format) != GL_UNSIGNED_NORMALIZED) return GL_FALSE; - if (!((type == GL_UNSIGNED_SHORT && rb->Format == MESA_FORMAT_Z16) || - type == GL_UNSIGNED_INT)) - return GL_FALSE; - ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT, &map, &stride); @@ -88,12 +280,7 @@ fast_read_depth_pixels( struct gl_context *ctx, GL_DEPTH_COMPONENT, type, 0, 0); for (j = 0; j < height; j++) { - if (type == GL_UNSIGNED_INT) { - _mesa_unpack_uint_z_row(rb->Format, width, map, (GLuint *)dst); - } else { - ASSERT(type == GL_UNSIGNED_SHORT && rb->Format == MESA_FORMAT_Z16); - memcpy(dst, map, width * 2); - } + _mesa_unpack_uint_z_row(rb->Format, width, map, (GLuint *)dst); map += stride; dst += dstStride; @@ -129,8 +316,10 @@ read_depth_pixels( struct gl_context *ctx, ASSERT(x + width <= (GLint) rb->Width); ASSERT(y + height <= (GLint) rb->Height); - if (fast_read_depth_pixels(ctx, x, y, width, height, type, pixels, packing)) + if (type == GL_UNSIGNED_INT && + read_uint_depth_pixels(ctx, x, y, width, height, type, pixels, packing)) { return; + } dstStride = _mesa_image_row_stride(packing, width, GL_DEPTH_COMPONENT, type); dst = (GLubyte *) _mesa_image_address2d(packing, pixels, width, height, @@ -143,7 +332,7 @@ read_depth_pixels( struct gl_context *ctx, return; } - depthValues = (GLfloat *) malloc(width * sizeof(GLfloat)); + depthValues = malloc(width * sizeof(GLfloat)); if (depthValues) { /* General case (slower) */ @@ -191,7 +380,7 @@ read_stencil_pixels( struct gl_context *ctx, return; } - stencil = (GLubyte *) malloc(width * sizeof(GLubyte)); + stencil = malloc(width * sizeof(GLubyte)); if (stencil) { /* process image row by row */ @@ -218,49 +407,38 @@ read_stencil_pixels( struct gl_context *ctx, /** - * Try to do glReadPixels of RGBA data using a simple memcpy or swizzle. + * Try to do glReadPixels of RGBA data using swizzle. * \return GL_TRUE if successful, GL_FALSE otherwise (use the slow path) */ static GLboolean -fast_read_rgba_pixels_memcpy( struct gl_context *ctx, - GLint x, GLint y, - GLsizei width, GLsizei height, - GLenum format, GLenum type, - GLvoid *pixels, - const struct gl_pixelstore_attrib *packing, - GLbitfield transferOps ) +read_rgba_pixels_swizzle(struct gl_context *ctx, + GLint x, GLint y, + GLsizei width, GLsizei height, + GLenum format, GLenum type, + GLvoid *pixels, + const struct gl_pixelstore_attrib *packing) { struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorReadBuffer; GLubyte *dst, *map; - int dstStride, stride, j, texelBytes; + int dstStride, stride, j; GLboolean swizzle_rb = GL_FALSE, copy_xrgb = GL_FALSE; /* XXX we could check for other swizzle/special cases here as needed */ - if (rb->Format == MESA_FORMAT_RGBA8888_REV && + if (rb->Format == MESA_FORMAT_R8G8B8A8_UNORM && format == GL_BGRA && type == GL_UNSIGNED_INT_8_8_8_8_REV && !ctx->Pack.SwapBytes) { swizzle_rb = GL_TRUE; } - else if (rb->Format == MESA_FORMAT_XRGB8888 && + else if (rb->Format == MESA_FORMAT_B8G8R8X8_UNORM && format == GL_BGRA && type == GL_UNSIGNED_INT_8_8_8_8_REV && !ctx->Pack.SwapBytes) { copy_xrgb = GL_TRUE; } - else if (!_mesa_format_matches_format_and_type(rb->Format, format, type, - ctx->Pack.SwapBytes)) - return GL_FALSE; - - /* If the format is unsigned normalized then we can ignore clamping - * because the values are already in the range [0,1] so it won't - * have any effect anyway. - */ - if (_mesa_get_format_datatype(rb->Format) == GL_UNSIGNED_NORMALIZED) - transferOps &= ~IMAGE_CLAMP_BIT; - - if (transferOps) + else { return GL_FALSE; + } dstStride = _mesa_image_row_stride(packing, width, format, type); dst = (GLubyte *) _mesa_image_address2d(packing, pixels, width, height, @@ -273,8 +451,6 @@ fast_read_rgba_pixels_memcpy( struct gl_context *ctx, return GL_TRUE; /* don't bother trying the slow path */ } - texelBytes = _mesa_get_format_bytes(rb->Format); - if (swizzle_rb) { /* swap R/B */ for (j = 0; j < height; j++) { @@ -300,13 +476,6 @@ fast_read_rgba_pixels_memcpy( struct gl_context *ctx, dst += dstStride; map += stride; } - } else { - /* just memcpy */ - for (j = 0; j < height; j++) { - memcpy(dst, map, width * texelBytes); - dst += dstStride; - map += stride; - } } ctx->Driver.UnmapRenderbuffer(ctx, rb); @@ -324,7 +493,7 @@ slow_read_rgba_pixels( struct gl_context *ctx, GLbitfield transferOps ) { struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorReadBuffer; - const gl_format rbFormat = _mesa_get_srgb_format_linear(rb->Format); + const mesa_format rbFormat = _mesa_get_srgb_format_linear(rb->Format); void *rgba; GLubyte *dst, *map; int dstStride, stride, j; @@ -385,22 +554,20 @@ read_rgba_pixels( struct gl_context *ctx, GLenum format, GLenum type, GLvoid *pixels, const struct gl_pixelstore_attrib *packing ) { - GLbitfield transferOps = ctx->_ImageTransferState; + GLbitfield transferOps; struct gl_framebuffer *fb = ctx->ReadBuffer; struct gl_renderbuffer *rb = fb->_ColorReadBuffer; if (!rb) return; - if ((ctx->Color._ClampReadColor == GL_TRUE || type != GL_FLOAT) && - !_mesa_is_enum_format_integer(format)) { - transferOps |= IMAGE_CLAMP_BIT; - } + transferOps = get_readpixels_transfer_ops(ctx, rb->Format, format, type, + GL_FALSE); /* Try the optimized paths first. */ - if (fast_read_rgba_pixels_memcpy(ctx, x, y, width, height, - format, type, pixels, packing, - transferOps)) { + if (!transferOps && + read_rgba_pixels_swizzle(ctx, x, y, width, height, + format, type, pixels, packing)) { return; } @@ -427,8 +594,8 @@ fast_read_depth_stencil_pixels(struct gl_context *ctx, if (rb != stencilRb) return GL_FALSE; - if (rb->Format != MESA_FORMAT_Z24_S8 && - rb->Format != MESA_FORMAT_S8_Z24) + if (rb->Format != MESA_FORMAT_S8_UINT_Z24_UNORM && + rb->Format != MESA_FORMAT_Z24_UNORM_S8_UINT) return GL_FALSE; ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, GL_MAP_READ_BIT, @@ -486,7 +653,7 @@ fast_read_depth_stencil_pixels_separate(struct gl_context *ctx, return GL_TRUE; /* don't bother trying the slow path */ } - stencilVals = (GLubyte *) malloc(width * sizeof(GLubyte)); + stencilVals = malloc(width * sizeof(GLubyte)); if (stencilVals) { for (j = 0; j < height; j++) { @@ -557,8 +724,8 @@ slow_read_depth_stencil_pixels_separate(struct gl_context *ctx, stencilStride = depthStride; } - stencilVals = (GLubyte *) malloc(width * sizeof(GLubyte)); - depthVals = (GLfloat *) malloc(width * sizeof(GLfloat)); + stencilVals = malloc(width * sizeof(GLubyte)); + depthVals = malloc(width * sizeof(GLfloat)); if (stencilVals && depthVals) { for (j = 0; j < height; j++) { @@ -655,6 +822,14 @@ _mesa_readpixels(struct gl_context *ctx, pixels = _mesa_map_pbo_dest(ctx, &clippedPacking, pixels); if (pixels) { + /* Try memcpy first. */ + if (readpixels_memcpy(ctx, x, y, width, height, format, type, + pixels, packing)) { + _mesa_unmap_pbo_dest(ctx, &clippedPacking); + return; + } + + /* Otherwise take the slow path. */ switch (format) { case GL_STENCIL_INDEX: read_stencil_pixels(ctx, x, y, width, height, type, pixels, @@ -680,16 +855,65 @@ _mesa_readpixels(struct gl_context *ctx, } +static GLenum +read_pixels_es3_error_check(GLenum format, GLenum type, + const struct gl_renderbuffer *rb) +{ + const GLenum internalFormat = rb->InternalFormat; + const GLenum data_type = _mesa_get_format_datatype(rb->Format); + GLboolean is_unsigned_int = GL_FALSE; + GLboolean is_signed_int = GL_FALSE; + + if (!_mesa_is_color_format(internalFormat)) { + return GL_INVALID_OPERATION; + } + + is_unsigned_int = _mesa_is_enum_format_unsigned_int(internalFormat); + if (!is_unsigned_int) { + is_signed_int = _mesa_is_enum_format_signed_int(internalFormat); + } + + switch (format) { + case GL_RGBA: + if (type == GL_FLOAT && data_type == GL_FLOAT) + return GL_NO_ERROR; /* EXT_color_buffer_float */ + if (type == GL_UNSIGNED_BYTE && data_type == GL_UNSIGNED_NORMALIZED) + return GL_NO_ERROR; + if (internalFormat == GL_RGB10_A2 && + type == GL_UNSIGNED_INT_2_10_10_10_REV) + return GL_NO_ERROR; + if (internalFormat == GL_RGB10_A2UI && type == GL_UNSIGNED_BYTE) + return GL_NO_ERROR; + break; + case GL_BGRA: + /* GL_EXT_read_format_bgra */ + if (type == GL_UNSIGNED_BYTE || + type == GL_UNSIGNED_SHORT_4_4_4_4_REV || + type == GL_UNSIGNED_SHORT_1_5_5_5_REV) + return GL_NO_ERROR; + break; + case GL_RGBA_INTEGER: + if ((is_signed_int && type == GL_INT) || + (is_unsigned_int && type == GL_UNSIGNED_INT)) + return GL_NO_ERROR; + break; + } + + return GL_INVALID_OPERATION; +} + + void GLAPIENTRY _mesa_ReadnPixelsARB( GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, GLvoid *pixels ) { - GLenum err; + GLenum err = GL_NO_ERROR; + struct gl_renderbuffer *rb; GET_CURRENT_CONTEXT(ctx); - ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); + FLUSH_VERTICES(ctx, 0); FLUSH_CURRENT(ctx, 0); if (MESA_VERBOSE & VERBOSE_API) @@ -705,6 +929,22 @@ _mesa_ReadnPixelsARB( GLint x, GLint y, GLsizei width, GLsizei height, return; } + if (ctx->NewState) + _mesa_update_state(ctx); + + if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { + _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, + "glReadPixels(incomplete framebuffer)" ); + return; + } + + rb = _mesa_get_read_renderbuffer_for_format(ctx, format); + if (rb == NULL) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glReadPixels(read buffer)"); + return; + } + /* OpenGL ES 1.x and OpenGL ES 2.0 impose additional restrictions on the * combinations of format and type that can be used. * @@ -713,15 +953,26 @@ _mesa_ReadnPixelsARB( GLint x, GLint y, GLsizei width, GLsizei height, * preferred combination. This code doesn't know what that preferred * combination is, and Mesa can handle anything valid. Just work instead. */ - if (_mesa_is_gles(ctx) && ctx->Version < 30) { - err = _mesa_es_error_check_format_and_type(format, type, 2); - if (err == GL_NO_ERROR) { - if (type == GL_FLOAT || type == GL_HALF_FLOAT_OES) { - err = GL_INVALID_OPERATION; - } else if (format == GL_DEPTH_COMPONENT - || format == GL_DEPTH_STENCIL) { - err = GL_INVALID_ENUM; + if (_mesa_is_gles(ctx)) { + if (ctx->API == API_OPENGLES2 && + _mesa_is_color_format(format) && + _mesa_get_color_read_format(ctx) == format && + _mesa_get_color_read_type(ctx) == type) { + err = GL_NO_ERROR; + } else if (ctx->Version < 30) { + err = _mesa_es_error_check_format_and_type(format, type, 2); + if (err == GL_NO_ERROR) { + if (type == GL_FLOAT || type == GL_HALF_FLOAT_OES) { + err = GL_INVALID_OPERATION; + } } + } else { + err = read_pixels_es3_error_check(format, type, rb); + } + + if (err == GL_NO_ERROR && (format == GL_DEPTH_COMPONENT + || format == GL_DEPTH_STENCIL)) { + err = GL_INVALID_ENUM; } if (err != GL_NO_ERROR) { @@ -732,9 +983,6 @@ _mesa_ReadnPixelsARB( GLint x, GLint y, GLsizei width, GLsizei height, } } - if (ctx->NewState) - _mesa_update_state(ctx); - err = _mesa_error_check_format_and_type(ctx, format, type); if (err != GL_NO_ERROR) { _mesa_error(ctx, err, "glReadPixels(invalid format %s and/or type %s)", @@ -743,9 +991,14 @@ _mesa_ReadnPixelsARB( GLint x, GLint y, GLsizei width, GLsizei height, return; } - if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { - _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, - "glReadPixels(incomplete framebuffer)" ); + if (_mesa_is_user_fbo(ctx->ReadBuffer) && + ctx->ReadBuffer->Visual.samples > 0) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(multisample FBO)"); + return; + } + + if (!_mesa_source_buffer_exists(ctx, format)) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(no readbuffer)"); return; } @@ -763,17 +1016,6 @@ _mesa_ReadnPixelsARB( GLint x, GLint y, GLsizei width, GLsizei height, } } - if (_mesa_is_user_fbo(ctx->ReadBuffer) && - ctx->ReadBuffer->Visual.samples > 0) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(multisample FBO)"); - return; - } - - if (!_mesa_source_buffer_exists(ctx, format)) { - _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(no readbuffer)"); - return; - } - if (width == 0 || height == 0) return; /* nothing to do */ @@ -791,7 +1033,7 @@ _mesa_ReadnPixelsARB( GLint x, GLint y, GLsizei width, GLsizei height, } if (_mesa_is_bufferobj(ctx->Pack.BufferObj) && - _mesa_bufferobj_mapped(ctx->Pack.BufferObj)) { + _mesa_check_disallowed_mapping(ctx->Pack.BufferObj)) { /* buffer is mapped - that's an error */ _mesa_error(ctx, GL_INVALID_OPERATION, "glReadPixels(PBO is mapped)"); return;