Skip to content

Draft: backends/drm: support tearing with atomic modesetting

Xaver Hugl requested to merge work/zamundaaa/atomic-tearing into work/zamundaaa/frames

With legacy, async pageflips automatically fall back to sync pageflips when they're not possible, but with atomic modesetting the commit fails instead. To handle when that happens I adjusted how frame scheduling is decided: RenderLoop no longer controls the presentation mode. Instead, the Compositor suggests a presentation mode to the backend, which attempts to do it, potentially falls back to normal VSync presentation, and only afterwards tells RenderLoop about it. If async presentation isn't possible / the atomic commits fail, the RenderLoop thus never changes its frame scheduling behavior, instead of continuously attempting to composite and commit new frames.

Another annoyance with async atomic commits is that only FB_ID can be changed. I didn't want to special-case tearing everywhere, so I only disable the hardware cursor and the commit thread keeps the last actually committed state around. If tearing is attempted, it only tells the kernel about the difference between the current and the last commit; whenever KWin changes more than just FB_ID, the async commit simply fails and everything should gracefully fall back to sync commits until we only do pageflips again.

I marked this both bugfix and feature, because while it's kind of a feature, we've had the checkbox for this in the GUI for a long time - a checkbox that's broken unless the user manually messes around with env vars... The risk of this causing regressions is pretty low, so I'd like to push this as a bugfix for 6.0.

This can be tested with https://cgit.freedesktop.org/drm/drm-misc/commit/?id=0e26cc72c71cb98e951716a6596060cd04b0ba6b, https://cgit.freedesktop.org/drm/drm-misc/commit/?id=4b4af74ab9719d17538a97f43137e93296ec7437 and https://cgit.freedesktop.org/drm/drm-misc/commit/?id=e4d983acffff270ccee417445a69b9ed198658b1 on top of Linux 6.6. Afaik these should be in 6.8 when that releases.

Draft because

  • the commit thread needs a better record of the last state. It needs to merge new commits into the "current state" one, so that the commit comparisons actually work. For testing I just added a hack, and it does work with that
  • the kernel really only allows FB_ID, not even IN_FENCE_FD is allowed. I think this should be fixed on the kernel side and not worked around in KWin
Edited by Xaver Hugl

Merge request reports