blob: ad8cf2f7b22e04a8f0e136686569ca1a5ff91c7c (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
|
use std::num::NonZeroU64;
use std::time::Duration;
use crate::utils::get_monotonic_time;
#[derive(Debug)]
pub struct FrameClock {
last_presentation_time: Option<Duration>,
refresh_interval_ns: Option<NonZeroU64>,
}
impl FrameClock {
pub fn new(refresh_interval: Option<Duration>) -> Self {
let refresh_interval_ns = if let Some(interval) = &refresh_interval {
assert_eq!(interval.as_secs(), 0);
Some(NonZeroU64::new(interval.subsec_nanos().into()).unwrap())
} else {
None
};
Self {
last_presentation_time: None,
refresh_interval_ns,
}
}
pub fn refresh_interval(&self) -> Option<Duration> {
self.refresh_interval_ns
.map(|r| Duration::from_nanos(r.get()))
}
pub fn presented(&mut self, presentation_time: Duration) {
if presentation_time.is_zero() {
// Not interested in these.
return;
}
self.last_presentation_time = Some(presentation_time);
}
pub fn next_presentation_time(&self) -> Duration {
let mut now = get_monotonic_time();
let Some(refresh_interval_ns) = self.refresh_interval_ns else {
return now;
};
let Some(last_presentation_time) = self.last_presentation_time else {
return now;
};
let refresh_interval_ns = refresh_interval_ns.get();
if now <= last_presentation_time {
// Got an early VBlank.
let orig_now = now;
now += Duration::from_nanos(refresh_interval_ns);
if now < last_presentation_time {
// Not sure when this can happen.
error!(
now = ?orig_now,
?last_presentation_time,
"got a 2+ early VBlank, {:?} until presentation",
last_presentation_time - now,
);
now = last_presentation_time + Duration::from_nanos(refresh_interval_ns);
}
}
let since_last = now - last_presentation_time;
let since_last_ns =
since_last.as_secs() * 1_000_000_000 + u64::from(since_last.subsec_nanos());
let to_next_ns = (since_last_ns / refresh_interval_ns + 1) * refresh_interval_ns;
last_presentation_time + Duration::from_nanos(to_next_ns)
}
}
|