diff options
author | Dave Airlie <airlied@redhat.com> | 2016-10-26 11:51:27 +1000 |
---|---|---|
committer | Emil Velikov <emil.l.velikov@gmail.com> | 2016-11-28 12:17:41 +0000 |
commit | ae6e22e311d417ec0b50edb9b656c1c3de6df28a (patch) | |
tree | 4bf99dc136cb6f5b145b4a45950134e8728f1610 | |
parent | f7b58a378ca94cf1c2637d640ce5b9fb8f8519a6 (diff) | |
download | external_mesa3d-ae6e22e311d417ec0b50edb9b656c1c3de6df28a.zip external_mesa3d-ae6e22e311d417ec0b50edb9b656c1c3de6df28a.tar.gz external_mesa3d-ae6e22e311d417ec0b50edb9b656c1c3de6df28a.tar.bz2 |
vulkan/wsi/x11: handle timeouts properly in next image acquire (v1.1)
For 0 timeout, just poll for an event, and if none, return
For UINT64_MAX timeout, just wait for special event blocked
For other timeouts get the xcb fd and block on it, decreasing
the timeout if we get woken up for non-special events.
v1.1: return VK_TIMEOUT for poll timeouts.
handle timeout going negative.
Reviewed-by: Edward O'Callaghan <funfunctor@folklore1984.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
(cherry picked from commit 787c172aed0ae88ca6a8c1a193d9dd744fbdc918)
-rw-r--r-- | src/vulkan/wsi/wsi_common_x11.c | 62 |
1 files changed, 57 insertions, 5 deletions
diff --git a/src/vulkan/wsi/wsi_common_x11.c b/src/vulkan/wsi/wsi_common_x11.c index 09718eb..ae2d111 100644 --- a/src/vulkan/wsi/wsi_common_x11.c +++ b/src/vulkan/wsi/wsi_common_x11.c @@ -34,6 +34,7 @@ #include <errno.h> #include <string.h> +#include <poll.h> #include "util/hash_table.h" #include "wsi_common.h" @@ -555,6 +556,26 @@ x11_handle_dri3_present_event(struct x11_swapchain *chain, return VK_SUCCESS; } + +static uint64_t wsi_get_current_time(void) +{ + uint64_t current_time; + struct timespec tv; + + clock_gettime(CLOCK_MONOTONIC, &tv); + current_time = tv.tv_nsec + tv.tv_sec*1000000000ull; + return current_time; +} + +static uint64_t wsi_get_absolute_timeout(uint64_t timeout) +{ + uint64_t current_time = wsi_get_current_time(); + + timeout = MIN2(UINT64_MAX - current_time, timeout); + + return current_time + timeout; +} + static VkResult x11_acquire_next_image(struct wsi_swapchain *anv_chain, uint64_t timeout, @@ -562,7 +583,9 @@ x11_acquire_next_image(struct wsi_swapchain *anv_chain, uint32_t *image_index) { struct x11_swapchain *chain = (struct x11_swapchain *)anv_chain; - + xcb_generic_event_t *event; + struct pollfd pfds; + uint64_t atimeout; while (1) { for (uint32_t i = 0; i < chain->image_count; i++) { if (!chain->images[i].busy) { @@ -575,10 +598,39 @@ x11_acquire_next_image(struct wsi_swapchain *anv_chain, } xcb_flush(chain->conn); - xcb_generic_event_t *event = - xcb_wait_for_special_event(chain->conn, chain->special_event); - if (!event) - return VK_ERROR_OUT_OF_DATE_KHR; + + if (timeout == UINT64_MAX) { + event = xcb_wait_for_special_event(chain->conn, chain->special_event); + if (!event) + return VK_ERROR_OUT_OF_DATE_KHR; + } else { + event = xcb_poll_for_special_event(chain->conn, chain->special_event); + if (!event) { + int ret; + if (timeout == 0) + return VK_NOT_READY; + + atimeout = wsi_get_absolute_timeout(timeout); + + pfds.fd = xcb_get_file_descriptor(chain->conn); + pfds.events = POLLIN; + ret = poll(&pfds, 1, timeout / 1000 / 1000); + if (ret == 0) + return VK_TIMEOUT; + if (ret == -1) + return VK_ERROR_OUT_OF_DATE_KHR; + + /* If a non-special event happens, the fd will still + * poll. So recalculate the timeout now just in case. + */ + uint64_t current_time = wsi_get_current_time(); + if (atimeout > current_time) + timeout = atimeout - current_time; + else + timeout = 0; + continue; + } + } VkResult result = x11_handle_dri3_present_event(chain, (void *)event); free(event); |