<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Sat, Sep 2, 2017 at 1:17 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:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);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></blockquote><div><br></div><div>Let's see how review goes but my Saturday morning gut reaction is that 
I'd rather we merge the "correct" version upstream directly and you can 
carry the implicit sync version as a patch in the ChromeOS tree.  I can probably be convinced otherwise but that's my reactioin today.</div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
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:<br>
<br>
  a little spinning cube demo APK<br>
  dEQP-VK.info.*<br>
  dEQP-VK.api.smoke.*<br>
  dEQP-VK.api.info.instance.*<br>
  dEQP-VK.api.info.device.*<br>
  dEQP-VK.api.wsi.android.*<br>
---<br>
 src/intel/Makefile.sources              |   3 +<br>
 src/intel/<a href="http://Makefile.vulkan.am" rel="noreferrer" target="_blank">Makefile.vulkan.am</a>            |   4 +<br>
 src/intel/vulkan/anv_android.c          | 246 ++++++++++++++++++++++++++++++<wbr>++<br>
 src/intel/vulkan/anv_device.c           |  38 ++++-<br>
 src/intel/vulkan/anv_<wbr>entrypoints_gen.py |  10 +-<br>
 src/intel/vulkan/anv_<wbr>extensions.py      |   1 +<br>
 src/intel/vulkan/anv_image.c            | 129 +++++++++++++++--<br>
 src/intel/vulkan/anv_private.h          |   1 +<br>
 8 files changed, 421 insertions(+), 11 deletions(-)<br>
 create mode 100644 src/intel/vulkan/anv_android.c<br>
<br>
diff --git a/src/intel/Makefile.sources b/src/intel/Makefile.sources<br>
index f6a69f65455..e4a371cbe3f 100644<br>
--- a/src/intel/Makefile.sources<br>
+++ b/src/intel/Makefile.sources<br>
@@ -228,6 +228,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 d1b1132ed2e..bc4b12768ad 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,12 @@ VULKAN_LIB_DEPS = \<br>
        -lm<br>
<br>
 if HAVE_PLATFORM_ANDROID<br>
