From 0d52d5d30458503fbac4408a31b4c0e136edba06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Manuel=20J=C3=A1quez=20Leal?= Date: Sat, 15 Jun 2019 13:17:53 +0200 Subject: [PATCH] Add GLPlayerMsg and glplayer_channel in canvas_traits GLPlayerMsg enum values are going to be the commands to send to the glplayer_thread. glplayer_channel mod is a copy of webgl_channel. --- components/canvas_traits/lib.rs | 1 + components/canvas_traits/media.rs | 54 +++++++++ components/canvas_traits/media_channel/ipc.rs | 14 +++ components/canvas_traits/media_channel/mod.rs | 106 ++++++++++++++++++ .../canvas_traits/media_channel/mpsc.rs | 58 ++++++++++ 5 files changed, 233 insertions(+) create mode 100644 components/canvas_traits/media_channel/ipc.rs create mode 100644 components/canvas_traits/media_channel/mod.rs create mode 100644 components/canvas_traits/media_channel/mpsc.rs diff --git a/components/canvas_traits/lib.rs b/components/canvas_traits/lib.rs index 2a52409a0e1..15d15a6ea68 100644 --- a/components/canvas_traits/lib.rs +++ b/components/canvas_traits/lib.rs @@ -15,6 +15,7 @@ extern crate serde; pub mod canvas; pub mod media; +mod media_channel; #[macro_use] pub mod webgl; mod webgl_channel; diff --git a/components/canvas_traits/media.rs b/components/canvas_traits/media.rs index 19be3e09a5d..4b5576dce91 100644 --- a/components/canvas_traits/media.rs +++ b/components/canvas_traits/media.rs @@ -2,8 +2,62 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +use euclid::Size2D; use servo_media::player::context::{GlApi, GlContext, NativeDisplay, PlayerGLContext}; +/// Helper function that creates a GLPlayer channel (GLPlayerSender, +/// GLPlayerReceiver) to be used in GLPlayerMsg. +pub use crate::media_channel::glplayer_channel; +/// Entry point channel type used for sending GLPlayerMsg messages to +/// the GLPlayer thread. +pub use crate::media_channel::GLPlayerChan; +/// Entry point type used in a Script Pipeline to get the GLPlayerChan +/// to be used in that thread. +pub use crate::media_channel::GLPlayerPipeline; +/// Receiver type used in GLPlayerMsg. +pub use crate::media_channel::GLPlayerReceiver; +/// Result type for send()/recv() calls in in GLPlayerMsg. +pub use crate::media_channel::GLPlayerSendResult; +/// Sender type used in GLPlayerMsg. +pub use crate::media_channel::GLPlayerSender; + +/// GLPlayer thread Message API +/// +/// These are the message that the thread will receive from the +/// constellation, the webrender::ExternalImageHandle multiplexor +/// implementation, or a htmlmediaelement +#[derive(Debug, Deserialize, Serialize)] +pub enum GLPlayerMsg { + /// Registers an instantiated player in DOM + RegisterPlayer(GLPlayerSender), + /// Unregisters a player's ID + UnregisterPlayer(u64), + /// Locks a specific texture from a player. Lock messages are used + /// for a correct synchronization with WebRender external image + /// API. + /// + /// WR locks a external texture when it wants to use the shared + /// texture contents. + /// + /// The WR client should not change the shared texture content + /// until the Unlock call. + /// + /// Currently OpenGL Sync Objects are used to implement the + /// synchronization mechanism. + Lock(u64, GLPlayerSender<(u32, Size2D, usize)>), + /// Unlocks a specific texture from a player. Unlock messages are + /// used for a correct synchronization with WebRender external + /// image API. + /// + /// The WR unlocks a context when it finished reading the shared + /// texture contents. + /// + /// Unlock messages are always sent after a Lock message. + Unlock(u64), + /// Frees all resources and closes the thread. + Exit, +} + #[derive(Clone, Debug, Deserialize, Serialize)] pub struct WindowGLContext { /// Application's GL Context diff --git a/components/canvas_traits/media_channel/ipc.rs b/components/canvas_traits/media_channel/ipc.rs new file mode 100644 index 00000000000..67548a8ddce --- /dev/null +++ b/components/canvas_traits/media_channel/ipc.rs @@ -0,0 +1,14 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +use serde::{Deserialize, Serialize}; +use std::io; + +pub type GLPlayerSender = ipc_channel::ipc::IpcSender; +pub type GLPlayerReceiver = ipc_channel::ipc::IpcReceiver; + +pub fn glplayer_channel Deserialize<'de>>( +) -> Result<(GLPlayerSender, GLPlayerReceiver), io::Error> { + ipc_channel::ipc::channel() +} diff --git a/components/canvas_traits/media_channel/mod.rs b/components/canvas_traits/media_channel/mod.rs new file mode 100644 index 00000000000..e6e7adffaa1 --- /dev/null +++ b/components/canvas_traits/media_channel/mod.rs @@ -0,0 +1,106 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +//! Enum wrappers to be able to select different channel implementations at runtime. + +mod ipc; +mod mpsc; + +use crate::media::GLPlayerMsg; +use serde::{Deserialize, Serialize}; +use servo_config::opts; +use std::fmt; + +lazy_static! { + static ref IS_MULTIPROCESS: bool = { opts::multiprocess() }; +} + +#[derive(Deserialize, Serialize)] +pub enum GLPlayerSender { + Ipc(ipc::GLPlayerSender), + Mpsc(mpsc::GLPlayerSender), +} + +impl Clone for GLPlayerSender +where + T: Serialize, +{ + fn clone(&self) -> Self { + match *self { + GLPlayerSender::Ipc(ref chan) => GLPlayerSender::Ipc(chan.clone()), + GLPlayerSender::Mpsc(ref chan) => GLPlayerSender::Mpsc(chan.clone()), + } + } +} + +impl fmt::Debug for GLPlayerSender { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "GLPlayerSender(..)") + } +} + +impl GLPlayerSender { + #[inline] + pub fn send(&self, msg: T) -> GLPlayerSendResult { + match *self { + GLPlayerSender::Ipc(ref sender) => sender.send(msg).map_err(|_| ()), + GLPlayerSender::Mpsc(ref sender) => sender.send(msg).map_err(|_| ()), + } + } +} + +pub type GLPlayerSendResult = Result<(), ()>; + +pub enum GLPlayerReceiver +where + T: for<'de> Deserialize<'de> + Serialize, +{ + Ipc(ipc::GLPlayerReceiver), + Mpsc(mpsc::GLPlayerReceiver), +} + +impl GLPlayerReceiver +where + T: for<'de> Deserialize<'de> + Serialize, +{ + pub fn recv(&self) -> Result { + match *self { + GLPlayerReceiver::Ipc(ref receiver) => receiver.recv().map_err(|_| ()), + GLPlayerReceiver::Mpsc(ref receiver) => receiver.recv().map_err(|_| ()), + } + } +} + +pub fn glplayer_channel() -> Result<(GLPlayerSender, GLPlayerReceiver), ()> +where + T: for<'de> Deserialize<'de> + Serialize, +{ + if *IS_MULTIPROCESS { + ipc::glplayer_channel() + .map(|(tx, rx)| (GLPlayerSender::Ipc(tx), GLPlayerReceiver::Ipc(rx))) + .map_err(|_| ()) + } else { + mpsc::glplayer_channel() + .map(|(tx, rx)| (GLPlayerSender::Mpsc(tx), GLPlayerReceiver::Mpsc(rx))) + } +} + +#[derive(Clone, Debug, Deserialize, Serialize)] +pub struct GLPlayerChan(pub GLPlayerSender); + +impl GLPlayerChan { + #[inline] + pub fn send(&self, msg: GLPlayerMsg) -> GLPlayerSendResult { + self.0.send(msg) + } +} + +#[derive(Clone, Debug, Deserialize, Serialize)] +pub struct GLPlayerPipeline(pub GLPlayerChan); + +impl GLPlayerPipeline { + pub fn channel(&self) -> GLPlayerChan { + self.0.clone() + } +} diff --git a/components/canvas_traits/media_channel/mpsc.rs b/components/canvas_traits/media_channel/mpsc.rs new file mode 100644 index 00000000000..7d6a396185a --- /dev/null +++ b/components/canvas_traits/media_channel/mpsc.rs @@ -0,0 +1,58 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +use serde::{Deserialize, Serialize}; +use serde::{Deserializer, Serializer}; +use std::sync::mpsc; + +#[macro_use] +macro_rules! unreachable_serializable { + ($name:ident) => { + impl Serialize for $name { + fn serialize(&self, _: S) -> Result { + unreachable!(); + } + } + + impl<'a, T> Deserialize<'a> for $name { + fn deserialize(_: D) -> Result<$name, D::Error> + where + D: Deserializer<'a>, + { + unreachable!(); + } + } + }; +} + +pub struct GLPlayerSender(mpsc::Sender); +pub struct GLPlayerReceiver(mpsc::Receiver); + +impl Clone for GLPlayerSender { + fn clone(&self) -> Self { + GLPlayerSender(self.0.clone()) + } +} + +impl GLPlayerSender { + #[inline] + pub fn send(&self, data: T) -> Result<(), mpsc::SendError> { + self.0.send(data) + } +} + +impl GLPlayerReceiver { + #[inline] + pub fn recv(&self) -> Result { + self.0.recv() + } +} + +pub fn glplayer_channel() -> Result<(GLPlayerSender, GLPlayerReceiver), ()> { + let (sender, receiver) = mpsc::channel(); + Ok((GLPlayerSender(sender), GLPlayerReceiver(receiver))) +} + +unreachable_serializable!(GLPlayerReceiver); +unreachable_serializable!(GLPlayerSender);