#include "glheader.h"
#include "bufferobj.h"
+#include "glformats.h"
#include "image.h"
#include "imports.h"
#include "mtypes.h"
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.
*/
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;
}
*/
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);
*/
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);
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.MapBufferRange(ctx, 0, unpack->BufferObj->Size,
+ buf = (GLubyte *) ctx->Driver.MapBufferRange(ctx, 0,
+ unpack->BufferObj->Size,
GL_MAP_READ_BIT,
unpack->BufferObj);
if (!buf) {
ctx->Driver.UnmapBuffer(ctx, unpack->BufferObj);
}
}
-
-