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@fastmail.fm>
Reviewed-by: Brian Paul <brianp@vmware.com>
Reviewed-by: Paul Berry <stereotype441@gmail.com>
This commit is contained in:
Fabian Bieler 2013-05-25 13:33:42 +02:00 committed by Paul Berry
parent ac74de3710
commit cd18269705
2 changed files with 42 additions and 21 deletions

View file

@ -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;

View file

@ -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;