summaryrefslogtreecommitdiffstats
path: root/src/vulkan/wsi
diff options
context:
space:
mode:
Diffstat (limited to 'src/vulkan/wsi')
-rw-r--r--src/vulkan/wsi/wsi_common_x11.c63
1 files changed, 60 insertions, 3 deletions
diff --git a/src/vulkan/wsi/wsi_common_x11.c b/src/vulkan/wsi/wsi_common_x11.c
index ab577868ab1..5f29ead3f23 100644
--- a/src/vulkan/wsi/wsi_common_x11.c
+++ b/src/vulkan/wsi/wsi_common_x11.c
@@ -130,6 +130,8 @@ wsi_x11_connection_create(const VkAllocationCallbacks *alloc,
{
xcb_query_extension_cookie_t dri3_cookie, pres_cookie, amd_cookie, nv_cookie;
xcb_query_extension_reply_t *dri3_reply, *pres_reply, *amd_reply, *nv_reply;
+ bool has_dri3_v1_2 = false;
+ bool has_present_v1_2 = false;
struct wsi_x11_connection *wsi_conn =
vk_alloc(alloc, sizeof(*wsi_conn), 8,
@@ -138,7 +140,7 @@ wsi_x11_connection_create(const VkAllocationCallbacks *alloc,
return NULL;
dri3_cookie = xcb_query_extension(conn, 4, "DRI3");
- pres_cookie = xcb_query_extension(conn, 7, "PRESENT");
+ pres_cookie = xcb_query_extension(conn, 7, "Present");
/* We try to be nice to users and emit a warning if they try to use a
* Vulkan application on a system without DRI3 enabled. However, this ends
@@ -172,12 +174,24 @@ wsi_x11_connection_create(const VkAllocationCallbacks *alloc,
ver_cookie = xcb_dri3_query_version(conn, 1, 2);
ver_reply = xcb_dri3_query_version_reply(conn, ver_cookie, NULL);
- wsi_conn->has_dri3_modifiers =
+ has_dri3_v1_2 =
(ver_reply->major_version > 1 || ver_reply->minor_version >= 2);
free(ver_reply);
}
wsi_conn->has_present = pres_reply->present != 0;
+ if (wsi_conn->has_present) {
+ xcb_present_query_version_cookie_t ver_cookie;
+ xcb_present_query_version_reply_t *ver_reply;
+
+ ver_cookie = xcb_present_query_version(conn, 1, 2);
+ ver_reply = xcb_present_query_version_reply(conn, ver_cookie, NULL);
+ has_present_v1_2 =
+ (ver_reply->major_version > 1 || ver_reply->minor_version >= 2);
+ free(ver_reply);
+ }
+
+ wsi_conn->has_dri3_modifiers = has_dri3_v1_2 && has_present_v1_2;
wsi_conn->is_proprietary_x11 = false;
if (amd_reply && amd_reply->present)
wsi_conn->is_proprietary_x11 = true;
@@ -649,6 +663,7 @@ struct x11_swapchain {
bool threaded;
VkResult status;
+ xcb_present_complete_mode_t last_present_mode;
struct wsi_queue present_queue;
struct wsi_queue acquire_queue;
pthread_t queue_manager;
@@ -682,6 +697,14 @@ x11_swapchain_result(struct x11_swapchain *chain, VkResult result)
if (result == VK_TIMEOUT || result == VK_NOT_READY)
return result;
+ /* Suboptimal isn't an error, but is a status which sticks to the swapchain
+ * and is always returned rather than success.
+ */
+ if (result == VK_SUBOPTIMAL_KHR) {
+ chain->status = result;
+ return result;
+ }
+
/* No changes, so return the last status. */
return chain->status;
}
@@ -730,7 +753,26 @@ x11_handle_dri3_present_event(struct x11_swapchain *chain,
xcb_present_complete_notify_event_t *complete = (void *) event;
if (complete->kind == XCB_PRESENT_COMPLETE_KIND_PIXMAP)
chain->last_present_msc = complete->msc;
- break;
+
+ VkResult result = VK_SUCCESS;
+
+ /* The winsys is now trying to flip directly and cannot due to our
+ * configuration. Request the user reallocate.
+ */
+ if (complete->mode == XCB_PRESENT_COMPLETE_MODE_SUBOPTIMAL_COPY &&
+ chain->last_present_mode != XCB_PRESENT_COMPLETE_MODE_SUBOPTIMAL_COPY)
+ result = VK_SUBOPTIMAL_KHR;
+
+ /* When we go from flipping to copying, the odds are very likely that
+ * we could reallocate in a more optimal way if we didn't have to care
+ * about scanout, so we always do this.
+ */
+ if (complete->mode == XCB_PRESENT_COMPLETE_MODE_COPY &&
+ chain->last_present_mode == XCB_PRESENT_COMPLETE_MODE_FLIP)
+ result = VK_SUBOPTIMAL_KHR;
+
+ chain->last_present_mode = complete->mode;
+ return result;
}
default:
@@ -866,6 +908,9 @@ x11_present_to_x11(struct x11_swapchain *chain, uint32_t image_index,
if (chain->base.present_mode == VK_PRESENT_MODE_IMMEDIATE_KHR)
options |= XCB_PRESENT_OPTION_ASYNC;
+ if (chain->has_dri3_modifiers)
+ options |= XCB_PRESENT_OPTION_SUBOPTIMAL;
+
xshmfence_reset(image->shm_fence);
++chain->send_sbc;
@@ -1261,6 +1306,18 @@ x11_surface_create_swapchain(VkIcdSurfaceBase *icd_surface,
chain->status = VK_SUCCESS;
chain->has_dri3_modifiers = wsi_conn->has_dri3_modifiers;
+ /* If we are reallocating from an old swapchain, then we inherit its
+ * last completion mode, to ensure we don't get into reallocation
+ * cycles. If we are starting anew, we set 'COPY', as that is the only
+ * mode which provokes reallocation when anything changes, to make
+ * sure we have the most optimal allocation.
+ */
+ struct x11_swapchain *old_chain = (void *) pCreateInfo->oldSwapchain;
+ if (old_chain)
+ chain->last_present_mode = old_chain->last_present_mode;
+ else
+ chain->last_present_mode = XCB_PRESENT_COMPLETE_MODE_COPY;
+
if (!wsi_x11_check_dri3_compatible(conn, local_fd))
chain->base.use_prime_blit = true;