vulkan: Allow drivers to add private gralloc usage flags

Change-Id: Iea33990b3a85a761e27d54bb323d866267c88901
(cherry picked from commit c040fbedde52d632a7ceeef3a9266d35b22ce53f)
diff --git a/vulkan/libvulkan/get_proc_addr.cpp b/vulkan/libvulkan/get_proc_addr.cpp
index 8aee40b..c840e5b 100644
--- a/vulkan/libvulkan/get_proc_addr.cpp
+++ b/vulkan/libvulkan/get_proc_addr.cpp
@@ -1169,6 +1169,13 @@
         ALOGE("missing device proc: %s", "vkCmdExecuteCommands");
         success = false;
     }
+    vtbl.GetSwapchainGrallocUsageANDROID = reinterpret_cast<PFN_vkGetSwapchainGrallocUsageANDROID>(get_proc_addr(device, "vkGetSwapchainGrallocUsageANDROID"));
+    if (UNLIKELY(!vtbl.GetSwapchainGrallocUsageANDROID)) {
+        // TODO(jessehall): temporarily make this optional, until drivers have been updated
+        // ALOGE("missing device proc: %s", "vkGetSwapchainGrallocUsageANDROID");
+        ALOGW("missing device proc: %s", "vkGetSwapchainGrallocUsageANDROID");
+        // success = false;
+    }
     vtbl.ImportNativeFenceANDROID = reinterpret_cast<PFN_vkImportNativeFenceANDROID>(get_proc_addr(device, "vkImportNativeFenceANDROID"));
     if (UNLIKELY(!vtbl.ImportNativeFenceANDROID)) {
         ALOGE("missing device proc: %s", "vkImportNativeFenceANDROID");
diff --git a/vulkan/libvulkan/get_proc_addr.cpp.tmpl b/vulkan/libvulkan/get_proc_addr.cpp.tmpl
index 3faa223..de348e7 100644
--- a/vulkan/libvulkan/get_proc_addr.cpp.tmpl
+++ b/vulkan/libvulkan/get_proc_addr.cpp.tmpl
@@ -256,6 +256,13 @@
         {{end}}
       {{end}}
     {{end}}
+    vtbl.GetSwapchainGrallocUsageANDROID = reinterpret_cast<PFN_vkGetSwapchainGrallocUsageANDROID>(get_proc_addr(device, "vkGetSwapchainGrallocUsageANDROID"));
+    if (UNLIKELY(!vtbl.GetSwapchainGrallocUsageANDROID)) {
+        // TODO(jessehall): temporarily make this optional, until drivers have been updated
+        // ALOGE("missing device proc: %s", "vkGetSwapchainGrallocUsageANDROID");
+        ALOGW("missing device proc: %s", "vkGetSwapchainGrallocUsageANDROID");
+        // success = false;
+    }
     vtbl.ImportNativeFenceANDROID = reinterpret_cast<PFN_vkImportNativeFenceANDROID>(get_proc_addr(device, "vkImportNativeFenceANDROID"));
     if (UNLIKELY(!vtbl.ImportNativeFenceANDROID)) {
         ALOGE("missing device proc: %s", "vkImportNativeFenceANDROID");
diff --git a/vulkan/libvulkan/loader.h b/vulkan/libvulkan/loader.h
index ef3d1f1..74694a8 100644
--- a/vulkan/libvulkan/loader.h
+++ b/vulkan/libvulkan/loader.h
@@ -202,6 +202,7 @@
     PFN_vkQueuePresentKHR QueuePresentKHR;
 
     // Implemented only by drivers, not by layers or the loader
+    PFN_vkGetSwapchainGrallocUsageANDROID GetSwapchainGrallocUsageANDROID;
     PFN_vkImportNativeFenceANDROID ImportNativeFenceANDROID;
     PFN_vkQueueSignalNativeFenceANDROID QueueSignalNativeFenceANDROID;
 };
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index 2f4c82e..6d9f6c8 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -306,6 +306,8 @@
     // -- Configure the native window --
     // Failure paths from here on need to disconnect the window.
 
+    const DeviceVtbl& driver_vtbl = GetDriverVtbl(device);
+
     std::shared_ptr<ANativeWindow> window = InitSharedPtr(
         device, static_cast<ANativeWindow*>(
                     reinterpret_cast<const VkSurfaceDescriptionWindowKHR*>(
@@ -368,8 +370,28 @@
         return VK_ERROR_INITIALIZATION_FAILED;
     }
 
-    // TODO(jessehall): Do we need to call modify native_window_set_usage()
-    // based on create_info->imageUsageFlags?
+    int gralloc_usage = 0;
+    // TODO(jessehall): Remove conditional once all drivers have been updated
+    if (driver_vtbl.GetSwapchainGrallocUsageANDROID) {
+        result = driver_vtbl.GetSwapchainGrallocUsageANDROID(
+            device, create_info->imageFormat, create_info->imageUsageFlags,
+            &gralloc_usage);
+        if (result != VK_SUCCESS) {
+            ALOGE("vkGetSwapchainGrallocUsageANDROID failed: %d", result);
+            native_window_api_disconnect(window.get(), NATIVE_WINDOW_API_EGL);
+            return VK_ERROR_INITIALIZATION_FAILED;
+        }
+    } else {
+        gralloc_usage = GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE;
+    }
+    err = native_window_set_usage(window.get(), gralloc_usage);
+    if (err != 0) {
+        // TODO(jessehall): Improve error reporting. Can we enumerate possible
+        // errors and translate them to valid Vulkan result codes?
+        ALOGE("native_window_set_usage failed: %s (%d)", strerror(-err), err);
+        native_window_api_disconnect(window.get(), NATIVE_WINDOW_API_EGL);
+        return VK_ERROR_INITIALIZATION_FAILED;
+    }
 
     // -- Allocate our Swapchain object --
     // After this point, we must deallocate the swapchain on error.
@@ -410,7 +432,6 @@
         .pQueueFamilyIndices = create_info->pQueueFamilyIndices,
     };
 
-    const DeviceVtbl& driver_vtbl = GetDriverVtbl(device);
     for (uint32_t i = 0; i < num_images; i++) {
         Swapchain::Image& img = swapchain->images[i];