Commit c95c158d authored by qiankun.miao's avatar qiankun.miao Committed by Commit bot

Validate bound buffer for draw calls

DrawArrays or drawElements should generate invalid operation error if no
buffer is bound to enabled attribution. Refer WebGL 1.0 spec for details
in section 6.5 "Enabled Vertex Attributes and Range Checking".

BUG=295792
TEST=conformance2/vertex_arrays/vertex-array-object.html
CQ_INCLUDE_TRYBOTS=tryserver.chromium.win:win_optional_gpu_tests_rel;tryserver.chromium.mac:mac_optional_gpu_tests_rel

Review-Url: https://codereview.chromium.org/2019513004
Cr-Commit-Position: refs/heads/master@{#398246}
parent 2d6574bd
......@@ -1542,6 +1542,11 @@ void WebGL2RenderingContextBase::drawArraysInstanced(GLenum mode, GLint first, G
if (!validateDrawArrays("drawArraysInstanced"))
return;
if (!m_boundVertexArrayObject->isAllEnabledAttribBufferBound()) {
synthesizeGLError(GL_INVALID_OPERATION, "drawArraysInstanced", "no buffer is bound to enabled attribute");
return;
}
ScopedRGBEmulationColorMask emulationColorMask(contextGL(), m_colorMask, m_drawingBuffer.get());
clearIfComposited();
contextGL()->DrawArraysInstancedANGLE(mode, first, count, instanceCount);
......@@ -1553,6 +1558,11 @@ void WebGL2RenderingContextBase::drawElementsInstanced(GLenum mode, GLsizei coun
if (!validateDrawElements("drawElementsInstanced", type, offset))
return;
if (!m_boundVertexArrayObject->isAllEnabledAttribBufferBound()) {
synthesizeGLError(GL_INVALID_OPERATION, "drawElementsInstanced", "no buffer is bound to enabled attribute");
return;
}
if (transformFeedbackActive() && !transformFeedbackPaused()) {
synthesizeGLError(GL_INVALID_OPERATION, "drawElementsInstanced", "transform feedback is active and not paused");
return;
......@@ -1569,6 +1579,11 @@ void WebGL2RenderingContextBase::drawRangeElements(GLenum mode, GLuint start, GL
if (!validateDrawElements("drawRangeElements", type, offset))
return;
if (!m_boundVertexArrayObject->isAllEnabledAttribBufferBound()) {
synthesizeGLError(GL_INVALID_OPERATION, "drawRangeElements", "no buffer is bound to enabled attribute");
return;
}
if (transformFeedbackActive() && !transformFeedbackPaused()) {
synthesizeGLError(GL_INVALID_OPERATION, "drawRangeElements", "transform feedback is active and not paused");
return;
......
......@@ -2184,6 +2184,7 @@ void WebGLRenderingContextBase::disableVertexAttribArray(GLuint index)
return;
}
m_boundVertexArrayObject->setAttribEnabled(index, false);
contextGL()->DisableVertexAttribArray(index);
}
......@@ -2216,6 +2217,11 @@ void WebGLRenderingContextBase::drawArrays(GLenum mode, GLint first, GLsizei cou
if (!validateDrawArrays("drawArrays"))
return;
if (!m_boundVertexArrayObject->isAllEnabledAttribBufferBound()) {
synthesizeGLError(GL_INVALID_OPERATION, "drawArrays", "no buffer is bound to enabled attribute");
return;
}
ScopedRGBEmulationColorMask emulationColorMask(contextGL(), m_colorMask, m_drawingBuffer.get());
clearIfComposited();
contextGL()->DrawArrays(mode, first, count);
......@@ -2227,6 +2233,11 @@ void WebGLRenderingContextBase::drawElements(GLenum mode, GLsizei count, GLenum
if (!validateDrawElements("drawElements", type, offset))
return;
if (!m_boundVertexArrayObject->isAllEnabledAttribBufferBound()) {
synthesizeGLError(GL_INVALID_OPERATION, "drawElements", "no buffer is bound to enabled attribute");
return;
}
if (transformFeedbackActive() && !transformFeedbackPaused()) {
synthesizeGLError(GL_INVALID_OPERATION, "drawElements", "transform feedback is active and not paused");
return;
......@@ -2243,6 +2254,11 @@ void WebGLRenderingContextBase::drawArraysInstancedANGLE(GLenum mode, GLint firs
if (!validateDrawArrays("drawArraysInstancedANGLE"))
return;
if (!m_boundVertexArrayObject->isAllEnabledAttribBufferBound()) {
synthesizeGLError(GL_INVALID_OPERATION, "drawArraysInstancedANGLE", "no buffer is bound to enabled attribute");
return;
}
ScopedRGBEmulationColorMask emulationColorMask(contextGL(), m_colorMask, m_drawingBuffer.get());
clearIfComposited();
contextGL()->DrawArraysInstancedANGLE(mode, first, count, primcount);
......@@ -2254,6 +2270,11 @@ void WebGLRenderingContextBase::drawElementsInstancedANGLE(GLenum mode, GLsizei
if (!validateDrawElements("drawElementsInstancedANGLE", type, offset))
return;
if (!m_boundVertexArrayObject->isAllEnabledAttribBufferBound()) {
synthesizeGLError(GL_INVALID_OPERATION, "drawElementsInstancedANGLE", "no buffer is bound to enabled attribute");
return;
}
ScopedRGBEmulationColorMask emulationColorMask(contextGL(), m_colorMask, m_drawingBuffer.get());
clearIfComposited();
contextGL()->DrawElementsInstancedANGLE(mode, count, type, reinterpret_cast<void*>(static_cast<intptr_t>(offset)), primcount);
......@@ -2285,6 +2306,7 @@ void WebGLRenderingContextBase::enableVertexAttribArray(GLuint index)
return;
}
m_boundVertexArrayObject->setAttribEnabled(index, true);
contextGL()->EnableVertexAttribArray(index);
}
......
......@@ -16,8 +16,13 @@ WebGLVertexArrayObjectBase::WebGLVertexArrayObjectBase(WebGLRenderingContextBase
, m_hasEverBeenBound(false)
, m_destructionInProgress(false)
, m_boundElementArrayBuffer(nullptr)
, m_isAllEnabledAttribBufferBound(true)
{
m_arrayBufferList.resize(ctx->maxVertexAttribs());
m_attribEnabled.resize(ctx->maxVertexAttribs());
for (size_t i = 0; i < m_attribEnabled.size(); ++i) {
m_attribEnabled[i] = false;
}
switch (m_type) {
case VaoTypeDefault:
......@@ -80,7 +85,7 @@ void WebGLVertexArrayObjectBase::setElementArrayBuffer(WebGLBuffer* buffer)
WebGLBuffer* WebGLVertexArrayObjectBase::getArrayBufferForAttrib(size_t index)
{
ASSERT(index < context()->maxVertexAttribs());
DCHECK(index < context()->maxVertexAttribs());
return m_arrayBufferList[index].get();
}
......@@ -92,6 +97,31 @@ void WebGLVertexArrayObjectBase::setArrayBufferForAttrib(GLuint index, WebGLBuff
m_arrayBufferList[index]->onDetached(context()->contextGL());
m_arrayBufferList[index] = buffer;
updateAttribBufferBoundStatus();
}
void WebGLVertexArrayObjectBase::setAttribEnabled(GLuint index, bool enabled)
{
DCHECK(index < context()->maxVertexAttribs());
m_attribEnabled[index] = enabled;
updateAttribBufferBoundStatus();
}
bool WebGLVertexArrayObjectBase::getAttribEnabled(GLuint index) const
{
DCHECK(index < context()->maxVertexAttribs());
return m_attribEnabled[index];
}
void WebGLVertexArrayObjectBase::updateAttribBufferBoundStatus()
{
m_isAllEnabledAttribBufferBound = true;
for (size_t i = 0; i < m_attribEnabled.size(); ++i) {
if (m_attribEnabled[i] && !m_arrayBufferList[i]) {
m_isAllEnabledAttribBufferBound = false;
return;
}
}
}
void WebGLVertexArrayObjectBase::unbindBuffer(WebGLBuffer* buffer)
......@@ -107,6 +137,7 @@ void WebGLVertexArrayObjectBase::unbindBuffer(WebGLBuffer* buffer)
m_arrayBufferList[i] = nullptr;
}
}
updateAttribBufferBoundStatus();
}
ScopedPersistent<v8::Array>* WebGLVertexArrayObjectBase::getPersistentCache()
......
......@@ -33,6 +33,9 @@ public:
WebGLBuffer* getArrayBufferForAttrib(size_t);
void setArrayBufferForAttrib(GLuint, WebGLBuffer*);
void setAttribEnabled(GLuint, bool);
bool getAttribEnabled(GLuint) const;
bool isAllEnabledAttribBufferBound() const { return m_isAllEnabledAttribBufferBound; }
void unbindBuffer(WebGLBuffer*);
ScopedPersistent<v8::Array>* getPersistentCache();
......@@ -47,6 +50,8 @@ private:
bool hasObject() const override { return m_object != 0; }
void deleteObjectImpl(gpu::gles2::GLES2Interface*) override;
void updateAttribBufferBoundStatus();
GLuint m_object;
VaoType m_type;
......@@ -54,6 +59,8 @@ private:
bool m_destructionInProgress;
Member<WebGLBuffer> m_boundElementArrayBuffer;
HeapVector<Member<WebGLBuffer>> m_arrayBufferList;
Vector<bool> m_attribEnabled;
bool m_isAllEnabledAttribBufferBound;
// For preserving the wrappers of WebGLBuffer objects latched in
// via vertexAttribPointer calls.
......
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