Commit f5c88e7e by Jamie Madill Committed by Commit Bot

Refactor and inline DrawElements validation.

This moves ValidateDrawBase into a common inline function. It also moves some checks in ValidateDrawElementsCommon into ValidateDrawElementsBase. "Base" is called from DrawElementsIndirect while "Common" is only called from non-indirect entry points. But this improves conformance because the missing checks in "Base" apply to DrawIndirect as well. In a follow-up patch many checks in "Base" will be cached into a single value. Much like what we did for ValidateDrawBase. Also inlines ValidateDrawElements which just calls through to "Common". Bug: angleproject:2966 Change-Id: Ibe0c5db25f403dd52a50dc73373ebb50cedad003 Reviewed-on: https://chromium-review.googlesource.com/c/1357147 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarYuly Novikov <ynovikov@chromium.org>
parent 149eb33b
......@@ -2823,36 +2823,6 @@ bool ValidateDrawMode(Context *context, PrimitiveMode mode)
return true;
}
bool ValidateDrawBase(Context *context, PrimitiveMode mode, GLsizei count)
{
if (!context->getStateCache().isValidDrawMode(mode))
{
return ValidateDrawMode(context, mode);
}
if (count < 0)
{
context->validationError(GL_INVALID_VALUE, kNegativeCount);
return false;
}
intptr_t drawStatesError = context->getStateCache().getBasicDrawStatesError(context);
if (drawStatesError)
{
const char *errorMessage = reinterpret_cast<const char *>(drawStatesError);
// All errors from ValidateDrawStates should return INVALID_OPERATION except Framebuffer
// Incomplete.
GLenum errorCode =
(errorMessage == kDrawFramebufferIncomplete ? GL_INVALID_FRAMEBUFFER_OPERATION
: GL_INVALID_OPERATION);
context->validationError(errorCode, errorMessage);
return false;
}
return true;
}
bool ValidateDrawArraysCommon(Context *context,
PrimitiveMode mode,
GLint first,
......@@ -2865,9 +2835,8 @@ bool ValidateDrawArraysCommon(Context *context,
return false;
}
if (count < 0)
if (!ValidateDrawBase(context, mode, count))
{
context->validationError(GL_INVALID_VALUE, kNegativeCount);
return false;
}
......@@ -2890,25 +2859,6 @@ bool ValidateDrawArraysCommon(Context *context,
}
}
if (!context->getStateCache().isValidDrawMode(mode))
{
return ValidateDrawMode(context, mode);
}
intptr_t drawStatesError = context->getStateCache().getBasicDrawStatesError(context);
if (drawStatesError)
{
const char *errorMessage = reinterpret_cast<const char *>(drawStatesError);
// All errors from ValidateDrawStates should return INVALID_OPERATION except Framebuffer
// Incomplete.
GLenum errorCode =
(errorMessage == kDrawFramebufferIncomplete ? GL_INVALID_FRAMEBUFFER_OPERATION
: GL_INVALID_OPERATION);
context->validationError(errorCode, errorMessage);
return false;
}
// Check the computation of maxVertex doesn't overflow.
// - first < 0 has been checked as an error condition.
// - if count < 0, skip validating no-op draw calls.
......@@ -2967,6 +2917,7 @@ bool ValidateDrawElementsBase(Context *context, PrimitiveMode mode, DrawElements
return false;
}
// TODO(jmadill): Cache all of these into fast checks. http://anglebug.com/2966
const State &state = context->getGLState();
TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
......@@ -2995,6 +2946,42 @@ bool ValidateDrawElementsBase(Context *context, PrimitiveMode mode, DrawElements
}
}
const VertexArray *vao = state.getVertexArray();
Buffer *elementArrayBuffer = vao->getElementArrayBuffer();
if (elementArrayBuffer)
{
if (context->getExtensions().webglCompatibility)
{
if (elementArrayBuffer->isBoundForTransformFeedbackAndOtherUse())
{
context->validationError(GL_INVALID_OPERATION,
kElementArrayBufferBoundForTransformFeedback);
return false;
}
}
else if (elementArrayBuffer->isMapped())
{
// WebGL buffers cannot be mapped/unmapped because the MapBufferRange,
// FlushMappedBufferRange, and UnmapBuffer entry points are removed from the
// WebGL 2.0 API. https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
context->validationError(GL_INVALID_OPERATION, kBufferMapped);
return false;
}
}
else
{
// [WebGL 1.0] Section 6.2 No Client Side Arrays
// If an indexed draw command (drawElements) is called and no WebGLBuffer is bound to
// the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
if (!context->getGLState().areClientArraysEnabled() ||
context->getExtensions().webglCompatibility)
{
context->validationError(GL_INVALID_OPERATION, kMustHaveElementArrayBinding);
return false;
}
}
return true;
}
......@@ -3006,15 +2993,16 @@ bool ValidateDrawElementsCommon(Context *context,
GLsizei primcount)
{
if (!ValidateDrawElementsBase(context, mode, type))
{
return false;
const State &state = context->getGLState();
}
if (!ValidateDrawBase(context, mode, count))
{
return false;
}
const State &state = context->getGLState();
const VertexArray *vao = state.getVertexArray();
Buffer *elementArrayBuffer = vao->getElementArrayBuffer();
......@@ -3040,45 +3028,14 @@ bool ValidateDrawElementsCommon(Context *context,
context->validationError(GL_INVALID_VALUE, kNegativeOffset);
return false;
}
if (!elementArrayBuffer)
{
// [WebGL 1.0] Section 6.2 No Client Side Arrays
// If an indexed draw command (drawElements) is called and no WebGLBuffer is bound to
// the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
context->validationError(GL_INVALID_OPERATION, kMustHaveElementArrayBinding);
return false;
}
if (elementArrayBuffer->isBoundForTransformFeedbackAndOtherUse())
// Early exit.
if (count == 0)
{
context->validationError(GL_INVALID_OPERATION,
kElementArrayBufferBoundForTransformFeedback);
return false;
}
}
else
{
if (elementArrayBuffer)
{
if (elementArrayBuffer->isMapped())
{
// WebGL buffers cannot be mapped/unmapped because the MapBufferRange,
// FlushMappedBufferRange, and UnmapBuffer entry points are removed from the
// WebGL 2.0 API. https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
context->validationError(GL_INVALID_OPERATION, kBufferMapped);
return false;
}
}
else if (!context->getGLState().areClientArraysEnabled())
{
context->validationError(GL_INVALID_OPERATION, kMustHaveElementArrayBinding);
return false;
}
return true;
}
if (count > 0)
{
if (!elementArrayBuffer)
{
if (!indices)
......@@ -3145,7 +3102,6 @@ bool ValidateDrawElementsCommon(Context *context,
// No op if there are no real indices in the index data (all are primitive restart).
return (indexRange.vertexIndexCount > 0);
}
}
return true;
}
......
......@@ -286,7 +286,38 @@ bool ValidateCopyTexImageParametersBase(Context *context,
GLint border,
Format *textureFormatOut);
bool ValidateDrawBase(Context *context, PrimitiveMode mode, GLsizei count);
bool ValidateDrawMode(Context *context, PrimitiveMode mode);
ANGLE_INLINE bool ValidateDrawBase(Context *context, PrimitiveMode mode, GLsizei count)
{
if (!context->getStateCache().isValidDrawMode(mode))
{
return ValidateDrawMode(context, mode);
}
if (count < 0)
{
context->validationError(GL_INVALID_VALUE, err::kNegativeCount);
return false;
}
intptr_t drawStatesError = context->getStateCache().getBasicDrawStatesError(context);
if (drawStatesError)
{
const char *errorMessage = reinterpret_cast<const char *>(drawStatesError);
// All errors from ValidateDrawStates should return INVALID_OPERATION except Framebuffer
// Incomplete.
GLenum errorCode =
(errorMessage == err::kDrawFramebufferIncomplete ? GL_INVALID_FRAMEBUFFER_OPERATION
: GL_INVALID_OPERATION);
context->validationError(errorCode, errorMessage);
return false;
}
return true;
}
bool ValidateDrawArraysCommon(Context *context,
PrimitiveMode mode,
GLint first,
......
......@@ -5771,15 +5771,6 @@ bool ValidateViewport(Context *context, GLint x, GLint y, GLsizei width, GLsizei
return true;
}
bool ValidateDrawElements(Context *context,
PrimitiveMode mode,
GLsizei count,
DrawElementsType type,
const void *indices)
{
return ValidateDrawElementsCommon(context, mode, count, type, indices, 1);
}
bool ValidateGetFramebufferAttachmentParameteriv(Context *context,
GLenum target,
GLenum attachment,
......
......@@ -45,6 +45,15 @@ ANGLE_INLINE bool ValidateBindBuffer(Context *context, BufferBinding target, GLu
return true;
}
ANGLE_INLINE bool ValidateDrawElements(Context *context,
PrimitiveMode mode,
GLsizei count,
DrawElementsType type,
const void *indices)
{
return ValidateDrawElementsCommon(context, mode, count, type, indices, 1);
}
} // namespace gl
#endif // LIBANGLE_VALIDATION_ES2_H_
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment