Create root compositor layers for all frames eagerly

Instead of waiting to create the root layer, create them as soon as the
Compositor receives the frame tree. This allows the compositor to
create a layer tree skeleton of which to hang the base layers when they
are ready.
This commit is contained in:
Bryan Bell 2014-08-29 16:49:08 -07:00 committed by Martin Robinson
parent 0e86679464
commit e17cc2d5e2

View file

@ -36,7 +36,7 @@ use layers::scene::Scene;
use opengles::gl2; use opengles::gl2;
use png; use png;
use servo_msg::compositor_msg::{Blank, Epoch, FixedPosition, FinishedLoading, IdleRenderState}; use servo_msg::compositor_msg::{Blank, Epoch, FixedPosition, FinishedLoading, IdleRenderState};
use servo_msg::compositor_msg::{LayerId, ReadyState, RenderState}; use servo_msg::compositor_msg::{LayerId, ReadyState, RenderingRenderState, RenderState};
use servo_msg::constellation_msg::{ConstellationChan, ExitMsg, LoadUrlMsg, NavigateMsg}; use servo_msg::constellation_msg::{ConstellationChan, ExitMsg, LoadUrlMsg, NavigateMsg};
use servo_msg::constellation_msg::{PipelineId, ResizedWindowMsg, WindowSizeData}; use servo_msg::constellation_msg::{PipelineId, ResizedWindowMsg, WindowSizeData};
use servo_msg::constellation_msg; use servo_msg::constellation_msg;
@ -293,7 +293,9 @@ impl IOCompositor {
} }
(Ok(SetIds(frame_tree, response_chan, new_constellation_chan)), _) => { (Ok(SetIds(frame_tree, response_chan, new_constellation_chan)), _) => {
self.set_ids(frame_tree, response_chan, new_constellation_chan); self.set_frame_tree(&frame_tree,
response_chan,
new_constellation_chan);
} }
(Ok(GetGraphicsMetadata(chan)), NotShuttingDown) => { (Ok(GetGraphicsMetadata(chan)), NotShuttingDown) => {
@ -391,19 +393,52 @@ impl IOCompositor {
} }
} }
fn set_ids(&mut self, fn set_frame_tree(&mut self,
frame_tree: SendableFrameTree, frame_tree: &SendableFrameTree,
response_chan: Sender<()>, response_chan: Sender<()>,
new_constellation_chan: ConstellationChan) { new_constellation_chan: ConstellationChan) {
response_chan.send(()); response_chan.send(());
self.root_pipeline = Some(frame_tree.pipeline.clone()); self.root_pipeline = Some(frame_tree.pipeline.clone());
// If we have an old root layer, release all old tiles before replacing it.
match self.scene.root {
Some(ref mut layer) => CompositorData::clear_all_tiles(layer.clone()),
None => { }
}
self.scene.root = Some(self.create_frame_tree_root_layers(frame_tree));
// Initialize the new constellation channel by sending it the root window size. // Initialize the new constellation channel by sending it the root window size.
self.constellation_chan = new_constellation_chan; self.constellation_chan = new_constellation_chan;
self.send_window_size(); self.send_window_size();
} }
fn create_frame_tree_root_layers(&mut self,
frame_tree: &SendableFrameTree)
-> Rc<Layer<CompositorData>> {
// Initialize the ReadyState and RenderState for this pipeline.
self.ready_states.insert(frame_tree.pipeline.id, Blank);
self.render_states.insert(frame_tree.pipeline.id, RenderingRenderState);
let layer_properties = LayerProperties {
pipeline_id: frame_tree.pipeline.id,
epoch: Epoch(0),
id: LayerId::null(),
rect: Rect::zero(),
background_color: azure_hl::Color::new(0., 0., 0., 0.),
scroll_policy: FixedPosition,
};
let root_layer = CompositorData::new_layer(frame_tree.pipeline.clone(),
layer_properties,
WantsScrollEvents,
self.opts.tile_size);
for kid in frame_tree.children.iter() {
root_layer.add_child(self.create_frame_tree_root_layers(&kid.frame_tree));
}
return root_layer;
}
fn find_layer_with_pipeline_and_layer_id(&self, fn find_layer_with_pipeline_and_layer_id(&self,
pipeline_id: PipelineId, pipeline_id: PipelineId,
layer_id: LayerId) layer_id: LayerId)
@ -419,6 +454,13 @@ impl IOCompositor {
} }
fn find_pipeline_root_layer(&self, pipeline_id: PipelineId) -> Rc<Layer<CompositorData>> {
match self.find_layer_with_pipeline_and_layer_id(pipeline_id, LayerId::null()) {
Some(ref layer) => layer.clone(),
None => fail!("Tried to create or update layer for unknown pipeline"),
}
}
fn update_layer_if_exists(&mut self, properties: LayerProperties) -> bool { fn update_layer_if_exists(&mut self, properties: LayerProperties) -> bool {
match self.find_layer_with_pipeline_and_layer_id(properties.pipeline_id, properties.id) { match self.find_layer_with_pipeline_and_layer_id(properties.pipeline_id, properties.id) {
Some(existing_layer) => { Some(existing_layer) => {
@ -440,35 +482,20 @@ impl IOCompositor {
let need_new_root_layer = !self.update_layer_if_exists(layer_properties); let need_new_root_layer = !self.update_layer_if_exists(layer_properties);
if need_new_root_layer { if need_new_root_layer {
let root_pipeline = match self.root_pipeline { let root_layer = self.find_pipeline_root_layer(layer_properties.pipeline_id);
Some(ref root_pipeline) => root_pipeline.clone(), CompositorData::update_layer(root_layer.clone(), layer_properties);
None => fail!("Compositor: Making new layer without initialized pipeline"),
};
let root_properties = LayerProperties { let root_layer_pipeline = root_layer.extra_data.borrow().pipeline.clone();
pipeline_id: root_pipeline.id, let first_child = CompositorData::new_layer(root_layer_pipeline.clone(),
epoch: layer_properties.epoch,
id: LayerId::null(),
rect: layer_properties.rect,
background_color: layer_properties.background_color,
scroll_policy: FixedPosition,
};
let new_root = CompositorData::new_layer(root_pipeline.clone(),
root_properties,
WantsScrollEvents,
self.opts.tile_size);
let first_chid = CompositorData::new_layer(root_pipeline.clone(),
layer_properties, layer_properties,
DoesntWantScrollEvents, DoesntWantScrollEvents,
self.opts.tile_size); self.opts.tile_size);
new_root.add_child(first_chid);
// Release all tiles from the layer before dropping it. // Add the first child / base layer to the front of the child list, so that
match self.scene.root { // child iframe layers are rendered on top of the base layer. These iframe
Some(ref mut layer) => CompositorData::clear_all_tiles(layer.clone()), // layers were added previously when creating the layer tree skeleton in
None => { } // create_frame_tree_root_layers.
} root_layer.children().insert(0, first_child);
self.scene.root = Some(new_root);
} }
self.scroll_layer_to_fragment_point_if_necessary(layer_properties.pipeline_id, self.scroll_layer_to_fragment_point_if_necessary(layer_properties.pipeline_id,
@ -487,22 +514,14 @@ impl IOCompositor {
} }
fn create_descendant_layer(&self, layer_properties: LayerProperties) { fn create_descendant_layer(&self, layer_properties: LayerProperties) {
match self.scene.root { let root_layer = self.find_pipeline_root_layer(layer_properties.pipeline_id);
Some(ref root_layer) => {
let root_layer_pipeline = root_layer.extra_data.borrow().pipeline.clone(); let root_layer_pipeline = root_layer.extra_data.borrow().pipeline.clone();
if root_layer_pipeline.id != layer_properties.pipeline_id {
fail!("Compositor: New layer pipeline does not match root layer pipeline");
}
let new_layer = CompositorData::new_layer(root_layer_pipeline, let new_layer = CompositorData::new_layer(root_layer_pipeline,
layer_properties, layer_properties,
DoesntWantScrollEvents, DoesntWantScrollEvents,
root_layer.tile_size); root_layer.tile_size);
root_layer.add_child(new_layer); root_layer.add_child(new_layer);
} }
None => fail!("Compositor: Received new layer without root layer")
}
}
fn send_window_size(&self) { fn send_window_size(&self) {
let dppx = self.page_zoom * self.device_pixels_per_screen_px(); let dppx = self.page_zoom * self.device_pixels_per_screen_px();