[fuchsia] Add R8G8B8A8 external image support. am: 6a2544969b

Change-Id: I985ee2f5d483ef0d04d758dad9bfa563b1228e12
diff --git a/system/vulkan_enc/ResourceTracker.cpp b/system/vulkan_enc/ResourceTracker.cpp
index c5bf514..2d2e650 100644
--- a/system/vulkan_enc/ResourceTracker.cpp
+++ b/system/vulkan_enc/ResourceTracker.cpp
@@ -1653,9 +1653,9 @@
         delete sysmem_collection;
     }
 
-    void setBufferCollectionConstraints(fuchsia::sysmem::BufferCollectionSyncPtr* collection,
-                                        const VkImageCreateInfo* pImageInfo,
-                                        size_t min_size_bytes) {
+    VkResult setBufferCollectionConstraints(fuchsia::sysmem::BufferCollectionSyncPtr* collection,
+                                            const VkImageCreateInfo* pImageInfo,
+                                            size_t min_size_bytes) {
         fuchsia::sysmem::BufferCollectionConstraints constraints = {};
         constraints.usage.vulkan = fuchsia::sysmem::vulkanUsageColorAttachment |
                                    fuchsia::sysmem::vulkanUsageTransferSrc |
@@ -1675,28 +1675,60 @@
         buffer_constraints.heap_permitted_count = 1;
         buffer_constraints.heap_permitted[0] =
             fuchsia::sysmem::HeapType::GOLDFISH_DEVICE_LOCAL;
-        constraints.image_format_constraints_count = 1;
-        fuchsia::sysmem::ImageFormatConstraints& image_constraints =
-            constraints.image_format_constraints[0];
-        image_constraints.pixel_format.type = fuchsia::sysmem::PixelFormatType::BGRA32;
-        image_constraints.color_spaces_count = 1;
-        image_constraints.color_space[0].type = fuchsia::sysmem::ColorSpaceType::SRGB;
-        image_constraints.min_coded_width = pImageInfo->extent.width;
-        image_constraints.max_coded_width = 0xfffffff;
-        image_constraints.min_coded_height = pImageInfo->extent.height;
-        image_constraints.max_coded_height = 0xffffffff;
-        image_constraints.min_bytes_per_row = pImageInfo->extent.width * 4;
-        image_constraints.max_bytes_per_row = 0xffffffff;
-        image_constraints.max_coded_width_times_coded_height = 0xffffffff;
-        image_constraints.layers = 1;
-        image_constraints.coded_width_divisor = 1;
-        image_constraints.coded_height_divisor = 1;
-        image_constraints.bytes_per_row_divisor = 1;
-        image_constraints.start_offset_divisor = 1;
-        image_constraints.display_width_divisor = 1;
-        image_constraints.display_height_divisor = 1;
+        std::vector<VkFormat> formats{pImageInfo->format};
+        if (pImageInfo->format == VK_FORMAT_UNDEFINED) {
+            // This is a hack to allow the client to say it supports every vulkan format the driver
+            // does. TODO(fxb/13247): Modify this function to take a list of vulkan formats to use.
+            formats = std::vector<VkFormat>{
+                VK_FORMAT_B8G8R8A8_UNORM,
+                VK_FORMAT_R8G8B8A8_UNORM,
+            };
+        }
+        constraints.image_format_constraints_count = formats.size();
+        uint32_t format_index = 0;
+        for (VkFormat format : formats) {
+            fuchsia::sysmem::ImageFormatConstraints& image_constraints =
+                constraints.image_format_constraints[format_index++];
+            switch (format) {
+            case VK_FORMAT_B8G8R8A8_SINT:
+            case VK_FORMAT_B8G8R8A8_UNORM:
+            case VK_FORMAT_B8G8R8A8_SRGB:
+            case VK_FORMAT_B8G8R8A8_SNORM:
+            case VK_FORMAT_B8G8R8A8_SSCALED:
+            case VK_FORMAT_B8G8R8A8_USCALED:
+                image_constraints.pixel_format.type = fuchsia::sysmem::PixelFormatType::BGRA32;
+                break;
+            case VK_FORMAT_R8G8B8A8_SINT:
+            case VK_FORMAT_R8G8B8A8_UNORM:
+            case VK_FORMAT_R8G8B8A8_SRGB:
+            case VK_FORMAT_R8G8B8A8_SNORM:
+            case VK_FORMAT_R8G8B8A8_SSCALED:
+            case VK_FORMAT_R8G8B8A8_USCALED:
+                image_constraints.pixel_format.type = fuchsia::sysmem::PixelFormatType::R8G8B8A8;
+                break;
+            default:
+                return VK_ERROR_FORMAT_NOT_SUPPORTED;
+            }
+            image_constraints.color_spaces_count = 1;
+            image_constraints.color_space[0].type = fuchsia::sysmem::ColorSpaceType::SRGB;
+            image_constraints.min_coded_width = pImageInfo->extent.width;
+            image_constraints.max_coded_width = 0xfffffff;
+            image_constraints.min_coded_height = pImageInfo->extent.height;
+            image_constraints.max_coded_height = 0xffffffff;
+            image_constraints.min_bytes_per_row = pImageInfo->extent.width * 4;
+            image_constraints.max_bytes_per_row = 0xffffffff;
+            image_constraints.max_coded_width_times_coded_height = 0xffffffff;
+            image_constraints.layers = 1;
+            image_constraints.coded_width_divisor = 1;
+            image_constraints.coded_height_divisor = 1;
+            image_constraints.bytes_per_row_divisor = 1;
+            image_constraints.start_offset_divisor = 1;
+            image_constraints.display_width_divisor = 1;
+            image_constraints.display_height_divisor = 1;
+        }
 
         (*collection)->SetConstraints(true, constraints);
+        return VK_SUCCESS;
     }
 
     VkResult on_vkSetBufferCollectionConstraintsFUCHSIA(
@@ -1705,10 +1737,9 @@
         const VkImageCreateInfo* pImageInfo) {
         auto sysmem_collection =
             reinterpret_cast<fuchsia::sysmem::BufferCollectionSyncPtr*>(collection);
-        setBufferCollectionConstraints(
+        return setBufferCollectionConstraints(
             sysmem_collection, pImageInfo,
             pImageInfo->extent.width * pImageInfo->extent.height * 4);
-        return VK_SUCCESS;
     }
 
     VkResult on_vkGetBufferCollectionPropertiesFUCHSIA(
@@ -2159,9 +2190,13 @@
                     ALOGE("BindSharedCollection failed: %d", status);
                     abort();
                 }
-                setBufferCollectionConstraints(&collection,
-                                               &imageCreateInfo,
-                                               finalAllocInfo.allocationSize);
+                VkResult res = setBufferCollectionConstraints(&collection,
+                                                              &imageCreateInfo,
+                                                              finalAllocInfo.allocationSize);
+                if (res != VK_SUCCESS) {
+                    ALOGE("setBufferCollectionConstraints failed: %d", res);
+                    abort();
+                }
 
                 fuchsia::sysmem::BufferCollectionInfo_2 info;
                 zx_status_t status2;
@@ -2187,13 +2222,35 @@
                     ALOGE("Failed to duplicate VMO: %d", status);
                     abort();
                 }
-                // TODO(reveman): Use imageCreateInfo.format to determine color
-                // buffer format.
+
+                fuchsia::hardware::goldfish::ColorBufferFormatType format;
+                switch (imageCreateInfo.format) {
+                case VK_FORMAT_B8G8R8A8_SINT:
+                case VK_FORMAT_B8G8R8A8_UNORM:
+                case VK_FORMAT_B8G8R8A8_SRGB:
+                case VK_FORMAT_B8G8R8A8_SNORM:
+                case VK_FORMAT_B8G8R8A8_SSCALED:
+                case VK_FORMAT_B8G8R8A8_USCALED:
+                    format = fuchsia::hardware::goldfish::ColorBufferFormatType::BGRA;
+                    break;
+                case VK_FORMAT_R8G8B8A8_SINT:
+                case VK_FORMAT_R8G8B8A8_UNORM:
+                case VK_FORMAT_R8G8B8A8_SRGB:
+                case VK_FORMAT_R8G8B8A8_SNORM:
+                case VK_FORMAT_R8G8B8A8_SSCALED:
+                case VK_FORMAT_R8G8B8A8_USCALED:
+                    format = fuchsia::hardware::goldfish::ColorBufferFormatType::RGBA;
+                    break;
+                default:
+                    ALOGE("Unsupported format: %d", imageCreateInfo.format);
+                    abort();
+                }
+
                 status = mControlDevice->CreateColorBuffer(
                     std::move(vmo_copy),
                     imageCreateInfo.extent.width,
                     imageCreateInfo.extent.height,
-                    fuchsia::hardware::goldfish::ColorBufferFormatType::BGRA,
+                    format,
                     &status2);
                 if (status != ZX_OK || status2 != ZX_OK) {
                     ALOGE("CreateColorBuffer failed: %d:%d", status, status2);
@@ -2601,7 +2658,7 @@
             zx_status_t status2;
             zx_status_t status = (*collection)->WaitForBuffersAllocated(&status2, &info);
             if (status == ZX_OK && status2 == ZX_OK) {
-                if (index < info.buffer_count) {
+                if (index < info.buffer_count && info.settings.has_image_format_constraints) {
                     vmo = std::move(info.buffers[index].vmo);
                 }
             } else {
@@ -2612,9 +2669,11 @@
                 zx_status_t status2 = ZX_OK;
                 status = mControlDevice->CreateColorBuffer(
                     std::move(vmo),
-                    localCreateInfo.extent.width,
-                    localCreateInfo.extent.height,
-                    fuchsia::hardware::goldfish::ColorBufferFormatType::BGRA,
+                    info.settings.image_format_constraints.min_coded_width,
+                    info.settings.image_format_constraints.min_coded_height,
+                    info.settings.image_format_constraints.pixel_format.type == fuchsia::sysmem::PixelFormatType::R8G8B8A8
+                        ? fuchsia::hardware::goldfish::ColorBufferFormatType::RGBA
+                        : fuchsia::hardware::goldfish::ColorBufferFormatType::BGRA,
                     &status2);
                 if (status != ZX_OK || (status2 != ZX_OK && status2 != ZX_ERR_ALREADY_EXISTS)) {
                     ALOGE("CreateColorBuffer failed: %d:%d", status, status2);