summaryrefslogtreecommitdiff
path: root/src/helpers/Monitor.cpp
diff options
context:
space:
mode:
authorVaxry <vaxry@vaxry.net>2025-10-27 13:34:08 +0000
committerVaxry <vaxry@vaxry.net>2025-10-27 13:34:14 +0000
commit560c53d87dedf7df8185eb370cfbf3575826e85c (patch)
tree0087bc0c761ec5502b0c880c952126b85e928aa5 /src/helpers/Monitor.cpp
parentfd42e9d0826e8af71dd6dc40e10f590169afae6d (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.cpp27
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;
}