diff options
Diffstat (limited to 'src/events/Monitors.cpp')
-rw-r--r-- | src/events/Monitors.cpp | 245 |
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); } } |