+VULKAN_CPPFLAGS += \<br>
+       -I$(top_srcdir)/include/<wbr>android \<br>
+       $(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_<wbr>android.c b/src/intel/vulkan/anv_<wbr>android.c<br>
new file mode 100644<br>
index 00000000000..24274510cd6<br>
--- /dev/null<br>
+++ b/src/intel/vulkan/anv_<wbr>android.c<br>
@@ -0,0 +1,246 @@<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_<wbr>buffer.h><br>
+#include <vulkan/vk_icd.h><br>
+#include <sync/sync.h><br>
+<br>
+#include "anv_private.h"<br>
+<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_<wbr>DISPATCH_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>
+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 *vkdev = malloc(sizeof(*vkdev));<br>
+   if (!vkdev)<br>
+      return -1;<br>
+<br>
+   *vkdev = (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>
+     .<wbr>EnumerateInstanceExtensionProp<wbr>erties = anv_<wbr>EnumerateInstanceExtensionProp<wbr>erties,<br>
+     .CreateInstance = anv_CreateInstance,<br>
+     .GetInstanceProcAddr = anv_GetInstanceProcAddr,<br>
+   };<br>
+<br>
+   *dev = &vkdev->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 anv_<wbr>GetSwapchainGrallocUsageANDROI<wbr>D(<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-><wbr>physicalDevice;<br>
+   VkPhysicalDevice phys_dev_h = anv_physical_device_to_handle(<wbr>phys_dev);<br>
+   VkFormatProperties props;<br>
+<br>
+   static const VkFormat fb_formats[] = {<br>
+      VK_FORMAT_B8G8R8A8_UNORM,<br>
+      VK_FORMAT_B5G6R5_UNORM_PACK16,<br>
+   };<br>
+<br>
+   *grallocUsage = 0;<br>
+   anv_<wbr>GetPhysicalDeviceFormatPropert<wbr>ies(phys_dev_h, format, &props);<br>
+<br>
+   for (uint32_t i = 0; i < ARRAY_SIZE(fb_formats); ++i) {<br>
+      if (format == fb_formats[i]) {<br>
+         /* TODO(chadv): Query these properties from isl. */<br>
+          *grallocUsage |= GRALLOC_USAGE_HW_FB |<br>
+                           GRALLOC_USAGE_HW_COMPOSER |<br>
+                           GRALLOC_USAGE_EXTERNAL_DISP;<br>
+          break;<br>
+      }<br>
+   }<br>
+<br>
+  if ((props.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_<wbr>IMAGE_BIT))<br>
+     *grallocUsage |= GRALLOC_USAGE_HW_TEXTURE;<br>
+<br>
+  if ((props.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_<wbr>ATTACHMENT_BIT))<br>
+     *grallocUsage |= GRALLOC_USAGE_HW_RENDER;<br>
+<br>
+  if ((props.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_<wbr>IMAGE_BIT))<br>
+     *grallocUsage |= GRALLOC_USAGE_HW_TEXTURE;<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_semaphore, semaphore, semaphore_h);<br>
+   ANV_FROM_HANDLE(anv_fence, fence, fence_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(VK_ERROR_DEVICE_<wbr>LOST,<br>
+                            "%s: failed to wait on nativeFenceFd=%d",<br>
+                            __func__, nativeFenceFd);<br>
+         goto done;<br>
+      }<br>
+   }<br>
+<br>
+   if (semaphore) {<br>
+      /* It's illegal to import into an existing import. */<br>
+      assert(semaphore->temporary.<wbr>type == ANV_SEMAPHORE_TYPE_NONE);<br>
+<br>
+      /* It's also illegal here to import into an in-flight semaphore.<br>
+       * Therefore, thanks to implicit sync, there's nothing to do here<br>
+       * because we have already blocked on the nativeFenceFd.<br>
+       */<br>
+   }<br>
+<br>
+   if (fence) {<br>
+      /* It's illegal to import into an existing import. */<br>
+      assert(fence->temporary.type == ANV_FENCE_TYPE_NONE);<br>
+<br>
+<br>
+      /* We can transition the fence's state from reset to signalled because<br>
+       * we blocked on the sync fd. Since the fence had no waiters, there's no<br>
+       * need to broadcast the state transition.<br>
+       */<br>
+      switch (fence->permanent.type) {<br>
+      case ANV_FENCE_TYPE_NONE:<br>
+         unreachable("anv_fence::<wbr>permanent::type is NONE");<br>
+      case ANV_FENCE_TYPE_BO:<br>
+         /* It's illegal to import into a fence in the non-resting state. */<br>
+         assert(fence-><a href="http://permanent.bo">permanent.bo</a>.<wbr>state == ANV_BO_FENCE_STATE_RESET);<br>
+         fence->permanent.bo.state = ANV_BO_FENCE_STATE_SIGNALED;<br>
+         break;<br>
+      case ANV_FENCE_TYPE_SYNCOBJ:<br>
+         break;<br>
+      }<br>
+   }<br>
+<br>
+ done:<br>
+   if (nativeFenceFd != -1) {<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/<wbr>devices/graphics/implement-<wbr>vulkan</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>
+<br>
+   return result;<br>
+}<br>
+<br>
+VkResult<br>
+anv_<wbr>QueueSignalReleaseImageANDROID<wbr>(<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,<br>
+      1, (VkSubmitInfo[]) {<br>
+         {<br>
+            .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,<br>
+            .waitSemaphoreCount = 1,<br>
+            .pWaitSemaphores = pWaitSemaphores,<br>
+         },<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_device.<wbr>c b/src/intel/vulkan/anv_device.<wbr>c<br>
index 8cc760c3721..d221ba46645 100644<br>
--- a/src/intel/vulkan/anv_device.<wbr>c<br>
+++ b/src/intel/vulkan/anv_device.<wbr>c<br>
@@ -1440,10 +1440,20 @@ VkResult anv_AllocateMemory(<br>
    struct anv_device_memory *mem;<br>
    VkResult result = VK_SUCCESS;<br>
<br>
+   /* VK_ANDROID_native_buffer defines VkNativeBufferANDROID as an extension<br>
+    * of VkImageCreateInfo. We abuse the struct by chaining it to<br>
+    * VkMemoryAllocateInfo in the implementation of vkCreateImage.<br>
+    */<br>
+   const VkNativeBufferANDROID *gralloc_info = NULL;<br>
+#ifdef ANDROID<br>
+   gralloc_info = vk_find_struct_const(<wbr>pAllocateInfo->pNext, NATIVE_BUFFER_ANDROID);<br>
+#endif<br>
+<br>
    assert(pAllocateInfo->sType == VK_STRUCTURE_TYPE_MEMORY_<wbr>ALLOCATE_INFO);<br>
<br>
    /* The Vulkan 1.0.33 spec says "allocationSize must be greater than 0". */<br>
-   assert(pAllocateInfo-><wbr>allocationSize > 0);<br>
+   assert(gralloc_info || pAllocateInfo->allocationSize > 0);<br>
+   assert(!gralloc_info || pAllocateInfo->allocationSize == 0);<br>
<br>
    /* The kernel relocation API has a limitation of a 32-bit delta value<br>
     * applied to the address before it is written which, in spite of it being<br>
@@ -1495,7 +1505,31 @@ VkResult anv_AllocateMemory(<br>
                                    0, &mem->bo);<br>
       if (result != VK_SUCCESS)<br>
          goto fail;<br>
-   } else {<br>
+   }<br>
+#ifdef ANDROID<br>
+   else if (gralloc_info) {<br>
+      if (gralloc_info->handle->numFds != 1) {<br>
+         result = vk_errorf(VK_ERROR_INVALID_<wbr>EXTERNAL_HANDLE_KHR,<br>
+                            "VkNativeBufferANDROID::<wbr>handle::numFds is %d, "<br>
+                            "expected 1", gralloc_info->handle->numFds);<br>
+         goto fail;<br>
+      }<br>
+<br>
+      int dma_buf = gralloc_info->handle->data[0];<br>
+<br>
+      /* Do not close the gralloc handle's dma_buf fd. The lifetime of the<br>
+       * dma_buf fd must exceed that of the gralloc handle, and we do not own<br>
+       * the gralloc handle.<br>
+       */<br>
+      result = anv_bo_cache_import(device, &device->bo_cache, dma_buf, -1,<br>
+                                   ANV_BO_CACHE_IMPORT_NO_CLOSE_<wbr>FD<br>
+                                   | ANV_BO_CACHE_IMPORT_IGNORE_<wbr>SIZE_PARAM,<br>
+                                   &mem->bo);<br>
+      if (result != VK_SUCCESS)<br>
+         goto fail;<br>
+   }<br>
+#endif<br>
+   else {<br>
       result = anv_bo_cache_alloc(device, &device->bo_cache,<br>
                                   pAllocateInfo->allocationSize,<br>
                                   &mem->bo);<br>
diff --git a/src/intel/vulkan/anv_<wbr>entrypoints_gen.py b/src/intel/vulkan/anv_<wbr>entrypoints_gen.py<br>
index 983be09a39b..dcdde31cdd7 100644<br>
--- a/src/intel/vulkan/anv_<wbr>entrypoints_gen.py<br>
+++ b/src/intel/vulkan/anv_<wbr>entrypoints_gen.py<br>
@@ -271,7 +271,15 @@ 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>
+        # Workaround VK_ANDROID_native_buffer. In vk.xml, it's listed as<br>
+        # supported="disabled", but we patch it to supported="vulkan" in our<br>
+        # custom vk_android_native_buffer.xml.<br>
+        assert (extension.attrib['supported'] == 'vulkan' or<br>
+                extension.attrib['name'] == 'VK_ANDROID_native_buffer')<br>
+<br>
+        if extension.attrib['supported'] != 'vulkan':<br>
+            continue<br>
+<br>
         for command in extension.findall('./require/<wbr>command'):<br>
             enabled_commands.add(command.<wbr>attrib['name'])<br>
<br>
diff --git a/src/intel/vulkan/anv_<wbr>extensions.py b/src/intel/vulkan/anv_<wbr>extensions.py<br>
index 6cd0c3692b6..18062359d31 100644<br>
--- a/src/intel/vulkan/anv_<wbr>extensions.py<br>
+++ b/src/intel/vulkan/anv_<wbr>extensions.py<br>
@@ -50,6 +50,7 @@ class Extension:<br>
 # the those extension strings, then tests dEQP-VK.api.info.instance.<wbr>extensions<br>
 # and dEQP-VK.api.info.device fail due to the duplicated strings.<br>
 EXTENSIONS = [<br>
+    Extension('VK_ANDROID_native_<wbr>buffer',                 5, 'ANDROID'),<br>
     Extension('VK_KHR_dedicated_<wbr>allocation',              1, True),<br>
     Extension('VK_KHR_descriptor_<wbr>update_template',        1, True),<br>
     Extension('VK_KHR_external_<wbr>fence',                    1,<br>
diff --git a/src/intel/vulkan/anv_image.c b/src/intel/vulkan/anv_image.c<br>
index 1cc3adae5ee..1b8bb363a17 100644<br>
--- a/src/intel/vulkan/anv_image.c<br>
+++ b/src/intel/vulkan/anv_image.c<br>
@@ -32,6 +32,11 @@<br>
 #include "util/debug.h"<br>
<br>
 #include "vk_format_info.h"<br>
+#include "vk_util.h"<br>
+<br>
+static void<br>
+add_fast_clear_state_buffer(<wbr>struct anv_image *image,<br>
+                            const struct anv_device *device);<br>
<br>
 static void<br>
 add_fast_clear_state_buffer(<wbr>struct anv_image *image,<br>
@@ -111,7 +116,9 @@ get_surface(struct anv_image *image, VkImageAspectFlags aspect)<br>
 }<br>
<br>
 static VkResult<br>
-choose_isl_tiling_flags(const struct anv_image_create_info *anv_info,<br>
+choose_isl_tiling_flags(<wbr>struct anv_device *device,<br>
+                        const struct anv_image_create_info *anv_info,<br>
+                        const VkNativeBufferANDROID *gralloc_info,<br>
                         isl_tiling_flags_t *restrict flags)<br>
 {<br>
    *flags = ISL_TILING_ANY_MASK;<br>
@@ -122,6 +129,41 @@ choose_isl_tiling_flags(const struct anv_image_create_info *anv_info,<br>
    if (anv_info->isl_tiling_flags)<br>
       *flags &= anv_info->isl_tiling_flags;<br>
<br>
+#if defined(ANDROID)<br>
+   if (gralloc_info) {<br>
+      int dma_buf = gralloc_info->handle->data[0];<br>
+<br>
+      uint32_t gem_handle = anv_gem_fd_to_handle(device, dma_buf);<br>
+      if (gem_handle == 0) {<br>
+         return vk_errorf(VK_ERROR_INVALID_<wbr>EXTERNAL_HANDLE_KHR,<br>
+                          "DRM_IOCTL_PRIME_FD_TO_HANDLE failed for "<br>
+                          "VkNativeBufferANDROID");<br>
+      }<br>
+<br>
+      int i915_tiling = anv_gem_get_tiling(device, gem_handle);<br>
+      switch (i915_tiling) {<br>
+      case I915_TILING_NONE:<br>
+         *flags &= ISL_TILING_LINEAR_BIT;<br>
+         break;<br>
+      case I915_TILING_X:<br>
+         *flags &= ISL_TILING_X_BIT;<br>
+         break;<br>
+      case I915_TILING_Y:<br>
+         *flags &= ISL_TILING_Y0_BIT;<br>
+         break;<br>
+      case -1:<br>
+         return vk_errorf(VK_ERROR_INVALID_<wbr>EXTERNAL_HANDLE_KHR,<br>
+                          "DRM_IOCTL_I915_GEM_GET_TILING failed for "<br>
+                          "VkNativeBufferANDROID");<br>
+      default:<br>
+         return vk_errorf(VK_ERROR_INVALID_<wbr>EXTERNAL_HANDLE_KHR,<br>
+                          "DRM_IOCTL_I915_GEM_GET_TILING returned unknown "<br>
+                          "tiling %d for VkNativeBufferANDROID", i915_tiling);<br>
+<br>
+      }<br>
+   }<br>
+#endif<br>
+<br>
    return VK_SUCCESS;<br>
 }<br>
<br>
@@ -245,9 +287,13 @@ try_make_mcs_surface(const struct anv_device *dev,<br>
 static VkResult<br>
 try_make_aux_surface(const struct anv_device *dev,<br>
                      const VkImageCreateInfo *base_info,<br>
+                     const VkNativeBufferANDROID *gralloc_info,<br>
                      VkImageAspectFlags aspect,<br>
                      struct anv_image *image)<br>
 {<br>
+   if (gralloc_info)<br>
+      return VK_SUCCESS;<br>
+<br>
    if (aspect == VK_IMAGE_ASPECT_DEPTH_BIT) {<br>
       try_make_hiz_surface(dev, base_info, image);<br>
    } else if (aspect == VK_IMAGE_ASPECT_COLOR_BIT &&<br>
@@ -344,8 +390,9 @@ add_fast_clear_state_buffer(<wbr>struct anv_image *image,<br>
  * Exactly one bit must be set in \a aspect.<br>
  */<br>
 static VkResult<br>
-make_main_surface(const struct anv_device *dev,<br>
+make_main_surface(struct anv_device *dev,<br>
                   const struct anv_image_create_info *anv_info,<br>
+                  const VkNativeBufferANDROID *gralloc_info,<br>
                   VkImageAspectFlags aspect,<br>
                   struct anv_image *image)<br>
 {<br>
@@ -360,7 +407,8 @@ make_main_surface(const struct anv_device *dev,<br>
    };<br>
<br>
    isl_tiling_flags_t tiling_flags;<br>
-   result = choose_isl_tiling_flags(anv_<wbr>info, &tiling_flags);<br>
+   result = choose_isl_tiling_flags(dev, anv_info, gralloc_info,<br>
+                                    &tiling_flags);<br>
    if (result != VK_SUCCESS)<br>
       return result;<br>
<br>
@@ -373,6 +421,19 @@ make_main_surface(const struct anv_device *dev,<br>
                                                aspect, base_info->tiling);<br>
    assert(format != ISL_FORMAT_UNSUPPORTED);<br>
<br>
+   uint32_t row_pitch = anv_info->stride;<br>
+#ifdef ANDROID<br>
+   if (gralloc_info) {<br>
+      row_pitch = gralloc_info->stride *<br>
+                  (isl_format_get_layout(format)<wbr>->bpb / 8);<br>
+   }<br>
+#endif<br>
+<br>
+   isl_surf_usage_flags_t usage =<br>
+      choose_isl_surf_usage(base_<wbr>info->flags, image->usage, aspect);<br>
+   if (gralloc_info)<br>
+      usage |= ISL_SURF_USAGE_DISABLE_AUX_<wbr>BIT;<br>
+<br>
    ok = isl_surf_init(&dev->isl_dev, &anv_surf->isl,<br>
       .dim = vk_to_isl_surf_dim[base_info-><wbr>imageType],<br>
       .format = format,<br>
@@ -383,8 +444,8 @@ make_main_surface(const struct anv_device *dev,<br>
       .array_len = base_info->arrayLayers,<br>
       .samples = base_info->samples,<br>
       .min_alignment = 0,<br>
-      .row_pitch = anv_info->stride,<br>
-      .usage = choose_isl_surf_usage(base_<wbr>info->flags, image->usage, aspect),<br>
+      .row_pitch = row_pitch,<br>
+      .usage = usage,<br>
       .tiling_flags = tiling_flags);<br>
<br>
    /* isl_surf_init() will fail only if provided invalid input. Invalid input<br>
@@ -393,9 +454,50 @@ make_main_surface(const struct anv_device *dev,<br>
    assert(ok);<br>
<br>
    add_surface(image, anv_surf);<br>
+<br>
+   if (gralloc_info)<br>
+      assert(anv_surf->offset == 0);<br>
+<br>
    return VK_SUCCESS;<br>
 }<br>
<br>
+#ifdef ANDROID<br>
+static VkResult<br>
+import_gralloc(struct anv_device *device,<br>
+               struct anv_image *image,<br>
+               const VkNativeBufferANDROID *gralloc_info,<br>
+               const VkAllocationCallbacks *alloc)<br>
+{<br>
+   VkDevice device_h = anv_device_to_handle(device);<br>
+   VkDeviceMemory mem_h = VK_NULL_HANDLE;<br>
+   VkResult result;<br>
+<br>
+   /* VK_ANDROID_native_buffer defines VkNativeBufferANDROID as an extension<br>
+    * of VkImageCreateInfo. We abuse the struct by chaining it to<br>
+    * VkMemoryAllocateInfo.<br>
+    */<br>
+   result = anv_AllocateMemory(device_h,<br>
+      &(VkMemoryAllocateInfo) {<br>
+         .sType = VK_STRUCTURE_TYPE_MEMORY_<wbr>ALLOCATE_INFO,<br>
+         .pNext = gralloc_info,<br>
+         .allocationSize = 0,<br>
+         .memoryTypeIndex = 0, /* XXX: Arbitrary memory type */<br>
+      },<br>
+      alloc,<br>
+      &mem_h);<br>
+<br>
+   if (result != VK_SUCCESS)<br>
+      return result;<br>
+<br>
+   ANV_FROM_HANDLE(anv_device_<wbr>memory, mem, mem_h);<br>
+   image->mem = mem;<br>
+   image->mem_offset = 0;<br>
+   image->mem_is_owned = true;<br>
+<br>
+   return VK_SUCCESS;<br>
+}<br>
+#endif<br>
+<br>
 VkResult<br>
 anv_image_create(VkDevice _device,<br>
                  const struct anv_image_create_info *anv_info,<br>
@@ -404,6 +506,8 @@ anv_image_create(VkDevice _device,<br>
 {<br>
    ANV_FROM_HANDLE(anv_device, device, _device);<br>
    const VkImageCreateInfo *base_info = anv_info->vk_info;<br>
+   const VkNativeBufferANDROID *gralloc_info =<br>
+      vk_find_struct_const(base_<wbr>info->pNext, NATIVE_BUFFER_ANDROID);<br>
    struct anv_image *image = NULL;<br>
    VkResult r;<br>
<br>
@@ -432,21 +536,30 @@ anv_image_create(VkDevice _device,<br>
    image->tiling = base_info->tiling;<br>
    image->aux_usage = ISL_AUX_USAGE_NONE;<br>
<br>
+#ifdef ANDROID<br>
+   if (gralloc_info) {<br>
+      r = import_gralloc(device, image, gralloc_info, alloc);<br>
+      if (r != VK_SUCCESS)<br>
+         goto fail;<br>
+   }<br>
+#endif<br>
+<br>
    uint32_t b;<br>
    for_each_bit(b, image->aspects) {<br>
       VkImageAspectFlagBits aspect = 1 << b;<br>
<br>
-      r = make_main_surface(device, anv_info, aspect, image);<br>
+      r = make_main_surface(device, anv_info, gralloc_info, aspect, image);<br>
       if (r != VK_SUCCESS)<br>
          goto fail;<br>
<br>
-      r = try_make_aux_surface(device, base_info, aspect, image);<br>
+      r = try_make_aux_surface(device, base_info, gralloc_info, aspect, image);<br>
       if (r != VK_SUCCESS)<br>
          goto fail;<br>
    }<br>
<br>
-   *pImage = anv_image_to_handle(image);<br>
+   VkImage image_h = anv_image_to_handle(image);<br>
<br>
+   *pImage = image_h;<br>
    return VK_SUCCESS;<br>
<br>
 fail:<br>
diff --git a/src/intel/vulkan/anv_<wbr>private.h b/src/intel/vulkan/anv_<wbr>private.h<br>
index d11a2363d9b..dafc37247f5 100644<br>
--- a/src/intel/vulkan/anv_<wbr>private.h<br>
+++ b/src/intel/vulkan/anv_<wbr>private.h<br>
@@ -71,6 +71,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_<wbr>buffer.h><br>
<br>
 #include "anv_entrypoints.h"<br>
 #include "isl/isl.h"<br>
<span class="gmail-HOEnZb"><font color="#888888">--<br>
2.13.5<br>
<br>
______________________________<wbr>_________________<br>
mesa-dev mailing list<br>
<a href="mailto:mesa-dev@lists.freedesktop.org">mesa-dev@lists.freedesktop.org</a><br>
<a href="https://lists.freedesktop.org/mailman/listinfo/mesa-dev" rel="noreferrer" target="_blank">https://lists.freedesktop.org/<wbr>mailman/listinfo/mesa-dev</a><br>
</font></span></blockquote></div><br></div></div>