Move stencil mask validation to before the draw.
ANGLE (and WebGL) restrict the back and front stencil masks
on draw, due to D3D restrictions. We would previously only
validate this if the stencil was enabled in D3D9. In D3D11
we would validate the stencil masks even if the stencil is
disabled, which is the behaviour the spec suggests.
Moving the error check to before the draw also prevents any
issue with interrupting a draw call mid-way through.
BUG=angle:571
BUG=378754
Change-Id: If7651c2be559eef64a872082e144dafa3b2c524b
Reviewed-on: https://chromium-review.googlesource.com/203299
Tested-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Shannon Woods <shannonwoods@chromium.org>
diff --git a/src/libGLESv2/Context.cpp b/src/libGLESv2/Context.cpp
index 6d5f329..708c89e 100644
--- a/src/libGLESv2/Context.cpp
+++ b/src/libGLESv2/Context.cpp
@@ -575,6 +575,21 @@
mState.depthStencil.stencilBackPassDepthPass = stencilBackPassDepthPass;
}
+const gl::DepthStencilState &Context::getDepthStencilState() const
+{
+ return mState.depthStencil;
+}
+
+GLint Context::getStencilRef() const
+{
+ return mState.stencilRef;
+}
+
+GLint Context::getStencilBackRef() const
+{
+ return mState.stencilBackRef;
+}
+
void Context::setPolygonOffsetFill(bool enabled)
{
mState.rasterizer.polygonOffsetFill = enabled;
diff --git a/src/libGLESv2/Context.h b/src/libGLESv2/Context.h
index 870ed02..ca57a0f 100644
--- a/src/libGLESv2/Context.h
+++ b/src/libGLESv2/Context.h
@@ -182,6 +182,9 @@
void setStencilBackWritemask(GLuint stencilBackWritemask);
void setStencilOperations(GLenum stencilFail, GLenum stencilPassDepthFail, GLenum stencilPassDepthPass);
void setStencilBackOperations(GLenum stencilBackFail, GLenum stencilBackPassDepthFail, GLenum stencilBackPassDepthPass);
+ const gl::DepthStencilState &getDepthStencilState() const;
+ GLint getStencilRef() const;
+ GLint getStencilBackRef() const;
void setPolygonOffsetFill(bool enabled);
bool isPolygonOffsetFillEnabled() const;
diff --git a/src/libGLESv2/renderer/d3d11/Renderer11.cpp b/src/libGLESv2/renderer/d3d11/Renderer11.cpp
index 2d00b53..05d6fd5 100644
--- a/src/libGLESv2/renderer/d3d11/Renderer11.cpp
+++ b/src/libGLESv2/renderer/d3d11/Renderer11.cpp
@@ -654,14 +654,9 @@
memcmp(&depthStencilState, &mCurDepthStencilState, sizeof(gl::DepthStencilState)) != 0 ||
stencilRef != mCurStencilRef || stencilBackRef != mCurStencilBackRef)
{
- if (depthStencilState.stencilWritemask != depthStencilState.stencilBackWritemask ||
- stencilRef != stencilBackRef ||
- depthStencilState.stencilMask != depthStencilState.stencilBackMask)
- {
- ERR("Separate front/back stencil writemasks, reference values, or stencil mask values are "
- "invalid under WebGL.");
- return gl::error(GL_INVALID_OPERATION);
- }
+ ASSERT(depthStencilState.stencilWritemask == depthStencilState.stencilBackWritemask);
+ ASSERT(stencilRef == stencilBackRef);
+ ASSERT(depthStencilState.stencilMask == depthStencilState.stencilBackMask);
ID3D11DepthStencilState *dxDepthStencilState = mStateCache.getDepthStencilState(depthStencilState);
if (!dxDepthStencilState)
diff --git a/src/libGLESv2/renderer/d3d9/Renderer9.cpp b/src/libGLESv2/renderer/d3d9/Renderer9.cpp
index 46b7a72..030834e 100644
--- a/src/libGLESv2/renderer/d3d9/Renderer9.cpp
+++ b/src/libGLESv2/renderer/d3d9/Renderer9.cpp
@@ -893,13 +893,10 @@
const D3DRENDERSTATETYPE D3DRS_CCW_STENCILREF = D3DRS_STENCILREF;
const D3DRENDERSTATETYPE D3DRS_CCW_STENCILMASK = D3DRS_STENCILMASK;
const D3DRENDERSTATETYPE D3DRS_CCW_STENCILWRITEMASK = D3DRS_STENCILWRITEMASK;
- if (depthStencilState.stencilWritemask != depthStencilState.stencilBackWritemask ||
- stencilRef != stencilBackRef ||
- depthStencilState.stencilMask != depthStencilState.stencilBackMask)
- {
- ERR("Separate front/back stencil writemasks, reference values, or stencil mask values are invalid under WebGL.");
- return gl::error(GL_INVALID_OPERATION);
- }
+
+ ASSERT(depthStencilState.stencilWritemask == depthStencilState.stencilBackWritemask);
+ ASSERT(stencilRef == stencilBackRef);
+ ASSERT(depthStencilState.stencilMask == depthStencilState.stencilBackMask);
// get the maximum size of the stencil ref
unsigned int maxStencil = (1 << mCurStencilSize) - 1;
diff --git a/src/libGLESv2/validationES.cpp b/src/libGLESv2/validationES.cpp
index 6fec360..dba2231 100644
--- a/src/libGLESv2/validationES.cpp
+++ b/src/libGLESv2/validationES.cpp
@@ -1302,6 +1302,18 @@
return gl::error(GL_INVALID_OPERATION, false);
}
+ const gl::DepthStencilState &depthStencilState = context->getDepthStencilState();
+ if (depthStencilState.stencilWritemask != depthStencilState.stencilBackWritemask ||
+ context->getStencilRef() != context->getStencilBackRef() ||
+ depthStencilState.stencilMask != depthStencilState.stencilBackMask)
+ {
+ // Note: these separate values are not supported in WebGL, due to D3D's limitations.
+ // See Section 6.10 of the WebGL 1.0 spec
+ ERR("This ANGLE implementation does not support separate front/back stencil "
+ "writemasks, reference values, or stencil mask values.");
+ return gl::error(GL_INVALID_OPERATION, false);
+ }
+
// No-op if zero count
return (count > 0);
}