mirror of
https://github.com/servo/servo.git
synced 2025-08-05 13:40:08 +01:00
Ensure render and layout tasks get destructed before main thread finishes
Fixes #1097.
This commit is contained in:
parent
44404766da
commit
e7a591a7e1
9 changed files with 146 additions and 90 deletions
|
@ -136,47 +136,52 @@ impl<C: RenderListener + Send,T:Send+Freeze> RenderTask<C,T> {
|
||||||
compositor: C,
|
compositor: C,
|
||||||
constellation_chan: ConstellationChan,
|
constellation_chan: ConstellationChan,
|
||||||
opts: Opts,
|
opts: Opts,
|
||||||
profiler_chan: ProfilerChan) {
|
profiler_chan: ProfilerChan,
|
||||||
do spawn_with((port, compositor, constellation_chan, opts, profiler_chan))
|
shutdown_chan: Chan<()>) {
|
||||||
|(port, compositor, constellation_chan, opts, profiler_chan)| {
|
do spawn_with((port, compositor, constellation_chan, opts, profiler_chan, shutdown_chan))
|
||||||
|
|(port, compositor, constellation_chan, opts, profiler_chan, shutdown_chan)| {
|
||||||
|
|
||||||
let native_graphics_context = compositor.get_graphics_metadata().map(
|
{ // Ensures RenderTask and graphics context are destroyed before shutdown msg
|
||||||
|md| NativePaintingGraphicsContext::from_metadata(&md));
|
let native_graphics_context = compositor.get_graphics_metadata().map(
|
||||||
let cpu_painting = opts.cpu_painting;
|
|md| NativePaintingGraphicsContext::from_metadata(&md));
|
||||||
|
let cpu_painting = opts.cpu_painting;
|
||||||
|
|
||||||
// FIXME: rust/#5967
|
// FIXME: rust/#5967
|
||||||
let mut render_task = RenderTask {
|
let mut render_task = RenderTask {
|
||||||
id: id,
|
id: id,
|
||||||
port: port,
|
port: port,
|
||||||
compositor: compositor,
|
compositor: compositor,
|
||||||
constellation_chan: constellation_chan,
|
constellation_chan: constellation_chan,
|
||||||
font_ctx: ~FontContext::new(opts.render_backend.clone(),
|
font_ctx: ~FontContext::new(opts.render_backend.clone(),
|
||||||
false,
|
false,
|
||||||
profiler_chan.clone()),
|
profiler_chan.clone()),
|
||||||
opts: opts,
|
opts: opts,
|
||||||
profiler_chan: profiler_chan,
|
profiler_chan: profiler_chan,
|
||||||
|
|
||||||
graphics_context: if cpu_painting {
|
graphics_context: if cpu_painting {
|
||||||
CpuGraphicsContext
|
CpuGraphicsContext
|
||||||
} else {
|
} else {
|
||||||
GpuGraphicsContext
|
GpuGraphicsContext
|
||||||
},
|
},
|
||||||
|
|
||||||
native_graphics_context: native_graphics_context,
|
native_graphics_context: native_graphics_context,
|
||||||
|
|
||||||
render_layer: None,
|
render_layer: None,
|
||||||
|
|
||||||
paint_permission: false,
|
paint_permission: false,
|
||||||
epoch: Epoch(0),
|
epoch: Epoch(0),
|
||||||
buffer_map: BufferMap::new(10000000),
|
buffer_map: BufferMap::new(10000000),
|
||||||
};
|
};
|
||||||
|
|
||||||
render_task.start();
|
render_task.start();
|
||||||
|
|
||||||
// Destroy all the buffers.
|
// Destroy all the buffers.
|
||||||
render_task.native_graphics_context.as_ref().map(|ctx|
|
render_task.native_graphics_context.as_ref().map(|ctx|
|
||||||
render_task.buffer_map.clear(ctx)
|
render_task.buffer_map.clear(ctx)
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
shutdown_chan.send(());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@ use layers::layers::TextureLayerKind;
|
||||||
use layers::platform::surface::{NativeCompositingGraphicsContext, NativeSurfaceMethods};
|
use layers::platform::surface::{NativeCompositingGraphicsContext, NativeSurfaceMethods};
|
||||||
use layers::texturegl::{Texture, TextureTarget};
|
use layers::texturegl::{Texture, TextureTarget};
|
||||||
#[cfg(target_os="macos")] use layers::texturegl::TextureTargetRectangle;
|
#[cfg(target_os="macos")] use layers::texturegl::TextureTargetRectangle;
|
||||||
use pipeline::Pipeline;
|
use pipeline::CompositionPipeline;
|
||||||
use script::dom::event::{ClickEvent, MouseDownEvent, MouseUpEvent};
|
use script::dom::event::{ClickEvent, MouseDownEvent, MouseUpEvent};
|
||||||
use script::script_task::SendEventMsg;
|
use script::script_task::SendEventMsg;
|
||||||
use servo_msg::compositor_msg::{LayerBuffer, LayerBufferSet, Epoch, Tile};
|
use servo_msg::compositor_msg::{LayerBuffer, LayerBufferSet, Epoch, Tile};
|
||||||
|
@ -34,7 +34,7 @@ use layers::texturegl::TextureTarget2D;
|
||||||
/// Each layer can also have child layers.
|
/// Each layer can also have child layers.
|
||||||
pub struct CompositorLayer {
|
pub struct CompositorLayer {
|
||||||
/// This layer's pipeline. BufferRequests and mouse events will be sent through this.
|
/// This layer's pipeline. BufferRequests and mouse events will be sent through this.
|
||||||
pipeline: Pipeline,
|
pipeline: CompositionPipeline,
|
||||||
|
|
||||||
/// The size of the underlying page in page coordinates. This is an option
|
/// The size of the underlying page in page coordinates. This is an option
|
||||||
/// because we may not know the size of the page until layout is finished completely.
|
/// because we may not know the size of the page until layout is finished completely.
|
||||||
|
@ -104,7 +104,7 @@ enum ScrollBehavior {
|
||||||
impl CompositorLayer {
|
impl CompositorLayer {
|
||||||
/// Creates a new CompositorLayer with an optional page size. If no page size is given,
|
/// Creates a new CompositorLayer with an optional page size. If no page size is given,
|
||||||
/// the layer is initially hidden and initialized without a quadtree.
|
/// the layer is initially hidden and initialized without a quadtree.
|
||||||
pub fn new(pipeline: Pipeline,
|
pub fn new(pipeline: CompositionPipeline,
|
||||||
page_size: Option<Size2D<f32>>,
|
page_size: Option<Size2D<f32>>,
|
||||||
tile_size: uint,
|
tile_size: uint,
|
||||||
max_mem: Option<uint>,
|
max_mem: Option<uint>,
|
||||||
|
@ -669,7 +669,7 @@ impl CompositorLayer {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adds a child.
|
// Adds a child.
|
||||||
pub fn add_child(&mut self, pipeline: Pipeline, page_size: Option<Size2D<f32>>, tile_size: uint,
|
pub fn add_child(&mut self, pipeline: CompositionPipeline, page_size: Option<Size2D<f32>>, tile_size: uint,
|
||||||
max_mem: Option<uint>, clipping_rect: Rect<f32>) {
|
max_mem: Option<uint>, clipping_rect: Rect<f32>) {
|
||||||
let container = @mut ContainerLayer();
|
let container = @mut ContainerLayer();
|
||||||
container.scissor = Some(clipping_rect);
|
container.scissor = Some(clipping_rect);
|
||||||
|
|
|
@ -5,7 +5,8 @@
|
||||||
pub use windowing;
|
pub use windowing;
|
||||||
|
|
||||||
use constellation::SendableFrameTree;
|
use constellation::SendableFrameTree;
|
||||||
use windowing::WindowMethods;
|
use windowing::{ApplicationMethods, WindowMethods};
|
||||||
|
use platform::Application;
|
||||||
|
|
||||||
use azure::azure_hl::{SourceSurfaceMethods, Color};
|
use azure::azure_hl::{SourceSurfaceMethods, Color};
|
||||||
use geom::point::Point2D;
|
use geom::point::Point2D;
|
||||||
|
@ -145,27 +146,38 @@ pub enum Msg {
|
||||||
SetUnRenderedColor(PipelineId, Color),
|
SetUnRenderedColor(PipelineId, Color),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub enum CompositorMode {
|
||||||
|
Windowed(Application),
|
||||||
|
Headless
|
||||||
|
}
|
||||||
|
|
||||||
pub struct CompositorTask {
|
pub struct CompositorTask {
|
||||||
|
mode: CompositorMode,
|
||||||
opts: Opts,
|
opts: Opts,
|
||||||
port: Port<Msg>,
|
port: Port<Msg>,
|
||||||
constellation_chan: ConstellationChan,
|
constellation_chan: ConstellationChan,
|
||||||
profiler_chan: ProfilerChan,
|
profiler_chan: ProfilerChan,
|
||||||
shutdown_chan: SharedChan<()>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CompositorTask {
|
impl CompositorTask {
|
||||||
pub fn new(opts: Opts,
|
pub fn new(opts: Opts,
|
||||||
port: Port<Msg>,
|
port: Port<Msg>,
|
||||||
constellation_chan: ConstellationChan,
|
constellation_chan: ConstellationChan,
|
||||||
profiler_chan: ProfilerChan,
|
profiler_chan: ProfilerChan)
|
||||||
shutdown_chan: Chan<()>)
|
|
||||||
-> CompositorTask {
|
-> CompositorTask {
|
||||||
|
|
||||||
|
let mode: CompositorMode = if opts.headless {
|
||||||
|
Headless
|
||||||
|
} else {
|
||||||
|
Windowed(ApplicationMethods::new())
|
||||||
|
};
|
||||||
|
|
||||||
CompositorTask {
|
CompositorTask {
|
||||||
|
mode: mode,
|
||||||
opts: opts,
|
opts: opts,
|
||||||
port: port,
|
port: port,
|
||||||
constellation_chan: constellation_chan,
|
constellation_chan: constellation_chan,
|
||||||
profiler_chan: profiler_chan,
|
profiler_chan: profiler_chan
|
||||||
shutdown_chan: SharedChan::new(shutdown_chan),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -182,10 +194,9 @@ impl CompositorTask {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run(&self) {
|
pub fn run(&self) {
|
||||||
if self.opts.headless {
|
match self.mode {
|
||||||
run_headless::run_compositor(self);
|
Windowed(ref app) => run::run_compositor(self, app),
|
||||||
} else {
|
Headless => run_headless::run_compositor(self),
|
||||||
run::run_compositor(self);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,8 +4,10 @@
|
||||||
|
|
||||||
use compositing::compositor_layer::CompositorLayer;
|
use compositing::compositor_layer::CompositorLayer;
|
||||||
use compositing::*;
|
use compositing::*;
|
||||||
|
|
||||||
use platform::{Application, Window};
|
use platform::{Application, Window};
|
||||||
use windowing::{ApplicationMethods, WindowEvent, WindowMethods};
|
|
||||||
|
use windowing::{WindowEvent, WindowMethods};
|
||||||
use windowing::{IdleWindowEvent, ResizeWindowEvent, LoadUrlWindowEvent, MouseWindowEventClass};
|
use windowing::{IdleWindowEvent, ResizeWindowEvent, LoadUrlWindowEvent, MouseWindowEventClass};
|
||||||
use windowing::{ScrollWindowEvent, ZoomWindowEvent, NavigationWindowEvent, FinishedWindowEvent};
|
use windowing::{ScrollWindowEvent, ZoomWindowEvent, NavigationWindowEvent, FinishedWindowEvent};
|
||||||
use windowing::{QuitWindowEvent, MouseWindowClickEvent, MouseWindowMouseDownEvent, MouseWindowMouseUpEvent};
|
use windowing::{QuitWindowEvent, MouseWindowClickEvent, MouseWindowMouseDownEvent, MouseWindowMouseUpEvent};
|
||||||
|
@ -34,9 +36,8 @@ use std::rt::io::timer::Timer;
|
||||||
use std::vec;
|
use std::vec;
|
||||||
|
|
||||||
/// Starts the compositor, which listens for messages on the specified port.
|
/// Starts the compositor, which listens for messages on the specified port.
|
||||||
pub fn run_compositor(compositor: &CompositorTask) {
|
pub fn run_compositor(compositor: &CompositorTask, app: &Application) {
|
||||||
let app: Application = ApplicationMethods::new();
|
let window: @mut Window = WindowMethods::new(app);
|
||||||
let window: @mut Window = WindowMethods::new(&app);
|
|
||||||
|
|
||||||
// Create an initial layer tree.
|
// Create an initial layer tree.
|
||||||
//
|
//
|
||||||
|
@ -419,8 +420,6 @@ pub fn run_compositor(compositor: &CompositorTask) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
compositor.shutdown_chan.send(());
|
|
||||||
|
|
||||||
// Clear out the compositor layers so that painting tasks can destroy the buffers.
|
// Clear out the compositor layers so that painting tasks can destroy the buffers.
|
||||||
match compositor_layer {
|
match compositor_layer {
|
||||||
None => {}
|
None => {}
|
||||||
|
|
|
@ -37,5 +37,4 @@ pub fn run_compositor(compositor: &CompositorTask) {
|
||||||
=> ()
|
=> ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
compositor.shutdown_chan.send(())
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ use extra::url::Url;
|
||||||
use geom::rect::Rect;
|
use geom::rect::Rect;
|
||||||
use geom::size::Size2D;
|
use geom::size::Size2D;
|
||||||
use gfx::opts::Opts;
|
use gfx::opts::Opts;
|
||||||
use pipeline::Pipeline;
|
use pipeline::{Pipeline, CompositionPipeline};
|
||||||
use script::script_task::{ResizeMsg, ResizeInactiveMsg};
|
use script::script_task::{ResizeMsg, ResizeInactiveMsg};
|
||||||
use servo_msg::constellation_msg::{ConstellationChan, ExitMsg, FailureMsg, FrameRectMsg};
|
use servo_msg::constellation_msg::{ConstellationChan, ExitMsg, FailureMsg, FrameRectMsg};
|
||||||
use servo_msg::constellation_msg::{IFrameSandboxState, IFrameUnsandboxed, InitLoadUrlMsg};
|
use servo_msg::constellation_msg::{IFrameSandboxState, IFrameUnsandboxed, InitLoadUrlMsg};
|
||||||
|
@ -81,7 +81,7 @@ impl Clone for ChildFrameTree {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct SendableFrameTree {
|
pub struct SendableFrameTree {
|
||||||
pipeline: Pipeline,
|
pipeline: CompositionPipeline,
|
||||||
children: ~[SendableChildFrameTree],
|
children: ~[SendableChildFrameTree],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,7 +129,7 @@ impl FrameTree {
|
||||||
|
|
||||||
fn to_sendable(&self) -> SendableFrameTree {
|
fn to_sendable(&self) -> SendableFrameTree {
|
||||||
let sendable_frame_tree = SendableFrameTree {
|
let sendable_frame_tree = SendableFrameTree {
|
||||||
pipeline: (*self.pipeline).clone(),
|
pipeline: self.pipeline.to_sendable(),
|
||||||
children: self.children.iter().map(|frame_tree| frame_tree.to_sendable()).collect(),
|
children: self.children.iter().map(|frame_tree| frame_tree.to_sendable()).collect(),
|
||||||
};
|
};
|
||||||
sendable_frame_tree
|
sendable_frame_tree
|
||||||
|
|
|
@ -207,18 +207,23 @@ impl LayoutTask {
|
||||||
render_chan: RenderChan<AbstractNode<()>>,
|
render_chan: RenderChan<AbstractNode<()>>,
|
||||||
img_cache_task: ImageCacheTask,
|
img_cache_task: ImageCacheTask,
|
||||||
opts: Opts,
|
opts: Opts,
|
||||||
profiler_chan: ProfilerChan) {
|
profiler_chan: ProfilerChan,
|
||||||
|
shutdown_chan: Chan<()>) {
|
||||||
spawn_with!(task::task(), [port, constellation_chan, script_chan,
|
spawn_with!(task::task(), [port, constellation_chan, script_chan,
|
||||||
render_chan, img_cache_task, profiler_chan], {
|
render_chan, img_cache_task, profiler_chan, shutdown_chan], {
|
||||||
let mut layout = LayoutTask::new(id,
|
{ // Ensures LayoutTask gets destroyed before we send the shutdown message
|
||||||
port,
|
let mut layout = LayoutTask::new(id,
|
||||||
constellation_chan,
|
port,
|
||||||
script_chan,
|
constellation_chan,
|
||||||
render_chan,
|
script_chan,
|
||||||
img_cache_task,
|
render_chan,
|
||||||
&opts,
|
img_cache_task,
|
||||||
profiler_chan);
|
&opts,
|
||||||
layout.start();
|
profiler_chan);
|
||||||
|
layout.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
shutdown_chan.send(());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,19 +19,29 @@ use servo_net::image_cache_task::ImageCacheTask;
|
||||||
use servo_net::resource_task::ResourceTask;
|
use servo_net::resource_task::ResourceTask;
|
||||||
use servo_util::time::ProfilerChan;
|
use servo_util::time::ProfilerChan;
|
||||||
use std::task;
|
use std::task;
|
||||||
|
use std::comm;
|
||||||
|
|
||||||
/// A uniquely-identifiable pipeline of script task, layout task, and render task.
|
/// A uniquely-identifiable pipeline of script task, layout task, and render task.
|
||||||
#[deriving(Clone)]
|
|
||||||
pub struct Pipeline {
|
pub struct Pipeline {
|
||||||
id: PipelineId,
|
id: PipelineId,
|
||||||
subpage_id: Option<SubpageId>,
|
subpage_id: Option<SubpageId>,
|
||||||
script_chan: ScriptChan,
|
script_chan: ScriptChan,
|
||||||
layout_chan: LayoutChan,
|
layout_chan: LayoutChan,
|
||||||
render_chan: RenderChan<AbstractNode<()>>,
|
render_chan: RenderChan<AbstractNode<()>>,
|
||||||
|
layout_shutdown_port: Port<()>,
|
||||||
|
render_shutdown_port: Port<()>,
|
||||||
/// The most recently loaded url
|
/// The most recently loaded url
|
||||||
url: Option<Url>,
|
url: Option<Url>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A subset of the Pipeline nthat is eeded for layer composition
|
||||||
|
#[deriving(Clone)]
|
||||||
|
pub struct CompositionPipeline {
|
||||||
|
id: PipelineId,
|
||||||
|
script_chan: ScriptChan,
|
||||||
|
render_chan: RenderChan<AbstractNode<()>>,
|
||||||
|
}
|
||||||
|
|
||||||
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.
|
||||||
|
@ -46,13 +56,16 @@ impl Pipeline {
|
||||||
-> Pipeline {
|
-> Pipeline {
|
||||||
let (layout_port, layout_chan) = special_stream!(LayoutChan);
|
let (layout_port, layout_chan) = special_stream!(LayoutChan);
|
||||||
let (render_port, render_chan) = special_stream!(RenderChan);
|
let (render_port, render_chan) = special_stream!(RenderChan);
|
||||||
|
let (render_shutdown_port, render_shutdown_chan) = comm::stream();
|
||||||
|
let (layout_shutdown_port, layout_shutdown_chan) = comm::stream();
|
||||||
|
|
||||||
RenderTask::create(id,
|
RenderTask::create(id,
|
||||||
render_port,
|
render_port,
|
||||||
compositor_chan.clone(),
|
compositor_chan.clone(),
|
||||||
constellation_chan.clone(),
|
constellation_chan.clone(),
|
||||||
opts.clone(),
|
opts.clone(),
|
||||||
profiler_chan.clone());
|
profiler_chan.clone(),
|
||||||
|
render_shutdown_chan);
|
||||||
|
|
||||||
LayoutTask::create(id,
|
LayoutTask::create(id,
|
||||||
layout_port,
|
layout_port,
|
||||||
|
@ -61,7 +74,8 @@ impl Pipeline {
|
||||||
render_chan.clone(),
|
render_chan.clone(),
|
||||||
image_cache_task.clone(),
|
image_cache_task.clone(),
|
||||||
opts.clone(),
|
opts.clone(),
|
||||||
profiler_chan);
|
profiler_chan,
|
||||||
|
layout_shutdown_chan);
|
||||||
|
|
||||||
let new_layout_info = NewLayoutInfo {
|
let new_layout_info = NewLayoutInfo {
|
||||||
old_id: script_pipeline.id.clone(),
|
old_id: script_pipeline.id.clone(),
|
||||||
|
@ -75,7 +89,9 @@ impl Pipeline {
|
||||||
subpage_id,
|
subpage_id,
|
||||||
script_pipeline.script_chan.clone(),
|
script_pipeline.script_chan.clone(),
|
||||||
layout_chan,
|
layout_chan,
|
||||||
render_chan)
|
render_chan,
|
||||||
|
layout_shutdown_port,
|
||||||
|
render_shutdown_port)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create(id: PipelineId,
|
pub fn create(id: PipelineId,
|
||||||
|
@ -90,11 +106,15 @@ impl Pipeline {
|
||||||
let (script_port, script_chan) = special_stream!(ScriptChan);
|
let (script_port, script_chan) = special_stream!(ScriptChan);
|
||||||
let (layout_port, layout_chan) = special_stream!(LayoutChan);
|
let (layout_port, layout_chan) = special_stream!(LayoutChan);
|
||||||
let (render_port, render_chan) = special_stream!(RenderChan);
|
let (render_port, render_chan) = special_stream!(RenderChan);
|
||||||
|
let (render_shutdown_port, render_shutdown_chan) = comm::stream();
|
||||||
|
let (layout_shutdown_port, layout_shutdown_chan) = comm::stream();
|
||||||
let pipeline = Pipeline::new(id,
|
let pipeline = Pipeline::new(id,
|
||||||
subpage_id,
|
subpage_id,
|
||||||
script_chan.clone(),
|
script_chan.clone(),
|
||||||
layout_chan.clone(),
|
layout_chan.clone(),
|
||||||
render_chan.clone());
|
render_chan.clone(),
|
||||||
|
layout_shutdown_port,
|
||||||
|
render_shutdown_port);
|
||||||
|
|
||||||
// Wrap task creation within a supervised task so that failure will
|
// Wrap task creation within a supervised task so that failure will
|
||||||
// only tear down those tasks instead of ours.
|
// only tear down those tasks instead of ours.
|
||||||
|
@ -111,7 +131,9 @@ impl Pipeline {
|
||||||
layout_port,
|
layout_port,
|
||||||
constellation_chan,
|
constellation_chan,
|
||||||
image_cache_task,
|
image_cache_task,
|
||||||
profiler_chan
|
profiler_chan,
|
||||||
|
layout_shutdown_chan,
|
||||||
|
render_shutdown_chan
|
||||||
], {
|
], {
|
||||||
ScriptTask::create(id,
|
ScriptTask::create(id,
|
||||||
compositor_chan.clone(),
|
compositor_chan.clone(),
|
||||||
|
@ -127,7 +149,8 @@ impl Pipeline {
|
||||||
compositor_chan.clone(),
|
compositor_chan.clone(),
|
||||||
constellation_chan.clone(),
|
constellation_chan.clone(),
|
||||||
opts.clone(),
|
opts.clone(),
|
||||||
profiler_chan.clone());
|
profiler_chan.clone(),
|
||||||
|
render_shutdown_chan);
|
||||||
|
|
||||||
LayoutTask::create(id,
|
LayoutTask::create(id,
|
||||||
layout_port,
|
layout_port,
|
||||||
|
@ -136,7 +159,8 @@ impl Pipeline {
|
||||||
render_chan.clone(),
|
render_chan.clone(),
|
||||||
image_cache_task,
|
image_cache_task,
|
||||||
opts.clone(),
|
opts.clone(),
|
||||||
profiler_chan);
|
profiler_chan,
|
||||||
|
layout_shutdown_chan);
|
||||||
});
|
});
|
||||||
|
|
||||||
spawn_with!(task::task(), [failure_chan], {
|
spawn_with!(task::task(), [failure_chan], {
|
||||||
|
@ -158,7 +182,9 @@ impl Pipeline {
|
||||||
subpage_id: Option<SubpageId>,
|
subpage_id: Option<SubpageId>,
|
||||||
script_chan: ScriptChan,
|
script_chan: ScriptChan,
|
||||||
layout_chan: LayoutChan,
|
layout_chan: LayoutChan,
|
||||||
render_chan: RenderChan<AbstractNode<()>>)
|
render_chan: RenderChan<AbstractNode<()>>,
|
||||||
|
layout_shutdown_port: Port<()>,
|
||||||
|
render_shutdown_port: Port<()>)
|
||||||
-> Pipeline {
|
-> Pipeline {
|
||||||
Pipeline {
|
Pipeline {
|
||||||
id: id,
|
id: id,
|
||||||
|
@ -166,6 +192,8 @@ impl Pipeline {
|
||||||
script_chan: script_chan,
|
script_chan: script_chan,
|
||||||
layout_chan: layout_chan,
|
layout_chan: layout_chan,
|
||||||
render_chan: render_chan,
|
render_chan: render_chan,
|
||||||
|
layout_shutdown_port: layout_shutdown_port,
|
||||||
|
render_shutdown_port: render_shutdown_port,
|
||||||
url: None,
|
url: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -192,6 +220,19 @@ impl Pipeline {
|
||||||
pub fn exit(&self) {
|
pub fn exit(&self) {
|
||||||
// Script task handles shutting down layout, and layout handles shutting down the renderer.
|
// Script task handles shutting down layout, and layout handles shutting down the renderer.
|
||||||
self.script_chan.try_send(script_task::ExitPipelineMsg(self.id));
|
self.script_chan.try_send(script_task::ExitPipelineMsg(self.id));
|
||||||
|
|
||||||
|
// 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
|
||||||
|
self.render_shutdown_port.try_recv();
|
||||||
|
self.layout_shutdown_port.try_recv();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_sendable(&self) -> CompositionPipeline {
|
||||||
|
CompositionPipeline {
|
||||||
|
id: self.id.clone(),
|
||||||
|
script_chan: self.script_chan.clone(),
|
||||||
|
render_chan: self.render_chan.clone(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -124,7 +124,7 @@ fn start(argc: int, argv: **u8) -> int {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run(opts: Opts) {
|
fn run(opts: Opts) {
|
||||||
let (shutdown_port, shutdown_chan) = comm::stream();
|
let (exit_response_from_constellation, exit_chan) = comm::stream();
|
||||||
let (profiler_port, profiler_chan) = special_stream!(ProfilerChan);
|
let (profiler_port, profiler_chan) = special_stream!(ProfilerChan);
|
||||||
let (compositor_port, compositor_chan) = special_stream!(CompositorChan);
|
let (compositor_port, compositor_chan) = special_stream!(CompositorChan);
|
||||||
let (constellation_port, constellation_chan) = special_stream!(ConstellationChan);
|
let (constellation_port, constellation_chan) = special_stream!(ConstellationChan);
|
||||||
|
@ -158,24 +158,20 @@ fn run(opts: Opts) {
|
||||||
for filename in opts.urls.iter() {
|
for filename in opts.urls.iter() {
|
||||||
constellation_chan.send(InitLoadUrlMsg(make_url(filename.clone(), None)))
|
constellation_chan.send(InitLoadUrlMsg(make_url(filename.clone(), None)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait for the compositor to shut down.
|
|
||||||
shutdown_port.recv();
|
|
||||||
|
|
||||||
// Shut the constellation down.
|
|
||||||
debug!("master: Shut down");
|
|
||||||
let (exit_response_from_constellation, exit_chan) = comm::stream();
|
|
||||||
constellation_chan.send(ExitMsg(exit_chan));
|
|
||||||
exit_response_from_constellation.recv();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let compositor_task = CompositorTask::new(opts,
|
let compositor_task = CompositorTask::new(opts,
|
||||||
compositor_port,
|
compositor_port,
|
||||||
constellation_chan,
|
constellation_chan.clone(),
|
||||||
profiler_chan,
|
profiler_chan);
|
||||||
shutdown_chan);
|
|
||||||
|
|
||||||
debug!("preparing to enter main loop");
|
debug!("preparing to enter main loop");
|
||||||
compositor_task.run();
|
compositor_task.run();
|
||||||
|
|
||||||
|
// Constellation has to be shut down before the compositor goes out of
|
||||||
|
// scope, as the compositor manages setup/teardown of global subsystems
|
||||||
|
debug!("shutting down the constellation");
|
||||||
|
constellation_chan.send(ExitMsg(exit_chan));
|
||||||
|
exit_response_from_constellation.recv();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue