xserver: Branch 'master' - 3 commits

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Fri Dec 11 10:09:23 UTC 2020


 hw/xwayland/xwayland-cursor.c         |   79 ++++++++++++++++++++--------------
 hw/xwayland/xwayland-window-buffers.c |   25 ++++++++++
 2 files changed, 71 insertions(+), 33 deletions(-)

New commits:
commit f95d81e88be07f43c91660e675d077ccd9ee47a9
Author: Olivier Fourdan <ofourdan at redhat.com>
Date:   Mon Dec 7 14:21:56 2020 +0100

    xwayland: Hold window buffer until released
    
    The window buffer mechanism would free the pixmap and its corresponding
    Wayland buffer as soon as window buffers are disposed.
    
    Typically when the X11 window is unrealized, the current window buffer
    is still used by the Wayland compositor and yet Xwayland will destroy
    the buffer.
    
    As a matter of fact, Xwayland should not destroy the Wayland buffer
    before the wl_buffer.release event is received.
    
    Add a reference counter to the window buffer similar to the to pixmap
    reference counter to keep the buffer around until the release callback
    is received.
    
    Increase that reference counter on the buffer which will be attached to
    the surface, and drop that reference when receiving the release callback
    notification.
    
    v2: Use a specific reference counter on the buffer rather than relying
        on the pixmap refcnt (Michel Dänzer <mdaenzer at redhat.com>)
    
    Signed-off-by: Olivier Fourdan <ofourdan at redhat.com>
    Reviewed-by: Michel Dänzer <mdaenzer at redhat.com>
    Acked-by: Martin Peres <martin.peres at mupuf.org>

diff --git a/hw/xwayland/xwayland-window-buffers.c b/hw/xwayland/xwayland-window-buffers.c
index 7336a7fbe..f04c79a8a 100644
--- a/hw/xwayland/xwayland-window-buffers.c
+++ b/hw/xwayland/xwayland-window-buffers.c
@@ -40,6 +40,7 @@ struct xwl_window_buffer {
     PixmapPtr pixmap;
     RegionPtr damage_region;
     Bool recycle_on_release;
+    int refcnt;
     uint32_t time;
     struct xorg_list link_buffer;
 };
@@ -79,6 +80,7 @@ xwl_window_buffer_new(struct xwl_window *xwl_window)
     xwl_window_buffer->xwl_window = xwl_window;
     xwl_window_buffer->damage_region = RegionCreate(NullBox, 1);
     xwl_window_buffer->pixmap = NullPixmap;
+    xwl_window_buffer->refcnt = 1;
 
     xorg_list_append(&xwl_window_buffer->link_buffer,
                      &xwl_window->window_buffers_available);
@@ -96,9 +98,14 @@ xwl_window_buffer_destroy_pixmap(struct xwl_window_buffer *xwl_window_buffer)
     xwl_window_buffer->pixmap = NullPixmap;
 }
 
-static void
+static Bool
 xwl_window_buffer_dispose(struct xwl_window_buffer *xwl_window_buffer)
 {
+    assert(xwl_window_buffer->refcnt > 0);
+
+    if (--xwl_window_buffer->refcnt)
+        return FALSE;
+
     RegionDestroy(xwl_window_buffer->damage_region);
 
     if (xwl_window_buffer->pixmap)
@@ -106,6 +113,8 @@ xwl_window_buffer_dispose(struct xwl_window_buffer *xwl_window_buffer)
 
     xorg_list_del(&xwl_window_buffer->link_buffer);
     free(xwl_window_buffer);
+
+    return TRUE;
 }
 
 static void
@@ -187,6 +196,12 @@ xwl_window_buffer_release_callback(void *data)
     struct xwl_window *xwl_window = xwl_window_buffer->xwl_window;
     struct xwl_window_buffer *oldest_available_buffer;
 
+    /* Drop the reference on the buffer we took in get_pixmap. If that
+     * frees the window buffer, we're done.
+     */
+    if (xwl_window_buffer_dispose(xwl_window_buffer))
+        return;
+
     if (xwl_window_buffer->recycle_on_release)
         xwl_window_buffer_recycle(xwl_window_buffer);
 
@@ -250,15 +265,21 @@ xwl_window_buffers_dispose(struct xwl_window *xwl_window)
 {
     struct xwl_window_buffer *xwl_window_buffer, *tmp;
 
+    /* This is called prior to free the xwl_window, make sure to untie
+     * the buffers from the xwl_window so that we don't point at freed
+     * memory if we get a release buffer later.
+     */
     xorg_list_for_each_entry_safe(xwl_window_buffer, tmp,
                                   &xwl_window->window_buffers_available,
                                   link_buffer) {
+        xorg_list_del(&xwl_window_buffer->link_buffer);
         xwl_window_buffer_dispose(xwl_window_buffer);
     }
 
     xorg_list_for_each_entry_safe(xwl_window_buffer, tmp,
                                   &xwl_window->window_buffers_unavailable,
                                   link_buffer) {
+        xorg_list_del(&xwl_window_buffer->link_buffer);
         xwl_window_buffer_dispose(xwl_window_buffer);
     }
 
@@ -329,6 +350,8 @@ xwl_window_buffers_get_pixmap(struct xwl_window *xwl_window,
 
     RegionEmpty(xwl_window_buffer->damage_region);
 
+    /* Hold a reference on the buffer until it's released by the compositor */
+    xwl_window_buffer->refcnt++;
     xwl_pixmap_set_buffer_release_cb(xwl_window_buffer->pixmap,
                                      xwl_window_buffer_release_callback,
                                      xwl_window_buffer);
commit 85d8eac4bcf44c077bb82aaae10ae45feb9c4e72
Author: Olivier Fourdan <ofourdan at redhat.com>
Date:   Mon Dec 7 14:09:58 2020 +0100

    xwayland: Hold cursor buffer until released
    
    The cursor code would destroy the buffer as soon as the cursor is
    unrealized on X11 side.
    
    Yet, the Wayland compositor may still be using the buffer as long as a
    released callback has not been received.
    
    Increase the reference counter on the pixmap to hold a reference on the
    pixmap when attaching it to the surface and use the new pixmap release
    callback mechanism to release that reference when the buffer is
    released.
    
    Signed-off-by: Olivier Fourdan <ofourdan at redhat.com>
    Acked-by: Martin Peres <martin.peres at mupuf.org>
    Reviewed-by: Michel Dänzer <mdaenzer at redhat.com>

diff --git a/hw/xwayland/xwayland-cursor.c b/hw/xwayland/xwayland-cursor.c
index 6869222b4..91cc18464 100644
--- a/hw/xwayland/xwayland-cursor.c
+++ b/hw/xwayland/xwayland-cursor.c
@@ -34,6 +34,7 @@
 
 #include "xwayland-cursor.h"
 #include "xwayland-input.h"
+#include "xwayland-pixmap.h"
 #include "xwayland-screen.h"
 #include "xwayland-shm.h"
 #include "xwayland-types.h"
@@ -135,6 +136,13 @@ static const struct wl_callback_listener frame_listener = {
     frame_callback
 };
 
+static void
+xwl_cursor_buffer_release_callback(void *data)
+{
+    /* drop the reference we took in set_cursor */
+    xwl_shm_destroy_pixmap(data);
+}
+
 static void
 xwl_cursor_copy_bits_to_pixmap(CursorPtr cursor, PixmapPtr pixmap)
 {
@@ -161,6 +169,12 @@ xwl_cursor_attach_pixmap(struct xwl_seat *xwl_seat,
     xwl_cursor->frame_cb = wl_surface_frame(xwl_cursor->surface);
     wl_callback_add_listener(xwl_cursor->frame_cb, &frame_listener, xwl_cursor);
 
+    /* Hold a reference on the pixmap until it's released by the compositor */
+    pixmap->refcnt++;
+    xwl_pixmap_set_buffer_release_cb(pixmap,
+                                     xwl_cursor_buffer_release_callback,
+                                     pixmap);
+
     wl_surface_commit(xwl_cursor->surface);
 }
 
commit 79afbd608b7e6abc5d6d0f7e1fb6e460500c7934
Author: Olivier Fourdan <ofourdan at redhat.com>
Date:   Thu Dec 10 10:10:05 2020 +0100

    xwayland: Factorize common cursor code
    
    The seat and tablet cursor functions are very similar, factorize the
    commonalities to simplify the code and reduce the copy/paste.
    
    Signed-off-by: Olivier Fourdan <ofourdan at redhat.com>
    Reviewed-by: Michel Dänzer <mdaenzer at redhat.com>

diff --git a/hw/xwayland/xwayland-cursor.c b/hw/xwayland/xwayland-cursor.c
index 91728f1c1..6869222b4 100644
--- a/hw/xwayland/xwayland-cursor.c
+++ b/hw/xwayland/xwayland-cursor.c
@@ -135,13 +135,41 @@ static const struct wl_callback_listener frame_listener = {
     frame_callback
 };
 
+static void
+xwl_cursor_copy_bits_to_pixmap(CursorPtr cursor, PixmapPtr pixmap)
+{
+    int stride;
+
+    stride = cursor->bits->width * 4;
+    if (cursor->bits->argb)
+        memcpy(pixmap->devPrivate.ptr,
+               cursor->bits->argb, cursor->bits->height * stride);
+    else
+        expand_source_and_mask(cursor, pixmap->devPrivate.ptr);
+}
+
+static void
+xwl_cursor_attach_pixmap(struct xwl_seat *xwl_seat,
+                         struct xwl_cursor *xwl_cursor, PixmapPtr pixmap)
+{
+    wl_surface_attach(xwl_cursor->surface,
+                      xwl_shm_pixmap_get_wl_buffer(pixmap), 0, 0);
+    xwl_surface_damage(xwl_seat->xwl_screen, xwl_cursor->surface, 0, 0,
+                       xwl_seat->x_cursor->bits->width,
+                       xwl_seat->x_cursor->bits->height);
+
+    xwl_cursor->frame_cb = wl_surface_frame(xwl_cursor->surface);
+    wl_callback_add_listener(xwl_cursor->frame_cb, &frame_listener, xwl_cursor);
+
+    wl_surface_commit(xwl_cursor->surface);
+}
+
 void
 xwl_seat_set_cursor(struct xwl_seat *xwl_seat)
 {
     struct xwl_cursor *xwl_cursor = &xwl_seat->cursor;
     PixmapPtr pixmap;
     CursorPtr cursor;
-    int stride;
 
     if (!xwl_seat->wl_pointer)
         return;
@@ -164,28 +192,15 @@ xwl_seat_set_cursor(struct xwl_seat *xwl_seat)
     if (!pixmap)
         return;
 
-    stride = cursor->bits->width * 4;
-    if (cursor->bits->argb)
-        memcpy(pixmap->devPrivate.ptr,
-               cursor->bits->argb, cursor->bits->height * stride);
-    else
-        expand_source_and_mask(cursor, pixmap->devPrivate.ptr);
+    xwl_cursor_copy_bits_to_pixmap(cursor, pixmap);
 
     wl_pointer_set_cursor(xwl_seat->wl_pointer,
                           xwl_seat->pointer_enter_serial,
                           xwl_cursor->surface,
                           xwl_seat->x_cursor->bits->xhot,
                           xwl_seat->x_cursor->bits->yhot);
-    wl_surface_attach(xwl_cursor->surface,
-                      xwl_shm_pixmap_get_wl_buffer(pixmap), 0, 0);
-    xwl_surface_damage(xwl_seat->xwl_screen, xwl_cursor->surface, 0, 0,
-                       xwl_seat->x_cursor->bits->width,
-                       xwl_seat->x_cursor->bits->height);
-
-    xwl_cursor->frame_cb = wl_surface_frame(xwl_cursor->surface);
-    wl_callback_add_listener(xwl_cursor->frame_cb, &frame_listener, xwl_cursor);
 
-    wl_surface_commit(xwl_cursor->surface);
+    xwl_cursor_attach_pixmap(xwl_seat, xwl_cursor, pixmap);
 }
 
 void
@@ -195,7 +210,6 @@ xwl_tablet_tool_set_cursor(struct xwl_tablet_tool *xwl_tablet_tool)
     struct xwl_cursor *xwl_cursor = &xwl_tablet_tool->cursor;
     PixmapPtr pixmap;
     CursorPtr cursor;
-    int stride;
 
     if (!xwl_seat->x_cursor) {
         zwp_tablet_tool_v2_set_cursor(xwl_tablet_tool->tool,
@@ -216,28 +230,15 @@ xwl_tablet_tool_set_cursor(struct xwl_tablet_tool *xwl_tablet_tool)
     if (!pixmap)
         return;
 
-    stride = cursor->bits->width * 4;
-    if (cursor->bits->argb)
-        memcpy(pixmap->devPrivate.ptr,
-               cursor->bits->argb, cursor->bits->height * stride);
-    else
-        expand_source_and_mask(cursor, pixmap->devPrivate.ptr);
+    xwl_cursor_copy_bits_to_pixmap(cursor, pixmap);
 
     zwp_tablet_tool_v2_set_cursor(xwl_tablet_tool->tool,
                                   xwl_tablet_tool->proximity_in_serial,
                                   xwl_cursor->surface,
                                   xwl_seat->x_cursor->bits->xhot,
                                   xwl_seat->x_cursor->bits->yhot);
-    wl_surface_attach(xwl_cursor->surface,
-                      xwl_shm_pixmap_get_wl_buffer(pixmap), 0, 0);
-    xwl_surface_damage(xwl_seat->xwl_screen, xwl_cursor->surface, 0, 0,
-                       xwl_seat->x_cursor->bits->width,
-                       xwl_seat->x_cursor->bits->height);
 
-    xwl_cursor->frame_cb = wl_surface_frame(xwl_cursor->surface);
-    wl_callback_add_listener(xwl_cursor->frame_cb, &frame_listener, xwl_cursor);
-
-    wl_surface_commit(xwl_cursor->surface);
+    xwl_cursor_attach_pixmap(xwl_seat, xwl_cursor, pixmap);
 }
 
 static void


More information about the xorg-commit mailing list