From 98a83ce14c96f4727791e9a63fd606fdcaa008fc Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Mon, 17 Oct 2022 12:29:38 +0200 Subject: [PATCH] backend/drm: fix EINVAL atomic commits after VT switch The drm_connector_commit_state() call in handle_session_active() was not resulting in any atomic commit, because it didn't match any of the if branches: active = true, no new buffer was committed, and adaptive sync/gamma LUT were unchanged. Thus the commit was a no-op. Later on, when the compositor performs regular page-flips, the kernel would return EINVAL indicating that a modeset was needed. Rework the logic to use a non-blocking page-flip commit if a buffer was committed, and use a blocking commit if the connector is on or is being disabled. The only case where we should skip the atomic commit is when disabling (active = false) an already-disabled connector (conn->crtc == NULL). Note, 6936e163b514 ("backend/drm: short-circuit no-op commits") has introduced early returns for other situations where we don't need to perform an atomic commit (e.g. updating scale or transform of an output). Fixes: f216e979836a ("backend/drm: drop drm_connector_set_mode()") Closes: https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/3432 --- backend/drm/drm.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/backend/drm/drm.c b/backend/drm/drm.c index 24b31c8b..b54919d9 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -592,18 +592,11 @@ bool drm_connector_commit_state(struct wlr_drm_connector *conn, } } - if (!pending.active) { - if (conn->crtc != NULL && !drm_crtc_commit(conn, &pending, 0, false)) { - return false; - } - } else if (pending.base->committed & WLR_OUTPUT_STATE_BUFFER) { + if (pending.base->committed & WLR_OUTPUT_STATE_BUFFER) { if (!drm_crtc_page_flip(conn, &pending)) { return false; } - } else if (pending.base->committed & (WLR_OUTPUT_STATE_ADAPTIVE_SYNC_ENABLED | - WLR_OUTPUT_STATE_GAMMA_LUT)) { - assert(conn->crtc != NULL); - // TODO: maybe request a page-flip event here? + } else if (pending.active || conn->crtc != NULL) { if (!drm_crtc_commit(conn, &pending, 0, false)) { return false; }