This patch enables Pixmap flips for child windows via Wayland sub-surfaces.
If the Wayland compositor doesn't support sub-surfaces we fall back to flips without sub-surfaces when possible as before. A small change to Present is necessary, to restore the window pixmap correctly after an unflip operation. Signed-off-by: Roman Gilg <subd...@gmail.com> --- hw/xwayland/xwayland-present.c | 44 ++++++++++++++++++++++++++++++++++++------ hw/xwayland/xwayland.c | 6 +++++- hw/xwayland/xwayland.h | 2 ++ present/present_winmode.c | 4 +--- 4 files changed, 46 insertions(+), 10 deletions(-) diff --git a/hw/xwayland/xwayland-present.c b/hw/xwayland/xwayland-present.c index c10128c..8fa6831 100644 --- a/hw/xwayland/xwayland-present.c +++ b/hw/xwayland/xwayland-present.c @@ -53,17 +53,25 @@ 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; - /* Clear remaining events */ + /* Clear remaining queued events */ xorg_list_for_each_entry_safe(event, tmp, &xwl_window->present_event_list, list) { xorg_list_del(&event->list); free(event); @@ -231,7 +239,9 @@ xwl_present_check_flip(RRCrtcPtr crtc, */ if (xwl_window->present_crtc_fake != crtc) return FALSE; - 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; @@ -246,11 +256,15 @@ xwl_present_flip(WindowPtr present_window, Bool sync_flip) { struct xwl_window *xwl_window = xwl_window_from_window(present_window); - BoxPtr present_box; + WindowPtr window = xwl_window->window; + struct xwl_screen *xwl_screen = xwl_window->xwl_screen; + BoxPtr win_box, present_box; Bool buffer_created; struct wl_buffer *buffer; struct xwl_present_event *event; + struct wl_region *input_region; + win_box = RegionExtents(&window->winSize); present_box = RegionExtents(&present_window->winSize); /* We always switch to another child window, if it wants to present. */ @@ -260,8 +274,21 @@ xwl_present_flip(WindowPtr present_window, xwl_window->present_window = present_window; xorg_list_add(&xwl_window->present_link, &xwl_present_windows); - /* We can flip directly to the main surface (full screen window without clips) */ - xwl_window->present_surface = xwl_window->surface; + if (RegionEqual(&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_window->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_desync(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); @@ -270,6 +297,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 2182c71..18e5b8b 100644 --- a/hw/xwayland/xwayland.c +++ b/hw/xwayland/xwayland.c @@ -659,7 +659,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. */ @@ -683,6 +683,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 0969043..166ba9b 100644 --- a/hw/xwayland/xwayland.h +++ b/hw/xwayland/xwayland.h @@ -77,6 +77,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; @@ -120,6 +121,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; struct wl_callback *present_frame_callback; struct xorg_list present_event_list; diff --git a/present/present_winmode.c b/present/present_winmode.c index 3027db7..8e98634 100644 --- a/present/present_winmode.c +++ b/present/present_winmode.c @@ -123,7 +123,6 @@ present_winmode_restore_window_pixmap(WindowPtr window) flip_pixmap = window_priv->flip_pending ? window_priv->flip_pending->pixmap : window_priv->flip_active->pixmap; - assert (flip_pixmap); restore_pixmap = screen->GetWindowPixmap(window->parent); @@ -419,12 +418,11 @@ present_winmode_execute(present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_m RegionIntersect(damage, damage, &window->clipList); } else damage = &window->clipList; - DamageDamageRegion(&vblank->window->drawable, damage); + if (*screen_priv->winmode_info->flip_executed) (*screen_priv->winmode_info->flip_executed) (vblank->window, vblank->crtc, vblank->event_id, damage); - return; } -- 2.7.4 _______________________________________________ xorg-devel@lists.x.org: X.Org development Archives: http://lists.x.org/archives/xorg-devel Info: https://lists.x.org/mailman/listinfo/xorg-devel