diff options
Diffstat (limited to 'libs/hwui/renderthread/VulkanManager.cpp')
-rw-r--r-- | libs/hwui/renderthread/VulkanManager.cpp | 63 |
1 files changed, 58 insertions, 5 deletions
diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp index 6c540f627a68..5c6cb9ad43db 100644 --- a/libs/hwui/renderthread/VulkanManager.cpp +++ b/libs/hwui/renderthread/VulkanManager.cpp @@ -480,6 +480,32 @@ VulkanSurface::BackbufferInfo* VulkanManager::getAvailableBackbuffer(VulkanSurfa return backbuffer; } +static SkMatrix getPreTransformMatrix(int width, int height, + VkSurfaceTransformFlagBitsKHR transform) { + switch (transform) { + case VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR: + return SkMatrix::I(); + case VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR: + return SkMatrix::MakeAll(0, -1, height, 1, 0, 0, 0, 0, 1); + case VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR: + return SkMatrix::MakeAll(-1, 0, width, 0, -1, height, 0, 0, 1); + case VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR: + return SkMatrix::MakeAll(0, 1, 0, -1, 0, width, 0, 0, 1); + case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR: + return SkMatrix::MakeAll(-1, 0, width, 0, 1, 0, 0, 0, 1); + case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR: + return SkMatrix::MakeAll(0, -1, height, -1, 0, width, 0, 0, 1); + case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR: + return SkMatrix::MakeAll(1, 0, 0, 0, -1, height, 0, 0, 1); + case VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR: + return SkMatrix::MakeAll(0, 1, 0, 1, 0, 0, 0, 0, 1); + default: + LOG_ALWAYS_FATAL("Unsupported pre transform of swapchain."); + } + return SkMatrix::I(); +} + + SkSurface* VulkanManager::getBackbufferSurface(VulkanSurface** surfaceOut) { // Recreate VulkanSurface, if ANativeWindow has been resized. VulkanSurface* surface = *surfaceOut; @@ -516,7 +542,7 @@ SkSurface* VulkanManager::getBackbufferSurface(VulkanSurface** surfaceOut) { // maybe use attach somehow? but need a Window return nullptr; } - if (VK_ERROR_OUT_OF_DATE_KHR == res) { + if (VK_ERROR_OUT_OF_DATE_KHR == res || VK_SUBOPTIMAL_KHR == res) { // tear swapchain down and try again if (!createSwapchain(surface)) { return nullptr; @@ -595,6 +621,10 @@ SkSurface* VulkanManager::getBackbufferSurface(VulkanSurface** surfaceOut) { } backendRT.setVkImageLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + surface->mPreTransform = getPreTransformMatrix(surface->windowWidth(), + surface->windowHeight(), + surface->mTransform); + surface->mBackbuffer = std::move(skSurface); return surface->mBackbuffer.get(); } @@ -749,6 +779,17 @@ bool VulkanManager::createSwapchain(VulkanSurface* surface) { return false; } + if (!SkToBool(caps.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR)) { + return false; + } + VkSurfaceTransformFlagBitsKHR transform; + if (SkToBool(caps.supportedTransforms & caps.currentTransform) && + !SkToBool(caps.currentTransform & VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR)) { + transform = caps.currentTransform; + } else { + transform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; + } + VkExtent2D extent = caps.currentExtent; // clamp width; to handle currentExtent of -1 and protect us from broken hints if (extent.width < caps.minImageExtent.width) { @@ -760,6 +801,16 @@ bool VulkanManager::createSwapchain(VulkanSurface* surface) { extent.height = caps.minImageExtent.height; } SkASSERT(extent.height <= caps.maxImageExtent.height); + + VkExtent2D swapExtent = extent; + if (transform == VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR || + transform == VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR || + transform == VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR || + transform == VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR) { + swapExtent.width = extent.height; + swapExtent.height = extent.width; + } + surface->mWindowWidth = extent.width; surface->mWindowHeight = extent.height; @@ -775,7 +826,7 @@ bool VulkanManager::createSwapchain(VulkanSurface* surface) { VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; SkASSERT((caps.supportedUsageFlags & usageFlags) == usageFlags); - SkASSERT(caps.supportedTransforms & caps.currentTransform); + SkASSERT(caps.supportedCompositeAlpha & (VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR | VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR)); VkCompositeAlphaFlagBitsKHR composite_alpha = @@ -822,7 +873,7 @@ bool VulkanManager::createSwapchain(VulkanSurface* surface) { swapchainCreateInfo.minImageCount = imageCount; swapchainCreateInfo.imageFormat = surfaceFormat; swapchainCreateInfo.imageColorSpace = colorSpace; - swapchainCreateInfo.imageExtent = extent; + swapchainCreateInfo.imageExtent = swapExtent; swapchainCreateInfo.imageArrayLayers = 1; swapchainCreateInfo.imageUsage = usageFlags; @@ -837,7 +888,7 @@ bool VulkanManager::createSwapchain(VulkanSurface* surface) { swapchainCreateInfo.pQueueFamilyIndices = nullptr; } - swapchainCreateInfo.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; + swapchainCreateInfo.preTransform = transform; swapchainCreateInfo.compositeAlpha = composite_alpha; swapchainCreateInfo.presentMode = mode; swapchainCreateInfo.clipped = true; @@ -848,6 +899,8 @@ bool VulkanManager::createSwapchain(VulkanSurface* surface) { return false; } + surface->mTransform = transform; + // destroy the old swapchain if (swapchainCreateInfo.oldSwapchain != VK_NULL_HANDLE) { mDeviceWaitIdle(mDevice); @@ -857,7 +910,7 @@ bool VulkanManager::createSwapchain(VulkanSurface* surface) { mDestroySwapchainKHR(mDevice, swapchainCreateInfo.oldSwapchain, nullptr); } - createBuffers(surface, surfaceFormat, extent); + createBuffers(surface, surfaceFormat, swapExtent); // The window content is not updated (frozen) until a buffer of the window size is received. // This prevents temporary stretching of the window after it is resized, but before the first |