canonical / canonical/mir

Wayland frontend and server hang rendering threads when the screen turns off

Open
#2,136 3 comments 0 reactions 0 assignees View on GitHub
Dominant language
C++
Stars
786
Forks
139
Avg merge
5d 37m
Merged PRs (30d)
41

Description

The TMI version of this issue's investigation for Lomiri is https://gitlab.com/ubports/core/lomiri-system-compositor/-/issues/11

TL;DR: When the display turns off on a Mesa system, the mir_frontend's `swap_buffers` will hang after one successful frame. This is because Mesa throttles Wayland frame callbacks to no more than one per vsync, and the vsync has stopped when the display is off. Even if `eglSwapInterval` is set to 0, frame callbacks are throttled.

This seems to be expected behavior from a Wayland compositor, and in fact Mir is much more lenient than other compositors: opinionated compositors like wlroots and Clutter (not so sure about Clutter, but it seems to be part of the folklore online) will stop frame callbacks whenever a client is completely occluded by another client. This is efficient I suppose, saving CPU and GPU resources in buffer swaps and continuous rendering for a client that the user can't see. So I believe that we should not try and change this behavior with secret background timeouts in `swap_buffers` or the like.

However, every interesting Wayland application and toolkit has had to work around this problem since no other compositing protocol on the planet seems to do this. [Firefox](https://bugzilla.mozilla.org/show_bug.cgi?id=1489902) and [Qt](https://bugreports.qt.io/browse/QTBUG-69077) are two examples. [Qt's workaround](https://github.com/qt/qtwayland/commit/85bb158ddf08aca4d76c13c6a9fcd2637d84d3ea) involves timing out the wait for the frame callback and cancelling any further rendering, but I don't think that's a viable solution here. While it's not okay for your web browser or Qt application to hang up because the render thread is blocked on eglSwapBuffers, that's a design decision in many applications. The function which contains eglSwapBuffers often contains other side effects. Without eglSwapBuffers and those side effects completing as assumed, it might not be safe to advance the rendering or main threads.

This issue presents in `egmde` running under Sway since wlroots stops sending frame callbacks to occluded applications. To reproduce the problem, run `egmde` in a terminal (you can open your terminal with Windows+Enter). Move the `egmde` window to another workspace (Windows+Shift+2). Send an interrupt to the egmde process with Control+C in the terminal. Notice the egmde will never actually shut down.

There is some upstream work in Wayland to resolve this problem. [surface-suspension](https://gitlab.freedesktop.org/wayland/wayland-protocols/-/merge_requests/99) is a protocol which allows the compositor to tell the client when its surface is suspended and it will no longer receive any frame callbacks. In the world as intended by this proposal, it seems that we would want all clients on a given (screen? display? display_server?) to be given the suspended signal when vsync is expected to stop.

Contributor guide

No contributing guide indexed for this repository

Research direction

Start with the mir_frontend swap_buffers path and reproduce the egmde hang under Sway using the workspace and Control+C steps in the issue. Read the linked Wayland surface-suspension proposal and related compositor work before deciding on a supported resolution. Done should mean rendering or shutdown no longer hangs when frame callbacks stop, with the behavior verified in the reproduction case.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp, linux
Domain
desktop, operating-systems
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.