aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/events/Monitors.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/events/Monitors.cpp')
-rw-r--r--src/events/Monitors.cpp245
1 files changed, 27 insertions, 218 deletions
diff --git a/src/events/Monitors.cpp b/src/events/Monitors.cpp
index fbc163cc..ccdb3ef0 100644
--- a/src/events/Monitors.cpp
+++ b/src/events/Monitors.cpp
@@ -44,7 +44,7 @@ void Events::listener_change(wl_listener* listener, void* data) {
}
void Events::listener_newOutput(wl_listener* listener, void* data) {
- // new monitor added, let's accomodate for that.
+ // new monitor added, let's accommodate for that.
const auto OUTPUT = (wlr_output*)data;
// for warping the cursor on launch
@@ -101,6 +101,13 @@ void Events::listener_newOutput(wl_listener* listener, void* data) {
const auto POS = PNEWMONITOR->vecPosition + PNEWMONITOR->vecSize / 2.f;
if (g_pCompositor->m_sSeat.mouse)
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, g_pCompositor->m_sSeat.mouse->mouse, POS.x, POS.y);
+ } else {
+ for (auto& w : g_pCompositor->m_vWindows) {
+ if (w->m_iMonitorID == PNEWMONITOR->ID) {
+ w->m_iLastSurfaceMonitorID = -1;
+ w->updateSurfaceOutputs();
+ }
+ }
}
}
@@ -119,235 +126,37 @@ void Events::listener_monitorFrame(void* owner, void* data) {
if (!PMONITOR->m_bEnabled)
return;
- static std::chrono::high_resolution_clock::time_point startRender = std::chrono::high_resolution_clock::now();
- static std::chrono::high_resolution_clock::time_point startRenderOverlay = std::chrono::high_resolution_clock::now();
- static std::chrono::high_resolution_clock::time_point endRenderOverlay = std::chrono::high_resolution_clock::now();
-
- static auto* const PDEBUGOVERLAY = &g_pConfigManager->getConfigValuePtr("debug:overlay")->intValue;
- static auto* const PDAMAGETRACKINGMODE = &g_pConfigManager->getConfigValuePtr("debug:damage_tracking")->intValue;
- static auto* const PDAMAGEBLINK = &g_pConfigManager->getConfigValuePtr("debug:damage_blink")->intValue;
- static auto* const PNODIRECTSCANOUT = &g_pConfigManager->getConfigValuePtr("misc:no_direct_scanout")->intValue;
- static auto* const PVFR = &g_pConfigManager->getConfigValuePtr("misc:vfr")->intValue;
-
- static int damageBlinkCleanup = 0; // because double-buffered
-
- if (!*PDAMAGEBLINK)
- damageBlinkCleanup = 0;
+ static auto* const PENABLERAT = &g_pConfigManager->getConfigValuePtr("misc:render_ahead_of_time")->intValue;
+ static auto* const PRATSAFE = &g_pConfigManager->getConfigValuePtr("misc:render_ahead_safezone")->intValue;
- if (*PDEBUGOVERLAY == 1) {
- startRender = std::chrono::high_resolution_clock::now();
- g_pDebugOverlay->frameData(PMONITOR);
- }
-
- if (PMONITOR->framesToSkip > 0) {
- PMONITOR->framesToSkip -= 1;
+ PMONITOR->lastPresentationTimer.reset();
- if (!PMONITOR->noFrameSchedule)
- g_pCompositor->scheduleFrameForMonitor(PMONITOR);
- else {
- Debug::log(LOG, "NoFrameSchedule hit for %s.", PMONITOR->szName.c_str());
+ if (*PENABLERAT) {
+ if (!PMONITOR->RATScheduled) {
+ // render
+ g_pHyprRenderer->renderMonitor(PMONITOR);
}
- g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PMONITOR->ID);
-
- if (PMONITOR->framesToSkip > 10)
- PMONITOR->framesToSkip = 0;
- return;
- }
- // checks //
- if (PMONITOR->ID == g_pHyprRenderer->m_pMostHzMonitor->ID ||
- *PVFR == 1) { // unfortunately with VFR we don't have the guarantee mostHz is going to be updated all the time, so we have to ignore that
- g_pCompositor->sanityCheckWorkspaces();
+ PMONITOR->RATScheduled = false;
- g_pConfigManager->dispatchExecOnce(); // We exec-once when at least one monitor starts refreshing, meaning stuff has init'd
+ const auto& [avg, max, min] = g_pHyprRenderer->getRenderTimes(PMONITOR);
- if (g_pConfigManager->m_bWantsMonitorReload)
- g_pConfigManager->performMonitorReload();
-
- g_pHyprRenderer->ensureCursorRenderingMode(); // so that the cursor gets hidden/shown if the user requested timeouts
- }
- // //
-
- if (PMONITOR->scheduledRecalc) {
- PMONITOR->scheduledRecalc = false;
- g_pLayoutManager->getCurrentLayout()->recalculateMonitor(PMONITOR->ID);
- }
-
- // Direct scanout first
- if (!*PNODIRECTSCANOUT) {
- if (g_pHyprRenderer->attemptDirectScanout(PMONITOR)) {
+ if (max + *PRATSAFE > 1000.0 / PMONITOR->refreshRate)
return;
- } else if (g_pHyprRenderer->m_pLastScanout) {
- Debug::log(LOG, "Left a direct scanout.");
- g_pHyprRenderer->m_pLastScanout = nullptr;
- }
- }
-
- EMIT_HOOK_EVENT("preRender", PMONITOR);
- timespec now;
- clock_gettime(CLOCK_MONOTONIC, &now);
+ const auto MSLEFT = 1000.0 / PMONITOR->refreshRate - PMONITOR->lastPresentationTimer.getMillis();
- // check the damage
- pixman_region32_t damage;
- bool hasChanged;
- pixman_region32_init(&damage);
+ PMONITOR->RATScheduled = true;
- if (*PDAMAGETRACKINGMODE == -1) {
- Debug::log(CRIT, "Damage tracking mode -1 ????");
- return;
- }
-
- if (!wlr_output_damage_attach_render(PMONITOR->damage, &hasChanged, &damage)) {
- Debug::log(ERR, "Couldn't attach render to display %s ???", PMONITOR->szName.c_str());
- return;
- }
-
- PMONITOR->renderingActive = true;
-
- // we need to cleanup fading out when rendering the appropriate context
- g_pCompositor->cleanupFadingOut(PMONITOR->ID);
-
- if (!hasChanged && *PDAMAGETRACKINGMODE != DAMAGE_TRACKING_NONE && PMONITOR->forceFullFrames == 0 && damageBlinkCleanup == 0) {
- pixman_region32_fini(&damage);
- wlr_output_rollback(PMONITOR->output);
-
- if (*PDAMAGEBLINK || *PVFR == 0)
- g_pCompositor->scheduleFrameForMonitor(PMONITOR);
-
- PMONITOR->renderingActive = false;
+ const auto ESTRENDERTIME = std::ceil(avg + *PRATSAFE);
+ const auto TIMETOSLEEP = std::floor(MSLEFT - ESTRENDERTIME);
- return;
- }
-
- // if we have no tracking or full tracking, invalidate the entire monitor
- if (*PDAMAGETRACKINGMODE == DAMAGE_TRACKING_NONE || *PDAMAGETRACKINGMODE == DAMAGE_TRACKING_MONITOR || PMONITOR->forceFullFrames > 0 || damageBlinkCleanup > 0 ||
- PMONITOR->isMirror() /* why??? */) {
- pixman_region32_union_rect(&damage, &damage, 0, 0, (int)PMONITOR->vecTransformedSize.x * 10, (int)PMONITOR->vecTransformedSize.y * 10); // wot?
-
- pixman_region32_copy(&g_pHyprOpenGL->m_rOriginalDamageRegion, &damage);
+ if (MSLEFT < 1 || MSLEFT < ESTRENDERTIME || TIMETOSLEEP < 1)
+ g_pHyprRenderer->renderMonitor(PMONITOR);
+ else
+ wl_event_source_timer_update(PMONITOR->renderTimer, TIMETOSLEEP);
} else {
- static auto* const PBLURENABLED = &g_pConfigManager->getConfigValuePtr("decoration:blur")->intValue;
-
- // if we use blur we need to expand the damage for proper blurring
- if (*PBLURENABLED == 1) {
- // TODO: can this be optimized?
- static auto* const PBLURSIZE = &g_pConfigManager->getConfigValuePtr("decoration:blur_size")->intValue;
- static auto* const PBLURPASSES = &g_pConfigManager->getConfigValuePtr("decoration:blur_passes")->intValue;
- const auto BLURRADIUS = *PBLURSIZE * pow(2, *PBLURPASSES); // is this 2^pass? I don't know but it works... I think.
-
- // now, prep the damage, get the extended damage region
- wlr_region_expand(&damage, &damage, BLURRADIUS); // expand for proper blurring
-
- pixman_region32_copy(&g_pHyprOpenGL->m_rOriginalDamageRegion, &damage);
-
- wlr_region_expand(&damage, &damage, BLURRADIUS); // expand for proper blurring 2
- } else {
- pixman_region32_copy(&g_pHyprOpenGL->m_rOriginalDamageRegion, &damage);
- }
- }
-
- if (PMONITOR->forceFullFrames > 0) {
- PMONITOR->forceFullFrames -= 1;
- if (PMONITOR->forceFullFrames > 10)
- PMONITOR->forceFullFrames = 0;
- }
-
- const bool UNLOCK_SC = g_pHyprRenderer->m_bSoftwareCursorsLocked;
- if (UNLOCK_SC)
- wlr_output_lock_software_cursors(PMONITOR->output, true);
-
- g_pHyprOpenGL->begin(PMONITOR, &damage);
-
- if (PMONITOR->isMirror()) {
- g_pHyprOpenGL->renderMirrored();
- } else {
- g_pHyprOpenGL->clear(CColor(17.0 / 255.0, 17.0 / 255.0, 17.0 / 255.0, 1.0));
- g_pHyprOpenGL->clearWithTex(); // will apply the hypr "wallpaper"
-
- g_pHyprRenderer->renderAllClientsForMonitor(PMONITOR->ID, &now);
-
- if (PMONITOR == g_pCompositor->m_pLastMonitor) {
- g_pHyprNotificationOverlay->draw(PMONITOR);
- g_pHyprError->draw();
- }
-
- // for drawing the debug overlay
- if (PMONITOR == g_pCompositor->m_vMonitors.front().get() && *PDEBUGOVERLAY == 1) {
- startRenderOverlay = std::chrono::high_resolution_clock::now();
- g_pDebugOverlay->draw();
- endRenderOverlay = std::chrono::high_resolution_clock::now();
- }
-
- if (*PDAMAGEBLINK && damageBlinkCleanup == 0) {
- wlr_box monrect = {0, 0, PMONITOR->vecTransformedSize.x, PMONITOR->vecTransformedSize.y};
- g_pHyprOpenGL->renderRect(&monrect, CColor(1.0, 0.0, 1.0, 100.0 / 255.0), 0);
- damageBlinkCleanup = 1;
- } else if (*PDAMAGEBLINK) {
- damageBlinkCleanup++;
- if (damageBlinkCleanup > 3)
- damageBlinkCleanup = 0;
- }
-
- if (wlr_renderer_begin(g_pCompositor->m_sWLRRenderer, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y)) {
- wlr_output_render_software_cursors(PMONITOR->output, NULL);
- wlr_renderer_end(g_pCompositor->m_sWLRRenderer);
- }
- }
-
- g_pHyprOpenGL->end();
-
- // calc frame damage
- pixman_region32_t frameDamage;
- pixman_region32_init(&frameDamage);
-
- const auto TRANSFORM = wlr_output_transform_invert(PMONITOR->output->transform);
- wlr_region_transform(&frameDamage, &g_pHyprOpenGL->m_rOriginalDamageRegion, TRANSFORM, (int)PMONITOR->vecTransformedSize.x, (int)PMONITOR->vecTransformedSize.y);
-
- if (*PDAMAGETRACKINGMODE == DAMAGE_TRACKING_NONE || *PDAMAGETRACKINGMODE == DAMAGE_TRACKING_MONITOR)
- pixman_region32_union_rect(&frameDamage, &frameDamage, 0, 0, (int)PMONITOR->vecTransformedSize.x, (int)PMONITOR->vecTransformedSize.y);
-
- if (*PDAMAGEBLINK)
- pixman_region32_union(&frameDamage, &frameDamage, &damage);
-
- wlr_output_set_damage(PMONITOR->output, &frameDamage);
-
- if (!PMONITOR->mirrors.empty())
- g_pHyprRenderer->damageMirrorsWith(PMONITOR, &frameDamage);
-
- pixman_region32_fini(&frameDamage);
-
- PMONITOR->renderingActive = false;
-
- if (!wlr_output_commit(PMONITOR->output)) {
- pixman_region32_fini(&damage);
-
- if (UNLOCK_SC)
- wlr_output_lock_software_cursors(PMONITOR->output, false);
-
- return;
- }
-
- g_pProtocolManager->m_pScreencopyProtocolManager->onRenderEnd(PMONITOR);
- pixman_region32_fini(&damage);
-
- if (UNLOCK_SC)
- wlr_output_lock_software_cursors(PMONITOR->output, false);
-
- if (*PDAMAGEBLINK || *PVFR == 0 || PMONITOR->pendingFrame)
- g_pCompositor->scheduleFrameForMonitor(PMONITOR);
-
- PMONITOR->pendingFrame = false;
-
- if (*PDEBUGOVERLAY == 1) {
- const float µs = std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now() - startRender).count() / 1000.f;
- g_pDebugOverlay->renderData(PMONITOR, µs);
- if (PMONITOR == g_pCompositor->m_vMonitors.front().get()) {
- const float µsNoOverlay = µs - std::chrono::duration_cast<std::chrono::nanoseconds>(endRenderOverlay - startRenderOverlay).count() / 1000.f;
- g_pDebugOverlay->renderDataNoOverlay(PMONITOR, µsNoOverlay);
- } else {
- g_pDebugOverlay->renderDataNoOverlay(PMONITOR, µs);
- }
+ g_pHyprRenderer->renderMonitor(PMONITOR);
}
}