Skip to content

Commit

Permalink
Create root compositor layers for all frames eagerly
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
bjwbell authored and mrobinson committed Sep 12, 2014
1 parent 0e86679 commit e17cc2d
Showing 1 changed file with 69 additions and 50 deletions.
119 changes: 69 additions & 50 deletions components/compositing/compositor.rs
Expand Up @@ -36,7 +36,7 @@ use layers::scene::Scene;
use opengles::gl2;
use png;
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::{PipelineId, ResizedWindowMsg, WindowSizeData};
use servo_msg::constellation_msg;
Expand Down Expand Up @@ -293,7 +293,9 @@ impl IOCompositor {
}

(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) => {
Expand Down Expand Up @@ -391,19 +393,52 @@ impl IOCompositor {
}
}

fn set_ids(&mut self,
frame_tree: SendableFrameTree,
response_chan: Sender<()>,
new_constellation_chan: ConstellationChan) {
fn set_frame_tree(&mut self,
frame_tree: &SendableFrameTree,
response_chan: Sender<()>,
new_constellation_chan: ConstellationChan) {
response_chan.send(());

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.
self.constellation_chan = new_constellation_chan;
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,
pipeline_id: PipelineId,
layer_id: LayerId)
Expand All @@ -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 {
match self.find_layer_with_pipeline_and_layer_id(properties.pipeline_id, properties.id) {
Some(existing_layer) => {
Expand All @@ -440,35 +482,20 @@ impl IOCompositor {

let need_new_root_layer = !self.update_layer_if_exists(layer_properties);
if need_new_root_layer {
let root_pipeline = match self.root_pipeline {
Some(ref root_pipeline) => root_pipeline.clone(),
None => fail!("Compositor: Making new layer without initialized pipeline"),
};

let root_properties = LayerProperties {
pipeline_id: root_pipeline.id,
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,
DoesntWantScrollEvents,
self.opts.tile_size);
new_root.add_child(first_chid);

// Release all tiles from the layer before dropping it.
match self.scene.root {
Some(ref mut layer) => CompositorData::clear_all_tiles(layer.clone()),
None => { }
}
self.scene.root = Some(new_root);
let root_layer = self.find_pipeline_root_layer(layer_properties.pipeline_id);
CompositorData::update_layer(root_layer.clone(), layer_properties);

let root_layer_pipeline = root_layer.extra_data.borrow().pipeline.clone();
let first_child = CompositorData::new_layer(root_layer_pipeline.clone(),
layer_properties,
DoesntWantScrollEvents,
self.opts.tile_size);

// Add the first child / base layer to the front of the child list, so that
// child iframe layers are rendered on top of the base layer. These iframe
// layers were added previously when creating the layer tree skeleton in
// create_frame_tree_root_layers.
root_layer.children().insert(0, first_child);
}

self.scroll_layer_to_fragment_point_if_necessary(layer_properties.pipeline_id,
Expand All @@ -487,21 +514,13 @@ impl IOCompositor {
}

fn create_descendant_layer(&self, layer_properties: LayerProperties) {
match self.scene.root {
Some(ref root_layer) => {
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,
layer_properties,
DoesntWantScrollEvents,
root_layer.tile_size);
root_layer.add_child(new_layer);
}
None => fail!("Compositor: Received new layer without root layer")
}
let root_layer = self.find_pipeline_root_layer(layer_properties.pipeline_id);
let root_layer_pipeline = root_layer.extra_data.borrow().pipeline.clone();
let new_layer = CompositorData::new_layer(root_layer_pipeline,
layer_properties,
DoesntWantScrollEvents,
root_layer.tile_size);
root_layer.add_child(new_layer);
}

fn send_window_size(&self) {
Expand Down

0 comments on commit e17cc2d

Please sign in to comment.