Use semaphores for page flip.

Change-Id: I95804221fa8b638246cf4792370da76f70d2ac56
diff --git a/src/intel/vulkan/anv_wsi.c b/src/intel/vulkan/anv_wsi.c
index 43fa5ea..cf14637 100644
--- a/src/intel/vulkan/anv_wsi.c
+++ b/src/intel/vulkan/anv_wsi.c
@@ -391,8 +391,9 @@
 
       anv_QueueSubmit(_queue, 0, NULL, swapchain->fences[0]);
 
-      result = swapchain->queue_present(swapchain,
-                                        pPresentInfo->pImageIndices[i]);
+      result =
+          swapchain->queue_present(swapchain, pPresentInfo->pImageIndices[i],
+                                   pPresentInfo->waitSemaphoreCount, pPresentInfo->pWaitSemaphores);
       /* TODO: What if one of them returns OUT_OF_DATE? */
       if (result != VK_SUCCESS)
          return result;
diff --git a/src/vulkan/wsi/wsi_common.h b/src/vulkan/wsi/wsi_common.h
index 2868d1a..b1a1d19 100644
--- a/src/vulkan/wsi/wsi_common.h
+++ b/src/vulkan/wsi/wsi_common.h
@@ -62,8 +62,8 @@
    VkResult (*acquire_next_image)(struct wsi_swapchain *swap_chain,
                                   uint64_t timeout, VkSemaphore semaphore,
                                   uint32_t *image_index);
-   VkResult (*queue_present)(struct wsi_swapchain *swap_chain,
-                             uint32_t image_index);
+   VkResult (*queue_present)(struct wsi_swapchain* swap_chain, uint32_t image_index,
+                             uint32_t wait_semaphore_count, const VkSemaphore* wait_semaphores);
 };
 
 struct wsi_interface {
diff --git a/src/vulkan/wsi/wsi_common_magma.cc b/src/vulkan/wsi/wsi_common_magma.cc
index e9b9096..570e063 100644
--- a/src/vulkan/wsi/wsi_common_magma.cc
+++ b/src/vulkan/wsi/wsi_common_magma.cc
@@ -48,25 +48,25 @@
 class MagmaImage {
 public:
    static std::unique_ptr<MagmaImage> Create(VkDevice device, const wsi_magma_callbacks* callbacks,
+                                             magma_system_connection* connection,
                                              const VkSwapchainCreateInfoKHR* create_info,
                                              const VkAllocationCallbacks* pAllocator);
 
    ~MagmaImage() { callbacks_->free_wsi_image(device_, allocator_, image_, device_memory_); }
 
-   bool busy() { return busy_; }
-
-   void set_busy(bool busy) { busy_ = busy; }
-
    magma_buffer_t buffer_handle() { return buffer_handle_; }
 
    VkImage image() { return image_; }
 
+   magma_semaphore_t semaphore() { return semaphore_; }
+
 private:
    MagmaImage(VkDevice device, const wsi_magma_callbacks* callbacks,
               const VkAllocationCallbacks* allocator, magma_buffer_t buffer_handle, VkImage image,
-              VkDeviceMemory device_memory)
+              VkDeviceMemory device_memory, magma_semaphore_t semaphore)
        : device_(device), allocator_(allocator), callbacks_(callbacks),
-         buffer_handle_(buffer_handle), image_(image), device_memory_(device_memory)
+         buffer_handle_(buffer_handle), image_(image), device_memory_(device_memory),
+         semaphore_(semaphore)
    {
    }
 
@@ -76,11 +76,12 @@
    magma_buffer_t buffer_handle_;
    VkImage image_;
    VkDeviceMemory device_memory_;
-   bool busy_ = false;
+   magma_semaphore_t semaphore_;
 };
 
 std::unique_ptr<MagmaImage> MagmaImage::Create(VkDevice device,
                                                const wsi_magma_callbacks* callbacks,
+                                               magma_system_connection* connection,
                                                const VkSwapchainCreateInfoKHR* pCreateInfo,
                                                const VkAllocationCallbacks* allocator)
 {
@@ -98,8 +99,15 @@
    if (result != VK_SUCCESS)
       return DRETP(nullptr, "create_wsi_image failed");
 
-   auto magma_image = std::unique_ptr<MagmaImage>(
-       new MagmaImage(device, callbacks, allocator, buffer_handle, image, device_memory));
+   magma_semaphore_t semaphore;
+   magma_status_t status = magma_system_create_semaphore(connection, &semaphore);
+   if (status != MAGMA_STATUS_OK)
+      return DRETP(nullptr, "failed to create semaphore");
+
+   magma_system_signal_semaphore(semaphore);
+
+   auto magma_image = std::unique_ptr<MagmaImage>(new MagmaImage(
+       device, callbacks, allocator, buffer_handle, image, device_memory, semaphore));
 
    return magma_image;
 }
