From a109675f1fad764f942bdd547d780878be35e242 Mon Sep 17 00:00:00 2001 From: BZLZHH Date: Fri, 6 Feb 2026 00:38:46 +0800 Subject: [PATCH] [Feat] (MG_State/RenderState): Support indexed blend states. --- MobileGL/MG_State/GLState/Core.cpp | 18 +++ MobileGL/MG_State/GLState/Core.h | 6 + .../GLState/RenderState/RenderState.cpp | 103 +++++++++++++++--- .../GLState/RenderState/RenderState.h | 21 +++- 4 files changed, 129 insertions(+), 19 deletions(-) diff --git a/MobileGL/MG_State/GLState/Core.cpp b/MobileGL/MG_State/GLState/Core.cpp index 87e313f0..93008e65 100644 --- a/MobileGL/MG_State/GLState/Core.cpp +++ b/MobileGL/MG_State/GLState/Core.cpp @@ -244,6 +244,14 @@ namespace MobileGL { return m_renderState.IsCapabilityEnabled(cap); } + void GLContext::SetCapabilityIndexed(CapabilityInput cap, Uint index, Bool enabled) { + m_renderState.SetCapabilityIndexed(cap, index, enabled); + } + + Bool GLContext::IsCapabilityEnabledIndexed(CapabilityInput cap, Uint index) const { + return m_renderState.IsCapabilityEnabledIndexed(cap, index); + } + void GLContext::SetBlendFunc(BlendFactor srcRGB, BlendFactor dstRGB, BlendFactor srcAlpha, BlendFactor dstAlpha) { m_renderState.SetBlendFunc(srcRGB, dstRGB, srcAlpha, dstAlpha); @@ -254,6 +262,16 @@ namespace MobileGL { m_renderState.GetBlendFunc(srcRGB, dstRGB, srcAlpha, dstAlpha); } + void GLContext::SetBlendFuncIndexed(Uint index, BlendFactor srcRGB, BlendFactor dstRGB, + BlendFactor srcAlpha, BlendFactor dstAlpha) { + m_renderState.SetBlendFuncIndexed(index, srcRGB, dstRGB, srcAlpha, dstAlpha); + } + + void GLContext::GetBlendFuncIndexed(Uint index, BlendFactor& srcRGB, BlendFactor& dstRGB, + BlendFactor& srcAlpha, BlendFactor& dstAlpha) const { + m_renderState.GetBlendFuncIndexed(index, srcRGB, dstRGB, srcAlpha, dstAlpha); + } + void GLContext::SetDepthFunc(DepthTestFunc func) { m_renderState.SetDepthFunc(func); } diff --git a/MobileGL/MG_State/GLState/Core.h b/MobileGL/MG_State/GLState/Core.h index 9e7f4001..3ac2eeac 100644 --- a/MobileGL/MG_State/GLState/Core.h +++ b/MobileGL/MG_State/GLState/Core.h @@ -92,9 +92,15 @@ namespace MobileGL { const IntVec4& GetViewport() const; // x, y, width, height void SetCapability(CapabilityInput cap, Bool enabled); Bool IsCapabilityEnabled(CapabilityInput cap) const; + void SetCapabilityIndexed(CapabilityInput cap, Uint index, Bool enabled); + Bool IsCapabilityEnabledIndexed(CapabilityInput cap, Uint index) const; void SetBlendFunc(BlendFactor srcRGB, BlendFactor dstRGB, BlendFactor srcAlpha, BlendFactor dstAlpha); void GetBlendFunc(BlendFactor& srcRGB, BlendFactor& dstRGB, BlendFactor& srcAlpha, BlendFactor& dstAlpha) const; + void SetBlendFuncIndexed(Uint index, BlendFactor srcRGB, BlendFactor dstRGB, BlendFactor srcAlpha, + BlendFactor dstAlpha); + void GetBlendFuncIndexed(Uint index, BlendFactor& srcRGB, BlendFactor& dstRGB, BlendFactor& srcAlpha, + BlendFactor& dstAlpha) const; void SetDepthFunc(DepthTestFunc func); DepthTestFunc GetDepthFunc() const; void SetDepthMask(Bool flag); diff --git a/MobileGL/MG_State/GLState/RenderState/RenderState.cpp b/MobileGL/MG_State/GLState/RenderState/RenderState.cpp index acd7f987..b23f5c34 100644 --- a/MobileGL/MG_State/GLState/RenderState/RenderState.cpp +++ b/MobileGL/MG_State/GLState/RenderState/RenderState.cpp @@ -7,6 +7,7 @@ // End of Source File Header #include "RenderState.h" +#include "MG_Util/Types.h" namespace MobileGL { namespace MG_State { @@ -43,10 +44,19 @@ namespace MobileGL { break; switch (cap) { - SET_CAPABILITY(Blend, enabled); SET_CAPABILITY(DepthTest, enabled); SET_CAPABILITY(CullFace, enabled); SET_CAPABILITY(ScissorTest, enabled); + case CapabilityInput::Blend: { + Bool stateChanged = false; + for (auto& blendState : m_parameters.BlendStates) { + if (blendState.Enabled == enabled) continue; + blendState.Enabled = enabled; + stateChanged = true; + } + if (stateChanged) ++m_version; + break; + } default: // not supported currently break; } @@ -58,35 +68,100 @@ namespace MobileGL { case CapabilityInput::capability: \ return m_parameters.capability##Enabled; switch (cap) { - RETURN_CAPABILITY(Blend); RETURN_CAPABILITY(DepthTest); RETURN_CAPABILITY(CullFace); RETURN_CAPABILITY(ScissorTest); + case CapabilityInput::Blend: + return m_parameters.BlendStates[0].Enabled; default: return false; } } + void RenderState::SetCapabilityIndexed(CapabilityInput cap, Uint index, Bool enabled) { + // Only for BlendState currently + if (cap != CapabilityInput::Blend) { + THROW_UNIMPL_EXCEPTION; + return; + } + if (index >= MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS) { + MOBILEGL_ASSERT(false, "Blend capability index out of range: %d", index); + return; + } + if (m_parameters.BlendStates[index].Enabled == enabled) return; + + m_parameters.BlendStates[index].Enabled = enabled; + ++m_version; + } + + Bool RenderState::IsCapabilityEnabledIndexed(CapabilityInput cap, Uint index) const { + // Only for BlendState currently + if (cap != CapabilityInput::Blend) { + THROW_UNIMPL_EXCEPTION; + return false; + } + if (index >= MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS) { + MOBILEGL_ASSERT(false, "Blend capability index out of range: %d", index); + return false; + } + return m_parameters.BlendStates[index].Enabled; + } + // -------------------- Blending -------------------- void RenderState::SetBlendFunc(BlendFactor srcRGB, BlendFactor dstRGB, BlendFactor srcAlpha, BlendFactor dstAlpha) { - if (m_parameters.SrcFactorRGB == srcRGB && m_parameters.DstFactorRGB == dstRGB && - m_parameters.SrcFactorAlpha == srcAlpha && m_parameters.DstFactorAlpha == dstAlpha) - return; - - m_parameters.SrcFactorRGB = srcRGB; - m_parameters.DstFactorRGB = dstRGB; - m_parameters.SrcFactorAlpha = srcAlpha; - m_parameters.DstFactorAlpha = dstAlpha; + Bool stateChanged = false; + for (auto& blendState : m_parameters.BlendStates) { + if (blendState.SrcFactorRGB == srcRGB && blendState.DstFactorRGB == dstRGB && + blendState.SrcFactorAlpha == srcAlpha && blendState.DstFactorAlpha == dstAlpha) { + continue; + } + blendState.SrcFactorRGB = srcRGB; + blendState.DstFactorRGB = dstRGB; + blendState.SrcFactorAlpha = srcAlpha; + blendState.DstFactorAlpha = dstAlpha; + stateChanged = true; + } + if (!stateChanged) return; ++m_version; } void RenderState::GetBlendFunc(BlendFactor& srcRGB, BlendFactor& dstRGB, BlendFactor& srcAlpha, BlendFactor& dstAlpha) const { - srcRGB = m_parameters.SrcFactorRGB; - dstRGB = m_parameters.DstFactorRGB; - srcAlpha = m_parameters.SrcFactorAlpha; - dstAlpha = m_parameters.DstFactorAlpha; + srcRGB = m_parameters.BlendStates[0].SrcFactorRGB; + dstRGB = m_parameters.BlendStates[0].DstFactorRGB; + srcAlpha = m_parameters.BlendStates[0].SrcFactorAlpha; + dstAlpha = m_parameters.BlendStates[0].DstFactorAlpha; + } + + void RenderState::SetBlendFuncIndexed(Uint index, BlendFactor srcRGB, BlendFactor dstRGB, + BlendFactor srcAlpha, BlendFactor dstAlpha) { + if (index >= MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS) { + MOBILEGL_ASSERT(false, "Blend function index out of range: %d", index); + return; + } + PerBufferBlendState& blendState = m_parameters.BlendStates[index]; + if (blendState.SrcFactorRGB == srcRGB && blendState.DstFactorRGB == dstRGB && + blendState.SrcFactorAlpha == srcAlpha && blendState.DstFactorAlpha == dstAlpha) { + return; + } + blendState.SrcFactorRGB = srcRGB; + blendState.DstFactorRGB = dstRGB; + blendState.SrcFactorAlpha = srcAlpha; + blendState.DstFactorAlpha = dstAlpha; + ++m_version; + } + + void RenderState::GetBlendFuncIndexed(Uint index, BlendFactor& srcRGB, BlendFactor& dstRGB, + BlendFactor& srcAlpha, BlendFactor& dstAlpha) const { + if (index >= MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS) { + MOBILEGL_ASSERT(false, "Blend function index out of range: %d", index); + return; + } + srcRGB = m_parameters.BlendStates[index].SrcFactorRGB; + dstRGB = m_parameters.BlendStates[index].DstFactorRGB; + srcAlpha = m_parameters.BlendStates[index].SrcFactorAlpha; + dstAlpha = m_parameters.BlendStates[index].DstFactorAlpha; } // -------------------- Depth -------------------- diff --git a/MobileGL/MG_State/GLState/RenderState/RenderState.h b/MobileGL/MG_State/GLState/RenderState/RenderState.h index c97f92c9..0b1a3214 100644 --- a/MobileGL/MG_State/GLState/RenderState/RenderState.h +++ b/MobileGL/MG_State/GLState/RenderState/RenderState.h @@ -9,6 +9,7 @@ #pragma once #include #include +#include namespace MobileGL { enum class BlendFactor { @@ -127,16 +128,20 @@ namespace MobileGL { Int Alignment = 4; }; + struct PerBufferBlendState { + Bool Enabled = false; + BlendFactor SrcFactorRGB = BlendFactor::One; + BlendFactor DstFactorRGB = BlendFactor::Zero; + BlendFactor SrcFactorAlpha = BlendFactor::One; + BlendFactor DstFactorAlpha = BlendFactor::Zero; + }; + struct RenderStateParameters { // Rasterization IntVec4 Viewport = IntVec4(0, 0, 0, 0); // x, y, width, height // Blending - Bool BlendEnabled = false; - BlendFactor SrcFactorRGB = BlendFactor::One; - BlendFactor DstFactorRGB = BlendFactor::Zero; - BlendFactor SrcFactorAlpha = BlendFactor::One; - BlendFactor DstFactorAlpha = BlendFactor::Zero; + Array BlendStates; // Depth Bool DepthTestEnabled = false; @@ -175,11 +180,17 @@ namespace MobileGL { // Capabilities void SetCapability(CapabilityInput cap, Bool enabled); Bool IsCapabilityEnabled(CapabilityInput cap) const; + void SetCapabilityIndexed(CapabilityInput cap, Uint index, Bool enabled); + Bool IsCapabilityEnabledIndexed(CapabilityInput cap, Uint index) const; // Blending void SetBlendFunc(BlendFactor srcRGB, BlendFactor dstRGB, BlendFactor srcAlpha, BlendFactor dstAlpha); void GetBlendFunc(BlendFactor& srcRGB, BlendFactor& dstRGB, BlendFactor& srcAlpha, BlendFactor& dstAlpha) const; + void SetBlendFuncIndexed(Uint index, BlendFactor srcRGB, BlendFactor dstRGB, BlendFactor srcAlpha, + BlendFactor dstAlpha); + void GetBlendFuncIndexed(Uint index, BlendFactor& srcRGB, BlendFactor& dstRGB, BlendFactor& srcAlpha, + BlendFactor& dstAlpha) const; // Depth void SetDepthFunc(DepthTestFunc func);