Make compositing generic over layout_task

This will allow breaking the layout -> compositing dependency
This commit is contained in:
Ariel Ben-Yehuda 2014-07-21 16:22:45 +03:00
parent 4b3a78e54b
commit 7ac6924319
4 changed files with 119 additions and 109 deletions

View file

@ -10,6 +10,7 @@ use geom::size::TypedSize2D;
use gfx::render_task; use gfx::render_task;
use libc; use libc;
use pipeline::{Pipeline, CompositionPipeline}; use pipeline::{Pipeline, CompositionPipeline};
use layout::layout_task::LayoutTaskFactory;
use script::script_task::{ResizeMsg, ResizeInactiveMsg, ExitPipelineMsg}; use script::script_task::{ResizeMsg, ResizeInactiveMsg, ExitPipelineMsg};
use script::layout_interface; use script::layout_interface;
use script::layout_interface::LayoutChan; use script::layout_interface::LayoutChan;
@ -31,13 +32,14 @@ use servo_util::time::TimeProfilerChan;
use servo_util::url::parse_url; use servo_util::url::parse_url;
use servo_util::task::spawn_named; use servo_util::task::spawn_named;
use std::cell::RefCell; use std::cell::RefCell;
use std::kinds::marker;
use std::mem::replace; use std::mem::replace;
use std::io; use std::io;
use std::rc::Rc; use std::rc::Rc;
use url::Url; use url::Url;
/// Maintains the pipelines and navigation context and grants permission to composite /// Maintains the pipelines and navigation context and grants permission to composite
pub struct Constellation { pub struct Constellation<LTF> {
pub chan: ConstellationChan, pub chan: ConstellationChan,
pub request_port: Receiver<Msg>, pub request_port: Receiver<Msg>,
pub compositor_chan: CompositorChan, pub compositor_chan: CompositorChan,
@ -49,6 +51,7 @@ pub struct Constellation {
next_pipeline_id: PipelineId, next_pipeline_id: PipelineId,
pending_frames: Vec<FrameChange>, pending_frames: Vec<FrameChange>,
pending_sizes: HashMap<(PipelineId, SubpageId), TypedRect<PagePx, f32>>, pending_sizes: HashMap<(PipelineId, SubpageId), TypedRect<PagePx, f32>>,
layout_task_factory: marker::CovariantType<LTF>,
pub time_profiler_chan: TimeProfilerChan, pub time_profiler_chan: TimeProfilerChan,
pub window_size: WindowSizeData, pub window_size: WindowSizeData,
pub opts: Opts, pub opts: Opts,
@ -240,7 +243,7 @@ impl NavigationContext {
} }
} }
impl Constellation { impl<LTF: LayoutTaskFactory> Constellation<LTF> {
pub fn start(compositor_chan: CompositorChan, pub fn start(compositor_chan: CompositorChan,
opts: &Opts, opts: &Opts,
resource_task: ResourceTask, resource_task: ResourceTask,
@ -252,7 +255,7 @@ impl Constellation {
let constellation_chan_clone = constellation_chan.clone(); let constellation_chan_clone = constellation_chan.clone();
let opts_clone = opts.clone(); let opts_clone = opts.clone();
spawn_named("Constellation", proc() { spawn_named("Constellation", proc() {
let mut constellation = Constellation { let mut constellation : Constellation<LTF> = Constellation {
chan: constellation_chan_clone, chan: constellation_chan_clone,
request_port: constellation_port, request_port: constellation_port,
compositor_chan: compositor_chan, compositor_chan: compositor_chan,
@ -264,6 +267,7 @@ impl Constellation {
next_pipeline_id: PipelineId(0), next_pipeline_id: PipelineId(0),
pending_frames: vec!(), pending_frames: vec!(),
pending_sizes: HashMap::new(), pending_sizes: HashMap::new(),
layout_task_factory: marker::CovariantType,
time_profiler_chan: time_profiler_chan, time_profiler_chan: time_profiler_chan,
window_size: WindowSizeData { window_size: WindowSizeData {
visible_viewport: TypedSize2D(800_f32, 600_f32), visible_viewport: TypedSize2D(800_f32, 600_f32),
@ -286,6 +290,26 @@ impl Constellation {
} }
} }
/// Helper function for creating a pipeline
fn new_pipeline(&self,
id: PipelineId,
subpage_id: Option<SubpageId>,
url: Url)
-> Pipeline {
Pipeline::create::<LTF>(id,
subpage_id,
self.chan.clone(),
self.compositor_chan.clone(),
self.image_cache_task.clone(),
self.font_cache_task.clone(),
self.resource_task.clone(),
self.time_profiler_chan.clone(),
self.window_size,
self.opts.clone(),
url)
}
/// Helper function for getting a unique pipeline Id /// Helper function for getting a unique pipeline Id
fn get_next_pipeline_id(&mut self) -> PipelineId { fn get_next_pipeline_id(&mut self) -> PipelineId {
let id = self.next_pipeline_id; let id = self.next_pipeline_id;
@ -422,17 +446,7 @@ impl Constellation {
debug!("creating replacement pipeline for about:failure"); debug!("creating replacement pipeline for about:failure");
let new_id = self.get_next_pipeline_id(); let new_id = self.get_next_pipeline_id();
let pipeline = Pipeline::create(new_id, let pipeline = self.new_pipeline(new_id, subpage_id, parse_url("about:failure", None));
subpage_id,
self.chan.clone(),
self.compositor_chan.clone(),
self.image_cache_task.clone(),
self.font_cache_task.clone(),
self.resource_task.clone(),
self.time_profiler_chan.clone(),
self.window_size,
self.opts.clone(),
parse_url("about:failure", None));
pipeline.load(); pipeline.load();
let pipeline_wrapped = Rc::new(pipeline); let pipeline_wrapped = Rc::new(pipeline);
@ -450,17 +464,8 @@ impl Constellation {
} }
fn handle_init_load(&mut self, url: Url) { fn handle_init_load(&mut self, url: Url) {
let pipeline = Pipeline::create(self.get_next_pipeline_id(), let next_pipeline_id = self.get_next_pipeline_id();
None, let pipeline = self.new_pipeline(next_pipeline_id, None, url);
self.chan.clone(),
self.compositor_chan.clone(),
self.image_cache_task.clone(),
self.font_cache_task.clone(),
self.resource_task.clone(),
self.time_profiler_chan.clone(),
self.window_size,
self.opts.clone(),
url);
pipeline.load(); pipeline.load();
let pipeline_wrapped = Rc::new(pipeline); let pipeline_wrapped = Rc::new(pipeline);
@ -577,30 +582,20 @@ impl Constellation {
let pipeline = if same_script { let pipeline = if same_script {
debug!("Constellation: loading same-origin iframe at {:?}", url); debug!("Constellation: loading same-origin iframe at {:?}", url);
// Reuse the script task if same-origin url's // Reuse the script task if same-origin url's
Pipeline::with_script(next_pipeline_id, Pipeline::with_script::<LTF>(next_pipeline_id,
subpage_id, subpage_id,
self.chan.clone(), self.chan.clone(),
self.compositor_chan.clone(), self.compositor_chan.clone(),
self.image_cache_task.clone(), self.image_cache_task.clone(),
self.font_cache_task.clone(), self.font_cache_task.clone(),
self.time_profiler_chan.clone(), self.time_profiler_chan.clone(),
self.opts.clone(), self.opts.clone(),
source_pipeline.clone(), source_pipeline.clone(),
url) url)
} else { } else {
debug!("Constellation: loading cross-origin iframe at {:?}", url); debug!("Constellation: loading cross-origin iframe at {:?}", url);
// Create a new script task if not same-origin url's // Create a new script task if not same-origin url's
Pipeline::create(next_pipeline_id, self.new_pipeline(next_pipeline_id, Some(subpage_id), url)
Some(subpage_id),
self.chan.clone(),
self.compositor_chan.clone(),
self.image_cache_task.clone(),
self.font_cache_task.clone(),
self.resource_task.clone(),
self.time_profiler_chan.clone(),
self.window_size,
self.opts.clone(),
url)
}; };
debug!("Constellation: sending load msg to pipeline {:?}", pipeline.id); debug!("Constellation: sending load msg to pipeline {:?}", pipeline.id);
@ -647,18 +642,7 @@ impl Constellation {
let subpage_id = source_frame.pipeline.subpage_id; let subpage_id = source_frame.pipeline.subpage_id;
let next_pipeline_id = self.get_next_pipeline_id(); let next_pipeline_id = self.get_next_pipeline_id();
let pipeline = Pipeline::create(next_pipeline_id, let pipeline = self.new_pipeline(next_pipeline_id, subpage_id, url);
subpage_id,
self.chan.clone(),
self.compositor_chan.clone(),
self.image_cache_task.clone(),
self.font_cache_task.clone(),
self.resource_task.clone(),
self.time_profiler_chan.clone(),
self.window_size,
self.opts.clone(),
url);
pipeline.load(); pipeline.load();
let pipeline_wrapped = Rc::new(pipeline); let pipeline_wrapped = Rc::new(pipeline);

View file

@ -3,7 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use CompositorChan; use CompositorChan;
use layout::layout_task::LayoutTask; use layout::layout_task::LayoutTaskFactory;
use gfx::render_task::{PaintPermissionGranted, PaintPermissionRevoked}; use gfx::render_task::{PaintPermissionGranted, PaintPermissionRevoked};
use gfx::render_task::{RenderChan, RenderTask}; use gfx::render_task::{RenderChan, RenderTask};
@ -45,17 +45,18 @@ pub struct CompositionPipeline {
impl Pipeline { impl Pipeline {
/// Starts a render task, layout task, and script task. Returns the channels wrapped in a /// Starts a render task, layout task, and script task. Returns the channels wrapped in a
/// struct. /// struct.
pub fn with_script(id: PipelineId, pub fn with_script<LTF:LayoutTaskFactory>(
subpage_id: SubpageId, id: PipelineId,
constellation_chan: ConstellationChan, subpage_id: SubpageId,
compositor_chan: CompositorChan, constellation_chan: ConstellationChan,
image_cache_task: ImageCacheTask, compositor_chan: CompositorChan,
font_cache_task: FontCacheTask, image_cache_task: ImageCacheTask,
time_profiler_chan: TimeProfilerChan, font_cache_task: FontCacheTask,
opts: Opts, time_profiler_chan: TimeProfilerChan,
script_pipeline: Rc<Pipeline>, opts: Opts,
url: Url) script_pipeline: Rc<Pipeline>,
-> Pipeline { url: Url)
-> Pipeline {
let (layout_port, layout_chan) = LayoutChan::new(); let (layout_port, layout_chan) = LayoutChan::new();
let (render_port, render_chan) = RenderChan::new(); let (render_port, render_chan) = RenderChan::new();
let (render_shutdown_chan, render_shutdown_port) = channel(); let (render_shutdown_chan, render_shutdown_port) = channel();
@ -76,18 +77,19 @@ impl Pipeline {
time_profiler_chan.clone(), time_profiler_chan.clone(),
render_shutdown_chan); render_shutdown_chan);
LayoutTask::create(id, LayoutTaskFactory::create(None::<&mut LTF>,
layout_port, id,
layout_chan.clone(), layout_port,
constellation_chan, layout_chan.clone(),
failure, constellation_chan,
script_pipeline.script_chan.clone(), failure,
render_chan.clone(), script_pipeline.script_chan.clone(),
image_cache_task.clone(), render_chan.clone(),
font_cache_task.clone(), image_cache_task.clone(),
opts.clone(), font_cache_task.clone(),
time_profiler_chan, opts.clone(),
layout_shutdown_chan); time_profiler_chan,
layout_shutdown_chan);
let new_layout_info = NewLayoutInfo { let new_layout_info = NewLayoutInfo {
old_pipeline_id: script_pipeline.id.clone(), old_pipeline_id: script_pipeline.id.clone(),
@ -109,18 +111,19 @@ impl Pipeline {
url) url)
} }
pub fn create(id: PipelineId, pub fn create<LTF:LayoutTaskFactory>(
subpage_id: Option<SubpageId>, id: PipelineId,
constellation_chan: ConstellationChan, subpage_id: Option<SubpageId>,
compositor_chan: CompositorChan, constellation_chan: ConstellationChan,
image_cache_task: ImageCacheTask, compositor_chan: CompositorChan,
font_cache_task: FontCacheTask, image_cache_task: ImageCacheTask,
resource_task: ResourceTask, font_cache_task: FontCacheTask,
time_profiler_chan: TimeProfilerChan, resource_task: ResourceTask,
window_size: WindowSizeData, time_profiler_chan: TimeProfilerChan,
opts: Opts, window_size: WindowSizeData,
url: Url) opts: Opts,
-> Pipeline { url: Url)
-> Pipeline {
let (script_port, script_chan) = ScriptChan::new(); let (script_port, script_chan) = ScriptChan::new();
let (layout_port, layout_chan) = LayoutChan::new(); let (layout_port, layout_chan) = LayoutChan::new();
let (render_port, render_chan) = RenderChan::new(); let (render_port, render_chan) = RenderChan::new();
@ -161,18 +164,19 @@ impl Pipeline {
time_profiler_chan.clone(), time_profiler_chan.clone(),
render_shutdown_chan); render_shutdown_chan);
LayoutTask::create(id, LayoutTaskFactory::create(None::<&mut LTF>,
layout_port, id,
layout_chan.clone(), layout_port,
constellation_chan, layout_chan.clone(),
failure, constellation_chan,
script_chan.clone(), failure,
render_chan.clone(), script_chan.clone(),
image_cache_task, render_chan.clone(),
font_cache_task, image_cache_task,
opts.clone(), font_cache_task,
time_profiler_chan, opts.clone(),
layout_shutdown_chan); time_profiler_chan,
layout_shutdown_chan);
pipeline pipeline
} }

View file

@ -62,6 +62,23 @@ use style::{AuthorOrigin, Stylesheet, Stylist};
use sync::{Arc, Mutex}; use sync::{Arc, Mutex};
use url::Url; use url::Url;
// A static method creating a layout task
pub trait LayoutTaskFactory {
fn create(_phantom: Option<&mut Self>, // FIXME: use a proper static method
id: PipelineId,
port: Receiver<Msg>,
chan: LayoutChan,
constellation_chan: ConstellationChan,
failure_msg: Failure,
script_chan: ScriptChan,
render_chan: RenderChan,
img_cache_task: ImageCacheTask,
font_cache_task: FontCacheTask,
opts: Opts,
time_profiler_chan: TimeProfilerChan,
shutdown_chan: Sender<()>);
}
/// Information needed by the layout task. /// Information needed by the layout task.
pub struct LayoutTask { pub struct LayoutTask {
/// The ID of the pipeline that we belong to. /// The ID of the pipeline that we belong to.
@ -272,9 +289,10 @@ impl ImageResponder for LayoutImageResponder {
} }
} }
impl LayoutTask { impl LayoutTaskFactory for LayoutTask {
/// Spawns a new layout task. /// Spawns a new layout task.
pub fn create(id: PipelineId, fn create(_phantom: Option<&mut LayoutTask>,
id: PipelineId,
port: Receiver<Msg>, port: Receiver<Msg>,
chan: LayoutChan, chan: LayoutChan,
constellation_chan: ConstellationChan, constellation_chan: ConstellationChan,
@ -306,7 +324,9 @@ impl LayoutTask {
shutdown_chan.send(()); shutdown_chan.send(());
}); });
} }
}
impl LayoutTask {
/// Creates a new `LayoutTask` structure. /// Creates a new `LayoutTask` structure.
fn new(id: PipelineId, fn new(id: PipelineId,
port: Receiver<Msg>, port: Receiver<Msg>,

View file

@ -20,6 +20,7 @@ extern crate servo_msg = "msg";
#[phase(plugin, link)] #[phase(plugin, link)]
extern crate servo_util = "util"; extern crate servo_util = "util";
extern crate script; extern crate script;
extern crate layout;
extern crate green; extern crate green;
extern crate gfx; extern crate gfx;
extern crate libc; extern crate libc;
@ -125,7 +126,8 @@ pub fn run(opts: opts::Opts) {
ImageCacheTask::new(resource_task.clone()) ImageCacheTask::new(resource_task.clone())
}; };
let font_cache_task = FontCacheTask::new(); let font_cache_task = FontCacheTask::new();
let constellation_chan = Constellation::start(compositor_chan, let constellation_chan = Constellation::<layout::layout_task::LayoutTask>::start(
compositor_chan,
opts, opts,
resource_task, resource_task,
image_cache_task, image_cache_task,