vulkan: Allow drivers to add private gralloc usage flags

Change-Id: Iea33990b3a85a761e27d54bb323d866267c88901
(cherry picked from commit c040fbedde52d632a7ceeef3a9266d35b22ce53f)
diff --git a/vulkan/doc/implementors_guide.adoc b/vulkan/doc/implementors_guide.adoc
index e972b2f..313a5e1 100644
--- a/vulkan/doc/implementors_guide.adoc
+++ b/vulkan/doc/implementors_guide.adoc
@@ -2,7 +2,7 @@
 = Vulkan on Android Implementor's Guide =
 :toc: right
 :numbered:
-:revnumber: 1
+:revnumber: 2
 
 This document is intended for GPU IHVs writing Vulkan drivers for Android, and OEMs integrating them for specific devices. It describes how a Vulkan driver interacts with the system, how GPU-specific tools should be installed, and Android-specific requirements.
 
@@ -51,6 +51,18 @@
 
 The +vk_wsi_swapchin+ and +vk_wsi_device_swapchain+ extensions will primarily be implemented by the platform and live in +libvulkan.so+. The +VkSwapchain+ object and all interaction with +ANativeWindow+ will be handled by the platform and not exposed to drivers. The WSI implementation will rely on a few private interfaces to the driver for this implementation. These will be loaded through the driver's +vkGetDeviceProcAddr+ functions, after passing through any enabled layers.
 
+Implementations may need swapchain buffers to be allocated with implementation-defined private gralloc usage flags. When creating a swapchain, the platform will ask the driver to translate the requested format and image usage flags into gralloc usage flags by calling
+[source,c]
+----
+VkResult VKAPI vkGetSwapchainGrallocUsageANDROID(
+    VkDevice            device,
+    VkFormat            format,
+    VkImageUsageFlags   imageUsage,
+    int*                grallocUsage
+);
+----
+The +format+ and +imageUsage+ parameters are taken from the +VkSwapchainCreateInfoKHR+ structure. The driver should fill +*grallocUsage+ with the gralloc usage flags it requires for that format and usage. These will be combined with the usage flags requested by the swapchain consumer when allocating buffers.
+
 +VkNativeBufferANDROID+ is a +vkCreateImage+ extension structure for creating an image backed by a gralloc buffer. This structure is provided to +vkCreateImage+ in the +VkImageCreateInfo+ structure chain. Calls to +vkCreateImage+ with this structure will happen during the first call to +vkGetSwapChainInfoWSI(.. VK_SWAP_CHAIN_INFO_TYPE_IMAGES_WSI ..)+. The WSI implementation will allocate the number of native buffers requested for the swapchain, then create a +VkImage+ for each one.
 
 [source,c]
diff --git a/vulkan/doc/implementors_guide.html b/vulkan/doc/implementors_guide.html
index 8c2aabb..8186ae3 100644
--- a/vulkan/doc/implementors_guide.html
+++ b/vulkan/doc/implementors_guide.html
@@ -795,9 +795,22 @@
 <h2 id="_window_system_integration">2. Window System Integration</h2>
 <div class="sectionbody">
 <div class="paragraph"><p>The <span class="monospaced">vk_wsi_swapchin</span> and <span class="monospaced">vk_wsi_device_swapchain</span> extensions will primarily be implemented by the platform and live in <span class="monospaced">libvulkan.so</span>. The <span class="monospaced">VkSwapchain</span> object and all interaction with <span class="monospaced">ANativeWindow</span> will be handled by the platform and not exposed to drivers. The WSI implementation will rely on a few private interfaces to the driver for this implementation. These will be loaded through the driver&#8217;s <span class="monospaced">vkGetDeviceProcAddr</span> functions, after passing through any enabled layers.</p></div>
