Mesa (master): mesa/main: Check for 0 size draws after validation.

Paul Berry stereotype441 at kemper.freedesktop.org
Tue Aug 27 22:19:30 UTC 2013


Module: Mesa
Branch: master
Commit: cd18269705c948f5141478a48cf82a1fddd06b83
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=cd18269705c948f5141478a48cf82a1fddd06b83

Author: Fabian Bieler <fabianbieler at fastmail.fm>
Date:   Sat May 25 13:33:42 2013 +0200

mesa/main: Check for 0 size draws after validation.

When validating draw parameters move check for 0 draw count last
(drawing with count 0 is not an error), so that other parameters (e.g.: the
primitive type) are validated and the correct errors (if applicable) are
generated.

>From the OpenGL 3.3 spec page 33 (page 48 of the PDF):
"[Regarding DrawArraysOneInstance, in terms of which other draw operations
are defined:]
If count is negative, an INVALID_VALUE error is generated."

This patch also changes the bahavior of MultiDrawElements to perform the draw
operation if some primitive's index counts are zero.

Signed-off-by: Fabian Bieler <fabianbieler at fastmail.fm>
Reviewed-by: Brian Paul <brianp at vmware.com>
Reviewed-by: Paul Berry <stereotype441 at gmail.com>

---

 src/mesa/main/api_validate.c  |   51 ++++++++++++++++++++++++-----------------
 src/mesa/vbo/vbo_exec_array.c |   12 +++++++++
 2 files changed, 42 insertions(+), 21 deletions(-)

diff --git a/src/mesa/main/api_validate.c b/src/mesa/main/api_validate.c
index 243bb89..0029921 100644
--- a/src/mesa/main/api_validate.c
+++ b/src/mesa/main/api_validate.c
@@ -402,9 +402,8 @@ _mesa_validate_DrawElements(struct gl_context *ctx,
       return GL_FALSE;
    }
 
