diff options
Diffstat (limited to 'hw/xwayland/xwayland-present.c')
-rw-r--r-- | hw/xwayland/xwayland-present.c | 137 |
1 files changed, 65 insertions, 72 deletions
diff --git a/hw/xwayland/xwayland-present.c b/hw/xwayland/xwayland-present.c index 2937d9c97..6076f6498 100644 --- a/hw/xwayland/xwayland-present.c +++ b/hw/xwayland/xwayland-present.c @@ -24,6 +24,7 @@ */ #include "xwayland.h" +#include "glamor.h" #include <present.h> @@ -59,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); @@ -95,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; @@ -109,6 +111,27 @@ xwl_present_reset_timer(struct xwl_present_window *xwl_present_window) } } +static void +xwl_present_free_event(struct xwl_present_event *event) +{ + if (!event) + return; + + if (event->pixmap) { + if (!event->buffer_released) { + struct wl_buffer *buffer = + xwl_glamor_pixmap_get_wl_buffer(event->pixmap, NULL); + + wl_buffer_set_user_data(buffer, NULL); + } + + dixDestroyPixmap(event->pixmap, event->pixmap->drawable.id); + } + + xorg_list_del(&event->list); + free(event); +} + void xwl_present_cleanup(WindowPtr window) { @@ -118,10 +141,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); @@ -129,26 +149,13 @@ xwl_present_cleanup(WindowPtr window) } /* Clear remaining events */ - xorg_list_for_each_entry_safe(event, tmp, &xwl_present_window->event_list, list) { - xorg_list_del(&event->list); - free(event); - } + xorg_list_for_each_entry_safe(event, tmp, &xwl_present_window->event_list, list) + xwl_present_free_event(event); - /* 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_del(&event->list); - event->abort = TRUE; - } + xwl_present_free_event(xwl_present_window->sync_flip); + + xorg_list_for_each_entry_safe(event, tmp, &xwl_present_window->release_queue, list) + xwl_present_free_event(event); /* Clear timer */ xwl_present_free_timer(xwl_present_window); @@ -162,13 +169,6 @@ xwl_present_cleanup(WindowPtr window) } static void -xwl_present_free_event(struct xwl_present_event *event) -{ - xorg_list_del(&event->list); - free(event); -} - -static void xwl_present_buffer_release(void *data, struct wl_buffer *buffer) { struct xwl_present_event *event = data; @@ -217,7 +217,7 @@ xwl_present_msc_bump(struct xwl_present_window *xwl_present_window) /* 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); + xwl_present_free_event(event); } else { xorg_list_add(&event->list, &xwl_present_window->release_queue); } @@ -243,7 +243,10 @@ xwl_present_timer_callback(OsTimerPtr timer, { struct xwl_present_window *xwl_present_window = arg; - xwl_present_window->frame_timer_firing = TRUE; + /* If we were expecting a frame callback for this window, it didn't arrive + * in a second. Stop listening to it to avoid double-bumping the MSC + */ + xorg_list_del(&xwl_present_window->frame_callback_list); xwl_present_msc_bump(xwl_present_window); xwl_present_reset_timer(xwl_present_window); @@ -251,20 +254,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; - - if (xwl_present_window->frame_timer_firing) { - /* If the timer is firing, this frame callback is too late */ - return; - } + xorg_list_del(&xwl_present_window->frame_callback_list); xwl_present_msc_bump(xwl_present_window); @@ -274,10 +267,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, @@ -359,6 +348,7 @@ xwl_present_queue_vblank(WindowPtr present_window, uint64_t msc) { struct xwl_present_window *xwl_present_window = xwl_present_window_get_priv(present_window); + struct xwl_window *xwl_window = xwl_window_from_window(present_window); struct xwl_present_event *event; event = malloc(sizeof *event); @@ -366,12 +356,21 @@ xwl_present_queue_vblank(WindowPtr present_window, return BadAlloc; event->event_id = event_id; + event->pixmap = NULL; event->xwl_present_window = xwl_present_window; event->target_msc = msc; xorg_list_append(&event->list, &xwl_present_window->event_list); - if (!xwl_present_window->frame_timer) + /* If there's a pending frame callback, use that */ + if (xwl_window && xwl_window->frame_callback && + xorg_list_is_empty(&xwl_present_window->frame_callback_list)) { + xorg_list_add(&xwl_present_window->frame_callback_list, + &xwl_window->frame_callback_list); + } + + if ((xwl_window && xwl_window->frame_callback) || + !xwl_present_window->frame_timer) xwl_present_reset_timer(xwl_present_window); return Success; @@ -395,8 +394,7 @@ xwl_present_abort_vblank(WindowPtr present_window, xorg_list_for_each_entry_safe(event, tmp, &xwl_present_window->event_list, list) { if (event->event_id == event_id) { - xorg_list_del(&event->list); - free(event); + xwl_present_free_event(event); return; } } @@ -412,9 +410,7 @@ xwl_present_abort_vblank(WindowPtr present_window, static void xwl_present_flush(WindowPtr window) { - /* Only called when a Pixmap is copied instead of flipped, - * but in this case we wait on the next block_handler. - */ + glamor_block_handler(window->drawable.pScreen); } static Bool @@ -465,11 +461,12 @@ xwl_present_flip(WindowPtr present_window, if (!event) return FALSE; + pixmap->refcnt++; buffer = xwl_glamor_pixmap_get_wl_buffer(pixmap, &buffer_created); event->event_id = event_id; event->xwl_present_window = xwl_present_window; - event->buffer = buffer; + event->pixmap = pixmap; event->target_msc = target_msc; event->pending = TRUE; event->abort = FALSE; @@ -489,18 +486,20 @@ 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 */ - 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, + damage_box->x1 - present_window->drawable.x, + damage_box->y1 - present_window->drawable.y, damage_box->x2 - damage_box->x1, damage_box->y2 - damage_box->y1); @@ -529,18 +528,12 @@ xwl_present_flips_stop(WindowPtr window) } void -xwl_present_unrealize_window(WindowPtr window) +xwl_present_unrealize_window(struct xwl_present_window *xwl_present_window) { - struct xwl_present_window *xwl_present_window = xwl_present_window_priv(window); - - if (!xwl_present_window || !xwl_present_window->frame_callback) - 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); } |