diff options
Diffstat (limited to 'src/mesa/main/api_validate.c')
-rw-r--r-- | src/mesa/main/api_validate.c | 108 |
1 files changed, 41 insertions, 67 deletions
diff --git a/src/mesa/main/api_validate.c b/src/mesa/main/api_validate.c index 2df4f173893..4a1448deee6 100644 --- a/src/mesa/main/api_validate.c +++ b/src/mesa/main/api_validate.c @@ -29,7 +29,7 @@ #include "imports.h" #include "mtypes.h" #include "state.h" - +#include "vbo/vbo.h" /** @@ -52,51 +52,6 @@ index_bytes(GLenum type, GLsizei count) /** - * Find the max index in the given element/index buffer - */ -static GLuint -max_buffer_index(GLcontext *ctx, GLuint count, GLenum type, - const void *indices, - struct gl_buffer_object *elementBuf) -{ - const GLubyte *map = NULL; - GLuint max = 0; - GLuint i; - - if (_mesa_is_bufferobj(elementBuf)) { - /* elements are in a user-defined buffer object. need to map it */ - map = ctx->Driver.MapBuffer(ctx, GL_ELEMENT_ARRAY_BUFFER, - GL_READ_ONLY, elementBuf); - /* Actual address is the sum of pointers */ - indices = (const GLvoid *) ADD_POINTERS(map, (const GLubyte *) indices); - } - - if (type == GL_UNSIGNED_INT) { - for (i = 0; i < count; i++) - if (((GLuint *) indices)[i] > max) - max = ((GLuint *) indices)[i]; - } - else if (type == GL_UNSIGNED_SHORT) { - for (i = 0; i < count; i++) - if (((GLushort *) indices)[i] > max) - max = ((GLushort *) indices)[i]; - } - else { - ASSERT(type == GL_UNSIGNED_BYTE); - for (i = 0; i < count; i++) - if (((GLubyte *) indices)[i] > max) - max = ((GLubyte *) indices)[i]; - } - - if (map) { - ctx->Driver.UnmapBuffer(ctx, GL_ELEMENT_ARRAY_BUFFER_ARB, elementBuf); - } - - return max; -} - - -/** * Check if OK to draw arrays/elements. */ static GLboolean @@ -124,6 +79,40 @@ check_valid_to_render(GLcontext *ctx, const char *function) return GL_TRUE; } +static GLboolean +check_index_bounds(GLcontext *ctx, GLsizei count, GLenum type, + const GLvoid *indices, GLint basevertex) +{ + struct _mesa_prim prim; + struct _mesa_index_buffer ib; + GLuint min, max; + + /* Only the X Server needs to do this -- otherwise, accessing outside + * array/BO bounds allows application termination. + */ + if (!ctx->Const.CheckArrayBounds) + return GL_TRUE; + + memset(&prim, 0, sizeof(prim)); + prim.count = count; + + memset(&ib, 0, sizeof(ib)); + ib.type = type; + ib.ptr = indices; + ib.obj = ctx->Array.ElementArrayBufferObj; + + vbo_get_minmax_index(ctx, &prim, &ib, &min, &max); + + if (min + basevertex < 0 || + max + basevertex > ctx->Array.ArrayObj->_MaxElement) { + /* the max element is out of bounds of one or more enabled arrays */ + _mesa_warning(ctx, "glDrawElements() index=%u is " + "out of bounds (max=%u)", max, ctx->Array.ArrayObj->_MaxElement); + return GL_FALSE; + } + + return GL_TRUE; +} /** * Error checking for glDrawElements(). Includes parameter checking @@ -133,7 +122,7 @@ check_valid_to_render(GLcontext *ctx, const char *function) GLboolean _mesa_validate_DrawElements(GLcontext *ctx, GLenum mode, GLsizei count, GLenum type, - const GLvoid *indices) + const GLvoid *indices, GLint basevertex) { ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); @@ -177,17 +166,8 @@ _mesa_validate_DrawElements(GLcontext *ctx, return GL_FALSE; } - if (ctx->Const.CheckArrayBounds) { - /* find max array index */ - GLuint max = max_buffer_index(ctx, count, type, indices, - ctx->Array.ElementArrayBufferObj); - if (max >= ctx->Array.ArrayObj->_MaxElement) { - /* the max element is out of bounds of one or more enabled arrays */ - _mesa_warning(ctx, "glDrawElements() index=%u is " - "out of bounds (max=%u)", max, ctx->Array.ArrayObj->_MaxElement); - return GL_FALSE; - } - } + if (!check_index_bounds(ctx, count, type, indices, basevertex)) + return GL_FALSE; return GL_TRUE; } @@ -202,7 +182,7 @@ GLboolean _mesa_validate_DrawRangeElements(GLcontext *ctx, GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, - const GLvoid *indices) + const GLvoid *indices, GLint basevertex) { ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); @@ -250,14 +230,8 @@ _mesa_validate_DrawRangeElements(GLcontext *ctx, GLenum mode, return GL_FALSE; } - if (ctx->Const.CheckArrayBounds) { - GLuint max = max_buffer_index(ctx, count, type, indices, - ctx->Array.ElementArrayBufferObj); - if (max >= ctx->Array.ArrayObj->_MaxElement) { - /* the max element is out of bounds of one or more enabled arrays */ - return GL_FALSE; - } - } + if (!check_index_bounds(ctx, count, type, indices, basevertex)) + return GL_FALSE; return GL_TRUE; } |