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.
This commit is contained in:
parent
251288ec59
commit
0840103ae0
3 changed files with 38 additions and 8 deletions
|
|
@ -66,6 +66,7 @@ void CMonitor::onConnect(bool noRule) {
|
||||||
CScopeGuard x = {[]() { g_pCompositor->arrangeMonitors(); }};
|
CScopeGuard x = {[]() { g_pCompositor->arrangeMonitors(); }};
|
||||||
|
|
||||||
m_zoomAnimProgress->setValueAndWarp(0.F);
|
m_zoomAnimProgress->setValueAndWarp(0.F);
|
||||||
|
m_zoomAnimFrameCounter = 0;
|
||||||
|
|
||||||
g_pEventLoopManager->doLater([] { g_pConfigManager->ensurePersistentWorkspacesPresent(); });
|
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) {
|
m_listeners.presented = m_output->events.present.listen([this](const Aquamarine::IOutput::SPresentEvent& event) {
|
||||||
if (m_pendingDpmsAnimation) {
|
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->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;
|
timespec* ts = event.when;
|
||||||
|
|
@ -102,8 +110,26 @@ void CMonitor::onConnect(bool noRule) {
|
||||||
else
|
else
|
||||||
PROTO::presentation->onPresented(m_self.lock(), Time::fromTimespec(event.when), event.refresh, event.seq, event.flags);
|
PROTO::presentation->onPresented(m_self.lock(), Time::fromTimespec(event.when), event.refresh, event.seq, event.flags);
|
||||||
|
|
||||||
if (m_zoomAnimProgress->goal() == 0.F)
|
if (m_zoomAnimFrameCounter < 5) {
|
||||||
*m_zoomAnimProgress = 1.F;
|
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();
|
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
|
// enable the monitor. Wait for the frame to be presented, then begin animation
|
||||||
m_dpmsBlackOpacity->setValueAndWarp(1.F);
|
m_dpmsBlackOpacity->setValueAndWarp(1.F);
|
||||||
m_dpmsBlackOpacity->setCallbackOnEnd(nullptr);
|
m_dpmsBlackOpacity->setCallbackOnEnd(nullptr);
|
||||||
m_pendingDpmsAnimation = true;
|
m_pendingDpmsAnimation = true;
|
||||||
|
m_pendingDpmsAnimationCounter = 0;
|
||||||
commitDPMSState(true);
|
commitDPMSState(true);
|
||||||
} else {
|
} else {
|
||||||
// disable the monitor. Begin the animation, then do dpms on its end.
|
// disable the monitor. Begin the animation, then do dpms on its end.
|
||||||
|
|
|
||||||
|
|
@ -183,12 +183,15 @@ class CMonitor {
|
||||||
|
|
||||||
// for dpms off anim
|
// for dpms off anim
|
||||||
PHLANIMVAR<float> m_dpmsBlackOpacity;
|
PHLANIMVAR<float> m_dpmsBlackOpacity;
|
||||||
bool m_pendingDpmsAnimation = false;
|
bool m_pendingDpmsAnimation = false;
|
||||||
|
int m_pendingDpmsAnimationCounter = 0;
|
||||||
|
|
||||||
PHLANIMVAR<float> m_cursorZoom;
|
PHLANIMVAR<float> m_cursorZoom;
|
||||||
|
|
||||||
// for initial zoom anim
|
// for initial zoom anim
|
||||||
PHLANIMVAR<float> m_zoomAnimProgress;
|
PHLANIMVAR<float> m_zoomAnimProgress;
|
||||||
|
CTimer m_newMonitorAnimTimer;
|
||||||
|
int m_zoomAnimFrameCounter = 0;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
bool canTear = false;
|
bool canTear = false;
|
||||||
|
|
|
||||||
|
|
@ -1310,7 +1310,7 @@ void CHyprRenderer::renderMonitor(PHLMONITOR pMonitor, bool commit) {
|
||||||
else
|
else
|
||||||
g_pHyprOpenGL->m_renderData.mouseZoomFactor = 1.f;
|
g_pHyprOpenGL->m_renderData.mouseZoomFactor = 1.f;
|
||||||
|
|
||||||
if (pMonitor->m_zoomAnimProgress->isBeingAnimated()) {
|
if (pMonitor->m_zoomAnimProgress->value() != 1) {
|
||||||
g_pHyprOpenGL->m_renderData.mouseZoomFactor = 2.0 - pMonitor->m_zoomAnimProgress->value(); // 2x zoom -> 1x zoom
|
g_pHyprOpenGL->m_renderData.mouseZoomFactor = 2.0 - pMonitor->m_zoomAnimProgress->value(); // 2x zoom -> 1x zoom
|
||||||
g_pHyprOpenGL->m_renderData.mouseZoomUseMouse = false;
|
g_pHyprOpenGL->m_renderData.mouseZoomUseMouse = false;
|
||||||
g_pHyprOpenGL->m_renderData.useNearestNeighbor = false;
|
g_pHyprOpenGL->m_renderData.useNearestNeighbor = false;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue