<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">I made some fairly straightforward comments.  with that, and the squash you sent, 1-6 and 8-10 are</div><div class="gmail_quote"><br></div><div class="gmail_quote">Reviewed-by: Jason Ekstrand <<a href="mailto:jason@jlekstrand.net">jason@jlekstrand.net</a>></div><div class="gmail_quote"><br></div><div class="gmail_quote">I'd like to see the respin of patch 7 but I fully expect to give it my R-B almost immediately.</div><div class="gmail_quote"><br></div><div class="gmail_quote">--Jason<br></div><div class="gmail_quote"><br></div><div class="gmail_quote">On Mon, Oct 16, 2017 at 11:55 AM, Chad Versace <span dir="ltr"><<a href="mailto:chadversary@chromium.org" target="_blank">chadversary@chromium.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">This implementation is correct (afaict), but takes two shortcuts<br>
regarding the import/export of Android sync fds.<br>
<br>
  Shortcut 1. When Android calls vkAcquireImageANDROID to import a sync<br>
  fd into a VkSemaphore or VkFence, the driver instead simply blocks on<br>
  the sync fd, then puts the VkSemaphore or VkFence into the signalled<br>
  state. Thanks to implicit sync, this produces correct behavior (with<br>
  extra latency overhead, perhaps) despite its ugliness.<br>
<br>
  Shortcut 2. When Android calls vkQueueSignalReleaseImageANDRO<wbr>ID to export<br>
  a collection of wait semaphores as a sync fd, the driver instead<br>
  submits the semaphores to the queue, then returns sync fd -1, which<br>
  informs the caller that no additional synchronization is needed.<br>
  Again, thanks to implicit sync, this produces correct behavior (with<br>
  extra batch submission overhead) despite its ugliness.<br>
<br>
I chose to take the shortcuts instead of properly importing/exporting<br>
the sync fds for two reasons:<br>
<br>
  Reason 1. I've already tested this patch with dEQP and with demos<br>
  apps. It works. I wanted to get the tested patches into the tree now,<br>
  and polish the implementation afterwards.<br>
<br>
  Reason 2. I want to run this on a 3.18 kernel (gasp!). In 3.18, i915<br>
  supports neither Android's sync_fence, nor upstream's sync_file, nor<br>
  drm_syncobj. Again, I tested these patches on Android with a 3.18<br>
  kernel and they work.<br>
<br>
I plan to quickly follow-up with patches that remove the shortcuts and<br>
properly import/export the sync fds.<br>
<br>
Non-Testing<br>
===========<br>
I did not test at all using the Android.mk buildsystem. I probably<br>
broke it. Please test and review that.<br>
<br>
Testing<br>
=======<br>
I tested with 64-bit ARC++ on a Skylake Chromebook and a 3.18 kernel.<br>
The following pass (as of patchset v9):<br>
<br>
  - a little spinning cube demo APK<br>
  - several Sascha demos<br>
  - dEQP-VK.info.*<br>
  - dEQP-VK.api.wsi.android.*<br>
      (except dEQP-VK.api.wsi.android.swapch<wbr>ain.*.image_usage, because<br>
      dEQP wants to create swapchains with VK_IMAGE_USAGE_STORAGE_BIT)<br>
  - dEQP-VK.api.smoke.*<br>
  - dEQP-VK.api.info.instance.*<br>
  - dEQP-VK.api.info.device.*<br>
<br>
v2:<br>
  - Reject VkNativeBufferANDROID if the dma-buf's size is too small for<br>
    the VkImage.<br>
  - Stop abusing VkNativeBufferANDROID by passing it to vkAllocateMemory<br>
    during vkCreateImage. Instead, directly import its dma-buf during<br>
    vkCreateImage with anv_bo_cache_import(). [for jekstrand]<br>
  - Rebase onto Tapani's VK_EXT_debug_report changes.<br>
  - Drop `CPPFLAGS += $(top_srcdir)/include/android`<wbr>. The dir does not<br>
    exist.<br>
<br>
v3:<br>
  - Delete duplicate #include "anv_private.h". [per Tapani]<br>
  - Try to fix the Android-IA build in <a href="http://Android.vulkan.mk" rel="noreferrer" target="_blank">Android.vulkan.mk</a> by following<br>
    Tapani's example.<br>
<br>
v4:<br>
  - Unset EXEC_OBJECT_ASYNC and set EXEC_OBJECT_WRITE on the imported<br>
    gralloc buffer, just as we do for all other winsys buffers in<br>
    anv_wsi.c. [found by Tapani]<br>
<br>
v5:<br>
  - Really fix the Android-IA build by ensuring that <a href="http://Android.vulkan.mk" rel="noreferrer" target="_blank">Android.vulkan.mk</a><br>
    uses Mesa' vulkan.h and not Android's.  Insert -I$(MESA_TOP)/include<br>
    before -Iframeworks/native/vulkan/inc<wbr>lude. [for Tapani]<br>
  - In vkAcquireImageANDROID, submit signal operations to the<br>
    VkSemaphore and VkFence. [for zhou]<br>
<br>
v6:<br>
  - Drop copy-paste duplication in vkGetSwapchainGrallocUsageANDR<wbr>OID().<br>
    [found by zhou]<br>
  - Improve comments in vkGetSwapchainGrallocUsageANDR<wbr>OID().<br>
