Migrate vulkan to new zx display APIs

Change-Id: I54cdaa577cf9b1c2048cd82a518655f7c8da1ec1
diff --git a/include/vulkan/vk_icd.h b/include/vulkan/vk_icd.h
index f0f02f2..d95fe50 100644
--- a/include/vulkan/vk_icd.h
+++ b/include/vulkan/vk_icd.h
@@ -121,8 +121,7 @@
 #ifdef VK_USE_PLATFORM_MAGMA_KHR
 typedef struct _VkIcdSurfaceMagma {
    VkIcdSurfaceBase base;
-   int fd;
-   void* connection;
+   bool has_fb;
 } VkIcdSurfaceMagma;
 #endif // VK_USE_PLATFORM_MAGMA_KHR
 
diff --git a/src/intel/vulkan/BUILD.gn b/src/intel/vulkan/BUILD.gn
index 2d8154b..aa67109 100644
--- a/src/intel/vulkan/BUILD.gn
+++ b/src/intel/vulkan/BUILD.gn
@@ -84,6 +84,7 @@
     "$mesa_build_root/src/util",
     "$mesa_build_root/src/vulkan/util",
     "$msd_intel_gen_build_root/include",
+    "//zircon/public/lib/framebuffer",
   ]
 
   sources = [
diff --git a/src/intel/vulkan/anv_wsi.c b/src/intel/vulkan/anv_wsi.c
index 861cfc6..d891d07 100644
--- a/src/intel/vulkan/anv_wsi.c
+++ b/src/intel/vulkan/anv_wsi.c
@@ -41,7 +41,7 @@
     .create_wsi_image = anv_wsi_magma_image_create,
     .free_wsi_image = anv_wsi_magma_image_free,
     .get_platform_semaphore = anv_wsi_magma_get_platform_semaphore,
-    .vk_import_semaphore_fuchsia_handle_khr = anv_ImportSemaphoreFuchsiaHandleKHR,
+    .signal_semaphore = anv_wsi_magma_signal_semaphore,
 };
 #endif
 
diff --git a/src/intel/vulkan/anv_wsi_magma.cc b/src/intel/vulkan/anv_wsi_magma.cc
index 34922d1..6da4622 100644
--- a/src/intel/vulkan/anv_wsi_magma.cc
+++ b/src/intel/vulkan/anv_wsi_magma.cc
@@ -6,6 +6,7 @@
 #include "anv_magma.h"
 #include "wsi_common_magma.h"
 #include <fcntl.h>
+#include <lib/framebuffer/framebuffer.h>
 
 #include "vk_format_info.h"
 
@@ -36,12 +37,8 @@
       return VK_ERROR_OUT_OF_HOST_MEMORY;
 
    surface->base.platform = VK_ICD_WSI_PLATFORM_MAGMA;
-   surface->fd = open("/dev/class/display/000", O_RDONLY);
-
-   if (surface->fd >= 0)
-      surface->connection = magma_create_connection(surface->fd, MAGMA_CAPABILITY_DISPLAY);
-   else
-      surface->connection = nullptr;
+   const char* err;
+   surface->has_fb = fb_bind(false, &err) == ZX_OK;
 
    *pSurface = VkIcdSurfaceBase_to_handle(&surface->base);
 
@@ -56,10 +53,8 @@
 void anv_wsi_magma_destroy_surface(VkIcdSurfaceBase* icd_surface)
 {
    auto surface = reinterpret_cast<VkIcdSurfaceMagma*>(icd_surface);
-   if (surface->connection)
-      magma_release_connection(reinterpret_cast<magma_connection_t*>(surface->connection));
-   if (surface->fd >= 0)
-      close(surface->fd);
+   if (surface->has_fb)
+      fb_release();
 }
 
 VkResult anv_wsi_magma_image_create(VkDevice device_h, const VkSwapchainCreateInfoKHR* pCreateInfo,
@@ -148,3 +143,11 @@
                               ? &semaphore->temporary : &semaphore->permanent;
    return impl->syncobj;
 }
