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:
parent
b583395cd3
commit
d85bfa6ab7
|
@ -89,6 +89,7 @@ struct xwl_pixmap {
|
||||||
struct xwl_screen *xwl_screen;
|
struct xwl_screen *xwl_screen;
|
||||||
struct wl_buffer *buffer;
|
struct wl_buffer *buffer;
|
||||||
struct xwl_eglstream_pending_stream *pending_stream;
|
struct xwl_eglstream_pending_stream *pending_stream;
|
||||||
|
Bool wait_for_buffer_release;
|
||||||
|
|
||||||
/* XWL_PIXMAP_EGLSTREAM. */
|
/* XWL_PIXMAP_EGLSTREAM. */
|
||||||
EGLStreamKHR stream;
|
EGLStreamKHR stream;
|
||||||
|
@ -577,8 +578,16 @@ xwl_eglstream_queue_pending_stream(WindowPtr window, PixmapPtr pixmap)
|
||||||
static void
|
static void
|
||||||
xwl_eglstream_buffer_release_callback(void *data)
|
xwl_eglstream_buffer_release_callback(void *data)
|
||||||
{
|
{
|
||||||
/* drop the reference we took in post_damage, freeing if necessary */
|
PixmapPtr pixmap = data;
|
||||||
dixDestroyPixmap(data, 0);
|
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 = {
|
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_glamor_egl_make_current(xwl_screen);
|
||||||
|
|
||||||
|
xwl_pixmap->wait_for_buffer_release = FALSE;
|
||||||
xwl_pixmap->xwl_screen = xwl_screen;
|
xwl_pixmap->xwl_screen = xwl_screen;
|
||||||
xwl_pixmap->surface = EGL_NO_SURFACE;
|
xwl_pixmap->surface = EGL_NO_SURFACE;
|
||||||
xwl_pixmap->stream = eglCreateStreamKHR(xwl_screen->egl_display, NULL);
|
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;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* hang onto the pixmap until the compositor has released it */
|
if (!xwl_pixmap->wait_for_buffer_release) {
|
||||||
pixmap->refcnt++;
|
/* hang onto the pixmap until the compositor has released it */
|
||||||
|
pixmap->refcnt++;
|
||||||
|
xwl_pixmap->wait_for_buffer_release = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
/* Restore previous state */
|
/* Restore previous state */
|
||||||
|
|
Loading…
Reference in New Issue
Block a user