Commit ac528015 by Jamie Madill

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/203299Tested-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarShannon Woods <shannonwoods@chromium.org>
parent 21c05532
...@@ -575,6 +575,21 @@ void Context::setStencilBackOperations(GLenum stencilBackFail, GLenum stencilBac ...@@ -575,6 +575,21 @@ void Context::setStencilBackOperations(GLenum stencilBackFail, GLenum stencilBac
mState.depthStencil.stencilBackPassDepthPass = stencilBackPassDepthPass; 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) void Context::setPolygonOffsetFill(bool enabled)
{ {
mState.rasterizer.polygonOffsetFill = enabled; mState.rasterizer.polygonOffsetFill = enabled;
......
...@@ -182,6 +182,9 @@ class Context ...@@ -182,6 +182,9 @@ class Context
void setStencilBackWritemask(GLuint stencilBackWritemask); void setStencilBackWritemask(GLuint stencilBackWritemask);
void setStencilOperations(GLenum stencilFail, GLenum stencilPassDepthFail, GLenum stencilPassDepthPass); void setStencilOperations(GLenum stencilFail, GLenum stencilPassDepthFail, GLenum stencilPassDepthPass);
void setStencilBackOperations(GLenum stencilBackFail, GLenum stencilBackPassDepthFail, GLenum stencilBackPassDepthPass); void setStencilBackOperations(GLenum stencilBackFail, GLenum stencilBackPassDepthFail, GLenum stencilBackPassDepthPass);
const gl::DepthStencilState &getDepthStencilState() const;
GLint getStencilRef() const;
GLint getStencilBackRef() const;
void setPolygonOffsetFill(bool enabled); void setPolygonOffsetFill(bool enabled);
bool isPolygonOffsetFillEnabled() const; bool isPolygonOffsetFillEnabled() const;
......
...@@ -654,14 +654,9 @@ void Renderer11::setDepthStencilState(const gl::DepthStencilState &depthStencilS ...@@ -654,14 +654,9 @@ void Renderer11::setDepthStencilState(const gl::DepthStencilState &depthStencilS
memcmp(&depthStencilState, &mCurDepthStencilState, sizeof(gl::DepthStencilState)) != 0 || memcmp(&depthStencilState, &mCurDepthStencilState, sizeof(gl::DepthStencilState)) != 0 ||
stencilRef != mCurStencilRef || stencilBackRef != mCurStencilBackRef) stencilRef != mCurStencilRef || stencilBackRef != mCurStencilBackRef)
{ {
if (depthStencilState.stencilWritemask != depthStencilState.stencilBackWritemask || ASSERT(depthStencilState.stencilWritemask == depthStencilState.stencilBackWritemask);
stencilRef != stencilBackRef || ASSERT(stencilRef == stencilBackRef);
depthStencilState.stencilMask != depthStencilState.stencilBackMask) ASSERT(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);
}
ID3D11DepthStencilState *dxDepthStencilState = mStateCache.getDepthStencilState(depthStencilState); ID3D11DepthStencilState *dxDepthStencilState = mStateCache.getDepthStencilState(depthStencilState);
if (!dxDepthStencilState) if (!dxDepthStencilState)
......
...@@ -893,13 +893,10 @@ void Renderer9::setDepthStencilState(const gl::DepthStencilState &depthStencilSt ...@@ -893,13 +893,10 @@ void Renderer9::setDepthStencilState(const gl::DepthStencilState &depthStencilSt
const D3DRENDERSTATETYPE D3DRS_CCW_STENCILREF = D3DRS_STENCILREF; const D3DRENDERSTATETYPE D3DRS_CCW_STENCILREF = D3DRS_STENCILREF;
const D3DRENDERSTATETYPE D3DRS_CCW_STENCILMASK = D3DRS_STENCILMASK; const D3DRENDERSTATETYPE D3DRS_CCW_STENCILMASK = D3DRS_STENCILMASK;
const D3DRENDERSTATETYPE D3DRS_CCW_STENCILWRITEMASK = D3DRS_STENCILWRITEMASK; const D3DRENDERSTATETYPE D3DRS_CCW_STENCILWRITEMASK = D3DRS_STENCILWRITEMASK;
if (depthStencilState.stencilWritemask != depthStencilState.stencilBackWritemask ||
stencilRef != stencilBackRef || ASSERT(depthStencilState.stencilWritemask == depthStencilState.stencilBackWritemask);
depthStencilState.stencilMask != depthStencilState.stencilBackMask) ASSERT(stencilRef == stencilBackRef);
{ ASSERT(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);
}
// get the maximum size of the stencil ref // get the maximum size of the stencil ref
unsigned int maxStencil = (1 << mCurStencilSize) - 1; unsigned int maxStencil = (1 << mCurStencilSize) - 1;
......
...@@ -1302,6 +1302,18 @@ static bool ValidateDrawBase(const gl::Context *context, GLsizei count) ...@@ -1302,6 +1302,18 @@ static bool ValidateDrawBase(const gl::Context *context, GLsizei count)
return gl::error(GL_INVALID_OPERATION, false); 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 // No-op if zero count
return (count > 0); return (count > 0);
} }
......
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