-   if (count <= 0) {
-      if (count < 0)
-	 _mesa_error(ctx, GL_INVALID_VALUE, "glDrawElements(count)" );
+   if (count < 0) {
+      _mesa_error(ctx, GL_INVALID_VALUE, "glDrawElements(count)" );
       return GL_FALSE;
    }
 
@@ -436,6 +435,9 @@ _mesa_validate_DrawElements(struct gl_context *ctx,
    if (!check_index_bounds(ctx, count, type, indices, basevertex))
       return GL_FALSE;
 
+   if (count == 0)
+      return GL_FALSE;
+
    return GL_TRUE;
 }
 
@@ -456,10 +458,9 @@ _mesa_validate_MultiDrawElements(struct gl_context *ctx,
    FLUSH_CURRENT(ctx, 0);
 
    for (i = 0; i < primcount; i++) {
-      if (count[i] <= 0) {
-         if (count[i] < 0)
-            _mesa_error(ctx, GL_INVALID_VALUE,
-                        "glMultiDrawElements(count)" );
+      if (count[i] < 0) {
+         _mesa_error(ctx, GL_INVALID_VALUE,
+                     "glMultiDrawElements(count)" );
          return GL_FALSE;
       }
    }
@@ -531,9 +532,8 @@ _mesa_validate_DrawRangeElements(struct gl_context *ctx, GLenum mode,
       return GL_FALSE;
    }
 
-   if (count <= 0) {
-      if (count < 0)
-	 _mesa_error(ctx, GL_INVALID_VALUE, "glDrawRangeElements(count)" );
+   if (count < 0) {
+      _mesa_error(ctx, GL_INVALID_VALUE, "glDrawRangeElements(count)" );
       return GL_FALSE;
    }
 
@@ -570,6 +570,9 @@ _mesa_validate_DrawRangeElements(struct gl_context *ctx, GLenum mode,
    if (!check_index_bounds(ctx, count, type, indices, basevertex))
       return GL_FALSE;
 
+   if (count == 0)
+      return GL_FALSE;
+
    return GL_TRUE;
 }
 
@@ -587,9 +590,8 @@ _mesa_validate_DrawArrays(struct gl_context *ctx,
       = ctx->TransformFeedback.CurrentObject;
    FLUSH_CURRENT(ctx, 0);
 
-   if (count <= 0) {
-      if (count < 0)
-         _mesa_error(ctx, GL_INVALID_VALUE, "glDrawArrays(count)" );
+   if (count < 0) {
+      _mesa_error(ctx, GL_INVALID_VALUE, "glDrawArrays(count)" );
       return GL_FALSE;
    }
 
@@ -628,6 +630,9 @@ _mesa_validate_DrawArrays(struct gl_context *ctx,
       xfb_obj->GlesRemainingPrims -= prim_count;
    }
 
+   if (count == 0)
+      return GL_FALSE;
+
    return GL_TRUE;
 }
 
@@ -640,10 +645,9 @@ _mesa_validate_DrawArraysInstanced(struct gl_context *ctx, GLenum mode, GLint fi
       = ctx->TransformFeedback.CurrentObject;
    FLUSH_CURRENT(ctx, 0);
 
-   if (count <= 0) {
-      if (count < 0)
-         _mesa_error(ctx, GL_INVALID_VALUE,
-                     "glDrawArraysInstanced(count=%d)", count);
+   if (count < 0) {
+      _mesa_error(ctx, GL_INVALID_VALUE,
+                  "glDrawArraysInstanced(count=%d)", count);
       return GL_FALSE;
    }
 
@@ -696,6 +700,9 @@ _mesa_validate_DrawArraysInstanced(struct gl_context *ctx, GLenum mode, GLint fi
       xfb_obj->GlesRemainingPrims -= prim_count;
    }
 
+   if (count == 0)
+      return GL_FALSE;
+
    return GL_TRUE;
 }
 
@@ -721,10 +728,9 @@ _mesa_validate_DrawElementsInstanced(struct gl_context *ctx,
       return GL_FALSE;
    }
 
-   if (count <= 0) {
-      if (count < 0)
-	 _mesa_error(ctx, GL_INVALID_VALUE,
-                     "glDrawElementsInstanced(count=%d)", count);
+   if (count < 0) {
+      _mesa_error(ctx, GL_INVALID_VALUE,
+                  "glDrawElementsInstanced(count=%d)", count);
       return GL_FALSE;
    }
 
@@ -761,6 +767,9 @@ _mesa_validate_DrawElementsInstanced(struct gl_context *ctx,
          return GL_FALSE;
    }
 
+   if (count == 0)
+      return GL_FALSE;
+
    if (!check_index_bounds(ctx, count, type, indices, basevertex))
       return GL_FALSE;
 
diff --git a/src/mesa/vbo/vbo_exec_array.c b/src/mesa/vbo/vbo_exec_array.c
index bd05cd0..1670409 100644
--- a/src/mesa/vbo/vbo_exec_array.c
+++ b/src/mesa/vbo/vbo_exec_array.c
@@ -1334,6 +1334,16 @@ vbo_validated_multidrawelements(struct gl_context *ctx, GLenum mode,
       }
    }
 
+   /* Draw primitives individually if one count is zero, so we can easily skip
+    * that primitive.
+    */
+   for (i = 0; i < primcount; i++) {
+      if (count[i] == 0) {
+         fallback = GL_TRUE;
+         break;
+      }
+   }
+
    /* If the index buffer isn't in a VBO, then treating the application's
     * subranges of the index buffer as one large index buffer may lead to
     * us reading unmapped memory.
@@ -1370,6 +1380,8 @@ vbo_validated_multidrawelements(struct gl_context *ctx, GLenum mode,
    } else {
       /* render one prim at a time */
       for (i = 0; i < primcount; i++) {
+	 if (count[i] == 0)
+	    continue;
 	 ib.count = count[i];
 	 ib.type = type;
 	 ib.obj = ctx->Array.ArrayObj->ElementArrayBufferObj;




More information about the mesa-commit mailing list