diff options
author | Martin Robinson <mrobinson@igalia.com> | 2014-11-14 10:33:50 -0800 |
---|---|---|
committer | Martin Robinson <mrobinson@igalia.com> | 2015-01-09 16:20:04 -0800 |
commit | 19f57008da833e8a8b0bf401c960c271e305970e (patch) | |
tree | 7e61de69c1bde90d2393226765ea94ac9fb4c51f | |
parent | f1d82cf82c9fcbfdf0e40363588fd4ca0f708a3a (diff) | |
download | servo-19f57008da833e8a8b0bf401c960c271e305970e.tar.gz servo-19f57008da833e8a8b0bf401c960c271e305970e.zip |
Notify compositor when a FrameTree changes pipelines
When the constellation change a FrameTree pipeline, it should send a
notification to the compositor, so that it can negotiate buffers from
the correct render task. This commit also migrates away from the
generalized FrameTreeUpdateMsg to ones specific to the situation at
hand. That turned out to be an unnecessary abstraction.
-rw-r--r-- | components/compositing/compositor.rs | 55 | ||||
-rw-r--r-- | components/compositing/compositor_task.rs | 15 | ||||
-rw-r--r-- | components/compositing/constellation.rs | 52 | ||||
-rw-r--r-- | components/compositing/headless.rs | 6 |
4 files changed, 89 insertions, 39 deletions
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<Window: WindowMethods> IOCompositor<Window> { 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<Window: WindowMethods> IOCompositor<Window> { 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<TypedRect<PagePx, f32>>) { + 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<Window: WindowMethods> IOCompositor<Window> { 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<Rc<Layer<CompositorData>>> { @@ -683,7 +720,7 @@ impl<Window: WindowMethods> IOCompositor<Window> { 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<TypedRect<PagePx, f32>>, 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<FrameTree>), } -/// 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<TypedRect<PagePx, f32>>, -} - impl FrameTree { fn to_sendable(&self) -> SendableFrameTree { SendableFrameTree { @@ -699,7 +689,8 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> { } } - fn update_child_pipeline(frame_tree: Rc<FrameTree>, + fn update_child_pipeline(&mut self, + frame_tree: Rc<FrameTree>, new_pipeline: Rc<Pipeline>, old_subpage_id: SubpageId) { let existing_tree = match frame_tree.find_with_subpage_id(Some(old_subpage_id)) { @@ -709,7 +700,21 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> { 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<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> { old_subpage_id: Option<SubpageId>) { 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<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> { 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(()); } |