mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-24 00:10:10 +01:00
wsi/x11: Avoid using xcb_wait_for_special_event in FIFO modes
If the window is destroyed from underneath us while we happen to be in xcb_wait_for_special_event, there's no recovery. The special event will never match because the XID is no longer valid, and Present doesn't have an in-band DestroyNotify. We're going to work around this by using the poll API instead. If we get an event we short-circuit back to the top of the "wait for available image" loop, so we drain the whole special event queue before any other logic. Which means if we run out of special events (and the connection and swapchain are still valid) that we _don't_ have enough images available, so to hurry along any events that the X server hasn't flushed out yet we call GetGeometry on the swapchain's window. As a side effect this verifies that the window is still alive. Reviewed-By: Mike Blumenkrantz <michael.blumenkrantz@gmail.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/15800>
This commit is contained in:
parent
260cd1a18b
commit
44a20baeb8
1 changed files with 27 additions and 8 deletions
|
|
@ -1457,25 +1457,44 @@ x11_manage_fifo_queues(void *state)
|
|||
goto fail;
|
||||
|
||||
if (chain->has_acquire_queue) {
|
||||
xcb_generic_event_t *event = NULL;
|
||||
xcb_connection_t *conn = chain->conn;
|
||||
|
||||
/* Wait for our presentation to occur and ensure we have at least one
|
||||
* image that can be acquired by the client afterwards. This ensures we
|
||||
* can pull on the present-queue on the next loop.
|
||||
*/
|
||||
while (chain->images[image_index].present_queued ||
|
||||
chain->sent_image_count == chain->base.image_count) {
|
||||
xcb_generic_event_t *event =
|
||||
xcb_wait_for_special_event(chain->conn, chain->special_event);
|
||||
if (!event) {
|
||||
|
||||
event = xcb_poll_for_special_event(conn, chain->special_event);
|
||||
if (event) {
|
||||
result = x11_handle_dri3_present_event(chain, (void *)event);
|
||||
/* Ensure that VK_SUBOPTIMAL_KHR is reported to the application */
|
||||
result = x11_swapchain_result(chain, result);
|
||||
free(event);
|
||||
if (result < 0)
|
||||
goto fail;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (chain->status < 0 || xcb_connection_has_error(conn)) {
|
||||
result = VK_ERROR_SURFACE_LOST_KHR;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
result = x11_handle_dri3_present_event(chain, (void *)event);
|
||||
/* Ensure that VK_SUBOPTIMAL_KHR is reported to the application */
|
||||
result = x11_swapchain_result(chain, result);
|
||||
free(event);
|
||||
if (result < 0)
|
||||
/* poke the window to see if it got destroyed from under us, and
|
||||
* to flush any pending special events out of the server
|
||||
*/
|
||||
xcb_get_geometry_reply_t *geometry =
|
||||
xcb_get_geometry_reply(conn,
|
||||
xcb_get_geometry(conn, chain->window),
|
||||
NULL);
|
||||
if (geometry == NULL) {
|
||||
result = VK_ERROR_SURFACE_LOST_KHR;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue