From e5b1ec4078e1c04fd624709500e9c3a9ae4da988 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Mon, 13 Jul 2015 19:59:13 -0700 Subject: [PATCH] script: Split `Pipeline::create` into chrome process and content process parts. This will make it easier to adapt to IPC. The trickiest part here was to make script tasks spawn new layout tasks directly instead of having the pipeline do it for them. The latter approach will not work in multiprocess mode, because layout and script must run in the same address space and the pipeline cannot inject tasks into another process. --- components/compositing/compositor.rs | 4 +- components/compositing/constellation.rs | 44 ++-- components/compositing/pipeline.rs | 254 +++++++++++++++--------- components/layout/layout_task.rs | 30 ++- components/layout_traits/lib.rs | 16 +- components/script/Cargo.toml | 3 + components/script/layout_interface.rs | 31 ++- components/script/lib.rs | 1 + components/script/script_task.rs | 38 +++- components/script_traits/Cargo.toml | 6 + components/script_traits/lib.rs | 34 +++- components/servo/Cargo.lock | 4 + 12 files changed, 316 insertions(+), 149 deletions(-) diff --git a/components/compositing/compositor.rs b/components/compositing/compositor.rs index b02027e4672..965386c7af9 100644 --- a/components/compositing/compositor.rs +++ b/components/compositing/compositor.rs @@ -28,7 +28,7 @@ use layers::platform::surface::NativeDisplay; use layers::rendergl::RenderContext; use layers::rendergl; use layers::scene::Scene; -use layout_traits::{LayoutControlChan, LayoutControlMsg}; +use layout_traits::LayoutControlChan; use msg::compositor_msg::{Epoch, FrameTreeId, LayerId, LayerKind}; use msg::compositor_msg::{LayerProperties, ScrollPolicy}; use msg::constellation_msg::AnimationState; @@ -39,7 +39,7 @@ use msg::constellation_msg::{PipelineId, WindowSizeData}; use png; use profile_traits::mem; use profile_traits::time::{self, ProfilerCategory, profile}; -use script_traits::{ConstellationControlMsg, ScriptControlChan}; +use script_traits::{ConstellationControlMsg, LayoutControlMsg, ScriptControlChan}; use std::collections::HashMap; use std::collections::hash_map::Entry::{Occupied, Vacant}; use std::mem as std_mem; diff --git a/components/compositing/constellation.rs b/components/compositing/constellation.rs index 6cd40b7863f..b7498ccf843 100644 --- a/components/compositing/constellation.rs +++ b/components/compositing/constellation.rs @@ -20,7 +20,7 @@ use euclid::size::Size2D; use euclid::scale_factor::ScaleFactor; use gfx::font_cache_task::FontCacheTask; use ipc_channel::ipc; -use layout_traits::{LayoutControlChan, LayoutControlMsg, LayoutTaskFactory}; +use layout_traits::{LayoutControlChan, LayoutTaskFactory}; use libc; use msg::compositor_msg::{Epoch, LayerId}; use msg::constellation_msg::AnimationState; @@ -37,7 +37,7 @@ use net_traits::image_cache_task::ImageCacheTask; use net_traits::storage_task::{StorageTask, StorageTaskMsg}; use profile_traits::mem; use profile_traits::time; -use script_traits::{CompositorEvent, ConstellationControlMsg}; +use script_traits::{CompositorEvent, ConstellationControlMsg, LayoutControlMsg}; use script_traits::{ScriptControlChan, ScriptState, ScriptTaskFactory}; use std::borrow::ToOwned; use std::collections::HashMap; @@ -282,21 +282,31 @@ impl Constellation { let PipelineId(ref mut i) = self.next_pipeline_id; *i += 1; - let pipeline = Pipeline::create::(pipeline_id, - parent_info, - self.chan.clone(), - self.compositor_proxy.clone_compositor_proxy(), - self.devtools_chan.clone(), - self.image_cache_task.clone(), - self.font_cache_task.clone(), - self.resource_task.clone(), - self.storage_task.clone(), - self.time_profiler_chan.clone(), - self.mem_profiler_chan.clone(), - initial_window_rect, - script_channel, - load_data, - self.window_size.device_pixel_ratio); + let spawning_paint_only = script_channel.is_some(); + let (pipeline, mut pipeline_content) = + Pipeline::create::(pipeline_id, + parent_info, + self.chan.clone(), + self.compositor_proxy.clone_compositor_proxy(), + self.devtools_chan.clone(), + self.image_cache_task.clone(), + self.font_cache_task.clone(), + self.resource_task.clone(), + self.storage_task.clone(), + self.time_profiler_chan.clone(), + self.mem_profiler_chan.clone(), + initial_window_rect, + script_channel, + load_data, + self.window_size.device_pixel_ratio); + + // TODO(pcwalton): In multiprocess mode, send that `PipelineContent` instance over to + // the content process and call this over there. + if spawning_paint_only { + pipeline_content.start_paint_task(); + } else { + pipeline_content.start_all::(); + } assert!(!self.pipelines.contains_key(&pipeline_id)); self.pipelines.insert(pipeline_id, pipeline); diff --git a/components/compositing/pipeline.rs b/components/compositing/pipeline.rs index ac7e9e560b2..d3c76d8837f 100644 --- a/components/compositing/pipeline.rs +++ b/components/compositing/pipeline.rs @@ -3,8 +3,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use CompositorProxy; -use layout_traits::{LayoutControlMsg, LayoutTaskFactory, LayoutControlChan}; -use script_traits::{ScriptControlChan, ScriptTaskFactory}; +use layout_traits::{LayoutTaskFactory, LayoutControlChan}; +use script_traits::{LayoutControlMsg, ScriptControlChan, ScriptTaskFactory}; use script_traits::{NewLayoutInfo, ConstellationControlMsg}; use compositor_task; @@ -14,17 +14,19 @@ use euclid::scale_factor::ScaleFactor; use gfx::paint_task::Msg as PaintMsg; use gfx::paint_task::{PaintChan, PaintTask}; use gfx::font_cache_task::FontCacheTask; -use ipc_channel::ipc; +use ipc_channel::ipc::{self, IpcReceiver}; use layers::geometry::DevicePixel; use msg::compositor_msg::ScriptListener; use msg::constellation_msg::{ConstellationChan, Failure, FrameId, PipelineId, SubpageId}; use msg::constellation_msg::{LoadData, WindowSizeData, PipelineExitType, MozBrowserEvent}; -use profile_traits::mem; +use profile_traits::mem as profile_mem; use profile_traits::time; use net_traits::ResourceTask; use net_traits::image_cache_task::ImageCacheTask; use net_traits::storage_task::StorageTask; -use std::sync::mpsc::{Receiver, channel}; +use std::any::Any; +use std::mem; +use std::sync::mpsc::{Receiver, Sender, channel}; use std::thread; use url::Url; use util::geometry::{PagePx, ViewportPx}; @@ -74,118 +76,85 @@ impl Pipeline { resource_task: ResourceTask, storage_task: StorageTask, time_profiler_chan: time::ProfilerChan, - mem_profiler_chan: mem::ProfilerChan, + mem_profiler_chan: profile_mem::ProfilerChan, window_rect: Option>, script_chan: Option, load_data: LoadData, device_pixel_ratio: ScaleFactor) - -> Pipeline + -> (Pipeline, PipelineContent) where LTF: LayoutTaskFactory, STF:ScriptTaskFactory { - let layout_pair = ScriptTaskFactory::create_layout_channel(None::<&mut STF>); let (paint_port, paint_chan) = PaintChan::new(); let (paint_shutdown_chan, paint_shutdown_port) = channel(); let (layout_shutdown_chan, layout_shutdown_port) = channel(); let (pipeline_chan, pipeline_port) = ipc::channel().unwrap(); + let mut pipeline_port = Some(pipeline_port); let failure = Failure { pipeline_id: id, parent_info: parent_info, }; - let script_chan = match script_chan { - None => { - let (script_chan, script_port) = channel(); - let (script_to_compositor_chan, script_to_compositor_port) = - ipc::channel().unwrap(); - - let window_size = window_rect.map(|rect| { - WindowSizeData { - visible_viewport: rect.size, - initial_viewport: rect.size * ScaleFactor::new(1.0), - device_pixel_ratio: device_pixel_ratio, - } - }); - - let compositor_proxy_for_script_listener_thread = - compositor_proxy.clone_compositor_proxy(); - thread::spawn(move || { - compositor_task::run_script_listener_thread( - compositor_proxy_for_script_listener_thread, - script_to_compositor_port) - }); - - ScriptTaskFactory::create(None::<&mut STF>, - id, - parent_info, - ScriptListener::new(script_to_compositor_chan), - &layout_pair, - ScriptControlChan(script_chan.clone()), - script_port, - constellation_chan.clone(), - failure.clone(), - resource_task, - storage_task.clone(), - image_cache_task.clone(), - devtools_chan, - window_size, - load_data.clone()); - ScriptControlChan(script_chan) + let window_size = window_rect.map(|rect| { + WindowSizeData { + visible_viewport: rect.size, + initial_viewport: rect.size * ScaleFactor::new(1.0), + device_pixel_ratio: device_pixel_ratio, } - Some(script_chan) => { - let (containing_pipeline_id, subpage_id) = - parent_info.expect("script_pipeline != None but subpage_id == None"); - let new_layout_info = NewLayoutInfo { - containing_pipeline_id: containing_pipeline_id, - new_pipeline_id: id, - subpage_id: subpage_id, - layout_chan: ScriptTaskFactory::clone_layout_channel(None::<&mut STF>, - &layout_pair), - load_data: load_data.clone(), - }; + }); - let ScriptControlChan(ref chan) = script_chan; - chan.send(ConstellationControlMsg::AttachLayout(new_layout_info)).unwrap(); - script_chan.clone() - } + if let Some(ref script_chan) = script_chan { + let (containing_pipeline_id, subpage_id) = + parent_info.expect("script_pipeline != None but subpage_id == None"); + let new_layout_info = NewLayoutInfo { + containing_pipeline_id: containing_pipeline_id, + new_pipeline_id: id, + subpage_id: subpage_id, + load_data: load_data.clone(), + paint_chan: box() (paint_chan.clone()) as Box, + failure: failure, + pipeline_port: mem::replace(&mut pipeline_port, None).unwrap(), + layout_shutdown_chan: layout_shutdown_chan.clone(), + }; + + script_chan.0.send(ConstellationControlMsg::AttachLayout(new_layout_info)).unwrap(); + } + + let (script_chan, script_port) = channel(); + let pipeline = Pipeline::new(id, + parent_info, + ScriptControlChan(script_chan.clone()), + LayoutControlChan(pipeline_chan), + paint_chan.clone(), + layout_shutdown_port, + paint_shutdown_port, + load_data.url.clone(), + window_rect); + + let pipeline_content = PipelineContent { + id: id, + parent_info: parent_info, + constellation_chan: constellation_chan, + compositor_proxy: compositor_proxy, + devtools_chan: devtools_chan, + image_cache_task: image_cache_task, + font_cache_task: font_cache_task, + resource_task: resource_task, + storage_task: storage_task, + time_profiler_chan: time_profiler_chan, + mem_profiler_chan: mem_profiler_chan, + window_size: window_size, + script_chan: script_chan, + load_data: load_data, + failure: failure, + script_port: script_port, + paint_chan: paint_chan, + paint_port: Some(paint_port), + pipeline_port: pipeline_port, + paint_shutdown_chan: paint_shutdown_chan, + layout_shutdown_chan: layout_shutdown_chan, }; - PaintTask::create(id, - load_data.url.clone(), - paint_chan.clone(), - paint_port, - compositor_proxy, - constellation_chan.clone(), - font_cache_task.clone(), - failure.clone(), - time_profiler_chan.clone(), - mem_profiler_chan.clone(), - paint_shutdown_chan); - - LayoutTaskFactory::create(None::<&mut LTF>, - id, - load_data.url.clone(), - parent_info.is_some(), - layout_pair, - pipeline_port, - constellation_chan, - failure, - script_chan.clone(), - paint_chan.clone(), - image_cache_task, - font_cache_task, - time_profiler_chan, - mem_profiler_chan, - layout_shutdown_chan); - - Pipeline::new(id, - parent_info, - script_chan, - LayoutControlChan(pipeline_chan), - paint_chan, - layout_shutdown_port, - paint_shutdown_port, - load_data.url, - window_rect) + (pipeline, pipeline_content) } pub fn new(id: PipelineId, @@ -289,3 +258,92 @@ impl Pipeline { script_channel.send(event).unwrap(); } } + +pub struct PipelineContent { + id: PipelineId, + parent_info: Option<(PipelineId, SubpageId)>, + constellation_chan: ConstellationChan, + compositor_proxy: Box, + devtools_chan: Option, + image_cache_task: ImageCacheTask, + font_cache_task: FontCacheTask, + resource_task: ResourceTask, + storage_task: StorageTask, + time_profiler_chan: time::ProfilerChan, + mem_profiler_chan: profile_mem::ProfilerChan, + window_size: Option, + script_chan: Sender, + load_data: LoadData, + failure: Failure, + script_port: Receiver, + paint_chan: PaintChan, + paint_port: Option>, + paint_shutdown_chan: Sender<()>, + pipeline_port: Option>, + layout_shutdown_chan: Sender<()>, +} + +impl PipelineContent { + pub fn start_all(mut self) where LTF: LayoutTaskFactory, STF: ScriptTaskFactory { + let layout_pair = ScriptTaskFactory::create_layout_channel(None::<&mut STF>); + let (script_to_compositor_chan, script_to_compositor_port) = ipc::channel().unwrap(); + + self.start_paint_task(); + + let compositor_proxy_for_script_listener_thread = + self.compositor_proxy.clone_compositor_proxy(); + thread::spawn(move || { + compositor_task::run_script_listener_thread( + compositor_proxy_for_script_listener_thread, + script_to_compositor_port) + }); + + ScriptTaskFactory::create(None::<&mut STF>, + self.id, + self.parent_info, + ScriptListener::new(script_to_compositor_chan), + &layout_pair, + ScriptControlChan(self.script_chan.clone()), + self.script_port, + self.constellation_chan.clone(), + self.failure.clone(), + self.resource_task, + self.storage_task.clone(), + self.image_cache_task.clone(), + self.devtools_chan, + self.window_size, + self.load_data.clone()); + + LayoutTaskFactory::create(None::<&mut LTF>, + self.id, + self.load_data.url.clone(), + self.parent_info.is_some(), + layout_pair, + self.pipeline_port.unwrap(), + self.constellation_chan, + self.failure, + ScriptControlChan(self.script_chan.clone()), + self.paint_chan.clone(), + self.image_cache_task, + self.font_cache_task, + self.time_profiler_chan, + self.mem_profiler_chan, + self.layout_shutdown_chan); + } + + pub fn start_paint_task(&mut self) { + PaintTask::create(self.id, + self.load_data.url.clone(), + self.paint_chan.clone(), + mem::replace(&mut self.paint_port, None).unwrap(), + self.compositor_proxy.clone_compositor_proxy(), + self.constellation_chan.clone(), + self.font_cache_task.clone(), + self.failure.clone(), + self.time_profiler_chan.clone(), + self.mem_profiler_chan.clone(), + self.paint_shutdown_chan.clone()); + + } +} + diff --git a/components/layout/layout_task.rs b/components/layout/layout_task.rs index 82cfc06974c..e5141726865 100644 --- a/components/layout/layout_task.rs +++ b/components/layout/layout_task.rs @@ -40,7 +40,7 @@ use gfx::font_cache_task::FontCacheTask; use gfx::paint_task::Msg as PaintMsg; use gfx::paint_task::{PaintChan, PaintLayer}; use ipc_channel::ipc::IpcReceiver; -use layout_traits::{LayoutControlMsg, LayoutTaskFactory}; +use layout_traits::LayoutTaskFactory; use log; use msg::compositor_msg::{Epoch, ScrollPolicy, LayerId}; use msg::constellation_msg::Msg as ConstellationMsg; @@ -53,10 +53,10 @@ use net_traits::image_cache_task::{ImageCacheTask, ImageCacheResult, ImageCacheC use script::dom::bindings::js::LayoutJS; use script::dom::node::{LayoutData, Node}; use script::layout_interface::{Animation, ContentBoxResponse, ContentBoxesResponse}; -use script::layout_interface::{HitTestResponse, LayoutChan, LayoutRPC}; -use script::layout_interface::{MouseOverResponse, Msg, Reflow, ReflowGoal, ReflowQueryType}; +use script::layout_interface::{HitTestResponse, LayoutChan, LayoutRPC, MouseOverResponse}; +use script::layout_interface::{NewLayoutTaskInfo, Msg, Reflow, ReflowGoal, ReflowQueryType}; use script::layout_interface::{ScriptLayoutChan, ScriptReflow, TrustedNodeAddress}; -use script_traits::{ConstellationControlMsg, OpaqueScriptLayoutChannel}; +use script_traits::{ConstellationControlMsg, LayoutControlMsg, OpaqueScriptLayoutChannel}; use script_traits::{ScriptControlChan, StylesheetLoadResponder}; use std::borrow::ToOwned; use std::cell::Cell; @@ -559,6 +559,9 @@ impl LayoutTask { let rw_data = self.lock_rw_data(possibly_locked_rw_data); sender.send(rw_data.epoch).unwrap(); }, + Msg::CreateLayoutTask(info) => { + self.create_layout_task(info) + } Msg::PrepareToExit(response_chan) => { self.prepare_to_exit(response_chan, possibly_locked_rw_data); return false @@ -607,6 +610,24 @@ impl LayoutTask { reports_chan.send(reports); } + fn create_layout_task(&self, info: NewLayoutTaskInfo) { + LayoutTaskFactory::create(None::<&mut LayoutTask>, + info.id, + info.url.clone(), + info.is_parent, + info.layout_pair, + info.pipeline_port, + info.constellation_chan, + info.failure, + ScriptControlChan(info.script_chan.clone()), + *info.paint_chan.downcast::().unwrap(), + self.image_cache_task.clone(), + self.font_cache_task.clone(), + self.time_profiler_chan.clone(), + self.mem_profiler_chan.clone(), + info.layout_shutdown_chan); + } + /// Enters a quiescent state in which no new messages except for /// `layout_interface::Msg::ReapLayoutData` will be processed until an `ExitNow` is /// received. A pong is immediately sent on the given response channel. @@ -1399,3 +1420,4 @@ fn get_root_flow_background_color(flow: &mut Flow) -> AzColor { .resolve_color(kid_block_flow.fragment.style.get_background().background_color) .to_gfx_color() } + diff --git a/components/layout_traits/lib.rs b/components/layout_traits/lib.rs index 64237be3bad..361ba3c2654 100644 --- a/components/layout_traits/lib.rs +++ b/components/layout_traits/lib.rs @@ -21,29 +21,17 @@ extern crate util; // The traits are here instead of in layout so // that these modules won't have to depend on layout. -use euclid::rect::Rect; use gfx::font_cache_task::FontCacheTask; use gfx::paint_task::PaintChan; use ipc_channel::ipc::{IpcReceiver, IpcSender}; -use msg::compositor_msg::{Epoch, LayerId}; -use msg::constellation_msg::{ConstellationChan, Failure, PipelineId, PipelineExitType}; +use msg::constellation_msg::{ConstellationChan, Failure, PipelineId}; use profile_traits::mem; use profile_traits::time; use net_traits::image_cache_task::ImageCacheTask; -use script_traits::{ScriptControlChan, OpaqueScriptLayoutChannel}; +use script_traits::{LayoutControlMsg, ScriptControlChan, OpaqueScriptLayoutChannel}; use std::sync::mpsc::Sender; -use util::geometry::Au; use url::Url; -/// Messages sent to the layout task from the constellation and/or compositor. -#[derive(Deserialize, Serialize)] -pub enum LayoutControlMsg { - ExitNow(PipelineExitType), - GetCurrentEpoch(IpcSender), - TickAnimations, - SetVisibleRects(Vec<(LayerId, Rect)>), -} - /// A channel wrapper for constellation messages #[derive(Clone, Deserialize, Serialize)] pub struct LayoutControlChan(pub IpcSender); diff --git a/components/script/Cargo.toml b/components/script/Cargo.toml index 6aefc2903d7..4c372699894 100644 --- a/components/script/Cargo.toml +++ b/components/script/Cargo.toml @@ -30,6 +30,9 @@ path = "../profile_traits" [dependencies.script_traits] path = "../script_traits" +[dependencies.layout_traits] +path = "../layout_traits" + [dependencies.devtools_traits] path = "../devtools_traits" diff --git a/components/script/layout_interface.rs b/components/script/layout_interface.rs index 7db08689279..3c26f062214 100644 --- a/components/script/layout_interface.rs +++ b/components/script/layout_interface.rs @@ -10,15 +10,17 @@ use dom::node::LayoutData; use euclid::point::Point2D; use euclid::rect::Rect; -use ipc_channel::ipc::IpcSender; +use ipc_channel::ipc::{IpcReceiver, IpcSender}; use libc::uintptr_t; use msg::compositor_msg::LayerId; -use msg::constellation_msg::{PipelineExitType, WindowSizeData}; +use msg::constellation_msg::{ConstellationChan, Failure, PipelineExitType, PipelineId}; +use msg::constellation_msg::{WindowSizeData}; use msg::compositor_msg::Epoch; +use net_traits::image_cache_task::ImageCacheTask; use net_traits::PendingAsyncLoad; use profile_traits::mem::{Reporter, ReportsChan}; -use script_traits::{ScriptControlChan, OpaqueScriptLayoutChannel, UntrustedNodeAddress}; -use script_traits::StylesheetLoadResponder; +use script_traits::{ConstellationControlMsg, LayoutControlMsg, ScriptControlChan}; +use script_traits::{OpaqueScriptLayoutChannel, StylesheetLoadResponder, UntrustedNodeAddress}; use std::any::Any; use std::sync::mpsc::{channel, Receiver, Sender}; use style::animation::PropertyAnimation; @@ -72,7 +74,12 @@ pub enum Msg { ExitNow(PipelineExitType), /// Get the last epoch counter for this layout task. - GetCurrentEpoch(IpcSender) + GetCurrentEpoch(IpcSender), + + /// Creates a new layout task. + /// + /// This basically exists to keep the script-layout dependency one-way. + CreateLayoutTask(NewLayoutTaskInfo), } /// Synchronous messages that script can send to layout. @@ -209,3 +216,17 @@ impl Animation { } } +pub struct NewLayoutTaskInfo { + pub id: PipelineId, + pub url: Url, + pub is_parent: bool, + pub layout_pair: OpaqueScriptLayoutChannel, + pub pipeline_port: IpcReceiver, + pub constellation_chan: ConstellationChan, + pub failure: Failure, + pub script_chan: Sender, + pub image_cache_task: ImageCacheTask, + pub paint_chan: Box, + pub layout_shutdown_chan: Sender<()>, +} + diff --git a/components/script/lib.rs b/components/script/lib.rs index 66d184846f3..7c31e5503e9 100644 --- a/components/script/lib.rs +++ b/components/script/lib.rs @@ -46,6 +46,7 @@ extern crate fnv; extern crate hyper; extern crate ipc_channel; extern crate js; +extern crate layout_traits; extern crate libc; extern crate msg; extern crate net_traits; diff --git a/components/script/script_task.rs b/components/script/script_task.rs index 693e89058ef..d079d9f3e75 100644 --- a/components/script/script_task.rs +++ b/components/script/script_task.rs @@ -42,8 +42,8 @@ use dom::servohtmlparser::{ServoHTMLParser, ParserContext}; use dom::window::{Window, WindowHelpers, ScriptHelpers, ReflowReason}; use dom::worker::TrustedWorkerAddress; use parse::html::{ParseContext, parse_html}; -use layout_interface::{ScriptLayoutChan, LayoutChan, ReflowGoal, ReflowQueryType}; -use layout_interface; +use layout_interface::{self, NewLayoutTaskInfo, ScriptLayoutChan, LayoutChan, ReflowGoal}; +use layout_interface::{ReflowQueryType}; use network_listener::NetworkListener; use page::{Page, IterablePage, Frame}; use timers::TimerId; @@ -925,18 +925,44 @@ impl ScriptTask { containing_pipeline_id, new_pipeline_id, subpage_id, - layout_chan, load_data, + paint_chan, + failure, + pipeline_port, + layout_shutdown_chan, } = new_layout_info; + let layout_pair = ScriptTask::create_layout_channel(None::<&mut ScriptTask>); + let layout_chan = LayoutChan(*ScriptTask::clone_layout_channel( + None::<&mut ScriptTask>, + &layout_pair).downcast::>().unwrap()); + + let layout_creation_info = NewLayoutTaskInfo { + id: new_pipeline_id, + url: load_data.url.clone(), + is_parent: false, + layout_pair: layout_pair, + pipeline_port: pipeline_port, + constellation_chan: self.constellation_chan.clone(), + failure: failure, + paint_chan: paint_chan, + script_chan: self.control_chan.0.clone(), + image_cache_task: self.image_cache_task.clone(), + layout_shutdown_chan: layout_shutdown_chan, + }; + let page = self.root_page(); let parent_page = page.find(containing_pipeline_id).expect("ScriptTask: received a layout whose parent has a PipelineId which does not correspond to a pipeline in the script task's page tree. This is a bug."); - let parent_window = parent_page.window(); - let chan = layout_chan.downcast_ref::>().unwrap(); - let layout_chan = LayoutChan(chan.clone()); + + // Tell layout to actually spawn the task. + parent_window.layout_chan() + .0 + .send(layout_interface::Msg::CreateLayoutTask(layout_creation_info)) + .unwrap(); + // Kick off the fetch for the new resource. let new_load = InProgressLoad::new(new_pipeline_id, Some((containing_pipeline_id, subpage_id)), layout_chan, parent_window.r().window_size(), diff --git a/components/script_traits/Cargo.toml b/components/script_traits/Cargo.toml index 72b968cf20f..64ccafed1fa 100644 --- a/components/script_traits/Cargo.toml +++ b/components/script_traits/Cargo.toml @@ -19,7 +19,13 @@ path = "../util" [dependencies.devtools_traits] path = "../devtools_traits" +[dependencies.ipc-channel] +git = "https://github.com/pcwalton/ipc-channel" + [dependencies] url = "0.2.35" libc = "*" euclid = "0.1" +serde = "*" +serde_macros = "*" + diff --git a/components/script_traits/lib.rs b/components/script_traits/lib.rs index 3d7375b6409..f60d3ccaf6d 100644 --- a/components/script_traits/lib.rs +++ b/components/script_traits/lib.rs @@ -6,18 +6,24 @@ //! The traits are here instead of in script so that these modules won't have //! to depend on script. +#![feature(custom_derive, plugin)] +#![plugin(serde_macros)] #![deny(missing_docs)] extern crate devtools_traits; extern crate euclid; +extern crate ipc_channel; extern crate libc; extern crate msg; extern crate net_traits; +extern crate serde; extern crate util; extern crate url; use devtools_traits::DevtoolsControlChan; +use ipc_channel::ipc::{IpcReceiver, IpcSender}; use libc::c_void; +use msg::compositor_msg::{Epoch, LayerId}; use msg::constellation_msg::{ConstellationChan, PipelineId, Failure, WindowSizeData}; use msg::constellation_msg::{LoadData, SubpageId, Key, KeyState, KeyModifiers}; use msg::constellation_msg::{MozBrowserEvent, PipelineExitType}; @@ -29,6 +35,7 @@ use net_traits::storage_task::StorageTask; use std::any::Any; use std::sync::mpsc::{Sender, Receiver}; use url::Url; +use util::geometry::Au; use euclid::point::Point2D; use euclid::rect::Rect; @@ -40,6 +47,19 @@ use euclid::rect::Rect; pub struct UntrustedNodeAddress(pub *const c_void); unsafe impl Send for UntrustedNodeAddress {} +/// Messages sent to the layout task from the constellation and/or compositor. +#[derive(Deserialize, Serialize)] +pub enum LayoutControlMsg { + /// Requests that this layout task exit. + ExitNow(PipelineExitType), + /// Requests the current epoch (layout counter) from this layout. + GetCurrentEpoch(IpcSender), + /// Asks layout to run another step in its animation. + TickAnimations, + /// Informs layout as to which regions of the page are visible. + SetVisibleRects(Vec<(LayerId, Rect)>), +} + /// The initial data associated with a newly-created framed pipeline. pub struct NewLayoutInfo { /// Id of the parent of this new pipeline. @@ -48,11 +68,19 @@ pub struct NewLayoutInfo { pub new_pipeline_id: PipelineId, /// Id of the new frame associated with this pipeline. pub subpage_id: SubpageId, - /// Channel for communicating with this new pipeline's layout task. - /// (This is a LayoutChannel.) - pub layout_chan: Box, /// Network request data which will be initiated by the script task. pub load_data: LoadData, + /// The paint channel, cast to `Box`. + /// + /// TODO(pcwalton): When we convert this to use IPC, this will need to become an + /// `IpcAnySender`. + pub paint_chan: Box, + /// Information on what to do on task failure. + pub failure: Failure, + /// A port on which layout can receive messages from the pipeline. + pub pipeline_port: IpcReceiver, + /// A shutdown channel so that layout can notify others when it's done. + pub layout_shutdown_chan: Sender<()>, } /// `StylesheetLoadResponder` is used to notify a responder that a style sheet diff --git a/components/servo/Cargo.lock b/components/servo/Cargo.lock index f69593bc603..7c15392644b 100644 --- a/components/servo/Cargo.lock +++ b/components/servo/Cargo.lock @@ -1111,6 +1111,7 @@ dependencies = [ "hyper 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "ipc-channel 0.1.0 (git+https://github.com/pcwalton/ipc-channel)", "js 0.1.0 (git+https://github.com/servo/rust-mozjs)", + "layout_traits 0.0.1", "libc 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "msg 0.0.1", @@ -1150,9 +1151,12 @@ version = "0.0.1" dependencies = [ "devtools_traits 0.0.1", "euclid 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ipc-channel 0.1.0 (git+https://github.com/pcwalton/ipc-channel)", "libc 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "msg 0.0.1", "net_traits 0.0.1", + "serde 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_macros 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "url 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", "util 0.0.1", ]