+
+void anv_wsi_magma_signal_semaphore(VkSemaphore vk_semaphore)
+{
+   ANV_FROM_HANDLE(anv_semaphore, semaphore, vk_semaphore);
+   anv_semaphore_impl* impl = semaphore->temporary.type != ANV_SEMAPHORE_TYPE_NONE
+                              ? &semaphore->temporary : &semaphore->permanent;
+   magma_signal_semaphore(impl->syncobj);
+}
diff --git a/src/intel/vulkan/anv_wsi_magma.h b/src/intel/vulkan/anv_wsi_magma.h
index dda05ea..32b9f38 100644
--- a/src/intel/vulkan/anv_wsi_magma.h
+++ b/src/intel/vulkan/anv_wsi_magma.h
@@ -25,6 +25,8 @@
 
 uintptr_t anv_wsi_magma_get_platform_semaphore(VkDevice device, VkSemaphore semaphore);
 
+void anv_wsi_magma_signal_semaphore(VkSemaphore semaphore);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/src/vulkan/wsi/BUILD.gn b/src/vulkan/wsi/BUILD.gn
index 2b465f3..732f309 100644
--- a/src/vulkan/wsi/BUILD.gn
+++ b/src/vulkan/wsi/BUILD.gn
@@ -37,7 +37,8 @@
     "$magma_build_root/include:magma_abi",
     "$magma_build_root/src/magma_util",
     "$mesa_build_root/include:vulkan",
-    "$mesa_build_root/src/util"
+    "$mesa_build_root/src/util",
+    "//zircon/public/lib/framebuffer",
   ]
 
   include_dirs = [ "$mesa_build_root/src/vulkan/util" ]
diff --git a/src/vulkan/wsi/wsi_common.h b/src/vulkan/wsi/wsi_common.h
index c91b7b0..2e01016 100644
--- a/src/vulkan/wsi/wsi_common.h
+++ b/src/vulkan/wsi/wsi_common.h
@@ -136,7 +136,7 @@
                           VkImage image_h,
                           VkDeviceMemory memory_h);
    uintptr_t (*get_platform_semaphore)(VkDevice device, VkSemaphore semaphore);
-   PFN_vkImportSemaphoreFuchsiaHandleKHR vk_import_semaphore_fuchsia_handle_khr;
+   void (*signal_semaphore)(VkSemaphore semaphore);
 };
 
 #define WSI_DEFINE_NONDISP_HANDLE_CASTS(__wsi_type, __VkType)              \
diff --git a/src/vulkan/wsi/wsi_common_magma.cc b/src/vulkan/wsi/wsi_common_magma.cc
index 8fa0811..c2da472 100644
--- a/src/vulkan/wsi/wsi_common_magma.cc
+++ b/src/vulkan/wsi/wsi_common_magma.cc
@@ -3,8 +3,10 @@
 // found in the LICENSE file.
 
 #include <functional>
+#include <lib/framebuffer/framebuffer.h>
 #include <memory>
 #include <vector>
+#include <zircon/syscalls.h>
 
 #include "util/macros.h"
 #include "wsi_common_magma.h"
@@ -42,20 +44,16 @@
 class WsiMagmaConnections {
 public:
    WsiMagmaConnections(magma_connection_t* render_connection,
-                       magma_connection_t* display_connection, const wsi_magma_callbacks* callbacks)
-       : callbacks_(callbacks), render_connection_(render_connection),
-         display_connection_(display_connection)
+                       const wsi_magma_callbacks* callbacks)
+       : callbacks_(callbacks), render_connection_(render_connection)
    {
    }
 
    magma_connection_t* render_connection() { return render_connection_; }
 
-   magma_connection_t* display_connection() { return display_connection_; }
-
 private:
    const wsi_magma_callbacks* callbacks_;  // not owned
    magma_connection_t* render_connection_; // not owned
-   magma_connection_t* display_connection_;
 };
 
 //////////////////////////////////////////////////////////////////////////////
@@ -69,11 +67,11 @@
 
    ~MagmaImage();
 
-   magma_buffer_t display_buffer() { return display_buffer_; }
+   uint64_t display_buffer() { return display_buffer_; }
 
-   magma_semaphore_t display_semaphore() { return display_semaphore_; }
+   zx_handle_t buffer_presented_semaphore() { return buffer_presented_semaphore_; }
 
-   magma_semaphore_t buffer_presented_semaphore() { return buffer_presented_semaphore_; }
+   uint64_t buffer_presented_semaphore_id() { return buffer_presented_semaphore_id_; }
 
    VkImage image() { return image_; }
 
