<div dir="ltr">Hi Roman,<br><div class="gmail_extra"><br><div class="gmail_quote">On Fri, May 4, 2018 at 3:07 AM, 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">Instead of reusing xwl_window introduce a persistent window struct for every<br>
window, that asks for Present flips.<br>
<br>
This struct saves all relevant data and is only freed on window destroy.<br>
<br>
Signed-off-by: Roman Gilg <<a href="mailto:subdiff@gmail.com">subdiff@gmail.com</a>><br>
---<br>
 hw/xwayland/xwayland-present.c | 277 ++++++++++++++++++++++++------<wbr>-----------<br>
 hw/xwayland/xwayland.c         |  50 ++++----<br>
 hw/xwayland/xwayland.h         |  37 +++---<br>
 3 files changed, 212 insertions(+), 152 deletions(-)<br>
<br>
diff --git a/hw/xwayland/xwayland-<wbr>present.c b/hw/xwayland/xwayland-<wbr>present.c<br>
index 66bfaae..ae9f47e 100644<br>
--- a/hw/xwayland/xwayland-<wbr>present.c<br>
+++ b/hw/xwayland/xwayland-<wbr>present.c<br>
@@ -36,11 +36,49 @@<br>
 #define TIMER_LEN_COPY      17  // ~60fps<br>
 #define TIMER_LEN_FLIP    1000  // 1fps<br>
<br>
+static DevPrivateKeyRec xwl_present_window_private_<wbr>key;<br>
+<br>
+static struct xwl_present_window *<br>
+xwl_present_window_priv(<wbr>WindowPtr window)<br>
+{<br>
+    return dixGetPrivate(&window-><wbr>devPrivates,<br>
+                         &xwl_present_window_private_<wbr>key);<br>
+}<br>
+<br>
+static struct xwl_present_window *<br>
+xwl_present_window_get_priv(<wbr>WindowPtr window)<br>
+{<br>
+    struct xwl_present_window *xwl_present_window = xwl_present_window_priv(<wbr>window);<br>
+<br>
+    if (xwl_present_window == NULL) {<br>
+        ScreenPtr screen = window->drawable.pScreen;<br>
+<br>
+        xwl_present_window = calloc (1, sizeof (struct xwl_present_window));<br>
+        if (!xwl_present_window)<br>
+            return NULL;<br>
+<br>
+        xwl_present_window->crtc_fake = RRCrtcCreate(screen,<br>
+                                                     xwl_present_window);<br>
+        xwl_present_window->window = window;<br>
+        xwl_present_window->msc = 1;<br>
+        xwl_present_window->ust = GetTimeInMicros();<br>
+<br>
+        xorg_list_init(&xwl_present_<wbr>window->event_list);<br>
+        xorg_list_init(&xwl_present_<wbr>window->release_queue);<br>
+<br>
+        dixSetPrivate(&window-><wbr>devPrivates,<br>
+                      &xwl_present_window_private_<wbr>key,<br>
+                      xwl_present_window);<br>
+    }<br>
+<br>
+    return xwl_present_window;<br>
+}<br>
+<br>
 static void<br>
-xwl_present_free_timer(struct xwl_window *xwl_window)<br>
+xwl_present_free_timer(struct xwl_present_window *xwl_present_window)<br>
 {<br>
-    TimerFree(xwl_window->present_<wbr>timer);<br>
-    xwl_window->present_timer = NULL;<br>
+    TimerFree(xwl_present_window-><wbr>frame_timer);<br>
+    xwl_present_window->frame_<wbr>timer = NULL;<br>
 }<br>
<br>
 static CARD32<br>
@@ -49,57 +87,73 @@ xwl_present_timer_callback(<wbr>OsTimerPtr timer,<br>
                            void *arg);<br>
<br>
 static inline Bool<br>
-xwl_present_has_events(struct xwl_window *xwl_window)<br>
+xwl_present_has_events(struct xwl_present_window *xwl_present_window)<br>
 {<br>
-    return !xorg_list_is_empty(&xwl_<wbr>window->present_event_list) ||<br>
-           !xorg_list_is_empty(&xwl_<wbr>window->present_release_queue)<wbr>;<br>
+    return !xorg_list_is_empty(&xwl_<wbr>present_window->event_list) ||<br>
+           !xorg_list_is_empty(&xwl_<wbr>present_window->release_queue)<wbr>;<br>
+}<br>
+<br>
+static inline Bool<br>
+xwl_present_is_flipping(<wbr>WindowPtr window, struct xwl_window *xwl_window)<br>
+{<br>
+    return xwl_window && xwl_window->present_window == window;<br>
 }<br>
<br>
 static void<br>
