зеркало из https://github.com/mozilla/gecko-dev.git
servo: Merge #2880 - Revert "Merge pull request #2819 from bjwbell/iframe-layers" (from zwarich:iframes-revert)
Source-Repo: https://github.com/servo/servo Source-Revision: 514eaf46108db76c423a86d0b5d0ae3df66bba35
This commit is contained in:
Родитель
e8a6e4a1db
Коммит
b0f9b9f4cf
|
@ -20,7 +20,7 @@ use windowing::{WindowEvent, WindowMethods, WindowNavigateMsg, ZoomWindowEvent};
|
|||
use windowing::PinchZoomWindowEvent;
|
||||
|
||||
use azure::azure_hl::SourceSurfaceMethods;
|
||||
use azure::{azure_hl, AzFloat};
|
||||
use azure::azure_hl;
|
||||
use geom::matrix::identity;
|
||||
use geom::point::{Point2D, TypedPoint2D};
|
||||
use geom::rect::Rect;
|
||||
|
@ -34,8 +34,7 @@ use layers::scene::Scene;
|
|||
use layers::layers::Layer;
|
||||
use opengles::gl2;
|
||||
use png;
|
||||
use servo_msg::compositor_msg::{Blank, Epoch, FinishedLoading};
|
||||
use servo_msg::compositor_msg::{IdleRenderState, RenderingRenderState};
|
||||
use servo_msg::compositor_msg::{Blank, Epoch, FinishedLoading, IdleRenderState};
|
||||
use servo_msg::compositor_msg::{LayerId, ReadyState, RenderState};
|
||||
use servo_msg::constellation_msg::{ConstellationChan, ExitMsg, LoadUrlMsg, NavigateMsg};
|
||||
use servo_msg::constellation_msg::{PipelineId, ResizedWindowMsg, WindowSizeData};
|
||||
|
@ -49,7 +48,6 @@ use std::io::timer::sleep;
|
|||
use std::collections::hashmap::HashMap;
|
||||
use std::path::Path;
|
||||
use std::rc::Rc;
|
||||
use std::cmp;
|
||||
use time::precise_time_s;
|
||||
|
||||
|
||||
|
@ -64,7 +62,7 @@ pub struct IOCompositor {
|
|||
context: RenderContext,
|
||||
|
||||
/// The root pipeline.
|
||||
pipeline_tree: Option<CompositionPipelineTree>,
|
||||
root_pipeline: Option<CompositionPipeline>,
|
||||
|
||||
/// The canvas to paint a page.
|
||||
scene: Scene<CompositorData>,
|
||||
|
@ -98,6 +96,9 @@ pub struct IOCompositor {
|
|||
/// The time of the last zoom action has started.
|
||||
zoom_time: f64,
|
||||
|
||||
/// Current display/reflow status of the page
|
||||
ready_state: ReadyState,
|
||||
|
||||
/// Whether the page being rendered has loaded completely.
|
||||
/// Differs from ReadyState because we can finish loading (ready)
|
||||
/// many times for a single page.
|
||||
|
@ -126,29 +127,6 @@ enum ShutdownState {
|
|||
FinishedShuttingDown,
|
||||
}
|
||||
|
||||
#[deriving(Clone)]
|
||||
struct CompositionPipelineTree {
|
||||
pipeline: CompositionPipeline,
|
||||
children: Vec<CompositionPipelineTree>,
|
||||
ready_state: ReadyState,
|
||||
render_state: RenderState,
|
||||
}
|
||||
|
||||
impl CompositionPipelineTree {
|
||||
pub fn new(frame_tree: SendableFrameTree) -> CompositionPipelineTree {
|
||||
let mut tree = CompositionPipelineTree {
|
||||
pipeline: frame_tree.pipeline,
|
||||
children: Vec::new(),
|
||||
ready_state: Blank,
|
||||
render_state: RenderingRenderState,
|
||||
};
|
||||
for child_tree in frame_tree.children.iter() {
|
||||
tree.children.push(CompositionPipelineTree::new(child_tree.frame_tree.clone()));
|
||||
}
|
||||
return tree;
|
||||
}
|
||||
}
|
||||
|
||||
impl IOCompositor {
|
||||
fn new(app: &Application,
|
||||
opts: Opts,
|
||||
|
@ -170,7 +148,7 @@ impl IOCompositor {
|
|||
port: port,
|
||||
opts: opts,
|
||||
context: rendergl::init_render_context(CompositorTask::create_graphics_context()),
|
||||
pipeline_tree: None,
|
||||
root_pipeline: None,
|
||||
scene: Scene::new(window_size.as_f32().to_untyped(), identity()),
|
||||
window_size: window_size,
|
||||
hidpi_factor: hidpi_factor,
|
||||
|
@ -181,6 +159,7 @@ impl IOCompositor {
|
|||
viewport_zoom: ScaleFactor(1.0),
|
||||
zoom_action: false,
|
||||
zoom_time: 0f64,
|
||||
ready_state: Blank,
|
||||
load_complete: false,
|
||||
constellation_chan: constellation_chan,
|
||||
time_profiler_chan: time_profiler_chan,
|
||||
|
@ -288,12 +267,13 @@ impl IOCompositor {
|
|||
break;
|
||||
}
|
||||
|
||||
(Ok(ChangeReadyState(ready_state, pipeline_id)), NotShuttingDown) => {
|
||||
self.change_ready_state(ready_state, pipeline_id);
|
||||
(Ok(ChangeReadyState(ready_state)), NotShuttingDown) => {
|
||||
self.window.set_ready_state(ready_state);
|
||||
self.ready_state = ready_state;
|
||||
}
|
||||
|
||||
(Ok(ChangeRenderState(state, pipeline_id)), NotShuttingDown) => {
|
||||
self.change_render_state(state, pipeline_id);
|
||||
(Ok(ChangeRenderState(render_state)), NotShuttingDown) => {
|
||||
self.change_render_state(render_state);
|
||||
}
|
||||
|
||||
(Ok(SetIds(frame_tree, response_chan, new_constellation_chan)), _) => {
|
||||
|
@ -306,25 +286,12 @@ impl IOCompositor {
|
|||
|
||||
(Ok(CreateOrUpdateRootLayer(layer_properties)),
|
||||
NotShuttingDown) => {
|
||||
let scene_root = self.scene.root.clone();
|
||||
self.create_or_update_root_layer(&scene_root, layer_properties);
|
||||
self.create_or_update_root_layer(layer_properties);
|
||||
}
|
||||
|
||||
(Ok(CreateOrUpdateDescendantLayer(layer_properties)),
|
||||
NotShuttingDown) => {
|
||||
match self.find_parent_pipeline_id(self.get_root_pipeline_tree(),
|
||||
layer_properties.pipeline_id) {
|
||||
Some(parent_pipeline_id) =>
|
||||
self.create_or_update_descendant_layer(layer_properties,
|
||||
parent_pipeline_id),
|
||||
None if self.is_root_pipeline(layer_properties.pipeline_id) =>
|
||||
self.create_or_update_descendant_layer(layer_properties,
|
||||
layer_properties.pipeline_id),
|
||||
None =>
|
||||
fail!("didn't find pipeline for parent layer for pipeline id {:?}",
|
||||
layer_properties.pipeline_id),
|
||||
}
|
||||
|
||||
self.create_or_update_descendant_layer(layer_properties);
|
||||
}
|
||||
|
||||
(Ok(SetLayerClipRect(pipeline_id, layer_id, new_rect)), NotShuttingDown) => {
|
||||
|
@ -352,75 +319,11 @@ impl IOCompositor {
|
|||
}
|
||||
}
|
||||
}
|
||||
fn change_ready_state(&mut self, ready_state: ReadyState, pipeline_id: PipelineId) {
|
||||
let mut use_param_ready_state = false;
|
||||
{
|
||||
let mut_root_pipeline_tree = self.get_mut_root_pipeline_tree();
|
||||
match IOCompositor::find_mut_pipeline(mut_root_pipeline_tree, pipeline_id) {
|
||||
Some(tree) => tree.ready_state = ready_state,
|
||||
None => use_param_ready_state = true,
|
||||
};
|
||||
}
|
||||
if use_param_ready_state {
|
||||
self.window.set_ready_state(ready_state);
|
||||
return;
|
||||
}
|
||||
let tree = match self.pipeline_tree {
|
||||
Some(ref tree) => Some(tree),
|
||||
None => None
|
||||
};
|
||||
self.window.set_ready_state(self.get_ready_state(tree));
|
||||
}
|
||||
|
||||
fn get_ready_state(&self, pipeline_tree: Option<&CompositionPipelineTree>) -> ReadyState {
|
||||
match pipeline_tree {
|
||||
Some(ref tree) => {
|
||||
let mut ready_state = tree.ready_state;
|
||||
for child in tree.children.iter() {
|
||||
ready_state = cmp::min(ready_state,self.get_ready_state(Some(child)));
|
||||
if ready_state == Blank { break; };
|
||||
}
|
||||
ready_state
|
||||
}
|
||||
None => Blank,
|
||||
}
|
||||
}
|
||||
|
||||
fn change_render_state(&mut self, render_state: RenderState, pipeline_id: PipelineId) {
|
||||
debug!("change_render_state: composite_ready {}, {:?}, {}",
|
||||
self.composite_ready, render_state, pipeline_id);
|
||||
let mut use_param_render_state = false;
|
||||
{
|
||||
let mut_root_pipeline_tree = self.get_mut_root_pipeline_tree();
|
||||
match IOCompositor::find_mut_pipeline(mut_root_pipeline_tree, pipeline_id) {
|
||||
Some(tree) => tree.render_state = render_state,
|
||||
None => use_param_render_state = true,
|
||||
};
|
||||
}
|
||||
if use_param_render_state {
|
||||
self.window.set_render_state(render_state);
|
||||
return;
|
||||
}
|
||||
let tree = match self.pipeline_tree {
|
||||
Some(ref tree) => Some(tree),
|
||||
None => None
|
||||
};
|
||||
let new_render_state = self.get_render_state(tree);
|
||||
self.window.set_render_state(new_render_state);
|
||||
self.composite_ready = new_render_state == IdleRenderState;
|
||||
}
|
||||
|
||||
fn get_render_state(&self, pipeline_tree: Option<&CompositionPipelineTree>) -> RenderState {
|
||||
match pipeline_tree {
|
||||
Some(ref tree) => {
|
||||
let mut render_state = tree.render_state;
|
||||
for child in tree.children.iter() {
|
||||
render_state = cmp::min(render_state,self.get_render_state(Some(child)));
|
||||
if render_state == RenderingRenderState { break; };
|
||||
}
|
||||
render_state
|
||||
}
|
||||
None => IdleRenderState,
|
||||
fn change_render_state(&mut self, render_state: RenderState) {
|
||||
self.window.set_render_state(render_state);
|
||||
if render_state == IdleRenderState {
|
||||
self.composite_ready = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -429,34 +332,14 @@ impl IOCompositor {
|
|||
response_chan: Sender<()>,
|
||||
new_constellation_chan: ConstellationChan) {
|
||||
response_chan.send(());
|
||||
let tree = CompositionPipelineTree::new(frame_tree);
|
||||
self.pipeline_tree = Some(tree.clone());
|
||||
self.scene.root = Some(self.create_pipeline_tree_root_layers(&tree.clone()));
|
||||
|
||||
self.root_pipeline = Some(frame_tree.pipeline.clone());
|
||||
|
||||
// Initialize the new constellation channel by sending it the root window size.
|
||||
self.constellation_chan = new_constellation_chan;
|
||||
self.send_window_size();
|
||||
}
|
||||
|
||||
fn create_pipeline_tree_root_layers(&mut self,
|
||||
pipeline_tree: &CompositionPipelineTree)
|
||||
-> Rc<Layer<CompositorData>> {
|
||||
let compositor_data = CompositorData::new_root(pipeline_tree.pipeline.clone(),
|
||||
LayerId::null(),
|
||||
Epoch(0),
|
||||
self.opts.cpu_painting,
|
||||
azure_hl::Color::new(0 as AzFloat,
|
||||
0 as AzFloat,
|
||||
0 as AzFloat,
|
||||
0 as AzFloat));
|
||||
let root_layer = Rc::new(Layer::new(Rect::zero(),
|
||||
self.opts.tile_size,
|
||||
compositor_data));
|
||||
for child_pipeline in pipeline_tree.children.iter() {
|
||||
root_layer.add_child(self.create_pipeline_tree_root_layers(child_pipeline));
|
||||
}
|
||||
return root_layer;
|
||||
}
|
||||
|
||||
fn update_layer_if_exists(&mut self, properties: LayerProperties) -> bool {
|
||||
match self.scene.root {
|
||||
Some(ref root_layer) => {
|
||||
|
@ -474,205 +357,59 @@ impl IOCompositor {
|
|||
}
|
||||
}
|
||||
|
||||
fn create_or_update_root_layer(&mut self,
|
||||
root: &Option<Rc<Layer<CompositorData>>>,
|
||||
layer_properties: LayerProperties) {
|
||||
fn create_or_update_root_layer(&mut self, layer_properties: LayerProperties) {
|
||||
let need_new_root_layer = !self.update_layer_if_exists(layer_properties);
|
||||
if need_new_root_layer {
|
||||
let pipeline = match IOCompositor::find_pipeline(self.get_root_pipeline_tree(),
|
||||
layer_properties.pipeline_id) {
|
||||
Some(pipeline_tree) => pipeline_tree.pipeline.clone(),
|
||||
None =>
|
||||
fail!("Compositor: Making new layer without initialized pipeline {}",
|
||||
layer_properties.pipeline_id),
|
||||
let root_pipeline = match self.root_pipeline {
|
||||
Some(ref root_pipeline) => root_pipeline.clone(),
|
||||
None => fail!("Compositor: Making new layer without initialized pipeline"),
|
||||
};
|
||||
let new_compositor_data =
|
||||
CompositorData::new_root(pipeline.clone(),
|
||||
layer_properties.id,
|
||||
layer_properties.epoch,
|
||||
self.opts.cpu_painting,
|
||||
layer_properties.background_color);
|
||||
let new_compositor_data = CompositorData::new_root(root_pipeline,
|
||||
layer_properties.epoch,
|
||||
self.opts.cpu_painting,
|
||||
layer_properties.background_color);
|
||||
let new_root = Rc::new(Layer::new(layer_properties.rect,
|
||||
self.opts.tile_size,
|
||||
new_compositor_data));
|
||||
|
||||
if self.is_root_pipeline(layer_properties.pipeline_id) {
|
||||
let scene_root = match self.scene.root {
|
||||
// Release all tiles from the layer before dropping it.
|
||||
Some(ref mut layer) if layer.extra_data.borrow().id == LayerId::null() => {
|
||||
CompositorData::clear_all_tiles(layer.clone());
|
||||
layer
|
||||
},
|
||||
// root layer is already initialized
|
||||
Some(_) => fail!("scene.root already initalized"),
|
||||
None => fail!("No scene root layer"),
|
||||
};
|
||||
CompositorData::add_child(new_root.clone(), layer_properties);
|
||||
|
||||
let mut scene_bounds = scene_root.bounds.borrow_mut();
|
||||
if *scene_bounds == Rect::zero() {
|
||||
*scene_bounds = layer_properties.rect;
|
||||
}
|
||||
*scene_root.extra_data.borrow_mut() = new_compositor_data;
|
||||
} else {
|
||||
let root_layer =
|
||||
match self.find_pipeline_root_layer(root, layer_properties.pipeline_id) {
|
||||
// Release all tiles from the layer before dropping it.
|
||||
Some(ref mut layer) => {
|
||||
CompositorData::clear_all_tiles(layer.clone());
|
||||
layer.clone()
|
||||
},
|
||||
None => fail!("No pipeline root layer"),
|
||||
};
|
||||
|
||||
let mut root_bounds = root_layer.bounds.borrow_mut();
|
||||
if *root_bounds == Rect::zero() {
|
||||
*root_bounds = layer_properties.rect;
|
||||
}
|
||||
*root_layer.extra_data.borrow_mut() = new_compositor_data;
|
||||
// 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);
|
||||
}
|
||||
|
||||
self.scroll_layer_to_fragment_point_if_necessary(layer_properties.pipeline_id,
|
||||
layer_properties.id);
|
||||
self.ask_for_tiles();
|
||||
}
|
||||
|
||||
fn is_root_pipeline(&mut self, pipeline_id: PipelineId) -> bool {
|
||||
match self.pipeline_tree {
|
||||
Some(ref root_pipeline) => root_pipeline.pipeline.id == pipeline_id,
|
||||
None => fail!("Compositor: Uninitialized pipeline tree"),
|
||||
}
|
||||
}
|
||||
|
||||
fn get_mut_root_pipeline_tree<'a>(&'a mut self) -> Option<&'a mut CompositionPipelineTree>{
|
||||
match self.pipeline_tree {
|
||||
Some(ref mut tree) => Some(tree),
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn get_root_pipeline_tree<'a>(&'a self) -> Option<&'a CompositionPipelineTree>{
|
||||
match self.pipeline_tree {
|
||||
Some(ref tree) => Some(tree),
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn find_mut_pipeline<'a>(tree: Option<&'a mut CompositionPipelineTree>,
|
||||
pipeline_id: PipelineId)
|
||||
-> Option<&'a mut CompositionPipelineTree> {
|
||||
match tree {
|
||||
Some(pipeline_tree) => {
|
||||
if pipeline_tree.pipeline.id == pipeline_id {
|
||||
Some(pipeline_tree)
|
||||
} else {
|
||||
for child in pipeline_tree.children.mut_iter() {
|
||||
if child.pipeline.id == pipeline_id {
|
||||
return Some(child);
|
||||
}
|
||||
match IOCompositor::find_mut_pipeline(Some(child), pipeline_id) {
|
||||
Some(tree) => return Some(tree),
|
||||
None => { },
|
||||
};
|
||||
}
|
||||
None
|
||||
}},
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn find_pipeline<'a>(tree: Option<&'a CompositionPipelineTree>,
|
||||
pipeline_id: PipelineId)
|
||||
-> Option<&'a CompositionPipelineTree> {
|
||||
match tree {
|
||||
Some(pipeline_tree) => {
|
||||
if pipeline_tree.pipeline.id == pipeline_id {
|
||||
Some(pipeline_tree)
|
||||
} else {
|
||||
for child in pipeline_tree.children.iter() {
|
||||
if child.pipeline.id == pipeline_id {
|
||||
return Some(child);
|
||||
}
|
||||
match IOCompositor::find_pipeline(Some(child), pipeline_id) {
|
||||
Some(tree) => return Some(tree),
|
||||
None => { },
|
||||
};
|
||||
}
|
||||
None
|
||||
}},
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn find_parent_pipeline_id(&self,
|
||||
tree: Option<&CompositionPipelineTree>,
|
||||
child_pipeline_id: PipelineId)
|
||||
-> Option<PipelineId> {
|
||||
match tree {
|
||||
Some(ref pipeline_tree) => {
|
||||
for child_pipeline in pipeline_tree.children.iter() {
|
||||
if child_pipeline.pipeline.id == child_pipeline_id {
|
||||
return Some(pipeline_tree.pipeline.id);
|
||||
}
|
||||
}
|
||||
for child_tree in pipeline_tree.children.iter() {
|
||||
match self.find_parent_pipeline_id(Some(child_tree),
|
||||
child_pipeline_id) {
|
||||
Some(parent_pipeline_id) => return Some(parent_pipeline_id),
|
||||
None => {},
|
||||
}
|
||||
}
|
||||
None
|
||||
},
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn create_or_update_descendant_layer(&mut self,
|
||||
layer_properties: LayerProperties,
|
||||
parent_layer_pipeline_id: PipelineId) {
|
||||
fn create_or_update_descendant_layer(&mut self, layer_properties: LayerProperties) {
|
||||
if !self.update_layer_if_exists(layer_properties) {
|
||||
self.create_descendant_layer(layer_properties, parent_layer_pipeline_id);
|
||||
self.create_descendant_layer(layer_properties);
|
||||
}
|
||||
self.scroll_layer_to_fragment_point_if_necessary(layer_properties.pipeline_id,
|
||||
layer_properties.id);
|
||||
self.ask_for_tiles();
|
||||
}
|
||||
|
||||
fn find_pipeline_root_layer(&self,
|
||||
root: &Option<Rc<Layer<CompositorData>>>,
|
||||
pipeline_id: PipelineId)
|
||||
-> Option<Rc<Layer<CompositorData>>> {
|
||||
let root_layer = match *root {
|
||||
Some(ref layer) => layer.clone(),
|
||||
None => fail!("no layer"),
|
||||
};
|
||||
if root_layer.extra_data.borrow().pipeline.id == pipeline_id {
|
||||
return Some(root_layer);
|
||||
} else {
|
||||
for child in root_layer.children().iter() {
|
||||
match self.find_pipeline_root_layer(&Some(child.clone()), pipeline_id) {
|
||||
Some(l) => return Some(l),
|
||||
None => { },
|
||||
}
|
||||
}
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
||||
fn create_descendant_layer(&mut self,
|
||||
layer_properties: LayerProperties,
|
||||
parent_layer_pipeline_id: PipelineId) {
|
||||
fn create_descendant_layer(&self, layer_properties: LayerProperties) {
|
||||
match self.scene.root {
|
||||
Some(ref root_layer) => {
|
||||
let x = Some(root_layer.clone());
|
||||
let parent_layer = match self.find_pipeline_root_layer(&x,
|
||||
parent_layer_pipeline_id) {
|
||||
Some(l) => l,
|
||||
None => fail!("couldn't find parent layer"),
|
||||
};
|
||||
let pipeline = match IOCompositor::find_pipeline(self.get_root_pipeline_tree(),
|
||||
layer_properties.pipeline_id) {
|
||||
Some(pipeline_tree) => pipeline_tree.pipeline.clone(),
|
||||
None => fail!("Received new layer without initialized pipeline"),
|
||||
};
|
||||
CompositorData::add_child(parent_layer.clone(), layer_properties, pipeline);
|
||||
let parent_layer_id = root_layer.extra_data.borrow().id;
|
||||
match CompositorData::find_layer_with_pipeline_and_layer_id(root_layer.clone(),
|
||||
layer_properties.pipeline_id,
|
||||
parent_layer_id) {
|
||||
Some(ref mut parent_layer) => {
|
||||
CompositorData::add_child(parent_layer.clone(), layer_properties);
|
||||
}
|
||||
None => {
|
||||
fail!("Compositor: couldn't find parent layer");
|
||||
}
|
||||
}
|
||||
}
|
||||
None => fail!("Compositor: Received new layer without initialized pipeline")
|
||||
}
|
||||
|
@ -720,29 +457,17 @@ impl IOCompositor {
|
|||
pipeline_id: PipelineId,
|
||||
layer_id: LayerId,
|
||||
new_rect: Rect<f32>) {
|
||||
let root_layer = match self.scene.root {
|
||||
Some(ref root) => Some(root.clone()),
|
||||
None => None,
|
||||
};
|
||||
let id = match (layer_id == LayerId::null(),
|
||||
self.find_pipeline_root_layer(&root_layer, pipeline_id)) {
|
||||
(false, _) => layer_id,
|
||||
(true, Some(l)) => l.extra_data.borrow().id,
|
||||
(true, None) => fail!("No root layer for {}", pipeline_id)};
|
||||
|
||||
let ask: bool = match self.scene.root {
|
||||
Some(ref layer) =>
|
||||
match CompositorData::find_layer_with_pipeline_and_layer_id(layer.clone(),
|
||||
pipeline_id,
|
||||
id) {
|
||||
Some(child_node) => {
|
||||
*child_node.bounds.borrow_mut() = new_rect;
|
||||
true
|
||||
},
|
||||
None =>
|
||||
fail!("failed to clip rect for (pipeline_id, layer_id): {}, {}",
|
||||
pipeline_id, id)},
|
||||
None => false,
|
||||
Some(ref layer) => {
|
||||
assert!(CompositorData::set_clipping_rect(layer.clone(),
|
||||
pipeline_id,
|
||||
layer_id,
|
||||
new_rect));
|
||||
true
|
||||
}
|
||||
None => {
|
||||
false
|
||||
}
|
||||
};
|
||||
|
||||
if ask {
|
||||
|
@ -1050,11 +775,7 @@ impl IOCompositor {
|
|||
|
||||
// Render to PNG. We must read from the back buffer (ie, before
|
||||
// self.window.present()) as OpenGL ES 2 does not have glReadBuffer().
|
||||
let tree = match self.pipeline_tree {
|
||||
Some(ref tree) => Some(tree),
|
||||
None => None
|
||||
};
|
||||
if self.load_complete && self.get_ready_state(tree) == FinishedLoading
|
||||
if self.load_complete && self.ready_state == FinishedLoading
|
||||
&& self.opts.output_file.is_some() {
|
||||
let (width, height) = (self.window_size.width.get(), self.window_size.height.get());
|
||||
let path = from_str::<Path>(self.opts.output_file.get_ref().as_slice()).unwrap();
|
||||
|
|
|
@ -76,12 +76,11 @@ impl CompositorData {
|
|||
}
|
||||
|
||||
pub fn new_root(pipeline: CompositionPipeline,
|
||||
layer_id: LayerId,
|
||||
epoch: Epoch,
|
||||
cpu_painting: bool,
|
||||
unrendered_color: Color) -> CompositorData {
|
||||
CompositorData::new(pipeline,
|
||||
layer_id,
|
||||
LayerId::null(),
|
||||
epoch,
|
||||
cpu_painting,
|
||||
WantsScrollEvents,
|
||||
|
@ -90,12 +89,11 @@ impl CompositorData {
|
|||
}
|
||||
|
||||
/// Adds a child layer to the layer with the given ID and the given pipeline, if it doesn't
|
||||
/// exist yet. The child layer will have the same tile size, memory limit, and CPU
|
||||
/// exist yet. The child layer will have the same pipeline, tile size, memory limit, and CPU
|
||||
/// painting status as its parent.
|
||||
pub fn add_child(layer: Rc<Layer<CompositorData>>,
|
||||
layer_properties: LayerProperties,
|
||||
pipeline: CompositionPipeline) {
|
||||
let new_compositor_data = CompositorData::new(pipeline,
|
||||
layer_properties: LayerProperties) {
|
||||
let new_compositor_data = CompositorData::new(layer.extra_data.borrow().pipeline.clone(),
|
||||
layer_properties.id,
|
||||
layer_properties.epoch,
|
||||
layer.extra_data.borrow().cpu_painting,
|
||||
|
@ -165,6 +163,34 @@ impl CompositorData {
|
|||
layer.children().iter().map(get_child_buffer_request).any(|b| b) || redisplay
|
||||
}
|
||||
|
||||
// Move the sublayer to an absolute position in page coordinates relative to its parent,
|
||||
// and clip the layer to the specified size in page coordinates.
|
||||
// This method returns false if the specified layer is not found.
|
||||
pub fn set_clipping_rect(layer: Rc<Layer<CompositorData>>,
|
||||
pipeline_id: PipelineId,
|
||||
layer_id: LayerId,
|
||||
new_rect: Rect<f32>)
|
||||
-> bool {
|
||||
debug!("compositor_data: starting set_clipping_rect()");
|
||||
match CompositorData::find_child_with_pipeline_and_layer_id(layer.clone(),
|
||||
pipeline_id,
|
||||
layer_id) {
|
||||
Some(child_node) => {
|
||||
debug!("compositor_data: node found for set_clipping_rect()");
|
||||
*child_node.bounds.borrow_mut() = new_rect;
|
||||
true
|
||||
}
|
||||
None => {
|
||||
layer.children().iter()
|
||||
.any(|kid| CompositorData::set_clipping_rect(kid.clone(),
|
||||
pipeline_id,
|
||||
layer_id,
|
||||
new_rect))
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update_layer(layer: Rc<Layer<CompositorData>>, layer_properties: LayerProperties) {
|
||||
layer.extra_data.borrow_mut().epoch = layer_properties.epoch;
|
||||
layer.extra_data.borrow_mut().unrendered_color = layer_properties.background_color;
|
||||
|
@ -181,6 +207,19 @@ impl CompositorData {
|
|||
size);
|
||||
}
|
||||
|
||||
fn find_child_with_pipeline_and_layer_id(layer: Rc<Layer<CompositorData>>,
|
||||
pipeline_id: PipelineId,
|
||||
layer_id: LayerId)
|
||||
-> Option<Rc<Layer<CompositorData>>> {
|
||||
for kid in layer.children().iter() {
|
||||
if pipeline_id == kid.extra_data.borrow().pipeline.id &&
|
||||
layer_id == kid.extra_data.borrow().id {
|
||||
return Some(kid.clone());
|
||||
}
|
||||
}
|
||||
return None
|
||||
}
|
||||
|
||||
pub fn find_layer_with_pipeline_and_layer_id(layer: Rc<Layer<CompositorData>>,
|
||||
pipeline_id: PipelineId,
|
||||
layer_id: LayerId)
|
||||
|
@ -280,3 +319,4 @@ impl CompositorData {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -38,8 +38,8 @@ pub struct CompositorChan {
|
|||
|
||||
/// Implementation of the abstract `ScriptListener` interface.
|
||||
impl ScriptListener for CompositorChan {
|
||||
fn set_ready_state(&self, pipeline_id: PipelineId, ready_state: ReadyState) {
|
||||
let msg = ChangeReadyState(ready_state, pipeline_id);
|
||||
fn set_ready_state(&self, ready_state: ReadyState) {
|
||||
let msg = ChangeReadyState(ready_state);
|
||||
self.chan.send(msg);
|
||||
}
|
||||
|
||||
|
@ -117,6 +117,8 @@ impl RenderListener for CompositorChan {
|
|||
} else {
|
||||
self.chan.send(CreateOrUpdateDescendantLayer(layer_properties));
|
||||
}
|
||||
|
||||
self.chan.send(SetLayerClipRect(pipeline_id, metadata.id, layer_properties.rect));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -131,10 +133,8 @@ impl RenderListener for CompositorChan {
|
|||
self.chan.send(SetLayerClipRect(pipeline_id, layer_id, new_rect))
|
||||
}
|
||||
|
||||
fn set_render_state(&self,
|
||||
render_state: RenderState,
|
||||
pipeline_id: PipelineId) {
|
||||
self.chan.send(ChangeRenderState(render_state, pipeline_id))
|
||||
fn set_render_state(&self, render_state: RenderState) {
|
||||
self.chan.send(ChangeRenderState(render_state))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -175,16 +175,15 @@ pub enum Msg {
|
|||
/// layer with that ID exists).
|
||||
CreateOrUpdateDescendantLayer(LayerProperties),
|
||||
/// Alerts the compositor that the specified layer's clipping rect has changed.
|
||||
/// If LayerId is LayerId::null() then set the pipeline root layer clipping rect.
|
||||
SetLayerClipRect(PipelineId, LayerId, Rect<f32>),
|
||||
/// Scroll a page in a window
|
||||
ScrollFragmentPoint(PipelineId, LayerId, Point2D<f32>),
|
||||
/// Requests that the compositor paint the given layer buffer set for the given page size.
|
||||
Paint(PipelineId, Epoch, Vec<(LayerId, Box<LayerBufferSet>)>),
|
||||
/// Alerts the compositor to the current status of page loading.
|
||||
ChangeReadyState(ReadyState, PipelineId),
|
||||
ChangeReadyState(ReadyState),
|
||||
/// Alerts the compositor to the current status of rendering.
|
||||
ChangeRenderState(RenderState, PipelineId),
|
||||
ChangeRenderState(RenderState),
|
||||
/// Sets the channel to the current layout and render tasks, along with their id
|
||||
SetIds(SendableFrameTree, Sender<()>, ConstellationChan),
|
||||
/// The load of a page for a given URL has completed.
|
||||
|
|
|
@ -69,13 +69,11 @@ struct ChildFrameTree {
|
|||
pub rect: Option<TypedRect<PagePx, f32>>,
|
||||
}
|
||||
|
||||
#[deriving(Clone)]
|
||||
pub struct SendableFrameTree {
|
||||
pub pipeline: CompositionPipeline,
|
||||
pub children: Vec<SendableChildFrameTree>,
|
||||
}
|
||||
|
||||
#[deriving(Clone)]
|
||||
pub struct SendableChildFrameTree {
|
||||
pub frame_tree: SendableFrameTree,
|
||||
pub rect: Option<TypedRect<PagePx, f32>>,
|
||||
|
|
|
@ -246,7 +246,6 @@ impl<C:RenderListener + Send> RenderTask<C> {
|
|||
}
|
||||
|
||||
let mut replies = Vec::new();
|
||||
self.compositor.set_render_state(RenderingRenderState, self.id);
|
||||
for ReRenderRequest { buffer_requests, scale, layer_id, epoch }
|
||||
in requests.move_iter() {
|
||||
if self.epoch == epoch {
|
||||
|
@ -255,7 +254,6 @@ impl<C:RenderListener + Send> RenderTask<C> {
|
|||
debug!("renderer epoch mismatch: {:?} != {:?}", self.epoch, epoch);
|
||||
}
|
||||
}
|
||||
self.compositor.set_render_state(IdleRenderState, self.id);
|
||||
|
||||
debug!("render_task: returning surfaces");
|
||||
self.compositor.paint(self.id, self.epoch, replies);
|
||||
|
@ -267,11 +265,17 @@ impl<C:RenderListener + Send> RenderTask<C> {
|
|||
}
|
||||
PaintPermissionGranted => {
|
||||
self.paint_permission = true;
|
||||
self.epoch.next();
|
||||
initialize_layers(&mut self.compositor,
|
||||
self.id,
|
||||
self.epoch,
|
||||
self.render_layers.as_slice());
|
||||
|
||||
// Here we assume that the main layer—the layer responsible for the page size—
|
||||
// is the first layer. This is a pretty fragile assumption. It will be fixed
|
||||
// once we use the layers-based scrolling infrastructure for all scrolling.
|
||||
if self.render_layers.len() > 1 {
|
||||
self.epoch.next();
|
||||
initialize_layers(&mut self.compositor,
|
||||
self.id,
|
||||
self.epoch,
|
||||
self.render_layers.as_slice());
|
||||
}
|
||||
}
|
||||
PaintPermissionRevoked => {
|
||||
self.paint_permission = false;
|
||||
|
@ -301,6 +305,8 @@ impl<C:RenderListener + Send> RenderTask<C> {
|
|||
None => return,
|
||||
};
|
||||
|
||||
self.compositor.set_render_state(RenderingRenderState);
|
||||
|
||||
// Divide up the layer into tiles.
|
||||
for tile in tiles.iter() {
|
||||
// Optimize the display list for this tile.
|
||||
|
@ -437,6 +443,8 @@ impl<C:RenderListener + Send> RenderTask<C> {
|
|||
};
|
||||
|
||||
replies.push((render_layer.id, layer_buffer_set));
|
||||
self.compositor.set_render_state(IdleRenderState);
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -14,13 +14,13 @@ use std::fmt;
|
|||
use constellation_msg::PipelineId;
|
||||
|
||||
/// The status of the renderer.
|
||||
#[deriving(Eq, Ord, PartialOrd, PartialEq, Clone)]
|
||||
#[deriving(PartialEq, Clone)]
|
||||
pub enum RenderState {
|
||||
RenderingRenderState,
|
||||
IdleRenderState,
|
||||
RenderingRenderState,
|
||||
}
|
||||
|
||||
#[deriving(Eq, Ord, PartialOrd, PartialEq, Clone)]
|
||||
#[deriving(PartialEq, Clone)]
|
||||
pub enum ReadyState {
|
||||
/// Informs the compositor that nothing has been done yet. Used for setting status
|
||||
Blank,
|
||||
|
@ -33,7 +33,7 @@ pub enum ReadyState {
|
|||
}
|
||||
|
||||
/// A newtype struct for denoting the age of messages; prevents race conditions.
|
||||
#[deriving(PartialEq, PartialOrd)]
|
||||
#[deriving(PartialEq)]
|
||||
pub struct Epoch(pub uint);
|
||||
|
||||
impl Epoch {
|
||||
|
@ -105,13 +105,13 @@ pub trait RenderListener {
|
|||
epoch: Epoch,
|
||||
replies: Vec<(LayerId, Box<LayerBufferSet>)>);
|
||||
|
||||
fn set_render_state(&self, render_state: RenderState, pipeline_id: PipelineId);
|
||||
fn set_render_state(&self, render_state: RenderState);
|
||||
}
|
||||
|
||||
/// The interface used by the script task to tell the compositor to update its ready state,
|
||||
/// which is used in displaying the appropriate message in the window's title.
|
||||
pub trait ScriptListener : Clone {
|
||||
fn set_ready_state(&self, pipeline_id: PipelineId, ReadyState);
|
||||
fn set_ready_state(&self, ReadyState);
|
||||
fn scroll_fragment_point(&self,
|
||||
pipeline_id: PipelineId,
|
||||
layer_id: LayerId,
|
||||
|
|
|
@ -76,7 +76,7 @@ pub enum NavigationDirection {
|
|||
Back,
|
||||
}
|
||||
|
||||
#[deriving(Clone, PartialEq, Eq, Hash, Encodable, Show)]
|
||||
#[deriving(Clone, PartialEq, Eq, Hash, Encodable)]
|
||||
pub struct PipelineId(pub uint);
|
||||
|
||||
#[deriving(Clone, PartialEq, Eq, Hash, Encodable)]
|
||||
|
|
|
@ -319,7 +319,7 @@ impl Page {
|
|||
self.join_layout();
|
||||
|
||||
// Tell the user that we're performing layout.
|
||||
compositor.set_ready_state(self.id, PerformingLayout);
|
||||
compositor.set_ready_state(PerformingLayout);
|
||||
|
||||
// Layout will let us know when it's done.
|
||||
let (join_chan, join_port) = channel();
|
||||
|
|
|
@ -452,7 +452,7 @@ impl ScriptTask {
|
|||
let mut layout_join_port = page.layout_join_port.deref().borrow_mut();
|
||||
*layout_join_port = None;
|
||||
}
|
||||
self.compositor.set_ready_state(pipeline_id, FinishedLoading);
|
||||
self.compositor.set_ready_state(FinishedLoading);
|
||||
}
|
||||
|
||||
/// Handles a navigate forward or backward message.
|
||||
|
@ -549,7 +549,7 @@ impl ScriptTask {
|
|||
let document = Document::new(&*window, Some(url.clone()), HTMLDocument, None).root();
|
||||
window.deref().init_browser_context(&*document);
|
||||
|
||||
self.compositor.set_ready_state(pipeline_id, Loading);
|
||||
self.compositor.set_ready_state(Loading);
|
||||
// Parse HTML.
|
||||
//
|
||||
// Note: We can parse the next document in parallel with any previous documents.
|
||||
|
|
Загрузка…
Ссылка в новой задаче