summaryrefslogtreecommitdiff
path: root/src/helpers
diff options
context:
space:
mode:
authorVaxry <vaxry@vaxry.net>2025-04-16 01:37:48 +0100
committerVaxry <vaxry@vaxry.net>2025-04-16 01:37:48 +0100
commit877fb5b93ada9b25b4d2f5ca5f69370fa345f1ac (patch)
tree5b52ad19c695590ae50c7adae06b8e3aeccf34c1 /src/helpers
parent0e521788bcc414c9cf81648d3167757d83deb60f (diff)
time: move to stl's clocks and move timer
Diffstat (limited to 'src/helpers')
-rw-r--r--src/helpers/Monitor.cpp21
-rw-r--r--src/helpers/Monitor.hpp2
-rw-r--r--src/helpers/Timer.cpp22
-rw-r--r--src/helpers/Timer.hpp16
-rw-r--r--src/helpers/time/Time.cpp139
-rw-r--r--src/helpers/time/Time.hpp25
-rw-r--r--src/helpers/time/Timer.cpp23
-rw-r--r--src/helpers/time/Timer.hpp16
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