scheduler: keep a strong monitor ref in frame callbacks

This commit is contained in:
Pppp1116 2026-04-03 13:24:54 +01:00 committed by Vaxry
parent 0647b5449c
commit d5b00bbc17

View file

@ -17,21 +17,21 @@ bool CMonitorFrameScheduler::newSchedulingEnabled() {
}
void CMonitorFrameScheduler::onSyncFired() {
if (!newSchedulingEnabled())
const auto PMONITOR = m_monitor.lock();
if (!PMONITOR || !newSchedulingEnabled())
return;
// Sync fired: reset submitted state, set as rendered. Check the last render time. If we are running
// late, we will instantly render here.
if (std::chrono::duration_cast<std::chrono::microseconds>(hrc::now() - m_lastRenderBegun).count() / 1000.F < 1000.F / m_monitor->m_refreshRate) {
if (std::chrono::duration_cast<std::chrono::microseconds>(hrc::now() - m_lastRenderBegun).count() / 1000.F < 1000.F / PMONITOR->m_refreshRate) {
// we are in. Frame is valid. We can just render as normal.
Log::logger->log(Log::TRACE, "CMonitorFrameScheduler: {} -> onSyncFired, didn't miss.", m_monitor->m_name);
Log::logger->log(Log::TRACE, "CMonitorFrameScheduler: {} -> onSyncFired, didn't miss.", PMONITOR->m_name);
m_renderAtFrame = true;
return;
}
Log::logger->log(Log::TRACE, "CMonitorFrameScheduler: {} -> onSyncFired, missed.", m_monitor->m_name);
Log::logger->log(Log::TRACE, "CMonitorFrameScheduler: {} -> onSyncFired, missed.", PMONITOR->m_name);
// we are out. The frame is taking too long to render. Begin rendering immediately, but don't commit yet.
m_pendingThird = true;
@ -43,7 +43,7 @@ void CMonitorFrameScheduler::onSyncFired() {
// FIXME: this is horrible. "renderMonitor" should not be able to do that.
auto self = m_self;
g_pHyprRenderer->renderMonitor(m_monitor.lock(), false);
g_pHyprRenderer->renderMonitor(PMONITOR, false);
if (!self)
return;
@ -52,21 +52,22 @@ void CMonitorFrameScheduler::onSyncFired() {
}
void CMonitorFrameScheduler::onPresented() {
if (!newSchedulingEnabled())
const auto PMONITOR = m_monitor.lock();
if (!PMONITOR || !newSchedulingEnabled())
return;
if (!m_pendingThird)
return;
Log::logger->log(Log::TRACE, "CMonitorFrameScheduler: {} -> onPresented, missed, committing pending.", m_monitor->m_name);
Log::logger->log(Log::TRACE, "CMonitorFrameScheduler: {} -> onPresented, missed, committing pending.", PMONITOR->m_name);
m_pendingThird = false;
Log::logger->log(Log::TRACE, "CMonitorFrameScheduler: {} -> onPresented, missed, committing pending at the earliest convenience.", m_monitor->m_name);
Log::logger->log(Log::TRACE, "CMonitorFrameScheduler: {} -> onPresented, missed, committing pending at the earliest convenience.", PMONITOR->m_name);
m_pendingThird = false;
g_pEventLoopManager->doLater([m = m_monitor.lock()] {
g_pEventLoopManager->doLater([m = PMONITOR] {
if (!m)
return;
g_pHyprRenderer->commitPendingAndDoExplicitSync(m); // commit the pending frame. If it didn't fire yet (is not rendered) it doesn't matter. Syncs will wait.
@ -79,35 +80,36 @@ void CMonitorFrameScheduler::onPresented() {
}
void CMonitorFrameScheduler::onFrame() {
if (!canRender())
const auto PMONITOR = m_monitor.lock();
if (!PMONITOR || !canRender())
return;
m_monitor->recheckSolitary();
PMONITOR->recheckSolitary();
m_monitor->m_tearingState.busy = false;
PMONITOR->m_tearingState.busy = false;
if (m_monitor->m_tearingState.activelyTearing && m_monitor->m_solitaryClient.lock() /* can be invalidated by a recheck */) {
if (PMONITOR->m_tearingState.activelyTearing && PMONITOR->m_solitaryClient.lock() /* can be invalidated by a recheck */) {
if (!m_monitor->m_tearingState.frameScheduledWhileBusy)
if (!PMONITOR->m_tearingState.frameScheduledWhileBusy)
return; // we did not schedule a frame yet to be displayed, but we are tearing. Why render?
m_monitor->m_tearingState.nextRenderTorn = true;
m_monitor->m_tearingState.frameScheduledWhileBusy = false;
PMONITOR->m_tearingState.nextRenderTorn = true;
PMONITOR->m_tearingState.frameScheduledWhileBusy = false;
}
if (!newSchedulingEnabled()) {
m_monitor->m_lastPresentationTimer.reset();
PMONITOR->m_lastPresentationTimer.reset();
g_pHyprRenderer->renderMonitor(m_monitor.lock());
g_pHyprRenderer->renderMonitor(PMONITOR);
return;
}
if (!m_renderAtFrame) {
Log::logger->log(Log::TRACE, "CMonitorFrameScheduler: {} -> frame event, but m_renderAtFrame = false.", m_monitor->m_name);
Log::logger->log(Log::TRACE, "CMonitorFrameScheduler: {} -> frame event, but m_renderAtFrame = false.", PMONITOR->m_name);
return;
}
Log::logger->log(Log::TRACE, "CMonitorFrameScheduler: {} -> frame event, render = true, rendering normally.", m_monitor->m_name);
Log::logger->log(Log::TRACE, "CMonitorFrameScheduler: {} -> frame event, render = true, rendering normally.", PMONITOR->m_name);
m_lastRenderBegun = hrc::now();
@ -115,7 +117,7 @@ void CMonitorFrameScheduler::onFrame() {
// FIXME: this is horrible. "renderMonitor" should not be able to do that.
auto self = m_self;
g_pHyprRenderer->renderMonitor(m_monitor.lock());
g_pHyprRenderer->renderMonitor(PMONITOR);
if (!self)
return;