[Mesa-dev] [PATCH 14/21] anv: add VK_EXT_display_control to anv driver
Keith Packard
keithp at keithp.com
Wed Feb 14 00:31:27 UTC 2018
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 at 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 --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);
+}
--
2.15.1
More information about the mesa-dev
mailing list