X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fmain%2Fapi_validate.c;h=64ab324af2269b02fb1f6d6702c21627f7709d14;hb=09fbb3837b6aa5dfc6c94f41ab5443820177c569;hp=8d3cbafc64c0a301acddb7646bc69be825687a55;hpb=08836341788a9f9d638d9dc8328510ccd18ddeb5;p=mesa.git diff --git a/src/mesa/main/api_validate.c b/src/mesa/main/api_validate.c index 8d3cbafc64c..64ab324af22 100644 --- a/src/mesa/main/api_validate.c +++ b/src/mesa/main/api_validate.c @@ -1,11 +1,8 @@ - -/* $Id: api_validate.c,v 1.4 2001/03/03 20:33:27 brianp Exp $ */ - /* * Mesa 3-D graphics library - * Version: 3.5 + * Version: 7.0.1 * - * Copyright (C) 1999-2000 Brian Paul All Rights Reserved. + * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -28,16 +25,17 @@ #include "glheader.h" #include "api_validate.h" #include "context.h" +#include "imports.h" #include "mtypes.h" #include "state.h" GLboolean _mesa_validate_DrawElements(GLcontext *ctx, - GLenum mode, GLsizei count, GLenum type, + GLenum mode, GLsizei count, GLenum type, const GLvoid *indices) { - ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); + ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); if (count <= 0) { if (count < 0) @@ -45,14 +43,13 @@ _mesa_validate_DrawElements(GLcontext *ctx, return GL_FALSE; } - if (mode < 0 || - mode > GL_POLYGON) { - _mesa_error(ctx, GL_INVALID_ENUM, "glDrawArrays(mode)" ); + if (mode > GL_POLYGON) { + _mesa_error(ctx, GL_INVALID_ENUM, "glDrawElements(mode)" ); return GL_FALSE; } - if (type != GL_UNSIGNED_INT && - type != GL_UNSIGNED_BYTE && + if (type != GL_UNSIGNED_INT && + type != GL_UNSIGNED_BYTE && type != GL_UNSIGNED_SHORT) { _mesa_error(ctx, GL_INVALID_ENUM, "glDrawElements(type)" ); @@ -60,31 +57,108 @@ _mesa_validate_DrawElements(GLcontext *ctx, } if (ctx->NewState) - _mesa_update_state( ctx ); + _mesa_update_state(ctx); - if (!ctx->Array.Vertex.Enabled) + /* Always need vertex positions */ + if (!ctx->Array.ArrayObj->Vertex.Enabled + && !(ctx->VertexProgram._Enabled && ctx->Array.ArrayObj->VertexAttrib[0].Enabled)) return GL_FALSE; + /* Vertex buffer object tests */ + if (ctx->Array.ElementArrayBufferObj->Name) { + GLuint indexBytes; + + /* use indices in the buffer object */ + if (!ctx->Array.ElementArrayBufferObj->Size) { + _mesa_warning(ctx, + "glDrawElements called with empty array elements buffer"); + return GL_FALSE; + } + + /* make sure count doesn't go outside buffer bounds */ + if (type == GL_UNSIGNED_INT) { + indexBytes = count * sizeof(GLuint); + } + else if (type == GL_UNSIGNED_BYTE) { + indexBytes = count * sizeof(GLubyte); + } + else { + ASSERT(type == GL_UNSIGNED_SHORT); + indexBytes = count * sizeof(GLushort); + } + + if (indexBytes > ctx->Array.ElementArrayBufferObj->Size) { + _mesa_warning(ctx, "glDrawElements index out of buffer bounds"); + return GL_FALSE; + } + } + else { + /* not using a VBO */ + if (!indices) + return GL_FALSE; + } + + if (ctx->Const.CheckArrayBounds) { + /* find max array index */ + const GLubyte *map; + GLuint max = 0; + GLint i; + + map = ctx->Driver.MapBuffer(ctx, + GL_ELEMENT_ARRAY_BUFFER_ARB, + GL_READ_ONLY, + ctx->Array.ElementArrayBufferObj); + + /* 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]; + } + + ctx->Driver.UnmapBuffer(ctx, + GL_ELEMENT_ARRAY_BUFFER_ARB, + ctx->Array.ElementArrayBufferObj); + + if (max >= ctx->Array._MaxElement) { + /* the max element is out of bounds of one or more enabled arrays */ + return GL_FALSE; + } + } + return GL_TRUE; } GLboolean -_mesa_validate_DrawRangeElements(GLcontext *ctx, GLenum mode, - GLuint start, GLuint end, - GLsizei count, GLenum type, +_mesa_validate_DrawRangeElements(GLcontext *ctx, GLenum mode, + GLuint start, GLuint end, + GLsizei count, GLenum type, const GLvoid *indices) { - ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); + ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); if (count <= 0) { if (count < 0) - _mesa_error(ctx, GL_INVALID_VALUE, "glDrawElements(count)" ); + _mesa_error(ctx, GL_INVALID_VALUE, "glDrawRangeElements(count)" ); return GL_FALSE; } - if (mode < 0 || mode > GL_POLYGON) { - _mesa_error(ctx, GL_INVALID_ENUM, "glDrawArrays(mode)" ); + if (mode > GL_POLYGON) { + _mesa_error(ctx, GL_INVALID_ENUM, "glDrawRangeElements(mode)" ); return GL_FALSE; } @@ -93,47 +167,94 @@ _mesa_validate_DrawRangeElements(GLcontext *ctx, GLenum mode, return GL_FALSE; } - if (type != GL_UNSIGNED_INT && - type != GL_UNSIGNED_BYTE && - type != GL_UNSIGNED_SHORT) - { - _mesa_error(ctx, GL_INVALID_ENUM, "glDrawElements(type)" ); + if (type != GL_UNSIGNED_INT && + type != GL_UNSIGNED_BYTE && + type != GL_UNSIGNED_SHORT) { + _mesa_error(ctx, GL_INVALID_ENUM, "glDrawRangeElements(type)" ); return GL_FALSE; } if (ctx->NewState) - _mesa_update_state( ctx ); + _mesa_update_state(ctx); - if (!ctx->Array.Vertex.Enabled) + /* Always need vertex positions */ + if (!ctx->Array.ArrayObj->Vertex.Enabled + && !(ctx->VertexProgram._Enabled && ctx->Array.ArrayObj->VertexAttrib[0].Enabled)) return GL_FALSE; + /* Vertex buffer object tests */ + if (ctx->Array.ElementArrayBufferObj->Name) { + /* XXX re-use code from above? */ + } + else { + /* not using VBO */ + if (!indices) + return GL_FALSE; + } + + if (ctx->Const.CheckArrayBounds) { + /* Find max array index. + * We don't trust the user's start and end values. + */ + GLuint max = 0; + GLint i; + 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 (max >= ctx->Array._MaxElement) { + /* the max element is out of bounds of one or more enabled arrays */ + return GL_FALSE; + } + } + return GL_TRUE; } - +/** + * Called from the tnl module to error check the function parameters and + * verify that we really can draw something. + */ GLboolean -_mesa_validate_DrawArrays(GLcontext *ctx, +_mesa_validate_DrawArrays(GLcontext *ctx, GLenum mode, GLint start, GLsizei count) { - ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); + ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); - if (count<0) { + if (count < 0) { _mesa_error(ctx, GL_INVALID_VALUE, "glDrawArrays(count)" ); return GL_FALSE; } - if (mode < 0 || mode > GL_POLYGON) { + if (mode > GL_POLYGON) { _mesa_error(ctx, GL_INVALID_ENUM, "glDrawArrays(mode)" ); return GL_FALSE; } if (ctx->NewState) - _mesa_update_state( ctx ); + _mesa_update_state(ctx); - if (!ctx->Array.Vertex.Enabled) + /* Always need vertex positions */ + if (!ctx->Array.ArrayObj->Vertex.Enabled && !ctx->Array.ArrayObj->VertexAttrib[0].Enabled) return GL_FALSE; + if (ctx->Const.CheckArrayBounds) { + if (start + count > (GLint) ctx->Array._MaxElement) + return GL_FALSE; + } + return GL_TRUE; } -