From a109675f1fad764f942bdd547d780878be35e242 Mon Sep 17 00:00:00 2001 From: BZLZHH Date: Fri, 6 Feb 2026 00:38:46 +0800 Subject: [PATCH 1/3] [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); From 91eb75a95d952bd32cdce6bd778885f1ce55b18c Mon Sep 17 00:00:00 2001 From: BZLZHH Date: Fri, 6 Feb 2026 01:03:51 +0800 Subject: [PATCH 2/3] [Feat] (MG_Impl/RenderState): Implement Enablei, Disablei, BlendFuncSeparatei, IsEnabled, IsEnabledi. --- .../MG_Impl/GLImpl/Exporting/Definitions.cpp | 6 +- .../GLImpl/RenderState/GL_RenderState.cpp | 87 ++++++++++++++++++- .../GLImpl/RenderState/GL_RenderState.h | 3 + 3 files changed, 89 insertions(+), 7 deletions(-) diff --git a/MobileGL/MG_Impl/GLImpl/Exporting/Definitions.cpp b/MobileGL/MG_Impl/GLImpl/Exporting/Definitions.cpp index 4847a903..3f40d24c 100644 --- a/MobileGL/MG_Impl/GLImpl/Exporting/Definitions.cpp +++ b/MobileGL/MG_Impl/GLImpl/Exporting/Definitions.cpp @@ -385,15 +385,15 @@ DECLARE_GL_FUNCTION_STUB_HEAD(void, GetObjectLabel, GLenum identifier, GLuint na DECLARE_GL_FUNCTION_STUB_HEAD(void, ObjectPtrLabel, const void* ptr, GLsizei length, const GLchar* label) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ObjectPtrLabel, ptr, length, label) DECLARE_GL_FUNCTION_STUB_HEAD(void, GetObjectPtrLabel, const void* ptr, GLsizei bufSize, GLsizei* length, GLchar* label) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetObjectPtrLabel, ptr, bufSize, length, label) DECLARE_GL_FUNCTION_STUB_HEAD(void, GetPointerv, GLenum pname, void** params) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, GetPointerv, pname, params) -DECLARE_GL_FUNCTION_STUB_HEAD(void, Enablei, GLenum target, GLuint index) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, Enablei, target, index) -DECLARE_GL_FUNCTION_STUB_HEAD(void, Disablei, GLenum target, GLuint index) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, Disablei, target, index) +DECLARE_GL_FUNCTION_HEAD(void, Enablei, GLenum target, GLuint index) DECLARE_GL_FUNCTION_END_NO_RETURN(void, Enablei, target, index) +DECLARE_GL_FUNCTION_HEAD(void, Disablei, GLenum target, GLuint index) DECLARE_GL_FUNCTION_END_NO_RETURN(void, Disablei, target, index) DECLARE_GL_FUNCTION_STUB_HEAD(void, BlendEquationi, GLuint buf, GLenum mode) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, BlendEquationi, buf, mode) DECLARE_GL_FUNCTION_STUB_HEAD(void, BlendEquationiARB, GLuint buf, GLenum mode) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, BlendEquationi, buf, mode) DECLARE_GL_FUNCTION_STUB_HEAD(void, BlendEquationSeparatei, GLuint buf, GLenum modeRGB, GLenum modeAlpha) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, BlendEquationSeparatei, buf, modeRGB, modeAlpha) DECLARE_GL_FUNCTION_STUB_HEAD(void, BlendEquationSeparateiARB, GLuint buf, GLenum modeRGB, GLenum modeAlpha) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, BlendEquationSeparatei, buf, modeRGB, modeAlpha) DECLARE_GL_FUNCTION_STUB_HEAD(void, BlendFunci, GLuint buf, GLenum src, GLenum dst) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, BlendFunci, buf, src, dst) DECLARE_GL_FUNCTION_STUB_HEAD(void, BlendFunciARB, GLuint buf, GLenum src, GLenum dst) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, BlendFunci, buf, src, dst) -DECLARE_GL_FUNCTION_STUB_HEAD(void, BlendFuncSeparatei, GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, BlendFuncSeparatei, buf, srcRGB, dstRGB, srcAlpha, dstAlpha) +DECLARE_GL_FUNCTION_HEAD(void, BlendFuncSeparatei, GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) DECLARE_GL_FUNCTION_END_NO_RETURN(void, BlendFuncSeparatei, buf, srcRGB, dstRGB, srcAlpha, dstAlpha) DECLARE_GL_FUNCTION_STUB_HEAD(void, BlendFuncSeparateiARB, GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, BlendFuncSeparatei, buf, srcRGB, dstRGB, srcAlpha, dstAlpha) DECLARE_GL_FUNCTION_STUB_HEAD(void, ColorMaski, GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a) DECLARE_GL_FUNCTION_STUB_END_NO_RETURN(void, ColorMaski, index, r, g, b, a) DECLARE_GL_FUNCTION_HEAD(GLboolean, IsEnabledi, GLenum target, GLuint index) DECLARE_GL_FUNCTION_END(GLboolean, IsEnabledi, target, index) diff --git a/MobileGL/MG_Impl/GLImpl/RenderState/GL_RenderState.cpp b/MobileGL/MG_Impl/GLImpl/RenderState/GL_RenderState.cpp index 57548582..3f4f2b55 100644 --- a/MobileGL/MG_Impl/GLImpl/RenderState/GL_RenderState.cpp +++ b/MobileGL/MG_Impl/GLImpl/RenderState/GL_RenderState.cpp @@ -111,13 +111,32 @@ namespace MobileGL { } GLboolean IsEnabledi_State(GLenum target, GLuint index) { - // TODO: implement - return GL_FALSE; + CapabilityInput capInput = MG_Util::ConvertGLEnumToCapabilityInput(target); + if (capInput == CapabilityInput::Unknown) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidEnum, + MakeShared("MG_Impl/GLImpl", "IsEnabledi_State", + "Capability enum " + + MG_Util::ConvertCapabilityInputToString(capInput) + "(" + + MG_Util::ConvertGLEnumToString(target) + ") is not supported.")); + return GL_FALSE; + } + + return MG_State::pGLContext->IsCapabilityEnabledIndexed(capInput, index) ? GL_TRUE : GL_FALSE; } GLboolean IsEnabled_State(GLenum cap) { - // TODO: implement - return GL_FALSE; + CapabilityInput capInput = MG_Util::ConvertGLEnumToCapabilityInput(cap); + if (capInput == CapabilityInput::Unknown) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidEnum, MakeShared( + "MG_Impl/GLImpl", "IsEnabled_State", + "Capability enum " + MG_Util::ConvertCapabilityInputToString(capInput) + + "(" + MG_Util::ConvertGLEnumToString(cap) + ") is not supported.")); + return GL_FALSE; + } + + return MG_State::pGLContext->IsCapabilityEnabled(capInput) ? GL_TRUE : GL_FALSE; } void Hint_State(GLenum target, GLenum mode) { @@ -253,7 +272,67 @@ namespace MobileGL { MG_State::pGLContext->SetClearColor(FloatVec4(red, green, blue, alpha)); } + void BlendFuncSeparatei_State(GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) { + if (buf >= MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidValue, + MakeShared( + "MG_Impl/GLImpl", "BlendFuncSeparatei_State", + "Buffer index " + std::to_string(buf) + " is out of range. Max supported is " + + std::to_string(MG_State::GLState::FramebufferObject::MAX_DRAW_BUFFERS - 1) + ".")); + return; + } + + BlendFactor srcRGBM = MG_Util::ConvertGLEnumToBlendFactor(srcRGB); + BlendFactor dstRGBM = MG_Util::ConvertGLEnumToBlendFactor(dstRGB); + BlendFactor srcAlphaM = MG_Util::ConvertGLEnumToBlendFactor(srcAlpha); + BlendFactor dstAlphaM = MG_Util::ConvertGLEnumToBlendFactor(dstAlpha); + MG_State::pGLContext->SetBlendFuncIndexed(buf, srcRGBM, dstRGBM, srcAlphaM, dstAlphaM); + } + + void Disablei_State(GLenum target, GLuint index) { + auto capInput = MG_Util::ConvertGLEnumToCapabilityInput(target); + if (capInput == CapabilityInput::Unknown) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidEnum, + MakeShared("MG_Impl/GLImpl", "Disablei_State", + "Capability enum " + + MG_Util::ConvertCapabilityInputToString(capInput) + "(" + + MG_Util::ConvertGLEnumToString(target) + ") is not supported.")); + return; + } + + MG_State::pGLContext->SetCapabilityIndexed(capInput, index, false); + } + + void Enablei_State(GLenum target, GLuint index) { + auto capInput = MG_Util::ConvertGLEnumToCapabilityInput(target); + if (capInput == CapabilityInput::Unknown) { + MG_State::pGLContext->RecordError( + ErrorCode::InvalidEnum, + MakeShared("MG_Impl/GLImpl", "Enablei_State", + "Capability enum " + + MG_Util::ConvertCapabilityInputToString(capInput) + "(" + + MG_Util::ConvertGLEnumToString(target) + ") is not supported.")); + return; + } + + MG_State::pGLContext->SetCapabilityIndexed(capInput, index, true); + } + /* @INSERTION_POINT:FUNCTION_IMPLEMENTATION@ */ + void BlendFuncSeparatei(GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) { + BlendFuncSeparatei_State(buf, srcRGB, dstRGB, srcAlpha, dstAlpha); + } + + void Disablei(GLenum target, GLuint index) { + Disablei_State(target, index); + } + + void Enablei(GLenum target, GLuint index) { + Enablei_State(target, index); + } + void BlendFunc(GLenum sfactor, GLenum dfactor) { BlendFunc_State(sfactor, dfactor); } diff --git a/MobileGL/MG_Impl/GLImpl/RenderState/GL_RenderState.h b/MobileGL/MG_Impl/GLImpl/RenderState/GL_RenderState.h index 0dac02b3..36e1551d 100644 --- a/MobileGL/MG_Impl/GLImpl/RenderState/GL_RenderState.h +++ b/MobileGL/MG_Impl/GLImpl/RenderState/GL_RenderState.h @@ -12,6 +12,9 @@ namespace MobileGL { namespace MG_Impl::GLImpl { /* @INSERTION_POINT:FUNCTION_DECLARATION@ */ + void BlendFuncSeparatei(GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); + void Disablei(GLenum target, GLuint index); + void Enablei(GLenum target, GLuint index); void BlendFunc(GLenum sfactor, GLenum dfactor); void Viewport(GLint x, GLint y, GLsizei width, GLsizei height); void StencilOpSeparate(GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass); From 07927dc4a3333581f23f714a16274d690d6b82fa Mon Sep 17 00:00:00 2001 From: BZLZHH Date: Fri, 6 Feb 2026 01:05:18 +0800 Subject: [PATCH 3/3] [Feat] (MG_Backend/DirectGLES): Sync indexed blend states. --- MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp | 109 ++++++++++++++++-- 1 file changed, 98 insertions(+), 11 deletions(-) diff --git a/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp b/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp index 4710e3a4..25afd4ef 100644 --- a/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp +++ b/MobileGL/MG_Backend/DirectGLES/DirectGLES.cpp @@ -305,7 +305,6 @@ namespace MobileGL::MG_Backend::DirectGLES { MG_External::GLES::glDisable(cap_gl); \ } \ } - SYNC_CAPABILITY(Blend, GL_BLEND); SYNC_CAPABILITY(DepthTest, GL_DEPTH_TEST); SYNC_CAPABILITY(ScissorTest, GL_SCISSOR_TEST); SYNC_CAPABILITY(CullFace, GL_CULL_FACE); @@ -314,19 +313,107 @@ namespace MobileGL::MG_Backend::DirectGLES { const auto& ToGLBoolean = [](Bool b) -> GLboolean { return b ? GL_TRUE : GL_FALSE; }; - if (parameters.SrcFactorRGB != g_syncedRenderStateParameters.SrcFactorRGB || - parameters.DstFactorRGB != g_syncedRenderStateParameters.DstFactorRGB || - parameters.SrcFactorAlpha != g_syncedRenderStateParameters.SrcFactorAlpha || - parameters.DstFactorAlpha != g_syncedRenderStateParameters.DstFactorAlpha) { // Blend func - const BlendFactor &srcRGB = parameters.SrcFactorRGB, &dstRGB = parameters.DstFactorRGB, - &srcAlpha = parameters.SrcFactorAlpha, &dstAlpha = parameters.DstFactorAlpha; + { // Blend State + using FBO = MG_State::GLState::FramebufferObject; + const auto& targetStates = parameters.BlendStates; + auto& syncedStates = g_syncedRenderStateParameters.BlendStates; - MG_External::GLES::glBlendFuncSeparate( - MG_Util::ConvertBlendFactorToGLEnum(srcRGB), MG_Util::ConvertBlendFactorToGLEnum(dstRGB), - MG_Util::ConvertBlendFactorToGLEnum(srcAlpha), MG_Util::ConvertBlendFactorToGLEnum(dstAlpha)); + Bool allEnabled = true; + Bool allDisabled = true; + Bool anyCapDirty = false; + + for (Uint i = 0; i < FBO::MAX_DRAW_BUFFERS; ++i) { + Bool enabled = targetStates[i].Enabled; + if (enabled) + allDisabled = false; + else + allEnabled = false; + + if (enabled != syncedStates[i].Enabled) { + anyCapDirty = true; + } + } + + if (anyCapDirty) { + if (allEnabled) { + MG_External::GLES::glEnable(GL_BLEND); + for (auto& s : syncedStates) + s.Enabled = true; + } else if (allDisabled) { + MG_External::GLES::glDisable(GL_BLEND); + for (auto& s : syncedStates) + s.Enabled = false; + } else { + for (Uint i = 0; i < FBO::MAX_DRAW_BUFFERS; ++i) { + if (targetStates[i].Enabled != syncedStates[i].Enabled) { + syncedStates[i].Enabled = targetStates[i].Enabled; + syncedStates[i].Enabled ? MG_External::GLES::glEnablei(GL_BLEND, i) + : MG_External::GLES::glDisablei(GL_BLEND, i); + } + } + } + } + + Bool allFuncsSame = true; + Bool anyFuncDirty = false; + const auto& first = targetStates[0]; + + for (Uint i = 0; i < FBO::MAX_DRAW_BUFFERS; ++i) { + const auto& cur = targetStates[i]; + const auto& syn = syncedStates[i]; + + Bool isDiffFromSyn = + (cur.SrcFactorRGB != syn.SrcFactorRGB || cur.DstFactorRGB != syn.DstFactorRGB || + cur.SrcFactorAlpha != syn.SrcFactorAlpha || cur.DstFactorAlpha != syn.DstFactorAlpha); + + if (isDiffFromSyn) anyFuncDirty = true; + + if (allFuncsSame && i > 0) { + if (cur.SrcFactorRGB != first.SrcFactorRGB || cur.DstFactorRGB != first.DstFactorRGB || + cur.SrcFactorAlpha != first.SrcFactorAlpha || cur.DstFactorAlpha != first.DstFactorAlpha) { + allFuncsSame = false; + } + } + } + + if (anyFuncDirty) { + if (allFuncsSame) { + MG_External::GLES::glBlendFuncSeparate( + MG_Util::ConvertBlendFactorToGLEnum(first.SrcFactorRGB), + MG_Util::ConvertBlendFactorToGLEnum(first.DstFactorRGB), + MG_Util::ConvertBlendFactorToGLEnum(first.SrcFactorAlpha), + MG_Util::ConvertBlendFactorToGLEnum(first.DstFactorAlpha)); + + for (auto& syn : syncedStates) { + syn.SrcFactorRGB = first.SrcFactorRGB; + syn.DstFactorRGB = first.DstFactorRGB; + syn.SrcFactorAlpha = first.SrcFactorAlpha; + syn.DstFactorAlpha = first.DstFactorAlpha; + } + } else { + for (Uint i = 0; i < FBO::MAX_DRAW_BUFFERS; ++i) { + const auto& cur = targetStates[i]; + auto& syn = syncedStates[i]; + + if (cur.SrcFactorRGB != syn.SrcFactorRGB || cur.DstFactorRGB != syn.DstFactorRGB || + cur.SrcFactorAlpha != syn.SrcFactorAlpha || cur.DstFactorAlpha != syn.DstFactorAlpha) { + syn.SrcFactorRGB = cur.SrcFactorRGB; + syn.DstFactorRGB = cur.DstFactorRGB; + syn.SrcFactorAlpha = cur.SrcFactorAlpha; + syn.DstFactorAlpha = cur.DstFactorAlpha; + + MG_External::GLES::glBlendFuncSeparatei( + i, MG_Util::ConvertBlendFactorToGLEnum(cur.SrcFactorRGB), + MG_Util::ConvertBlendFactorToGLEnum(cur.DstFactorRGB), + MG_Util::ConvertBlendFactorToGLEnum(cur.SrcFactorAlpha), + MG_Util::ConvertBlendFactorToGLEnum(cur.DstFactorAlpha)); + } + } + } + } } - { // Blend equation + { // Depth state if (parameters.DepthFunc != g_syncedRenderStateParameters.DepthFunc) { MG_External::GLES::glDepthFunc(MG_Util::ConvertDepthTestFuncToGLEnum(parameters.DepthFunc)); }