From f7ec86c5d57c45db75df9fa22ac3add7cb6d56a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 12 Oct 2026 17:22:41 +0200 Subject: [PATCH] Android Vulkan: Don't trust a stale surface extent after a rotation Since rotation is handled in place, the swapchain is recreated right after surfaceChanged, and the surface can still report the previous orientation's extent. On a Galaxy S8+ this happened in about one in four rotations, leaving a portrait swapchain on a landscape window or the other way around, squashed into half the screen until the next rotation. If the extent is exactly the window size transposed, use the window size. Co-Authored-By: Claude Opus 5.5 --- Common/GPU/Vulkan/VulkanContext.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Common/GPU/Vulkan/VulkanContext.cpp b/Common/GPU/Vulkan/VulkanContext.cpp index bbb44768ef..c1e8ea7eb5 100644 --- a/Common/GPU/Vulkan/VulkanContext.cpp +++ b/Common/GPU/Vulkan/VulkanContext.cpp @@ -1532,6 +1532,19 @@ bool VulkanContext::InitSwapchain(VkPresentModeKHR desiredPresentMode) { } } +#if PPSSPP_PLATFORM(ANDROID) + // Right after an in-place rotation, the surface can still report the previous orientation's extent (seen + // on a Mali Galaxy S8+, when queried within a few ms of surfaceChanged). That leaves a portrait swapchain + // on a landscape window or the other way around, until the next rotation. The window size we were told + // about is current, so if the extent is exactly that transposed, it's stale. + if (g_display.pixel_xres > 0 && g_display.pixel_yres > 0 && g_display.pixel_xres != g_display.pixel_yres && + currentExtent.width == (uint32_t)g_display.pixel_yres && currentExtent.height == (uint32_t)g_display.pixel_xres) { + WARN_LOG(Log::G3D, "Surface extent %dx%d is the window transposed, probably stale after a rotation. Using %dx%d.", + currentExtent.width, currentExtent.height, g_display.pixel_xres, g_display.pixel_yres); + std::swap(currentExtent.width, currentExtent.height); + } +#endif + swapChainExtent_.width = clamp(currentExtent.width, surfCapabilities_.minImageExtent.width, surfCapabilities_.maxImageExtent.width); swapChainExtent_.height = clamp(currentExtent.height, surfCapabilities_.minImageExtent.height, surfCapabilities_.maxImageExtent.height);