diff --git a/components/compositing/compositor.rs b/components/compositing/compositor.rs index a2d86d9d5a5..df0d505ad4e 100644 --- a/components/compositing/compositor.rs +++ b/components/compositing/compositor.rs @@ -5,7 +5,7 @@ use compositor_layer::{CompositorData, CompositorLayer, WantsScrollEventsFlag}; use compositor_task::{CompositorEventListener, CompositorProxy, CompositorReceiver}; use compositor_task::{CompositorTask, LayerProperties, Msg}; -use constellation::{FrameId, FrameTreeDiff, SendableFrameTree}; +use constellation::{FrameId, SendableFrameTree}; use pipeline::CompositionPipeline; use scrolling::ScrollingTimerProxy; use windowing; @@ -289,9 +289,15 @@ impl IOCompositor { self.send_viewport_rects_for_all_layers(); } - (Msg::FrameTreeUpdate(frame_tree_diff, response_channel), + (Msg::ChangeLayerPipelineAndRemoveChildren(old_pipeline, new_pipeline, response_channel), ShutdownState::NotShuttingDown) => { - self.update_frame_tree(&frame_tree_diff); + self.handle_change_layer_pipeline_and_remove_children(old_pipeline, new_pipeline); + response_channel.send(()); + } + + (Msg::CreateRootLayerForPipeline(parent_pipeline, pipeline, rect, response_channel), + ShutdownState::NotShuttingDown) => { + self.handle_create_root_layer_for_pipeline(parent_pipeline, pipeline, rect); response_channel.send(()); } @@ -534,8 +540,41 @@ impl IOCompositor { return root_layer; } - fn update_frame_tree(&mut self, frame_tree_diff: &FrameTreeDiff) { - let pipeline_id = frame_tree_diff.parent_pipeline.id; + fn handle_change_layer_pipeline_and_remove_children(&mut self, + old_pipeline: CompositionPipeline, + new_pipeline: CompositionPipeline) { + let root_layer = match self.find_pipeline_root_layer(old_pipeline.id) { + Some(root_layer) => root_layer, + None => { + debug!("Ignoring ChangeLayerPipelineAndRemoveChildren message for pipeline ({}) shutting down.", + old_pipeline.id); + return; + } + }; + + root_layer.clear_all_tiles(self); + root_layer.children().clear(); + + let new_pipeline_id = new_pipeline.id; + self.get_or_create_pipeline_details(new_pipeline_id).pipeline = Some(new_pipeline); + } + + fn handle_create_root_layer_for_pipeline(&mut self, + parent_pipeline: CompositionPipeline, + new_pipeline: CompositionPipeline, + frame_rect: Option>) { + let root_layer = self.create_root_layer_for_pipeline_and_rect(&new_pipeline, frame_rect); + match frame_rect { + Some(ref frame_rect) => { + *root_layer.masks_to_bounds.borrow_mut() = true; + + let frame_rect = frame_rect.to_untyped(); + *root_layer.bounds.borrow_mut() = Rect::from_untyped(&frame_rect); + } + None => {} + } + + let pipeline_id = parent_pipeline.id; let parent_layer = match self.find_pipeline_root_layer(pipeline_id) { Some(root_layer) => root_layer, None => { @@ -544,9 +583,7 @@ impl IOCompositor { return; } }; - parent_layer.add_child( - self.create_root_layer_for_pipeline_and_rect(&frame_tree_diff.pipeline, - frame_tree_diff.rect)); + parent_layer.add_child(root_layer); } fn find_pipeline_root_layer(&self, pipeline_id: PipelineId) -> Option>> { @@ -683,7 +720,7 @@ impl IOCompositor { Some(ref layer) => { layer.bounds.borrow_mut().origin = Point2D::from_untyped(&new_origin) } - None => panic!("Compositor received SetLayerOrigin for nonexistent layer"), + None => panic!("Compositor received SetLayerOrigin for nonexistent layer: {}", pipeline_id), }; self.send_buffer_requests_for_all_layers(); diff --git a/components/compositing/compositor_task.rs b/components/compositing/compositor_task.rs index aa4424e2214..3ff651da281 100644 --- a/components/compositing/compositor_task.rs +++ b/components/compositing/compositor_task.rs @@ -5,7 +5,7 @@ //! Communication with the compositor task. pub use windowing; -pub use constellation::{FrameId, SendableFrameTree, FrameTreeDiff}; +pub use constellation::{FrameId, SendableFrameTree}; use compositor; use headless; @@ -13,15 +13,17 @@ use windowing::{WindowEvent, WindowMethods}; use azure::azure_hl::{SourceSurfaceMethods, Color}; use geom::point::Point2D; -use geom::rect::Rect; +use geom::rect::{Rect, TypedRect}; use geom::size::Size2D; use layers::platform::surface::{NativeCompositingGraphicsContext, NativeGraphicsMetadata}; use layers::layers::LayerBufferSet; +use pipeline::CompositionPipeline; use servo_msg::compositor_msg::{Epoch, LayerId, LayerMetadata, ReadyState}; use servo_msg::compositor_msg::{PaintListener, PaintState, ScriptListener, ScrollPolicy}; use servo_msg::constellation_msg::{ConstellationChan, LoadData, PipelineId}; use servo_msg::constellation_msg::{Key, KeyState, KeyModifiers}; use servo_util::cursor::Cursor; +use servo_util::geometry::PagePx; use servo_util::memory::MemoryProfilerChan; use servo_util::time::TimeProfilerChan; use std::comm::{channel, Sender, Receiver}; @@ -206,8 +208,10 @@ pub enum Msg { PaintMsgDiscarded, /// Replaces the current frame tree, typically called during main frame navigation. SetFrameTree(SendableFrameTree, Sender<()>, ConstellationChan), - /// Sends an updated version of the frame tree. - FrameTreeUpdate(FrameTreeDiff, Sender<()>), + /// Requests the compositor to create a root layer for a new frame. + CreateRootLayerForPipeline(CompositionPipeline, CompositionPipeline, Option>, Sender<()>), + /// Requests the compositor to change a root layer's pipeline and remove all child layers. + ChangeLayerPipelineAndRemoveChildren(CompositionPipeline, CompositionPipeline, Sender<()>), /// The load of a page has completed. LoadComplete, /// Indicates that the scrolling timeout with the given starting timestamp has happened and a @@ -237,8 +241,9 @@ impl Show for Msg { Msg::ChangePageTitle(..) => write!(f, "ChangePageTitle"), Msg::ChangePageLoadData(..) => write!(f, "ChangePageLoadData"), Msg::PaintMsgDiscarded(..) => write!(f, "PaintMsgDiscarded"), - Msg::FrameTreeUpdate(..) => write!(f, "FrameTreeUpdate"), Msg::SetFrameTree(..) => write!(f, "SetFrameTree"), + Msg::CreateRootLayerForPipeline(..) => write!(f, "CreateRootLayerForPipeline"), + Msg::ChangeLayerPipelineAndRemoveChildren(..) => write!(f, "ChangeLayerPipelineAndRemoveChildren"), Msg::LoadComplete => write!(f, "LoadComplete"), Msg::ScrollTimeout(..) => write!(f, "ScrollTimeout"), Msg::KeyEvent(..) => write!(f, "KeyEvent"), diff --git a/components/compositing/constellation.rs b/components/compositing/constellation.rs index 6e2d1380aa9..e1fa00c2e82 100644 --- a/components/compositing/constellation.rs +++ b/components/compositing/constellation.rs @@ -156,16 +156,6 @@ enum ReplaceResult { OriginalNode(Rc), } -/// A struct that triggers the addition of a new frame to a previously existing frame tree. -pub struct FrameTreeDiff { - /// The parent pipeline of the new frame. - pub parent_pipeline: CompositionPipeline, - /// The pipeline of the new frame itself. - pub pipeline: CompositionPipeline, - /// The frame rect of the new frame used for positioning its compositor layer. - pub rect: Option>, -} - impl FrameTree { fn to_sendable(&self) -> SendableFrameTree { SendableFrameTree { @@ -699,7 +689,8 @@ impl Constellation { } } - fn update_child_pipeline(frame_tree: Rc, + fn update_child_pipeline(&mut self, + frame_tree: Rc, new_pipeline: Rc, old_subpage_id: SubpageId) { let existing_tree = match frame_tree.find_with_subpage_id(Some(old_subpage_id)) { @@ -709,7 +700,21 @@ impl Constellation { old_subpage_id), }; - *existing_tree.pipeline.borrow_mut() = new_pipeline; + let old_pipeline = existing_tree.pipeline.borrow().clone(); + *existing_tree.pipeline.borrow_mut() = new_pipeline.clone(); + + // If we have not yet sent this frame to the compositor for layer creation, we don't + // need to inform the compositor of updates to the pipeline. + if !existing_tree.has_compositor_layer.get() { + return; + } + + let (chan, port) = channel(); + self.compositor_proxy.send(CompositorMsg::ChangeLayerPipelineAndRemoveChildren( + old_pipeline.to_sendable(), + new_pipeline.to_sendable(), + chan)); + let _ = port.recv_opt(); } fn create_or_update_child_pipeline(&mut self, @@ -719,12 +724,13 @@ impl Constellation { old_subpage_id: Option) { match old_subpage_id { Some(old_subpage_id) => - Constellation::update_child_pipeline(frame_tree.clone(), new_pipeline, old_subpage_id), + self.update_child_pipeline(frame_tree.clone(), new_pipeline, old_subpage_id), None => { - let new_frame_tree = - Rc::new(FrameTree::new(self.get_next_frame_id(), new_pipeline, - Some(frame_tree.pipeline.borrow().clone()))); - frame_tree.add_child(ChildFrameTree::new(new_frame_tree, new_rect)); + let child_tree = Rc::new( + FrameTree::new(self.get_next_frame_id(), + new_pipeline, + Some(frame_tree.pipeline.borrow().clone()))); + frame_tree.add_child(ChildFrameTree::new(child_tree, new_rect)); } } } @@ -1112,14 +1118,12 @@ impl Constellation { return; } - let sendable_frame_tree_diff = FrameTreeDiff { - parent_pipeline: parent.pipeline.borrow().to_sendable(), - pipeline: child.frame_tree.pipeline.borrow().to_sendable(), - rect: child.rect, - }; - let (chan, port) = channel(); - self.compositor_proxy.send(CompositorMsg::FrameTreeUpdate(sendable_frame_tree_diff, chan)); + self.compositor_proxy.send(CompositorMsg::CreateRootLayerForPipeline( + parent.pipeline.borrow().to_sendable(), + child.frame_tree.pipeline.borrow().to_sendable(), + child.rect, + chan)); match port.recv_opt() { Ok(()) => { child.frame_tree.has_compositor_layer.set(true); diff --git a/components/compositing/headless.rs b/components/compositing/headless.rs index 8b58d727292..86188636260 100644 --- a/components/compositing/headless.rs +++ b/components/compositing/headless.rs @@ -90,7 +90,11 @@ impl CompositorEventListener for NullCompositor { response_chan.send(()); } - Msg::FrameTreeUpdate(_, response_channel) => { + Msg::ChangeLayerPipelineAndRemoveChildren(_, _, response_channel) => { + response_channel.send(()); + } + + Msg::CreateRootLayerForPipeline(_, _, _, response_channel) => { response_channel.send(()); }