From 97057cbf443ed1291eff23debd2dabb5e78fd7c6 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Wed, 3 Aug 2022 13:38:06 +0200 Subject: [PATCH] rhi: vulkan: Improve alpha swapchain logic Fixes: QTBUG-105011 Change-Id: Iea113d92e3261711b4fce88733cc2d7472b10829 Reviewed-by: Andy Nichols (cherry picked from commit 71e3840f3a36eb176fe5896c4fbc888a00968ad3) Reviewed-by: Qt Cherry-pick Bot --- src/gui/rhi/qrhivulkan.cpp | 44 +++++++++++++++++++++++++++++--------- 1 file changed, 34 insertions(+), 10 deletions(-) diff --git a/src/gui/rhi/qrhivulkan.cpp b/src/gui/rhi/qrhivulkan.cpp index 26fc3e05ed9..40019c56b0c 100644 --- a/src/gui/rhi/qrhivulkan.cpp +++ b/src/gui/rhi/qrhivulkan.cpp @@ -1425,21 +1425,45 @@ bool QRhiVulkan::recreateSwapChain(QRhiSwapChain *swapChain) ? VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR : surfaceCaps.currentTransform; + // This looks odd but matches how platforms work in practice. + // + // On Windows with NVIDIA for example, the only supportedCompositeAlpha + // value reported is OPAQUE, nothing else. Yet transparency works + // regardless, as long as the native window is set up correctly, so that's + // not something we need to handle here. + // + // On Linux with Intel and Mesa and running on xcb reports, on one + // particular system, INHERIT+PRE_MULTIPLIED. Tranparency works, regardless, + // presumably due to setting INHERIT. + // + // On the same setup with Wayland instead of xcb we see + // OPAQUE+PRE_MULTIPLIED reported. Here transparency won't work unless + // PRE_MULTIPLIED is set. + // + // Therefore our rules are: + // - Prefer INHERIT over OPAQUE. + // - Then based on the request, try the requested alpha mode, but if + // that's not reported as supported, try also the other (PRE/POST, + // POST/PRE) as that is better than nothing. This is not different from + // some other backends, e.g. D3D11 with DirectComposition there is also + // no control over being straight or pre-multiplied. Whereas with + // WGL/GLX/EGL we never had that sort of control. + VkCompositeAlphaFlagBitsKHR compositeAlpha = (surfaceCaps.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR) ? VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR : VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; - if (swapChainD->m_flags.testFlag(QRhiSwapChain::SurfaceHasPreMulAlpha) - && (surfaceCaps.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR)) - { - compositeAlpha = VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR; - } - - if (swapChainD->m_flags.testFlag(QRhiSwapChain::SurfaceHasNonPreMulAlpha) - && (surfaceCaps.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR)) - { - compositeAlpha = VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR; + if (swapChainD->m_flags.testFlag(QRhiSwapChain::SurfaceHasPreMulAlpha)) { + if (surfaceCaps.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR) + compositeAlpha = VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR; + else if (surfaceCaps.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR) + compositeAlpha = VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR; + } else if (swapChainD->m_flags.testFlag(QRhiSwapChain::SurfaceHasNonPreMulAlpha)) { + if (surfaceCaps.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR) + compositeAlpha = VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR; + else if (surfaceCaps.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR) + compositeAlpha = VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR; } VkImageUsageFlags usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;