[Mesa-dev] [PATCH 3/3] mesa/main: Check for 0 size draws after validation.

Fabian Bieler fabianbieler at fastmail.fm
Fri Jun 14 04:37:09 PDT 2013


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>
---
 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 7ab8e30..0770f94 100644
--- a/src/mesa/main/api_validate.c
+++ b/src/mesa/main/api_validate.c
@@ -334,9 +334,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;
    }
 
@@ -368,6 +367,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;
 }
 
@@ -388,10 +390,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;
       }
    }
@@ -463,9 +464,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;
    }
 
@@ -502,6 +502,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;
 }
 
@@ -519,9 +522,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;
    }
 
@@ -560,6 +562,9 @@ _mesa_validate_DrawArrays(struct gl_context *ctx,
       xfb_obj->GlesRemainingPrims -= prim_count;
    }
 
+   if (count == 0)
+      return GL_FALSE;
+
    return GL_TRUE;
 }
 
@@ -572,10 +577,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;
    }
 
@@ -628,6 +632,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;
 }
 
@@ -653,10 +660,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;
    }
 
@@ -693,6 +699,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 9dadd04..c080000 100644
--- a/src/mesa/vbo/vbo_exec_array.c
+++ b/src/mesa/vbo/vbo_exec_array.c
@@ -1298,6 +1298,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.
@@ -1334,6 +1344,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;
-- 
1.8.1.2



More information about the mesa-dev mailing list