@@ -171,54 +179,44 @@
    static VkResult AcquireNextImage(wsi_swapchain* wsi_chain, uint64_t timeout,
                                     VkSemaphore semaphore, uint32_t* pImageIndex)
    {
-      DLOG("AcquireNextImage");
-
       MagmaSwapchain* chain = cast(wsi_chain);
 
-      for (uint32_t i = 0; i < chain->image_count(); i++) {
-         if (!chain->get_image(i)->busy()) {
-            DLOG("returning image index %u", i);
-            *pImageIndex = i;
-            return VK_SUCCESS;
-         }
+      uint32_t index = chain->next_index_;
+      MagmaImage* image = chain->get_image(index);
+      DLOG("AcquireNextImage semaphore id 0x%" PRIx64,
+           magma_system_get_semaphore_id(image->semaphore()));
+
+      magma_status_t status = magma_system_wait_semaphore(image->semaphore(), timeout);
+      if (status == MAGMA_STATUS_TIMED_OUT) {
+         DLOG("timeout waiting for image semaphore");
+         return VK_TIMEOUT;
       }
 
-      // TODO(MA-114): wait until a buffer is available
-      assert(timeout == 0);
+      assert(status == MAGMA_STATUS_OK);
 
-      return VK_NOT_READY;
+      if (++chain->next_index_ >= chain->image_count())
+         chain->next_index_ = 0;
+
+      *pImageIndex = index;
+      DLOG("AcquireNextImage returning index %u id 0x%" PRIx64, *pImageIndex,
+           magma_system_get_buffer_id(image->buffer_handle()));
+
+      return VK_SUCCESS;
    }
 
-   static void PageflipCallback(int32_t error, void* data)
+   static VkResult QueuePresent(wsi_swapchain* swapchain, uint32_t image_index,
+                                uint32_t wait_semaphore_count, const VkSemaphore* wait_semaphores)
    {
-      DLOG("PageflipCallback (error %d)", error);
-      DASSERT(error == 0);
-      MagmaImage* image = reinterpret_cast<MagmaImage*>(data);
-      image->set_busy(false);
-   }
-
-   static VkResult QueuePresent(wsi_swapchain* swapchain, uint32_t image_index)
-   {
-      DLOG("QueuePresent image_index %u", image_index);
-
       MagmaSwapchain* magma_swapchain = cast(swapchain);
       MagmaImage* image = magma_swapchain->get_image(image_index);
 
-      assert(!image->busy());
+      DLOG("QueuePresent image_index %u id 0x%" PRIx64, image_index,
+           magma_system_get_buffer_id(image->buffer_handle()));
 
-      image->set_busy(true);
-
-      // Workaround for the synchronous behavior of magma_system_display_page_flip:
-      // we allow the next frame to begin before the current frame finishes by
-      // delaying the present of the current frame until the next present.
-      if (magma_swapchain->last_buffer_presented_ != -1) {
-         MagmaImage* last_image =
-             magma_swapchain->get_image(magma_swapchain->last_buffer_presented_);
-         magma_system_display_page_flip(magma_swapchain->connection(), last_image->buffer_handle(),
-                                        PageflipCallback, last_image);
-      }
-
-      magma_swapchain->last_buffer_presented_ = image_index;
+      magma_semaphore_t signal_semaphores[1]{image->semaphore()};
+      magma_system_display_page_flip(
+          magma_swapchain->connection(), image->buffer_handle(), wait_semaphore_count,
+          reinterpret_cast<const magma_semaphore_t*>(wait_semaphores), 1, signal_semaphores);
 
       return VK_SUCCESS;
    }
@@ -236,7 +234,7 @@
    const uint32_t magic_ = kMagic;
    magma_system_connection* connection_;
    std::vector<std::unique_ptr<MagmaImage>> images_;
-   int32_t last_buffer_presented_ = -1;
+   uint32_t next_index_ = 0;
 };
 
 static VkResult magma_surface_get_support(VkIcdSurfaceBase* icd_surface,
@@ -331,8 +329,8 @@
    uint32_t num_images = pCreateInfo->minImageCount;
 
    for (uint32_t i = 0; i < num_images; i++) {
-      std::unique_ptr<MagmaImage> image =
-          MagmaImage::Create(device, wsi_magma->callbacks(), pCreateInfo, pAllocator);
+      std::unique_ptr<MagmaImage> image = MagmaImage::Create(
+          device, wsi_magma->callbacks(), wsi_magma->connection(device), pCreateInfo, pAllocator);
       if (!image)
          return VK_ERROR_OUT_OF_DEVICE_MEMORY;