From 560c53d87dedf7df8185eb370cfbf3575826e85c Mon Sep 17 00:00:00 2001 From: Vaxry Date: Mon, 27 Oct 2025 13:34:08 +0000 Subject: monitor/dpms: fix possible invalid state If dpms gets immediately re-enabled, a commit could fail, not schedule any frames anymore, and the monitor would be stuck off. Fix this by adding a timer to retry if commit fails. ref #12045 --- src/helpers/Monitor.cpp | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) (limited to 'src/helpers/Monitor.cpp') diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index ac9c065f..e12a4bff 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -1882,13 +1882,14 @@ void CMonitor::setDPMS(bool on) { if (on) { // enable the monitor. Wait for the frame to be presented, then begin animation - m_dpmsBlackOpacity->setValueAndWarp(1.F); m_dpmsBlackOpacity->setCallbackOnEnd(nullptr); + m_dpmsBlackOpacity->setValueAndWarp(1.F); m_pendingDpmsAnimation = true; m_pendingDpmsAnimationCounter = 0; commitDPMSState(true); } else { // disable the monitor. Begin the animation, then do dpms on its end. + m_dpmsBlackOpacity->setCallbackOnEnd(nullptr); m_dpmsBlackOpacity->setValueAndWarp(0.F); *m_dpmsBlackOpacity = 1.F; m_dpmsBlackOpacity->setCallbackOnEnd( @@ -1908,7 +1909,29 @@ void CMonitor::commitDPMSState(bool state) { m_output->state->setEnabled(state); if (!m_state.commit()) { - Debug::log(ERR, "Couldn't commit output {} for DPMS = {}", m_name, state); + Debug::log(ERR, "Couldn't commit output {} for DPMS = {}, will retry.", m_name, state); + + // retry in 2 frames. This could happen when the DRM backend rejects our commit + // because disable + enable were sent almost instantly + + m_dpmsRetryTimer = makeShared( + std::chrono::milliseconds(2000 / sc(m_refreshRate)), + [this, self = m_self](SP s, void* d) { + if (!self) + return; + + m_output->state->resetExplicitFences(); + m_output->state->setEnabled(m_dpmsStatus); + if (!m_state.commit()) { + Debug::log(ERR, "Couldn't retry committing output {} for DPMS = {}", m_name, m_dpmsStatus); + return; + } + + m_dpmsRetryTimer.reset(); + }, + nullptr); + g_pEventLoopManager->addTimer(m_dpmsRetryTimer); + return; } -- cgit v1.2.3