@@ -84,13 +82,13 @@
 private:
    MagmaImage(VkDevice device, const wsi_magma_callbacks* callbacks,
               std::shared_ptr<WsiMagmaConnections> connections, magma_buffer_t render_buffer,
-              magma_buffer_t display_buffer, magma_semaphore_t display_semaphore, VkImage image,
-              VkDeviceMemory device_memory, const VkAllocationCallbacks* allocator,
-              magma_semaphore_t buffer_presented_semaphore)
+              uint64_t display_buffer, zx_handle_t buffer_presented_semaphore,
+              uint64_t buffer_presented_semaphore_id, VkImage image, VkDeviceMemory device_memory,
+              const VkAllocationCallbacks* allocator)
        : device_(device), image_(image), device_memory_(device_memory), callbacks_(callbacks),
          connections_(std::move(connections)), render_buffer_(render_buffer),
-         display_buffer_(display_buffer), display_semaphore_(display_semaphore),
-         buffer_presented_semaphore_(buffer_presented_semaphore), allocator_(allocator)
+         display_buffer_(display_buffer), buffer_presented_semaphore_(buffer_presented_semaphore),
+         buffer_presented_semaphore_id_(buffer_presented_semaphore_id), allocator_(allocator)
    {
    }
 
@@ -99,9 +97,10 @@
    VkDeviceMemory device_memory_;
    const wsi_magma_callbacks* callbacks_;
    std::shared_ptr<WsiMagmaConnections> connections_;
-   magma_buffer_t render_buffer_, display_buffer_; // render_buffer is not owned
-   magma_semaphore_t display_semaphore_;
-   magma_semaphore_t buffer_presented_semaphore_;
+   magma_buffer_t render_buffer_; // render_buffer is not owned
+   uint64_t display_buffer_;
+   zx_handle_t buffer_presented_semaphore_;
+   uint64_t buffer_presented_semaphore_id_;
    const VkAllocationCallbacks* allocator_;
 };
 
@@ -115,9 +114,9 @@
    uint32_t row_pitch;
    uint32_t offset;
    uint32_t bpp = 32;
-   magma_buffer_t render_buffer, display_buffer;
-   magma_semaphore_t display_semaphore;
-   magma_semaphore_t buffer_presented_semaphore;
+   magma_buffer_t render_buffer;
+   uint64_t display_buffer;
+   zx_handle_t buffer_presented_semaphore;
    uint32_t buffer_handle, semaphore_handle;
    uint32_t size;
    VkImage image;
@@ -133,31 +132,40 @@
    if (status != MAGMA_STATUS_OK)
       return DRETP(nullptr, "failed to export buffer");
 
-   status = magma_import(connections->display_connection(), buffer_handle, &display_buffer);
+   // Must be consistent with intel-gpu-core.h and the tiling format
+   // used by VK_IMAGE_USAGE_SCANOUT_BIT_GOOGLE.
+   const uint32_t kImageTypeXTiled = 1;
+   status = fb_import_image(buffer_handle, kImageTypeXTiled, &display_buffer);
    if (status != MAGMA_STATUS_OK)
       return DRETP(nullptr, "failed to import buffer");
 
-   status = magma_create_semaphore(connections->display_connection(), &display_semaphore);
-   if (status != MAGMA_STATUS_OK)
-      return DRETP(nullptr, "failed to create semaphore");
+   if (zx_event_create(0, &buffer_presented_semaphore) != ZX_OK
+         || zx_object_signal(buffer_presented_semaphore, 0, ZX_EVENT_SIGNALED) != ZX_OK)
+      return DRETP(nullptr, "failed to create or signal semaphore");
 
-   magma_signal_semaphore(display_semaphore);
+   zx_info_handle_basic_t info;
+   if (zx_object_get_info(buffer_presented_semaphore, ZX_INFO_HANDLE_BASIC,
+                          &info, sizeof(info), nullptr, nullptr) != ZX_OK)
+      return DRETP(nullptr, "failed to get semaphore id");
 
