Add support for wide gamut render targets in Vulkan

Support rendering into FP16 render targets.
Enforce correct color space for both ARGB and F16
color formats.

Test: About 30 additional CTS tests pass with Vulkan
Bug: 116117654
Change-Id: I61941a2d79a0e69837d20816c90d3e936fd7acb0
diff --git a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
index e34f160..4ef30fc 100644
--- a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
@@ -123,8 +123,7 @@
     }
 
     if (surface) {
-        // TODO: handle color mode
-        mVkSurface = mVkManager.createSurface(surface);
+        mVkSurface = mVkManager.createSurface(surface, colorMode);
     }
 
     return mVkSurface != nullptr;
diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp
index 285a1a5..83e9db3 100644
--- a/libs/hwui/renderthread/VulkanManager.cpp
+++ b/libs/hwui/renderthread/VulkanManager.cpp
@@ -618,7 +618,8 @@
         VulkanSurface::ImageInfo& imageInfo = surface->mImageInfos[i];
         imageInfo.mSurface = SkSurface::MakeFromBackendRenderTarget(
                 mRenderThread.getGrContext(), backendRT, kTopLeft_GrSurfaceOrigin,
-                kRGBA_8888_SkColorType, nullptr, &props);
+                surface->mColorMode == ColorMode::WideColorGamut ? kRGBA_F16_SkColorType
+                : kRGBA_8888_SkColorType, nullptr, &props);
     }
 
     SkASSERT(mCommandPool != VK_NULL_HANDLE);
@@ -733,24 +734,22 @@
                     ? VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR
                     : VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
 
-    // Pick our surface format. For now, just make sure it matches our sRGB request:
-    VkFormat surfaceFormat = VK_FORMAT_UNDEFINED;
+    VkFormat surfaceFormat = VK_FORMAT_R8G8B8A8_UNORM;
     VkColorSpaceKHR colorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
-
-    bool wantSRGB = false;
-#ifdef ANDROID_ENABLE_LINEAR_BLENDING
-    wantSRGB = true;
-#endif
+    if (surface->mColorMode == ColorMode::WideColorGamut) {
+        surfaceFormat = VK_FORMAT_R16G16B16A16_SFLOAT;
+        colorSpace = VK_COLOR_SPACE_EXTENDED_SRGB_NONLINEAR_EXT;
+    }
+    bool foundSurfaceFormat = false;
     for (uint32_t i = 0; i < surfaceFormatCount; ++i) {
-        // We are assuming we can get either R8G8B8A8_UNORM or R8G8B8A8_SRGB
-        VkFormat desiredFormat = wantSRGB ? VK_FORMAT_R8G8B8A8_SRGB : VK_FORMAT_R8G8B8A8_UNORM;
-        if (desiredFormat == surfaceFormats[i].format) {
-            surfaceFormat = surfaceFormats[i].format;
-            colorSpace = surfaceFormats[i].colorSpace;
+        if (surfaceFormat == surfaceFormats[i].format
+                && colorSpace == surfaceFormats[i].colorSpace) {
+            foundSurfaceFormat = true;
+            break;
         }
     }
 
-    if (VK_FORMAT_UNDEFINED == surfaceFormat) {
+    if (!foundSurfaceFormat) {
         return false;
     }
 
@@ -812,14 +811,14 @@
     return true;
 }
 
-VulkanSurface* VulkanManager::createSurface(ANativeWindow* window) {
+VulkanSurface* VulkanManager::createSurface(ANativeWindow* window, ColorMode colorMode) {
     initialize();
 
     if (!window) {
         return nullptr;
     }
 
-    VulkanSurface* surface = new VulkanSurface();
+    VulkanSurface* surface = new VulkanSurface(colorMode);
 
     VkAndroidSurfaceCreateInfoKHR surfaceCreateInfo;
     memset(&surfaceCreateInfo, 0, sizeof(VkAndroidSurfaceCreateInfoKHR));
diff --git a/libs/hwui/renderthread/VulkanManager.h b/libs/hwui/renderthread/VulkanManager.h
index c211f5d..e54eb6a 100644
--- a/libs/hwui/renderthread/VulkanManager.h
+++ b/libs/hwui/renderthread/VulkanManager.h
@@ -26,6 +26,7 @@
 #include <ui/Fence.h>
 #include <utils/StrongPointer.h>
 #include <vk/GrVkBackendContext.h>
+#include "IRenderPipeline.h"
 
 class GrVkExtensions;
 
@@ -37,7 +38,7 @@
 
 class VulkanSurface {
 public:
-    VulkanSurface() {}
+    VulkanSurface(ColorMode colorMode) : mColorMode(colorMode) {}
 
     sk_sp<SkSurface> getBackBufferSurface() { return mBackbuffer; }
 
@@ -73,6 +74,7 @@
     VkImage* mImages = nullptr;
     ImageInfo* mImageInfos;
     uint16_t mCurrentTime = 0;
+    ColorMode mColorMode;
 };
 
 // This class contains the shared global Vulkan objects, such as VkInstance, VkDevice and VkQueue,
@@ -90,7 +92,7 @@
 
     // Given a window this creates a new VkSurfaceKHR and VkSwapchain and stores them inside a new
     // VulkanSurface object which is returned.
-    VulkanSurface* createSurface(ANativeWindow* window);
+    VulkanSurface* createSurface(ANativeWindow* window, ColorMode colorMode);
 
     // Destroy the VulkanSurface and all associated vulkan objects.
     void destroySurface(VulkanSurface* surface);