diff --git a/hw/xwayland/xwayland-present.c b/hw/xwayland/xwayland-present.c index 31c276623..baa97d6f3 100644 --- a/hw/xwayland/xwayland-present.c +++ b/hw/xwayland/xwayland-present.c @@ -60,6 +60,7 @@ xwl_present_window_get_priv(WindowPtr window) xwl_present_window->msc = 1; xwl_present_window->ust = GetTimeInMicros(); + xorg_list_init(&xwl_present_window->frame_callback_list); xorg_list_init(&xwl_present_window->event_list); xorg_list_init(&xwl_present_window->release_queue); @@ -96,7 +97,7 @@ xwl_present_reset_timer(struct xwl_present_window *xwl_present_window) if (xwl_present_has_events(xwl_present_window)) { CARD32 timeout; - if (xwl_present_window->frame_callback) + if (!xorg_list_is_empty(&xwl_present_window->frame_callback_list)) timeout = TIMER_LEN_FLIP; else timeout = TIMER_LEN_COPY; @@ -119,10 +120,7 @@ xwl_present_cleanup(WindowPtr window) if (!xwl_present_window) return; - if (xwl_present_window->frame_callback) { - wl_callback_destroy(xwl_present_window->frame_callback); - xwl_present_window->frame_callback = NULL; - } + xorg_list_del(&xwl_present_window->frame_callback_list); if (xwl_present_window->sync_callback) { wl_callback_destroy(xwl_present_window->sync_callback); @@ -252,15 +250,10 @@ xwl_present_timer_callback(OsTimerPtr timer, return 0; } -static void -xwl_present_frame_callback(void *data, - struct wl_callback *callback, - uint32_t time) +void +xwl_present_frame_callback(struct xwl_present_window *xwl_present_window) { - struct xwl_present_window *xwl_present_window = data; - - wl_callback_destroy(xwl_present_window->frame_callback); - xwl_present_window->frame_callback = NULL; + xorg_list_del(&xwl_present_window->frame_callback_list); if (xwl_present_window->frame_timer_firing) { /* If the timer is firing, this frame callback is too late */ @@ -275,10 +268,6 @@ xwl_present_frame_callback(void *data, xwl_present_reset_timer(xwl_present_window); } -static const struct wl_callback_listener xwl_present_frame_listener = { - xwl_present_frame_callback -}; - static void xwl_present_sync_callback(void *data, struct wl_callback *callback, @@ -488,11 +477,12 @@ xwl_present_flip(WindowPtr present_window, /* We can flip directly to the main surface (full screen window without clips) */ wl_surface_attach(xwl_window->surface, buffer, 0, 0); - if (!xwl_present_window->frame_callback) { - xwl_present_window->frame_callback = wl_surface_frame(xwl_window->surface); - wl_callback_add_listener(xwl_present_window->frame_callback, - &xwl_present_frame_listener, - xwl_present_window); + if (!xwl_window->frame_callback) + xwl_window_create_frame_callback(xwl_window); + + if (xorg_list_is_empty(&xwl_present_window->frame_callback_list)) { + xorg_list_add(&xwl_present_window->frame_callback_list, + &xwl_window->frame_callback_list); } /* Realign timer */ @@ -532,14 +522,14 @@ xwl_present_unrealize_window(WindowPtr window) { struct xwl_present_window *xwl_present_window = xwl_present_window_priv(window); - if (!xwl_present_window || !xwl_present_window->frame_callback) + if (!xwl_present_window || + xorg_list_is_empty(&xwl_present_window->frame_callback_list)) return; /* The pending frame callback may never be called, so drop it and shorten * the frame timer interval. */ - wl_callback_destroy(xwl_present_window->frame_callback); - xwl_present_window->frame_callback = NULL; + xorg_list_del(&xwl_present_window->frame_callback_list); xwl_present_reset_timer(xwl_present_window); } diff --git a/hw/xwayland/xwayland.c b/hw/xwayland/xwayland.c index ef01842f0..feb1058b7 100644 --- a/hw/xwayland/xwayland.c +++ b/hw/xwayland/xwayland.c @@ -600,6 +600,10 @@ ensure_surface_for_window(WindowPtr window) dixSetPrivate(&window->devPrivates, &xwl_window_private_key, xwl_window); xorg_list_init(&xwl_window->link_damage); +#ifdef GLAMOR_HAS_GBM + xorg_list_init(&xwl_window->frame_callback_list); +#endif + xwl_window_init_allow_commits(xwl_window); return TRUE; @@ -684,11 +688,6 @@ xwl_unrealize_window(WindowPtr window) xwl_screen->UnrealizeWindow = screen->UnrealizeWindow; screen->UnrealizeWindow = xwl_unrealize_window; -#ifdef GLAMOR_HAS_GBM - if (xwl_screen->present) - xwl_present_unrealize_window(window); -#endif - xwl_window = xwl_window_get(window); if (!xwl_window) return ret; @@ -700,6 +699,11 @@ xwl_unrealize_window(WindowPtr window) if (xwl_window->frame_callback) wl_callback_destroy(xwl_window->frame_callback); +#ifdef GLAMOR_HAS_GBM + if (xwl_screen->present) + xwl_present_unrealize_window(window); +#endif + free(xwl_window); dixSetPrivate(&window->devPrivates, &xwl_window_private_key, NULL); @@ -741,6 +745,18 @@ frame_callback(void *data, wl_callback_destroy (xwl_window->frame_callback); xwl_window->frame_callback = NULL; + +#ifdef GLAMOR_HAS_GBM + if (xwl_window->xwl_screen->present) { + struct xwl_present_window *xwl_present_window, *tmp; + + xorg_list_for_each_entry_safe(xwl_present_window, tmp, + &xwl_window->frame_callback_list, + frame_callback_list) { + xwl_present_frame_callback(xwl_present_window); + } + } +#endif } static const struct wl_callback_listener frame_listener = { diff --git a/hw/xwayland/xwayland.h b/hw/xwayland/xwayland.h index d20016c5d..d4eb6bf1a 100644 --- a/hw/xwayland/xwayland.h +++ b/hw/xwayland/xwayland.h @@ -183,6 +183,7 @@ struct xwl_window { struct wl_callback *frame_callback; Bool allow_commits; #ifdef GLAMOR_HAS_GBM + struct xorg_list frame_callback_list; Bool present_flipped; #endif }; @@ -192,7 +193,7 @@ struct xwl_present_window { struct xwl_screen *xwl_screen; struct xwl_present_event *sync_flip; WindowPtr window; - struct xorg_list link; + struct xorg_list frame_callback_list; uint64_t msc; uint64_t ust; @@ -454,6 +455,7 @@ Bool xwl_glamor_allow_commits(struct xwl_window *xwl_window); void xwl_glamor_egl_make_current(struct xwl_screen *xwl_screen); #ifdef GLAMOR_HAS_GBM +void xwl_present_frame_callback(struct xwl_present_window *xwl_present_window); Bool xwl_present_init(ScreenPtr screen); void xwl_present_cleanup(WindowPtr window); void xwl_present_unrealize_window(WindowPtr window);