-   status = magma_create_semaphore(connections->display_connection(), &buffer_presented_semaphore);
-   if (status != MAGMA_STATUS_OK)
-      return DRETP(nullptr, "failed to create semaphore");
+   zx_handle_t dup;
+   if (zx_handle_duplicate(buffer_presented_semaphore, ZX_RIGHT_SAME_RIGHTS, &dup) != ZX_OK
+         || fb_import_event(dup, info.koid) != ZX_OK)
+      return DRETP(nullptr, "failed to duplicate or import display semaphore");
 
    return std::unique_ptr<MagmaImage>(new MagmaImage(
-       device, callbacks, std::move(connections), render_buffer, display_buffer, display_semaphore,
-       image, device_memory, allocator, buffer_presented_semaphore));
+       device, callbacks, std::move(connections), render_buffer, display_buffer,
+       buffer_presented_semaphore, info.koid, image, device_memory, allocator));
 }
 
 MagmaImage::~MagmaImage()
 {
    callbacks_->free_wsi_image(device_, allocator_, image_, device_memory_);
 
-   magma_release_buffer(connections_->display_connection(), display_buffer_);
-   magma_release_semaphore(connections_->display_connection(), display_semaphore_);
+   fb_release_image(display_buffer_);
+   fb_release_event(buffer_presented_semaphore_id_);
+
+   zx_handle_close(buffer_presented_semaphore_);
 }
 
 //////////////////////////////////////////////////////////////////////////////
@@ -182,8 +190,6 @@
       this->queue_present = QueuePresent;
    }
 
-   magma_connection_t* display_connection() { return connections_->display_connection(); }
-
    magma_connection_t* render_connection() { return connections_->render_connection(); }
 
    uint32_t image_count() { return images_.size(); }
@@ -224,7 +230,7 @@
       return VK_SUCCESS;
    }
 
-   static VkResult AcquireNextImage(wsi_swapchain* wsi_chain, uint64_t timeout,
+   static VkResult AcquireNextImage(wsi_swapchain* wsi_chain, uint64_t timeout_ns,
                                     VkSemaphore semaphore, uint32_t* pImageIndex)
    {
       MagmaSwapchain* chain = cast(wsi_chain);
@@ -233,26 +239,22 @@
       MagmaImage* image = chain->get_image(index);
 
       DLOG("AcquireNextImage semaphore id 0x%" PRIx64,
-           magma_get_semaphore_id(image->display_semaphore()));
+           image->buffer_presented_semaphore_id());
 
+      // The zircon display APIs don't support providing an image back to the driver
+      // before the image is retired. Returning the presented semaphore from the vulkan API
+      // only prevents clients from rendering into the buffer, not from presenting the
+      // buffer (with a wait semaphore). So we can't return the buffer until this is signaled.
+      zx_signals_t observed;
+      zx_status_t status;
+      if ((status = zx_object_wait_one(image->buffer_presented_semaphore(), ZX_EVENT_SIGNALED,
+                                       zx_deadline_after(timeout_ns), &observed)) != ZX_OK) {
+         return VK_TIMEOUT;
+      }
+      // Unsignal the event.
+      zx_object_signal(image->buffer_presented_semaphore(), ZX_EVENT_SIGNALED, 0);
       if (semaphore) {
-         uint32_t semaphore_handle;
-         magma_status_t status = magma_export_semaphore(
-             chain->display_connection(), image->display_semaphore(), &semaphore_handle);
-         if (status == MAGMA_STATUS_OK) {
-            VkImportSemaphoreFuchsiaHandleInfoKHR info = {
-                .sType = VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FUCHSIA_HANDLE_INFO_KHR,
-                .semaphore = semaphore,
-                .flags = VK_SEMAPHORE_IMPORT_TEMPORARY_BIT_KHR,
-                .handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_FUCHSIA_FENCE_BIT_KHR,
-                .handle = semaphore_handle};
-            VkResult result =
-                image->callbacks()->vk_import_semaphore_fuchsia_handle_khr(image->device(), &info);
-            if (result != VK_SUCCESS)
-               DLOG("vkImportSemaphoreFuchsiaHandleKHR failed: %d", result);
-         } else {
-            DLOG("magma_export_semaphore failed: %d", status);
-         }
+         image->callbacks()->signal_semaphore(semaphore);
       }
 
       if (++chain->next_index_ >= chain->image_count())
@@ -260,7 +262,7 @@
 
       *pImageIndex = index;
       DLOG("AcquireNextImage returning index %u id 0x%" PRIx64, *pImageIndex,
-           magma_get_buffer_id(image->display_buffer()));
+           image->display_buffer());
 
       return VK_SUCCESS;
    }
@@ -273,36 +275,37 @@
       MagmaImage* image = magma_swapchain->get_image(image_index);
 
       DLOG("QueuePresent image_index %u id 0x%" PRIx64, image_index,
-           magma_get_buffer_id(image->display_buffer()));
+           image->display_buffer());
 
