diff mbox

[14/21] anv: add VK_EXT_display_control to anv driver

Message ID 20180214003134.1552-15-keithp@keithp.com (mailing list archive)
State New, archived
Headers show

Commit Message

Keith Packard Feb. 14, 2018, 12:31 a.m. UTC
This extension provides fences and frame count information to direct
display contexts. It uses new kernel ioctls to provide 64-bits of
vblank sequence and nanosecond resolution.

Signed-off-by: Keith Packard <keithp@keithp.com>
---
 src/intel/vulkan/anv_extensions.py |   1 +
 src/intel/vulkan/anv_private.h     |   4 ++
 src/intel/vulkan/anv_queue.c       |  59 ++++++++++++++++++---
 src/intel/vulkan/anv_wsi_display.c | 103 +++++++++++++++++++++++++++++++++++++
 4 files changed, 160 insertions(+), 7 deletions(-)
diff mbox

Patch

diff --git a/src/intel/vulkan/anv_extensions.py b/src/intel/vulkan/anv_extensions.py
index 32643e31045..1c6c4f8e27b 100644
--- a/src/intel/vulkan/anv_extensions.py
+++ b/src/intel/vulkan/anv_extensions.py
@@ -90,6 +90,7 @@  EXTENSIONS = [
     Extension('VK_EXT_debug_report',                      8, True),
     Extension('VK_EXT_external_memory_dma_buf',           1, True),
     Extension('VK_EXT_display_surface_counter',           1, 'VK_USE_PLATFORM_DISPLAY_KHR'),
+    Extension('VK_EXT_display_control',                   1, 'VK_USE_PLATFORM_DISPLAY_KHR'),
 ]
 
 class VkVersion:
diff --git a/src/intel/vulkan/anv_private.h b/src/intel/vulkan/anv_private.h
index d38dd9e4220..1d3e5fcd921 100644
--- a/src/intel/vulkan/anv_private.h
+++ b/src/intel/vulkan/anv_private.h
@@ -1941,6 +1941,7 @@  enum anv_fence_type {
    ANV_FENCE_TYPE_NONE = 0,
    ANV_FENCE_TYPE_BO,
    ANV_FENCE_TYPE_SYNCOBJ,
+   ANV_FENCE_TYPE_WSI,
 };
 
 enum anv_bo_fence_state {
@@ -1975,6 +1976,9 @@  struct anv_fence_impl {
 
       /** DRM syncobj handle for syncobj-based fences */
       uint32_t syncobj;
+
+      /** WSI fence */
+      struct wsi_fence *fence_wsi;
    };
 };
 
diff --git a/src/intel/vulkan/anv_queue.c b/src/intel/vulkan/anv_queue.c
index c6b2e01c628..d0bfad742d7 100644
--- a/src/intel/vulkan/anv_queue.c
+++ b/src/intel/vulkan/anv_queue.c
@@ -320,6 +320,10 @@  anv_fence_impl_cleanup(struct anv_device *device,
    case ANV_FENCE_TYPE_SYNCOBJ:
       anv_gem_syncobj_destroy(device, impl->syncobj);
       return;
+
+   case ANV_FENCE_TYPE_WSI:
+      impl->fence_wsi->destroy(impl->fence_wsi);
+      return;
    }
 
    unreachable("Invalid fence type");
