Merge "EGL/ANGLE/Vulkan: respect EGL resolved RGBX format" into main
diff --git a/opengl/libs/EGL/egl_platform_entries.cpp b/opengl/libs/EGL/egl_platform_entries.cpp
index a6af713..6e4d513 100644
--- a/opengl/libs/EGL/egl_platform_entries.cpp
+++ b/opengl/libs/EGL/egl_platform_entries.cpp
@@ -711,24 +711,25 @@
     }
     attrib_list = strippedAttribList.data();
 
-    if (!cnx->angleLoaded) {
-        int err = native_window_set_buffers_format(window, static_cast<int>(format));
-        if (err != 0) {
-            ALOGE("error setting native window pixel format: %s (%d)", strerror(-err), err);
+    int err = native_window_set_buffers_format(window, static_cast<int>(format));
+    if (err != 0) {
+        ALOGE("error setting native window pixel format: %s (%d)", strerror(-err), err);
+        if (!cnx->angleLoaded) {
             native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
-            return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
         }
+        return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
+    }
 
-        android_dataspace dataSpace = dataSpaceFromEGLColorSpace(colorSpace, format);
-        // Set dataSpace even if it could be HAL_DATASPACE_UNKNOWN.
-        // HAL_DATASPACE_UNKNOWN is the default value, but it may have changed
-        // at this point.
-        err = native_window_set_buffers_data_space(window, dataSpace);
-        if (err != 0) {
-            ALOGE("error setting native window pixel dataSpace: %s (%d)", strerror(-err), err);
+    android_dataspace dataSpace = dataSpaceFromEGLColorSpace(colorSpace, format);
+    // Set dataSpace even if it could be HAL_DATASPACE_UNKNOWN. HAL_DATASPACE_UNKNOWN is the default
+    // value, but it may have changed at this point.
+    err = native_window_set_buffers_data_space(window, dataSpace);
+    if (err != 0) {
+        ALOGE("error setting native window pixel dataSpace: %s (%d)", strerror(-err), err);
+        if (!cnx->angleLoaded) {
             native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
-            return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
         }
+        return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
     }
 
     // the EGL spec requires that a new EGLSurface default to swap interval
@@ -743,8 +744,8 @@
     }
 
     // EGLSurface creation failed
+    native_window_set_buffers_format(window, 0);
     if (!cnx->angleLoaded) {
-        native_window_set_buffers_format(window, 0);
         native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
     }
     return EGL_NO_SURFACE;
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index 74d3d9d..3eeb6b1 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -250,6 +250,7 @@
     android::sp<ANativeWindow> window;
     VkSwapchainKHR swapchain_handle;
     uint64_t consumer_usage;
+    int default_format;
 
     // Indicate whether this surface has been used by a swapchain, no matter the
     // swapchain is still current or has been destroyed.
@@ -526,12 +527,15 @@
     *count = num_copied;
 }
 
-PixelFormat GetNativePixelFormat(VkFormat format) {
+PixelFormat GetNativePixelFormat(VkFormat format,
+                                 VkCompositeAlphaFlagBitsKHR alpha) {
     PixelFormat native_format = PixelFormat::RGBA_8888;
     switch (format) {
         case VK_FORMAT_R8G8B8A8_UNORM:
         case VK_FORMAT_R8G8B8A8_SRGB:
-            native_format = PixelFormat::RGBA_8888;
+            native_format = alpha == VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR
+                                ? PixelFormat::RGBX_8888
+                                : PixelFormat::RGBA_8888;
             break;
         case VK_FORMAT_R5G6B5_UNORM_PACK16:
             native_format = PixelFormat::RGB_565;
@@ -621,11 +625,12 @@
         return VK_ERROR_OUT_OF_HOST_MEMORY;
     Surface* surface = new (mem) Surface;
 
-    surface->window = pCreateInfo->window;
+    ANativeWindow* window = pCreateInfo->window;
+    surface->window = window;
     surface->swapchain_handle = VK_NULL_HANDLE;
     surface->used_by_swapchain = false;
-    int err = native_window_get_consumer_usage(surface->window.get(),
-                                               &surface->consumer_usage);
+    int err =
+        native_window_get_consumer_usage(window, &surface->consumer_usage);
     if (err != android::OK) {
         ALOGE("native_window_get_consumer_usage() failed: %s (%d)",
               strerror(-err), err);
@@ -634,8 +639,16 @@
         return VK_ERROR_SURFACE_LOST_KHR;
     }
 
-    err =
-        native_window_api_connect(surface->window.get(), NATIVE_WINDOW_API_EGL);
+    err = window->query(window, NATIVE_WINDOW_FORMAT, &surface->default_format);
+    if (err != android::OK) {
+        ALOGE("NATIVE_WINDOW_FORMAT query failed: %s (%d)", strerror(-err),
+              err);
+        surface->~Surface();
+        allocator->pfnFree(allocator->pUserData, surface);
+        return VK_ERROR_SURFACE_LOST_KHR;
+    }
+
+    err = native_window_api_connect(window, NATIVE_WINDOW_API_EGL);
     if (err != android::OK) {
         ALOGE("native_window_api_connect() failed: %s (%d)", strerror(-err),
               err);
@@ -901,7 +914,7 @@
     VkSurfaceCapabilities2KHR* pSurfaceCapabilities) {
     ATRACE_CALL();
 
-    auto surface = pSurfaceInfo->surface;
+    auto surface_handle = pSurfaceInfo->surface;
     auto capabilities = &pSurfaceCapabilities->surfaceCapabilities;
 
     VkSurfacePresentModeEXT const *pPresentMode = nullptr;
@@ -922,7 +935,9 @@
     int transform_hint;
     int max_buffer_count;
     int min_undequeued_buffers;
-    if (surface == VK_NULL_HANDLE) {
+    VkCompositeAlphaFlagsKHR composite_alpha =
+        VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR;
+    if (surface_handle == VK_NULL_HANDLE) {
         const InstanceData& instance_data = GetData(physicalDevice);
         ProcHook::Extension surfaceless = ProcHook::GOOGLE_surfaceless_query;
         bool surfaceless_enabled =
@@ -943,7 +958,8 @@
         capabilities->minImageCount = 0xFFFFFFFF;
         capabilities->maxImageCount = 0xFFFFFFFF;
     } else {
-        ANativeWindow* window = SurfaceFromHandle(surface)->window.get();
+        Surface& surface = *SurfaceFromHandle(surface_handle);
+        ANativeWindow* window = surface.window.get();
 
         err = window->query(window, NATIVE_WINDOW_DEFAULT_WIDTH, &width);
         if (err != android::OK) {
@@ -1018,6 +1034,17 @@
                     min_undequeued_buffers + default_additional_buffers);
             capabilities->maxImageCount = static_cast<uint32_t>(max_buffer_count);
         }
+
+        // The surface default format can be either of below:
+        // - consumer side default format
+        // - platform EGL resolved format and we get here via ANGLE
+        //
+        // For any of above, advertise OPAQUE bit so that later swapchain
+        // creation can resolve VK_FORMAT_R8G8B8A8_* to RGBX_8888 only if the
+        // client also requests OPAQUE bit for compositeAlpha.
+        if (surface.default_format == (int)PixelFormat::RGBX_8888) {
+            composite_alpha |= VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
+        }
     }
 
     capabilities->currentExtent =
@@ -1044,9 +1071,7 @@
     capabilities->currentTransform =
         TranslateNativeToVulkanTransform(transform_hint);
 
-    // On Android, window composition is a WindowManager property, not something
-    // associated with the bufferqueue. It can't be changed from here.
-    capabilities->supportedCompositeAlpha = VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR;
+    capabilities->supportedCompositeAlpha = composite_alpha;
 
     capabilities->supportedUsageFlags =
         VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
@@ -1645,20 +1670,21 @@
 
     ALOGV("vkCreateSwapchainKHR: surface=0x%" PRIx64
           " minImageCount=%u imageFormat=%u imageColorSpace=%u"
-          " imageExtent=%ux%u imageUsage=%#x preTransform=%u presentMode=%u"
-          " oldSwapchain=0x%" PRIx64,
+          " imageExtent=%ux%u imageUsage=%#x preTransform=%u compositeAlpha=%u"
+          " presentMode=%u oldSwapchain=0x%" PRIx64,
           reinterpret_cast<uint64_t>(create_info->surface),
           create_info->minImageCount, create_info->imageFormat,
           create_info->imageColorSpace, create_info->imageExtent.width,
           create_info->imageExtent.height, create_info->imageUsage,
-          create_info->preTransform, create_info->presentMode,
+          create_info->preTransform, create_info->compositeAlpha,
+          create_info->presentMode,
           reinterpret_cast<uint64_t>(create_info->oldSwapchain));
 
     if (!allocator)
         allocator = &GetData(device).allocator;
 
-    PixelFormat native_pixel_format =
-        GetNativePixelFormat(create_info->imageFormat);
+    PixelFormat native_pixel_format = GetNativePixelFormat(
+        create_info->imageFormat, create_info->compositeAlpha);
     DataSpace native_dataspace = GetNativeDataspace(
         create_info->imageColorSpace, create_info->imageFormat);
     if (native_dataspace == DataSpace::UNKNOWN) {