+<div class="paragraph"><p>Implementations may need swapchain buffers to be allocated with implementation-defined private gralloc usage flags. When creating a swapchain, the platform will ask the driver to translate the requested format and image usage flags into gralloc usage flags by calling</p></div>
+<div class="listingblock">
+<div class="content"><!-- Generator: GNU source-highlight 3.1.6
+by Lorenzo Bettini
+http://www.lorenzobettini.it
+http://www.gnu.org/software/src-highlite -->
+<pre><tt>VkResult <span style="color: #008080">VKAPI</span> <span style="font-weight: bold"><span style="color: #000000">vkGetSwapchainGrallocUsageANDROID</span></span><span style="color: #990000">(</span>
+    <span style="color: #008080">VkDevice</span>            device<span style="color: #990000">,</span>
+    <span style="color: #008080">VkFormat</span>            format<span style="color: #990000">,</span>
+    <span style="color: #008080">VkImageUsageFlags</span>   imageUsage<span style="color: #990000">,</span>
+    <span style="color: #009900">int</span><span style="color: #990000">*</span>                grallocUsage
+<span style="color: #990000">);</span></tt></pre></div></div>
+<div class="paragraph"><p>The <span class="monospaced">format</span> and <span class="monospaced">imageUsage</span> parameters are taken from the <span class="monospaced">VkSwapchainCreateInfoKHR</span> structure. The driver should fill <span class="monospaced">*grallocUsage</span> with the gralloc usage flags it requires for that format and usage. These will be combined with the usage flags requested by the swapchain consumer when allocating buffers.</p></div>
 <div class="paragraph"><p><span class="monospaced">VkNativeBufferANDROID</span> is a <span class="monospaced">vkCreateImage</span> extension structure for creating an image backed by a gralloc buffer. This structure is provided to <span class="monospaced">vkCreateImage</span> in the <span class="monospaced">VkImageCreateInfo</span> structure chain. Calls to <span class="monospaced">vkCreateImage</span> with this structure will happen during the first call to <span class="monospaced">vkGetSwapChainInfoWSI(.. VK_SWAP_CHAIN_INFO_TYPE_IMAGES_WSI ..)</span>. The WSI implementation will allocate the number of native buffers requested for the swapchain, then create a <span class="monospaced">VkImage</span> for each one.</p></div>
 <div class="listingblock">
-<div class="content"><!-- Generator: GNU source-highlight 3.1.8
+<div class="content"><!-- Generator: GNU source-highlight 3.1.6
 by Lorenzo Bettini
 http://www.lorenzobettini.it
 http://www.gnu.org/software/src-highlite -->
@@ -832,7 +845,7 @@
 </div></div>
 <div class="paragraph"><p><span class="monospaced">vkImportNativeFenceANDROID</span> imports an externally-signalled native fence into an existing <span class="monospaced">VkSemaphore</span> object:</p></div>
 <div class="listingblock">
-<div class="content"><!-- Generator: GNU source-highlight 3.1.8
+<div class="content"><!-- Generator: GNU source-highlight 3.1.6
 by Lorenzo Bettini
 http://www.lorenzobettini.it
 http://www.gnu.org/software/src-highlite -->
@@ -845,7 +858,7 @@
 will be in the signalled state when this function returns. The driver takes ownership of the fence fd and is responsible for closing it when the <span class="monospaced">VkSemaphore</span> is destroyed, when a different native fence is imported, or any other condition that replaces the <span class="monospaced">VkSemaphore</span>'s underlying synchronization object. If <span class="monospaced">fenceFd</span> is -1, the <span class="monospaced">VkSemaphore</span> will be considered signalled immediately, but it can still be passed to <span class="monospaced">vkQueueWaitSemaphore</span>.</p></div>
 <div class="paragraph"><p><span class="monospaced">vkQueueSignalNativeFenceANDROID</span> creates a native fence and schedules it to be signalled when prior work on the queue has completed.</p></div>
 <div class="listingblock">
-<div class="content"><!-- Generator: GNU source-highlight 3.1.8
+<div class="content"><!-- Generator: GNU source-highlight 3.1.6
 by Lorenzo Bettini
 http://www.lorenzobettini.it
 http://www.gnu.org/software/src-highlite -->
@@ -899,7 +912,7 @@
 <div id="footer">
 <div id="footer-text">
 Version 1<br>
-Last updated 2015-08-16 23:34:58 PDT
+Last updated 2015-11-04 09:13:11 PST
 </div>
 </div>
 </body>
