The open source OpenXR runtime
1// Copyright 2019-2020, Collabora, Ltd.
2// SPDX-License-Identifier: BSL-1.0
3/*!
4 * @file
5 * @brief Implementation of a steady, convertible clock.
6 * @author Rylie Pavlik <rylie.pavlik@collabora.com>
7 * @ingroup aux_util
8 */
9
10#include "xrt/xrt_config_os.h"
11#include "xrt/xrt_compiler.h"
12
13#include "os/os_time.h"
14
15#include "u_time.h"
16
17#include <new>
18#include <assert.h>
19#include <stdlib.h>
20#include <time.h>
21
22
23/*
24 *
25 * Structs.
26 *
27 */
28
29struct time_state
30{
31 timepoint_ns offset;
32};
33
34
35/*
36 *
37 * 'Exported' functions.
38 *
39 */
40
41extern "C" struct time_state *
42time_state_create(int64_t offset)
43{
44 time_state *state = new (std::nothrow) time_state;
45 if (!state) {
46 return state;
47 }
48 state->offset = offset;
49 return state;
50}
51
52extern "C" void
53time_state_destroy(struct time_state **state_ptr)
54{
55 struct time_state *state = *state_ptr;
56
57 if (state == NULL) {
58 return;
59 }
60
61 delete state;
62 *state_ptr = NULL;
63}
64
65extern "C" timepoint_ns
66time_state_get_now(struct time_state const *state)
67{
68 assert(state != NULL);
69
70 return time_state_monotonic_to_ts_ns(state, os_monotonic_get_ns());
71}
72
73extern "C" timepoint_ns
74time_state_get_now_and_update(struct time_state *state)
75{
76 assert(state != NULL);
77
78 return time_state_get_now(state);
79}
80
81extern "C" void
82time_state_to_timespec(struct time_state const *state, timepoint_ns timestamp, struct timespec *out)
83{
84 assert(state != NULL);
85 assert(out != NULL);
86
87 int64_t ns = time_state_ts_to_monotonic_ns(state, timestamp);
88
89 out->tv_sec = ns / (U_1_000_000_000);
90 out->tv_nsec = ns % (U_1_000_000_000);
91}
92
93extern "C" timepoint_ns
94time_state_from_timespec(struct time_state const *state, const struct timespec *timespecTime)
95{
96 assert(state != NULL);
97 assert(timespecTime != NULL);
98
99 int64_t ns = 0;
100 ns += timespecTime->tv_nsec;
101 ns += timespecTime->tv_sec * U_1_000_000_000;
102
103 return time_state_monotonic_to_ts_ns(state, ns);
104}
105
106extern "C" timepoint_ns
107time_state_monotonic_to_ts_ns(struct time_state const *state, int64_t monotonic_ns)
108{
109 assert(state != NULL);
110
111 return monotonic_ns - state->offset;
112}
113
114extern "C" int64_t
115time_state_ts_to_monotonic_ns(struct time_state const *state, timepoint_ns timestamp)
116{
117 assert(state != NULL);
118
119 return timestamp + state->offset;
120}
121
122#ifdef XRT_OS_WINDOWS
123extern "C" void
124time_state_to_win32perfcounter(struct time_state const *state, timepoint_ns timestamp, LARGE_INTEGER *out_qpc_ticks)
125{
126 assert(state != NULL);
127 assert(out_qpc_ticks != NULL);
128
129 int64_t ns = time_state_ts_to_monotonic_ns(state, timestamp);
130
131 out_qpc_ticks->QuadPart = ns / os_ns_per_qpc_tick_get();
132}
133
134extern "C" timepoint_ns
135time_state_from_win32perfcounter(struct time_state const *state, const LARGE_INTEGER *qpc_ticks)
136{
137 assert(state != NULL);
138 assert(qpc_ticks != NULL);
139
140 int64_t ns = qpc_ticks->QuadPart * os_ns_per_qpc_tick_get();
141
142 return time_state_monotonic_to_ts_ns(state, ns);
143}
144#endif // XRT_OS_WINDOWS