api_validate.c revision ee34e6ef716bb630440299ac1efbc2055ef09ffd
1/* 2 * Mesa 3-D graphics library 3 * Version: 6.1 4 * 5 * Copyright (C) 1999-2003 Brian Paul All Rights Reserved. 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a 8 * copy of this software and associated documentation files (the "Software"), 9 * to deal in the Software without restriction, including without limitation 10 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 * and/or sell copies of the Software, and to permit persons to whom the 12 * Software is furnished to do so, subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be included 15 * in all copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 */ 24 25#include "glheader.h" 26#include "api_validate.h" 27#include "context.h" 28#include "imports.h" 29#include "mtypes.h" 30#include "state.h" 31 32 33GLboolean 34_mesa_validate_DrawElements(GLcontext *ctx, 35 GLenum mode, GLsizei count, GLenum type, 36 const GLvoid *indices) 37{ 38 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); 39 40 if (count <= 0) { 41 if (count < 0) 42 _mesa_error(ctx, GL_INVALID_VALUE, "glDrawElements(count)" ); 43 return GL_FALSE; 44 } 45 46 if (mode > GL_POLYGON) { 47 _mesa_error(ctx, GL_INVALID_ENUM, "glDrawElements(mode)" ); 48 return GL_FALSE; 49 } 50 51 if (type != GL_UNSIGNED_INT && 52 type != GL_UNSIGNED_BYTE && 53 type != GL_UNSIGNED_SHORT) 54 { 55 _mesa_error(ctx, GL_INVALID_ENUM, "glDrawElements(type)" ); 56 return GL_FALSE; 57 } 58 59 if (ctx->NewState) 60 _mesa_update_state(ctx); 61 62 /* Always need vertex positions */ 63 if (!ctx->Array.ArrayObj->Vertex.Enabled 64 && !(ctx->VertexProgram._Enabled && ctx->Array.ArrayObj->VertexAttrib[0].Enabled)) 65 return GL_FALSE; 66 67 /* Vertex buffer object tests */ 68 if (ctx->Array.ElementArrayBufferObj->Name) { 69 GLuint indexBytes; 70 71 /* use indices in the buffer object */ 72 if (!ctx->Array.ElementArrayBufferObj->Data) { 73 _mesa_warning(ctx, "DrawElements with empty vertex elements buffer!"); 74 return GL_FALSE; 75 } 76 77 /* make sure count doesn't go outside buffer bounds */ 78 if (type == GL_UNSIGNED_INT) { 79 indexBytes = count * sizeof(GLuint); 80 } 81 else if (type == GL_UNSIGNED_BYTE) { 82 indexBytes = count * sizeof(GLubyte); 83 } 84 else { 85 ASSERT(type == GL_UNSIGNED_SHORT); 86 indexBytes = count * sizeof(GLushort); 87 } 88 89 if ((GLubyte *) indices + indexBytes > 90 ctx->Array.ElementArrayBufferObj->Data + 91 ctx->Array.ElementArrayBufferObj->Size) { 92 _mesa_warning(ctx, "glDrawElements index out of buffer bounds"); 93 return GL_FALSE; 94 } 95 96 /* Actual address is the sum of pointers. Indices may be used below. */ 97 if (ctx->Const.CheckArrayBounds) { 98 indices = (const GLvoid *) 99 ADD_POINTERS(ctx->Array.ElementArrayBufferObj->Data, 100 (const GLubyte *) indices); 101 } 102 } 103 104 if (ctx->Const.CheckArrayBounds) { 105 /* find max array index */ 106 GLuint max = 0; 107 GLint i; 108 if (type == GL_UNSIGNED_INT) { 109 for (i = 0; i < count; i++) 110 if (((GLuint *) indices)[i] > max) 111 max = ((GLuint *) indices)[i]; 112 } 113 else if (type == GL_UNSIGNED_SHORT) { 114 for (i = 0; i < count; i++) 115 if (((GLushort *) indices)[i] > max) 116 max = ((GLushort *) indices)[i]; 117 } 118 else { 119 ASSERT(type == GL_UNSIGNED_BYTE); 120 for (i = 0; i < count; i++) 121 if (((GLubyte *) indices)[i] > max) 122 max = ((GLubyte *) indices)[i]; 123 } 124 if (max >= ctx->Array._MaxElement) { 125 /* the max element is out of bounds of one or more enabled arrays */ 126 return GL_FALSE; 127 } 128 } 129 130 return GL_TRUE; 131} 132 133 134GLboolean 135_mesa_validate_DrawRangeElements(GLcontext *ctx, GLenum mode, 136 GLuint start, GLuint end, 137 GLsizei count, GLenum type, 138 const GLvoid *indices) 139{ 140 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); 141 142 if (count <= 0) { 143 if (count < 0) 144 _mesa_error(ctx, GL_INVALID_VALUE, "glDrawRangeElements(count)" ); 145 return GL_FALSE; 146 } 147 148 if (mode > GL_POLYGON) { 149 _mesa_error(ctx, GL_INVALID_ENUM, "glDrawRangeElements(mode)" ); 150 return GL_FALSE; 151 } 152 153 if (end < start) { 154 _mesa_error(ctx, GL_INVALID_VALUE, "glDrawRangeElements(end<start)"); 155 return GL_FALSE; 156 } 157 158 if (type != GL_UNSIGNED_INT && 159 type != GL_UNSIGNED_BYTE && 160 type != GL_UNSIGNED_SHORT) { 161 _mesa_error(ctx, GL_INVALID_ENUM, "glDrawRangeElements(type)" ); 162 return GL_FALSE; 163 } 164 165 if (ctx->NewState) 166 _mesa_update_state(ctx); 167 168 /* Always need vertex positions */ 169 if (!ctx->Array.ArrayObj->Vertex.Enabled 170 && !(ctx->VertexProgram._Enabled && ctx->Array.ArrayObj->VertexAttrib[0].Enabled)) 171 return GL_FALSE; 172 173 if (ctx->Const.CheckArrayBounds) { 174 /* Find max array index. 175 * We don't trust the user's start and end values. 176 */ 177 GLuint max = 0; 178 GLint i; 179 if (type == GL_UNSIGNED_INT) { 180 for (i = 0; i < count; i++) 181 if (((GLuint *) indices)[i] > max) 182 max = ((GLuint *) indices)[i]; 183 } 184 else if (type == GL_UNSIGNED_SHORT) { 185 for (i = 0; i < count; i++) 186 if (((GLushort *) indices)[i] > max) 187 max = ((GLushort *) indices)[i]; 188 } 189 else { 190 ASSERT(type == GL_UNSIGNED_BYTE); 191 for (i = 0; i < count; i++) 192 if (((GLubyte *) indices)[i] > max) 193 max = ((GLubyte *) indices)[i]; 194 } 195 if (max >= ctx->Array._MaxElement) { 196 /* the max element is out of bounds of one or more enabled arrays */ 197 return GL_FALSE; 198 } 199 } 200 201 return GL_TRUE; 202} 203 204 205/** 206 * Called from the tnl module to error check the function parameters and 207 * verify that we really can draw something. 208 */ 209GLboolean 210_mesa_validate_DrawArrays(GLcontext *ctx, 211 GLenum mode, GLint start, GLsizei count) 212{ 213 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); 214 215 if (count < 0) { 216 _mesa_error(ctx, GL_INVALID_VALUE, "glDrawArrays(count)" ); 217 return GL_FALSE; 218 } 219 220 if (mode > GL_POLYGON) { 221 _mesa_error(ctx, GL_INVALID_ENUM, "glDrawArrays(mode)" ); 222 return GL_FALSE; 223 } 224 225 if (ctx->NewState) 226 _mesa_update_state(ctx); 227 228 /* Always need vertex positions */ 229 if (!ctx->Array.ArrayObj->Vertex.Enabled && !ctx->Array.ArrayObj->VertexAttrib[0].Enabled) 230 return GL_FALSE; 231 232 if (ctx->Const.CheckArrayBounds) { 233 if (start + count > (GLint) ctx->Array._MaxElement) 234 return GL_FALSE; 235 } 236 237 return GL_TRUE; 238} 239