Merge branch 'mesa_7_6_branch'
[mesa.git] / src / mesa / main / api_validate.c
index b2f11ffbfe3effde7735555e414fd53b3a34852b..e71e5a6ce867c529d508d5ab148069771e7fb0d7 100644 (file)
 
 #include "glheader.h"
 #include "api_validate.h"
+#include "bufferobj.h"
 #include "context.h"
 #include "imports.h"
 #include "mtypes.h"
 #include "state.h"
-
+#include "vbo/vbo.h"
 
 
 /**
@@ -53,16 +54,16 @@ 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;
    GLuint i;
 
-   if (elementBuf->Name) {
+   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);
@@ -96,14 +97,12 @@ max_buffer_index(GLcontext *ctx, GLuint count, GLenum type,
 
 
 /**
- * Check if OK to render by examining framebuffer status and vertex arrays.
+ * Check if OK to draw arrays/elements.
  */
 static GLboolean
-check_valid_to_render(GLcontext *ctx, char *function)
+check_valid_to_render(GLcontext *ctx, const char *function)
 {
-   if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
-      _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
-                  "glDraw%s(incomplete framebuffer)", function);
+   if (!_mesa_valid_to_render(ctx, function)) {
       return GL_FALSE;
    }
 
@@ -125,6 +124,40 @@ check_valid_to_render(GLcontext *ctx, 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
@@ -134,7 +167,7 @@ check_valid_to_render(GLcontext *ctx, 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);
 
@@ -160,11 +193,11 @@ _mesa_validate_DrawElements(GLcontext *ctx,
    if (ctx->NewState)
       _mesa_update_state(ctx);
 
-   if (!check_valid_to_render(ctx, "Elements"))
+   if (!check_valid_to_render(ctx, "glDrawElements"))
       return GL_FALSE;
 
    /* Vertex buffer object tests */
-   if (ctx->Array.ElementArrayBufferObj->Name) {
+   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) {
@@ -178,17 +211,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;
 }
@@ -203,7 +227,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);
 
@@ -233,11 +257,11 @@ _mesa_validate_DrawRangeElements(GLcontext *ctx, GLenum mode,
    if (ctx->NewState)
       _mesa_update_state(ctx);
 
-   if (!check_valid_to_render(ctx, "RangeElements"))
+   if (!check_valid_to_render(ctx, "glDrawRangeElements"))
       return GL_FALSE;
 
    /* Vertex buffer object tests */
-   if (ctx->Array.ElementArrayBufferObj->Name) {
+   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) {
@@ -251,14 +275,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;
 }
@@ -289,7 +307,7 @@ _mesa_validate_DrawArrays(GLcontext *ctx,
    if (ctx->NewState)
       _mesa_update_state(ctx);
 
-   if (!check_valid_to_render(ctx, "Arrays"))
+   if (!check_valid_to_render(ctx, "glDrawArrays"))
       return GL_FALSE;
 
    if (ctx->Const.CheckArrayBounds) {