Do flips for child windows via subsurfaces if the Wayland server supports them.
Signed-off-by: Roman Gilg <subd...@gmail.com> --- hw/xwayland/xwayland-present.c | 57 +++++++++++++++++++++++++++++++++--------- hw/xwayland/xwayland.c | 6 ++++- hw/xwayland/xwayland.h | 2 ++ present/present_wnmd.c | 23 ----------------- 4 files changed, 52 insertions(+), 36 deletions(-) diff --git a/hw/xwayland/xwayland-present.c b/hw/xwayland/xwayland-present.c index d08c39e..f68bf92 100644 --- a/hw/xwayland/xwayland-present.c +++ b/hw/xwayland/xwayland-present.c @@ -55,15 +55,22 @@ xwl_present_cleanup(WindowPtr window) * And therefore need to cleanup. */ + /* Clear frame callback */ if (xwl_window->present_frame_callback) { wl_callback_destroy(xwl_window->present_frame_callback); xwl_window->present_frame_callback = NULL; } + /* Clear surfaces */ + if (xwl_window->present_subsurface) { + wl_subsurface_destroy(xwl_window->present_subsurface); + wl_surface_destroy(xwl_window->present_surface); + xwl_window->present_subsurface = NULL; + } + xwl_window->present_surface = NULL; + /* Reset base data */ xorg_list_del(&xwl_window->present_link); - - xwl_window->present_surface = NULL; xwl_window->present_window = NULL; TimerFree(xwl_window->present_frame_timer); @@ -299,29 +306,31 @@ xwl_present_check_flip(RRCrtcPtr crtc, return FALSE; /* - * We currently only allow flips of windows, that have the same - * dimensions as their xwl_window parent window. For the case of - * different sizes subsurfaces are presumably the way forward. + * Allow different sizes for the presenting window and its associated + * xwl_window only if the Wayland server supports subsurfaces. */ - if (!RegionEqual(&xwl_window->window->winSize, &present_window->winSize)) + if (!RegionEqual(&xwl_window->window->winSize, &present_window->winSize) && + !xwl_window->xwl_screen->subcompositor) return FALSE; return TRUE; } -static void +static Bool xwl_present_reset_present_window(struct xwl_window *xwl_window, WindowPtr present_window) { /* Do not reset if it is the same present_window. But this also means, that * we always switch to another child window, if it wants to present. */ if (xwl_window->present_window == present_window) - return; + return FALSE; if (xwl_window->present_window) xwl_present_cleanup(xwl_window->present_window); xwl_window->present_window = present_window; xorg_list_add(&xwl_window->present_link, &xwl_present_windows); + + return TRUE; } static Bool @@ -334,18 +343,37 @@ xwl_present_flip(WindowPtr present_window, RegionPtr damage) { struct xwl_window *xwl_window = xwl_window_of_top(present_window); - BoxPtr present_box, damage_box; + BoxPtr win_box, present_box, damage_box; + struct xwl_screen *xwl_screen = xwl_window->xwl_screen; Bool buffer_created; struct wl_buffer *buffer; struct xwl_present_event *event; + struct wl_region *input_region; + win_box = RegionExtents(&xwl_window->window->winSize); present_box = RegionExtents(&present_window->winSize); damage_box = RegionExtents(damage); /* Potentially reset the presenting window */ - xwl_present_reset_present_window(xwl_window, present_window); - /* We can flip directly to the main surface (full screen window without clips) */ - xwl_window->present_surface = xwl_window->surface; + if ( xwl_present_reset_present_window(xwl_window, present_window) ) { + + if (RegionEqual(&xwl_window->window->winSize, &present_window->winSize)) { + /* We can flip directly to the main surface (full screen window without clips) */ + xwl_window->present_surface = xwl_window->surface; + } else { + xwl_window->present_surface = wl_compositor_create_surface(xwl_screen->compositor); + wl_surface_set_user_data(xwl_window->present_surface, xwl_window); + + xwl_window->present_subsurface = + wl_subcompositor_get_subsurface(xwl_screen->subcompositor, xwl_window->present_surface, xwl_window->surface); + wl_subsurface_set_sync(xwl_window->present_subsurface); + + input_region = wl_compositor_create_region(xwl_screen->compositor); + wl_surface_set_input_region(xwl_window->present_surface, input_region); + wl_region_destroy(input_region); + } + + } event = malloc(sizeof *event); if (!event) { @@ -353,6 +381,11 @@ xwl_present_flip(WindowPtr present_window, return FALSE; } + if (xwl_window->present_subsurface) + wl_subsurface_set_position(xwl_window->present_subsurface, + present_box->x1 - win_box->x1, + present_box->y1 - win_box->y1); + buffer = xwl_glamor_pixmap_get_wl_buffer(pixmap, present_box->x2 - present_box->x1, present_box->y2 - present_box->y1, diff --git a/hw/xwayland/xwayland.c b/hw/xwayland/xwayland.c index 386f11c..a83f718 100644 --- a/hw/xwayland/xwayland.c +++ b/hw/xwayland/xwayland.c @@ -698,7 +698,7 @@ xwl_screen_post_damage(struct xwl_screen *xwl_screen) xorg_list_for_each_entry_safe(xwl_window, next_xwl_window, &xwl_screen->damage_window_list, link_damage) { /* Present on the main surface. So don't commit here as well. */ - if (xwl_window->present_surface) + if (xwl_window->present_surface && !xwl_window->present_subsurface) continue; /* If we're waiting on a frame callback from the server, * don't attach a new buffer. */ @@ -722,6 +722,10 @@ registry_global(void *data, struct wl_registry *registry, uint32_t id, xwl_screen->compositor = wl_registry_bind(registry, id, &wl_compositor_interface, 1); } + else if (strcmp(interface, "wl_subcompositor") == 0) { + xwl_screen->subcompositor = + wl_registry_bind(registry, id, &wl_subcompositor_interface, 1); + } else if (strcmp(interface, "wl_shm") == 0) { xwl_screen->shm = wl_registry_bind(registry, id, &wl_shm_interface, 1); } diff --git a/hw/xwayland/xwayland.h b/hw/xwayland/xwayland.h index c294a92..464a90e 100644 --- a/hw/xwayland/xwayland.h +++ b/hw/xwayland/xwayland.h @@ -79,6 +79,7 @@ struct xwl_screen { struct wl_registry *registry; struct wl_registry *input_registry; struct wl_compositor *compositor; + struct wl_subcompositor *subcompositor; struct zwp_tablet_manager_v2 *tablet_manager; struct wl_shm *shm; struct wl_shell *shell; @@ -135,6 +136,7 @@ struct xwl_window { struct xorg_list present_link; WindowPtr present_window; struct wl_surface *present_surface; + struct wl_subsurface *present_subsurface; uint64_t present_msc; Bool present_frame_timer_firing; diff --git a/present/present_wnmd.c b/present/present_wnmd.c index 77f4f19..cec7855 100644 --- a/present/present_wnmd.c +++ b/present/present_wnmd.c @@ -120,24 +120,6 @@ present_wnmd_free_idle_vblanks(WindowPtr window) } } -static WindowPtr -present_wnmd_toplvl_pixmap_window(WindowPtr window) -{ - ScreenPtr screen = window->drawable.pScreen; - PixmapPtr pixmap = (*screen->GetWindowPixmap)(window); - WindowPtr w = window; - WindowPtr next_w; - - while(w->parent) { - next_w = w->parent; - if ( (*screen->GetWindowPixmap)(next_w) != pixmap) { - break; - } - w = next_w; - } - return w; -} - void present_wnmd_set_abort_flip(WindowPtr window) { @@ -257,7 +239,6 @@ present_wnmd_check_flip(RRCrtcPtr crtc, { ScreenPtr screen = window->drawable.pScreen; present_screen_priv_ptr screen_priv = present_screen_priv(screen); - WindowPtr toplvl_window = present_wnmd_toplvl_pixmap_window(window); if (!screen_priv) return FALSE; @@ -287,10 +268,6 @@ present_wnmd_check_flip(RRCrtcPtr crtc, window->drawable.height != pixmap->drawable.height) return FALSE; - /* Window must be same region as toplevel window */ - if ( !RegionEqual(&window->winSize, &toplvl_window->winSize) ) - return FALSE; - /* Ask the driver for permission */ if (screen_priv->wnmd_info->check_flip) { if (!(*screen_priv->wnmd_info->check_flip) (crtc, window, pixmap, sync_flip)) { -- 2.7.4 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev