bool RendererD3D::skipDraw(const gl::State &glState, gl::PrimitiveMode drawMode) { if (drawMode == gl::PrimitiveMode::Points) { bool usesPointSize = GetImplAs<ProgramD3D>(glState.getProgram())->usesPointSize(); // ProgramBinary assumes non-point rendering if gl_PointSize isn't written, // which affects varying interpolation. Since the value of gl_PointSize is // undefined when not written, just skip drawing to avoid unexpected results. if (!usesPointSize && !glState.isTransformFeedbackActiveUnpaused()) { // Notify developers of risking undefined behavior. WARN() << "Point rendering without writing to gl_PointSize."; return true; } } else if (gl::IsTriangleMode(drawMode)) { if (glState.getRasterizerState().cullFace && glState.getRasterizerState().cullMode == gl::CullFaceMode::FrontAndBack) { return true; } } return false; }
gl::Error StateManager11::updateCurrentValueAttribs(const gl::State &state, VertexDataManager *vertexDataManager) { const auto &activeAttribsMask = state.getProgram()->getActiveAttribLocationsMask(); const auto &dirtyActiveAttribs = (activeAttribsMask & mDirtyCurrentValueAttribs); const auto &vertexAttributes = state.getVertexArray()->getVertexAttributes(); for (auto attribIndex : angle::IterateBitSet(dirtyActiveAttribs)) { if (vertexAttributes[attribIndex].enabled) continue; mDirtyCurrentValueAttribs.reset(attribIndex); const auto ¤tValue = state.getVertexAttribCurrentValue(static_cast<unsigned int>(attribIndex)); auto currentValueAttrib = &mCurrentValueAttribs[attribIndex]; currentValueAttrib->currentValueType = currentValue.Type; currentValueAttrib->attribute = &vertexAttributes[attribIndex]; gl::Error error = vertexDataManager->storeCurrentValue(currentValue, currentValueAttrib, static_cast<size_t>(attribIndex)); if (error.isError()) { return error; } } return gl::Error(GL_NO_ERROR); }
void StateManagerGL::setClearState(const gl::State &state, GLbitfield mask) { // Only apply the state required to do a clear setScissor(state.getScissor()); setViewport(state.getViewport()); if ((mask & GL_COLOR_BUFFER_BIT) != 0) { setClearColor(state.getColorClearValue()); const gl::BlendState &blendState = state.getBlendState(); setColorMask(blendState.colorMaskRed, blendState.colorMaskGreen, blendState.colorMaskBlue, blendState.colorMaskAlpha); } if ((mask & GL_DEPTH_BUFFER_BIT) != 0) { setClearDepth(state.getDepthClearValue()); setDepthMask(state.getDepthStencilState().depthMask); } if ((mask & GL_STENCIL_BUFFER_BIT) != 0) { setClearStencil(state.getStencilClearValue()); setStencilMask(state.getDepthStencilState().stencilMask); } }
void VertexArray11::clearDirtyAndPromoteDynamicAttribs(const gl::State &state, GLsizei count) { const gl::Program *program = state.getProgram(); const auto &activeLocations = program->getActiveAttribLocationsMask(); mAttribsToUpdate &= ~activeLocations; // Promote to static after we clear the dirty attributes, otherwise we can lose dirtyness. auto activeDynamicAttribs = (mDynamicAttribsMask & activeLocations); VertexDataManager::PromoteDynamicAttribs(mTranslatedAttribs, activeDynamicAttribs, count); }
gl::Error FramebufferD3D::blit(const gl::State &state, const gl::Rectangle &sourceArea, const gl::Rectangle &destArea, GLbitfield mask, GLenum filter, const gl::Framebuffer *sourceFramebuffer) { bool blitRenderTarget = false; if ((mask & GL_COLOR_BUFFER_BIT) && sourceFramebuffer->getReadColorbuffer() != nullptr && mData.getFirstColorAttachment() != nullptr) { blitRenderTarget = true; } bool blitStencil = false; if ((mask & GL_STENCIL_BUFFER_BIT) && sourceFramebuffer->getStencilbuffer() != nullptr && mData.mStencilAttachment != nullptr) { blitStencil = true; } bool blitDepth = false; if ((mask & GL_DEPTH_BUFFER_BIT) && sourceFramebuffer->getDepthbuffer() != nullptr && mData.mDepthAttachment != nullptr) { blitDepth = true; } if (blitRenderTarget || blitDepth || blitStencil) { const gl::Rectangle *scissor = state.isScissorTestEnabled() ? &state.getScissor() : NULL; gl::Error error = blit(sourceArea, destArea, scissor, blitRenderTarget, blitDepth, blitStencil, filter, sourceFramebuffer); if (error.isError()) { return error; } } return gl::Error(GL_NO_ERROR); }
unsigned int GetBlendSampleMask(const gl::State &glState, int samples) { unsigned int mask = 0; if (glState.isSampleCoverageEnabled()) { GLfloat coverageValue = glState.getSampleCoverageValue(); if (coverageValue != 0) { float threshold = 0.5f; for (int i = 0; i < samples; ++i) { mask <<= 1; if ((i + 1) * coverageValue >= threshold) { threshold += 1.0f; mask |= 1; } } } bool coverageInvert = glState.getSampleCoverageInvert(); if (coverageInvert) { mask = ~mask; } } else { mask = 0xFFFFFFFF; } if (glState.isSampleMaskEnabled()) { mask &= glState.getSampleMaskWord(0); } return mask; }
gl::Error FramebufferGL::readPixels(const gl::State &state, const gl::Rectangle &area, GLenum format, GLenum type, GLvoid *pixels) const { const gl::PixelPackState &packState = state.getPackState(); if (packState.pixelBuffer.get() != nullptr) { UNIMPLEMENTED(); } mStateManager->bindFramebuffer(GL_READ_FRAMEBUFFER, mFramebufferID); mFunctions->readPixels(area.x, area.y, area.width, area.height, format, type, pixels); return gl::Error(GL_NO_ERROR); }
gl::Error FramebufferD3D::readPixels(const gl::State &state, const gl::Rectangle &area, GLenum format, GLenum type, GLvoid *pixels) const { const gl::PixelPackState &packState = state.getPackState(); GLenum sizedInternalFormat = gl::GetSizedInternalFormat(format, type); const gl::InternalFormat &sizedFormatInfo = gl::GetInternalFormatInfo(sizedInternalFormat); GLuint outputPitch = sizedFormatInfo.computeRowPitch(type, area.width, packState.alignment, packState.rowLength); GLsizei outputSkipBytes = sizedFormatInfo.computeSkipPixels( outputPitch, 0, 0, packState.skipRows, packState.skipPixels); return readPixelsImpl(area, format, type, outputPitch, packState, reinterpret_cast<uint8_t *>(pixels) + outputSkipBytes); }
gl::Error FramebufferD3D::readPixels(const gl::State &state, const gl::Rectangle &area, GLenum format, GLenum type, GLvoid *pixels) const { const gl::PixelPackState &packState = state.getPackState(); if (packState.rowLength != 0 || packState.skipRows != 0 || packState.skipPixels != 0) { UNIMPLEMENTED(); return gl::Error(GL_INVALID_OPERATION, "invalid pixel store parameters in readPixels"); } GLenum sizedInternalFormat = gl::GetSizedInternalFormat(format, type); const gl::InternalFormat &sizedFormatInfo = gl::GetInternalFormatInfo(sizedInternalFormat); GLuint outputPitch = sizedFormatInfo.computeRowPitch(type, area.width, packState.alignment, 0); return readPixels(area, format, type, outputPitch, packState, reinterpret_cast<uint8_t*>(pixels)); }
void VertexArray11::flushAttribUpdates(const gl::State &state) { const gl::Program *program = state.getProgram(); const auto &activeLocations = program->getActiveAttribLocationsMask(); if (mAttribsToUpdate.any()) { // Skip attrib locations the program doesn't use. gl::AttributesMask activeToUpdate = mAttribsToUpdate & activeLocations; for (auto toUpdateIndex : activeToUpdate) { mAttribsToUpdate.reset(toUpdateIndex); updateVertexAttribStorage(toUpdateIndex); } } }
void StateManagerGL::syncState(const gl::State &state, const gl::State::DirtyBits &dirtyBits) { // TODO(jmadill): Investigate only syncing vertex state for active attributes for (auto dirtyBit : angle::IterateBitSet(dirtyBits | mLocalDirtyBits)) { switch (dirtyBit) { case gl::State::DIRTY_BIT_SCISSOR_TEST_ENABLED: setScissorTestEnabled(state.isScissorTestEnabled()); break; case gl::State::DIRTY_BIT_SCISSOR: setScissor(state.getScissor()); break; case gl::State::DIRTY_BIT_VIEWPORT: setViewport(state.getViewport()); break; case gl::State::DIRTY_BIT_DEPTH_RANGE: setDepthRange(state.getNearPlane(), state.getFarPlane()); break; case gl::State::DIRTY_BIT_BLEND_ENABLED: setBlendEnabled(state.isBlendEnabled()); break; case gl::State::DIRTY_BIT_BLEND_COLOR: setBlendColor(state.getBlendColor()); break; case gl::State::DIRTY_BIT_BLEND_FUNCS: { const auto &blendState = state.getBlendState(); setBlendFuncs(blendState.sourceBlendRGB, blendState.destBlendRGB, blendState.sourceBlendAlpha, blendState.destBlendAlpha); break; } case gl::State::DIRTY_BIT_BLEND_EQUATIONS: { const auto &blendState = state.getBlendState(); setBlendEquations(blendState.blendEquationRGB, blendState.blendEquationAlpha); break; } case gl::State::DIRTY_BIT_COLOR_MASK: { const auto &blendState = state.getBlendState(); setColorMask(blendState.colorMaskRed, blendState.colorMaskGreen, blendState.colorMaskBlue, blendState.colorMaskAlpha); break; } case gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED: setSampleAlphaToCoverageEnabled(state.isSampleAlphaToCoverageEnabled()); break; case gl::State::DIRTY_BIT_SAMPLE_COVERAGE_ENABLED: setSampleCoverageEnabled(state.isSampleCoverageEnabled()); break; case gl::State::DIRTY_BIT_SAMPLE_COVERAGE: setSampleCoverage(state.getSampleCoverageValue(), state.getSampleCoverageInvert()); break; case gl::State::DIRTY_BIT_DEPTH_TEST_ENABLED: setDepthTestEnabled(state.isDepthTestEnabled()); break; case gl::State::DIRTY_BIT_DEPTH_FUNC: setDepthFunc(state.getDepthStencilState().depthFunc); break; case gl::State::DIRTY_BIT_DEPTH_MASK: setDepthMask(state.getDepthStencilState().depthMask); break; case gl::State::DIRTY_BIT_STENCIL_TEST_ENABLED: setStencilTestEnabled(state.isStencilTestEnabled()); break; case gl::State::DIRTY_BIT_STENCIL_FUNCS_FRONT: { const auto &depthStencilState = state.getDepthStencilState(); setStencilFrontFuncs(depthStencilState.stencilFunc, state.getStencilRef(), depthStencilState.stencilMask); break; } case gl::State::DIRTY_BIT_STENCIL_FUNCS_BACK: { const auto &depthStencilState = state.getDepthStencilState(); setStencilBackFuncs(depthStencilState.stencilBackFunc, state.getStencilBackRef(), depthStencilState.stencilBackMask); break; } case gl::State::DIRTY_BIT_STENCIL_OPS_FRONT: { const auto &depthStencilState = state.getDepthStencilState(); setStencilFrontOps(depthStencilState.stencilFail, depthStencilState.stencilPassDepthFail, depthStencilState.stencilPassDepthPass); break; } case gl::State::DIRTY_BIT_STENCIL_OPS_BACK: { const auto &depthStencilState = state.getDepthStencilState(); setStencilBackOps(depthStencilState.stencilBackFail, depthStencilState.stencilBackPassDepthFail, depthStencilState.stencilBackPassDepthPass); break; } case gl::State::DIRTY_BIT_STENCIL_WRITEMASK_FRONT: setStencilFrontWritemask(state.getDepthStencilState().stencilWritemask); break; case gl::State::DIRTY_BIT_STENCIL_WRITEMASK_BACK: setStencilBackWritemask(state.getDepthStencilState().stencilBackWritemask); break; case gl::State::DIRTY_BIT_CULL_FACE_ENABLED: setCullFaceEnabled(state.isCullFaceEnabled()); break; case gl::State::DIRTY_BIT_CULL_FACE: setCullFace(state.getRasterizerState().cullMode); break; case gl::State::DIRTY_BIT_FRONT_FACE: setFrontFace(state.getRasterizerState().frontFace); break; case gl::State::DIRTY_BIT_POLYGON_OFFSET_FILL_ENABLED: setPolygonOffsetFillEnabled(state.isPolygonOffsetFillEnabled()); break; case gl::State::DIRTY_BIT_POLYGON_OFFSET: { const auto &rasterizerState = state.getRasterizerState(); setPolygonOffset(rasterizerState.polygonOffsetFactor, rasterizerState.polygonOffsetUnits); break; } case gl::State::DIRTY_BIT_RASTERIZER_DISCARD_ENABLED: setRasterizerDiscardEnabled(state.isRasterizerDiscardEnabled()); break; case gl::State::DIRTY_BIT_LINE_WIDTH: setLineWidth(state.getLineWidth()); break; case gl::State::DIRTY_BIT_PRIMITIVE_RESTART_ENABLED: setPrimitiveRestartEnabled(state.isPrimitiveRestartEnabled()); break; case gl::State::DIRTY_BIT_CLEAR_COLOR: setClearColor(state.getColorClearValue()); break; case gl::State::DIRTY_BIT_CLEAR_DEPTH: setClearDepth(state.getDepthClearValue()); break; case gl::State::DIRTY_BIT_CLEAR_STENCIL: setClearStencil(state.getStencilClearValue()); break; case gl::State::DIRTY_BIT_UNPACK_ALIGNMENT: // TODO(jmadill): split this setPixelUnpackState(state.getUnpackState()); break; case gl::State::DIRTY_BIT_UNPACK_ROW_LENGTH: // TODO(jmadill): split this setPixelUnpackState(state.getUnpackState()); break; case gl::State::DIRTY_BIT_UNPACK_IMAGE_HEIGHT: // TODO(jmadill): split this setPixelUnpackState(state.getUnpackState()); break; case gl::State::DIRTY_BIT_UNPACK_SKIP_IMAGES: // TODO(jmadill): split this setPixelUnpackState(state.getUnpackState()); break; case gl::State::DIRTY_BIT_UNPACK_SKIP_ROWS: // TODO(jmadill): split this setPixelUnpackState(state.getUnpackState()); break; case gl::State::DIRTY_BIT_UNPACK_SKIP_PIXELS: // TODO(jmadill): split this setPixelUnpackState(state.getUnpackState()); break; case gl::State::DIRTY_BIT_PACK_ALIGNMENT: // TODO(jmadill): split this setPixelPackState(state.getPackState()); break; case gl::State::DIRTY_BIT_PACK_REVERSE_ROW_ORDER: // TODO(jmadill): split this setPixelPackState(state.getPackState()); break; case gl::State::DIRTY_BIT_PACK_ROW_LENGTH: // TODO(jmadill): split this setPixelPackState(state.getPackState()); break; case gl::State::DIRTY_BIT_PACK_SKIP_ROWS: // TODO(jmadill): split this setPixelPackState(state.getPackState()); break; case gl::State::DIRTY_BIT_PACK_SKIP_PIXELS: // TODO(jmadill): split this setPixelPackState(state.getPackState()); break; case gl::State::DIRTY_BIT_DITHER_ENABLED: // TODO(jmadill): implement this break; case gl::State::DIRTY_BIT_GENERATE_MIPMAP_HINT: // TODO(jmadill): implement this break; case gl::State::DIRTY_BIT_SHADER_DERIVATIVE_HINT: // TODO(jmadill): implement this break; case gl::State::DIRTY_BIT_READ_FRAMEBUFFER_BINDING: // TODO(jmadill): implement this break; case gl::State::DIRTY_BIT_READ_FRAMEBUFFER_OBJECT: // TODO(jmadill): implement this break; case gl::State::DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING: // TODO(jmadill): implement this break; case gl::State::DIRTY_BIT_DRAW_FRAMEBUFFER_OBJECT: // TODO(jmadill): implement this break; case gl::State::DIRTY_BIT_RENDERBUFFER_BINDING: // TODO(jmadill): implement this break; case gl::State::DIRTY_BIT_VERTEX_ARRAY_BINDING: // TODO(jmadill): implement this break; case gl::State::DIRTY_BIT_VERTEX_ARRAY_OBJECT: state.getVertexArray()->syncImplState(); break; case gl::State::DIRTY_BIT_PROGRAM_BINDING: // TODO(jmadill): implement this break; case gl::State::DIRTY_BIT_PROGRAM_OBJECT: // TODO(jmadill): implement this break; default: { ASSERT(dirtyBit >= gl::State::DIRTY_BIT_CURRENT_VALUE_0 && dirtyBit < gl::State::DIRTY_BIT_CURRENT_VALUE_MAX); size_t attribIndex = static_cast<size_t>(dirtyBit) - gl::State::DIRTY_BIT_CURRENT_VALUE_0; setAttributeCurrentData(attribIndex, state.getVertexAttribCurrentValue( static_cast<unsigned int>(attribIndex))); break; } } mLocalDirtyBits.reset(); } }
gl::Error VertexDataManager::prepareVertexData(const gl::State &state, GLint start, GLsizei count, TranslatedAttribute *translated, GLsizei instances) { if (!mStreamingBuffer) { return gl::Error(GL_OUT_OF_MEMORY, "Internal streaming vertex buffer is unexpectedly NULL."); } // Invalidate static buffers that don't contain matching attributes for (int attributeIndex = 0; attributeIndex < gl::MAX_VERTEX_ATTRIBS; attributeIndex++) { translated[attributeIndex].active = (state.getProgram()->getSemanticIndex(attributeIndex) != -1); const gl::VertexAttribute &curAttrib = state.getVertexAttribState(attributeIndex); if (translated[attributeIndex].active && curAttrib.enabled) { invalidateMatchingStaticData(curAttrib, state.getVertexAttribCurrentValue(attributeIndex)); } } // Reserve the required space in the buffers for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) { const gl::VertexAttribute &curAttrib = state.getVertexAttribState(i); if (translated[i].active && curAttrib.enabled) { gl::Error error = reserveSpaceForAttrib(curAttrib, state.getVertexAttribCurrentValue(i), count, instances); if (error.isError()) { return error; } } } // Perform the vertex data translations for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) { const gl::VertexAttribute &curAttrib = state.getVertexAttribState(i); if (translated[i].active) { if (curAttrib.enabled) { gl::Error error = storeAttribute(curAttrib, state.getVertexAttribCurrentValue(i), &translated[i], start, count, instances); if (error.isError()) { return error; } } else { if (!mCurrentValueBuffer[i]) { mCurrentValueBuffer[i] = new StreamingVertexBufferInterface(mRenderer, CONSTANT_VERTEX_BUFFER_SIZE); } gl::Error error = storeCurrentValue(curAttrib, state.getVertexAttribCurrentValue(i), &translated[i], &mCurrentValue[i], &mCurrentValueOffsets[i], mCurrentValueBuffer[i]); if (error.isError()) { return error; } } } } for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) { const gl::VertexAttribute &curAttrib = state.getVertexAttribState(i); if (translated[i].active && curAttrib.enabled) { gl::Buffer *buffer = curAttrib.buffer.get(); if (buffer) { BufferD3D *bufferImpl = BufferD3D::makeBufferD3D(buffer->getImplementation()); bufferImpl->promoteStaticUsage(count * ComputeVertexAttributeTypeSize(curAttrib)); } } } return gl::Error(GL_NO_ERROR); }
void StateManager9::syncState(const gl::State &state, const gl::State::DirtyBits &dirtyBits) { for (auto dirtyBit : angle::IterateBitSet(dirtyBits)) { switch (dirtyBit) { case gl::State::DIRTY_BIT_BLEND_ENABLED: if (state.getBlendState().blend != mCurBlendState.blend) { mDirtyBits.set(DIRTY_BIT_BLEND_ENABLED); // BlendColor and funcs and equations has to be set if blend is enabled mDirtyBits.set(DIRTY_BIT_BLEND_COLOR); mDirtyBits.set(DIRTY_BIT_BLEND_FUNCS_EQUATIONS); } break; case gl::State::DIRTY_BIT_BLEND_FUNCS: { const gl::BlendState &blendState = state.getBlendState(); if (blendState.sourceBlendRGB != mCurBlendState.sourceBlendRGB || blendState.destBlendRGB != mCurBlendState.destBlendRGB || blendState.sourceBlendAlpha != mCurBlendState.sourceBlendAlpha || blendState.destBlendAlpha != mCurBlendState.destBlendAlpha) { mDirtyBits.set(DIRTY_BIT_BLEND_FUNCS_EQUATIONS); // BlendColor depends on the values of blend funcs mDirtyBits.set(DIRTY_BIT_BLEND_COLOR); } break; } case gl::State::DIRTY_BIT_BLEND_EQUATIONS: { const gl::BlendState &blendState = state.getBlendState(); if (blendState.blendEquationRGB != mCurBlendState.blendEquationRGB || blendState.blendEquationAlpha != mCurBlendState.blendEquationAlpha) { mDirtyBits.set(DIRTY_BIT_BLEND_FUNCS_EQUATIONS); } break; } case gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED: if (state.getBlendState().sampleAlphaToCoverage != mCurBlendState.sampleAlphaToCoverage) { mDirtyBits.set(DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE); } break; case gl::State::DIRTY_BIT_COLOR_MASK: { const gl::BlendState &blendState = state.getBlendState(); if (blendState.colorMaskRed != mCurBlendState.colorMaskRed || blendState.colorMaskGreen != mCurBlendState.colorMaskGreen || blendState.colorMaskBlue != mCurBlendState.colorMaskBlue || blendState.colorMaskAlpha != mCurBlendState.colorMaskAlpha) { mDirtyBits.set(DIRTY_BIT_COLOR_MASK); } break; } case gl::State::DIRTY_BIT_DITHER_ENABLED: if (state.getBlendState().dither != mCurBlendState.dither) { mDirtyBits.set(DIRTY_BIT_DITHER); } break; case gl::State::DIRTY_BIT_BLEND_COLOR: if (state.getBlendColor() != mCurBlendColor) { mDirtyBits.set(DIRTY_BIT_BLEND_COLOR); } break; case gl::State::DIRTY_BIT_CULL_FACE_ENABLED: if (state.getRasterizerState().cullFace != mCurRasterState.cullFace) { mDirtyBits.set(DIRTY_BIT_CULL_MODE); } break; case gl::State::DIRTY_BIT_CULL_FACE: if (state.getRasterizerState().cullMode != mCurRasterState.cullMode) { mDirtyBits.set(DIRTY_BIT_CULL_MODE); } break; case gl::State::DIRTY_BIT_FRONT_FACE: if (state.getRasterizerState().frontFace != mCurRasterState.frontFace) { mDirtyBits.set(DIRTY_BIT_CULL_MODE); // Viewport state depends on rasterizer.frontface mDirtyBits.set(DIRTY_BIT_VIEWPORT); } break; case gl::State::DIRTY_BIT_POLYGON_OFFSET_FILL_ENABLED: if (state.getRasterizerState().polygonOffsetFill != mCurRasterState.polygonOffsetFill) { mDirtyBits.set(DIRTY_BIT_DEPTH_BIAS); } break; case gl::State::DIRTY_BIT_POLYGON_OFFSET: { const gl::RasterizerState &rasterizerState = state.getRasterizerState(); if (rasterizerState.polygonOffsetFactor != mCurRasterState.polygonOffsetFactor || rasterizerState.polygonOffsetUnits != mCurRasterState.polygonOffsetUnits) { mDirtyBits.set(DIRTY_BIT_DEPTH_BIAS); } } case gl::State::DIRTY_BIT_DEPTH_MASK: if (state.getDepthStencilState().depthMask != mCurDepthStencilState.depthMask) { mDirtyBits.set(DIRTY_BIT_STENCIL_DEPTH_MASK); } break; case gl::State::DIRTY_BIT_DEPTH_TEST_ENABLED: if (state.getDepthStencilState().depthTest != mCurDepthStencilState.depthTest) { mDirtyBits.set(DIRTY_BIT_STENCIL_DEPTH_FUNC); } break; case gl::State::DIRTY_BIT_DEPTH_FUNC: if (state.getDepthStencilState().depthFunc != mCurDepthStencilState.depthFunc) { mDirtyBits.set(DIRTY_BIT_STENCIL_DEPTH_FUNC); } break; case gl::State::DIRTY_BIT_STENCIL_TEST_ENABLED: if (state.getDepthStencilState().stencilTest != mCurDepthStencilState.stencilTest) { mDirtyBits.set(DIRTY_BIT_STENCIL_TEST_ENABLED); // If we enable the stencil test, all of these must be set mDirtyBits.set(DIRTY_BIT_STENCIL_WRITEMASK_BACK); mDirtyBits.set(DIRTY_BIT_STENCIL_WRITEMASK_FRONT); mDirtyBits.set(DIRTY_BIT_STENCIL_FUNCS_FRONT); mDirtyBits.set(DIRTY_BIT_STENCIL_FUNCS_BACK); mDirtyBits.set(DIRTY_BIT_STENCIL_OPS_FRONT); mDirtyBits.set(DIRTY_BIT_STENCIL_OPS_BACK); } break; case gl::State::DIRTY_BIT_STENCIL_FUNCS_FRONT: { const gl::DepthStencilState &depthStencilState = state.getDepthStencilState(); if (depthStencilState.stencilFunc != mCurDepthStencilState.stencilFunc || depthStencilState.stencilMask != mCurDepthStencilState.stencilMask || state.getStencilRef() != mCurStencilRef) { mDirtyBits.set(DIRTY_BIT_STENCIL_FUNCS_FRONT); } break; } case gl::State::DIRTY_BIT_STENCIL_FUNCS_BACK: { const gl::DepthStencilState &depthStencilState = state.getDepthStencilState(); if (depthStencilState.stencilBackFunc != mCurDepthStencilState.stencilBackFunc || depthStencilState.stencilBackMask != mCurDepthStencilState.stencilBackMask || state.getStencilBackRef() != mCurStencilBackRef) { mDirtyBits.set(DIRTY_BIT_STENCIL_FUNCS_BACK); } break; } case gl::State::DIRTY_BIT_STENCIL_WRITEMASK_FRONT: if (state.getDepthStencilState().stencilWritemask != mCurDepthStencilState.stencilWritemask) { mDirtyBits.set(DIRTY_BIT_STENCIL_WRITEMASK_FRONT); } break; case gl::State::DIRTY_BIT_STENCIL_WRITEMASK_BACK: if (state.getDepthStencilState().stencilBackWritemask != mCurDepthStencilState.stencilBackWritemask) { mDirtyBits.set(DIRTY_BIT_STENCIL_WRITEMASK_BACK); } break; case gl::State::DIRTY_BIT_STENCIL_OPS_FRONT: { const gl::DepthStencilState &depthStencilState = state.getDepthStencilState(); if (depthStencilState.stencilFail != mCurDepthStencilState.stencilFail || depthStencilState.stencilPassDepthFail != mCurDepthStencilState.stencilPassDepthFail || depthStencilState.stencilPassDepthPass != mCurDepthStencilState.stencilPassDepthPass) { mDirtyBits.set(DIRTY_BIT_STENCIL_OPS_FRONT); } break; } case gl::State::DIRTY_BIT_STENCIL_OPS_BACK: { const gl::DepthStencilState &depthStencilState = state.getDepthStencilState(); if (depthStencilState.stencilBackFail != mCurDepthStencilState.stencilBackFail || depthStencilState.stencilBackPassDepthFail != mCurDepthStencilState.stencilBackPassDepthFail || depthStencilState.stencilBackPassDepthPass != mCurDepthStencilState.stencilBackPassDepthPass) { mDirtyBits.set(DIRTY_BIT_STENCIL_OPS_BACK); } break; } case gl::State::DIRTY_BIT_SCISSOR_TEST_ENABLED: if (state.isScissorTestEnabled() != mCurScissorEnabled) { mDirtyBits.set(DIRTY_BIT_SCISSOR_ENABLED); // If scissor is enabled, we have to set the scissor rect mDirtyBits.set(DIRTY_BIT_SCISSOR_RECT); } break; case gl::State::DIRTY_BIT_SCISSOR: if (state.getScissor() != mCurScissorRect) { mDirtyBits.set(DIRTY_BIT_SCISSOR_RECT); } break; case gl::State::DIRTY_BIT_DEPTH_RANGE: if (state.getNearPlane() != mCurNear || state.getFarPlane() != mCurFar) { mDirtyBits.set(DIRTY_BIT_VIEWPORT); } break; case gl::State::DIRTY_BIT_VIEWPORT: if (state.getViewport() != mCurViewport) { mDirtyBits.set(DIRTY_BIT_VIEWPORT); } break; default: break; } } }
void StateManager11::syncState(const gl::State &state, const gl::State::DirtyBits &dirtyBits) { if (!dirtyBits.any()) { return; } for (auto dirtyBit : angle::IterateBitSet(dirtyBits)) { switch (dirtyBit) { case gl::State::DIRTY_BIT_BLEND_EQUATIONS: { const gl::BlendState &blendState = state.getBlendState(); if (blendState.blendEquationRGB != mCurBlendState.blendEquationRGB || blendState.blendEquationAlpha != mCurBlendState.blendEquationAlpha) { mBlendStateIsDirty = true; } break; } case gl::State::DIRTY_BIT_BLEND_FUNCS: { const gl::BlendState &blendState = state.getBlendState(); if (blendState.sourceBlendRGB != mCurBlendState.sourceBlendRGB || blendState.destBlendRGB != mCurBlendState.destBlendRGB || blendState.sourceBlendAlpha != mCurBlendState.sourceBlendAlpha || blendState.destBlendAlpha != mCurBlendState.destBlendAlpha) { mBlendStateIsDirty = true; } break; } case gl::State::DIRTY_BIT_BLEND_ENABLED: if (state.getBlendState().blend != mCurBlendState.blend) { mBlendStateIsDirty = true; } break; case gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED: if (state.getBlendState().sampleAlphaToCoverage != mCurBlendState.sampleAlphaToCoverage) { mBlendStateIsDirty = true; } break; case gl::State::DIRTY_BIT_DITHER_ENABLED: if (state.getBlendState().dither != mCurBlendState.dither) { mBlendStateIsDirty = true; } break; case gl::State::DIRTY_BIT_COLOR_MASK: { const gl::BlendState &blendState = state.getBlendState(); if (blendState.colorMaskRed != mCurBlendState.colorMaskRed || blendState.colorMaskGreen != mCurBlendState.colorMaskGreen || blendState.colorMaskBlue != mCurBlendState.colorMaskBlue || blendState.colorMaskAlpha != mCurBlendState.colorMaskAlpha) { mBlendStateIsDirty = true; } break; } case gl::State::DIRTY_BIT_BLEND_COLOR: if (state.getBlendColor() != mCurBlendColor) { mBlendStateIsDirty = true; } break; case gl::State::DIRTY_BIT_DEPTH_MASK: if (state.getDepthStencilState().depthMask != mCurDepthStencilState.depthMask) { mDepthStencilStateIsDirty = true; } break; case gl::State::DIRTY_BIT_DEPTH_TEST_ENABLED: if (state.getDepthStencilState().depthTest != mCurDepthStencilState.depthTest) { mDepthStencilStateIsDirty = true; } break; case gl::State::DIRTY_BIT_DEPTH_FUNC: if (state.getDepthStencilState().depthFunc != mCurDepthStencilState.depthFunc) { mDepthStencilStateIsDirty = true; } break; case gl::State::DIRTY_BIT_STENCIL_TEST_ENABLED: if (state.getDepthStencilState().stencilTest != mCurDepthStencilState.stencilTest) { mDepthStencilStateIsDirty = true; } break; case gl::State::DIRTY_BIT_STENCIL_FUNCS_FRONT: { const gl::DepthStencilState &depthStencil = state.getDepthStencilState(); if (depthStencil.stencilFunc != mCurDepthStencilState.stencilFunc || depthStencil.stencilMask != mCurDepthStencilState.stencilMask || state.getStencilRef() != mCurStencilRef) { mDepthStencilStateIsDirty = true; } break; } case gl::State::DIRTY_BIT_STENCIL_FUNCS_BACK: { const gl::DepthStencilState &depthStencil = state.getDepthStencilState(); if (depthStencil.stencilBackFunc != mCurDepthStencilState.stencilBackFunc || depthStencil.stencilBackMask != mCurDepthStencilState.stencilBackMask || state.getStencilBackRef() != mCurStencilBackRef) { mDepthStencilStateIsDirty = true; } break; } case gl::State::DIRTY_BIT_STENCIL_WRITEMASK_FRONT: if (state.getDepthStencilState().stencilWritemask != mCurDepthStencilState.stencilWritemask) { mDepthStencilStateIsDirty = true; } break; case gl::State::DIRTY_BIT_STENCIL_WRITEMASK_BACK: if (state.getDepthStencilState().stencilBackWritemask != mCurDepthStencilState.stencilBackWritemask) { mDepthStencilStateIsDirty = true; } break; case gl::State::DIRTY_BIT_STENCIL_OPS_FRONT: { const gl::DepthStencilState &depthStencil = state.getDepthStencilState(); if (depthStencil.stencilFail != mCurDepthStencilState.stencilFail || depthStencil.stencilPassDepthFail != mCurDepthStencilState.stencilPassDepthFail || depthStencil.stencilPassDepthPass != mCurDepthStencilState.stencilPassDepthPass) { mDepthStencilStateIsDirty = true; } break; } case gl::State::DIRTY_BIT_STENCIL_OPS_BACK: { const gl::DepthStencilState &depthStencil = state.getDepthStencilState(); if (depthStencil.stencilBackFail != mCurDepthStencilState.stencilBackFail || depthStencil.stencilBackPassDepthFail != mCurDepthStencilState.stencilBackPassDepthFail || depthStencil.stencilBackPassDepthPass != mCurDepthStencilState.stencilBackPassDepthPass) { mDepthStencilStateIsDirty = true; } break; } case gl::State::DIRTY_BIT_CULL_FACE_ENABLED: if (state.getRasterizerState().cullFace != mCurRasterState.cullFace) { mRasterizerStateIsDirty = true; } break; case gl::State::DIRTY_BIT_CULL_FACE: if (state.getRasterizerState().cullMode != mCurRasterState.cullMode) { mRasterizerStateIsDirty = true; } break; case gl::State::DIRTY_BIT_FRONT_FACE: if (state.getRasterizerState().frontFace != mCurRasterState.frontFace) { mRasterizerStateIsDirty = true; } break; case gl::State::DIRTY_BIT_POLYGON_OFFSET_FILL_ENABLED: if (state.getRasterizerState().polygonOffsetFill != mCurRasterState.polygonOffsetFill) { mRasterizerStateIsDirty = true; } break; case gl::State::DIRTY_BIT_POLYGON_OFFSET: { const gl::RasterizerState &rasterState = state.getRasterizerState(); if (rasterState.polygonOffsetFactor != mCurRasterState.polygonOffsetFactor || rasterState.polygonOffsetUnits != mCurRasterState.polygonOffsetUnits) { mRasterizerStateIsDirty = true; } break; } case gl::State::DIRTY_BIT_RASTERIZER_DISCARD_ENABLED: if (state.getRasterizerState().rasterizerDiscard != mCurRasterState.rasterizerDiscard) { mRasterizerStateIsDirty = true; } break; case gl::State::DIRTY_BIT_SCISSOR: if (state.getScissor() != mCurScissorRect) { mScissorStateIsDirty = true; } break; case gl::State::DIRTY_BIT_SCISSOR_TEST_ENABLED: if (state.isScissorTestEnabled() != mCurScissorEnabled) { mScissorStateIsDirty = true; // Rasterizer state update needs mCurScissorsEnabled and updates when it changes mRasterizerStateIsDirty = true; } break; case gl::State::DIRTY_BIT_DEPTH_RANGE: if (state.getNearPlane() != mCurNear || state.getFarPlane() != mCurFar) { mViewportStateIsDirty = true; } break; case gl::State::DIRTY_BIT_VIEWPORT: if (state.getViewport() != mCurViewport) { mViewportStateIsDirty = true; } break; case gl::State::DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING: mRenderTargetIsDirty = true; break; default: if (dirtyBit >= gl::State::DIRTY_BIT_CURRENT_VALUE_0 && dirtyBit < gl::State::DIRTY_BIT_CURRENT_VALUE_MAX) { size_t attribIndex = static_cast<size_t>(dirtyBit - gl::State::DIRTY_BIT_CURRENT_VALUE_0); mDirtyCurrentValueAttribs.set(attribIndex); } break; } } }
gl::Error VertexDataManager::prepareVertexData(const gl::State &state, GLint start, GLsizei count, std::vector<TranslatedAttribute> *translatedAttribs, GLsizei instances) { ASSERT(mStreamingBuffer); const gl::VertexArray *vertexArray = state.getVertexArray(); const auto &vertexAttributes = vertexArray->getVertexAttributes(); mDynamicAttribsMaskCache.reset(); const gl::Program *program = state.getProgram(); translatedAttribs->clear(); for (size_t attribIndex = 0; attribIndex < vertexAttributes.size(); ++attribIndex) { // Skip attrib locations the program doesn't use. if (!program->isAttribLocationActive(attribIndex)) continue; const auto &attrib = vertexAttributes[attribIndex]; // Resize automatically puts in empty attribs translatedAttribs->resize(attribIndex + 1); TranslatedAttribute *translated = &(*translatedAttribs)[attribIndex]; auto currentValueData = state.getVertexAttribCurrentValue(static_cast<unsigned int>(attribIndex)); // Record the attribute now translated->active = true; translated->attribute = &attrib; translated->currentValueType = currentValueData.Type; translated->divisor = attrib.divisor; switch (ClassifyAttributeStorage(attrib)) { case VertexStorageType::STATIC: { // Store static attribute. gl::Error error = StoreStaticAttrib(translated, start, count, instances); if (error.isError()) { return error; } break; } case VertexStorageType::DYNAMIC: // Dynamic attributes must be handled together. mDynamicAttribsMaskCache.set(attribIndex); break; case VertexStorageType::DIRECT: // Update translated data for direct attributes. StoreDirectAttrib(translated, start); break; case VertexStorageType::CURRENT_VALUE: { gl::Error error = storeCurrentValue(currentValueData, translated, attribIndex); if (error.isError()) { return error; } break; } default: UNREACHABLE(); break; } } if (mDynamicAttribsMaskCache.none()) { gl::Error(GL_NO_ERROR); } return storeDynamicAttribs(translatedAttribs, mDynamicAttribsMaskCache, start, count, instances); }
gl::Error VertexDataManager::prepareVertexData(const gl::State &state, GLint start, GLsizei count, std::vector<TranslatedAttribute> *translatedAttribs, GLsizei instances) { if (!mStreamingBuffer) { return gl::Error(GL_OUT_OF_MEMORY, "Internal streaming vertex buffer is unexpectedly NULL."); } // Compute active enabled and active disable attributes, for speed. // TODO(jmadill): don't recompute if there was no state change const gl::VertexArray *vertexArray = state.getVertexArray(); const gl::Program *program = state.getProgram(); const auto &vertexAttributes = vertexArray->getVertexAttributes(); mActiveEnabledAttributes.clear(); mActiveDisabledAttributes.clear(); translatedAttribs->clear(); for (size_t attribIndex = 0; attribIndex < vertexAttributes.size(); ++attribIndex) { if (program->isAttribLocationActive(attribIndex)) { // Resize automatically puts in empty attribs translatedAttribs->resize(attribIndex + 1); TranslatedAttribute *translated = &(*translatedAttribs)[attribIndex]; // Record the attribute now translated->active = true; translated->attribute = &vertexAttributes[attribIndex]; translated->currentValueType = state.getVertexAttribCurrentValue(static_cast<unsigned int>(attribIndex)).Type; translated->divisor = vertexAttributes[attribIndex].divisor; if (vertexAttributes[attribIndex].enabled) { mActiveEnabledAttributes.push_back(translated); } else { mActiveDisabledAttributes.push_back(attribIndex); } } } // Reserve the required space in the buffers for (const TranslatedAttribute *activeAttrib : mActiveEnabledAttributes) { gl::Error error = reserveSpaceForAttrib(*activeAttrib, count, instances); if (error.isError()) { return error; } } // Perform the vertex data translations for (TranslatedAttribute *activeAttrib : mActiveEnabledAttributes) { gl::Error error = storeAttribute(activeAttrib, start, count, instances); if (error.isError()) { hintUnmapAllResources(vertexAttributes); return error; } } for (size_t attribIndex : mActiveDisabledAttributes) { if (mCurrentValueCache[attribIndex].buffer == nullptr) { mCurrentValueCache[attribIndex].buffer = new StreamingVertexBufferInterface(mFactory, CONSTANT_VERTEX_BUFFER_SIZE); } gl::Error error = storeCurrentValue( state.getVertexAttribCurrentValue(static_cast<unsigned int>(attribIndex)), &(*translatedAttribs)[attribIndex], &mCurrentValueCache[attribIndex]); if (error.isError()) { hintUnmapAllResources(vertexAttributes); return error; } } // Commit all the static vertex buffers. This fixes them in size/contents, and forces ANGLE // to use a new static buffer (or recreate the static buffers) next time for (size_t attribIndex = 0; attribIndex < vertexAttributes.size(); ++attribIndex) { const gl::VertexAttribute &attrib = vertexAttributes[attribIndex]; gl::Buffer *buffer = attrib.buffer.get(); BufferD3D *storage = buffer ? GetImplAs<BufferD3D>(buffer) : nullptr; StaticVertexBufferInterface *staticBuffer = storage ? storage->getStaticVertexBuffer(attrib) : nullptr; if (staticBuffer) { staticBuffer->commit(); } } // Hint to unmap all the resources hintUnmapAllResources(vertexAttributes); for (const TranslatedAttribute *activeAttrib : mActiveEnabledAttributes) { gl::Buffer *buffer = activeAttrib->attribute->buffer.get(); if (buffer) { BufferD3D *bufferD3D = GetImplAs<BufferD3D>(buffer); size_t typeSize = ComputeVertexAttributeTypeSize(*activeAttrib->attribute); bufferD3D->promoteStaticUsage(count * static_cast<int>(typeSize)); } } 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); }
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 VertexArray11::updateDirtyAndDynamicAttribs(VertexDataManager *vertexDataManager, const gl::State &state, GLint start, GLsizei count, GLsizei instances) { flushAttribUpdates(state); const gl::Program *program = state.getProgram(); const auto &activeLocations = program->getActiveAttribLocationsMask(); const auto &attribs = mData.getVertexAttributes(); const auto &bindings = mData.getVertexBindings(); if (mAttribsToTranslate.any()) { // Skip attrib locations the program doesn't use, saving for the next frame. gl::AttributesMask dirtyActiveAttribs = (mAttribsToTranslate & activeLocations); for (auto dirtyAttribIndex : dirtyActiveAttribs) { mAttribsToTranslate.reset(dirtyAttribIndex); auto *translatedAttrib = &mTranslatedAttribs[dirtyAttribIndex]; const auto ¤tValue = state.getVertexAttribCurrentValue(dirtyAttribIndex); // Record basic attrib info translatedAttrib->attribute = &attribs[dirtyAttribIndex]; translatedAttrib->binding = &bindings[translatedAttrib->attribute->bindingIndex]; translatedAttrib->currentValueType = currentValue.Type; translatedAttrib->divisor = translatedAttrib->binding->divisor; switch (mAttributeStorageTypes[dirtyAttribIndex]) { case VertexStorageType::DIRECT: VertexDataManager::StoreDirectAttrib(translatedAttrib); break; case VertexStorageType::STATIC: { ANGLE_TRY(VertexDataManager::StoreStaticAttrib(translatedAttrib)); break; } case VertexStorageType::CURRENT_VALUE: // Current value attribs are managed by the StateManager11. break; default: UNREACHABLE(); break; } } } if (mDynamicAttribsMask.any()) { auto activeDynamicAttribs = (mDynamicAttribsMask & activeLocations); for (auto dynamicAttribIndex : activeDynamicAttribs) { auto *dynamicAttrib = &mTranslatedAttribs[dynamicAttribIndex]; const auto ¤tValue = state.getVertexAttribCurrentValue(dynamicAttribIndex); // Record basic attrib info dynamicAttrib->attribute = &attribs[dynamicAttribIndex]; dynamicAttrib->binding = &bindings[dynamicAttrib->attribute->bindingIndex]; dynamicAttrib->currentValueType = currentValue.Type; dynamicAttrib->divisor = dynamicAttrib->binding->divisor; } return vertexDataManager->storeDynamicAttribs(&mTranslatedAttribs, activeDynamicAttribs, start, count, instances); } return gl::NoError(); }