<br>
v7:<br>
  - Fix vkGetSwapchainGrallocUsageANDR<wbr>OID() to inspect its<br>
    VkImageUsageFlags parameter. [for tfiga]<br>
  - This fix regresses dEQP-VK.api.wsi.android.swapch<wbr>ain.*.image_usage<br>
    because dEQP wants to create swapchains with<br>
    VK_IMAGE_USAGE_STORAGE_BIT.<br>
<br>
v8:<br>
  - Drop unneeded goto in vkAcquireImageANDROID. [for tfiga]<br>
<br>
v8.1: (minor changes)<br>
  - Drop errant hunks added by rerere in anv_device.c.<br>
  - Drop explicit mention of VK_ANDROID_native_buffer in<br>
    anv_entrypoints_gen.py. [for jekstrand]<br>
<br>
v9:<br>
  - Isolate as much Android code as possible, moving it from anv_image.c<br>
    to anv_android.c. Connect the files with anv_image_from_gralloc().<br>
    Remove VkNativeBufferANDROID params from all anv_image.c<br>
    funcs. [for krh]<br>
  - Replace some intel_loge() with vk_errorf() in anv_android.c.<br>
  - Use © in copyright line. [for krh]<br>
<br>
Reviewed-by: Tapani Pälli <<a href="mailto:tapani.palli@intel.com" target="_blank">tapani.palli@intel.com</a>> (v5)<br>
Cc: Jason Ekstrand <<a href="mailto:jason@jlekstrand.net" target="_blank">jason@jlekstrand.net</a>><br>
Cc: zhoucm1 <<a href="mailto:david1.zhou@amd.com" target="_blank">david1.zhou@amd.com</a>><br>
Cc: Tomasz Figa <<a href="mailto:tfiga@chromium.org" target="_blank">tfiga@chromium.org</a>><br>
Cc: Kristian H. Kristensen <<a href="mailto:hoegsberg@google.com" target="_blank">hoegsberg@google.com</a>><br>
---<br>
 src/intel/<a href="http://Android.vulkan.mk" rel="noreferrer" target="_blank">Android.vulkan.mk</a>             |   7 +-<br>
 src/intel/Makefile.sources              |   3 +<br>
 src/intel/<a href="http://Makefile.vulkan.am" rel="noreferrer" target="_blank">Makefile.vulkan.am</a>            |   2 +<br>
 src/intel/vulkan/anv_android.<wbr>c          | 416 ++++++++++++++++++++++++++++++<wbr>++<br>
 src/intel/vulkan/anv_entrypoi<wbr>nts_gen.py |   4 +-<br>
 src/intel/vulkan/anv_extensio<wbr>ns.py      |   1 +<br>
 src/intel/vulkan/anv_image.c            |  20 +-<br>
 src/intel/vulkan/anv_private.<wbr>h          |  12 +<br>
 8 files changed, 459 insertions(+), 6 deletions(-)<br>
 create mode 100644 src/intel/vulkan/anv_android.c<br>
<br>
diff --git a/src/intel/<a href="http://Android.vulkan.mk" rel="noreferrer" target="_blank">Android.vulkan.mk</a> b/src/intel/<a href="http://Android.vulkan.mk" rel="noreferrer" target="_blank">Android.vulkan.mk</a><br>
index ee98e30c35..b9a0446f72 100644<br>
--- a/src/intel/<a href="http://Android.vulkan.mk" rel="noreferrer" target="_blank">Android.vulkan.mk</a><br>
+++ b/src/intel/<a href="http://Android.vulkan.mk" rel="noreferrer" target="_blank">Android.vulkan.mk</a><br>
@@ -28,6 +28,7 @@ VK_ENTRYPOINTS_SCRIPT := $(MESA_PYTHON2) $(LOCAL_PATH)/vulkan/anv_entry<wbr>points_ge<br>
 VK_EXTENSIONS_SCRIPT := $(MESA_PYTHON2) $(LOCAL_PATH)/vulkan/anv_exten<wbr>sions.py<br>
<br>
 VULKAN_COMMON_INCLUDES := \<br>
+       $(MESA_TOP)/include \<br>
        $(MESA_TOP)/src/mapi \<br>
        $(MESA_TOP)/src/gallium/auxili<wbr>ary \<br>
        $(MESA_TOP)/src/gallium/includ<wbr>e \<br>
@@ -36,7 +37,8 @@ VULKAN_COMMON_INCLUDES := \<br>
        $(MESA_TOP)/src/vulkan/util \<br>
        $(MESA_TOP)/src/intel \<br>
        $(MESA_TOP)/include/drm-uapi \<br>
-       $(MESA_TOP)/src/intel/vulkan<br>
+       $(MESA_TOP)/src/intel/vulkan \<br>
+       frameworks/native/vulkan/incl<wbr>ude<br>
<br>
 # libmesa_anv_entrypoints with header and dummy.c<br>
 #<br>
@@ -243,7 +245,8 @@ LOCAL_MODULE_CLASS := SHARED_LIBRARIES<br>
 LOCAL_LDFLAGS += -Wl,--build-id=sha1<br>
<br>
 LOCAL_SRC_FILES := \<br>
