backend/drm: fix queued cursor FB overwritten with NULL

With the following sequence of events, the cursor FB fields could
end up being all set to NULL while the cursor is enabled:

1. set_cursor is called, conn->cursor_pending_fb is set to a FB
   pointer.
2. The output is committed with a buffer. crtc->cursor->queued_fb
   is set to the FB pointer, conn->cursor_pending_fb is reset to
   NULL. A page-flip event is expected in the future.
3. The output is committed with a modeset before the page-flip
   event is triggered. crtc->cursor->queued_fb is reset to NULL.

At this point all of crtc->cursor->current_fb,
crtc->cursor->queued_fb and conn->cursor_pending_fb are NULL which
is a bogus state when the cursor plane is enabled.

To avoid this issue, avoid overwriting crtc->cursor->queued_fb
with a NULL pointer on commit. The cursor logic still isn't great,
but let's keep a rework of that for a separate patch.

Closes: https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/3734
This commit is contained in:
Simon Ser 2024-02-28 13:37:58 +01:00 committed by Simon Zeni
parent e3ab52af7b
commit f5889319f7

View file

@ -471,7 +471,7 @@ static bool drm_crtc_commit(struct wlr_drm_connector *conn,
if (state->primary_fb != NULL) {
crtc->primary->queued_fb = drm_fb_lock(state->primary_fb);
}
if (crtc->cursor != NULL) {
if (crtc->cursor != NULL && conn->cursor_pending_fb != NULL) {
drm_fb_move(&crtc->cursor->queued_fb, &conn->cursor_pending_fb);
}