mesa: do state validation in _mesa_valid_to_render()
[mesa.git] / src / mesa / main / api_validate.c
index 2df4f173893af28e2838c06aae55bb466f91805a..013048bbc1694eb8e0ea201221cdd6e4e307f589 100644 (file)
@@ -29,7 +29,7 @@
 #include "imports.h"
 #include "mtypes.h"
 #include "state.h"
-
+#include "vbo/vbo.h"
 
 
 /**
@@ -54,10 +54,10 @@ 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)
+GLuint
+_mesa_max_buffer_index(GLcontext *ctx, GLuint count, GLenum type,
+                       const void *indices,
+                       struct gl_buffer_object *elementBuf)
 {
    const GLubyte *map = NULL;
    GLuint max = 0;
@@ -124,6 +124,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 +167,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);
 
@@ -156,9 +190,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 +208,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 +224,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);
 
@@ -229,9 +251,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 +269,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;
 }
@@ -285,9 +298,6 @@ _mesa_validate_DrawArrays(GLcontext *ctx,
       return GL_FALSE;
    }
 
-   if (ctx->NewState)
-      _mesa_update_state(ctx);
-
    if (!check_valid_to_render(ctx, "glDrawArrays"))
       return GL_FALSE;