Commit b1d0a255 by Corentin Wallez Committed by Commit Bot

WebGL compatibility: add stencil mask and ref restriction

BUG=angleproject:1523 BUG=chromium:668223 Change-Id: I0726769c938fdfd50af0fad1cef1746d4af2a589 Reviewed-on: https://chromium-review.googlesource.com/422084 Commit-Queue: Corentin Wallez <cwallez@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent a4ab5804
...@@ -531,8 +531,7 @@ GLuint Context::createProgram() ...@@ -531,8 +531,7 @@ GLuint Context::createProgram()
GLuint Context::createShader(GLenum type) GLuint Context::createShader(GLenum type)
{ {
return mResourceManager->createShader(mImplementation.get(), return mResourceManager->createShader(mImplementation.get(), mLimitations, type);
mImplementation->getNativeLimitations(), type);
} }
GLuint Context::createTexture() GLuint Context::createTexture()
......
...@@ -132,6 +132,15 @@ const FramebufferAttachment *FramebufferState::getDepthOrStencilAttachment() con ...@@ -132,6 +132,15 @@ const FramebufferAttachment *FramebufferState::getDepthOrStencilAttachment() con
return nullptr; return nullptr;
} }
const FramebufferAttachment *FramebufferState::getStencilOrDepthStencilAttachment() const
{
if (mStencilAttachment.isAttached())
{
return &mStencilAttachment;
}
return getDepthStencilAttachment();
}
const FramebufferAttachment *FramebufferState::getColorAttachment(size_t colorAttachment) const const FramebufferAttachment *FramebufferState::getColorAttachment(size_t colorAttachment) const
{ {
ASSERT(colorAttachment < mColorAttachments.size()); ASSERT(colorAttachment < mColorAttachments.size());
...@@ -360,6 +369,11 @@ const FramebufferAttachment *Framebuffer::getDepthOrStencilbuffer() const ...@@ -360,6 +369,11 @@ const FramebufferAttachment *Framebuffer::getDepthOrStencilbuffer() const
return mState.getDepthOrStencilAttachment(); return mState.getDepthOrStencilAttachment();
} }
const FramebufferAttachment *Framebuffer::getStencilOrDepthStencilAttachment() const
{
return mState.getStencilOrDepthStencilAttachment();
}
const FramebufferAttachment *Framebuffer::getReadColorbuffer() const const FramebufferAttachment *Framebuffer::getReadColorbuffer() const
{ {
return mState.getReadAttachment(); return mState.getReadAttachment();
......
...@@ -62,6 +62,7 @@ class FramebufferState final : angle::NonCopyable ...@@ -62,6 +62,7 @@ class FramebufferState final : angle::NonCopyable
const FramebufferAttachment *getReadAttachment() const; const FramebufferAttachment *getReadAttachment() const;
const FramebufferAttachment *getFirstColorAttachment() const; const FramebufferAttachment *getFirstColorAttachment() const;
const FramebufferAttachment *getDepthOrStencilAttachment() const; const FramebufferAttachment *getDepthOrStencilAttachment() const;
const FramebufferAttachment *getStencilOrDepthStencilAttachment() const;
const FramebufferAttachment *getColorAttachment(size_t colorAttachment) const; const FramebufferAttachment *getColorAttachment(size_t colorAttachment) const;
const FramebufferAttachment *getDepthAttachment() const; const FramebufferAttachment *getDepthAttachment() const;
const FramebufferAttachment *getStencilAttachment() const; const FramebufferAttachment *getStencilAttachment() const;
...@@ -121,6 +122,7 @@ class Framebuffer final : public LabeledObject, public angle::SignalReceiver ...@@ -121,6 +122,7 @@ class Framebuffer final : public LabeledObject, public angle::SignalReceiver
const FramebufferAttachment *getStencilbuffer() const; const FramebufferAttachment *getStencilbuffer() const;
const FramebufferAttachment *getDepthStencilBuffer() const; const FramebufferAttachment *getDepthStencilBuffer() const;
const FramebufferAttachment *getDepthOrStencilbuffer() const; const FramebufferAttachment *getDepthOrStencilbuffer() const;
const FramebufferAttachment *getStencilOrDepthStencilAttachment() const;
const FramebufferAttachment *getReadColorbuffer() const; const FramebufferAttachment *getReadColorbuffer() const;
GLenum getReadColorbufferType() const; GLenum getReadColorbufferType() const;
const FramebufferAttachment *getFirstColorbuffer() const; const FramebufferAttachment *getFirstColorbuffer() const;
......
...@@ -3114,17 +3114,23 @@ bool ValidateDrawBase(ValidationContext *context, GLenum mode, GLsizei count) ...@@ -3114,17 +3114,23 @@ bool ValidateDrawBase(ValidationContext *context, GLenum mode, GLsizei count)
} }
Framebuffer *framebuffer = state.getDrawFramebuffer(); Framebuffer *framebuffer = state.getDrawFramebuffer();
if (context->getLimitations().noSeparateStencilRefsAndMasks) if (context->getLimitations().noSeparateStencilRefsAndMasks ||
context->getExtensions().webglCompatibility)
{ {
const FramebufferAttachment *stencilBuffer = framebuffer->getStencilbuffer(); const FramebufferAttachment *dsAttachment =
GLuint stencilBits = stencilBuffer ? stencilBuffer->getStencilSize() : 0; framebuffer->getStencilOrDepthStencilAttachment();
GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1; GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
const DepthStencilState &depthStencilState = state.getDepthStencilState(); const DepthStencilState &depthStencilState = state.getDepthStencilState();
if ((depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
(depthStencilState.stencilBackWritemask & minimumRequiredStencilMask) || bool differentRefs = state.getStencilRef() != state.getStencilBackRef();
state.getStencilRef() != state.getStencilBackRef() || bool differentWritemasks =
(depthStencilState.stencilMask & minimumRequiredStencilMask) != (depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
(depthStencilState.stencilBackMask & minimumRequiredStencilMask)) (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask);
bool differentMasks = (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
(depthStencilState.stencilBackMask & minimumRequiredStencilMask);
if (differentRefs || differentWritemasks || differentMasks)
{ {
// Note: these separate values are not supported in WebGL, due to D3D's limitations. See // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
// Section 6.10 of the WebGL 1.0 spec // Section 6.10 of the WebGL 1.0 spec
......
...@@ -212,6 +212,66 @@ TEST_P(WebGLCompatibilityTest, ForbidsClientSideElementBuffer) ...@@ -212,6 +212,66 @@ TEST_P(WebGLCompatibilityTest, ForbidsClientSideElementBuffer)
EXPECT_GL_ERROR(GL_INVALID_OPERATION); EXPECT_GL_ERROR(GL_INVALID_OPERATION);
} }
// Tests the WebGL requirement of having the same stencil mask, writemask and ref for fron and back
TEST_P(WebGLCompatibilityTest, RequiresSameStencilMaskAndRef)
{
// Run the test in an FBO to make sure we have some stencil bits.
GLRenderbuffer renderbuffer;
glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer.get());
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 32, 32);
GLFramebuffer framebuffer;
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer.get());
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
renderbuffer.get());
ANGLE_GL_PROGRAM(program, "void main() { gl_Position = vec4(0, 0, 0, 1); }",
"void main() { gl_FragColor = vec4(0, 1, 0, 1); }")
glUseProgram(program.get());
ASSERT_GL_NO_ERROR();
// Having ref and mask the same for front and back is valid.
glStencilMask(255);
glStencilFunc(GL_ALWAYS, 0, 255);
glDrawArrays(GL_TRIANGLES, 0, 6);
ASSERT_GL_NO_ERROR();
// Having a different front - back write mask generates an error.
glStencilMaskSeparate(GL_FRONT, 1);
glDrawArrays(GL_TRIANGLES, 0, 6);
EXPECT_GL_ERROR(GL_INVALID_OPERATION);
// Setting both write masks separately to the same value is valid.
glStencilMaskSeparate(GL_BACK, 1);
glDrawArrays(GL_TRIANGLES, 0, 6);
ASSERT_GL_NO_ERROR();
// Having a different stencil front - back mask generates an error
glStencilFuncSeparate(GL_FRONT, GL_ALWAYS, 0, 1);
glDrawArrays(GL_TRIANGLES, 0, 6);
EXPECT_GL_ERROR(GL_INVALID_OPERATION);
// Setting both masks separately to the same value is valid.
glStencilFuncSeparate(GL_BACK, GL_ALWAYS, 0, 1);
glDrawArrays(GL_TRIANGLES, 0, 6);
ASSERT_GL_NO_ERROR();
// Having a different stencil front - back reference generates an error
glStencilFuncSeparate(GL_FRONT, GL_ALWAYS, 255, 1);
glDrawArrays(GL_TRIANGLES, 0, 6);
EXPECT_GL_ERROR(GL_INVALID_OPERATION);
// Setting both references separately to the same value is valid.
glStencilFuncSeparate(GL_BACK, GL_ALWAYS, 255, 1);
glDrawArrays(GL_TRIANGLES, 0, 6);
ASSERT_GL_NO_ERROR();
// Using different stencil funcs, everything being equal is valid.
glStencilFuncSeparate(GL_BACK, GL_NEVER, 255, 1);
glDrawArrays(GL_TRIANGLES, 0, 6);
ASSERT_GL_NO_ERROR();
}
// Use this to select which configurations (e.g. which renderer, which GLES major version) these // Use this to select which configurations (e.g. which renderer, which GLES major version) these
// tests should be run against. // tests should be run against.
ANGLE_INSTANTIATE_TEST(WebGLCompatibilityTest, ANGLE_INSTANTIATE_TEST(WebGLCompatibilityTest,
......
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