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