Skip to content

wayland/surface: Avoid using buffers with unfinished client work, sub-surface fixes

If mutter's GPU work directly depends on unfinished client work, mutter's work can only start once the client work has finished, even if mutter is using a higher priority EGL context. This is sort of like a priority inversion, which makes it impossible for mutter's frame rate to exceed that of heavy clients.

When scanning out directly from client buffers, unfinished client work can cause the page flip to miss the next display refresh cycle, resulting in the previous frame being displayed again instead for another refresh cycle. This can be noticeable as stutter if another buffer was attached in between which would have been ready in time for the next refresh cycle.

To avoid these issues, wait for newly attached buffers to become idle before making use of them. Sounds easy, right? :) It's rather complex in fact, because the Wayland protocol allows clients to commit arbitrary other surface state changes together with attaching a new buffer. mutter must ensure that all state changes committed together by the client are also applied together atomically. (It gets even more complex than that for synchronized sub-surfaces)

To achieve this, introduce transactions consisting of state changes for one or multiple Wayland surfaces. All Wayland surface commits (plus sub-surface state changes which aren't part of commits) are handled as transactions. Before applying a transaction, wait for

  1. all newly attached buffers it references to become idle (to avoid the issues described above)
  2. all earlier committed transactions which reference any of the same surfaces to be applied first (to ensure that state for a given surface is applied in the same order as it was committed by the client)

This fixes #1162 (closed) if the GPU & drivers support high priority contexts which can preempt lower priority contexts.

There are also fixes for various aspects related to sub-surfaces. In particular, the weston-subsurfaces demo now works correctly when run with the -r1/-t1 command line parameters. Nested hierarchies of synchronized sub-surfaces should now work more correctly as well (I don't know of any test case for that though).

Reasons for draft status:

  • The meta_wayland_buffer_attach call needs to be moved from meta_wayland_surface_apply_state to meta_wayland_surface_commit, otherwise mutter will either crash or disconnect the client if the latter destroys the wl_buffer before the transaction is applied.
  • I hit a crash which looks like memory corruption, investigating.
  • Some state may not be handled fully correctly yet for protocol vs output.

I'd also like to make at least a proof of concept that this transaction mechanism is useful for the wp_transaction Wayland protocol as well. But I don't consider this a blocker.

Edited by Michel Dänzer

Merge request reports