-       $(VULKAN_GEM_FILES)<br>
+       $(VULKAN_GEM_FILES) \<br>
+       $(VULKAN_ANDROID_FILES)<br>
<br>
 LOCAL_C_INCLUDES := \<br>
        $(VULKAN_COMMON_INCLUDES) \<br>
diff --git a/src/intel/Makefile.sources b/src/intel/Makefile.sources<br>
index da018dcc6a..5a09e6d916 100644<br>
--- a/src/intel/Makefile.sources<br>
+++ b/src/intel/Makefile.sources<br>
@@ -231,6 +231,9 @@ VULKAN_FILES := \<br>
        vulkan/anv_wsi.c \<br>
        vulkan/vk_format_info.h<br>
<br>
+VULKAN_ANDROID_FILES := \<br>
+       vulkan/anv_android.c<br>
+<br>
 VULKAN_WSI_WAYLAND_FILES := \<br>
        vulkan/anv_wsi_wayland.c<br>
<br>
diff --git a/src/intel/<a href="http://Makefile.vulkan.am" rel="noreferrer" target="_blank">Makefile.vulkan.am</a> b/src/intel/<a href="http://Makefile.vulkan.am" rel="noreferrer" target="_blank">Makefile.vulkan.am</a><br>
index 0f488fc9f6..811faab556 100644<br>
--- a/src/intel/<a href="http://Makefile.vulkan.am" rel="noreferrer" target="_blank">Makefile.vulkan.am</a><br>
+++ b/src/intel/<a href="http://Makefile.vulkan.am" rel="noreferrer" target="_blank">Makefile.vulkan.am</a><br>
@@ -147,8 +147,10 @@ VULKAN_LIB_DEPS = \<br>
        -lm<br>
<br>
 if HAVE_PLATFORM_ANDROID<br>
+VULKAN_CPPFLAGS += $(ANDROID_CPPFLAGS)<br>
 VULKAN_CFLAGS += $(ANDROID_CFLAGS)<br>
 VULKAN_LIB_DEPS += $(ANDROID_LIBS)<br>
+VULKAN_SOURCES += $(VULKAN_ANDROID_FILES)<br>
 endif<br>
<br>
 if HAVE_PLATFORM_X11<br>
