X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fmain%2Fapi_validate.c;h=ac9709db3f1ef1d3cf4beaf78bbfdcef9e7bb998;hb=b2ddb93ff3b8c88682634ccdef247967e31fab84;hp=507e21fe81e13252acbce818a108eaa4e4535795;hpb=ba002eb1965ccdb09d7c3657d32e22e71ed4096a;p=mesa.git diff --git a/src/mesa/main/api_validate.c b/src/mesa/main/api_validate.c index 507e21fe81e..ac9709db3f1 100644 --- a/src/mesa/main/api_validate.c +++ b/src/mesa/main/api_validate.c @@ -27,9 +27,9 @@ #include "bufferobj.h" #include "context.h" #include "imports.h" +#include "mfeatures.h" #include "mtypes.h" -#include "state.h" - +#include "vbo/vbo.h" /** @@ -55,7 +55,7 @@ index_bytes(GLenum type, GLsizei count) * Find the max index in the given element/index buffer */ GLuint -_mesa_max_buffer_index(GLcontext *ctx, GLuint count, GLenum type, +_mesa_max_buffer_index(struct gl_context *ctx, GLuint count, GLenum type, const void *indices, struct gl_buffer_object *elementBuf) { @@ -100,26 +100,77 @@ _mesa_max_buffer_index(GLcontext *ctx, GLuint count, GLenum type, * Check if OK to draw arrays/elements. */ static GLboolean -check_valid_to_render(GLcontext *ctx, const char *function) +check_valid_to_render(struct gl_context *ctx, const char *function) { if (!_mesa_valid_to_render(ctx, function)) { return GL_FALSE; } + switch (ctx->API) { #if FEATURE_es2_glsl - /* For ES2, we can draw if any vertex array is enabled (and we should - * always have a vertex program/shader). - */ - if (ctx->Array.ArrayObj->_Enabled == 0x0 || !ctx->VertexProgram._Current) - return GL_FALSE; -#else - /* For regular OpenGL, only draw if we have vertex positions (regardless - * of whether or not we have a vertex program/shader). + case API_OPENGLES2: + /* For ES2, we can draw if any vertex array is enabled (and we + * should always have a vertex program/shader). */ + if (ctx->Array.ArrayObj->_Enabled == 0x0 || !ctx->VertexProgram._Current) + return GL_FALSE; + break; +#endif + +#if FEATURE_ES1 || FEATURE_GL + case API_OPENGLES: + case API_OPENGL: + /* For regular OpenGL, only draw if we have vertex positions + * (regardless of whether or not we have a vertex program/shader). */ + if (!ctx->Array.ArrayObj->Vertex.Enabled && + !ctx->Array.ArrayObj->VertexAttrib[0].Enabled) + return GL_FALSE; + break; +#endif + + default: + ASSERT_NO_FEATURE(); + } + + return GL_TRUE; +} + + +/** + * Do bounds checking on array element indexes. Check that the vertices + * pointed to by the indices don't lie outside buffer object bounds. + * \return GL_TRUE if OK, GL_FALSE if any indexed vertex goes is out of bounds + */ +static GLboolean +check_index_bounds(struct gl_context *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->Array.ArrayObj->Vertex.Enabled && - !ctx->Array.ArrayObj->VertexAttrib[0].Enabled) + 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 ((int)(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; -#endif + } return GL_TRUE; } @@ -131,11 +182,11 @@ check_valid_to_render(GLcontext *ctx, const char *function) * \return GL_TRUE if OK to render, GL_FALSE if error found */ GLboolean -_mesa_validate_DrawElements(GLcontext *ctx, +_mesa_validate_DrawElements(struct gl_context *ctx, GLenum mode, GLsizei count, GLenum type, - const GLvoid *indices) + const GLvoid *indices, GLint basevertex) { - ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); + ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); if (count <= 0) { if (count < 0) @@ -143,7 +194,7 @@ _mesa_validate_DrawElements(GLcontext *ctx, return GL_FALSE; } - if (mode > GL_POLYGON) { + if (mode > GL_TRIANGLE_STRIP_ADJACENCY_ARB) { _mesa_error(ctx, GL_INVALID_ENUM, "glDrawElements(mode)" ); return GL_FALSE; } @@ -156,9 +207,6 @@ _mesa_validate_DrawElements(GLcontext *ctx, return GL_FALSE; } - if (ctx->NewState) - _mesa_update_state(ctx); - if (!check_valid_to_render(ctx, "glDrawElements")) return GL_FALSE; @@ -177,17 +225,8 @@ _mesa_validate_DrawElements(GLcontext *ctx, return GL_FALSE; } - if (ctx->Const.CheckArrayBounds) { - /* find max array index */ - GLuint max = _mesa_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; } @@ -199,10 +238,10 @@ _mesa_validate_DrawElements(GLcontext *ctx, * \return GL_TRUE if OK to render, GL_FALSE if error found */ GLboolean -_mesa_validate_DrawRangeElements(GLcontext *ctx, GLenum mode, +_mesa_validate_DrawRangeElements(struct gl_context *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); @@ -212,7 +251,7 @@ _mesa_validate_DrawRangeElements(GLcontext *ctx, GLenum mode, return GL_FALSE; } - if (mode > GL_POLYGON) { + if (mode > GL_TRIANGLE_STRIP_ADJACENCY_ARB) { _mesa_error(ctx, GL_INVALID_ENUM, "glDrawRangeElements(mode)" ); return GL_FALSE; } @@ -229,9 +268,6 @@ _mesa_validate_DrawRangeElements(GLcontext *ctx, GLenum mode, return GL_FALSE; } - if (ctx->NewState) - _mesa_update_state(ctx); - if (!check_valid_to_render(ctx, "glDrawRangeElements")) return GL_FALSE; @@ -250,14 +286,8 @@ _mesa_validate_DrawRangeElements(GLcontext *ctx, GLenum mode, return GL_FALSE; } - if (ctx->Const.CheckArrayBounds) { - GLuint max = _mesa_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; } @@ -269,7 +299,7 @@ _mesa_validate_DrawRangeElements(GLcontext *ctx, GLenum mode, * \return GL_TRUE if OK to render, GL_FALSE if error found */ GLboolean -_mesa_validate_DrawArrays(GLcontext *ctx, +_mesa_validate_DrawArrays(struct gl_context *ctx, GLenum mode, GLint start, GLsizei count) { ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); @@ -280,14 +310,11 @@ _mesa_validate_DrawArrays(GLcontext *ctx, return GL_FALSE; } - if (mode > GL_POLYGON) { + if (mode > GL_TRIANGLE_STRIP_ADJACENCY_ARB) { _mesa_error(ctx, GL_INVALID_ENUM, "glDrawArrays(mode)" ); return GL_FALSE; } - if (ctx->NewState) - _mesa_update_state(ctx); - if (!check_valid_to_render(ctx, "glDrawArrays")) return GL_FALSE; @@ -298,3 +325,108 @@ _mesa_validate_DrawArrays(GLcontext *ctx, return GL_TRUE; } + + +GLboolean +_mesa_validate_DrawArraysInstanced(struct gl_context *ctx, GLenum mode, GLint first, + GLsizei count, GLsizei primcount) +{ + ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); + + if (count <= 0) { + if (count < 0) + _mesa_error(ctx, GL_INVALID_VALUE, + "glDrawArraysInstanced(count=%d)", count); + return GL_FALSE; + } + + if (mode > GL_TRIANGLE_STRIP_ADJACENCY_ARB) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glDrawArraysInstanced(mode=0x%x)", mode); + return GL_FALSE; + } + + if (primcount <= 0) { + if (primcount < 0) + _mesa_error(ctx, GL_INVALID_VALUE, + "glDrawArraysInstanced(primcount=%d)", primcount); + return GL_FALSE; + } + + if (!check_valid_to_render(ctx, "glDrawArraysInstanced(invalid to render)")) + return GL_FALSE; + + if (ctx->CompileFlag) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glDrawArraysInstanced(display list"); + return GL_FALSE; + } + + if (ctx->Const.CheckArrayBounds) { + if (first + count > (GLint) ctx->Array.ArrayObj->_MaxElement) + return GL_FALSE; + } + + return GL_TRUE; +} + + +GLboolean +_mesa_validate_DrawElementsInstanced(struct gl_context *ctx, + GLenum mode, GLsizei count, GLenum type, + const GLvoid *indices, GLsizei primcount) +{ + ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); + + if (count <= 0) { + if (count < 0) + _mesa_error(ctx, GL_INVALID_VALUE, + "glDrawElementsInstanced(count=%d)", count); + return GL_FALSE; + } + + if (mode > GL_TRIANGLE_STRIP_ADJACENCY_ARB) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glDrawElementsInstanced(mode = 0x%x)", mode); + return GL_FALSE; + } + + if (type != GL_UNSIGNED_INT && + type != GL_UNSIGNED_BYTE && + type != GL_UNSIGNED_SHORT) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glDrawElementsInstanced(type=0x%x)", type); + return GL_FALSE; + } + + if (primcount <= 0) { + if (primcount < 0) + _mesa_error(ctx, GL_INVALID_VALUE, + "glDrawElementsInstanced(primcount=%d)", primcount); + return GL_FALSE; + } + + if (!check_valid_to_render(ctx, "glDrawElementsInstanced")) + return GL_FALSE; + + /* Vertex buffer object tests */ + if (_mesa_is_bufferobj(ctx->Array.ElementArrayBufferObj)) { + /* use indices in the buffer object */ + /* make sure count doesn't go outside buffer bounds */ + if (index_bytes(type, count) > ctx->Array.ElementArrayBufferObj->Size) { + _mesa_warning(ctx, + "glDrawElementsInstanced index out of buffer bounds"); + return GL_FALSE; + } + } + else { + /* not using a VBO */ + if (!indices) + return GL_FALSE; + } + + if (!check_index_bounds(ctx, count, type, indices, 0)) + return GL_FALSE; + + return GL_TRUE; +}