-      magma_semaphore_t display_semaphores[wait_semaphore_count];
       magma_status_t status;
 
+      // TODO(MA-375): Support more than 1 wait semaphore
+      assert(wait_semaphore_count <= 1);
+
+      uint64_t wait_sem_id = FB_INVALID_ID;
       for (uint32_t i = 0; i < wait_semaphore_count; i++) {
          uint32_t semaphore_handle;
+         uintptr_t platform_sem = image->callbacks()
+             ->get_platform_semaphore(swapchain->device, wait_semaphores[i]);
+         wait_sem_id = magma_get_semaphore_id(platform_sem);
+
          status = magma_export_semaphore(
-             magma_swapchain->render_connection(),
-             image->callbacks()->get_platform_semaphore(swapchain->device, wait_semaphores[i]),
-             &semaphore_handle);
+             magma_swapchain->render_connection(), platform_sem, &semaphore_handle);
          if (status != MAGMA_STATUS_OK) {
             DLOG("Failed to export wait semaphore");
             continue;
          }
          magma_semaphore_t semaphore;
-         status = magma_import_semaphore(magma_swapchain->display_connection(), semaphore_handle,
-                                         &display_semaphores[i]);
-         if (status != MAGMA_STATUS_OK)
+         status = fb_import_event(semaphore_handle, wait_sem_id);
+         if (status != ZX_OK)
             DLOG("failed to import wait semaphore");
       }
 
-      magma_semaphore_t signal_semaphores[1]{image->display_semaphore()};
-
-      magma_display_page_flip(magma_swapchain->display_connection(), image->display_buffer(),
-                              wait_semaphore_count, display_semaphores, 1, signal_semaphores,
-                              image->buffer_presented_semaphore());
+      fb_present_image(image->display_buffer(),
+                       wait_sem_id, FB_INVALID_ID, image->buffer_presented_semaphore_id());
 
       for (uint32_t i = 0; i < wait_semaphore_count; i++) {
-         magma_release_semaphore(magma_swapchain->display_connection(), display_semaphores[i]);
+         fb_release_event(wait_sem_id);
       }
 
       return VK_SUCCESS;
@@ -333,9 +336,9 @@
                                           VkBool32* pSupported)
 {
    auto surface = reinterpret_cast<VkIcdSurfaceMagma*>(icd_surface);
-   DLOG("magma_surface_get_support queue %u connection %p", queueFamilyIndex, surface->connection);
+   DLOG("magma_surface_get_support queue %u connection %d", queueFamilyIndex, surface->has_fb);
 
-   *pSupported = surface->connection != nullptr;
+   *pSupported = surface->has_fb;
    return VK_SUCCESS;
 }
 
@@ -343,14 +346,14 @@
                                                VkSurfaceCapabilitiesKHR* caps)
 {
    auto surface = reinterpret_cast<VkIcdSurfaceMagma*>(icd_surface);
-   DLOG("magma_surface_get_capabilities connection %p", surface->connection);
+   DLOG("magma_surface_get_capabilities connection %d", surface->has_fb);
 
    VkExtent2D extent = {0xFFFFFFFF, 0xFFFFFFFF};
 
-   magma_display_size display_size;
-   magma_status_t status = magma_display_get_size(surface->fd, &display_size);
-   if (status == MAGMA_STATUS_OK)
-      extent = {display_size.width, display_size.height};
+   uint32_t width, height, stride;
+   zx_pixel_format_t format;
+   fb_get_config(&width, &height, &stride, &format);
+   extent = {width, height};
 
    caps->minImageExtent = {1, 1};
    caps->maxImageExtent = {extent};
@@ -425,10 +428,9 @@
    auto render_connection =
        reinterpret_cast<magma_connection_t*>(wsi_magma->callbacks()->get_render_connection(device));
    auto magma_surface = reinterpret_cast<VkIcdSurfaceMagma*>(icd_surface);
-   auto display_connection = reinterpret_cast<magma_connection_t*>(magma_surface->connection);
 
    // TODO(MA-115): use pAllocator here and for images (and elsewhere in magma?)
-   auto connections = std::make_shared<WsiMagmaConnections>(render_connection, display_connection,
+   auto connections = std::make_shared<WsiMagmaConnections>(render_connection,
                                                             wsi_magma->callbacks());
 
    auto chain = std::make_unique<MagmaSwapchain>(device, connections);