@@ -465,11 +469,32 @@  anv_wait_for_syncobj_fences(struct anv_device *device,
    uint32_t *syncobjs = vk_zalloc(&device->alloc,
                                   sizeof(*syncobjs) * fenceCount, 8,
                                   VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
+   uint32_t syncobjCount = 0;
    if (!syncobjs)
       return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
 
    for (uint32_t i = 0; i < fenceCount; i++) {
       ANV_FROM_HANDLE(anv_fence, fence, pFences[i]);
+
+      if (fence->permanent.type == ANV_FENCE_TYPE_WSI) {
+         struct anv_fence_impl *impl = &fence->permanent;
+         bool expired = impl->fence_wsi->wait(impl->fence_wsi, true, _timeout);
+
+         VkResult result;
+
+         if (!expired) {
+            result = VK_TIMEOUT;
+            goto done;
+         }
+         if (!waitAll) {
+            result = VK_SUCCESS;
+            goto done;
+         }
+         continue;
+      done:
+         vk_free(&device->alloc, syncobjs);
+         return result;
+      }
       assert(fence->permanent.type == ANV_FENCE_TYPE_SYNCOBJ);
 
       struct anv_fence_impl *impl =
@@ -477,7 +502,7 @@  anv_wait_for_syncobj_fences(struct anv_device *device,
          &fence->temporary : &fence->permanent;
 
       assert(impl->type == ANV_FENCE_TYPE_SYNCOBJ);
-      syncobjs[i] = impl->syncobj;
+      syncobjs[syncobjCount++] = impl->syncobj;
    }
 
    int64_t abs_timeout_ns = 0;
@@ -499,7 +524,7 @@  anv_wait_for_syncobj_fences(struct anv_device *device,
     */
    int ret;
    do {
-      ret = anv_gem_syncobj_wait(device, syncobjs, fenceCount,
+      ret = anv_gem_syncobj_wait(device, syncobjs, syncobjCount,
                                  abs_timeout_ns, waitAll);
    } while (ret == -1 && errno == ETIME && gettime_ns() < abs_timeout_ns);
 
@@ -545,14 +570,33 @@  anv_wait_for_bo_fences(struct anv_device *device,
       for (uint32_t i = 0; i < fenceCount; i++) {
          ANV_FROM_HANDLE(anv_fence, fence, pFences[i]);
 
-         /* This function assumes that all fences are BO fences and that they
-          * have no temporary state.  Since BO fences will never be exported,
-          * this should be a safe assumption.
+         /* This function assumes that all fences have no temporary
+          * state.Since BO fences will never be exported, this should be a
+          * safe assumption.
           */
-         assert(fence->permanent.type == ANV_FENCE_TYPE_BO);
          assert(fence->temporary.type == ANV_FENCE_TYPE_NONE);
          struct anv_fence_impl *impl = &fence->permanent;
 
+         /* This function assumes that all fences are either BO fences or WSI
+          * fences
+          */
+
+         if (impl->type == ANV_FENCE_TYPE_WSI) {
+            bool expired = impl->fence_wsi->wait(impl->fence_wsi, true, timeout);
+
+            if (!expired) {
+               result = VK_TIMEOUT;
+               goto done;
+            }
+            if (!waitAll) {
+               result = VK_SUCCESS;
+               goto done;
+            }
+            continue;
+         }
+
+         assert(impl->type == ANV_FENCE_TYPE_BO);
+
          switch (impl->bo.state) {
          case ANV_BO_FENCE_STATE_RESET:
             /* This fence hasn't been submitted yet, we'll catch it the next
@@ -610,7 +654,8 @@  anv_wait_for_bo_fences(struct anv_device *device,
          uint32_t now_pending_fences = 0;
          for (uint32_t i = 0; i < fenceCount; i++) {
             ANV_FROM_HANDLE(anv_fence, fence, pFences[i]);
-            if (fence->permanent.bo.state == ANV_BO_FENCE_STATE_RESET)
+            if (fence->permanent.type == ANV_FENCE_TYPE_BO &&
+                fence->permanent.bo.state == ANV_BO_FENCE_STATE_RESET)
                now_pending_fences++;
          }
          assert(now_pending_fences <= pending_fences);
diff --git a/src/intel/vulkan/anv_wsi_display.c b/src/intel/vulkan/anv_wsi_display.c
index e87aed49f7d..32a948d76ca 100644
--- a/src/intel/vulkan/anv_wsi_display.c
+++ b/src/intel/vulkan/anv_wsi_display.c
@@ -168,3 +168,106 @@  anv_GetRandROutputDisplayEXT(VkPhysicalDevice  physical_device,
                                        display);
 }
 #endif /* VK_USE_PLATFORM_XLIB_XRANDR_EXT */
+
+/* VK_EXT_display_control */
+
+VkResult
+anv_DisplayPowerControlEXT(VkDevice                    _device,
+                            VkDisplayKHR                display,
+                            const VkDisplayPowerInfoEXT *display_power_info)
+{
+   ANV_FROM_HANDLE(anv_device, device, _device);
+
+   return wsi_display_power_control(_device,
+                                    &device->instance->physicalDevice.wsi_device,
+                                    display,
+                                    display_power_info);
+}
+
+VkResult
+anv_RegisterDeviceEventEXT(VkDevice                    _device,
+                            const VkDeviceEventInfoEXT  *device_event_info,
+                            const VkAllocationCallbacks *allocator,
+                            VkFence                     *_fence)
+{
+   ANV_FROM_HANDLE(anv_device, device, _device);
+   const VkAllocationCallbacks  *alloc;
+   struct anv_fence            *fence;
+   VkResult                     ret;
+
+   if (allocator)
+     alloc = allocator;
+   else
+     alloc = &device->instance->alloc;
+
+   fence = vk_alloc(alloc, sizeof (*fence), 8,
+                    VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+   if (!fence)
+      return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
+
+   fence->permanent.type = ANV_FENCE_TYPE_WSI;
+
+   ret = wsi_register_device_event(_device,
+                                   &device->instance->physicalDevice.wsi_device,
+                                   device_event_info,
+                                   alloc,
+                                   &fence->permanent.fence_wsi);
+   if (ret == VK_SUCCESS)
+      *_fence = anv_fence_to_handle(fence);
+   else
+      vk_free(alloc, fence);
+   return ret;
+}
+
+VkResult
+anv_RegisterDisplayEventEXT(VkDevice                           _device,
+                             VkDisplayKHR                       display,
+                             const VkDisplayEventInfoEXT        *display_event_info,
+                             const VkAllocationCallbacks        *allocator,
+                             VkFence                            *_fence)
+{
+   ANV_FROM_HANDLE(anv_device, device, _device);
+   const VkAllocationCallbacks  *alloc;
+   struct anv_fence            *fence;
+   VkResult                     ret;
+
+   if (allocator)
+     alloc = allocator;
+   else
+     alloc = &device->instance->alloc;
+
+   fence = vk_zalloc2(&device->alloc, allocator, sizeof (*fence), 8,
+                      VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+   if (!fence)
+      return VK_ERROR_OUT_OF_HOST_MEMORY;
+
+   fence->permanent.type = ANV_FENCE_TYPE_WSI;
+
+   ret = wsi_register_display_event(_device,
+                                    &device->instance->physicalDevice.wsi_device,
+                                    display,
+                                    display_event_info,
+                                    alloc,
+                                    &(fence->permanent.fence_wsi));
+
+   if (ret == VK_SUCCESS)
+      *_fence = anv_fence_to_handle(fence);
+   else
+      vk_free(alloc, fence);
+   return ret;
+}
+
+VkResult
+anv_GetSwapchainCounterEXT(VkDevice                    _device,
+                            VkSwapchainKHR              swapchain,
+                            VkSurfaceCounterFlagBitsEXT flag_bits,
+                            uint64_t                    *value)
+{
+   ANV_FROM_HANDLE(anv_device, device, _device);
+
+   return wsi_get_swapchain_counter(_device,
+                                    &device->instance->physicalDevice.wsi_device,
+                                    swapchain,
+                                    flag_bits,
+                                    value);
+}