renderer: send frame callbacks on presented if no change (#14849)

some very picky clients like firefox expects a frame callback to
continue rendering and send buffers, if the frame is returning early
because no change its not going to recieve it, this becomes very
noticeable on a single firefox window and using new_render_scheduling
where it renders the monitor one extra time where occasionally nothing
had really changed.
This commit is contained in:
Tom Englund
2026-06-07 12:26:02 +02:00
committed by Vaxry
parent b2632eb4ce
commit d15b64e92a
3 changed files with 25 additions and 6 deletions
+11
View File
@@ -158,6 +158,17 @@ void CMonitor::onConnect(bool noRule) {
});
}
// if the monitor has no pending frames, we wont hit the no damage send frame callback path in rendermonitor
// this becomes really noticeable in new render scheduling. causing firefox to simply wait for a new frame callback.
// when nothing is scheduling new frames.
auto mon = m_self.lock();
if (!isMirror() && !g_pHyprRenderer->shouldRenderMonitor(mon)) {
auto const NOW = Time::steadyNow();
g_pHyprRenderer->sendFrameEventsToWorkspace(mon, m_activeWorkspace, NOW);
if (m_activeSpecialWorkspace)
g_pHyprRenderer->sendFrameEventsToWorkspace(mon, m_activeSpecialWorkspace, NOW);
}
m_frameScheduler->onPresented();
m_events.presented.emit();
+11 -4
View File
@@ -314,6 +314,16 @@ bool IHyprRenderer::shouldRenderWindow(PHLWINDOW pWindow) {
return false;
}
bool IHyprRenderer::shouldRenderMonitor(PHLMONITOR monitor) {
static auto PDAMAGETRACKINGMODE = CConfigValue<Config::INTEGER>("debug:damage_tracking");
bool hasChanged = monitor->m_output->needsFrame || monitor->m_damage.hasChanged();
if (!hasChanged && *PDAMAGETRACKINGMODE != DAMAGE_TRACKING_NONE && monitor->m_forceFullFrames == 0)
return false;
return true;
}
void IHyprRenderer::renderWorkspaceWindowsFullscreen(PHLMONITOR pMonitor, PHLWORKSPACE pWorkspace, const Time::steady_tp& time) {
PHLWINDOW pWorkspaceWindow = nullptr;
@@ -2036,10 +2046,7 @@ void IHyprRenderer::renderMonitor(PHLMONITOR pMonitor, bool commit) {
const auto NOW = Time::steadyNow();
// check the damage
bool hasChanged = pMonitor->m_output->needsFrame || pMonitor->m_damage.hasChanged();
if (!hasChanged && *PDAMAGETRACKINGMODE != DAMAGE_TRACKING_NONE && pMonitor->m_forceFullFrames == 0 && damageBlinkCleanup == 0)
if (!shouldRenderMonitor(pMonitor) && damageBlinkCleanup == 0)
return;
if (*PDAMAGETRACKINGMODE == -1) {
+3 -2
View File
@@ -75,6 +75,7 @@ namespace Render {
void damageMirrorsWith(PHLMONITOR, const CRegion&);
bool shouldRenderWindow(PHLWINDOW, PHLMONITOR);
bool shouldRenderWindow(PHLWINDOW);
bool shouldRenderMonitor(PHLMONITOR);
void ensureCursorRenderingMode();
bool shouldRenderCursor();
void setCursorHidden(bool hide);
@@ -184,6 +185,8 @@ namespace Render {
void pushMonitorTransformEnabled(bool enabled);
void popMonitorTransformEnabled();
bool monitorTransformEnabled();
void sendFrameEventsToWorkspace(PHLMONITOR pMonitor, PHLWORKSPACE pWorkspace,
const Time::steady_tp& now); // sends frame displayed events but doesn't actually render anything
void setProjectionType(const Vector2D& fbSize);
void setProjectionType(eRenderProjectionType projectionType);
@@ -253,8 +256,6 @@ namespace Render {
void renderSessionLockSurface(WP<SSessionLockSurface>, PHLMONITOR, const Time::steady_tp&);
void renderDragIcon(PHLMONITOR, const Time::steady_tp&);
void renderIMEPopup(CInputPopup*, PHLMONITOR, const Time::steady_tp&);
void sendFrameEventsToWorkspace(PHLMONITOR pMonitor, PHLWORKSPACE pWorkspace,
const Time::steady_tp& now); // sends frame displayed events but doesn't actually render anything
void renderSessionLockPrimer(PHLMONITOR pMonitor);
void renderSessionLockMissing(PHLMONITOR pMonitor);
void renderBackground(PHLMONITOR pMonitor);