display_linker.rs

 1use crate::{DisplayId, PlatformDisplayLinker, VideoTimestamp};
 2use collections::HashMap;
 3use parking_lot::Mutex;
 4use std::sync::Arc;
 5
 6type FrameCallback = Box<dyn FnOnce(&VideoTimestamp, &VideoTimestamp) + Send>;
 7
 8pub struct DisplayLinker {
 9    platform_linker: Arc<dyn PlatformDisplayLinker>,
10    next_frame_callbacks: Arc<Mutex<HashMap<DisplayId, Vec<FrameCallback>>>>,
11}
12
13impl DisplayLinker {
14    pub(crate) fn new(platform_linker: Arc<dyn PlatformDisplayLinker>) -> Self {
15        Self {
16            platform_linker,
17            next_frame_callbacks: Default::default(),
18        }
19    }
20
21    pub(crate) fn on_next_frame(
22        &self,
23        display_id: DisplayId,
24        callback: impl FnOnce(&VideoTimestamp, &VideoTimestamp) + Send + 'static,
25    ) {
26        let next_frame_callbacks = self.next_frame_callbacks.clone();
27        let callback = Box::new(callback);
28        match self.next_frame_callbacks.lock().entry(display_id) {
29            collections::hash_map::Entry::Occupied(mut entry) => {
30                if entry.get().is_empty() {
31                    self.platform_linker.start(display_id);
32                }
33                entry.get_mut().push(callback)
34            }
35            collections::hash_map::Entry::Vacant(entry) => {
36                // let platform_linker = self.platform_linker.clone();
37                self.platform_linker.set_output_callback(
38                    display_id,
39                    Box::new(move |current_time, output_time| {
40                        for callback in next_frame_callbacks
41                            .lock()
42                            .get_mut(&display_id)
43                            .unwrap()
44                            .drain(..)
45                        {
46                            callback(current_time, output_time);
47                        }
48                        // platform_linker.stop(display_id);
49                    }),
50                );
51                self.platform_linker.start(display_id);
52                entry.insert(vec![callback]);
53            }
54        }
55    }
56}