diff --git a/MobileGL/MG_Backend/DirectGLES/Managers.cpp b/MobileGL/MG_Backend/DirectGLES/Managers.cpp index 0e3efb6c..cf8a400f 100644 --- a/MobileGL/MG_Backend/DirectGLES/Managers.cpp +++ b/MobileGL/MG_Backend/DirectGLES/Managers.cpp @@ -2405,7 +2405,19 @@ namespace MobileGL::MG_Backend::DirectGLES { MGLOG_D("%s(%s:%d) ES error %s", func, file, line, MG_Util::ConvertGLEnumToString(err).c_str()); }); - const auto& swizzleParams = stateTextureObject->GetAllSwizzleParams(); + // A three-channel format widened to four for a multisample target (see + // NormalizePixelFormat) gains an alpha channel the frontend format does not have, and + // whatever the draw that filled it wrote there is not what GL would report: a format + // without alpha reads back as 1.0. Answer the ALPHA swizzle source with ONE so the + // promotion stays invisible, composed with the swizzle the application asked for. + Vec4 swizzleParams = stateTextureObject->GetAllSwizzleParams(); + if (TextureImpl::BackendTextureFormatAddsAlpha(stateTextureObject->GetFormat(), targetInternal)) { + for (SizeT channel = 0; channel < 4; ++channel) { + if (swizzleParams[channel] == TextureSwizzleParam::Alpha) { + swizzleParams[channel] = TextureSwizzleParam::One; + } + } + } if (swizzleParams != m_cacheSwizzleParams) { #define SYNC_TEX_SWIZZLE_PARAM_IF_CHANGED(func, glEnum) \ if (m_cacheSwizzleParams.func != swizzleParams.func) { \ diff --git a/MobileGL/MG_Backend/DirectGLES/Utils.cpp b/MobileGL/MG_Backend/DirectGLES/Utils.cpp index 1ccb8aa7..0693b5e7 100644 --- a/MobileGL/MG_Backend/DirectGLES/Utils.cpp +++ b/MobileGL/MG_Backend/DirectGLES/Utils.cpp @@ -177,6 +177,22 @@ namespace MobileGL::MG_Backend::DirectGLES { Bool ShouldUseCaveatRenderbufferFormat(TextureInternalFormat internalFormat) { return ShouldUseCaveatFormat(internalFormat, GetRenderbufferFormatCapabilityTargetIndex()); } + + Bool BackendTextureFormatAddsAlpha(TextureInternalFormat internalFormat, TextureTarget target) { + const SizeT targetIndex = + target == TextureTarget::Unknown ? kFormatCapabilityTargetCount : GetFormatCapabilityTargetIndex(target); + if (!TargetRequiresRenderableFormat(targetIndex)) { + return false; + } + if (pActiveBackendObject && !ShouldUseCaveatFormat(internalFormat, targetIndex)) { + return false; + } + const GLenum requestedInternalFormat = MG_Util::ConvertTextureInternalFormatToGLEnum(internalFormat); + const Flags options = + GetRuntimeFallbackNormalizeOptions(requestedInternalFormat, + GetRenderTargetNormalizeOptions(targetIndex)); + return static_cast(options & PixelFormatNormalizeOptionBit::NoThreeChannelRenderTarget); + } } // namespace TextureImpl namespace PrgramImpl { String ProcessOutColorLocations(const String& glslCode) { diff --git a/MobileGL/MG_Backend/DirectGLES/Utils.h b/MobileGL/MG_Backend/DirectGLES/Utils.h index fd896892..e433df2a 100644 --- a/MobileGL/MG_Backend/DirectGLES/Utils.h +++ b/MobileGL/MG_Backend/DirectGLES/Utils.h @@ -40,6 +40,11 @@ namespace MobileGL::MG_Backend::DirectGLES { void GenerateRenderbufferFormatInfo(TextureInternalFormat internalFormat, GLenum* outInternalFormat, GLenum* outFormat, GLenum* outType); Bool ShouldUseCaveatTextureFormat(TextureInternalFormat internalFormat, TextureTarget target); + + // True when the format the texture is actually created with has an alpha channel the + // frontend format does not (the three-channel multisample widening). GL reads such a + // channel back as 1.0, so any swizzle source of ALPHA has to be answered with ONE. + Bool BackendTextureFormatAddsAlpha(TextureInternalFormat internalFormat, TextureTarget target); Bool ShouldUseCaveatRenderbufferFormat(TextureInternalFormat internalFormat); } // namespace TextureImpl