Update stencil validation rules for WebGL
Based on kbr's patch:
https://chromium-review.googlesource.com/c/angle/angle/+/890605
Implements new rules in this revised WebGL conformance test:
https://github.com/KhronosGroup/WebGL/pull/2583
BUG=chromium:806557
Change-Id: I84701dd7156f0bc4a45ba68e63cb962d2d54c2e5
Reviewed-on: https://chromium-review.googlesource.com/952567
Commit-Queue: Kai Ninomiya <kainino@chromium.org>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
diff --git a/src/libANGLE/validationES.cpp b/src/libANGLE/validationES.cpp
index ea6add8..6bd9137 100644
--- a/src/libANGLE/validationES.cpp
+++ b/src/libANGLE/validationES.cpp
@@ -2515,28 +2515,35 @@
Framebuffer *framebuffer = state.getDrawFramebuffer();
if (context->getLimitations().noSeparateStencilRefsAndMasks || extensions.webglCompatibility)
{
+ ASSERT(framebuffer);
const FramebufferAttachment *dsAttachment =
framebuffer->getStencilOrDepthStencilAttachment();
- GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
- GLuint minimumRequiredStencilMask = (1 << stencilBits) - 1;
+ const GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
+ ASSERT(stencilBits <= 8);
+
const DepthStencilState &depthStencilState = state.getDepthStencilState();
-
- bool differentRefs = state.getStencilRef() != state.getStencilBackRef();
- bool differentWritemasks =
- (depthStencilState.stencilWritemask & minimumRequiredStencilMask) !=
- (depthStencilState.stencilBackWritemask & minimumRequiredStencilMask);
- bool differentMasks = (depthStencilState.stencilMask & minimumRequiredStencilMask) !=
- (depthStencilState.stencilBackMask & minimumRequiredStencilMask);
-
- if (differentRefs || differentWritemasks || differentMasks)
+ if (depthStencilState.stencilTest && stencilBits > 0)
{
- if (!extensions.webglCompatibility)
+ GLuint maxStencilValue = (1 << stencilBits) - 1;
+
+ bool differentRefs =
+ clamp(state.getStencilRef(), 0, static_cast<GLint>(maxStencilValue)) !=
+ clamp(state.getStencilBackRef(), 0, static_cast<GLint>(maxStencilValue));
+ bool differentWritemasks = (depthStencilState.stencilWritemask & maxStencilValue) !=
+ (depthStencilState.stencilBackWritemask & maxStencilValue);
+ bool differentMasks = (depthStencilState.stencilMask & maxStencilValue) !=
+ (depthStencilState.stencilBackMask & maxStencilValue);
+
+ if (differentRefs || differentWritemasks || differentMasks)
{
- ERR() << "This ANGLE implementation does not support separate front/back stencil "
- "writemasks, reference values, or stencil mask values.";
+ if (!extensions.webglCompatibility)
+ {
+ ERR() << "This ANGLE implementation does not support separate front/back "
+ "stencil writemasks, reference values, or stencil mask values.";
+ }
+ ANGLE_VALIDATION_ERR(context, InvalidOperation(), StencilReferenceMaskOrMismatch);
+ return false;
}
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), StencilReferenceMaskOrMismatch);
- return false;
}
}