xwayland: Complete "synchronous" Present flips from xwl_present_msc_bump
Completing them from xwl_present_sync_callback had at least two issues: * It was before the MSC was incremented in xwl_present_frame_callback, so the MSC value in the completion event could be lower than the target specified by the client. This could cause hangs with the Mesa Vulkan drivers. * It allowed clients to run at a frame-rate higher than the Wayland compositor's frame-rate, wasting energy on generating frames which were never displayed. This isn't expected to happen unless the client specified PresentOptionAsync (in which case flips are still completed from xwl_present_sync_callback, allowing higher frame-rates). v2: * Make xwl_present_has_events return true when there's a pending "synchronous" flip, so those complete after at most ~1 second even if the Wayland server doesn't send a frame event. Bugzilla: https://bugs.freedesktop.org/106713
This commit is contained in:
parent
2bfc46d414
commit
ace551d8a2
|
@ -85,7 +85,8 @@ xwl_present_timer_callback(OsTimerPtr timer,
|
||||||
static inline Bool
|
static inline Bool
|
||||||
xwl_present_has_events(struct xwl_present_window *xwl_present_window)
|
xwl_present_has_events(struct xwl_present_window *xwl_present_window)
|
||||||
{
|
{
|
||||||
return !xorg_list_is_empty(&xwl_present_window->event_list) ||
|
return !!xwl_present_window->sync_flip ||
|
||||||
|
!xorg_list_is_empty(&xwl_present_window->event_list) ||
|
||||||
!xorg_list_is_empty(&xwl_present_window->release_queue);
|
!xorg_list_is_empty(&xwl_present_window->release_queue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,6 +140,16 @@ xwl_present_cleanup(WindowPtr window)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Clear remaining buffer releases and inform Present about free ressources */
|
/* Clear remaining buffer releases and inform Present about free ressources */
|
||||||
|
event = xwl_present_window->sync_flip;
|
||||||
|
xwl_present_window->sync_flip = NULL;
|
||||||
|
if (event) {
|
||||||
|
if (event->buffer_released) {
|
||||||
|
free(event);
|
||||||
|
} else {
|
||||||
|
event->pending = FALSE;
|
||||||
|
event->abort = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
xorg_list_for_each_entry_safe(event, tmp, &xwl_present_window->release_queue, list) {
|
xorg_list_for_each_entry_safe(event, tmp, &xwl_present_window->release_queue, list) {
|
||||||
xorg_list_del(&event->list);
|
xorg_list_del(&event->list);
|
||||||
event->abort = TRUE;
|
event->abort = TRUE;
|
||||||
|
@ -199,6 +210,24 @@ xwl_present_msc_bump(struct xwl_present_window *xwl_present_window)
|
||||||
|
|
||||||
xwl_present_window->ust = GetTimeInMicros();
|
xwl_present_window->ust = GetTimeInMicros();
|
||||||
|
|
||||||
|
event = xwl_present_window->sync_flip;
|
||||||
|
xwl_present_window->sync_flip = NULL;
|
||||||
|
if (event) {
|
||||||
|
event->pending = FALSE;
|
||||||
|
|
||||||
|
present_wnmd_event_notify(xwl_present_window->window, event->event_id,
|
||||||
|
xwl_present_window->ust, msc);
|
||||||
|
|
||||||
|
if (event->buffer_released) {
|
||||||
|
/* If the buffer was already released, clean up now */
|
||||||
|
present_wnmd_event_notify(xwl_present_window->window, event->event_id,
|
||||||
|
xwl_present_window->ust, msc);
|
||||||
|
free(event);
|
||||||
|
} else {
|
||||||
|
xorg_list_add(&event->list, &xwl_present_window->release_queue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
xorg_list_for_each_entry_safe(event, tmp,
|
xorg_list_for_each_entry_safe(event, tmp,
|
||||||
&xwl_present_window->event_list,
|
&xwl_present_window->event_list,
|
||||||
list) {
|
list) {
|
||||||
|
@ -459,12 +488,17 @@ xwl_present_flip(WindowPtr present_window,
|
||||||
event->event_id = event_id;
|
event->event_id = event_id;
|
||||||
event->xwl_present_window = xwl_present_window;
|
event->xwl_present_window = xwl_present_window;
|
||||||
event->buffer = buffer;
|
event->buffer = buffer;
|
||||||
event->target_msc = xwl_present_window->msc;
|
event->target_msc = target_msc;
|
||||||
event->pending = TRUE;
|
event->pending = TRUE;
|
||||||
event->abort = FALSE;
|
event->abort = FALSE;
|
||||||
event->buffer_released = FALSE;
|
event->buffer_released = FALSE;
|
||||||
|
|
||||||
xorg_list_add(&event->list, &xwl_present_window->release_queue);
|
if (sync_flip) {
|
||||||
|
xorg_list_init(&event->list);
|
||||||
|
xwl_present_window->sync_flip = event;
|
||||||
|
} else {
|
||||||
|
xorg_list_add(&event->list, &xwl_present_window->release_queue);
|
||||||
|
}
|
||||||
|
|
||||||
if (buffer_created)
|
if (buffer_created)
|
||||||
wl_buffer_add_listener(buffer, &xwl_present_release_listener, NULL);
|
wl_buffer_add_listener(buffer, &xwl_present_release_listener, NULL);
|
||||||
|
@ -493,10 +527,13 @@ xwl_present_flip(WindowPtr present_window,
|
||||||
|
|
||||||
wl_surface_commit(xwl_window->surface);
|
wl_surface_commit(xwl_window->surface);
|
||||||
|
|
||||||
xwl_present_window->sync_callback = wl_display_sync(xwl_window->xwl_screen->display);
|
if (!sync_flip) {
|
||||||
wl_callback_add_listener(xwl_present_window->sync_callback,
|
xwl_present_window->sync_callback =
|
||||||
&xwl_present_sync_listener,
|
wl_display_sync(xwl_window->xwl_screen->display);
|
||||||
event);
|
wl_callback_add_listener(xwl_present_window->sync_callback,
|
||||||
|
&xwl_present_sync_listener,
|
||||||
|
event);
|
||||||
|
}
|
||||||
|
|
||||||
wl_display_flush(xwl_window->xwl_screen->display);
|
wl_display_flush(xwl_window->xwl_screen->display);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
|
@ -188,6 +188,7 @@ struct xwl_window {
|
||||||
#ifdef GLAMOR_HAS_GBM
|
#ifdef GLAMOR_HAS_GBM
|
||||||
struct xwl_present_window {
|
struct xwl_present_window {
|
||||||
struct xwl_screen *xwl_screen;
|
struct xwl_screen *xwl_screen;
|
||||||
|
struct xwl_present_event *sync_flip;
|
||||||
WindowPtr window;
|
WindowPtr window;
|
||||||
struct xorg_list link;
|
struct xorg_list link;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue