|
|
d05f4b |
From d9005a02e9c109e57dcc81b51de3b5778915af26 Mon Sep 17 00:00:00 2001
|
|
|
d05f4b |
From: Olivier Fourdan <ofourdan@redhat.com>
|
|
|
d05f4b |
Date: Fri, 30 Apr 2021 09:56:05 +0200
|
|
|
d05f4b |
Subject: [PATCH xserver 2/2] xwayland/eglstream: Remove stream validity
|
|
|
d05f4b |
MIME-Version: 1.0
|
|
|
d05f4b |
Content-Type: text/plain; charset=UTF-8
|
|
|
d05f4b |
Content-Transfer-Encoding: 8bit
|
|
|
d05f4b |
|
|
|
d05f4b |
To avoid an EGL stream in the wrong state, if the window pixmap changed
|
|
|
d05f4b |
before the stream was connected, we would still keep the pending stream
|
|
|
d05f4b |
but mark it as invalid. Once the callback is received, the pending would
|
|
|
d05f4b |
be simply discarded.
|
|
|
d05f4b |
|
|
|
d05f4b |
But all of this is actually to avoid a bug in egl-wayland, there should
|
|
|
d05f4b |
not be any problem with Xwayland destroying an EGL stream while the
|
|
|
d05f4b |
compositor is still using it.
|
|
|
d05f4b |
|
|
|
d05f4b |
With that bug now fixed in egl-wayland 1.1.7, we can safely drop all
|
|
|
d05f4b |
that logic from Xwayland EGLstream backend.
|
|
|
d05f4b |
|
|
|
d05f4b |
Signed-off-by: Olivier Fourdan <ofourdan@redhat.com>
|
|
|
d05f4b |
Reviewed-by: Michel Dänzer <mdaenzer@redhat.com>
|
|
|
d05f4b |
Closes: https://gitlab.freedesktop.org/xorg/xserver/-/issues/1189
|
|
|
d05f4b |
(cherry picked from commit 7d509b6f342d9732b567dc4efa867ea24919853b)
|
|
|
d05f4b |
---
|
|
|
d05f4b |
hw/xwayland/xwayland-glamor-eglstream.c | 165 ++++--------------------
|
|
|
d05f4b |
1 file changed, 28 insertions(+), 137 deletions(-)
|
|
|
d05f4b |
|
|
|
d05f4b |
diff --git a/hw/xwayland/xwayland-glamor-eglstream.c b/hw/xwayland/xwayland-glamor-eglstream.c
|
|
|
d05f4b |
index 2eae9494c..8d18caaf5 100644
|
|
|
d05f4b |
--- a/hw/xwayland/xwayland-glamor-eglstream.c
|
|
|
d05f4b |
+++ b/hw/xwayland/xwayland-glamor-eglstream.c
|
|
|
d05f4b |
@@ -52,15 +52,6 @@
|
|
|
d05f4b |
#include "wayland-eglstream-controller-client-protocol.h"
|
|
|
d05f4b |
#include "linux-dmabuf-unstable-v1-client-protocol.h"
|
|
|
d05f4b |
|
|
|
d05f4b |
-struct xwl_eglstream_pending_stream {
|
|
|
d05f4b |
- PixmapPtr pixmap;
|
|
|
d05f4b |
- WindowPtr window;
|
|
|
d05f4b |
-
|
|
|
d05f4b |
- struct wl_callback *cb;
|
|
|
d05f4b |
-
|
|
|
d05f4b |
- Bool is_valid;
|
|
|
d05f4b |
-};
|
|
|
d05f4b |
-
|
|
|
d05f4b |
struct xwl_eglstream_private {
|
|
|
d05f4b |
EGLDeviceEXT egl_device;
|
|
|
d05f4b |
struct wl_eglstream_display *display;
|
|
|
d05f4b |
@@ -90,7 +81,7 @@ struct xwl_pixmap {
|
|
|
d05f4b |
/* add any new <= 4-byte member here to avoid holes on 64-bit */
|
|
|
d05f4b |
struct xwl_screen *xwl_screen;
|
|
|
d05f4b |
struct wl_buffer *buffer;
|
|
|
d05f4b |
- struct xwl_eglstream_pending_stream *pending_stream;
|
|
|
d05f4b |
+ struct wl_callback *pending_cb;
|
|
|
d05f4b |
Bool wait_for_buffer_release;
|
|
|
d05f4b |
|
|
|
d05f4b |
/* XWL_PIXMAP_EGLSTREAM. */
|
|
|
d05f4b |
@@ -301,20 +292,12 @@ xwl_eglstream_destroy_pixmap_stream(struct xwl_pixmap *xwl_pixmap)
|
|
|
d05f4b |
free(xwl_pixmap);
|
|
|
d05f4b |
}
|
|
|
d05f4b |
|
|
|
d05f4b |
-static void
|
|
|
d05f4b |
-xwl_glamor_eglstream_destroy_pending_stream(struct xwl_eglstream_pending_stream *pending)
|
|
|
d05f4b |
-{
|
|
|
d05f4b |
- if (pending->cb)
|
|
|
d05f4b |
- wl_callback_destroy(pending->cb);
|
|
|
d05f4b |
- free(pending);
|
|
|
d05f4b |
-}
|
|
|
d05f4b |
-
|
|
|
d05f4b |
static void
|
|
|
d05f4b |
xwl_glamor_eglstream_remove_pending_stream(struct xwl_pixmap *xwl_pixmap)
|
|
|
d05f4b |
{
|
|
|
d05f4b |
- if (xwl_pixmap->pending_stream) {
|
|
|
d05f4b |
- xwl_glamor_eglstream_destroy_pending_stream(xwl_pixmap->pending_stream);
|
|
|
d05f4b |
- xwl_pixmap->pending_stream = NULL;
|
|
|
d05f4b |
+ if (xwl_pixmap->pending_cb) {
|
|
|
d05f4b |
+ wl_callback_destroy(xwl_pixmap->pending_cb);
|
|
|
d05f4b |
+ xwl_pixmap->pending_cb = NULL;
|
|
|
d05f4b |
}
|
|
|
d05f4b |
}
|
|
|
d05f4b |
|
|
|
d05f4b |
@@ -338,27 +321,13 @@ xwl_glamor_eglstream_get_wl_buffer_for_pixmap(PixmapPtr pixmap)
|
|
|
d05f4b |
}
|
|
|
d05f4b |
|
|
|
d05f4b |
static void
|
|
|
d05f4b |
-xwl_eglstream_maybe_set_pending_stream_invalid(PixmapPtr pixmap)
|
|
|
d05f4b |
+xwl_eglstream_cancel_pending_stream(PixmapPtr pixmap)
|
|
|
d05f4b |
{
|
|
|
d05f4b |
struct xwl_pixmap *xwl_pixmap;
|
|
|
d05f4b |
- struct xwl_eglstream_pending_stream *pending;
|
|
|
d05f4b |
|
|
|
d05f4b |
xwl_pixmap = xwl_pixmap_get(pixmap);
|
|
|
d05f4b |
- if (!xwl_pixmap)
|
|
|
d05f4b |
- return;
|
|
|
d05f4b |
-
|
|
|
d05f4b |
- pending = xwl_pixmap->pending_stream;
|
|
|
d05f4b |
- if (!pending)
|
|
|
d05f4b |
- return;
|
|
|
d05f4b |
-
|
|
|
d05f4b |
- pending->is_valid = FALSE;
|
|
|
d05f4b |
-
|
|
|
d05f4b |
- /* The compositor may still be using the stream, so we can't destroy
|
|
|
d05f4b |
- * it yet. We'll only have a guarantee that the stream is safe to
|
|
|
d05f4b |
- * destroy once we receive the pending wl_display_sync() for this
|
|
|
d05f4b |
- * stream
|
|
|
d05f4b |
- */
|
|
|
d05f4b |
- pending->pixmap->refcnt++;
|
|
|
d05f4b |
+ if (xwl_pixmap)
|
|
|
d05f4b |
+ xwl_glamor_eglstream_remove_pending_stream(xwl_pixmap);
|
|
|
d05f4b |
}
|
|
|
d05f4b |
|
|
|
d05f4b |
static void
|
|
|
d05f4b |
@@ -378,7 +347,7 @@ xwl_eglstream_set_window_pixmap(WindowPtr window, PixmapPtr pixmap)
|
|
|
d05f4b |
*/
|
|
|
d05f4b |
old_pixmap = (*screen->GetWindowPixmap) (window);
|
|
|
d05f4b |
if (old_pixmap && old_pixmap != pixmap)
|
|
|
d05f4b |
- xwl_eglstream_maybe_set_pending_stream_invalid(old_pixmap);
|
|
|
d05f4b |
+ xwl_eglstream_cancel_pending_stream(old_pixmap);
|
|
|
d05f4b |
|
|
|
d05f4b |
xwl_screen->screen->SetWindowPixmap = xwl_eglstream->SetWindowPixmap;
|
|
|
d05f4b |
(*xwl_screen->screen->SetWindowPixmap)(window, pixmap);
|
|
|
d05f4b |
@@ -464,68 +433,19 @@ xwl_eglstream_print_error(EGLDisplay egl_display,
|
|
|
d05f4b |
}
|
|
|
d05f4b |
}
|
|
|
d05f4b |
|
|
|
d05f4b |
-/* Because we run asynchronously with our wayland compositor, it's possible
|
|
|
d05f4b |
- * that an X client event could cause us to begin creating a stream for a
|
|
|
d05f4b |
- * pixmap/window combo before the stream for the pixmap this window
|
|
|
d05f4b |
- * previously used has been fully initialized. An example:
|
|
|
d05f4b |
- *
|
|
|
d05f4b |
- * - Start processing X client events.
|
|
|
d05f4b |
- * - X window receives resize event, causing us to create a new pixmap and
|
|
|
d05f4b |
- * begin creating the corresponding eglstream. This pixmap is known as
|
|
|
d05f4b |
- * pixmap A.
|
|
|
d05f4b |
- * - X window receives another resize event, and again changes its current
|
|
|
d05f4b |
- * pixmap causing us to create another corresponding eglstream for the same
|
|
|
d05f4b |
- * window. This pixmap is known as pixmap B.
|
|
|
d05f4b |
- * - Start handling events from the wayland compositor.
|
|
|
d05f4b |
- *
|
|
|
d05f4b |
- * Since both pixmap A and B will have scheduled wl_display_sync events to
|
|
|
d05f4b |
- * indicate when their respective streams are connected, we will receive each
|
|
|
d05f4b |
- * callback in the original order the pixmaps were created. This means the
|
|
|
d05f4b |
- * following would happen:
|
|
|
d05f4b |
- *
|
|
|
d05f4b |
- * - Receive pixmap A's stream callback, attach its stream to the surface of
|
|
|
d05f4b |
- * the window that just orphaned it.
|
|
|
d05f4b |
- * - Receive pixmap B's stream callback, fall over and fail because the
|
|
|
d05f4b |
- * window's surface now incorrectly has pixmap A's stream attached to it.
|
|
|
d05f4b |
- *
|
|
|
d05f4b |
- * We work around this problem by keeping a pending stream associated with
|
|
|
d05f4b |
- * the xwl_pixmap, which itself is associated with the window pixmap.
|
|
|
d05f4b |
- * In the scenario listed above, this should happen:
|
|
|
d05f4b |
- *
|
|
|
d05f4b |
- * - Begin processing X events...
|
|
|
d05f4b |
- * - A window is resized, a new window pixmap is created causing us to
|
|
|
d05f4b |
- * add an eglstream (known as eglstream A) waiting for its consumer
|
|
|
d05f4b |
- * to finish attachment.
|
|
|
d05f4b |
- * - Resize on same window happens. We invalidate the previously pending
|
|
|
d05f4b |
- * stream on the old window pixmap.
|
|
|
d05f4b |
- * A new window pixmap is attached to the window and another pending
|
|
|
d05f4b |
- * stream is created for that new pixmap (known as eglstream B).
|
|
|
d05f4b |
- * - Begin processing Wayland events...
|
|
|
d05f4b |
- * - Receive invalidated callback from compositor for eglstream A, destroy
|
|
|
d05f4b |
- * stream.
|
|
|
d05f4b |
- * - Receive callback from compositor for eglstream B, create producer.
|
|
|
d05f4b |
- * - Success!
|
|
|
d05f4b |
- */
|
|
|
d05f4b |
static void
|
|
|
d05f4b |
xwl_eglstream_consumer_ready_callback(void *data,
|
|
|
d05f4b |
struct wl_callback *callback,
|
|
|
d05f4b |
uint32_t time)
|
|
|
d05f4b |
{
|
|
|
d05f4b |
- struct xwl_eglstream_pending_stream *pending = data;
|
|
|
d05f4b |
- PixmapPtr pixmap = pending->pixmap;
|
|
|
d05f4b |
+ PixmapPtr pixmap = data;
|
|
|
d05f4b |
struct xwl_pixmap *xwl_pixmap = xwl_pixmap_get(pixmap);
|
|
|
d05f4b |
struct xwl_screen *xwl_screen = xwl_pixmap->xwl_screen;
|
|
|
d05f4b |
struct xwl_eglstream_private *xwl_eglstream =
|
|
|
d05f4b |
xwl_eglstream_get(xwl_screen);
|
|
|
d05f4b |
|
|
|
d05f4b |
wl_callback_destroy(callback);
|
|
|
d05f4b |
- pending->cb = NULL;
|
|
|
d05f4b |
-
|
|
|
d05f4b |
- if (!pending->is_valid) {
|
|
|
d05f4b |
- xwl_glamor_eglstream_remove_pending_stream(xwl_pixmap);
|
|
|
d05f4b |
- dixDestroyPixmap(pixmap, 0);
|
|
|
d05f4b |
- return;
|
|
|
d05f4b |
- }
|
|
|
d05f4b |
+ xwl_pixmap->pending_cb = NULL;
|
|
|
d05f4b |
|
|
|
d05f4b |
xwl_glamor_egl_make_current(xwl_screen);
|
|
|
d05f4b |
|
|
|
d05f4b |
@@ -541,42 +461,16 @@ xwl_eglstream_consumer_ready_callback(void *data,
|
|
|
d05f4b |
ErrorF("eglstream: Failed to create EGLSurface for pixmap\n");
|
|
|
d05f4b |
xwl_eglstream_print_error(xwl_screen->egl_display,
|
|
|
d05f4b |
xwl_pixmap->stream, eglGetError());
|
|
|
d05f4b |
- goto out;
|
|
|
d05f4b |
+ } else {
|
|
|
d05f4b |
+ DebugF("eglstream: completes eglstream for pixmap %p, congrats!\n",
|
|
|
d05f4b |
+ pixmap);
|
|
|
d05f4b |
}
|
|
|
d05f4b |
-
|
|
|
d05f4b |
- DebugF("eglstream: win %d completes eglstream for pixmap %p, congrats!\n",
|
|
|
d05f4b |
- pending->window->drawable.id, pending->pixmap);
|
|
|
d05f4b |
-
|
|
|
d05f4b |
-out:
|
|
|
d05f4b |
- xwl_glamor_eglstream_remove_pending_stream(xwl_pixmap);
|
|
|
d05f4b |
}
|
|
|
d05f4b |
|
|
|
d05f4b |
static const struct wl_callback_listener consumer_ready_listener = {
|
|
|
d05f4b |
xwl_eglstream_consumer_ready_callback
|
|
|
d05f4b |
};
|
|
|
d05f4b |
|
|
|
d05f4b |
-static struct xwl_eglstream_pending_stream *
|
|
|
d05f4b |
-xwl_eglstream_queue_pending_stream(WindowPtr window, PixmapPtr pixmap)
|
|
|
d05f4b |
-{
|
|
|
d05f4b |
- struct xwl_pixmap *xwl_pixmap = xwl_pixmap_get(pixmap);
|
|
|
d05f4b |
- struct xwl_screen *xwl_screen = xwl_pixmap->xwl_screen;
|
|
|
d05f4b |
- struct xwl_eglstream_pending_stream *pending_stream;
|
|
|
d05f4b |
-
|
|
|
d05f4b |
- DebugF("eglstream: win %d queues new pending stream for pixmap %p\n",
|
|
|
d05f4b |
- window->drawable.id, pixmap);
|
|
|
d05f4b |
-
|
|
|
d05f4b |
- pending_stream = calloc(1, sizeof(*pending_stream));
|
|
|
d05f4b |
- pending_stream->window = window;
|
|
|
d05f4b |
- pending_stream->pixmap = pixmap;
|
|
|
d05f4b |
- pending_stream->is_valid = TRUE;
|
|
|
d05f4b |
-
|
|
|
d05f4b |
- pending_stream->cb = wl_display_sync(xwl_screen->display);
|
|
|
d05f4b |
- wl_callback_add_listener(pending_stream->cb, &consumer_ready_listener,
|
|
|
d05f4b |
- pending_stream);
|
|
|
d05f4b |
-
|
|
|
d05f4b |
- return pending_stream;
|
|
|
d05f4b |
-}
|
|
|
d05f4b |
-
|
|
|
d05f4b |
static void
|
|
|
d05f4b |
xwl_eglstream_buffer_release_callback(void *data)
|
|
|
d05f4b |
{
|
|
|
d05f4b |
@@ -656,9 +550,9 @@ xwl_eglstream_create_pixmap_and_stream(struct xwl_screen *xwl_screen,
|
|
|
d05f4b |
wl_eglstream_controller_attach_eglstream_consumer(
|
|
|
d05f4b |
xwl_eglstream->controller, xwl_window->surface, xwl_pixmap->buffer);
|
|
|
d05f4b |
|
|
|
d05f4b |
- xwl_pixmap->pending_stream =
|
|
|
d05f4b |
- xwl_eglstream_queue_pending_stream(window, pixmap);
|
|
|
d05f4b |
-
|
|
|
d05f4b |
+ xwl_pixmap->pending_cb = wl_display_sync(xwl_screen->display);
|
|
|
d05f4b |
+ wl_callback_add_listener(xwl_pixmap->pending_cb, &consumer_ready_listener,
|
|
|
d05f4b |
+ pixmap);
|
|
|
d05f4b |
fail:
|
|
|
d05f4b |
if (stream_fd >= 0)
|
|
|
d05f4b |
close(stream_fd);
|
|
|
d05f4b |
@@ -673,25 +567,22 @@ xwl_glamor_eglstream_allow_commits(struct xwl_window *xwl_window)
|
|
|
d05f4b |
struct xwl_pixmap *xwl_pixmap = xwl_pixmap_get(pixmap);
|
|
|
d05f4b |
|
|
|
d05f4b |
if (xwl_pixmap) {
|
|
|
d05f4b |
- struct xwl_eglstream_pending_stream *pending = xwl_pixmap->pending_stream;
|
|
|
d05f4b |
-
|
|
|
d05f4b |
- if (pending) {
|
|
|
d05f4b |
+ if (xwl_pixmap->pending_cb) {
|
|
|
d05f4b |
/* Wait for the compositor to finish connecting the consumer for
|
|
|
d05f4b |
* this eglstream */
|
|
|
d05f4b |
- assert(pending->is_valid);
|
|
|
d05f4b |
-
|
|
|
d05f4b |
return FALSE;
|
|
|
d05f4b |
- } else {
|
|
|
d05f4b |
- if (xwl_pixmap->surface != EGL_NO_SURFACE ||
|
|
|
d05f4b |
- xwl_pixmap->type == XWL_PIXMAP_DMA_BUF)
|
|
|
d05f4b |
- return TRUE;
|
|
|
d05f4b |
-
|
|
|
d05f4b |
- /* The pending stream got removed, we have a xwl_pixmap and
|
|
|
d05f4b |
- * yet we do not have a surface.
|
|
|
d05f4b |
- * So something went wrong with the surface creation, retry.
|
|
|
d05f4b |
- */
|
|
|
d05f4b |
- xwl_eglstream_destroy_pixmap_stream(xwl_pixmap);
|
|
|
d05f4b |
}
|
|
|
d05f4b |
+
|
|
|
d05f4b |
+ if (xwl_pixmap->surface != EGL_NO_SURFACE ||
|
|
|
d05f4b |
+ xwl_pixmap->type == XWL_PIXMAP_DMA_BUF) {
|
|
|
d05f4b |
+ return TRUE;
|
|
|
d05f4b |
+ }
|
|
|
d05f4b |
+
|
|
|
d05f4b |
+ /* The pending stream got removed, we have a xwl_pixmap and
|
|
|
d05f4b |
+ * yet we do not have a surface.
|
|
|
d05f4b |
+ * So something went wrong with the surface creation, retry.
|
|
|
d05f4b |
+ */
|
|
|
d05f4b |
+ xwl_eglstream_destroy_pixmap_stream(xwl_pixmap);
|
|
|
d05f4b |
}
|
|
|
d05f4b |
|
|
|
d05f4b |
/* Glamor pixmap has no backing stream yet; begin making one and disallow
|
|
|
d05f4b |
--
|
|
|
d05f4b |
2.31.1
|
|
|
d05f4b |
|