diff options
Diffstat (limited to 'components/shared/compositing/lib.rs')
-rw-r--r-- | components/shared/compositing/lib.rs | 215 |
1 files changed, 215 insertions, 0 deletions
diff --git a/components/shared/compositing/lib.rs b/components/shared/compositing/lib.rs new file mode 100644 index 00000000000..81ef4ace3b9 --- /dev/null +++ b/components/shared/compositing/lib.rs @@ -0,0 +1,215 @@ +/* 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/. */ + +//! Communication with the compositor thread. + +mod constellation_msg; + +use std::fmt::{Debug, Error, Formatter}; + +use canvas::canvas_paint_thread::ImageUpdate; +pub use constellation_msg::ConstellationMsg; +use crossbeam_channel::{Receiver, Sender}; +use embedder_traits::EventLoopWaker; +use euclid::Rect; +use gfx_traits::Epoch; +use ipc_channel::ipc::IpcSender; +use log::warn; +use msg::constellation_msg::{PipelineId, TopLevelBrowsingContextId}; +use net_traits::image::base::Image; +use net_traits::NetToCompositorMsg; +use script_traits::{ + AnimationState, ConstellationControlMsg, EventResult, LayoutControlMsg, MouseButton, + MouseEventType, ScriptToCompositorMsg, +}; +use style_traits::CSSPixel; +use webrender_api::units::{DeviceIntPoint, DeviceIntSize}; +use webrender_api::{self, FontInstanceKey, FontKey, ImageKey}; + +/// Why we performed a composite. This is used for debugging. +#[derive(Clone, Copy, Debug, PartialEq)] +pub enum CompositingReason { + /// We hit the delayed composition timeout. (See `delayed_composition.rs`.) + DelayedCompositeTimeout, + /// The window has been scrolled and we're starting the first recomposite. + Scroll, + /// A scroll has continued and we need to recomposite again. + ContinueScroll, + /// We're performing the single composite in headless mode. + Headless, + /// We're performing a composite to run an animation. + Animation, + /// A new frame tree has been loaded. + NewFrameTree, + /// New painted buffers have been received. + NewPaintedBuffers, + /// The window has been zoomed. + Zoom, + /// A new WebRender frame has arrived. + NewWebRenderFrame, + /// WebRender has processed a scroll event and has generated a new frame. + NewWebRenderScrollFrame, + /// The window has been resized and will need to be synchronously repainted. + Resize, +} + +/// Sends messages to the compositor. +pub struct CompositorProxy { + pub sender: Sender<CompositorMsg>, + pub event_loop_waker: Box<dyn EventLoopWaker>, +} + +impl CompositorProxy { + pub fn send(&self, msg: CompositorMsg) { + if let Err(err) = self.sender.send(msg) { + warn!("Failed to send response ({:?}).", err); + } + self.event_loop_waker.wake(); + } +} + +impl Clone for CompositorProxy { + fn clone(&self) -> CompositorProxy { + CompositorProxy { + sender: self.sender.clone(), + event_loop_waker: self.event_loop_waker.clone(), + } + } +} + +/// The port that the compositor receives messages on. +pub struct CompositorReceiver { + pub receiver: Receiver<CompositorMsg>, +} + +impl CompositorReceiver { + pub fn try_recv_compositor_msg(&mut self) -> Option<CompositorMsg> { + self.receiver.try_recv().ok() + } + pub fn recv_compositor_msg(&mut self) -> CompositorMsg { + self.receiver.recv().unwrap() + } +} + +impl CompositorProxy { + pub fn recomposite(&self, reason: CompositingReason) { + self.send(CompositorMsg::Recomposite(reason)); + } +} + +/// Messages from (or via) the constellation thread to the compositor. +pub enum CompositorMsg { + /// Informs the compositor that the constellation has completed shutdown. + /// Required because the constellation can have pending calls to make + /// (e.g. SetFrameTree) at the time that we send it an ExitMsg. + ShutdownComplete, + /// Alerts the compositor that the given pipeline has changed whether it is running animations. + ChangeRunningAnimationsState(PipelineId, AnimationState), + /// Replaces the current frame tree, typically called during main frame navigation. + SetFrameTree(SendableFrameTree), + /// Composite. + Recomposite(CompositingReason), + /// Script has handled a touch event, and either prevented or allowed default actions. + TouchEventProcessed(EventResult), + /// Composite to a PNG file and return the Image over a passed channel. + CreatePng(Option<Rect<f32, CSSPixel>>, IpcSender<Option<Image>>), + /// A reply to the compositor asking if the output image is stable. + IsReadyToSaveImageReply(bool), + /// Pipeline visibility changed + PipelineVisibilityChanged(PipelineId, bool), + /// WebRender has successfully processed a scroll. The boolean specifies whether a composite is + /// needed. + NewScrollFrameReady(bool), + /// A pipeline was shut down. + // This message acts as a synchronization point between the constellation, + // when it shuts down a pipeline, to the compositor; when the compositor + // sends a reply on the IpcSender, the constellation knows it's safe to + // tear down the other threads associated with this pipeline. + PipelineExited(PipelineId, IpcSender<()>), + /// Runs a closure in the compositor thread. + /// It's used to dispatch functions from webrender to the main thread's event loop. + /// Required to allow WGL GLContext sharing in Windows. + Dispatch(Box<dyn Fn() + Send>), + /// Indicates to the compositor that it needs to record the time when the frame with + /// the given ID (epoch) is painted and report it to the layout thread of the given + /// pipeline ID. + PendingPaintMetric(PipelineId, Epoch), + /// The load of a page has completed + LoadComplete(TopLevelBrowsingContextId), + /// WebDriver mouse button event + WebDriverMouseButtonEvent(MouseEventType, MouseButton, f32, f32), + /// WebDriver mouse move event + WebDriverMouseMoveEvent(f32, f32), + + /// Get Window Informations size and position. + GetClientWindow(IpcSender<(DeviceIntSize, DeviceIntPoint)>), + /// Get screen size. + GetScreenSize(IpcSender<DeviceIntSize>), + /// Get screen available size. + GetScreenAvailSize(IpcSender<DeviceIntSize>), + + /// Messages forwarded to the compositor by the constellation from other crates. These + /// messages are mainly passed on from the compositor to WebRender. + Forwarded(ForwardedToCompositorMsg), +} + +pub struct SendableFrameTree { + pub pipeline: CompositionPipeline, + pub children: Vec<SendableFrameTree>, +} + +/// The subset of the pipeline that is needed for layer composition. +#[derive(Clone)] +pub struct CompositionPipeline { + pub id: PipelineId, + pub top_level_browsing_context_id: TopLevelBrowsingContextId, + pub script_chan: IpcSender<ConstellationControlMsg>, + pub layout_chan: IpcSender<LayoutControlMsg>, +} + +pub enum FontToCompositorMsg { + AddFontInstance(FontKey, f32, Sender<FontInstanceKey>), + AddFont(gfx_traits::FontData, Sender<FontKey>), +} + +pub enum CanvasToCompositorMsg { + GenerateKey(Sender<ImageKey>), + UpdateImages(Vec<ImageUpdate>), +} + +/// Messages forwarded by the Constellation to the Compositor. +pub enum ForwardedToCompositorMsg { + Layout(ScriptToCompositorMsg), + Net(NetToCompositorMsg), + Font(FontToCompositorMsg), + Canvas(CanvasToCompositorMsg), +} + +impl Debug for CompositorMsg { + fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { + match *self { + CompositorMsg::ShutdownComplete => write!(f, "ShutdownComplete"), + CompositorMsg::ChangeRunningAnimationsState(_, state) => { + write!(f, "ChangeRunningAnimationsState({:?})", state) + }, + CompositorMsg::SetFrameTree(..) => write!(f, "SetFrameTree"), + CompositorMsg::Recomposite(..) => write!(f, "Recomposite"), + CompositorMsg::TouchEventProcessed(..) => write!(f, "TouchEventProcessed"), + CompositorMsg::CreatePng(..) => write!(f, "CreatePng"), + CompositorMsg::IsReadyToSaveImageReply(..) => write!(f, "IsReadyToSaveImageReply"), + CompositorMsg::PipelineVisibilityChanged(..) => write!(f, "PipelineVisibilityChanged"), + CompositorMsg::PipelineExited(..) => write!(f, "PipelineExited"), + CompositorMsg::NewScrollFrameReady(..) => write!(f, "NewScrollFrameReady"), + CompositorMsg::Dispatch(..) => write!(f, "Dispatch"), + CompositorMsg::PendingPaintMetric(..) => write!(f, "PendingPaintMetric"), + CompositorMsg::LoadComplete(..) => write!(f, "LoadComplete"), + CompositorMsg::WebDriverMouseButtonEvent(..) => write!(f, "WebDriverMouseButtonEvent"), + CompositorMsg::WebDriverMouseMoveEvent(..) => write!(f, "WebDriverMouseMoveEvent"), + CompositorMsg::GetClientWindow(..) => write!(f, "GetClientWindow"), + CompositorMsg::GetScreenSize(..) => write!(f, "GetScreenSize"), + CompositorMsg::GetScreenAvailSize(..) => write!(f, "GetScreenAvailSize"), + CompositorMsg::Forwarded(..) => write!(f, "Webrender"), + } + } +} |