Vulkan: Fixing return code for vkQueuePresentKHR
We should let vkQueuePresentKHR return VK_SUBOPTIMAL_KHR if the preTransform bit
in VkSwapchainCreateInfoKHR doesn't match the window’s current transform.
Bug: 132976488
Test: VulkanPreTransformTest
Change-Id: I409609ab84a6be0f4e8c351b1bef88784c8f086d
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index e5f40aa..a8949d3 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -55,6 +55,22 @@
// VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR |
VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR;
+int TranslateVulkanToNativeTransform(VkSurfaceTransformFlagBitsKHR transform) {
+ switch (transform) {
+ // TODO: See TODO in TranslateNativeToVulkanTransform
+ case VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR:
+ return NATIVE_WINDOW_TRANSFORM_ROT_90;
+ case VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR:
+ return NATIVE_WINDOW_TRANSFORM_ROT_180;
+ case VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR:
+ return NATIVE_WINDOW_TRANSFORM_ROT_270;
+ case VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR:
+ case VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR:
+ default:
+ return 0;
+ }
+}
+
VkSurfaceTransformFlagBitsKHR TranslateNativeToVulkanTransform(int native) {
// Native and Vulkan transforms are isomorphic, but are represented
// differently. Vulkan transforms are built up of an optional horizontal
@@ -210,10 +226,12 @@
struct Swapchain {
Swapchain(Surface& surface_,
uint32_t num_images_,
- VkPresentModeKHR present_mode)
+ VkPresentModeKHR present_mode,
+ int pre_transform_)
: surface(surface_),
num_images(num_images_),
mailbox_mode(present_mode == VK_PRESENT_MODE_MAILBOX_KHR),
+ pre_transform(pre_transform_),
frame_timestamps_enabled(false),
shared(present_mode == VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR ||
present_mode == VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR) {
@@ -235,6 +253,7 @@
Surface& surface;
uint32_t num_images;
bool mailbox_mode;
+ int pre_transform;
bool frame_timestamps_enabled;
int64_t refresh_duration;
bool shared;
@@ -1237,9 +1256,9 @@
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
if (!mem)
return VK_ERROR_OUT_OF_HOST_MEMORY;
- Swapchain* swapchain =
- new (mem) Swapchain(surface, num_images, create_info->presentMode);
-
+ Swapchain* swapchain = new (mem)
+ Swapchain(surface, num_images, create_info->presentMode,
+ TranslateVulkanToNativeTransform(create_info->preTransform));
// -- Dequeue all buffers and create a VkImage for each --
// Any failures during or after this must cancel the dequeued buffers.
@@ -1713,6 +1732,19 @@
ReleaseSwapchainImage(device, window, fence, img);
OrphanSwapchain(device, &swapchain);
}
+ int window_transform_hint;
+ err = window->query(window, NATIVE_WINDOW_TRANSFORM_HINT,
+ &window_transform_hint);
+ if (err != 0) {
+ ALOGE("NATIVE_WINDOW_TRANSFORM_HINT query failed: %s (%d)",
+ strerror(-err), err);
+ swapchain_result = WorstPresentResult(
+ swapchain_result, VK_ERROR_SURFACE_LOST_KHR);
+ }
+ if (swapchain.pre_transform != window_transform_hint) {
+ swapchain_result =
+ WorstPresentResult(swapchain_result, VK_SUBOPTIMAL_KHR);
+ }
} else {
ReleaseSwapchainImage(device, nullptr, fence, img);
swapchain_result = VK_ERROR_OUT_OF_DATE_KHR;