aboutsummaryrefslogtreecommitdiffstats
path: root/components/compositing/pipeline.rs
diff options
context:
space:
mode:
Diffstat (limited to 'components/compositing/pipeline.rs')
-rw-r--r--components/compositing/pipeline.rs193
1 files changed, 193 insertions, 0 deletions
diff --git a/components/compositing/pipeline.rs b/components/compositing/pipeline.rs
new file mode 100644
index 00000000000..8ccc0fe48a5
--- /dev/null
+++ b/components/compositing/pipeline.rs
@@ -0,0 +1,193 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+use CompositorChan;
+use layout_traits::{LayoutTaskFactory, LayoutControlChan};
+use script_traits::{ScriptControlChan, ScriptTaskFactory};
+use script_traits::{AttachLayoutMsg, LoadMsg, NewLayoutInfo, ExitPipelineMsg};
+
+use gfx::render_task::{PaintPermissionGranted, PaintPermissionRevoked};
+use gfx::render_task::{RenderChan, RenderTask};
+use servo_msg::constellation_msg::{ConstellationChan, Failure, PipelineId, SubpageId};
+use servo_msg::constellation_msg::WindowSizeData;
+use servo_net::image_cache_task::ImageCacheTask;
+use gfx::font_cache_task::FontCacheTask;
+use servo_net::resource_task::ResourceTask;
+use servo_util::opts::Opts;
+use servo_util::time::TimeProfilerChan;
+use std::rc::Rc;
+use url::Url;
+
+/// A uniquely-identifiable pipeline of script task, layout task, and render task.
+pub struct Pipeline {
+ pub id: PipelineId,
+ pub subpage_id: Option<SubpageId>,
+ pub script_chan: ScriptControlChan,
+ pub layout_chan: LayoutControlChan,
+ pub render_chan: RenderChan,
+ pub layout_shutdown_port: Receiver<()>,
+ pub render_shutdown_port: Receiver<()>,
+ /// The most recently loaded url
+ pub url: Url,
+}
+
+/// The subset of the pipeline that is needed for layer composition.
+#[deriving(Clone)]
+pub struct CompositionPipeline {
+ pub id: PipelineId,
+ pub script_chan: ScriptControlChan,
+ pub render_chan: RenderChan,
+}
+
+impl Pipeline {
+ /// Starts a render task, layout task, and possibly a script task.
+ /// Returns the channels wrapped in a struct.
+ /// If script_pipeline is not None, then subpage_id must also be not None.
+ pub fn create<LTF:LayoutTaskFactory, STF:ScriptTaskFactory>(
+ id: PipelineId,
+ subpage_id: Option<SubpageId>,
+ constellation_chan: ConstellationChan,
+ compositor_chan: CompositorChan,
+ image_cache_task: ImageCacheTask,
+ font_cache_task: FontCacheTask,
+ resource_task: ResourceTask,
+ time_profiler_chan: TimeProfilerChan,
+ window_size: WindowSizeData,
+ opts: Opts,
+ script_pipeline: Option<Rc<Pipeline>>,
+ url: Url)
+ -> Pipeline {
+ let layout_pair = ScriptTaskFactory::create_layout_channel(None::<&mut STF>);
+ let (render_port, render_chan) = RenderChan::new();
+ let (render_shutdown_chan, render_shutdown_port) = channel();
+ let (layout_shutdown_chan, layout_shutdown_port) = channel();
+ let (pipeline_chan, pipeline_port) = channel();
+
+ let failure = Failure {
+ pipeline_id: id,
+ subpage_id: subpage_id,
+ };
+
+ let script_chan = match script_pipeline {
+ None => {
+ let (script_chan, script_port) = channel();
+ ScriptTaskFactory::create(None::<&mut STF>,
+ id,
+ box compositor_chan.clone(),
+ &layout_pair,
+ ScriptControlChan(script_chan.clone()),
+ script_port,
+ constellation_chan.clone(),
+ failure.clone(),
+ resource_task,
+ image_cache_task.clone(),
+ window_size);
+ ScriptControlChan(script_chan)
+ }
+ Some(spipe) => {
+ let new_layout_info = NewLayoutInfo {
+ old_pipeline_id: spipe.id.clone(),
+ new_pipeline_id: id,
+ subpage_id: subpage_id.expect("script_pipeline != None but subpage_id == None"),
+ layout_chan: ScriptTaskFactory::clone_layout_channel(None::<&mut STF>, &layout_pair),
+ };
+
+ let ScriptControlChan(ref chan) = spipe.script_chan;
+ chan.send(AttachLayoutMsg(new_layout_info));
+ spipe.script_chan.clone()
+ }
+ };
+
+ RenderTask::create(id,
+ render_port,
+ compositor_chan.clone(),
+ constellation_chan.clone(),
+ font_cache_task.clone(),
+ failure.clone(),
+ opts.clone(),
+ time_profiler_chan.clone(),
+ render_shutdown_chan);
+
+ LayoutTaskFactory::create(None::<&mut LTF>,
+ id,
+ layout_pair,
+ pipeline_port,
+ constellation_chan,
+ failure,
+ script_chan.clone(),
+ render_chan.clone(),
+ image_cache_task,
+ font_cache_task,
+ opts.clone(),
+ time_profiler_chan,
+ layout_shutdown_chan);
+
+ Pipeline::new(id,
+ subpage_id,
+ script_chan,
+ LayoutControlChan(pipeline_chan),
+ render_chan,
+ layout_shutdown_port,
+ render_shutdown_port,
+ url)
+ }
+
+ pub fn new(id: PipelineId,
+ subpage_id: Option<SubpageId>,
+ script_chan: ScriptControlChan,
+ layout_chan: LayoutControlChan,
+ render_chan: RenderChan,
+ layout_shutdown_port: Receiver<()>,
+ render_shutdown_port: Receiver<()>,
+ url: Url)
+ -> Pipeline {
+ Pipeline {
+ id: id,
+ subpage_id: subpage_id,
+ script_chan: script_chan,
+ layout_chan: layout_chan,
+ render_chan: render_chan,
+ layout_shutdown_port: layout_shutdown_port,
+ render_shutdown_port: render_shutdown_port,
+ url: url,
+ }
+ }
+
+ pub fn load(&self) {
+ let ScriptControlChan(ref chan) = self.script_chan;
+ chan.send(LoadMsg(self.id, self.url.clone()));
+ }
+
+ pub fn grant_paint_permission(&self) {
+ let _ = self.render_chan.send_opt(PaintPermissionGranted);
+ }
+
+ pub fn revoke_paint_permission(&self) {
+ debug!("pipeline revoking render channel paint permission");
+ let _ = self.render_chan.send_opt(PaintPermissionRevoked);
+ }
+
+ pub fn exit(&self) {
+ debug!("pipeline {:?} exiting", self.id);
+
+ // Script task handles shutting down layout, and layout handles shutting down the renderer.
+ // For now, if the script task has failed, we give up on clean shutdown.
+ let ScriptControlChan(ref chan) = self.script_chan;
+ if chan.send_opt(ExitPipelineMsg(self.id)).is_ok() {
+ // Wait until all slave tasks have terminated and run destructors
+ // NOTE: We don't wait for script task as we don't always own it
+ let _ = self.render_shutdown_port.recv_opt();
+ let _ = self.layout_shutdown_port.recv_opt();
+ }
+ }
+
+ pub fn to_sendable(&self) -> CompositionPipeline {
+ CompositionPipeline {
+ id: self.id.clone(),
+ script_chan: self.script_chan.clone(),
+ render_chan: self.render_chan.clone(),
+ }
+ }
+}
+