diff options
| author | Vaxry <43317083+vaxerski@users.noreply.github.com> | 2025-08-17 17:14:29 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-08-17 17:14:29 +0100 |
| commit | 0840103ae06e9d6ab4a8692ff18dc45e2e95e5c9 (patch) | |
| tree | 7ad40d8255cd25331074c7686ed601da2b618738 /src/helpers/Monitor.cpp | |
| parent | 251288ec5942b3544ad31de1299569284d80f0d7 (diff) | |
renderer: improve modeset timings (#11461)
some CRTCs will just happily eat frames and we can't do much. Some will eat one.
Adds a 5-frame buffer to DPMS and Added animations. Better than nothing.
Diffstat (limited to 'src/helpers/Monitor.cpp')
| -rw-r--r-- | src/helpers/Monitor.cpp | 39 |
1 files changed, 33 insertions, 6 deletions
diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 79961bd4..d6d9fedd 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -66,6 +66,7 @@ void CMonitor::onConnect(bool noRule) { CScopeGuard x = {[]() { g_pCompositor->arrangeMonitors(); }}; m_zoomAnimProgress->setValueAndWarp(0.F); + m_zoomAnimFrameCounter = 0; g_pEventLoopManager->doLater([] { g_pConfigManager->ensurePersistentWorkspacesPresent(); }); @@ -83,10 +84,17 @@ void CMonitor::onConnect(bool noRule) { m_listeners.presented = m_output->events.present.listen([this](const Aquamarine::IOutput::SPresentEvent& event) { if (m_pendingDpmsAnimation) { - // the first frame after a dpms on has been presented. Let's start the animation + m_pendingDpmsAnimationCounter++; + // we give ourselves 5 frames of a buffer. The first presentation event still doesn't usually say that we actually + // are scanning out to the CRTC, and it could still be modesetting. + // this is not ideal (some CRTCs will just eat frames) but it's better than nothing + m_dpmsBlackOpacity->setValueAndWarp(1.F); - *m_dpmsBlackOpacity = 0.F; - m_pendingDpmsAnimation = false; + + if (m_pendingDpmsAnimationCounter == 5) { + *m_dpmsBlackOpacity = 0.F; + m_pendingDpmsAnimation = false; + } } timespec* ts = event.when; @@ -102,8 +110,26 @@ void CMonitor::onConnect(bool noRule) { else PROTO::presentation->onPresented(m_self.lock(), Time::fromTimespec(event.when), event.refresh, event.seq, event.flags); - if (m_zoomAnimProgress->goal() == 0.F) - *m_zoomAnimProgress = 1.F; + if (m_zoomAnimFrameCounter < 5) { + m_zoomAnimFrameCounter++; + + // we give ourselves 5 frames of a buffer. The first presentation event still doesn't usually say that we actually + // are scanning out to the CRTC, and it could still be modesetting. + // this is not ideal (some CRTCs will just eat frames) but it's better than nothing + m_zoomAnimProgress->setValueAndWarp(0.F); + if (m_zoomAnimFrameCounter == 5) { + // start the animation for realzies + *m_zoomAnimProgress = 1.F; + } + + // damage the entire display to force a frame immediately + g_pEventLoopManager->doLater([self = m_self] { + if (!self) + return; + + g_pHyprRenderer->damageMonitor(self.lock()); + }); + } m_frameScheduler->onPresented(); }); @@ -1580,7 +1606,8 @@ void CMonitor::setDPMS(bool on) { // enable the monitor. Wait for the frame to be presented, then begin animation m_dpmsBlackOpacity->setValueAndWarp(1.F); m_dpmsBlackOpacity->setCallbackOnEnd(nullptr); - m_pendingDpmsAnimation = true; + m_pendingDpmsAnimation = true; + m_pendingDpmsAnimationCounter = 0; commitDPMSState(true); } else { // disable the monitor. Begin the animation, then do dpms on its end. |
