summaryrefslogtreecommitdiff
path: root/src/helpers/Monitor.cpp
diff options
context:
space:
mode:
authorVaxry <43317083+vaxerski@users.noreply.github.com>2025-07-08 12:41:10 +0200
committerGitHub <noreply@github.com>2025-07-08 12:41:10 +0200
commit8f948827a69499c0b112043debad35f82a312b6b (patch)
tree6d2c678a61db60e64c8cd1160267e2803f89066b /src/helpers/Monitor.cpp
parent9856563f8966856871a95f70757362f694ff22a6 (diff)
Renderer: Implement new render scheduling (#10936)
Implements a new render scheduling method, where we triple buffer when necessary. Enabled by default, improves FPS on underpowered devices. --------- Co-authored-by: Mihai Fufezan <mihai@fufexan.net>
Diffstat (limited to 'src/helpers/Monitor.cpp')
-rw-r--r--src/helpers/Monitor.cpp74
1 files changed, 9 insertions, 65 deletions
diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp
index 6874ac53..e29d9963 100644
--- a/src/helpers/Monitor.cpp
+++ b/src/helpers/Monitor.cpp
@@ -29,6 +29,7 @@
#include <aquamarine/output/Output.hpp>
#include "debug/Log.hpp"
#include "debug/HyprNotificationOverlay.hpp"
+#include "MonitorFrameScheduler.hpp"
#include <hyprutils/string/String.hpp>
#include <hyprutils/utils/ScopeGuard.hpp>
#include <cstring>
@@ -67,7 +68,7 @@ void CMonitor::onConnect(bool noRule) {
g_pEventLoopManager->doLater([] { g_pConfigManager->ensurePersistentWorkspacesPresent(); });
- m_listeners.frame = m_output->events.frame.registerListener([this](std::any d) { onMonitorFrame(); });
+ m_listeners.frame = m_output->events.frame.registerListener([this](std::any d) { m_frameScheduler->onFrame(); });
m_listeners.commit = m_output->events.commit.registerListener([this](std::any d) {
if (true) { // FIXME: E->state->committed & WLR_OUTPUT_STATE_BUFFER
PROTO::screencopy->onOutputCommit(m_self.lock());
@@ -92,6 +93,8 @@ void CMonitor::onConnect(bool noRule) {
PROTO::presentation->onPresented(m_self.lock(), Time::steadyNow(), E.refresh, E.seq, E.flags);
else
PROTO::presentation->onPresented(m_self.lock(), Time::fromTimespec(E.when), E.refresh, E.seq, E.flags);
+
+ m_frameScheduler->onPresented();
});
m_listeners.destroy = m_output->events.destroy.registerListener([this](std::any d) {
@@ -134,6 +137,8 @@ void CMonitor::onConnect(bool noRule) {
applyMonitorRule(&rule);
});
+ m_frameScheduler = makeUnique<CMonitorFrameScheduler>(m_self.lock());
+
m_tearingState.canTear = m_output->getBackend()->type() == Aquamarine::AQ_BACKEND_DRM;
m_name = m_output->name;
@@ -306,6 +311,8 @@ void CMonitor::onDisconnect(bool destroy) {
m_renderTimer = nullptr;
}
+ m_frameScheduler.reset();
+
if (!m_enabled || g_pCompositor->m_isShuttingDown)
return;
@@ -1562,69 +1569,6 @@ void CMonitor::debugLastPresentation(const std::string& message) {
m_lastPresentationTimer.getMillis() > 0 ? 1000.0f / m_lastPresentationTimer.getMillis() : 0.0f);
}
-void CMonitor::onMonitorFrame() {
- if ((g_pCompositor->m_aqBackend->hasSession() && !g_pCompositor->m_aqBackend->session->active) || !g_pCompositor->m_sessionActive || g_pCompositor->m_unsafeState) {
- Debug::log(WARN, "Attempted to render frame on inactive session!");
-
- if (g_pCompositor->m_unsafeState && std::ranges::any_of(g_pCompositor->m_monitors.begin(), g_pCompositor->m_monitors.end(), [&](auto& m) {
- return m->m_output != g_pCompositor->m_unsafeOutput->m_output;
- })) {
- // restore from unsafe state
- g_pCompositor->leaveUnsafeState();
- }
-
- return; // cannot draw on session inactive (different tty)
- }
-
- if (!m_enabled)
- return;
-
- g_pHyprRenderer->recheckSolitaryForMonitor(m_self.lock());
-
- m_tearingState.busy = false;
-
- if (m_tearingState.activelyTearing && m_solitaryClient.lock() /* can be invalidated by a recheck */) {
-
- if (!m_tearingState.frameScheduledWhileBusy)
- return; // we did not schedule a frame yet to be displayed, but we are tearing. Why render?
-
- m_tearingState.nextRenderTorn = true;
- m_tearingState.frameScheduledWhileBusy = false;
- }
-
- static auto PENABLERAT = CConfigValue<Hyprlang::INT>("misc:render_ahead_of_time");
- static auto PRATSAFE = CConfigValue<Hyprlang::INT>("misc:render_ahead_safezone");
-
- m_lastPresentationTimer.reset();
-
- if (*PENABLERAT && !m_tearingState.nextRenderTorn) {
- if (!m_ratsScheduled) {
- // render
- g_pHyprRenderer->renderMonitor(m_self.lock());
- }
-
- m_ratsScheduled = false;
-
- const auto& [avg, max, min] = g_pHyprRenderer->getRenderTimes(m_self.lock());
-
- if (max + *PRATSAFE > 1000.0 / m_refreshRate)
- return;
-
- const auto MSLEFT = (1000.0 / m_refreshRate) - m_lastPresentationTimer.getMillis();
-
- m_ratsScheduled = true;
-
- const auto ESTRENDERTIME = std::ceil(avg + *PRATSAFE);
- const auto TIMETOSLEEP = std::floor(MSLEFT - ESTRENDERTIME);
-
- if (MSLEFT < 1 || MSLEFT < ESTRENDERTIME || TIMETOSLEEP < 1)
- g_pHyprRenderer->renderMonitor(m_self.lock());
- else
- wl_event_source_timer_update(m_renderTimer, TIMETOSLEEP);
- } else
- g_pHyprRenderer->renderMonitor(m_self.lock());
-}
-
void CMonitor::onCursorMovedOnMonitor() {
if (!m_tearingState.activelyTearing || !m_solitaryClient || !g_pHyprRenderer->shouldRenderCursor())
return;
@@ -1717,7 +1661,7 @@ bool CMonitorState::updateSwapchain() {
}
options.format = m_owner->m_drmFormat;
options.scanout = true;
- options.length = 2;
+ options.length = 3;
options.size = MODE->pixelSize;
return m_owner->m_output->swapchain->reconfigure(options);
}