[PATCH 5/5] xwayland: Pixmap flips of child windows on sub-surfaces
Roman Gilg
subdiff at gmail.com
Tue Aug 29 15:24:32 UTC 2017
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 <subdiff at 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
More information about the xorg-devel
mailing list