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:
parent
8738ce85df
commit
6b016d58d2
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user