xwayland/eglstream: Do not always increment pixmap refcnt on commit

Currently, the EGLstream backend would increment the pixmap refcount for
each commit, and decrease that refcount on the wl_buffer release
callback.

But that's relying on the compositor sending us a release callback for
each commit, otherwise the pixmap refcount will keep increasing and the
pixmap will be leaked.

So instead, increment the refcount on the pixmap only when we have not
received a release notification for the wl_buffer, to avoid increasing
the pixmap refcount more than once without a corresponding release
event.

This way, if the pixmap is still in use when released on the X11 side,
the EGL stream will be kept until the compositor releases it.

Signed-off-by: Olivier Fourdan <ofourdan@redhat.com>
Suggested-by: Michel Dänzer <mdaenzer@redhat.com>
Reviewed-by: Michel Dänzer <mdaenzer@redhat.com>
This commit is contained in:
Olivier Fourdan 2021-05-04 10:56:38 +02:00
parent b583395cd3
commit d85bfa6ab7
1 changed files with 17 additions and 4 deletions

View File

@ -89,6 +89,7 @@ struct xwl_pixmap {
struct xwl_screen *xwl_screen;
struct wl_buffer *buffer;
struct xwl_eglstream_pending_stream *pending_stream;
Bool wait_for_buffer_release;
/* XWL_PIXMAP_EGLSTREAM. */
EGLStreamKHR stream;
@ -577,8 +578,16 @@ xwl_eglstream_queue_pending_stream(WindowPtr window, PixmapPtr pixmap)
static void
xwl_eglstream_buffer_release_callback(void *data)
{
/* drop the reference we took in post_damage, freeing if necessary */
dixDestroyPixmap(data, 0);
PixmapPtr pixmap = data;
struct xwl_pixmap *xwl_pixmap = xwl_pixmap_get(pixmap);
assert(xwl_pixmap);
if (xwl_pixmap->wait_for_buffer_release) {
xwl_pixmap->wait_for_buffer_release = FALSE;
/* drop the reference we took in the ready callback, freeing if necessary */
dixDestroyPixmap(pixmap, 0);
}
}
static const struct wl_buffer_listener xwl_eglstream_buffer_release_listener = {
@ -606,6 +615,7 @@ xwl_eglstream_create_pixmap_and_stream(struct xwl_screen *xwl_screen,
xwl_glamor_egl_make_current(xwl_screen);
xwl_pixmap->wait_for_buffer_release = FALSE;
xwl_pixmap->xwl_screen = xwl_screen;
xwl_pixmap->surface = EGL_NO_SURFACE;
xwl_pixmap->stream = eglCreateStreamKHR(xwl_screen->egl_display, NULL);
@ -762,8 +772,11 @@ xwl_glamor_eglstream_post_damage(struct xwl_window *xwl_window,
goto out;
}
/* hang onto the pixmap until the compositor has released it */
pixmap->refcnt++;
if (!xwl_pixmap->wait_for_buffer_release) {
/* hang onto the pixmap until the compositor has released it */
pixmap->refcnt++;
xwl_pixmap->wait_for_buffer_release = TRUE;
}
out:
/* Restore previous state */