xwayland: Replace xwl_window::present_window with ::present_flipped

There's no need to keep track of the window which last performed a
Present flip. This fixes crashes due to the assertion in
xwl_present_flips_stop failing. Fixes issue #10.

The damage generated by a flip only needs to be ignored once, then
xwl_window::present_flipped can be cleared. This may fix freezing in
the (hypothetical) scenario where Present flips are performed on a
window, followed by other drawing requests using the window as the
destination, but nothing triggering xwl_present_flips_stop. The damage
from the latter drawing requests would continue being ignored.
This commit is contained in:
Michel Dänzer 2018-11-01 18:44:24 +01:00 committed by Adam Jackson
parent 8738ce85df
commit 6b016d58d2
3 changed files with 27 additions and 50 deletions

View File

@ -90,24 +90,19 @@ xwl_present_has_events(struct xwl_present_window *xwl_present_window)
!xorg_list_is_empty(&xwl_present_window->release_queue); !xorg_list_is_empty(&xwl_present_window->release_queue);
} }
static inline Bool
xwl_present_is_flipping(WindowPtr window, struct xwl_window *xwl_window)
{
return xwl_window && xwl_window->present_window == window;
}
static void static void
xwl_present_reset_timer(struct xwl_present_window *xwl_present_window) xwl_present_reset_timer(struct xwl_present_window *xwl_present_window)
{ {
if (xwl_present_has_events(xwl_present_window)) { if (xwl_present_has_events(xwl_present_window)) {
WindowPtr present_window = xwl_present_window->window; CARD32 timeout;
Bool is_flipping = xwl_present_is_flipping(present_window,
xwl_window_from_window(present_window)); if (xwl_present_window->frame_callback)
timeout = TIMER_LEN_FLIP;
else
timeout = TIMER_LEN_COPY;
xwl_present_window->frame_timer = TimerSet(xwl_present_window->frame_timer, xwl_present_window->frame_timer = TimerSet(xwl_present_window->frame_timer,
0, 0, timeout,
is_flipping ? TIMER_LEN_FLIP :
TIMER_LEN_COPY,
&xwl_present_timer_callback, &xwl_present_timer_callback,
xwl_present_window); xwl_present_window);
} else { } else {
@ -118,16 +113,12 @@ xwl_present_reset_timer(struct xwl_present_window *xwl_present_window)
void void
xwl_present_cleanup(WindowPtr window) xwl_present_cleanup(WindowPtr window)
{ {
struct xwl_window *xwl_window = xwl_window_from_window(window);
struct xwl_present_window *xwl_present_window = xwl_present_window_priv(window); struct xwl_present_window *xwl_present_window = xwl_present_window_priv(window);
struct xwl_present_event *event, *tmp; struct xwl_present_event *event, *tmp;
if (!xwl_present_window) if (!xwl_present_window)
return; return;
if (xwl_window && xwl_window->present_window == window)
xwl_window->present_window = NULL;
if (xwl_present_window->frame_callback) { if (xwl_present_window->frame_callback) {
wl_callback_destroy(xwl_present_window->frame_callback); wl_callback_destroy(xwl_present_window->frame_callback);
xwl_present_window->frame_callback = NULL; xwl_present_window->frame_callback = NULL;
@ -366,10 +357,6 @@ xwl_present_queue_vblank(WindowPtr present_window,
if (!xwl_window) if (!xwl_window)
return BadMatch; return BadMatch;
if (xwl_window->present_window &&
xwl_window->present_window != present_window)
return BadMatch;
event = malloc(sizeof *event); event = malloc(sizeof *event);
if (!event) if (!event)
return BadAlloc; return BadAlloc;
@ -438,13 +425,6 @@ xwl_present_check_flip2(RRCrtcPtr crtc,
if (!xwl_window) if (!xwl_window)
return FALSE; return FALSE;
/*
* Do not flip if there is already another child window doing flips.
*/
if (xwl_window->present_window &&
xwl_window->present_window != present_window)
return FALSE;
/* /*
* We currently only allow flips of windows, that have the same * We currently only allow flips of windows, that have the same
* dimensions as their xwl_window parent window. For the case of * dimensions as their xwl_window parent window. For the case of
@ -481,8 +461,6 @@ xwl_present_flip(WindowPtr present_window,
if (!event) if (!event)
return FALSE; return FALSE;
xwl_window->present_window = present_window;
buffer = xwl_glamor_pixmap_get_wl_buffer(pixmap, &buffer_created); buffer = xwl_glamor_pixmap_get_wl_buffer(pixmap, &buffer_created);
event->event_id = event_id; event->event_id = event_id;
@ -507,13 +485,6 @@ xwl_present_flip(WindowPtr present_window,
/* We can flip directly to the main surface (full screen window without clips) */ /* We can flip directly to the main surface (full screen window without clips) */
wl_surface_attach(xwl_window->surface, buffer, 0, 0); wl_surface_attach(xwl_window->surface, buffer, 0, 0);
if (!xwl_present_window->frame_timer ||
xwl_present_window->frame_timer_firing) {
/* Realign timer */
xwl_present_window->frame_timer_firing = FALSE;
xwl_present_reset_timer(xwl_present_window);
}
if (!xwl_present_window->frame_callback) { if (!xwl_present_window->frame_callback) {
xwl_present_window->frame_callback = wl_surface_frame(xwl_window->surface); xwl_present_window->frame_callback = wl_surface_frame(xwl_window->surface);
wl_callback_add_listener(xwl_present_window->frame_callback, wl_callback_add_listener(xwl_present_window->frame_callback,
@ -521,6 +492,10 @@ xwl_present_flip(WindowPtr present_window,
xwl_present_window); xwl_present_window);
} }
/* Realign timer */
xwl_present_window->frame_timer_firing = FALSE;
xwl_present_reset_timer(xwl_present_window);
wl_surface_damage(xwl_window->surface, 0, 0, wl_surface_damage(xwl_window->surface, 0, 0,
damage_box->x2 - damage_box->x1, damage_box->x2 - damage_box->x1,
damage_box->y2 - damage_box->y1); damage_box->y2 - damage_box->y1);
@ -536,22 +511,15 @@ xwl_present_flip(WindowPtr present_window,
} }
wl_display_flush(xwl_window->xwl_screen->display); wl_display_flush(xwl_window->xwl_screen->display);
xwl_window->present_flipped = TRUE;
return TRUE; return TRUE;
} }
static void static void
xwl_present_flips_stop(WindowPtr window) xwl_present_flips_stop(WindowPtr window)
{ {
struct xwl_window *xwl_window = xwl_window_from_window(window);
struct xwl_present_window *xwl_present_window = xwl_present_window_priv(window); struct xwl_present_window *xwl_present_window = xwl_present_window_priv(window);
if (!xwl_window)
return;
assert(xwl_window->present_window == window);
xwl_window->present_window = NULL;
/* Change back to the fast refresh rate */ /* Change back to the fast refresh rate */
xwl_present_reset_timer(xwl_present_window); xwl_present_reset_timer(xwl_present_window);
} }

View File

@ -377,6 +377,18 @@ damage_report(DamagePtr pDamage, RegionPtr pRegion, void *data)
struct xwl_window *xwl_window = data; struct xwl_window *xwl_window = data;
struct xwl_screen *xwl_screen = xwl_window->xwl_screen; struct xwl_screen *xwl_screen = xwl_window->xwl_screen;
#ifdef GLAMOR_HAS_GBM
if (xwl_window->present_flipped) {
/* This damage is from a Present flip, which already committed a new
* buffer for the surface, so we don't need to do anything in response
*/
RegionEmpty(DamageRegion(pDamage));
xorg_list_del(&xwl_window->link_damage);
xwl_window->present_flipped = FALSE;
return;
}
#endif
xorg_list_add(&xwl_window->link_damage, &xwl_screen->damage_window_list); xorg_list_add(&xwl_window->link_damage, &xwl_screen->damage_window_list);
} }
@ -722,11 +734,6 @@ xwl_screen_post_damage(struct xwl_screen *xwl_screen)
xorg_list_for_each_entry_safe(xwl_window, next_xwl_window, xorg_list_for_each_entry_safe(xwl_window, next_xwl_window,
&xwl_screen->damage_window_list, link_damage) { &xwl_screen->damage_window_list, link_damage) {
#ifdef GLAMOR_HAS_GBM
/* Present on the main surface. So don't commit here as well. */
if (xwl_window->present_window)
continue;
#endif
/* If we're waiting on a frame callback from the server, /* If we're waiting on a frame callback from the server,
* don't attach a new buffer. */ * don't attach a new buffer. */
if (xwl_window->frame_callback) if (xwl_window->frame_callback)

View File

@ -179,7 +179,9 @@ struct xwl_window {
struct xorg_list link_damage; struct xorg_list link_damage;
struct wl_callback *frame_callback; struct wl_callback *frame_callback;
Bool allow_commits; Bool allow_commits;
WindowPtr present_window; #ifdef GLAMOR_HAS_GBM
Bool present_flipped;
#endif
}; };
#ifdef GLAMOR_HAS_GBM #ifdef GLAMOR_HAS_GBM