diff --git a/vulkan/include/vulkan/vk_ext_android_native_buffer.h b/vulkan/include/vulkan/vk_ext_android_native_buffer.h
index a1311f4..f923377 100644
--- a/vulkan/include/vulkan/vk_ext_android_native_buffer.h
+++ b/vulkan/include/vulkan/vk_ext_android_native_buffer.h
@@ -47,18 +47,25 @@
     int                         usage;
 } VkNativeBufferANDROID;
 
+typedef VkResult (VKAPI *PFN_vkGetSwapchainGrallocUsageANDROID)(VkDevice device, VkFormat format, VkImageUsageFlags imageUsage, int* grallocUsage);
 typedef VkResult (VKAPI *PFN_vkImportNativeFenceANDROID)(VkDevice device, VkSemaphore semaphore, int nativeFenceFd);
 typedef VkResult (VKAPI *PFN_vkQueueSignalNativeFenceANDROID)(VkQueue queue, int* pNativeFenceFd);
 
 #ifdef VK_PROTOTYPES
+VkResult VKAPI vkGetSwapchainGrallocUsageANDROID(
+    VkDevice            device,
+    VkFormat            format,
+    VkImageUsageFlags   imageUsage,
+    int*                grallocUsage
+);
 VkResult VKAPI vkImportNativeFenceANDROID(
-    VkDevice        device,
-    VkSemaphore     semaphore,
-    int             nativeFenceFd
+    VkDevice            device,
+    VkSemaphore         semaphore,
+    int                 nativeFenceFd
 );
 VkResult VKAPI vkQueueSignalNativeFenceANDROID(
-    VkQueue         queue,
-    int*            pNativeFenceFd
+    VkQueue             queue,
+    int*                pNativeFenceFd
 );
 #endif
 
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];
 
diff --git a/vulkan/nulldrv/null_driver.cpp b/vulkan/nulldrv/null_driver.cpp
index 4b4d22d..e1678ea 100644
--- a/vulkan/nulldrv/null_driver.cpp
+++ b/vulkan/nulldrv/null_driver.cpp
@@ -235,6 +235,9 @@
     PFN_vkVoidFunction proc = LookupDeviceProcAddr(name);
     if (proc)
         return proc;
+    if (strcmp(name, "vkGetSwapchainGrallocUsageANDROID") == 0)
+        return reinterpret_cast<PFN_vkVoidFunction>(
+            GetSwapchainGrallocUsageANDROID);
     if (strcmp(name, "vkImportNativeFenceANDROID") == 0)
         return reinterpret_cast<PFN_vkVoidFunction>(ImportNativeFenceANDROID);
     if (strcmp(name, "vkQueueSignalNativeFenceANDROID") == 0)
@@ -661,6 +664,15 @@
     return VK_SUCCESS;
 }
 
+VkResult GetSwapchainGrallocUsageANDROID(VkDevice,
+                                         VkFormat,
+                                         VkImageUsageFlags,
+                                         int* grallocUsage) {
+    // The null driver never reads or writes the gralloc buffer
+    *grallocUsage = 0;
+    return VK_SUCCESS;
+}
+
 VkResult ImportNativeFenceANDROID(VkDevice, VkSemaphore, int fence) {
     close(fence);
     return VK_SUCCESS;
diff --git a/vulkan/nulldrv/null_driver.h b/vulkan/nulldrv/null_driver.h
index 28f294d..6cf0afd 100644
--- a/vulkan/nulldrv/null_driver.h
+++ b/vulkan/nulldrv/null_driver.h
@@ -172,6 +172,7 @@
 void CmdEndRenderPass(VkCmdBuffer cmdBuffer);
 void CmdExecuteCommands(VkCmdBuffer cmdBuffer, uint32_t cmdBuffersCount, const VkCmdBuffer* pCmdBuffers);
 
+VkResult GetSwapchainGrallocUsageANDROID(VkDevice device, VkFormat format, VkImageUsageFlags imageUsage, int* grallocUsage);
 VkResult ImportNativeFenceANDROID(VkDevice device, VkSemaphore semaphore, int nativeFenceFd);
 VkResult QueueSignalNativeFenceANDROID(VkQueue queue, int* pNativeFenceFd);
 // clang-format on