Commit ce8602ab by Kenneth Russell Committed by Commit Bot

WebGL requires GL_FRAMEBUFFER_UNSUPPORTED for identical FBO attachments.

If the same level of a texture is attached to multiple color attachments of a framebuffer object, for example, the WebGL conformance tests require generating a GL_FRAMEBUFFER_UNSUPPORTED error. The Direct3D backend already had this restriction; apply it to all backends when the WebGL compatibility extension is enabled. Fixes the following WebGL conformance tests with the pass-through command decoder in Chrome: conformance/extensions/webgl-draw-buffers-framebuffer-unsupported conformance2/rendering/framebuffer-unsupported BUG=angleproject:2168 Change-Id: I340d06ca0ee969989c6c5725512b1b9542281477 Reviewed-on: https://chromium-review.googlesource.com/699856 Commit-Queue: Kenneth Russell <kbr@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent c1abf917
......@@ -1125,8 +1125,19 @@ GLenum Framebuffer::checkStatusImpl(const Context *context)
return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
}
// The WebGL conformance tests implicitly define that all framebuffer
// attachments must be unique. For example, the same level of a texture can
// not be attached to two different color attachments.
if (state.getExtensions().webglCompatibility)
{
if (!mState.colorAttachmentsAreUniqueImages())
{
return GL_FRAMEBUFFER_UNSUPPORTED;
}
}
syncState(context);
if (!mImpl->checkStatus())
if (!mImpl->checkStatus(context))
{
return GL_FRAMEBUFFER_UNSUPPORTED;
}
......
......@@ -78,7 +78,7 @@ class FramebufferImpl : angle::NonCopyable
GLbitfield mask,
GLenum filter) = 0;
virtual bool checkStatus() const = 0;
virtual bool checkStatus(const gl::Context *context) const = 0;
virtual void syncState(const gl::Context *context,
const gl::Framebuffer::DirtyBits &dirtyBits) = 0;
......
......@@ -48,7 +48,7 @@ class MockFramebufferImpl : public rx::FramebufferImpl
GLbitfield,
GLenum));
MOCK_CONST_METHOD0(checkStatus, bool());
MOCK_CONST_METHOD1(checkStatus, bool(const gl::Context *));
MOCK_METHOD2(syncState, void(const gl::Context *, const gl::Framebuffer::DirtyBits &));
......@@ -60,7 +60,7 @@ inline ::testing::NiceMock<MockFramebufferImpl> *MakeFramebufferMock()
::testing::NiceMock<MockFramebufferImpl> *framebufferImpl =
new ::testing::NiceMock<MockFramebufferImpl>();
// TODO(jmadill): add ON_CALLS for other returning methods
ON_CALL(*framebufferImpl, checkStatus()).WillByDefault(::testing::Return(true));
ON_CALL(*framebufferImpl, checkStatus(testing::_)).WillByDefault(::testing::Return(true));
// We must mock the destructor since NiceMock doesn't work for destructors.
EXPECT_CALL(*framebufferImpl, destructor()).Times(1).RetiresOnSaturation();
......
......@@ -285,7 +285,7 @@ gl::Error FramebufferD3D::blit(const gl::Context *context,
return gl::NoError();
}
bool FramebufferD3D::checkStatus() const
bool FramebufferD3D::checkStatus(const gl::Context *context) const
{
// if we have both a depth and stencil buffer, they must refer to the same object
// since we only support packed_depth_stencil and not separate depth and stencil
......@@ -295,10 +295,15 @@ bool FramebufferD3D::checkStatus() const
return false;
}
// D3D11 does not allow for overlapping RenderTargetViews
if (!mState.colorAttachmentsAreUniqueImages())
// D3D11 does not allow for overlapping RenderTargetViews.
// If WebGL compatibility is enabled, this has already been checked at a higher level.
ASSERT(!context->getExtensions().webglCompatibility || mState.colorAttachmentsAreUniqueImages());
if (!context->getExtensions().webglCompatibility)
{
return false;
if (!mState.colorAttachmentsAreUniqueImages())
{
return false;
}
}
// D3D requires all render targets to have the same dimensions.
......
......@@ -92,7 +92,7 @@ class FramebufferD3D : public FramebufferImpl
GLbitfield mask,
GLenum filter) override;
bool checkStatus() const override;
bool checkStatus(const gl::Context *context) const override;
void syncState(const gl::Context *context,
const gl::Framebuffer::DirtyBits &dirtyBits) override;
......
......@@ -594,7 +594,7 @@ gl::Error FramebufferGL::getSamplePosition(size_t index, GLfloat *xy) const
return gl::NoError();
}
bool FramebufferGL::checkStatus() const
bool FramebufferGL::checkStatus(const gl::Context *context) const
{
mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
GLenum status = mFunctions->checkFramebufferStatus(GL_FRAMEBUFFER);
......
......@@ -87,7 +87,7 @@ class FramebufferGL : public FramebufferImpl
gl::Error getSamplePosition(size_t index, GLfloat *xy) const override;
bool checkStatus() const override;
bool checkStatus(const gl::Context *context) const override;
void syncState(const gl::Context *context,
const gl::Framebuffer::DirtyBits &dirtyBits) override;
......
......@@ -179,7 +179,7 @@ gl::Error FramebufferNULL::blit(const gl::Context *context,
return gl::NoError();
}
bool FramebufferNULL::checkStatus() const
bool FramebufferNULL::checkStatus(const gl::Context *context) const
{
return true;
}
......
......@@ -63,7 +63,7 @@ class FramebufferNULL : public FramebufferImpl
GLbitfield mask,
GLenum filter) override;
bool checkStatus() const override;
bool checkStatus(const gl::Context *context) const override;
void syncState(const gl::Context *context,
const gl::Framebuffer::DirtyBits &dirtyBits) override;
......
......@@ -346,7 +346,7 @@ gl::Error FramebufferVk::blit(const gl::Context *context,
return gl::InternalError();
}
bool FramebufferVk::checkStatus() const
bool FramebufferVk::checkStatus(const gl::Context *context) const
{
UNIMPLEMENTED();
return bool();
......
......@@ -76,7 +76,7 @@ class FramebufferVk : public FramebufferImpl, public ResourceVk
GLbitfield mask,
GLenum filter) override;
bool checkStatus() const override;
bool checkStatus(const gl::Context *context) const override;
void syncState(const gl::Context *context,
const gl::Framebuffer::DirtyBits &dirtyBits) override;
......
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