-xwl_present_reset_timer(<wbr>struct xwl_window *xwl_window)<br>
+xwl_present_reset_timer(<wbr>struct xwl_present_window *xwl_present_window)<br>
 {<br>
-    if (xwl_present_has_events(xwl_<wbr>window)) {<br>
-        uint32_t timer_len = xwl_window->present_window ? TIMER_LEN_FLIP :<br>
-                                                          TIMER_LEN_COPY;<br>
-<br>
-        xwl_window->present_timer = TimerSet(xwl_window->present_<wbr>timer,<br>
-                                             0,<br>
-                                             timer_len,<br>
-                                             &xwl_present_timer_callback,<br>
-                                             xwl_window);<br>
+    if (xwl_present_has_events(xwl_<wbr>present_window)) {<br>
+        WindowPtr present_window = xwl_present_window->window;<br>
+        Bool is_flipping = xwl_present_is_flipping(<wbr>present_window,<br>
+                                                   xwl_window_from_window(<wbr>present_window));<br>
+<br>
+        xwl_present_window->frame_<wbr>timer = TimerSet(xwl_present_window-><wbr>frame_timer,<br>
+                                                   0,<br>
+                                                   is_flipping ? TIMER_LEN_FLIP :<br>
+                                                                 TIMER_LEN_COPY,<br>
+                                                   &xwl_present_timer_callback,<br>
+                                                   xwl_present_window);<br>
     } else {<br>
-        xwl_present_free_timer(xwl_<wbr>window);<br>
+        xwl_present_free_timer(xwl_<wbr>present_window);<br>
     }<br>
 }<br>
<br>
 void<br>
-xwl_present_cleanup(struct xwl_window *xwl_window, WindowPtr window)<br>
+xwl_present_cleanup(WindowPtr window)<br>
 {<br>
+    struct xwl_window *xwl_window = xwl_window_from_window(window)<wbr>;<br>
+    struct xwl_present_window *xwl_present_window = xwl_present_window_priv(<wbr>window);<br>
     struct xwl_present_event *event, *tmp;<br>
<br>
-    if (xwl_window->present_window != window && xwl_window->window != window)<br>
+    if (!xwl_present_window)<br>
         return;<br>
<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>
+    if (xwl_window && xwl_window->present_window == window)<br>
+        xwl_window->present_window = NULL;<br>
+<br>
+    RRCrtcDestroy(xwl_present_<wbr>window->crtc_fake);<br>
+<br>
+    if (xwl_present_window->frame_<wbr>callback) {<br>
+        wl_callback_destroy(xwl_<wbr>present_window->frame_<wbr>callback);<br>
+        xwl_present_window->frame_<wbr>callback = NULL;<br>
     }<br>
-    xwl_window->present_window = NULL;<br>
<br>
     /* Clear remaining events */<br>
-    xorg_list_for_each_entry_safe(<wbr>event, tmp, &xwl_window->present_event_<wbr>list, list) {<br>
+    xorg_list_for_each_entry_safe(<wbr>event, tmp, &xwl_present_window->event_<wbr>list, list) {<br>
         xorg_list_del(&event->list);<br>
         free(event);<br>
     }<br>
<br>
     /* Clear remaining buffer releases and inform Present about free ressources */<br>
-    xorg_list_for_each_entry_safe(<wbr>event, tmp, &xwl_window->present_release_<wbr>queue, list) {<br>
+    xorg_list_for_each_entry_safe(<wbr>event, tmp, &xwl_present_window->release_<wbr>queue, list) {<br>
         xorg_list_del(&event->list);<br>
         event->abort = TRUE;<br>
     }<br>
<br>
     /* Clear timer */<br>
-    xwl_present_free_timer(xwl_<wbr>window);<br>
+    xwl_present_free_timer(xwl_<wbr>present_window);<br>
+<br>
+    free(xwl_present_window);<br>
 }<br>
<br>
 static void<br>
@@ -113,11 +167,10 @@ static void<br>
 xwl_present_buffer_release(<wbr>void *data, struct wl_buffer *buffer)<br>
 {<br>
     struct xwl_present_event *event = data;<br>
-<br>
     if (!event)<br>
         return;<br>
-    wl_buffer_set_user_data(<wbr>buffer, NULL);<br>
<br>
+    wl_buffer_set_user_data(<wbr>buffer, NULL);<br>
     event->buffer_released = TRUE;<br>
<br>
     if (event->abort) {<br>
@@ -127,10 +180,10 @@ xwl_present_buffer_release(<wbr>void *data, struct wl_buffer *buffer)<br>
     }<br>
<br>
     if (!event->pending) {<br>
-        present_wnmd_event_notify(<wbr>event->present_window,<br>
+        present_wnmd_event_notify(<wbr>event->xwl_present_window-><wbr>window,<br>
                                   event->event_id,<br>
-                                  event->xwl_window->present_<wbr>ust,<br>
-                                  event->xwl_window->present_<wbr>msc);<br>
+                                  event->xwl_present_window-><wbr>ust,<br>
+                                  event->xwl_present_window-><wbr>msc);<br>
         xwl_present_free_event(event);<br>
     }<br>
 }<br>
@@ -140,18 +193,18 @@ static const struct wl_buffer_listener xwl_present_release_listener = {<br>
 };<br>
<br>
 static void<br>
-xwl_present_events_notify(<wbr>struct xwl_window *xwl_window)<br>
+xwl_present_events_notify(<wbr>struct xwl_present_window *xwl_present_window)<br>
 {<br>
-    uint64_t                    msc = xwl_window->present_msc;<br>
+    uint64_t                    msc = xwl_present_window->msc;<br>
     struct xwl_present_event    *event, *tmp;<br>
<br>
     xorg_list_for_each_entry_safe(<wbr>event, tmp,<br>
-                                  &xwl_window->present_event_<wbr>list,<br>
+                                  &xwl_present_window->event_<wbr>list,<br>
                                   list) {<br>
         if (event->target_msc <= msc) {<br>
-            present_wnmd_event_notify(<wbr>event->present_window,<br>
+            present_wnmd_event_notify(xwl_<wbr>present_window->window,<br>
                                       event->event_id,<br>
-                                      xwl_window->present_ust,<br>
+                                      xwl_present_window->ust,<br>
                                       msc);<br>
             xwl_present_free_event(event);<br>
         }<br>
@@ -163,21 +216,23 @@ xwl_present_timer_callback(<wbr>OsTimerPtr timer,<br>
                            CARD32 time,<br>
                            void *arg)<br>
 {<br>
-    struct xwl_window *xwl_window = arg;<br>
+    struct xwl_present_window *xwl_present_window = arg;<br>
+    WindowPtr present_window = xwl_present_window->window;<br>
+    struct xwl_window *xwl_window = xwl_window_from_window(<wbr>present_window);<br>
<br>
-    xwl_window->present_timer_<wbr>firing = TRUE;<br>
-    xwl_window->present_msc++;<br>
-    xwl_window->present_ust = GetTimeInMicros();<br>
+    xwl_present_window->frame_<wbr>timer_firing = TRUE;<br>
+    xwl_present_window->msc++;<br>
+    xwl_present_window->ust = GetTimeInMicros();<br>
<br>
-    xwl_present_events_notify(xwl_<wbr>window);<br>
+    xwl_present_events_notify(xwl_<wbr>present_window);<br>
<br>
-    if (xwl_present_has_events(xwl_<wbr>window)) {<br>
+    if (xwl_present_has_events(xwl_<wbr>present_window)) {<br>
         /* Still events, restart timer */<br>
-        return xwl_window->present_window ? TIMER_LEN_FLIP :<br>
-                                            TIMER_LEN_COPY;<br>
+        return xwl_present_is_flipping(<wbr>present_window, xwl_window) ? TIMER_LEN_FLIP :<br>
+                                                                     TIMER_LEN_COPY;<br>
     } else {<br>
         /* No more events, do not restart timer and delete it instead */<br>
-        xwl_present_free_timer(xwl_<wbr>window);<br>
+        xwl_present_free_timer(xwl_<wbr>present_window);<br>
         return 0;<br>
     }<br>
 }<br>
@@ -187,25 +242,25 @@ xwl_present_frame_callback(<wbr>void *data,<br>
                struct wl_callback *callback,<br>
                uint32_t time)<br>
 {<br>
-    struct xwl_window *xwl_window = data;<br>
+    struct xwl_present_window *xwl_present_window = data;<br>
<br>
-    wl_callback_destroy(xwl_<wbr>window->present_frame_<wbr>callback);<br>
-    xwl_window->present_frame_<wbr>callback = NULL;<br>
+    wl_callback_destroy(xwl_<wbr>present_window->frame_<wbr>callback);<br>
+    xwl_present_window->frame_<wbr>callback = NULL;<br>
<br>
-    if (xwl_window->present_timer_<wbr>firing) {<br>
+    if (xwl_present_window->frame_<wbr>timer_firing) {<br>
         /* If the timer is firing, this frame callback is too late */<br>
         return;<br>
     }<br>
<br>
-    xwl_window->present_msc++;<br>
-    xwl_window->present_ust = GetTimeInMicros();<br>
+    xwl_present_window->msc++;<br>
+    xwl_present_window->ust = GetTimeInMicros();<br>
<br>
-    xwl_present_events_notify(xwl_<wbr>window);<br>
+    xwl_present_events_notify(xwl_<wbr>present_window);<br>
<br>
     /* we do not need the timer anymore for this frame,<br>
      * reset it for potentially the next one<br>
      */<br>
-    xwl_present_reset_timer(xwl_<wbr>window);<br>
+    xwl_present_reset_timer(xwl_<wbr>present_window);<br>
 }<br>
<br>
 static const struct wl_callback_listener xwl_present_frame_listener = {<br>
@@ -218,7 +273,7 @@ xwl_present_sync_callback(void *data,<br>
                uint32_t time)<br>
 {<br>
     struct xwl_present_event *event = data;<br>
-    struct xwl_window *xwl_window = event->xwl_window;<br>
+    struct xwl_present_window *xwl_present_window = event->xwl_present_window;<br>
<br>
     event->pending = FALSE;<br>
<br>
@@ -230,17 +285,17 @@ xwl_present_sync_callback(void *data,<br>
         return;<br>
     }<br>
<br>
-    present_wnmd_event_notify(<wbr>event->present_window,<br>
+    present_wnmd_event_notify(xwl_<wbr>present_window->window,<br>
                               event->event_id,<br>
-                              xwl_window->present_ust,<br>
-                              xwl_window->present_msc);<br>
+                              xwl_present_window->ust,<br>
+                              xwl_present_window->msc);<br>
<br>
     if (event->buffer_released)<br>
         /* If the buffer was already released, send the event now again */<br>
-        present_wnmd_event_notify(<wbr>event->present_window,<br>
+        present_wnmd_event_notify(xwl_<wbr>present_window->window,<br>
                                   event->event_id,<br>
-                                  xwl_window->present_ust,<br>
-                                  xwl_window->present_msc);<br>
+                                  xwl_present_window->ust,<br>
+                                  xwl_present_window->msc);<br>
 }<br>
<br>
 static const struct wl_callback_listener xwl_present_sync_listener = {<br>
@@ -250,33 +305,24 @@ static const struct wl_callback_listener xwl_present_sync_listener = {<br>
 static RRCrtcPtr<br>
 xwl_present_get_crtc(WindowPtr present_window)<br>
 {<br>
-    struct xwl_window *xwl_window = xwl_window_from_window(<wbr>present_window);<br>
-    if (xwl_window == NULL)<br>
+    struct xwl_present_window *xwl_present_window = xwl_present_window_get_priv(<wbr>present_window);<br>
+    if (xwl_present_window == NULL)<br>
         return NULL;<br>
<br>
-    return xwl_window->present_crtc_fake;<br>
+    return xwl_present_window->crtc_fake;<br>
 }<br>
<br>
 static int<br>
 xwl_present_get_ust_msc(<wbr>WindowPtr present_window, uint64_t *ust, uint64_t *msc)<br>
 {<br>
-    struct xwl_window *xwl_window = xwl_window_from_window(<wbr>present_window);<br>
-    if (!xwl_window)<br>
+    struct xwl_present_window *xwl_present_window = xwl_present_window_get_priv(<wbr>present_window);<br>
+    if (!xwl_present_window)<br>
         return BadAlloc;<br>
-    *ust = xwl_window->present_ust;<br>
-    *msc = xwl_window->present_msc;<br>
<br>
-    return Success;<br>
-}<br>
-<br>
-static void<br>
-xwl_present_set_present_<wbr>window(struct xwl_window *xwl_window,<br>
-                               WindowPtr present_window)<br>
-{<br>
-    if (xwl_window->present_window)<br>
-        return;<br>
+    *ust = xwl_present_window->ust;<br>
+    *msc = xwl_present_window->msc;<br>
<br>
-    xwl_window->present_window = present_window;<br>
+    return Success;<br>
 }<br>
<br>
 /*<br>
@@ -290,12 +336,13 @@ xwl_present_queue_vblank(<wbr>WindowPtr present_window,<br>
                          uint64_t msc)<br>
 {<br>
     struct xwl_window *xwl_window = xwl_window_from_window(<wbr>present_window);<br>
+    struct xwl_present_window *xwl_present_window = xwl_present_window_get_priv(<wbr>present_window);<br>
     struct xwl_present_event *event;<br>
<br>
     if (!xwl_window)<br>
         return BadMatch;<br>
<br>
-    if (xwl_window->present_crtc_fake != crtc)<br>
+    if (xwl_present_window->crtc_fake != crtc)<br>
         return BadRequest;<br>
<br>
     if (xwl_window->present_window &&<br>
@@ -307,14 +354,13 @@ xwl_present_queue_vblank(<wbr>WindowPtr present_window,<br>
         return BadAlloc;<br>
<br>
     event->event_id = event_id;<br>
-    event->present_window = present_window;<br>
-    event->xwl_window = xwl_window;<br>
+    event->xwl_present_window = xwl_present_window;<br>
     event->target_msc = msc;<br>
<br>
-    xorg_list_append(&event->list, &xwl_window->present_event_<wbr>list);<br>
+    xorg_list_append(&event->list, &xwl_present_window->event_<wbr>list);<br>
<br>
-    if (!xwl_window->present_timer)<br>
-        xwl_present_reset_timer(xwl_<wbr>window);<br>
+    if (!xwl_present_window->frame_<wbr>timer)<br>
+        xwl_present_reset_timer(xwl_<wbr>present_window);<br>
<br>
     return Success;<br>
 }<br>
@@ -329,13 +375,13 @@ xwl_present_abort_vblank(<wbr>WindowPtr present_window,<br>
                          uint64_t event_id,<br>
                          uint64_t msc)<br>
 {<br>
-    struct xwl_window *xwl_window = xwl_window_from_window(<wbr>present_window);<br>
+    struct xwl_present_window *xwl_present_window = xwl_present_window_priv(<wbr>present_window);<br>
     struct xwl_present_event *event, *tmp;<br>
<br>
-    if (!xwl_window)<br>
+    if (!xwl_present_window)<br>
         return;<br>
<br>
-    xorg_list_for_each_entry_safe(<wbr>event, tmp, &xwl_window->present_event_<wbr>list, list) {<br>
+    xorg_list_for_each_entry_safe(<wbr>event, tmp, &xwl_present_window->event_<wbr>list, list) {<br>
         if (event->event_id == event_id) {<br>
             xorg_list_del(&event->list);<br>
             free(event);<br>
@@ -343,7 +389,7 @@ xwl_present_abort_vblank(<wbr>WindowPtr present_window,<br>
         }<br>
     }<br>
<br>
-    xorg_list_for_each_entry(<wbr>event, &xwl_window->present_release_<wbr>queue, list) {<br>
+    xorg_list_for_each_entry(<wbr>event, &xwl_present_window->release_<wbr>queue, list) {<br>
         if (event->event_id == event_id) {<br>
             event->abort = TRUE;<br>
             return;<br>
@@ -378,15 +424,6 @@ xwl_present_check_flip2(<wbr>RRCrtcPtr crtc,<br>
             xwl_window->present_window != present_window)<br>
         return FALSE;<br>
<br>
-    if (!xwl_window->present_crtc_<wbr>fake)<br>
-        return FALSE;<br>
-    /*<br>
-     * Make sure the client doesn't try to flip to another crtc<br>
-     * than the one created for 'xwl_window'.<br>
-     */<br>
-    if (xwl_window->present_crtc_fake != crtc)<br>
-        return FALSE;<br>
-<br>
     /*<br>
      * We currently only allow flips of windows, that have the same<br>
      * dimensions as their xwl_window parent window. For the case of<br>
@@ -408,35 +445,45 @@ xwl_present_flip(WindowPtr present_window,<br>
                  RegionPtr damage)<br>
 {<br>
     struct xwl_window           *xwl_window = xwl_window_from_window(<wbr>present_window);<br>
+    struct xwl_present_window   *xwl_present_window = xwl_present_window_priv(<wbr>present_window);<br>
     BoxPtr                      present_box, damage_box;<br>
     Bool                        buffer_created;<br>
     struct wl_buffer            *buffer;<br>
     struct xwl_present_event    *event;<br>
<br>
+    if (!xwl_window)<br>
+        return FALSE;<br>
+<br>
+    /*<br>
+     * Make sure the client doesn't try to flip to another crtc<br>
+     * than the one created for 'xwl_window'.<br>
+     */<br>
+    if (xwl_present_window->crtc_fake != crtc)<br>
+        return FALSE;<br>
+<br>
     present_box = RegionExtents(&present_window-<wbr>>winSize);<br>
     damage_box = RegionExtents(damage);<br>
<br>
-    xwl_present_set_present_<wbr>window(xwl_window, present_window);<br>
-<br>
     event = malloc(sizeof *event);<br>
     if (!event)<br>
         return FALSE;<br>
<br>
+    xwl_window->present_window = present_window;<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>
                                              &buffer_created);<br>
<br>
     event->event_id = event_id;<br>
-    event->present_window = present_window;<br>
-    event->xwl_window = xwl_window;<br>
+    event->xwl_present_window = xwl_present_window;<br>
     event->buffer = buffer;<br>
-    event->target_msc = xwl_window->present_msc;<br>
+    event->target_msc = xwl_present_window->msc;<br>
     event->pending = TRUE;<br>
     event->abort = FALSE;<br>
     event->buffer_released = FALSE;<br>
<br>
-    xorg_list_add(&event->list, &xwl_window->present_release_<wbr>queue);<br>
+    xorg_list_add(&event->list, &xwl_present_window->release_<wbr>queue);<br>
<br>
     if (buffer_created)<br>
         wl_buffer_add_listener(buffer, &xwl_present_release_listener, NULL);<br>
@@ -445,18 +492,18 @@ xwl_present_flip(WindowPtr present_window,<br>
     /* We can flip directly to the main surface (full screen window without clips) */<br>
     wl_surface_attach(xwl_window-><wbr>surface, buffer, 0, 0);<br>
<br>
-    if (!xwl_window->present_timer ||<br>
-            xwl_window->present_timer_<wbr>firing) {<br>
+    if (!xwl_present_window->frame_<wbr>timer ||<br>
+            xwl_present_window->frame_<wbr>timer_firing) {<br>
         /* Realign timer */<br>
-        xwl_window->present_timer_<wbr>firing = FALSE;<br>
-        xwl_present_reset_timer(xwl_<wbr>window);<br>
+        xwl_present_window->frame_<wbr>timer_firing = FALSE;<br>
+        xwl_present_reset_timer(xwl_<wbr>present_window);<br>
     }<br>
<br>
-    if (!xwl_window->present_frame_<wbr>callback) {<br>
-        xwl_window->present_frame_<wbr>callback = wl_surface_frame(xwl_window-><wbr>surface);<br>
-        wl_callback_add_listener(xwl_<wbr>window->present_frame_<wbr>callback,<br>
+    if (!xwl_present_window->frame_<wbr>callback) {<br>
+        xwl_present_window->frame_<wbr>callback = wl_surface_frame(xwl_window-><wbr>surface);<br>
+        wl_callback_add_listener(xwl_<wbr>present_window->frame_<wbr>callback,<br>
                                  &xwl_present_frame_listener,<br>
-                                 xwl_window);<br>
+                                 xwl_present_window);<br>
     }<br>
<br>
     wl_surface_damage(xwl_window-><wbr>surface, 0, 0,<br>
@@ -465,8 +512,8 @@ xwl_present_flip(WindowPtr present_window,<br>
<br>
     wl_surface_commit(xwl_window-><wbr>surface);<br>
<br>
-    xwl_window->present_sync_<wbr>callback = wl_display_sync(xwl_window-><wbr>xwl_screen->display);<br>
-    wl_callback_add_listener(xwl_<wbr>window->present_sync_callback,<br>
+    xwl_present_window->sync_<wbr>callback = wl_display_sync(xwl_window-><wbr>xwl_screen->display);<br>
+    wl_callback_add_listener(xwl_<wbr>present_window->sync_callback,<br>
                              &xwl_present_sync_listener,<br>
                              event);<br>
<br>
@@ -478,6 +525,7 @@ static void<br>
 xwl_present_flips_stop(<wbr>WindowPtr window)<br>
 {<br>
     struct xwl_window *xwl_window = xwl_window_from_window(window)<wbr>;<br>
+    struct xwl_present_window   *xwl_present_window = xwl_present_window_priv(<wbr>window);<br>
<br>
     if (!xwl_window)<br>
         return;<br>
@@ -487,7 +535,7 @@ xwl_present_flips_stop(<wbr>WindowPtr window)<br>
     xwl_window->present_window = NULL;<br>
<br>
     /* Change back to the fast refresh rate */<br>
-    xwl_present_reset_timer(xwl_<wbr>window);<br>
+    xwl_present_reset_timer(xwl_<wbr>present_window);<br>
 }<br>
<br>
 static present_wnmd_info_rec xwl_present_info = {<br>
@@ -518,5 +566,8 @@ xwl_present_init(ScreenPtr screen)<br>
     if (xwl_screen->egl_backend.post_<wbr>damage != NULL)<br>
         return FALSE;<br>
<br>
+    if (!dixRegisterPrivateKey(&xwl_<wbr>present_window_private_key, PRIVATE_WINDOW, 0))<br>
+        return FALSE;<br>
+<br>
     return present_wnmd_screen_init(<wbr>screen, &xwl_present_info);<br>
 }<br>
diff --git a/hw/xwayland/xwayland.c b/hw/xwayland/xwayland.c<br>
index f7e2ce9..f5b03b2 100644<br>
--- a/hw/xwayland/xwayland.c<br>
+++ b/hw/xwayland/xwayland.c<br>
@@ -531,17 +531,6 @@ xwl_realize_window(WindowPtr window)<br>
         wl_region_destroy(region);<br>
     }<br>
<br>
-#ifdef GLAMOR_HAS_GBM<br>
-    if (xwl_screen->present) {<br>
-        xwl_window->present_crtc_fake = RRCrtcCreate(xwl_screen-><wbr>screen, xwl_window);<br>
-        xwl_window->present_msc = 1;<br>
-        xwl_window->present_ust = GetTimeInMicros();<br>
-<br>
-        xorg_list_init(&xwl_window-><wbr>present_event_list);<br>
-        xorg_list_init(&xwl_window-><wbr>present_release_queue);<br>
-    }<br>
-#endif<br>
-<br>
     wl_display_flush(xwl_screen-><wbr>display);<br>
<br>
     send_surface_id_event(xwl_<wbr>window);<br>
@@ -607,12 +596,6 @@ xwl_unrealize_window(WindowPtr window)<br>
<br>
     compUnredirectWindow(<wbr>serverClient, window, CompositeRedirectManual);<br>
<br>
-#ifdef GLAMOR_HAS_GBM<br>
-    xwl_window = xwl_window_from_window(window)<wbr>;<br>
-    if (xwl_window && xwl_screen->present)<br>
-        xwl_present_cleanup(xwl_<wbr>window, window);<br>
-#endif<br>
-<br>
     screen->UnrealizeWindow = xwl_screen->UnrealizeWindow;<br>
     ret = (*screen->UnrealizeWindow) (window);<br>
     xwl_screen->UnrealizeWindow = screen->UnrealizeWindow;<br>
@@ -629,11 +612,6 @@ xwl_unrealize_window(WindowPtr window)<br>
     if (xwl_window->frame_callback)<br>
         wl_callback_destroy(xwl_<wbr>window->frame_callback);<br>
<br>
-#ifdef GLAMOR_HAS_GBM<br>
-    if (xwl_window->present_crtc_<wbr>fake)<br>
-        RRCrtcDestroy(xwl_window-><wbr>present_crtc_fake);<br>
-#endif<br>
-<br>
     free(xwl_window);<br>
     dixSetPrivate(&window-><wbr>devPrivates, &xwl_window_private_key, NULL);<br>
<br>
@@ -661,6 +639,31 @@ static const struct wl_callback_listener frame_listener = {<br>
     frame_callback<br>
 };<br>
<br>
+static Bool<br>
+xwl_destroy_window(WindowPtr window)<br>
+{<br>
+    ScreenPtr screen = window->drawable.pScreen;<br>
+    struct xwl_screen *xwl_screen = xwl_screen_get(screen);<br>
+    Bool ret;<br>
+<br>
+#ifdef GLAMOR_HAS_GBM<br>
+    if (xwl_screen->present)<br>
+        xwl_present_cleanup(window);<br>
+#endif<br>
+<br>
+    screen->DestroyWindow = xwl_screen->DestroyWindow;<br>
+<br>
+    if (screen->DestroyWindow)<br>
+        ret = screen->DestroyWindow (window);<br>
+    else<br>
+        ret = TRUE;<br>
+<br>
+    xwl_screen->DestroyWindow = screen->DestroyWindow;<br>
+    screen->DestroyWindow = xwl_destroy_window;<br>
+<br>
+    return ret;<br>
+}<br>
+<br>
 static void<br>
 xwl_window_post_damage(struct xwl_window *xwl_window)<br>
 {<br>
@@ -1114,6 +1117,9 @@ xwl_screen_init(ScreenPtr pScreen, int argc, char **argv)<br>
     xwl_screen->UnrealizeWindow = pScreen->UnrealizeWindow;<br>
     pScreen->UnrealizeWindow = xwl_unrealize_window;<br>
<br>
+    xwl_screen->DestroyWindow = pScreen->DestroyWindow;<br>
+    pScreen->DestroyWindow = xwl_destroy_window;<br>
+<br>
     xwl_screen->CloseScreen = pScreen->CloseScreen;<br>
     pScreen->CloseScreen = xwl_close_screen;<br>
<br>
diff --git a/hw/xwayland/xwayland.h b/hw/xwayland/xwayland.h<br>
index 985ba9d..ce290d4 100644<br>
--- a/hw/xwayland/xwayland.h<br>
+++ b/hw/xwayland/xwayland.h<br>
@@ -77,6 +77,7 @@ struct xwl_screen {<br>
     CloseScreenProcPtr CloseScreen;<br>
     RealizeWindowProcPtr RealizeWindow;<br>
     UnrealizeWindowProcPtr UnrealizeWindow;<br>
+    DestroyWindowProcPtr DestroyWindow;<br>
     XYToWindowProcPtr XYToWindow;<br>
<br>
     struct xorg_list output_list;<br>
@@ -172,26 +173,29 @@ struct xwl_window {<br>
     struct xorg_list link_damage;<br>
     struct wl_callback *frame_callback;<br>
     Bool allow_commits;<br>
-#ifdef GLAMOR_HAS_GBM<br>
-    /* present */<br>
-    RRCrtcPtr present_crtc_fake;<br>
-    struct xorg_list present_link;<br>
     WindowPtr present_window;<br>
-    uint64_t present_msc;<br>
-    uint64_t present_ust;<br>
+};<br>
+<br>
+#ifdef GLAMOR_HAS_GBM<br>
+struct xwl_present_window {<br>
+    struct xwl_screen *xwl_screen;<br>
+    WindowPtr window;<br>
+    struct xorg_list link;<br>
<br>
-    OsTimerPtr present_timer;<br>
-    Bool present_timer_firing;<br>
+    RRCrtcPtr crtc_fake;<br>
+    uint64_t msc;<br>
+    uint64_t ust;<br>
<br>
-    struct wl_callback *present_frame_callback;<br>
-    struct wl_callback *present_sync_callback;<br>
+    OsTimerPtr frame_timer;<br>
+    Bool frame_timer_firing;<br>
<br>
-    struct xorg_list present_event_list;<br>
-    struct xorg_list present_release_queue;<br>
-#endif<br>
+    struct wl_callback *frame_callback;<br>
+    struct wl_callback *sync_callback;<br>
+<br>
+    struct xorg_list event_list;<br>
+    struct xorg_list release_queue;<br>
 };<br>
<br>
-#ifdef GLAMOR_HAS_GBM<br>
 struct xwl_present_event {<br>
     uint64_t event_id;<br>
     uint64_t target_msc;<br>
@@ -200,8 +204,7 @@ struct xwl_present_event {<br>
     Bool pending;<br>
     Bool buffer_released;<br>
<br>
-    WindowPtr present_window;<br>
-    struct xwl_window *xwl_window;<br>
+    struct xwl_present_window *xwl_present_window;<br>
     struct wl_buffer *buffer;<br>
<br>
     struct xorg_list list;<br>
@@ -433,7 +436,7 @@ Bool xwl_glamor_allow_commits(<wbr>struct xwl_window *xwl_window);<br>
<br>
 #ifdef GLAMOR_HAS_GBM<br>
 Bool xwl_present_init(ScreenPtr screen);<br>
-void xwl_present_cleanup(struct xwl_window *xwl_window, WindowPtr window);<br>
+void xwl_present_cleanup(WindowPtr window);<br>
 #endif<br>
<br>
 void xwl_screen_release_tablet_<wbr>manager(struct xwl_screen *xwl_screen);<br>
<span class="HOEnZb"><font color="#888888">-- <br>
2.7.4<br>
<br>
______________________________<wbr>_________________<br>
<a href="mailto:xorg-devel@lists.x.org">xorg-devel@lists.x.org</a>: X.Org development<br>
Archives: <a href="http://lists.x.org/archives/xorg-devel" rel="noreferrer" target="_blank">http://lists.x.org/archives/<wbr>xorg-devel</a><br>
Info: <a href="https://lists.x.org/mailman/listinfo/xorg-devel" rel="noreferrer" target="_blank">https://lists.x.org/mailman/<wbr>listinfo/xorg-devel</a></font></span></blockquote></div><br></div><div class="gmail_extra">I reckon this is much better/nicer than changing the API/ABI :)<br><br></div><div class="gmail_extra">I am not familiar enough with the internals of the present implementation to comment on the correctness of the patch itself, but I tested it and it works well (it seems it works better actually, I don't see any black window being shown on remap at all now, although this might be subjective).<br><br></div><div class="gmail_extra">I also ran it in valgrind and tested the build without glamor just to make sure we didn't regress on this front either. No problem found, so, fwiw:<br><br></div><div class="gmail_extra">Tested-by: Olivier Fourdan <<a href="mailto:ofourdan@redhat.com">ofourdan@redhat.com</a>><br><br></div><div class="gmail_extra">As Pekka pointed out on irc, Xwayland would be better off using the Wayland presentation time protocol, but mutter doesn't implement it (yet) so there will be room for future improvement, but imho we would be in a much better state wrt 1.20 with your patch here.<br></div><div class="gmail_extra"><br></div><div class="gmail_extra">Cheers,<br></div><div class="gmail_extra">Olivier<br></div></div>