diff --git a/src/intel/vulkan/anv_android<wbr>.c b/src/intel/vulkan/anv_android<wbr>.c<br>
new file mode 100644<br>
index 0000000000..73baaf1f54<br>
--- /dev/null<br>
+++ b/src/intel/vulkan/anv_android<wbr>.c<br>
@@ -0,0 +1,416 @@<br>
+/*<br>
+ * Copyright © 2017 Google<br>
+ *<br>
+ * Permission is hereby granted, free of charge, to any person obtaining a<br>
+ * copy of this software and associated documentation files (the "Software"),<br>
+ * to deal in the Software without restriction, including without limitation<br>
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,<br>
+ * and/or sell copies of the Software, and to permit persons to whom the<br>
+ * Software is furnished to do so, subject to the following conditions:<br>
+ *<br>
+ * The above copyright notice and this permission notice (including the next<br>
+ * paragraph) shall be included in all copies or substantial portions of the<br>
+ * Software.<br>
+ *<br>
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR<br>
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,<br>
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL<br>
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER<br>
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING<br>
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS<br>
+ * IN THE SOFTWARE.<br>
+ */<br>
+<br>
+#include <hardware/gralloc.h><br>
+#include <hardware/hardware.h><br>
+#include <hardware/hwvulkan.h><br>
+#include <vulkan/vk_android_native_buff<wbr>er.h><br>
+#include <vulkan/vk_icd.h><br>
+#include <sync/sync.h><br>
+<br>
+#include "anv_private.h"<br>
+<br>
+static int anv_hal_open(const struct hw_module_t* mod, const char* id, struct hw_device_t** dev);<br>
+static int anv_hal_close(struct hw_device_t *dev);<br>
+<br>
+static void UNUSED<br>
+static_asserts(void)<br>
+{<br>
+   STATIC_ASSERT(HWVULKAN_DISPAT<wbr>CH_MAGIC == ICD_LOADER_MAGIC);<br>
+}<br>
+<br>
+PUBLIC struct hwvulkan_module_t HAL_MODULE_INFO_SYM = {<br>
+   .common = {<br>
+      .tag = HARDWARE_MODULE_TAG,<br>
+      .module_api_version = HWVULKAN_MODULE_API_VERSION_0_<wbr>1,<br>
+      .hal_api_version = HARDWARE_MAKE_API_VERSION(1, 0),<br>
+      .id = HWVULKAN_HARDWARE_MODULE_ID,<br>
+      .name = "Intel Vulkan HAL",<br>
+      .author = "Intel",<br>
+      .methods = &(hw_module_methods_t) {<br>
+         .open = anv_hal_open,<br>
+      },<br>
+   },<br>
+};<br>
+<br>
+/* If any bits in test_mask are set, then unset them and return true. */<br>
+static inline bool<br>
+unmask32(uint32_t *inout_mask, uint32_t test_mask)<br>
+{<br>
+   uint32_t orig_mask = *inout_mask;<br>
+   *inout_mask &= ~test_mask;<br>
+   return *inout_mask != orig_mask;<br>
+}<br>
+<br>
+static int<br>
+anv_hal_open(const struct hw_module_t* mod, const char* id,<br>
+             struct hw_device_t** dev)<br>
+{<br>
+   assert(mod == &HAL_MODULE_INFO_SYM.common);<br>
+   assert(strcmp(id, HWVULKAN_DEVICE_0) == 0);<br>
+<br>
+   hwvulkan_device_t *hal_dev = malloc(sizeof(*hal_dev));<br>
+   if (!hal_dev)<br>
+      return -1;<br>
+<br>
+   *hal_dev = (hwvulkan_device_t) {<br>
+      .common = {<br>
+         .tag = HARDWARE_DEVICE_TAG,<br>
+         .version = HWVULKAN_DEVICE_API_VERSION_0_<wbr>1,<br>
+         .module = &HAL_MODULE_INFO_SYM.common,<br>
+         .close = anv_hal_close,<br>
+      },<br>
+     .EnumerateInstanceExtensionPr<wbr>operties = anv_EnumerateInstanceExtension<wbr>Properties,<br>
+     .CreateInstance = anv_CreateInstance,<br>
+     .GetInstanceProcAddr = anv_GetInstanceProcAddr,<br>
+   };<br>
+<br>
+   *dev = &hal_dev->common;<br>
+   return 0;<br>
+}<br>
+<br>
+static int<br>
+anv_hal_close(struct hw_device_t *dev)<br>
+{<br>
+   /* hwvulkan.h claims that hw_device_t::close() is never called. */<br>
+   return -1;<br>
+}<br>
+<br>
+VkResult<br>
+anv_image_from_gralloc(VkDevi<wbr>ce device_h,<br>
+                       const VkImageCreateInfo *base_info,<br>
+                       const VkNativeBufferANDROID *gralloc_info,<br>
+                       const VkAllocationCallbacks *alloc,<br>
+                       VkImage *out_image_h)<br>
+<br>
+{<br>
+   ANV_FROM_HANDLE(anv_device, device, device_h);<br>
+   VkImage image_h = VK_NULL_HANDLE;<br>
+   struct anv_image *image = NULL;<br>
+   struct anv_bo *bo = NULL;<br>
+   VkResult result;<br>
+<br>
+   struct anv_image_create_info anv_info = {<br>
+      .vk_info = base_info,<br>
+      .isl_extra_usage_flags = ISL_SURF_USAGE_DISABLE_AUX_BIT<wbr>,<br>
+   };<br>
+<br>
+   if (gralloc_info->handle->numFds != 1) {<br>
+      return vk_errorf(device->instance, device,<br>
+                       VK_ERROR_INVALID_EXTERNAL_HAN<wbr>DLE_KHR,<br>
+                       "VkNativeBufferANDROID::handl<wbr>e::numFds is %d, "<br>
+                       "expected 1", gralloc_info->handle->numFds);<br>
+   }<br>
+<br>
+   /* Do not close the gralloc handle's dma_buf. The lifetime of the dma_buf<br>
+    * must exceed that of the gralloc handle, and we do not own the gralloc<br>
+    * handle.<br>
+    */<br>
+   int dma_buf = gralloc_info->handle->data[0];<br>
+<br>
+   result = anv_bo_cache_import(device, &device->bo_cache, dma_buf, &bo);<br>
+   if (result != VK_SUCCESS) {<br>
+      return vk_errorf(device->instance, device, result,<br>
+                       "failed to import dma-buf from VkNativeBufferANDROID");<br>
+   }<br>
+<br>
+   int i915_tiling = anv_gem_get_tiling(device, bo->gem_handle);<br>
+   switch (i915_tiling) {<br>
+   case I915_TILING_NONE:<br>
+      anv_info.isl_tiling_flags = ISL_TILING_LINEAR_BIT;<br>
+      break;<br>
+   case I915_TILING_X:<br>
+      anv_info.isl_tiling_flags = ISL_TILING_X_BIT;<br>
+      break;<br>
+   case I915_TILING_Y:<br>
+      anv_info.isl_tiling_flags = ISL_TILING_Y0_BIT;<br></blockquote><div><br></div><div>We have isl_tiling_for_i915_tiling to do this.  You may still want the switch statement for error handling purposes but I'm not a huge fan of repeated code.  How about</div><div><br></div><div>if (i915_tiling < 0) {</div><div>   /* Do the one error */<br></div><div>} else if (i915_tiling > I915_TILING_Y) {</div><div>   /* Do the other error */</div><div>}</div><div>anv_info.isl_tiling_flags = 1u << isl_tiling_from_i915_tiling(<wbr>i915_tiling);</div><div><br></div><div>It's not really less code but it keeps things centralized.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+      break;<br>
+   case -1:<br>
+      result = vk_errorf(device->instance, device,<br>
+                         VK_ERROR_INVALID_EXTERNAL_HAN<wbr>DLE_KHR,<br>
+                         "DRM_IOCTL_I915_GEM_GET_<wbr>TILING failed for "<br>
+                         "VkNativeBufferANDROID");<br>
+      goto fail_tiling;<br>
+   default:<br>
+      result = vk_errorf(device->instance, device,<br>
+                         VK_ERROR_INVALID_EXTERNAL_HAN<wbr>DLE_KHR,<br>
+                         "DRM_IOCTL_I915_GEM_GET_<wbr>TILING returned unknown "<br>
+                         "tiling %d for VkNativeBufferANDROID", i915_tiling);<br>
+      goto fail_tiling;<br>
+   }<br>
+<br>
+   enum isl_format format = anv_get_isl_format(&device->in<wbr>fo,<br>
+                                               base_info->format,<br>
+                                               VK_IMAGE_ASPECT_COLOR_BIT,<br>
+                                               base_info->tiling);<br></blockquote><div><br></div><div>Is base_info->tiling allowed to be anything other than OPTIMAL?  Not that it really matters...<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+   assert(format != ISL_FORMAT_UNSUPPORTED);<br>
+<br>
+   anv_info.stride = gralloc_info->stride *<br>
+                     (isl_format_get_layout(<wbr>format)->bpb / 8);<br>
+<br>
+   result = anv_image_create(device_h, &anv_info, alloc, &image_h);<br>
+   image = anv_image_from_handle(image_h)<wbr>;<br>
+   if (result != VK_SUCCESS)<br>
+      goto fail_create;<br>
+<br>
+   if (bo->size < image->size) {<br>
+      result = vk_errorf(device, device->instance,<br>
+                         VK_ERROR_INVALID_EXTERNAL_HAN<wbr>DLE_KHR,<br>
+                         "dma-buf from VkNativeBufferANDROID is too small for "<br>
+                         "VkImage: %"PRIu64" < %"PRIu64,<br>
+                         bo->size, image->size);<br>
+      goto fail_size;<br>
+   }<br>
+<br>
+   assert(image->n_planes == 1);<br>
+   assert(image->planes[0].bo_of<wbr>fset == 0);<br>
+<br>
+   image->planes[0].bo = bo;<br>
+   image->planes[0].bo_is_owned = true;<br>
+<br>
+   /* We need to set the WRITE flag on window system buffers so that GEM will<br>
+    * know we're writing to them and synchronize uses on other rings (for<br>
+    * example, if the display server uses the blitter ring).<br>
+    *<br>
+    * If this function fails and if the imported bo was resident in the cache,<br>
+    * we should avoid updating the bo's flags. Therefore, we defer updating<br>
+    * the flags until success is certain.<br>
+    *<br>
+    */<br>
+   bo->flags &= ~EXEC_OBJECT_ASYNC;<br>
+   bo->flags |= EXEC_OBJECT_WRITE;<br></blockquote><div><br></div><div>If Android is using sync_file, we shouldn't need this?  Maybe we need it now and can delete it later?  I just read the semaphore code below and answered my own question.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+<br>
+   /* Don't clobber the out-parameter until success is certain. */<br>
+   *out_image_h = image_h;<br>
+<br>
+   return VK_SUCCESS;<br>
+<br>
+ fail_size:<br>
+   anv_DestroyImage(device_h, image_h, alloc);<br>
+ fail_create:<br>
+ fail_tiling:<br>
+   anv_bo_cache_release(device, &device->bo_cache, bo);<br>
+<br>
+   return result;<br>
+}<br>
+<br>
+VkResult anv_GetSwapchainGrallocUsageAN<wbr>DROID(<br>
+    VkDevice            device_h,<br>
+    VkFormat            format,<br>
+    VkImageUsageFlags   imageUsage,<br>
+    int*                grallocUsage)<br>
+{<br>
+   ANV_FROM_HANDLE(anv_device, device, device_h);<br>
+   struct anv_physical_device *phys_dev = &device->instance->physicalDev<wbr>ice;<br>
+   VkPhysicalDevice phys_dev_h = anv_physical_device_to_handle(<wbr>phys_dev);<br>
+   VkResult result;<br>
+<br>
+   *grallocUsage = 0;<br>
+   intel_logd("%s: format=%d, usage=0x%x", __func__, format, imageUsage);<br>
+<br>
+   /* WARNING: Android Nougat's libvulkan.so hardcodes the VkImageUsageFlags<br>
+    * returned to applications via VkSurfaceCapabilitiesKHR::supp<wbr>ortedUsageFlags.<br>
+    * The relevant code in libvulkan/swapchain.cpp contains this fun comment:<br>
+    *<br>
+    *     TODO(jessehall): I think these are right, but haven't thought hard<br>
+    *     about it. Do we need to query the driver for support of any of<br>
+    *     these?<br>
+    *<br>
+    * Any disagreement between this function and the hardcoded<br>
+    * VkSurfaceCapabilitiesKHR:suppo<wbr>rtedUsageFlags causes tests<br>
+    * dEQP-VK.wsi.android.swapchain.<wbr>*.image_usage to fail.<br>
+    */<br>
+<br>
+   const VkPhysicalDeviceImageFormatInf<wbr>o2KHR image_format_info = {<br>
+      .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEV<wbr>ICE_IMAGE_FORMAT_INFO_2_KHR,<br>
+      .format = format,<br>
+      .type = VK_IMAGE_TYPE_2D,<br>
+      .tiling = VK_IMAGE_TILING_OPTIMAL,<br>
+      .usage = imageUsage,<br>
+   };<br>
+<br>
+   VkImageFormatProperties2KHR image_format_props = {<br>
+      .sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT<wbr>_PROPERTIES_2_KHR,<br>
+   };<br>
+<br>
+   /* Check that requested format and usage are supported. */<br>
+   result = anv_GetPhysicalDeviceImageForm<wbr>atProperties2KHR(phys_dev_h,<br>
+               &image_format_info, &image_format_props);<br>
+   if (result != VK_SUCCESS) {<br>
+      return vk_errorf(device->instance, device, result,<br>
+                       "anv_GetPhysicalDeviceImageFo<wbr>rmatProperties2KHR failed "<br>
+                       "inside %s", __func__);<br>
+   }<br>
+<br>
+   /* Reject STORAGE here to avoid complexity elsewhere. */<br>
+   if (imageUsage & VK_IMAGE_USAGE_STORAGE_BIT) {<br>
+      return vk_errorf(device->instance, device, VK_ERROR_FORMAT_NOT_SUPPORTED,<br>
+                       "VK_IMAGE_USAGE_STORAGE_BIT unsupported for gralloc "<br>
+                       "swapchain");<br>
+   }<br>
+<br>
+   if (unmask32(&imageUsage, VK_IMAGE_USAGE_TRANSFER_DST_BI<wbr>T |<br>
+                             VK_IMAGE_USAGE_COLOR_ATTACHME<wbr>NT_BIT))<br>
+      *grallocUsage |= GRALLOC_USAGE_HW_RENDER;<br>
+<br>
+   if (unmask32(&imageUsage, VK_IMAGE_USAGE_TRANSFER_SRC_BI<wbr>T |<br>
+                             VK_IMAGE_USAGE_SAMPLED_BIT |<br>
+                             VK_IMAGE_USAGE_INPUT_ATTACHME<wbr>NT_BIT))<br>
+      *grallocUsage |= GRALLOC_USAGE_HW_TEXTURE;<br>
+<br>
+   /* All VkImageUsageFlags not explicitly checked here are unsupported for<br>
+    * gralloc swapchains.<br>
+    */<br>
+   if (imageUsage != 0) {<br>
+      return vk_errorf(device->instance, device, VK_ERROR_FORMAT_NOT_SUPPORTED,<br>
+                       "unsupported VkImageUsageFlags(0x%x) for gralloc "<br>
+                       "swapchain", imageUsage);<br>
+   }<br>
+<br>
+   /* The below formats support GRALLOC_USAGE_HW_FB (that is, display<br>
+    * scanout). This short list of formats is univserally supported on Intel<br>
+    * but is incomplete.  The full set of supported formats is dependent on<br>
+    * kernel and hardware.<br>
+    *<br>
+    * FINISHME: Advertise all display-supported formats.<br>
+    */<br>
+   if (format == VK_FORMAT_B8G8R8A8_UNORM ||<br>
+       format == VK_FORMAT_B5G6R5_UNORM_PACK16) {<br>
+      *grallocUsage |= GRALLOC_USAGE_HW_FB |<br>
+                       GRALLOC_USAGE_HW_COMPOSER |<br>
+                       GRALLOC_USAGE_EXTERNAL_DISP;<br>
+   }<br>
+<br>
+   if (*grallocUsage == 0)<br>
+      return VK_ERROR_FORMAT_NOT_SUPPORTED;<br>
+<br>
+   return VK_SUCCESS;<br>
+}<br>
+<br>
+VkResult<br>
+anv_AcquireImageANDROID(<br>
+      VkDevice            device_h,<br>
+      VkImage             image_h,<br>
+      int                 nativeFenceFd,<br>
+      VkSemaphore         semaphore_h,<br>
+      VkFence             fence_h)<br>
+{<br>
+   ANV_FROM_HANDLE(anv_device, device, device_h);<br>
+   VkResult result = VK_SUCCESS;<br>
+<br>
+   if (nativeFenceFd != -1) {<br>
+      /* As a simple, firstpass implementation of VK_ANDROID_native_buffer, we<br>
+       * block on the nativeFenceFd. This may introduce latency and is<br>
+       * definitiely inefficient, yet it's correct.<br>
+       *<br>
+       * FINISHME(chadv): Import the nativeFenceFd into the VkSemaphore and<br>
+       * VkFence.<br>
+       */<br>
+      if (sync_wait(nativeFenceFd, /*timeout*/ -1) < 0) {<br>
+         result = vk_errorf(device->instance, device, VK_ERROR_DEVICE_LOST,<br>
+                            "%s: failed to wait on nativeFenceFd=%d",<br>
+                            __func__, nativeFenceFd);<br>
+      }<br>
+<br>
+      /* From VK_ANDROID_native_buffer's pseudo spec<br>
+       * (<a href="https://source.android.com/devices/graphics/implement-vulkan" rel="noreferrer" target="_blank">https://source.android.com/de<wbr>vices/graphics/implement-vulka<wbr>n</a>):<br>
+       *<br>
+       *    The driver takes ownership of the fence fd and is responsible for<br>
+       *    closing it [...] even if vkAcquireImageANDROID fails and returns<br>
+       *    an error.<br>
+       */<br>
+      close(nativeFenceFd);<br>
+<br>
+      if (result != VK_SUCCESS)<br>
+         return result;<br>
+   }<br>
+<br>
+   if (semaphore_h || fence_h) {<br>
+      /* Thanks to implicit sync, the image is ready for GPU access.  But we<br>
+       * must still put the semaphore into the "submit" state; otherwise the<br>
+       * client may get unexpected behavior if the client later uses it as<br>
+       * a wait semaphore.<br>
+       *<br>
+       * Because we blocked above on the nativeFenceFd, the image is also<br>
+       * ready for foreign-device access (including CPU access). But we must<br>
+       * still signal the fence; otherwise the client may get unexpected<br>
+       * behavior if the client later waits on it.<br>
+       *<br>
+       * For some values of anv_semaphore_type, we must submit the semaphore<br>
+       * to execbuf in order to signal it.  Likewise for anv_fence_type.<br>
+       * Instead of open-coding here the signal operation for each<br>
+       * anv_semaphore_type and anv_fence_type, we piggy-back on<br>
+       * vkQueueSubmit.<br>
+       */<br></blockquote><div><br></div><div>This makes me sad.... Also, it works.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+      const VkSubmitInfo submit = {<br>
+         .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,<br>
+         .waitSemaphoreCount = 0,<br>
+         .commandBufferCount = 0,<br>
+         .signalSemaphoreCount = (semaphore_h ? 1 : 0),<br>
+         .pSignalSemaphores = &semaphore_h,<br>
+      };<br>
+<br>
+      result = anv_QueueSubmit(anv_queue_to_h<wbr>andle(&device->queue), 1,<br>
+                               &submit, fence_h);<br>
+      if (result != VK_SUCCESS) {<br>
+         return vk_errorf(device->instance, device, result,<br>
+                          "anv_QueueSubmit failed inside %s", __func__);<br>
+      }<br>
+   }<br>
+<br>
+   return VK_SUCCESS;<br>
+}<br>
+<br>
+VkResult<br>
+anv_QueueSignalReleaseImageAN<wbr>DROID(<br>
+      VkQueue             queue,<br>
+      uint32_t            waitSemaphoreCount,<br>
+      const VkSemaphore*  pWaitSemaphores,<br>
+      VkImage             image,<br>
+      int*                pNativeFenceFd)<br>
+{<br>
+   VkResult result;<br>
+<br>
+   if (waitSemaphoreCount == 0)<br>
+      goto done;<br>
+<br>
+   result = anv_QueueSubmit(queue, 1,<br>
+      &(VkSubmitInfo) {<br>
+            .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,<br>
+            .waitSemaphoreCount = 1,<br>
+            .pWaitSemaphores = pWaitSemaphores,<br>
+      },<br>
+      (VkFence) VK_NULL_HANDLE);<br>
+   if (result != VK_SUCCESS)<br>
+      return result;<br>
+<br>
+ done:<br>
+   if (pNativeFenceFd) {<br>
+      /* We can rely implicit on sync because above we submitted all<br>
+       * semaphores to the queue.<br>
+       */<br>
+      *pNativeFenceFd = -1;<br>
+   }<br>
+<br>
+   return VK_SUCCESS;<br>
+}<br>
diff --git a/src/intel/vulkan/anv_entrypo<wbr>ints_gen.py b/src/intel/vulkan/anv_entrypo<wbr>ints_gen.py<br>
index bf376a881f..334b6de54b 100644<br>
--- a/src/intel/vulkan/anv_entrypo<wbr>ints_gen.py<br>
+++ b/src/intel/vulkan/anv_entrypo<wbr>ints_gen.py<br>
@@ -270,7 +270,9 @@ def get_entrypoints(doc, entrypoints_to_defines, start_index):<br>
         if extension.attrib['name'] not in supported:<br>
             continue<br>
