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;