X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fmain%2Fpbo.c;h=c73d7492f552bbaf77b8727577d9b8eade9ed7db;hb=bad1b271a0d0d2226d25a11c72c2b2d8b03833d4;hp=f93cdf1e3920fabab9724017f945edfcd4cbc0a8;hpb=56f0c00f125ee75caeadc1c9e8cab8a488635e5e;p=mesa.git diff --git a/src/mesa/main/pbo.c b/src/mesa/main/pbo.c index f93cdf1e392..c73d7492f55 100644 --- a/src/mesa/main/pbo.c +++ b/src/mesa/main/pbo.c @@ -32,6 +32,7 @@ #include "glheader.h" #include "bufferobj.h" +#include "glformats.h" #include "image.h" #include "imports.h" #include "mtypes.h" @@ -68,8 +69,8 @@ _mesa_validate_pbo_access(GLuint dimensions, GLenum format, GLenum type, GLsizei clientMemSize, const GLvoid *ptr) { - const GLvoid *start, *end, *offset; - const GLubyte *sizeAddr; /* buffer size, cast to a pointer */ + /* unsigned, to detect overflow/wrap-around */ + uintptr_t start, end, offset, size; /* If no PBO is bound, 'ptr' is a pointer to client memory containing 'clientMemSize' bytes. @@ -78,29 +79,45 @@ _mesa_validate_pbo_access(GLuint dimensions, */ if (!_mesa_is_bufferobj(pack->BufferObj)) { offset = 0; - sizeAddr = ((const GLubyte *) 0) + clientMemSize; + size = clientMemSize; } else { - offset = ptr; - sizeAddr = ((const GLubyte *) 0) + pack->BufferObj->Size; + offset = (uintptr_t)ptr; + size = pack->BufferObj->Size; + /* The ARB_pixel_buffer_object spec says: + * "INVALID_OPERATION is generated by ColorTable, ColorSubTable, + * ConvolutionFilter2D, ConvolutionFilter1D, SeparableFilter2D, + * TexImage1D, TexImage2D, TexImage3D, TexSubImage1D, + * TexSubImage2D, TexSubImage3D, and DrawPixels if the current + * PIXEL_UNPACK_BUFFER_BINDING_ARB value is non-zero and the data + * parameter is not evenly divisible into the number of basic machine + * units needed to store in memory a datum indicated by the type + * parameter." + */ + if (type != GL_BITMAP && + (offset % _mesa_sizeof_packed_type(type))) + return GL_FALSE; } - if (sizeAddr == 0) + if (size == 0) /* no buffer! */ return GL_FALSE; /* get the offset to the first pixel we'll read/write */ - start = _mesa_image_address(dimensions, pack, offset, width, height, - format, type, 0, 0, 0); + start = _mesa_image_offset(dimensions, pack, width, height, + format, type, 0, 0, 0); /* get the offset to just past the last pixel we'll read/write */ - end = _mesa_image_address(dimensions, pack, offset, width, height, - format, type, depth-1, height-1, width); + end = _mesa_image_offset(dimensions, pack, width, height, + format, type, depth-1, height-1, width); - if ((const GLubyte *) start > sizeAddr) { + start += offset; + end += offset; + + if (start > size) { /* This will catch negative values / wrap-around */ return GL_FALSE; } - if ((const GLubyte *) end > sizeAddr) { + if (end > size) { /* Image read/write goes beyond end of buffer */ return GL_FALSE; } @@ -128,9 +145,10 @@ _mesa_map_pbo_source(struct gl_context *ctx, if (_mesa_is_bufferobj(unpack->BufferObj)) { /* unpack from PBO */ - buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT, - GL_READ_ONLY_ARB, - unpack->BufferObj); + buf = (GLubyte *) ctx->Driver.MapBufferRange(ctx, 0, + unpack->BufferObj->Size, + GL_MAP_READ_BIT, + unpack->BufferObj); if (!buf) return NULL; @@ -155,11 +173,12 @@ _mesa_map_pbo_source(struct gl_context *ctx, */ 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) + 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); @@ -223,9 +242,10 @@ _mesa_map_pbo_dest(struct gl_context *ctx, if (_mesa_is_bufferobj(pack->BufferObj)) { /* pack into PBO */ - buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT, - GL_WRITE_ONLY_ARB, - pack->BufferObj); + buf = (GLubyte *) ctx->Driver.MapBufferRange(ctx, 0, + pack->BufferObj->Size, + GL_MAP_WRITE_BIT, + pack->BufferObj); if (!buf) return NULL; @@ -250,11 +270,11 @@ _mesa_map_pbo_dest(struct gl_context *ctx, */ GLvoid * _mesa_map_validate_pbo_dest(struct gl_context *ctx, - GLuint dimensions, - const struct gl_pixelstore_attrib *unpack, - GLsizei width, GLsizei height, GLsizei depth, - GLenum format, GLenum type, GLsizei clientMemSize, - GLvoid *ptr, const char *where) + GLuint dimensions, + const struct gl_pixelstore_attrib *unpack, + GLsizei width, GLsizei height, GLsizei depth, + GLenum format, GLenum type, GLsizei clientMemSize, + GLvoid *ptr, const char *where) { ASSERT(dimensions == 1 || dimensions == 2 || dimensions == 3); @@ -321,13 +341,15 @@ _mesa_validate_pbo_teximage(struct gl_context *ctx, GLuint dimensions, return pixels; } if (!_mesa_validate_pbo_access(dimensions, unpack, width, height, depth, - format, type, INT_MAX, pixels)) { + format, type, INT_MAX, pixels)) { _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(invalid PBO access)"); return NULL; } - buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT, - GL_READ_ONLY_ARB, unpack->BufferObj); + buf = (GLubyte *) ctx->Driver.MapBufferRange(ctx, 0, + unpack->BufferObj->Size, + GL_MAP_READ_BIT, + unpack->BufferObj); if (!buf) { _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(PBO is mapped)"); return NULL; @@ -363,8 +385,10 @@ _mesa_validate_pbo_compressed_teximage(struct gl_context *ctx, return NULL; } - buf = (GLubyte*) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT, - GL_READ_ONLY_ARB, packing->BufferObj); + buf = (GLubyte*) ctx->Driver.MapBufferRange(ctx, 0, + packing->BufferObj->Size, + GL_MAP_READ_BIT, + packing->BufferObj); if (!buf) { _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(PBO is mapped"); return NULL; @@ -386,5 +410,3 @@ _mesa_unmap_teximage_pbo(struct gl_context *ctx, ctx->Driver.UnmapBuffer(ctx, unpack->BufferObj); } } - -