summaryrefslogtreecommitdiff
path: root/libs/hwui/renderthread/VulkanManager.cpp
diff options
context:
space:
mode:
authorGreg Daniel <egdaniel@google.com>2019-01-08 16:01:18 -0500
committerStan Iliev <stani@google.com>2019-01-18 18:56:44 +0000
commitc407678982811caef636021cacd130c08e46784a (patch)
tree1434dd400c0176cfd1e7ed9fda957d0a17aedae6 /libs/hwui/renderthread/VulkanManager.cpp
parent793f1a793c2b9cd8f7356b83b8a2e5fd8d444e9b (diff)
Add support for preTransform in Vulkan swapchain.
Test: manual building and running of apps. Bug: 110985606 Bug: 122662274 Change-Id: Id53aa1ce028b448b1f12558eec78a60e09512166
Diffstat (limited to 'libs/hwui/renderthread/VulkanManager.cpp')
-rw-r--r--libs/hwui/renderthread/VulkanManager.cpp63
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