diff options
| author | Vaxry <vaxry@vaxry.net> | 2025-04-16 01:37:48 +0100 |
|---|---|---|
| committer | Vaxry <vaxry@vaxry.net> | 2025-04-16 01:37:48 +0100 |
| commit | 877fb5b93ada9b25b4d2f5ca5f69370fa345f1ac (patch) | |
| tree | 5b52ad19c695590ae50c7adae06b8e3aeccf34c1 /src/helpers | |
| parent | 0e521788bcc414c9cf81648d3167757d83deb60f (diff) | |
time: move to stl's clocks and move timer
Diffstat (limited to 'src/helpers')
| -rw-r--r-- | src/helpers/Monitor.cpp | 21 | ||||
| -rw-r--r-- | src/helpers/Monitor.hpp | 2 | ||||
| -rw-r--r-- | src/helpers/Timer.cpp | 22 | ||||
| -rw-r--r-- | src/helpers/Timer.hpp | 16 | ||||
| -rw-r--r-- | src/helpers/time/Time.cpp | 139 | ||||
| -rw-r--r-- | src/helpers/time/Time.hpp | 25 | ||||
| -rw-r--r-- | src/helpers/time/Timer.cpp | 23 | ||||
| -rw-r--r-- | src/helpers/time/Timer.hpp | 16 |
8 files changed, 217 insertions, 47 deletions
diff --git a/src/helpers/Monitor.cpp b/src/helpers/Monitor.cpp index 0a16643e..5e2fedd5 100644 --- a/src/helpers/Monitor.cpp +++ b/src/helpers/Monitor.cpp @@ -24,6 +24,7 @@ #include "../managers/LayoutManager.hpp" #include "../managers/input/InputManager.hpp" #include "sync/SyncTimeline.hpp" +#include "time/Time.hpp" #include "../desktop/LayerSurface.hpp" #include <aquamarine/output/Output.hpp> #include "debug/Log.hpp" @@ -32,6 +33,7 @@ #include <hyprutils/utils/ScopeGuard.hpp> #include <cstring> #include <ranges> + using namespace Hyprutils::String; using namespace Hyprutils::Utils; using namespace Hyprutils::OS; @@ -72,8 +74,15 @@ void CMonitor::onConnect(bool noRule) { output->events.needsFrame.registerListener([this](std::any d) { g_pCompositor->scheduleFrameForMonitor(self.lock(), Aquamarine::IOutput::AQ_SCHEDULE_NEEDS_FRAME); }); listeners.presented = output->events.present.registerListener([this](std::any d) { - auto E = std::any_cast<Aquamarine::IOutput::SPresentEvent>(d); - PROTO::presentation->onPresented(self.lock(), E.when, E.refresh, E.seq, E.flags); + auto E = std::any_cast<Aquamarine::IOutput::SPresentEvent>(d); + + timespec* ts = E.when; + if (!ts) { + timespec now; + clock_gettime(CLOCK_MONOTONIC, &now); + PROTO::presentation->onPresented(self.lock(), Time::fromTimespec(&now), E.refresh, E.seq, E.flags); + } else + PROTO::presentation->onPresented(self.lock(), Time::fromTimespec(E.when), E.refresh, E.seq, E.flags); }); listeners.destroy = output->events.destroy.registerListener([this](std::any d) { @@ -1377,9 +1386,7 @@ bool CMonitor::attemptDirectScanout() { auto PBUFFER = PSURFACE->current.buffer.buffer; if (PBUFFER == output->state->state().buffer) { - timespec now; - clock_gettime(CLOCK_MONOTONIC, &now); - PSURFACE->presentFeedback(&now, self.lock()); + PSURFACE->presentFeedback(Time::steadyNow(), self.lock()); if (scanoutNeedsCursorUpdate) { if (!state.test()) { @@ -1420,9 +1427,7 @@ bool CMonitor::attemptDirectScanout() { return false; } - timespec now; - clock_gettime(CLOCK_MONOTONIC, &now); - PSURFACE->presentFeedback(&now, self.lock()); + PSURFACE->presentFeedback(Time::steadyNow(), self.lock()); output->state->addDamage(PSURFACE->current.accumulateBufferDamage()); output->state->resetExplicitFences(); diff --git a/src/helpers/Monitor.hpp b/src/helpers/Monitor.hpp index a7d97c8d..2ce6b626 100644 --- a/src/helpers/Monitor.hpp +++ b/src/helpers/Monitor.hpp @@ -9,7 +9,7 @@ #include <array> #include <xf86drmMode.h> -#include "Timer.hpp" +#include "time/Timer.hpp" #include "math/Math.hpp" #include <optional> #include "../protocols/types/ColorManagement.hpp" diff --git a/src/helpers/Timer.cpp b/src/helpers/Timer.cpp deleted file mode 100644 index e00c5918..00000000 --- a/src/helpers/Timer.cpp +++ /dev/null @@ -1,22 +0,0 @@ -#include "Timer.hpp" -#include <chrono> - -void CTimer::reset() { - m_tpLastReset = std::chrono::steady_clock::now(); -} - -std::chrono::steady_clock::duration CTimer::getDuration() { - return std::chrono::steady_clock::now() - m_tpLastReset; -} - -float CTimer::getMillis() { - return std::chrono::duration_cast<std::chrono::microseconds>(getDuration()).count() / 1000.f; -} - -float CTimer::getSeconds() { - return std::chrono::duration_cast<std::chrono::milliseconds>(getDuration()).count() / 1000.f; -} - -const std::chrono::steady_clock::time_point& CTimer::chrono() const { - return m_tpLastReset; -}
\ No newline at end of file diff --git a/src/helpers/Timer.hpp b/src/helpers/Timer.hpp deleted file mode 100644 index a58225d0..00000000 --- a/src/helpers/Timer.hpp +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -#include <chrono> - -class CTimer { - public: - void reset(); - float getSeconds(); - float getMillis(); - const std::chrono::steady_clock::time_point& chrono() const; - - private: - std::chrono::steady_clock::time_point m_tpLastReset; - - std::chrono::steady_clock::duration getDuration(); -};
\ No newline at end of file diff --git a/src/helpers/time/Time.cpp b/src/helpers/time/Time.cpp new file mode 100644 index 00000000..791f5ea1 --- /dev/null +++ b/src/helpers/time/Time.cpp @@ -0,0 +1,139 @@ +#include "Time.hpp" + +#define chr std::chrono +#define TIMESPEC_NSEC_PER_SEC 1000000000L + +using s_ns = std::pair<uint64_t, uint64_t>; + +// HAS to be a > b +static s_ns timediff(const s_ns& a, const s_ns& b) { + s_ns d; + + d.first = a.first - b.first; + if (a.second >= b.second) + d.second = a.second - b.second; + else { + d.second = b.second - a.second; + d.first -= 1; + } + + return d; +} + +static s_ns timeadd(const s_ns& a, const s_ns& b) { + s_ns d; + + d.first = a.first + b.first; + if (a.second + b.second >= TIMESPEC_NSEC_PER_SEC) { + d.second = a.second + b.second - TIMESPEC_NSEC_PER_SEC; + d.first += 1; + } else + d.second = a.second + b.second; + + return d; +} + +Time::steady_tp Time::steadyNow() { + return chr::steady_clock::now(); +} + +Time::system_tp Time::systemNow() { + return chr::system_clock::now(); +} + +uint64_t Time::millis(const steady_tp& tp) { + return chr::duration_cast<chr::milliseconds>(tp.time_since_epoch()).count(); +} + +s_ns Time::secNsec(const steady_tp& tp) { + const uint64_t sec = chr::duration_cast<chr::seconds>(tp.time_since_epoch()).count(); + const chr::steady_clock::duration nsecdur = tp - chr::steady_clock::time_point(chr::seconds(sec)); + return std::make_pair<>(sec, chr::duration_cast<chr::nanoseconds>(nsecdur).count()); +} + +uint64_t Time::millis(const system_tp& tp) { + return chr::duration_cast<chr::milliseconds>(tp.time_since_epoch()).count(); +} + +s_ns Time::secNsec(const system_tp& tp) { + const uint64_t sec = chr::duration_cast<chr::seconds>(tp.time_since_epoch()).count(); + const chr::steady_clock::duration nsecdur = tp - chr::system_clock::time_point(chr::seconds(sec)); + return std::make_pair<>(sec, chr::duration_cast<chr::nanoseconds>(nsecdur).count()); +} + +// TODO: this is a mess, but C++ doesn't define what steady_clock is. +// At least on Linux, system_clock == CLOCK_REALTIME +// and steady_clock == CLOCK_MONOTONIC, +// or at least it seems so with gcc and gcc's stl. +// but, since we can't *ever* be sure, we have to guess. +// In general, this may shift the time around by a couple hundred ns. Doesn't matter, realistically. + +Time::steady_tp Time::fromTimespec(const timespec* ts) { + struct timespec mono, real; + clock_gettime(CLOCK_MONOTONIC, &mono); + clock_gettime(CLOCK_REALTIME, &real); + Time::steady_tp now = Time::steadyNow(); + Time::system_tp nowSys = Time::systemNow(); + s_ns stdSteady, stdReal; + stdSteady = Time::secNsec(now); + stdReal = Time::secNsec(nowSys); + + // timespec difference, REAL - MONO + s_ns diff; + diff.first = real.tv_sec - mono.tv_sec; + if (real.tv_nsec >= mono.tv_nsec) + diff.second = real.tv_nsec - mono.tv_nsec; + else { + diff.second = mono.tv_nsec - real.tv_nsec; + diff.first -= 1; + } + + // STD difference, REAL - MONO + s_ns diff2 = timediff(stdReal, stdSteady); + + s_ns diffFinal; + s_ns monotime = {ts->tv_sec, ts->tv_nsec}; + + if (diff.first >= diff2.first || (diff.first == diff2.first && diff.second >= diff2.second)) + diffFinal = timediff(diff, diff2); + else + diffFinal = timediff(diff2, diff); + + auto sum = timeadd(monotime, diffFinal); + return chr::steady_clock::time_point(std::chrono::seconds(sum.first)) + chr::nanoseconds(sum.second); +} + +struct timespec Time::toTimespec(const steady_tp& tp) { + struct timespec mono, real; + clock_gettime(CLOCK_MONOTONIC, &mono); + clock_gettime(CLOCK_REALTIME, &real); + Time::steady_tp now = Time::steadyNow(); + Time::system_tp nowSys = Time::systemNow(); + s_ns stdSteady, stdReal; + stdSteady = Time::secNsec(now); + stdReal = Time::secNsec(nowSys); + + // timespec difference, REAL - MONO + s_ns diff; + diff.first = real.tv_sec - mono.tv_sec; + if (real.tv_nsec >= mono.tv_nsec) + diff.second = real.tv_nsec - mono.tv_nsec; + else { + diff.second = mono.tv_nsec - real.tv_nsec; + diff.first -= 1; + } + + // STD difference, REAL - MONO + s_ns diff2 = timediff(stdReal, stdSteady); + + s_ns diffFinal; + s_ns tpTime = secNsec(tp); + + if (diff.first >= diff2.first || (diff.first == diff2.first && diff.second >= diff2.second)) + diffFinal = timediff(diff, diff2); + else + diffFinal = timediff(diff2, diff); + + auto sum = timeadd(tpTime, diffFinal); + return timespec{.tv_sec = sum.first, .tv_nsec = sum.second}; +} diff --git a/src/helpers/time/Time.hpp b/src/helpers/time/Time.hpp new file mode 100644 index 00000000..eb3b5771 --- /dev/null +++ b/src/helpers/time/Time.hpp @@ -0,0 +1,25 @@ +#pragma once + +#include <chrono> +#include <cstdint> +#include <utility> +#include <ctime> + +//NOLINTNEXTLINE +namespace Time { + using steady_tp = std::chrono::steady_clock::time_point; + using system_tp = std::chrono::system_clock::time_point; + using steady_dur = std::chrono::steady_clock::duration; + using system_dur = std::chrono::system_clock::duration; + + steady_tp steadyNow(); + system_tp systemNow(); + + steady_tp fromTimespec(const timespec*); + struct timespec toTimespec(const steady_tp& tp); + + uint64_t millis(const steady_tp& tp); + uint64_t millis(const system_tp& tp); + std::pair<uint64_t, uint64_t> secNsec(const steady_tp& tp); + std::pair<uint64_t, uint64_t> secNsec(const system_tp& tp); +};
\ No newline at end of file diff --git a/src/helpers/time/Timer.cpp b/src/helpers/time/Timer.cpp new file mode 100644 index 00000000..95f75441 --- /dev/null +++ b/src/helpers/time/Timer.cpp @@ -0,0 +1,23 @@ +#include "Timer.hpp" + +#define chr std::chrono + +void CTimer::reset() { + m_lastReset = Time::steadyNow(); +} + +Time::steady_dur CTimer::getDuration() { + return Time::steadyNow() - m_lastReset; +} + +float CTimer::getMillis() { + return chr::duration_cast<chr::microseconds>(getDuration()).count() / 1000.F; +} + +float CTimer::getSeconds() { + return chr::duration_cast<chr::milliseconds>(getDuration()).count() / 1000.F; +} + +const Time::steady_tp& CTimer::chrono() const { + return m_lastReset; +}
\ No newline at end of file diff --git a/src/helpers/time/Timer.hpp b/src/helpers/time/Timer.hpp new file mode 100644 index 00000000..c21f78db --- /dev/null +++ b/src/helpers/time/Timer.hpp @@ -0,0 +1,16 @@ +#pragma once + +#include "Time.hpp" + +class CTimer { + public: + void reset(); + float getSeconds(); + float getMillis(); + const Time::steady_tp& chrono() const; + + private: + Time::steady_tp m_lastReset; + + Time::steady_dur getDuration(); +};
\ No newline at end of file |
