<div dir="ltr">There is a mistake in the patch description since the mentioned small change to the Present extension code wasn't necessary in the end. So I reverted the change, but forgot about the description.</div><div class="gmail_extra"><br><div class="gmail_quote">On Tue, Aug 29, 2017 at 5:24 PM, Roman Gilg <span dir="ltr"><<a href="mailto:subdiff@gmail.com" target="_blank">subdiff@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">This patch enables Pixmap flips for child windows via Wayland<br>
sub-surfaces.<br>
<br>
If the Wayland compositor doesn't support sub-surfaces we fall back<br>
to flips without sub-surfaces when possible as before.<br>
<br>
A small change to Present is necessary, to restore the window pixmap<br>
correctly after an unflip operation.<br>
<br>
Signed-off-by: Roman Gilg <<a href="mailto:subdiff@gmail.com">subdiff@gmail.com</a>><br>
---<br>
 hw/xwayland/xwayland-present.c | 44 ++++++++++++++++++++++++++++++<wbr>++++++------<br>
 hw/xwayland/xwayland.c         |  6 +++++-<br>
 hw/xwayland/xwayland.h         |  2 ++<br>
 present/present_winmode.c      |  4 +---<br>
 4 files changed, 46 insertions(+), 10 deletions(-)<br>
<br>
diff --git a/hw/xwayland/xwayland-<wbr>present.c b/hw/xwayland/xwayland-<wbr>present.c<br>
index c10128c..8fa6831 100644<br>
--- a/hw/xwayland/xwayland-<wbr>present.c<br>
+++ b/hw/xwayland/xwayland-<wbr>present.c<br>
@@ -53,17 +53,25 @@ xwl_present_cleanup(WindowPtr window)<br>
      * And therefore need to cleanup.<br>
      */<br>
<br>
+    /* Clear frame callback */<br>
     if (xwl_window->present_frame_<wbr>callback) {<br>
         wl_callback_destroy(xwl_<wbr>window->present_frame_<wbr>callback);<br>
         xwl_window->present_frame_<wbr>callback = NULL;<br>
     }<br>
<br>
+    /* Clear surfaces */<br>
+    if (xwl_window->present_<wbr>subsurface) {<br>
+        wl_subsurface_destroy(xwl_<wbr>window->present_subsurface);<br>
+        wl_surface_destroy(xwl_window-<wbr>>present_surface);<br>
+        xwl_window->present_subsurface = NULL;<br>
+    }<br>
+    xwl_window->present_surface = NULL;<br>
+<br>
     /* Reset base data */<br>
     xorg_list_del(&xwl_window-><wbr>present_link);<br>
-    xwl_window->present_surface = NULL;<br>
     xwl_window->present_window = NULL;<br>
