1use std::cell::{Cell, LazyCell, RefCell};
6use std::rc::Rc;
7use std::sync::Arc;
8use std::sync::atomic::{AtomicBool, Ordering};
9use std::thread::{self, JoinHandle};
10use std::time::Duration;
11
12use crossbeam_channel::{RecvTimeoutError, Sender};
13use embedder_traits::{EventLoopWaker, RefreshDriver};
14use log::warn;
15use servo_constellation_traits::EmbedderToConstellationMessage;
16use timers::{BoxedTimerCallback, TimerEventRequest, TimerScheduler};
17
18use crate::painter::Painter;
19use crate::webview_renderer::WebViewRenderer;
20
21pub(crate) struct BaseRefreshDriver {
27 waiting_for_frame: Arc<AtomicBool>,
30 event_loop_waker: Box<dyn EventLoopWaker>,
32 observers: RefCell<Vec<Rc<dyn RefreshDriverObserver>>>,
34 refresh_driver: Rc<dyn RefreshDriver>,
37}
38
39impl BaseRefreshDriver {
40 pub(crate) fn new(
41 event_loop_waker: Box<dyn EventLoopWaker>,
42 refresh_driver: Option<Rc<dyn RefreshDriver>>,
43 timer_refresh_driver: &LazyCell<Rc<TimerRefreshDriver>>,
44 ) -> Self {
45 let refresh_driver = refresh_driver.unwrap_or_else(|| (**timer_refresh_driver).clone());
46 Self {
47 waiting_for_frame: Arc::new(AtomicBool::new(false)),
48 event_loop_waker,
49 observers: Default::default(),
50 refresh_driver,
51 }
52 }
53
54 pub(crate) fn add_observer(&self, observer: Rc<dyn RefreshDriverObserver>) {
55 let mut observers = self.observers.borrow_mut();
56 observers.push(observer);
57
58 if observers.len() == 1 {
60 self.observe_next_frame();
61 }
62 }
63
64 pub(crate) fn notify_will_paint(&self, painter: &mut Painter) -> bool {
69 if self.wait_to_paint() {
73 return false;
74 }
75
76 let still_has_observers = {
78 let mut observers = self.observers.borrow_mut();
79 observers.retain(|observer| observer.frame_started(painter));
80 !observers.is_empty()
81 };
82
83 if still_has_observers {
84 self.observe_next_frame();
85 }
86 true
87 }
88
89 fn observe_next_frame(&self) {
90 self.waiting_for_frame.store(true, Ordering::Relaxed);
91
92 let waiting_for_frame = self.waiting_for_frame.clone();
93 let event_loop_waker = self.event_loop_waker.clone_box();
94 self.refresh_driver.observe_next_frame(Box::new(move || {
95 waiting_for_frame.store(false, Ordering::Relaxed);
96 event_loop_waker.wake();
97 }));
98 }
99
100 pub(crate) fn wait_to_paint(&self) -> bool {
104 !self.observers.borrow().is_empty() && self.waiting_for_frame.load(Ordering::Relaxed)
105 }
106}
107
108pub(crate) trait RefreshDriverObserver {
113 fn frame_started(&self, painter: &mut Painter) -> bool;
117}
118
119pub(crate) struct AnimationRefreshDriverObserver {
124 pub(crate) constellation_sender: Sender<EmbedderToConstellationMessage>,
126
127 pub(crate) animating: Cell<bool>,
129}
130
131impl AnimationRefreshDriverObserver {
132 pub(crate) fn new(constellation_sender: Sender<EmbedderToConstellationMessage>) -> Self {
133 Self {
134 constellation_sender,
135 animating: Default::default(),
136 }
137 }
138
139 pub(crate) fn notify_animation_state_changed(
140 &self,
141 webview_renderer: &WebViewRenderer,
142 ) -> bool {
143 if !webview_renderer.animating() {
144 return false;
147 }
148
149 if let Err(error) =
150 self.constellation_sender
151 .send(EmbedderToConstellationMessage::TickAnimation(vec![
152 webview_renderer.id,
153 ]))
154 {
155 warn!("Sending tick to constellation failed ({error:?}).");
156 }
157
158 if self.animating.get() {
159 return false;
160 }
161
162 self.animating.set(true);
163 true
164 }
165}
166
167impl RefreshDriverObserver for AnimationRefreshDriverObserver {
168 fn frame_started(&self, painter: &mut Painter) -> bool {
169 let animating_webviews = painter.animating_webviews();
171
172 if animating_webviews.is_empty() {
175 self.animating.set(false);
176 return false;
177 }
178
179 if let Err(error) =
181 self.constellation_sender
182 .send(EmbedderToConstellationMessage::TickAnimation(
183 animating_webviews,
184 ))
185 {
186 warn!("Sending tick to constellation failed ({error:?}).");
187 return false;
188 }
189
190 self.animating.set(true);
191 true
192 }
193}
194
195enum TimerThreadMessage {
196 Request(TimerEventRequest),
197 Quit,
198}
199
200pub(crate) struct TimerRefreshDriver {
209 sender: Sender<TimerThreadMessage>,
210 join_handle: Option<JoinHandle<()>>,
211}
212
213impl Default for TimerRefreshDriver {
214 fn default() -> Self {
215 let (sender, receiver) = crossbeam_channel::unbounded::<TimerThreadMessage>();
216 let join_handle = thread::Builder::new()
217 .name(String::from("PaintTimerThread"))
218 .spawn(move || {
219 let mut scheduler = TimerScheduler::default();
220
221 loop {
222 let recv_result = match scheduler.next_deadline() {
223 Some(deadline) => receiver.recv_deadline(deadline),
224 None => receiver.recv().map_err(|_| RecvTimeoutError::Disconnected),
225 };
226 match recv_result {
227 Ok(TimerThreadMessage::Request(request)) => {
228 scheduler.schedule_timer(request);
229 },
230 Err(RecvTimeoutError::Timeout) => scheduler.dispatch_completed_timers(),
231 Ok(TimerThreadMessage::Quit) | Err(RecvTimeoutError::Disconnected) => {
232 return;
233 },
234 }
235 }
236 })
237 .expect("Could not create RefreshDriver timer thread.");
238
239 Self {
240 sender,
241 join_handle: Some(join_handle),
242 }
243 }
244}
245
246impl TimerRefreshDriver {
247 pub(crate) fn queue_timer(&self, duration: Duration, callback: BoxedTimerCallback) {
248 let _ = self
249 .sender
250 .send(TimerThreadMessage::Request(TimerEventRequest {
251 callback,
252 duration,
253 }));
254 }
255}
256
257impl RefreshDriver for TimerRefreshDriver {
258 fn observe_next_frame(&self, new_start_frame_callback: Box<dyn Fn() + Send + 'static>) {
259 const FRAME_DURATION: Duration = Duration::from_millis(1000 / 120);
260 self.queue_timer(FRAME_DURATION, new_start_frame_callback);
261 }
262}
263
264impl Drop for TimerRefreshDriver {
265 fn drop(&mut self) {
266 let _ = self.sender.send(TimerThreadMessage::Quit);
267 if let Some(join_handle) = self.join_handle.take() {
268 let _ = join_handle.join();
269 }
270 }
271}