diff options
author | Erik Kurzinger <ekurzinger@nvidia.com> | 2021-05-11 17:00:21 -0400 |
---|---|---|
committer | Olivier Fourdan <fourdan@gmail.com> | 2021-05-20 12:46:23 +0000 |
commit | 7515c23a416825f0db51f9b445279b12d5918ebf (patch) | |
tree | ca5f7026b267e9be9a5bb01988023a20f976f59b /hw/xwayland/xwayland-glamor-eglstream.c | |
parent | f3eb1684fa5008ad7c881f798a5efb7441b23035 (diff) | |
download | xserver-7515c23a416825f0db51f9b445279b12d5918ebf.tar.gz |
xwayland/eglstream: flush stream after eglSwapBuffers
When eglSwapBuffers inserts a new frame into a window's stream, there may be a
delay before the state of the consumer end of the stream is updated to reflect
this. If the subsequent wl_surface_attach, wl_surface_damage, wl_surface_commit
calls are received by the compositor before then, it will (typically) re-use
the previous frame acquired from the stream instead of the latest one.
This can leave the window displaying out-of-date contents, which might never be
updated thereafter.
To fix this, after calling eglSwapBuffers, xwl_glamor_eglstream_post_damage
should call eglStreamFlushNV. This call will block until it can be guaranteed
that the state of the consumer end of the stream has been updated to reflect
that a new frame is available.
Closes: https://gitlab.freedesktop.org/xorg/xserver/-/issues/1171
Signed-off-by: Erik Kurzinger <ekurzinger@nvidia.com>
Diffstat (limited to 'hw/xwayland/xwayland-glamor-eglstream.c')
-rw-r--r-- | hw/xwayland/xwayland-glamor-eglstream.c | 20 |
1 files changed, 20 insertions, 0 deletions
diff --git a/hw/xwayland/xwayland-glamor-eglstream.c b/hw/xwayland/xwayland-glamor-eglstream.c index 2d0827709..c583a1390 100644 --- a/hw/xwayland/xwayland-glamor-eglstream.c +++ b/hw/xwayland/xwayland-glamor-eglstream.c @@ -72,6 +72,7 @@ struct xwl_eglstream_private { SetWindowPixmapProcPtr SetWindowPixmap; Bool have_egl_damage; + Bool have_egl_stream_flush; GLint blit_prog; GLuint blit_vao; @@ -776,6 +777,13 @@ xwl_glamor_eglstream_post_damage(struct xwl_window *xwl_window, goto out; } +#ifdef EGL_NV_stream_flush + if (xwl_eglstream->have_egl_stream_flush) + /* block until stream state is updated on the compositor's side */ + eglStreamFlushNV(xwl_screen->egl_display, + xwl_pixmap->stream); +#endif + if (!xwl_pixmap->wait_for_buffer_release) { /* hang onto the pixmap until the compositor has released it */ pixmap->refcnt++; @@ -1173,6 +1181,18 @@ xwl_glamor_eglstream_init_egl(struct xwl_screen *xwl_screen) ErrorF("Driver lacks EGL_KHR_swap_buffers_with_damage, performance " "will be affected\n"); +#ifdef EGL_NV_stream_flush + xwl_eglstream->have_egl_stream_flush = + epoxy_has_egl_extension(xwl_screen->egl_display, + "EGL_NV_stream_flush"); +#else + xwl_eglstream->have_egl_stream_flush = FALSE; +#endif /* EGL_NV_stream_flush */ + + if (!xwl_eglstream->have_egl_stream_flush) + ErrorF("EGL_NV_stream_flush not available, " + "this may cause visible corruption.\n"); + xwl_eglstream_init_shaders(xwl_screen); if (epoxy_has_gl_extension("GL_OES_EGL_image") && |