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) ...@@ -2823,36 +2823,6 @@ bool ValidateDrawMode(Context *context, PrimitiveMode mode)
return true; 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, bool ValidateDrawArraysCommon(Context *context,
PrimitiveMode mode, PrimitiveMode mode,
GLint first, GLint first,
...@@ -2865,9 +2835,8 @@ bool ValidateDrawArraysCommon(Context *context, ...@@ -2865,9 +2835,8 @@ bool ValidateDrawArraysCommon(Context *context,
return false; return false;
} }
if (count < 0) if (!ValidateDrawBase(context, mode, count))
{ {
context->validationError(GL_INVALID_VALUE, kNegativeCount);
return false; return false;
} }
...@@ -2890,25 +2859,6 @@ bool ValidateDrawArraysCommon(Context *context, ...@@ -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. // Check the computation of maxVertex doesn't overflow.
// - first < 0 has been checked as an error condition. // - first < 0 has been checked as an error condition.
// - if count < 0, skip validating no-op draw calls. // - if count < 0, skip validating no-op draw calls.
...@@ -2967,6 +2917,7 @@ bool ValidateDrawElementsBase(Context *context, PrimitiveMode mode, DrawElements ...@@ -2967,6 +2917,7 @@ bool ValidateDrawElementsBase(Context *context, PrimitiveMode mode, DrawElements
return false; return false;
} }
// TODO(jmadill): Cache all of these into fast checks. http://anglebug.com/2966
const State &state = context->getGLState(); const State &state = context->getGLState();
TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback(); TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
...@@ -2995,6 +2946,42 @@ bool ValidateDrawElementsBase(Context *context, PrimitiveMode mode, DrawElements ...@@ -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; return true;
} }
...@@ -3006,15 +2993,16 @@ bool ValidateDrawElementsCommon(Context *context, ...@@ -3006,15 +2993,16 @@ bool ValidateDrawElementsCommon(Context *context,
GLsizei primcount) GLsizei primcount)
{ {
if (!ValidateDrawElementsBase(context, mode, type)) if (!ValidateDrawElementsBase(context, mode, type))
{
return false; return false;
}
const State &state = context->getGLState();
if (!ValidateDrawBase(context, mode, count)) if (!ValidateDrawBase(context, mode, count))
{ {
return false; return false;
} }
const State &state = context->getGLState();
const VertexArray *vao = state.getVertexArray(); const VertexArray *vao = state.getVertexArray();
Buffer *elementArrayBuffer = vao->getElementArrayBuffer(); Buffer *elementArrayBuffer = vao->getElementArrayBuffer();
...@@ -3040,45 +3028,14 @@ bool ValidateDrawElementsCommon(Context *context, ...@@ -3040,45 +3028,14 @@ bool ValidateDrawElementsCommon(Context *context,
context->validationError(GL_INVALID_VALUE, kNegativeOffset); context->validationError(GL_INVALID_VALUE, kNegativeOffset);
return false; 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, return true;
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;
}
} }
if (count > 0)
{
if (!elementArrayBuffer) if (!elementArrayBuffer)
{ {
if (!indices) if (!indices)
...@@ -3145,7 +3102,6 @@ bool ValidateDrawElementsCommon(Context *context, ...@@ -3145,7 +3102,6 @@ bool ValidateDrawElementsCommon(Context *context,
// No op if there are no real indices in the index data (all are primitive restart). // No op if there are no real indices in the index data (all are primitive restart).
return (indexRange.vertexIndexCount > 0); return (indexRange.vertexIndexCount > 0);
} }
}
return true; return true;
} }
......
...@@ -286,7 +286,38 @@ bool ValidateCopyTexImageParametersBase(Context *context, ...@@ -286,7 +286,38 @@ bool ValidateCopyTexImageParametersBase(Context *context,
GLint border, GLint border,
Format *textureFormatOut); 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, bool ValidateDrawArraysCommon(Context *context,
PrimitiveMode mode, PrimitiveMode mode,
GLint first, GLint first,
......
...@@ -5771,15 +5771,6 @@ bool ValidateViewport(Context *context, GLint x, GLint y, GLsizei width, GLsizei ...@@ -5771,15 +5771,6 @@ bool ValidateViewport(Context *context, GLint x, GLint y, GLsizei width, GLsizei
return true; 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, bool ValidateGetFramebufferAttachmentParameteriv(Context *context,
GLenum target, GLenum target,
GLenum attachment, GLenum attachment,
......
...@@ -45,6 +45,15 @@ ANGLE_INLINE bool ValidateBindBuffer(Context *context, BufferBinding target, GLu ...@@ -45,6 +45,15 @@ ANGLE_INLINE bool ValidateBindBuffer(Context *context, BufferBinding target, GLu
return true; 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 } // namespace gl
#endif // LIBANGLE_VALIDATION_ES2_H_ #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