aboutsummaryrefslogtreecommitdiffstats
path: root/src/components/main/layout/layout_task.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/components/main/layout/layout_task.rs')
-rw-r--r--src/components/main/layout/layout_task.rs98
1 files changed, 51 insertions, 47 deletions
diff --git a/src/components/main/layout/layout_task.rs b/src/components/main/layout/layout_task.rs
index 2224401188a..740576617fd 100644
--- a/src/components/main/layout/layout_task.rs
+++ b/src/components/main/layout/layout_task.rs
@@ -16,7 +16,7 @@ use layout::flow::{Flow, ImmutableFlowUtils, MutableFlowUtils, PreorderFlowTrave
use layout::flow::{PostorderFlowTraversal};
use layout::flow;
use layout::incremental::{RestyleDamage};
-use layout::util::{LayoutData, LayoutDataAccess, OpaqueNode};
+use layout::util::{LayoutDataAccess, OpaqueNode, LayoutDataWrapper};
use layout::wrapper::LayoutNode;
use extra::arc::{Arc, RWArc, MutexArc};
@@ -34,7 +34,7 @@ use script::dom::element::{HTMLBodyElementTypeId, HTMLHtmlElementTypeId};
use script::layout_interface::{AddStylesheetMsg, ContentBoxQuery};
use script::layout_interface::{ContentBoxesQuery, ContentBoxesResponse, ExitNowMsg, LayoutQuery};
use script::layout_interface::{HitTestQuery, ContentBoxResponse, HitTestResponse};
-use script::layout_interface::{ContentChangedDocumentDamage, Msg, PrepareToExitMsg};
+use script::layout_interface::{ContentChangedDocumentDamage, LayoutChan, Msg, PrepareToExitMsg};
use script::layout_interface::{QueryMsg, ReapLayoutDataMsg, Reflow, ReflowDocumentDamage};
use script::layout_interface::{ReflowForDisplay, ReflowMsg};
use script::script_task::{ReflowCompleteMsg, ScriptChan, SendEventMsg};
@@ -46,20 +46,22 @@ use servo_util::time::{ProfilerChan, profile};
use servo_util::time;
use std::cast::transmute;
use std::cast;
-use std::cell::Cell;
+use std::cell::RefCell;
use std::comm::Port;
-use std::task;
use std::util;
use style::{AuthorOrigin, Stylesheet, Stylist};
/// Information needed by the layout task.
-struct LayoutTask {
+pub struct LayoutTask {
/// The ID of the pipeline that we belong to.
id: PipelineId,
/// The port on which we receive messages.
port: Port<Msg>,
+ //// The channel to send messages to ourself.
+ chan: LayoutChan,
+
/// The channel on which messages can be sent to the constellation.
constellation_chan: ConstellationChan,
@@ -132,9 +134,9 @@ impl PreorderFlowTraversal for PropagateDamageTraversal {
/// The bubble-widths traversal, the first part of layout computation. This computes preferred
/// and intrinsic widths and bubbles them up the tree.
-struct BubbleWidthsTraversal<'self>(&'self mut LayoutContext);
+struct BubbleWidthsTraversal<'a>(&'a mut LayoutContext);
-impl<'self> PostorderFlowTraversal for BubbleWidthsTraversal<'self> {
+impl<'a> PostorderFlowTraversal for BubbleWidthsTraversal<'a> {
#[inline]
fn process(&mut self, flow: &mut Flow) -> bool {
flow.bubble_widths(**self);
@@ -151,9 +153,9 @@ impl<'self> PostorderFlowTraversal for BubbleWidthsTraversal<'self> {
}
/// The assign-widths traversal. In Gecko this corresponds to `Reflow`.
-struct AssignWidthsTraversal<'self>(&'self mut LayoutContext);
+struct AssignWidthsTraversal<'a>(&'a mut LayoutContext);
-impl<'self> PreorderFlowTraversal for AssignWidthsTraversal<'self> {
+impl<'a> PreorderFlowTraversal for AssignWidthsTraversal<'a> {
#[inline]
fn process(&mut self, flow: &mut Flow) -> bool {
flow.assign_widths(**self);
@@ -164,9 +166,9 @@ impl<'self> PreorderFlowTraversal for AssignWidthsTraversal<'self> {
/// The assign-heights-and-store-overflow traversal, the last (and most expensive) part of layout
/// computation. Determines the final heights for all layout objects, computes positions, and
/// computes overflow regions. In Gecko this corresponds to `FinishAndStoreOverflow`.
-struct AssignHeightsAndStoreOverflowTraversal<'self>(&'self mut LayoutContext);
+struct AssignHeightsAndStoreOverflowTraversal<'a>(&'a mut LayoutContext);
-impl<'self> PostorderFlowTraversal for AssignHeightsAndStoreOverflowTraversal<'self> {
+impl<'a> PostorderFlowTraversal for AssignHeightsAndStoreOverflowTraversal<'a> {
#[inline]
fn process(&mut self, flow: &mut Flow) -> bool {
flow.assign_height(**self);
@@ -186,10 +188,10 @@ struct LayoutImageResponder {
}
impl ImageResponder for LayoutImageResponder {
- fn respond(&self) -> ~fn(ImageResponseMsg) {
+ fn respond(&self) -> proc(ImageResponseMsg) {
let id = self.id.clone();
let script_chan = self.script_chan.clone();
- let f: ~fn(ImageResponseMsg) = |_| {
+ let f: proc(ImageResponseMsg) = proc(_) {
script_chan.send(SendEventMsg(id.clone(), ReflowEvent))
};
f
@@ -200,6 +202,7 @@ impl LayoutTask {
/// Spawns a new layout task.
pub fn create(id: PipelineId,
port: Port<Msg>,
+ chan: LayoutChan,
constellation_chan: ConstellationChan,
script_chan: ScriptChan,
render_chan: RenderChan<OpaqueNode>,
@@ -207,11 +210,11 @@ impl LayoutTask {
opts: Opts,
profiler_chan: ProfilerChan,
shutdown_chan: Chan<()>) {
- spawn_with!(task::task(), [port, constellation_chan, script_chan,
- render_chan, img_cache_task, profiler_chan, shutdown_chan], {
- { // Ensures LayoutTask gets destroyed before we send the shutdown message
+ spawn(proc() {
+ { // Ensures layout task is destroyed before we send shutdown message
let mut layout = LayoutTask::new(id,
port,
+ chan,
constellation_chan,
script_chan,
render_chan,
@@ -220,7 +223,6 @@ impl LayoutTask {
profiler_chan);
layout.start();
}
-
shutdown_chan.send(());
});
}
@@ -228,6 +230,7 @@ impl LayoutTask {
/// Creates a new `LayoutTask` structure.
fn new(id: PipelineId,
port: Port<Msg>,
+ chan: LayoutChan,
constellation_chan: ConstellationChan,
script_chan: ScriptChan,
render_chan: RenderChan<OpaqueNode>,
@@ -239,6 +242,7 @@ impl LayoutTask {
LayoutTask {
id: id,
port: port,
+ chan: chan,
constellation_chan: constellation_chan,
script_chan: script_chan,
render_chan: render_chan,
@@ -281,17 +285,15 @@ impl LayoutTask {
match self.port.recv() {
AddStylesheetMsg(sheet) => self.handle_add_stylesheet(sheet),
ReflowMsg(data) => {
- let data = Cell::new(data);
-
- do profile(time::LayoutPerformCategory, self.profiler_chan.clone()) {
- self.handle_reflow(data.take());
- }
+ profile(time::LayoutPerformCategory, self.profiler_chan.clone(), || {
+ self.handle_reflow(data);
+ });
}
QueryMsg(query) => {
- let query = Cell::new(query);
- do profile(time::LayoutQueryCategory, self.profiler_chan.clone()) {
- self.handle_query(query.take());
- }
+ let mut query = Some(query);
+ profile(time::LayoutQueryCategory, self.profiler_chan.clone(), || {
+ self.handle_query(query.take_unwrap());
+ });
}
ReapLayoutDataMsg(dead_layout_data) => {
unsafe {
@@ -340,16 +342,16 @@ impl LayoutTask {
/// Shuts down the layout task now. If there are any DOM nodes left, layout will now (safely)
/// crash.
fn exit_now(&mut self) {
- let (response_port, response_chan) = stream();
+ let (response_port, response_chan) = Chan::new();
self.render_chan.send(render_task::ExitMsg(response_chan));
response_port.recv()
}
fn handle_add_stylesheet(&mut self, sheet: Stylesheet) {
- let sheet = Cell::new(sheet);
- do self.stylist.write |stylist| {
- stylist.add_stylesheet(sheet.take(), AuthorOrigin);
- }
+ let mut sheet = Some(sheet);
+ self.stylist.write(|stylist| {
+ stylist.add_stylesheet(sheet.take_unwrap(), AuthorOrigin);
+ });
}
/// Builds the flow tree.
@@ -359,12 +361,13 @@ impl LayoutTask {
/// is intertwined with selector matching, making it difficult to compare directly. It is
/// marked `#[inline(never)]` to aid benchmarking in sampling profilers.
#[inline(never)]
- fn construct_flow_tree(&self, layout_context: &mut LayoutContext, node: LayoutNode) -> ~Flow: {
+ fn construct_flow_tree(&self, layout_context: &mut LayoutContext, node: LayoutNode) -> ~Flow {
node.traverse_postorder_mut(&mut FlowConstructor::init(layout_context));
- let result = match *node.mutate_layout_data().ptr {
+ let mut layout_data_ref = node.mutate_layout_data();
+ let result = match *layout_data_ref.get() {
Some(ref mut layout_data) => {
- util::replace(&mut layout_data.flow_construction_result, NoConstructionResult)
+ util::replace(&mut layout_data.data.flow_construction_result, NoConstructionResult)
}
None => fail!("no layout data for root node"),
};
@@ -436,18 +439,18 @@ impl LayoutTask {
// Initialize layout data for each node.
//
// FIXME: This is inefficient. We don't need an entire traversal to do this!
- do profile(time::LayoutAuxInitCategory, self.profiler_chan.clone()) {
- node.initialize_style_for_subtree();
- }
+ profile(time::LayoutAuxInitCategory, self.profiler_chan.clone(), || {
+ node.initialize_style_for_subtree(self.chan.clone());
+ });
// Perform CSS selector matching if necessary.
match data.damage.level {
ReflowDocumentDamage => {}
_ => {
- do profile(time::LayoutSelectorMatchCategory, self.profiler_chan.clone()) {
+ profile(time::LayoutSelectorMatchCategory, self.profiler_chan.clone(), || {
node.match_subtree(self.stylist.clone());
node.cascade_subtree(None);
- }
+ });
}
}
@@ -464,25 +467,25 @@ impl LayoutTask {
// Perform the primary layout passes over the flow tree to compute the locations of all
// the boxes.
- do profile(time::LayoutMainCategory, self.profiler_chan.clone()) {
+ profile(time::LayoutMainCategory, self.profiler_chan.clone(), || {
self.solve_constraints(layout_root, &mut layout_ctx)
- }
+ });
debug!("layout: constraint solving done:");
debug!("{:?}", layout_root.dump());
// Build the display list if necessary, and send it to the renderer.
if data.goal == ReflowForDisplay {
- do profile(time::LayoutDispListBuildCategory, self.profiler_chan.clone()) {
+ profile(time::LayoutDispListBuildCategory, self.profiler_chan.clone(), || {
let root_size = flow::base(layout_root).position.size;
- let display_list = ~Cell::new(DisplayList::<OpaqueNode>::new());
+ let display_list = ~RefCell::new(DisplayList::<OpaqueNode>::new());
let dirty = flow::base(layout_root).position.clone();
let display_list_builder = DisplayListBuilder {
ctx: &layout_ctx,
};
layout_root.build_display_list(&display_list_builder, &dirty, display_list);
- let display_list = Arc::new(display_list.take());
+ let display_list = Arc::new(display_list.unwrap());
let mut color = color::rgba(255.0, 255.0, 255.0, 255.0);
@@ -516,7 +519,7 @@ impl LayoutTask {
self.display_list = Some(display_list.clone());
self.render_chan.send(RenderMsg(render_layer));
- } // time(layout: display list building)
+ });
}
// Tell script that we're done.
@@ -663,8 +666,9 @@ impl LayoutTask {
/// Handles a message to destroy layout data. Layout data must be destroyed on *this* task
/// because it contains local managed pointers.
unsafe fn handle_reap_layout_data(&self, layout_data: LayoutDataRef) {
- let ptr: &mut Option<~LayoutData> = cast::transmute(layout_data.borrow_unchecked());
- *ptr = None
+ let mut layout_data_ref = layout_data.borrow_mut();
+ let _: Option<LayoutDataWrapper> = cast::transmute(
+ util::replace(layout_data_ref.get(), None));
}
}