1use std::sync::{Arc, Mutex};
6use std::thread;
7
8use compositing_traits::{WebrenderExternalImageRegistry, WebrenderImageHandlerType};
9use ipc_channel::ipc::{IpcSender, channel};
10use log::{trace, warn};
11use rustc_hash::FxHashMap;
12use webrender_api::ExternalImageId;
13
14use crate::{GLPlayerMsg, GLPlayerMsgForward};
17
18pub struct GLPlayerThread {
21 players: FxHashMap<u64, IpcSender<GLPlayerMsgForward>>,
23 external_images: Arc<Mutex<WebrenderExternalImageRegistry>>,
26}
27
28impl GLPlayerThread {
29 pub fn new(external_images: Arc<Mutex<WebrenderExternalImageRegistry>>) -> Self {
30 GLPlayerThread {
31 players: Default::default(),
32 external_images,
33 }
34 }
35
36 pub fn start(
37 external_images: Arc<Mutex<WebrenderExternalImageRegistry>>,
38 ) -> IpcSender<GLPlayerMsg> {
39 let (sender, receiver) = channel().unwrap();
40 thread::Builder::new()
41 .name("GLPlayer".to_owned())
42 .spawn(move || {
43 let mut renderer = GLPlayerThread::new(external_images);
44 loop {
45 let msg = receiver.recv().unwrap();
46 let exit = renderer.handle_msg(msg);
47 if exit {
48 return;
49 }
50 }
51 })
52 .expect("Thread spawning failed");
53
54 sender
55 }
56
57 #[inline]
59 fn handle_msg(&mut self, msg: GLPlayerMsg) -> bool {
60 trace!("processing {:?}", msg);
61 match msg {
62 GLPlayerMsg::RegisterPlayer(sender) => {
63 let id = self
64 .external_images
65 .lock()
66 .unwrap()
67 .next_id(WebrenderImageHandlerType::Media)
68 .0;
69 self.players.insert(id, sender.clone());
70 sender.send(GLPlayerMsgForward::PlayerId(id)).unwrap();
71 },
72 GLPlayerMsg::UnregisterPlayer(id) => {
73 self.external_images
74 .lock()
75 .unwrap()
76 .remove(&ExternalImageId(id));
77 if self.players.remove(&id).is_none() {
78 warn!("Tried to remove an unknown player");
79 }
80 },
81 GLPlayerMsg::Lock(id, handler_sender) => {
82 if let Some(sender) = self.players.get(&id) {
83 sender.send(GLPlayerMsgForward::Lock(handler_sender)).ok();
84 }
85 },
86 GLPlayerMsg::Unlock(id) => {
87 if let Some(sender) = self.players.get(&id) {
88 sender.send(GLPlayerMsgForward::Unlock()).ok();
89 }
90 },
91 GLPlayerMsg::Exit => return true,
92 }
93
94 false
95 }
96}