<br>
-    /* Clear remaining events */<br>
+    /* Clear remaining queued events */<br>
     xorg_list_for_each_entry_safe(<wbr>event, tmp, &xwl_window->present_event_<wbr>list, list) {<br>
         xorg_list_del(&event->list);<br>
         free(event);<br>
@@ -231,7 +239,9 @@ xwl_present_check_flip(<wbr>RRCrtcPtr crtc,<br>
      */<br>
     if (xwl_window->present_crtc_fake != crtc)<br>
         return FALSE;<br>
-    if (!RegionEqual(&xwl_window-><wbr>window->winSize, &present_window->winSize))<br>
+<br>
+    if (!RegionEqual(&xwl_window-><wbr>window->winSize, &present_window->winSize) &&<br>
+            !xwl_window->xwl_screen-><wbr>subcompositor)<br>
         return FALSE;<br>
<br>
     return TRUE;<br>
@@ -246,11 +256,15 @@ xwl_present_flip(WindowPtr present_window,<br>
                  Bool sync_flip)<br>
 {<br>
     struct xwl_window           *xwl_window = xwl_window_from_window(<wbr>present_window);<br>
-    BoxPtr                      present_box;<br>
+    WindowPtr                   window = xwl_window->window;<br>
+    struct xwl_screen           *xwl_screen = xwl_window->xwl_screen;<br>
+    BoxPtr                      win_box, present_box;<br>
     Bool                        buffer_created;<br>
     struct wl_buffer            *buffer;<br>
     struct xwl_present_event    *event;<br>
+    struct wl_region            *input_region;<br>
<br>
+    win_box = RegionExtents(&window-><wbr>winSize);<br>
     present_box = RegionExtents(&present_window-<wbr>>winSize);<br>
<br>
     /* We always switch to another child window, if it wants to present. */<br>
@@ -260,8 +274,21 @@ xwl_present_flip(WindowPtr present_window,<br>
         xwl_window->present_window = present_window;<br>
         xorg_list_add(&xwl_window-><wbr>present_link, &xwl_present_windows);<br>
<br>
-        /* We can flip directly to the main surface (full screen window without clips) */<br>
-        xwl_window->present_surface = xwl_window->surface;<br>
+        if (RegionEqual(&window->winSize, &present_window->winSize)) {<br>
+            /* We can flip directly to the main surface (full screen window without clips) */<br>
+            xwl_window->present_surface = xwl_window->surface;<br>
+        } else {<br>
+            xwl_window->present_surface =  wl_compositor_create_surface(<wbr>xwl_window->xwl_screen-><wbr>compositor);<br>
+            wl_surface_set_user_data(xwl_<wbr>window->present_surface, xwl_window);<br>
+<br>
+            xwl_window->present_subsurface =<br>
+                    wl_subcompositor_get_<wbr>subsurface(xwl_screen-><wbr>subcompositor, xwl_window->present_surface, xwl_window->surface);<br>
+            wl_subsurface_set_desync(xwl_<wbr>window->present_subsurface);<br>
+<br>
+            input_region = wl_compositor_create_region(<wbr>xwl_screen->compositor);<br>
+            wl_surface_set_input_region(<wbr>xwl_window->present_surface, input_region);<br>
+            wl_region_destroy(input_<wbr>region);<br>
+        }<br>
     }<br>
<br>
     event = malloc(sizeof *event);<br>
@@ -270,6 +297,11 @@ xwl_present_flip(WindowPtr present_window,<br>
         return FALSE;<br>
     }<br>
<br>
+    if (xwl_window->present_<wbr>subsurface)<br>
+        wl_subsurface_set_position(<wbr>xwl_window->present_<wbr>subsurface,<br>
+                                   present_box->x1 - win_box->x1,<br>
+                                   present_box->y1 - win_box->y1);<br>
+<br>
     buffer = xwl_glamor_pixmap_get_wl_<wbr>buffer(pixmap,<br>
                                              present_box->x2 - present_box->x1,<br>
                                              present_box->y2 - present_box->y1,<br>
diff --git a/hw/xwayland/xwayland.c b/hw/xwayland/xwayland.c<br>
index 2182c71..18e5b8b 100644<br>
--- a/hw/xwayland/xwayland.c<br>
+++ b/hw/xwayland/xwayland.c<br>
@@ -659,7 +659,7 @@ xwl_screen_post_damage(struct xwl_screen *xwl_screen)<br>
     xorg_list_for_each_entry_safe(<wbr>xwl_window, next_xwl_window,<br>
                                   &xwl_screen->damage_window_<wbr>list, link_damage) {<br>
         /* Present on the main surface. So don't commit here as well. */<br>
-        if (xwl_window->present_surface)<br>
+        if (xwl_window->present_surface && !xwl_window->present_<wbr>subsurface)<br>
             continue;<br>
         /* If we're waiting on a frame callback from the server,<br>
          * don't attach a new buffer. */<br>
@@ -683,6 +683,10 @@ registry_global(void *data, struct wl_registry *registry, uint32_t id,<br>
         xwl_screen->compositor =<br>
             wl_registry_bind(registry, id, &wl_compositor_interface, 1);<br>
     }<br>
+    else if (strcmp(interface, "wl_subcompositor") == 0) {<br>
+        xwl_screen->subcompositor =<br>
+            wl_registry_bind(registry, id, &wl_subcompositor_interface, 1);<br>
+    }<br>
     else if (strcmp(interface, "wl_shm") == 0) {<br>
         xwl_screen->shm = wl_registry_bind(registry, id, &wl_shm_interface, 1);<br>
     }<br>
diff --git a/hw/xwayland/xwayland.h b/hw/xwayland/xwayland.h<br>
index 0969043..166ba9b 100644<br>
--- a/hw/xwayland/xwayland.h<br>
+++ b/hw/xwayland/xwayland.h<br>
@@ -77,6 +77,7 @@ struct xwl_screen {<br>
     struct wl_registry *registry;<br>
     struct wl_registry *input_registry;<br>
     struct wl_compositor *compositor;<br>
+    struct wl_subcompositor *subcompositor;<br>
     struct zwp_tablet_manager_v2 *tablet_manager;<br>
     struct wl_shm *shm;<br>
     struct wl_shell *shell;<br>
@@ -120,6 +121,7 @@ struct xwl_window {<br>
     struct xorg_list present_link;<br>
     WindowPtr present_window;<br>
     struct wl_surface *present_surface;<br>
+    struct wl_subsurface *present_subsurface;<br>
     uint64_t present_msc;<br>
     struct wl_callback *present_frame_callback;<br>
     struct xorg_list present_event_list;<br>
diff --git a/present/present_winmode.c b/present/present_winmode.c<br>
index 3027db7..8e98634 100644<br>
--- a/present/present_winmode.c<br>
+++ b/present/present_winmode.c<br>
@@ -123,7 +123,6 @@ present_winmode_restore_<wbr>window_pixmap(WindowPtr window)<br>
<br>
     flip_pixmap = window_priv->flip_pending ? window_priv->flip_pending-><wbr>pixmap :<br>
                                               window_priv->flip_active-><wbr>pixmap;<br>
-<br>
     assert (flip_pixmap);<br>
<br>
     restore_pixmap = screen->GetWindowPixmap(<wbr>window->parent);<br>
@@ -419,12 +418,11 @@ present_winmode_execute(<wbr>present_vblank_ptr vblank, uint64_t ust, uint64_t crtc_m<br>
                     RegionIntersect(damage, damage, &window->clipList);<br>
                 } else<br>
                     damage = &window->clipList;<br>
-<br>
                 DamageDamageRegion(&vblank-><wbr>window->drawable, damage);<br>
+<br>
                 if (*screen_priv->winmode_info-><wbr>flip_executed)<br>
                     (*screen_priv->winmode_info-><wbr>flip_executed) (vblank->window, vblank->crtc, vblank->event_id, damage);<br>
<br>
-<br>
                 return;<br>
             }<br>
<span class="HOEnZb"><font color="#888888"><br>
--<br>
2.7.4<br>
<br>
</font></span></blockquote></div><br></div>