Module: Mesa Branch: staging/23.1 Commit: 40e9ad07ec0d5564fe9fb716cc54b86411c41f74 URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=40e9ad07ec0d5564fe9fb716cc54b86411c41f74
Author: Robert Mader <[email protected]> Date: Tue Jul 11 16:24:41 2023 +0200 egl/wayland: wait for compositor to release shm buffers Some Wayland compositors, notably Exo, do not always release buffers fast enough, and not in sync with their frame callbacks, to guarantee that a free buffer is available the next time a client calls `eglSwapBuffers()`. This currently leads to a crash in `dri2_wl_swrast_get_backbuffer_data()` with the swrast backend. To avoid this, simply block until the compositor releases a buffer eventually. While arguably compositors should release buffers they don't need any more for the next frame, this can be quite complex depending on the architecture - notably multi-process/IPC in case of Exo. cc: mesa-stable Signed-off-by: Robert Mader <[email protected]> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/24091> (cherry picked from commit 74451ed3f0832694c8c1fb8fbfe42b4ed2688d4a) --- .pick_status.json | 2 +- src/egl/drivers/dri2/platform_wayland.c | 14 +++++++++----- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/.pick_status.json b/.pick_status.json index 07c937514e8..b930171dba3 100644 --- a/.pick_status.json +++ b/.pick_status.json @@ -1732,7 +1732,7 @@ "description": "egl/wayland: wait for compositor to release shm buffers", "nominated": true, "nomination_type": 0, - "resolution": 0, + "resolution": 1, "main_sha": null, "because_sha": null }, diff --git a/src/egl/drivers/dri2/platform_wayland.c b/src/egl/drivers/dri2/platform_wayland.c index 4a896269d0c..8940c54bc5c 100644 --- a/src/egl/drivers/dri2/platform_wayland.c +++ b/src/egl/drivers/dri2/platform_wayland.c @@ -2436,7 +2436,7 @@ swrast_update_buffers(struct dri2_egl_surface *dri2_surf) } /* else choose any another free location */ - if (!dri2_surf->back) { + while (!dri2_surf->back) { for (int i = 0; i < ARRAY_SIZE(dri2_surf->color_buffers); i++) { if (!dri2_surf->color_buffers[i].locked) { dri2_surf->back = &dri2_surf->color_buffers[i]; @@ -2457,11 +2457,15 @@ swrast_update_buffers(struct dri2_egl_surface *dri2_surf) break; } } - } - if (!dri2_surf->back) { - _eglError(EGL_BAD_ALLOC, "failed to find free buffer"); - return -1; + /* wait for the compositor to release a buffer */ + if (!dri2_surf->back) { + if (wl_display_dispatch_queue(dri2_dpy->wl_dpy, dri2_surf->wl_queue) == + -1) { + _eglError(EGL_BAD_ALLOC, "waiting for a free buffer failed"); + return -1; + } + } } dri2_surf->back->locked = true;
