eglSwapBuffers blocks in wayland when it's wl_surface_frame event is stolen.
I've been trying write a desktop bar to replace swaybar. But after a recent system update, it would just stop drawing at random times, only to be brought back to life by moving the mouse over it. After determining the issue was eglSwapBuffers blocking for no documented reason I could determine, I spent several days trying to figure it out and I think I've tracked it down to the wayland EGL drivers. This is what I believe is going on...
Assume we're starting with at least one frame already presented
- I do my drawing operations in my main thread.
- At some point
get_back_bo()
in platform_wayland.c gets called in a second thread. - I call
eglSwapBuffers()
in my main thread. -
get_back_bo()
callswl_display_dispatch_queue_pending()
in the second thread. -
dri2_wl_swap_buffers_with_damage()
testsdri2_surf->throttle_callback
in the main thread, determining that a frame event is pending. -
wl_display_dispatch_queue_pending()
in the second thread dispatches the frame event,dri2_surf->throttle_callback
gets set to null. -
dri2_wl_swap_buffers_with_damage()
callswl_display_dispatch_queue()
in the main thread, expecting a frame event. -
wl_display_dispatch_queue()
blocks, waiting for an event that's already been removed from the queue.