diff options
Diffstat (limited to 'components/compositing')
-rw-r--r-- | components/compositing/compositor.rs | 11 | ||||
-rw-r--r-- | components/compositing/compositor_thread.rs | 29 | ||||
-rw-r--r-- | components/compositing/constellation.rs | 14 | ||||
-rw-r--r-- | components/compositing/headless.rs | 147 | ||||
-rw-r--r-- | components/compositing/lib.rs | 1 | ||||
-rw-r--r-- | components/compositing/pipeline.rs | 14 | ||||
-rw-r--r-- | components/compositing/windowing.rs | 3 |
7 files changed, 41 insertions, 178 deletions
diff --git a/components/compositing/compositor.rs b/components/compositing/compositor.rs index b5df18b2564..7f6c28c178e 100644 --- a/components/compositing/compositor.rs +++ b/components/compositing/compositor.rs @@ -525,6 +525,7 @@ impl<Window: WindowMethods> IOCompositor<Window> { (Msg::InitializeLayersForPipeline(pipeline_id, epoch, properties), ShutdownState::NotShuttingDown) => { + debug!("initializing layers for pipeline: {:?}", pipeline_id); self.pipeline_details(pipeline_id).current_epoch = epoch; self.collect_old_layers(pipeline_id, &properties); @@ -542,7 +543,7 @@ impl<Window: WindowMethods> IOCompositor<Window> { (Msg::GetNativeDisplay(chan), ShutdownState::NotShuttingDown) => { - chan.send(Some(self.native_display.clone())).unwrap(); + chan.send(self.native_display.clone()).unwrap(); } (Msg::AssignPaintedBuffers(pipeline_id, epoch, replies, frame_tree_id), @@ -641,7 +642,8 @@ impl<Window: WindowMethods> IOCompositor<Window> { reply.send(img).unwrap(); } - (Msg::PaintThreadExited(pipeline_id), ShutdownState::NotShuttingDown) => { + (Msg::PaintThreadExited(pipeline_id), _) => { + debug!("compositor learned about paint thread exiting: {:?}", pipeline_id); self.remove_pipeline_root_layer(pipeline_id); } @@ -690,8 +692,11 @@ impl<Window: WindowMethods> IOCompositor<Window> { reports_chan.send(reports); } - (Msg::PipelineExited(pipeline_id), _) => { + (Msg::PipelineExited(pipeline_id, sender), _) => { + debug!("Compositor got pipeline exited: {:?}", pipeline_id); self.pending_subpages.remove(&pipeline_id); + self.remove_pipeline_root_layer(pipeline_id); + sender.send(()).unwrap(); } // When we are shutting_down, we need to avoid performing operations diff --git a/components/compositing/compositor_thread.rs b/components/compositing/compositor_thread.rs index eb0020c366d..fdfd4c633bf 100644 --- a/components/compositing/compositor_thread.rs +++ b/components/compositing/compositor_thread.rs @@ -9,7 +9,6 @@ use compositor::{self, CompositingReason}; use euclid::point::Point2D; use euclid::size::Size2D; use gfx_traits::{Epoch, FrameTreeId, LayerId, LayerProperties, PaintListener}; -use headless; use ipc_channel::ipc::{self, IpcReceiver, IpcSender}; use layers::layers::{BufferRequest, LayerBufferSet}; use layers::platform::surface::{NativeDisplay, NativeSurface}; @@ -98,6 +97,8 @@ pub fn run_script_listener_thread(compositor_proxy: Box<CompositorProxy + 'stati ScriptToCompositorMsg::TouchEventProcessed(result) => { compositor_proxy.send(Msg::TouchEventProcessed(result)) } + + ScriptToCompositorMsg::Exited => break, } } } @@ -123,7 +124,7 @@ impl PaintListener for Box<CompositorProxy + 'static + Send> { // just return None in this case, since the paint thread // will exit shortly and never actually be requested // to paint buffers by the compositor. - port.recv().unwrap_or(None) + port.recv().ok() } fn assign_painted_buffers(&mut self, @@ -174,9 +175,7 @@ pub enum Msg { /// Requests the compositor's graphics metadata. Graphics metadata is what the painter needs /// to create surfaces that the compositor can see. On Linux this is the X display; on Mac this /// is the pixel format. - /// - /// The headless compositor returns `None`. - GetNativeDisplay(Sender<Option<NativeDisplay>>), + GetNativeDisplay(Sender<NativeDisplay>), /// Tells the compositor to create or update the layers for a pipeline if necessary /// (i.e. if no layer with that ID exists). @@ -233,7 +232,11 @@ pub enum Msg { /// Resize the window to size ResizeTo(Size2D<u32>), /// A pipeline was shut down. - PipelineExited(PipelineId), + // 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<()>), } impl Debug for Msg { @@ -276,20 +279,12 @@ impl Debug for Msg { pub struct CompositorThread; impl CompositorThread { - pub fn create<Window>(window: Option<Rc<Window>>, + pub fn create<Window>(window: Rc<Window>, state: InitialCompositorState) -> Box<CompositorEventListener + 'static> where Window: WindowMethods + 'static { - match window { - Some(window) => { - box compositor::IOCompositor::create(window, state) - as Box<CompositorEventListener> - } - None => { - box headless::NullCompositor::create(state) - as Box<CompositorEventListener> - } - } + box compositor::IOCompositor::create(window, state) + as Box<CompositorEventListener> } } diff --git a/components/compositing/constellation.rs b/components/compositing/constellation.rs index f1876e660c7..159477e34cb 100644 --- a/components/compositing/constellation.rs +++ b/components/compositing/constellation.rs @@ -648,8 +648,13 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF> } // Update pipeline url after redirections Request::Script(FromScriptMsg::SetFinalUrl(pipeline_id, final_url)) => { - debug!("constellation got set final url message"); - self.mut_pipeline(pipeline_id).url = final_url; + // The script may have finished loading after we already started shutting down. + if let Some(ref mut pipeline) = self.pipelines.get_mut(&pipeline_id) { + debug!("constellation got set final url message"); + pipeline.url = final_url; + } else { + debug!("constellation got set final url message for dead pipeline"); + } } Request::Script(FromScriptMsg::MozBrowserEvent(pipeline_id, subpage_id, @@ -693,9 +698,12 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF> } } } - Request::Script(FromScriptMsg::RemoveIFrame(pipeline_id)) => { + Request::Script(FromScriptMsg::RemoveIFrame(pipeline_id, sender)) => { debug!("constellation got remove iframe message"); self.handle_remove_iframe_msg(pipeline_id); + if let Some(sender) = sender { + sender.send(()).unwrap(); + } } Request::Script(FromScriptMsg::NewFavicon(url)) => { debug!("constellation got new favicon message"); diff --git a/components/compositing/headless.rs b/components/compositing/headless.rs deleted file mode 100644 index c46bdd52262..00000000000 --- a/components/compositing/headless.rs +++ /dev/null @@ -1,147 +0,0 @@ -/* 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 http://mozilla.org/MPL/2.0/. */ - -use AnimationTickType; -use CompositorMsg as ConstellationMsg; -use compositor_thread::{CompositorEventListener, CompositorReceiver}; -use compositor_thread::{InitialCompositorState, Msg}; -use euclid::scale_factor::ScaleFactor; -use euclid::{Point2D, Size2D}; -use msg::constellation_msg::WindowSizeData; -use profile_traits::mem; -use profile_traits::time; -use script_traits::AnimationState; -use std::sync::mpsc::Sender; -use util::opts; -use windowing::WindowEvent; - -/// Starts the compositor, which listens for messages on the specified port. -/// -/// This is the null compositor which doesn't draw anything to the screen. -/// It's intended for headless testing. -pub struct NullCompositor { - /// The port on which we receive messages. - pub port: Box<CompositorReceiver>, - /// A channel to the constellation. - constellation_chan: Sender<ConstellationMsg>, - /// A channel to the time profiler. - time_profiler_chan: time::ProfilerChan, - /// A channel to the memory profiler. - mem_profiler_chan: mem::ProfilerChan, -} - -impl NullCompositor { - fn new(state: InitialCompositorState) -> NullCompositor { - NullCompositor { - port: state.receiver, - constellation_chan: state.constellation_chan, - time_profiler_chan: state.time_profiler_chan, - mem_profiler_chan: state.mem_profiler_chan, - } - } - - pub fn create(state: InitialCompositorState) -> NullCompositor { - let compositor = NullCompositor::new(state); - - // Tell the constellation about the initial fake size. - { - compositor.constellation_chan.send(ConstellationMsg::ResizedWindow(WindowSizeData { - initial_viewport: Size2D::typed(800_f32, 600_f32), - visible_viewport: Size2D::typed(800_f32, 600_f32), - device_pixel_ratio: - ScaleFactor::new(opts::get().device_pixels_per_px.unwrap_or(1.0)), - })).unwrap(); - } - - compositor - } -} - -impl CompositorEventListener for NullCompositor { - fn handle_events(&mut self, _: Vec<WindowEvent>) -> bool { - match self.port.recv_compositor_msg() { - Msg::Exit(chan) => { - debug!("shutting down the constellation"); - self.constellation_chan.send(ConstellationMsg::Exit).unwrap(); - chan.send(()).unwrap(); - } - - Msg::ShutdownComplete => { - debug!("constellation completed shutdown"); - - // Drain compositor port, sometimes messages contain channels that are blocking - // another thread from finishing (i.e. SetIds) - while self.port.try_recv_compositor_msg().is_some() {} - - self.time_profiler_chan.send(time::ProfilerMsg::Exit); - self.mem_profiler_chan.send(mem::ProfilerMsg::Exit); - - return false - } - - Msg::GetNativeDisplay(chan) => { - chan.send(None).unwrap(); - } - - Msg::SetFrameTree(_, response_chan, _) => { - response_chan.send(()).unwrap(); - } - - Msg::GetClientWindow(send) => { - let rect = (Size2D::zero(), Point2D::zero()); - send.send(rect).unwrap(); - } - - Msg::ChangeRunningAnimationsState(pipeline_id, animation_state) => { - match animation_state { - AnimationState::AnimationsPresent | - AnimationState::NoAnimationsPresent | - AnimationState::NoAnimationCallbacksPresent => {} - AnimationState::AnimationCallbacksPresent => { - let msg = ConstellationMsg::TickAnimation(pipeline_id, AnimationTickType::Script); - self.constellation_chan.send(msg).unwrap() - } - } - } - - // Explicitly list ignored messages so that when we add a new one, - // we'll notice and think about whether it needs a response, like - // SetFrameTree. - - Msg::InitializeLayersForPipeline(..) | - Msg::AssignPaintedBuffers(..) | - Msg::ScrollFragmentPoint(..) | - Msg::Status(..) | - Msg::LoadStart(..) | - Msg::LoadComplete(..) | - Msg::DelayedCompositionTimeout(..) | - Msg::Recomposite(..) | - Msg::ChangePageTitle(..) | - Msg::ChangePageUrl(..) | - Msg::KeyEvent(..) | - Msg::TouchEventProcessed(..) | - Msg::SetCursor(..) | - Msg::ViewportConstrained(..) => {} - Msg::CreatePng(..) | - Msg::PaintThreadExited(..) | - Msg::MoveTo(..) | - Msg::ResizeTo(..) | - Msg::IsReadyToSaveImageReply(..) => {} - Msg::NewFavicon(..) => {} - Msg::HeadParsed => {} - Msg::ReturnUnusedNativeSurfaces(..) => {} - Msg::CollectMemoryReports(..) => {} - Msg::PipelineExited(..) => {} - } - true - } - - fn repaint_synchronously(&mut self) {} - - fn pinch_zoom_level(&self) -> f32 { - 1.0 - } - - fn title_for_main_frame(&self) {} -} diff --git a/components/compositing/lib.rs b/components/compositing/lib.rs index c5fc7537e0a..d72c2bace6c 100644 --- a/components/compositing/lib.rs +++ b/components/compositing/lib.rs @@ -68,7 +68,6 @@ mod compositor_layer; pub mod compositor_thread; pub mod constellation; mod delayed_composition; -mod headless; pub mod pipeline; #[cfg(not(target_os = "windows"))] pub mod sandboxing; diff --git a/components/compositing/pipeline.rs b/components/compositing/pipeline.rs index bbf892048c8..40b1a2baa6a 100644 --- a/components/compositing/pipeline.rs +++ b/components/compositing/pipeline.rs @@ -28,13 +28,13 @@ use script_traits::{LayoutControlMsg, LayoutMsg, NewLayoutInfo, ScriptMsg}; use script_traits::{ScriptToCompositorMsg, ScriptThreadFactory, TimerEventRequest}; use std::mem; use std::sync::mpsc::{Receiver, Sender, channel}; -use std::thread; use url::Url; use util; use util::geometry::{PagePx, ViewportPx}; use util::ipc::OptionalIpcSender; use util::opts::{self, Opts}; use util::prefs; +use util::thread; use webrender_traits; /// A uniquely-identifiable pipeline of script thread, layout thread, and paint thread. @@ -290,6 +290,13 @@ impl Pipeline { pub fn exit(&self) { debug!("pipeline {:?} exiting", self.id); + // The compositor wants to know when pipelines shut down too. + // It may still have messages to process from these other threads + // before they can be safely shut down. + let (sender, receiver) = ipc::channel().unwrap(); + self.compositor_proxy.send(CompositorMsg::PipelineExited(self.id, sender)); + receiver.recv().unwrap(); + // Script thread handles shutting down layout, and layout handles shutting down the painter. // For now, if the script thread has failed, we give up on clean shutdown. if self.script_chan @@ -300,9 +307,6 @@ impl Pipeline { let _ = self.paint_shutdown_port.recv(); let _ = self.layout_shutdown_port.recv(); } - - // The compositor wants to know when pipelines shut down too. - self.compositor_proxy.send(CompositorMsg::PipelineExited(self.id)) } pub fn freeze(&self) { @@ -472,7 +476,7 @@ impl PrivilegedPipelineContent { let compositor_proxy_for_script_listener_thread = self.compositor_proxy.clone_compositor_proxy(); let script_to_compositor_port = self.script_to_compositor_port; - thread::spawn(move || { + thread::spawn_named("CompositorScriptListener".to_owned(), move || { compositor_thread::run_script_listener_thread( compositor_proxy_for_script_listener_thread, script_to_compositor_port) diff --git a/components/compositing/windowing.rs b/components/compositing/windowing.rs index 02eda99b521..8719db56a03 100644 --- a/components/compositing/windowing.rs +++ b/components/compositing/windowing.rs @@ -15,7 +15,6 @@ use msg::constellation_msg::{Key, KeyModifiers, KeyState}; use net_traits::net_error_list::NetError; use script_traits::{MouseButton, TouchEventType, TouchId}; use std::fmt::{Debug, Error, Formatter}; -use std::rc::Rc; use style_traits::cursor::Cursor; use url::Url; use util::geometry::ScreenPx; @@ -142,7 +141,7 @@ pub trait WindowMethods { /// /// This is part of the windowing system because its implementation often involves OS-specific /// magic to wake the up window's event loop. - fn create_compositor_channel(_: &Option<Rc<Self>>) + fn create_compositor_channel(&self) -> (Box<CompositorProxy + Send>, Box<CompositorReceiver>); /// Requests that the window system prepare a composite. Typically this will involve making |