summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2016-10-26 11:51:27 +1000
committerEmil Velikov <emil.l.velikov@gmail.com>2016-11-28 12:17:41 +0000
commitae6e22e311d417ec0b50edb9b656c1c3de6df28a (patch)
tree4bf99dc136cb6f5b145b4a45950134e8728f1610
parentf7b58a378ca94cf1c2637d640ce5b9fb8f8519a6 (diff)
downloadexternal_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.c62
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);