<br>
-        assert extension.attrib['supported'] == 'vulkan'<br>
+        if extension.attrib['supported'] != 'vulkan':<br>
+            continue<br>
+<br>
         for command in extension.findall('./require/c<wbr>ommand'):<br>
             enabled_commands.add(command.<wbr>attrib['name'])<br>
<br>
diff --git a/src/intel/vulkan/anv_extensi<wbr>ons.py b/src/intel/vulkan/anv_extensi<wbr>ons.py<br>
index a828a668d6..b1e984b8cd 100644<br>
--- a/src/intel/vulkan/anv_extensi<wbr>ons.py<br>
+++ b/src/intel/vulkan/anv_extensi<wbr>ons.py<br>
@@ -50,6 +50,7 @@ class Extension:<br>
 # the those extension strings, then tests dEQP-VK.api.info.instance.exte<wbr>nsions<br>
 # and dEQP-VK.api.info.device fail due to the duplicated strings.<br>
 EXTENSIONS = [<br>
+    Extension('VK_ANDROID_native_b<wbr>uffer',                 5, 'ANDROID'),<br>
     Extension('VK_KHR_bind_memory<wbr>2',                      1, True),<br>
     Extension('VK_KHR_dedicated_a<wbr>llocation',              1, True),<br>
     Extension('VK_KHR_descriptor_<wbr>update_template',        1, True),<br>
diff --git a/src/intel/vulkan/anv_image.c b/src/intel/vulkan/anv_image.c<br>
index b80011e222..cd96bfd0d6 100644<br>
--- a/src/intel/vulkan/anv_image.c<br>
+++ b/src/intel/vulkan/anv_image.c<br>
@@ -40,9 +40,10 @@<br>
 static isl_surf_usage_flags_t<br>
 choose_isl_surf_usage(VkImage<wbr>CreateFlags vk_create_flags,<br>
                       VkImageUsageFlags vk_usage,<br>
+                      isl_surf_usage_flags_t isl_extra_usage,<br>
                       VkImageAspectFlags aspect)<br>
 {<br>
-   isl_surf_usage_flags_t isl_usage = 0;<br>
+   isl_surf_usage_flags_t isl_usage = isl_extra_usage;<br>
<br>
    if (vk_usage & VK_IMAGE_USAGE_SAMPLED_BIT)<br>
       isl_usage |= ISL_SURF_USAGE_TEXTURE_BIT;<br>
@@ -290,6 +291,10 @@ make_surface(const struct anv_device *dev,<br>
       anv_get_format_plane(&dev->in<wbr>fo, image->vk_format, aspect, image->tiling);<br>
    struct anv_surface *anv_surf = &image->planes[plane].surface;<br>
<br>
+   const isl_surf_usage_flags_t usage =<br>
+      choose_isl_surf_usage(vk_info-<wbr>>flags, image->usage,<br>
+                            anv_info->isl_extra_usage_flag<wbr>s, aspect);<br>
+<br>
    /* If an image is created as BLOCK_TEXEL_VIEW_COMPATIBLE, then we need to<br>
     * fall back to linear on Broadwell and earlier because we aren't<br>
     * guaranteed that we can handle offsets correctly.  On Sky Lake, the<br>
@@ -316,7 +321,7 @@ make_surface(const struct anv_device *dev,<br>
       .samples = vk_info->samples,<br>
       .min_alignment = 0,<br>
       .row_pitch = anv_info->stride,<br>
-      .usage = choose_isl_surf_usage(vk_info-<wbr>>flags, image->usage, aspect),<br>
+      .usage = usage,<br>
       .tiling_flags = tiling_flags);<br>
<br>
    /* isl_surf_init() will fail only if provided invalid input. Invalid input<br>
@@ -347,7 +352,7 @@ make_surface(const struct anv_device *dev,<br>
          .samples = vk_info->samples,<br>
          .min_alignment = 0,<br>
          .row_pitch = anv_info->stride,<br>
-         .usage = choose_isl_surf_usage(image->u<wbr>sage, image->usage, aspect),<br>
+         .usage = usage,<br>
          .tiling_flags = ISL_TILING_ANY_MASK);<br>
<br>
       /* isl_surf_init() will fail only if provided invalid input. Invalid input<br>
@@ -547,6 +552,15 @@ anv_CreateImage(VkDevice device,<br>
                 const VkAllocationCallbacks *pAllocator,<br>
                 VkImage *pImage)<br>
 {<br>
+#ifdef ANDROID<br>
+   const VkNativeBufferANDROID *gralloc_info =<br>
+      vk_find_struct_const(pCreateIn<wbr>fo->pNext, NATIVE_BUFFER_ANDROID);<br>
+<br>
+   if (gralloc_info)<br>
+      return anv_image_from_gralloc(device, pCreateInfo, gralloc_info,<br>
+                                    pAllocator, pImage);<br>
+#endif<br>
+<br>
    return anv_image_create(device,<br>
       &(struct anv_image_create_info) {<br>
          .vk_info = pCreateInfo,<br>
diff --git a/src/intel/vulkan/anv_private<wbr>.h b/src/intel/vulkan/anv_private<wbr>.h<br>
index b51d110514..36c7220679 100644<br>
--- a/src/intel/vulkan/anv_private<wbr>.h<br>
+++ b/src/intel/vulkan/anv_private<wbr>.h<br>
@@ -69,6 +69,7 @@ struct gen_l3_config;<br>
 #include <vulkan/vulkan.h><br>
 #include <vulkan/vulkan_intel.h><br>
 #include <vulkan/vk_icd.h><br>
+#include <vulkan/vk_android_native_buff<wbr>er.h><br>
<br>
 #include "anv_entrypoints.h"<br>
 #include "isl/isl.h"<br>
@@ -2632,6 +2633,9 @@ struct anv_image_create_info {<br>
    /** An opt-in bitmask which filters an ISL-mapping of the Vulkan tiling. */<br>
    isl_tiling_flags_t isl_tiling_flags;<br>
<br>
+   /** These flags will be added to any derived from VkImageCreateInfo. */<br>
+   isl_surf_usage_flags_t isl_extra_usage_flags;<br>
+<br>
    uint32_t stride;<br>
 };<br>
<br>
@@ -2640,6 +2644,14 @@ VkResult anv_image_create(VkDevice _device,<br>
                           const VkAllocationCallbacks* alloc,<br>
                           VkImage *pImage);<br>
<br>
+#ifdef ANDROID<br>
+VkResult anv_image_from_gralloc(VkDevic<wbr>e device_h,<br>
+                                const VkImageCreateInfo *base_info,<br>
+                                const VkNativeBufferANDROID *gralloc_info,<br>
+                                const VkAllocationCallbacks *alloc,<br>
+                                VkImage *pImage);<br>
+#endif<br>
+<br>
 const struct anv_surface *<br>
 anv_image_get_surface_for_asp<wbr>ect_mask(const struct anv_image *image,<br>
                                       VkImageAspectFlags aspect_mask);<br>
<span class="m_-8188284107046820196HOEnZb"><font color="#888888">--<br>
2.13.0<br>
<br>
</font></span></blockquote></div><br></div></div>