diff options
| author | Vaxry <vaxry@vaxry.net> | 2025-10-27 13:34:08 +0000 |
|---|---|---|
| committer | Vaxry <vaxry@vaxry.net> | 2025-10-27 13:34:14 +0000 |
| commit | 560c53d87dedf7df8185eb370cfbf3575826e85c (patch) | |
| tree | 0087bc0c761ec5502b0c880c952126b85e928aa5 /src/helpers/Monitor.cpp | |
| parent | fd42e9d0826e8af71dd6dc40e10f590169afae6d (diff) | |
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
Diffstat (limited to 'src/helpers/Monitor.cpp')
| -rw-r--r-- | src/helpers/Monitor.cpp | 27 |
1 files changed, 25 insertions, 2 deletions
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<CEventLoopTimer>( + std::chrono::milliseconds(2000 / sc<int>(m_refreshRate)), + [this, self = m_self](SP<CEventLoopTimer> 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; } |
