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