backend/drm: fix drmModePageFlip() when disabling CRTC on legacy uAPI

drmModePageFlip() will fail with EBUSY on a disabled CRTC.

We can't fix this by clearing the DRM_MODE_PAGE_FLIP_EVENT when
performing a commit which disables CRTCs, because some device-wide
commits might also page-flip other enabled CRTCs (and skipping the
page-flip event would mess up our buffer tracking).

Fix this by immediately completing page-flips which disable a CRTC
on the legacy uAPI.

Closes: https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/3918
This commit is contained in:
Simon Ser 2024-11-23 15:29:44 +01:00
parent 9aca985865
commit 3e651b4642
2 changed files with 14 additions and 2 deletions

View file

@ -582,6 +582,16 @@ static void drm_connector_apply_commit(const struct wlr_drm_connector_state *sta
conn->cursor_enabled = false;
conn->crtc = NULL;
// Legacy uAPI doesn't support requesting page-flip events when
// turning off a CRTC
if (page_flip != NULL && conn->backend->iface == &legacy_iface) {
drm_page_flip_pop(page_flip, crtc->id);
conn->pending_page_flip = NULL;
if (page_flip->connectors_len == 0) {
drm_page_flip_destroy(page_flip);
}
}
}
}

View file

@ -150,7 +150,7 @@ static bool legacy_crtc_commit(const struct wlr_drm_connector_state *state,
state->base->adaptive_sync_enabled ? "enabled" : "disabled");
}
if (cursor != NULL && drm_connector_is_cursor_visible(conn)) {
if (cursor != NULL && state->active && drm_connector_is_cursor_visible(conn)) {
struct wlr_drm_fb *cursor_fb = state->cursor_fb;
if (cursor_fb == NULL) {
wlr_drm_conn_log(conn, WLR_DEBUG, "Failed to acquire cursor FB");
@ -192,7 +192,9 @@ static bool legacy_crtc_commit(const struct wlr_drm_connector_state *state,
}
}
if (flags & DRM_MODE_PAGE_FLIP_EVENT) {
// Legacy uAPI doesn't support requesting page-flip events when
// turning off a CRTC
if (state->active && (flags & DRM_MODE_PAGE_FLIP_EVENT)) {
if (drmModePageFlip(drm->fd, crtc->id, fb_id, flags, page_flip)) {
wlr_drm_conn_log_errno(conn, WLR_ERROR, "drmModePageFlip failed");
return false;