|
1 | | -use crate::platform::prelude::PlatformResult; |
2 | 1 | use crate::platform::x11::host_handle::HostHandle; |
3 | | -use calloop::LoopSignal; |
4 | | -use std::task::Waker; |
5 | | -use std::time::Duration; |
| 2 | +use std::os::fd::{AsFd, BorrowedFd}; |
| 3 | +use std::sync::atomic::{AtomicU8, Ordering}; |
| 4 | +use std::sync::mpsc::{Receiver, SyncSender, TryRecvError}; |
| 5 | +use std::sync::Arc; |
| 6 | +use std::time::{Duration, Instant}; |
6 | 7 |
|
7 | | -pub(crate) struct WakerSource {} |
| 8 | +mod eventfd; |
| 9 | +use crate::platform::prelude::PresentStateShared; |
| 10 | +use crate::DropData; |
| 11 | +use eventfd::*; |
| 12 | + |
| 13 | +// TODO: only instanciate FDs and stuff when first waker is created |
| 14 | +pub(crate) struct WakerSource { |
| 15 | + inner: EventFdWakerSource, |
| 16 | + flags: Arc<SharedFlags>, |
| 17 | + redraw_channel_send: SyncSender<Instant>, |
| 18 | + redraw_channel_recv: Receiver<Instant>, |
| 19 | +} |
8 | 20 |
|
9 | 21 | impl WakerSource { |
10 | 22 | pub fn new(host: &HostHandle) -> Self { |
11 | | - todo!() |
| 23 | + if host.fd_support().is_some() { |
| 24 | + } else if host.timer_support().is_some() { |
| 25 | + todo!() |
| 26 | + } else { |
| 27 | + } |
| 28 | + |
| 29 | + let (send, recv) = std::sync::mpsc::sync_channel(100); |
| 30 | + |
| 31 | + Self { |
| 32 | + inner: EventFdWakerSource::new(), |
| 33 | + flags: Arc::new(SharedFlags::new()), |
| 34 | + redraw_channel_recv: recv, |
| 35 | + redraw_channel_send: send, |
| 36 | + } |
| 37 | + } |
| 38 | + |
| 39 | + pub fn create_waker(&self) -> WindowWaker { |
| 40 | + WindowWaker { |
| 41 | + inner: self.inner.create_waker(), |
| 42 | + flag: Arc::clone(&self.flags), |
| 43 | + redraw_channel_send: self.redraw_channel_send.clone(), |
| 44 | + } |
12 | 45 | } |
13 | 46 |
|
14 | | - pub fn new_waker(&self) -> Waker { |
15 | | - todo!() |
| 47 | + pub fn poll_requests(&self, present_state_shared: &PresentStateShared, host: &HostHandle) { |
| 48 | + if !self.inner.poll() { |
| 49 | + return; |
| 50 | + } |
| 51 | + |
| 52 | + let flags = self.flags.take(); |
| 53 | + let requests = self.get_all_redraw_requests(); |
| 54 | + |
| 55 | + for instant in requests { |
| 56 | + if let Some(duration) = instant.checked_duration_since(Instant::now()) { |
| 57 | + present_state_shared.request_present_notify_after(duration, host); |
| 58 | + } else { |
| 59 | + present_state_shared.request_present_notify() |
| 60 | + } |
| 61 | + } |
| 62 | + |
| 63 | + if flags.poll() { |
| 64 | + present_state_shared.request_poll(); |
| 65 | + } |
| 66 | + |
| 67 | + if flags.redraw() { |
| 68 | + present_state_shared.request_present_notify(); |
| 69 | + } |
| 70 | + |
| 71 | + if flags.dropped() { |
| 72 | + // TODO |
| 73 | + } |
| 74 | + } |
| 75 | + |
| 76 | + fn get_all_redraw_requests(&self) -> Vec<Instant> { |
| 77 | + let mut requests = vec![]; |
| 78 | + |
| 79 | + loop { |
| 80 | + match self.redraw_channel_recv.try_recv() { |
| 81 | + Ok(instant) => requests.push(instant), |
| 82 | + Err(TryRecvError::Empty) => break, |
| 83 | + Err(TryRecvError::Disconnected) => unreachable!(), // We always hold onto one sender |
| 84 | + } |
| 85 | + } |
| 86 | + |
| 87 | + requests |
| 88 | + } |
| 89 | + |
| 90 | + pub fn inner_fd(&self) -> BorrowedFd<'_> { |
| 91 | + self.inner.as_fd() |
16 | 92 | } |
17 | 93 | } |
18 | 94 |
|
19 | 95 | #[derive(Clone)] |
20 | 96 | pub struct WindowWaker { |
21 | | - pub(crate) loop_signal: LoopSignal, |
| 97 | + inner: EventFdWaker, |
| 98 | + flag: Arc<SharedFlags>, |
| 99 | + redraw_channel_send: SyncSender<Instant>, |
22 | 100 | } |
23 | 101 |
|
24 | 102 | impl WindowWaker { |
25 | 103 | pub fn request_redraw(&self) { |
26 | | - self.request_redraw_after(Duration::ZERO) |
| 104 | + self.flag.set_redraw(); |
| 105 | + self.inner.wake(); |
27 | 106 | } |
28 | 107 |
|
29 | 108 | pub fn request_redraw_after(&self, duration: Duration) { |
30 | | - todo!() |
| 109 | + if duration.is_zero() { |
| 110 | + return self.request_redraw(); |
| 111 | + } |
| 112 | + |
| 113 | + self.redraw_channel_send.send(Instant::now() + duration).unwrap(); |
| 114 | + self.inner.wake() |
31 | 115 | } |
32 | 116 |
|
33 | 117 | pub fn request_poll(&self) { |
34 | | - todo!() |
| 118 | + self.flag.set_poll(); |
| 119 | + self.inner.wake(); |
| 120 | + } |
| 121 | +} |
| 122 | + |
| 123 | +impl Drop for WindowWaker { |
| 124 | + fn drop(&mut self) { |
| 125 | + self.flag.set_dropped(); |
| 126 | + } |
| 127 | +} |
| 128 | + |
| 129 | +struct SharedFlags(AtomicU8); |
| 130 | + |
| 131 | +impl SharedFlags { |
| 132 | + pub fn new() -> Self { |
| 133 | + Self(AtomicU8::new(0)) |
| 134 | + } |
| 135 | + |
| 136 | + const POLL: u8 = 1 << 0; |
| 137 | + const REDRAW: u8 = 1 << 1; |
| 138 | + const DROPPED: u8 = 1 << 2; |
| 139 | + |
| 140 | + fn set_poll(&self) { |
| 141 | + self.0.fetch_or(Self::POLL, Ordering::Release); |
| 142 | + } |
| 143 | + |
| 144 | + fn set_redraw(&self) { |
| 145 | + self.0.fetch_or(Self::REDRAW, Ordering::Release); |
| 146 | + } |
| 147 | + |
| 148 | + fn set_dropped(&self) { |
| 149 | + self.0.fetch_or(Self::DROPPED, Ordering::Release); |
| 150 | + } |
| 151 | + |
| 152 | + fn take(&self) -> FlagsValues { |
| 153 | + FlagsValues(self.0.swap(0, Ordering::Acquire)) |
| 154 | + } |
| 155 | +} |
| 156 | + |
| 157 | +pub struct FlagsValues(u8); |
| 158 | + |
| 159 | +impl FlagsValues { |
| 160 | + fn poll(&self) -> bool { |
| 161 | + self.0 & SharedFlags::POLL != 0 |
| 162 | + } |
| 163 | + |
| 164 | + fn redraw(&self) -> bool { |
| 165 | + self.0 & SharedFlags::REDRAW != 0 |
| 166 | + } |
| 167 | + |
| 168 | + fn dropped(&self) -> bool { |
| 169 | + self.0 & SharedFlags::DROPPED != 0 |
35 | 170 | } |
36 | 171 | } |
0 commit comments