X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fmain%2Fpbo.c;h=cea55f2a0d29eb7fe55969bdf644b1323980a838;hb=093aeb35651f20de70492ded56cc2a0f48174edf;hp=400cec3f0e2fcfd325c98211858386fe0b3b5bac;hpb=3d8d5b298a268b119d840bc9bae0ee9e0c9244a9;p=mesa.git diff --git a/src/mesa/main/pbo.c b/src/mesa/main/pbo.c index 400cec3f0e2..cea55f2a0d2 100644 --- a/src/mesa/main/pbo.c +++ b/src/mesa/main/pbo.c @@ -31,6 +31,7 @@ +#include "errors.h" #include "glheader.h" #include "bufferobj.h" #include "glformats.h" @@ -80,7 +81,7 @@ _mesa_validate_pbo_access(GLuint dimensions, */ if (!_mesa_is_bufferobj(pack->BufferObj)) { offset = 0; - size = clientMemSize; + size = (clientMemSize == INT_MAX) ? UINTPTR_MAX : clientMemSize; } else { offset = (uintptr_t)ptr; size = pack->BufferObj->Size; @@ -103,6 +104,12 @@ _mesa_validate_pbo_access(GLuint dimensions, /* no buffer! */ return GL_FALSE; + /* If the size of the image is zero then no pixels are accessed so we + * don't need to check anything else. + */ + if (width == 0 || height == 0 || depth == 0) + return GL_TRUE; + /* get the offset to the first pixel we'll read/write */ start = _mesa_image_offset(dimensions, pack, width, height, format, type, 0, 0, 0); @@ -149,7 +156,8 @@ _mesa_map_pbo_source(struct gl_context *ctx, buf = (GLubyte *) ctx->Driver.MapBufferRange(ctx, 0, unpack->BufferObj->Size, GL_MAP_READ_BIT, - unpack->BufferObj); + unpack->BufferObj, + MAP_INTERNAL); if (!buf) return NULL; @@ -163,48 +171,104 @@ _mesa_map_pbo_source(struct gl_context *ctx, return buf; } - /** - * Combine PBO-read validation and mapping. - * If any GL errors are detected, they'll be recorded and NULL returned. + * Perform PBO validation for read operations with uncompressed textures. + * If any GL errors are detected, false is returned, otherwise returns true. * \sa _mesa_validate_pbo_access - * \sa _mesa_map_pbo_source - * A call to this function should have a matching call to - * _mesa_unmap_pbo_source(). */ -const GLvoid * -_mesa_map_validate_pbo_source(struct gl_context *ctx, - GLuint dimensions, - const struct gl_pixelstore_attrib *unpack, - GLsizei width, GLsizei height, GLsizei depth, - GLenum format, GLenum type, - GLsizei clientMemSize, - const GLvoid *ptr, const char *where) +bool +_mesa_validate_pbo_source(struct gl_context *ctx, GLuint dimensions, + const struct gl_pixelstore_attrib *unpack, + GLsizei width, GLsizei height, GLsizei depth, + GLenum format, GLenum type, + GLsizei clientMemSize, + const GLvoid *ptr, const char *where) { - ASSERT(dimensions == 1 || dimensions == 2 || dimensions == 3); + assert(dimensions == 1 || dimensions == 2 || dimensions == 3); if (!_mesa_validate_pbo_access(dimensions, unpack, width, height, depth, format, type, clientMemSize, ptr)) { if (_mesa_is_bufferobj(unpack->BufferObj)) { _mesa_error(ctx, GL_INVALID_OPERATION, - "%s(out of bounds PBO access)", where); + "%s(out of bounds PBO access)", + where); } else { _mesa_error(ctx, GL_INVALID_OPERATION, "%s(out of bounds access: bufSize (%d) is too small)", where, clientMemSize); } - return NULL; + return false; } if (!_mesa_is_bufferobj(unpack->BufferObj)) { /* non-PBO access: no further validation to be done */ - return ptr; + return true; } - if (_mesa_bufferobj_mapped(unpack->BufferObj)) { + if (_mesa_check_disallowed_mapping(unpack->BufferObj)) { /* buffer is already mapped - that's an error */ - _mesa_error(ctx, GL_INVALID_OPERATION, "%s(PBO is mapped)", where); - return NULL; + _mesa_error(ctx, GL_INVALID_OPERATION, "%s(PBO is mapped)", + where); + return false; + } + + return true; +} + +/** + * Perform PBO validation for read operations with compressed textures. + * If any GL errors are detected, false is returned, otherwise returns true. + */ +bool +_mesa_validate_pbo_source_compressed(struct gl_context *ctx, GLuint dimensions, + const struct gl_pixelstore_attrib *unpack, + GLsizei imageSize, const GLvoid *pixels, + const char *where) +{ + if (!_mesa_is_bufferobj(unpack->BufferObj)) { + /* not using a PBO */ + return true; + } + + if ((const GLubyte *) pixels + imageSize > + ((const GLubyte *) 0) + unpack->BufferObj->Size) { + /* out of bounds read! */ + _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid PBO access)", + where); + return false; + } + + if (_mesa_check_disallowed_mapping(unpack->BufferObj)) { + /* buffer is already mapped - that's an error */ + _mesa_error(ctx, GL_INVALID_OPERATION, "%s(PBO is mapped)", + where); + return false; + } + + return true; +} + +/** + * Perform PBO-read mapping. + * If any GL errors are detected, they'll be recorded and NULL returned. + * \sa _mesa_validate_pbo_source + * \sa _mesa_map_pbo_source + * A call to this function should have a matching call to + * _mesa_unmap_pbo_source(). + */ +const GLvoid * +_mesa_map_validate_pbo_source(struct gl_context *ctx, + GLuint dimensions, + const struct gl_pixelstore_attrib *unpack, + GLsizei width, GLsizei height, GLsizei depth, + GLenum format, GLenum type, + GLsizei clientMemSize, + const GLvoid *ptr, const char *where) +{ + if (!_mesa_validate_pbo_source(ctx, dimensions, unpack, + width, height, depth, format, type, + clientMemSize, ptr, where)) { + return NULL; } ptr = _mesa_map_pbo_source(ctx, unpack, ptr); @@ -219,9 +283,9 @@ void _mesa_unmap_pbo_source(struct gl_context *ctx, const struct gl_pixelstore_attrib *unpack) { - ASSERT(unpack != &ctx->Pack); /* catch pack/unpack mismatch */ + assert(unpack != &ctx->Pack); /* catch pack/unpack mismatch */ if (_mesa_is_bufferobj(unpack->BufferObj)) { - ctx->Driver.UnmapBuffer(ctx, unpack->BufferObj); + ctx->Driver.UnmapBuffer(ctx, unpack->BufferObj, MAP_INTERNAL); } } @@ -246,7 +310,8 @@ _mesa_map_pbo_dest(struct gl_context *ctx, buf = (GLubyte *) ctx->Driver.MapBufferRange(ctx, 0, pack->BufferObj->Size, GL_MAP_WRITE_BIT, - pack->BufferObj); + pack->BufferObj, + MAP_INTERNAL); if (!buf) return NULL; @@ -277,7 +342,7 @@ _mesa_map_validate_pbo_dest(struct gl_context *ctx, GLenum format, GLenum type, GLsizei clientMemSize, GLvoid *ptr, const char *where) { - ASSERT(dimensions == 1 || dimensions == 2 || dimensions == 3); + assert(dimensions == 1 || dimensions == 2 || dimensions == 3); if (!_mesa_validate_pbo_access(dimensions, unpack, width, height, depth, format, type, clientMemSize, ptr)) { @@ -297,7 +362,7 @@ _mesa_map_validate_pbo_dest(struct gl_context *ctx, return ptr; } - if (_mesa_bufferobj_mapped(unpack->BufferObj)) { + if (_mesa_check_disallowed_mapping(unpack->BufferObj)) { /* buffer is already mapped - that's an error */ _mesa_error(ctx, GL_INVALID_OPERATION, "%s(PBO is mapped)", where); return NULL; @@ -315,9 +380,9 @@ void _mesa_unmap_pbo_dest(struct gl_context *ctx, const struct gl_pixelstore_attrib *pack) { - ASSERT(pack != &ctx->Unpack); /* catch pack/unpack mismatch */ + assert(pack != &ctx->Unpack); /* catch pack/unpack mismatch */ if (_mesa_is_bufferobj(pack->BufferObj)) { - ctx->Driver.UnmapBuffer(ctx, pack->BufferObj); + ctx->Driver.UnmapBuffer(ctx, pack->BufferObj, MAP_INTERNAL); } } @@ -351,7 +416,8 @@ _mesa_validate_pbo_teximage(struct gl_context *ctx, GLuint dimensions, buf = (GLubyte *) ctx->Driver.MapBufferRange(ctx, 0, unpack->BufferObj->Size, GL_MAP_READ_BIT, - unpack->BufferObj); + unpack->BufferObj, + MAP_INTERNAL); if (!buf) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s%uD(PBO is mapped)", funcName, dimensions); @@ -378,27 +444,27 @@ _mesa_validate_pbo_compressed_teximage(struct gl_context *ctx, { GLubyte *buf; + if (!_mesa_validate_pbo_source_compressed(ctx, dimensions, packing, + imageSize, pixels, funcName)) { + /* error is already set during validation */ + return NULL; + } + if (!_mesa_is_bufferobj(packing->BufferObj)) { /* not using a PBO - return pointer unchanged */ return pixels; } - if ((const GLubyte *) pixels + imageSize > - ((const GLubyte *) 0) + packing->BufferObj->Size) { - /* out of bounds read! */ - _mesa_error(ctx, GL_INVALID_OPERATION, "%s%uD(invalid PBO access)", - funcName, dimensions); - return NULL; - } buf = (GLubyte*) ctx->Driver.MapBufferRange(ctx, 0, packing->BufferObj->Size, GL_MAP_READ_BIT, - packing->BufferObj); - if (!buf) { - _mesa_error(ctx, GL_INVALID_OPERATION, "%s%uD(PBO is mapped)", funcName, - dimensions); - return NULL; - } + packing->BufferObj, + MAP_INTERNAL); + + /* Validation above already checked that PBO is not mapped, so buffer + * should not be null. + */ + assert(buf); return ADD_POINTERS(buf, pixels); } @@ -413,6 +479,6 @@ _mesa_unmap_teximage_pbo(struct gl_context *ctx, const struct gl_pixelstore_attrib *unpack) { if (_mesa_is_bufferobj(unpack->BufferObj)) { - ctx->Driver.UnmapBuffer(ctx, unpack->BufferObj); + ctx->Driver.UnmapBuffer(ctx, unpack->BufferObj, MAP_INTERNAL); } }