gl::Error StateManager9::setBlendDepthRasterStates(const gl::State &glState, unsigned int sampleMask) { const gl::Framebuffer *framebuffer = glState.getDrawFramebuffer(); const gl::BlendState &blendState = glState.getBlendState(); const gl::ColorF &blendColor = glState.getBlendColor(); const gl::RasterizerState &rasterState = glState.getRasterizerState(); const auto &depthStencilState = glState.getDepthStencilState(); bool frontFaceCCW = (glState.getRasterizerState().frontFace == GL_CCW); unsigned int maxStencil = (1 << mCurStencilSize) - 1; // All the depth stencil states depends on the front face ccw variable if (frontFaceCCW != mCurFrontFaceCCW) { forceSetDepthStencilState(); mCurFrontFaceCCW = frontFaceCCW; } for (auto dirtyBit : angle::IterateBitSet(mDirtyBits)) { switch (dirtyBit) { case DIRTY_BIT_BLEND_ENABLED: setBlendEnabled(blendState.blend); break; case DIRTY_BIT_BLEND_COLOR: setBlendColor(blendState, blendColor); break; case DIRTY_BIT_BLEND_FUNCS_EQUATIONS: setBlendFuncsEquations(blendState); break; case DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE: setSampleAlphaToCoverage(blendState.sampleAlphaToCoverage); break; case DIRTY_BIT_COLOR_MASK: setColorMask(framebuffer, blendState.colorMaskRed, blendState.colorMaskBlue, blendState.colorMaskGreen, blendState.colorMaskAlpha); break; case DIRTY_BIT_DITHER: setDither(blendState.dither); break; case DIRTY_BIT_CULL_MODE: setCullMode(rasterState.cullFace, rasterState.cullMode, rasterState.frontFace); break; case DIRTY_BIT_DEPTH_BIAS: setDepthBias(rasterState.polygonOffsetFill, rasterState.polygonOffsetFactor, rasterState.polygonOffsetUnits); break; case DIRTY_BIT_STENCIL_DEPTH_MASK: setDepthMask(depthStencilState.depthMask); break; case DIRTY_BIT_STENCIL_DEPTH_FUNC: setDepthFunc(depthStencilState.depthTest, depthStencilState.depthFunc); break; case DIRTY_BIT_STENCIL_TEST_ENABLED: setStencilTestEnabled(depthStencilState.stencilTest); break; case DIRTY_BIT_STENCIL_FUNCS_FRONT: setStencilFuncsFront(depthStencilState.stencilFunc, depthStencilState.stencilMask, glState.getStencilRef(), frontFaceCCW, maxStencil); break; case DIRTY_BIT_STENCIL_FUNCS_BACK: setStencilFuncsBack(depthStencilState.stencilBackFunc, depthStencilState.stencilBackMask, glState.getStencilBackRef(), frontFaceCCW, maxStencil); break; case DIRTY_BIT_STENCIL_WRITEMASK_FRONT: setStencilWriteMask(depthStencilState.stencilWritemask, frontFaceCCW); break; case DIRTY_BIT_STENCIL_WRITEMASK_BACK: setStencilBackWriteMask(depthStencilState.stencilBackWritemask, frontFaceCCW); break; case DIRTY_BIT_STENCIL_OPS_FRONT: setStencilOpsFront(depthStencilState.stencilFail, depthStencilState.stencilPassDepthFail, depthStencilState.stencilPassDepthPass, frontFaceCCW); break; case DIRTY_BIT_STENCIL_OPS_BACK: setStencilOpsBack(depthStencilState.stencilBackFail, depthStencilState.stencilBackPassDepthFail, depthStencilState.stencilBackPassDepthPass, frontFaceCCW); break; default: break; } } if (sampleMask != mCurSampleMask) { setSampleMask(sampleMask); } return gl::Error(GL_NO_ERROR); }
gl::Error StateManager11::setDepthStencilState(const gl::State &glState) { const auto &fbo = *glState.getDrawFramebuffer(); // Disable the depth test/depth write if we are using a stencil-only attachment. // This is because ANGLE emulates stencil-only with D24S8 on D3D11 - we should neither read // nor write to the unused depth part of this emulated texture. bool disableDepth = (!fbo.hasDepth() && fbo.hasStencil()); // Similarly we disable the stencil portion of the DS attachment if the app only binds depth. bool disableStencil = (fbo.hasDepth() && !fbo.hasStencil()); // CurDisableDepth/Stencil are reset automatically after we call forceSetDepthStencilState. if (!mDepthStencilStateIsDirty && mCurDisableDepth.valid() && disableDepth == mCurDisableDepth.value() && mCurDisableStencil.valid() && disableStencil == mCurDisableStencil.value()) { return gl::Error(GL_NO_ERROR); } const auto &depthStencilState = glState.getDepthStencilState(); int stencilRef = glState.getStencilRef(); int stencilBackRef = glState.getStencilBackRef(); // get the maximum size of the stencil ref unsigned int maxStencil = 0; if (depthStencilState.stencilTest && mCurStencilSize > 0) { maxStencil = (1 << mCurStencilSize) - 1; } ASSERT((depthStencilState.stencilWritemask & maxStencil) == (depthStencilState.stencilBackWritemask & maxStencil)); ASSERT(stencilRef == stencilBackRef); ASSERT((depthStencilState.stencilMask & maxStencil) == (depthStencilState.stencilBackMask & maxStencil)); ID3D11DepthStencilState *dxDepthStencilState = NULL; gl::Error error = mRenderer->getStateCache().getDepthStencilState( depthStencilState, disableDepth, disableStencil, &dxDepthStencilState); if (error.isError()) { return error; } ASSERT(dxDepthStencilState); // Max D3D11 stencil reference value is 0xFF, // corresponding to the max 8 bits in a stencil buffer // GL specifies we should clamp the ref value to the // nearest bit depth when doing stencil ops static_assert(D3D11_DEFAULT_STENCIL_READ_MASK == 0xFF, "Unexpected value of D3D11_DEFAULT_STENCIL_READ_MASK"); static_assert(D3D11_DEFAULT_STENCIL_WRITE_MASK == 0xFF, "Unexpected value of D3D11_DEFAULT_STENCIL_WRITE_MASK"); UINT dxStencilRef = std::min<UINT>(stencilRef, 0xFFu); mRenderer->getDeviceContext()->OMSetDepthStencilState(dxDepthStencilState, dxStencilRef); mCurDepthStencilState = depthStencilState; mCurStencilRef = stencilRef; mCurStencilBackRef = stencilBackRef; mCurDisableDepth = disableDepth; mCurDisableStencil = disableStencil; mDepthStencilStateIsDirty = false; return gl::Error(GL_NO_ERROR); }