aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--components/gfx/display_list/mod.rs12
-rw-r--r--components/gfx/paint_task.rs23
-rw-r--r--components/layout/block.rs14
-rw-r--r--components/layout/display_list_builder.rs63
-rw-r--r--components/layout/flow.rs12
-rw-r--r--components/layout/fragment.rs107
-rw-r--r--components/layout/inline.rs3
-rw-r--r--components/layout/parallel.rs43
-rw-r--r--components/layout/table_row.rs3
-rw-r--r--components/layout/table_wrapper.rs4
-rw-r--r--components/layout/util.rs2
-rw-r--r--components/util/opts.rs9
-rw-r--r--components/util/workqueue.rs8
-rw-r--r--ports/cef/core.rs1
14 files changed, 216 insertions, 88 deletions
diff --git a/components/gfx/display_list/mod.rs b/components/gfx/display_list/mod.rs
index 799810e4a70..50aa8b0867b 100644
--- a/components/gfx/display_list/mod.rs
+++ b/components/gfx/display_list/mod.rs
@@ -766,6 +766,18 @@ impl<T> BorderRadii<T> where T: PartialEq + Zero {
}
}
+impl<T> BorderRadii<T> where T: PartialEq + Zero + Clone {
+ /// Returns a set of border radii that all have the given value.
+ pub fn all_same(value: T) -> BorderRadii<T> {
+ BorderRadii {
+ top_left: value.clone(),
+ top_right: value.clone(),
+ bottom_right: value.clone(),
+ bottom_left: value.clone(),
+ }
+ }
+}
+
/// Paints a line segment.
#[derive(Clone)]
pub struct LineDisplayItem {
diff --git a/components/gfx/paint_task.rs b/components/gfx/paint_task.rs
index bab531c3a0e..5c9008bb009 100644
--- a/components/gfx/paint_task.rs
+++ b/components/gfx/paint_task.rs
@@ -571,18 +571,11 @@ impl WorkerThread {
if opts::get().show_debug_parallel_paint {
// Overlay a transparent solid color to identify the thread that
// painted this tile.
- let colors = [Color { r: 6.0/255.0, g: 153.0/255.0, b: 198.0/255.0, a: 0.7 },
- Color { r: 255.0/255.0, g: 212.0/255.0, b: 83.0/255.0, a: 0.7 },
- Color { r: 116.0/255.0, g: 29.0/255.0, b: 109.0/255.0, a: 0.7 },
- Color { r: 204.0/255.0, g: 158.0/255.0, b: 199.0/255.0, a: 0.7 },
- Color { r: 242.0/255.0, g: 46.0/255.0, b: 121.0/255.0, a: 0.7 },
- Color { r: 116.0/255.0, g: 203.0/255.0, b: 196.0/255.0, a: 0.7 },
- Color { r: 255.0/255.0, g: 249.0/255.0, b: 201.0/255.0, a: 0.7 },
- Color { r: 137.0/255.0, g: 196.0/255.0, b: 78.0/255.0, a: 0.7 }];
+ let color = THREAD_TINT_COLORS[thread_id % THREAD_TINT_COLORS.len()];
paint_context.draw_solid_color(&Rect(Point2D(Au(0), Au(0)),
Size2D(Au::from_px(size.width as isize),
Au::from_px(size.height as isize))),
- colors[thread_id % colors.len()]);
+ color);
}
}
@@ -639,3 +632,15 @@ enum MsgToWorkerThread {
enum MsgFromWorkerThread {
PaintedTile(Box<LayerBuffer>),
}
+
+pub static THREAD_TINT_COLORS: [Color; 8] = [
+ Color { r: 6.0/255.0, g: 153.0/255.0, b: 198.0/255.0, a: 0.7 },
+ Color { r: 255.0/255.0, g: 212.0/255.0, b: 83.0/255.0, a: 0.7 },
+ Color { r: 116.0/255.0, g: 29.0/255.0, b: 109.0/255.0, a: 0.7 },
+ Color { r: 204.0/255.0, g: 158.0/255.0, b: 199.0/255.0, a: 0.7 },
+ Color { r: 242.0/255.0, g: 46.0/255.0, b: 121.0/255.0, a: 0.7 },
+ Color { r: 116.0/255.0, g: 203.0/255.0, b: 196.0/255.0, a: 0.7 },
+ Color { r: 255.0/255.0, g: 249.0/255.0, b: 201.0/255.0, a: 0.7 },
+ Color { r: 137.0/255.0, g: 196.0/255.0, b: 78.0/255.0, a: 0.7 },
+];
+
diff --git a/components/layout/block.rs b/components/layout/block.rs
index 64e1372de2e..ba11c33cb5f 100644
--- a/components/layout/block.rs
+++ b/components/layout/block.rs
@@ -863,6 +863,7 @@ impl BlockFlow {
// At this point, `cur_b` is at the content edge of our box. Now iterate over children.
let mut floats = self.base.floats.clone();
let mut layers_needed_for_descendants = false;
+ let thread_id = self.base.thread_id;
for kid in self.base.child_iter() {
if flow::base(kid).flags.contains(IS_ABSOLUTELY_POSITIONED) {
// Assume that the *hypothetical box* for an absolute flow starts immediately
@@ -870,7 +871,8 @@ impl BlockFlow {
kid.as_block().hypothetical_position.b = cur_b;
kid.place_float_if_applicable(layout_context);
if !flow::base(kid).flags.is_float() {
- kid.assign_block_size_for_inorder_child_if_necessary(layout_context);
+ kid.assign_block_size_for_inorder_child_if_necessary(layout_context,
+ thread_id);
}
propagate_layer_flag_from_child(&mut layers_needed_for_descendants, kid);
@@ -910,7 +912,8 @@ impl BlockFlow {
// Lay the child out if this was an in-order traversal.
let need_to_process_child_floats =
- kid.assign_block_size_for_inorder_child_if_necessary(layout_context);
+ kid.assign_block_size_for_inorder_child_if_necessary(layout_context,
+ thread_id);
// Mark flows for layerization if necessary to handle painting order correctly.
propagate_layer_flag_from_child(&mut layers_needed_for_descendants, kid);
@@ -1047,8 +1050,9 @@ impl BlockFlow {
} else {
// We don't need to reflow, but we still need to perform in-order traversals if
// necessary.
+ let thread_id = self.base.thread_id;
for kid in self.base.child_iter() {
- kid.assign_block_size_for_inorder_child_if_necessary(layout_context);
+ kid.assign_block_size_for_inorder_child_if_necessary(layout_context, thread_id);
}
}
@@ -1650,7 +1654,8 @@ impl Flow for BlockFlow {
}
fn assign_block_size_for_inorder_child_if_necessary<'a>(&mut self,
- layout_context: &'a LayoutContext<'a>)
+ layout_context: &'a LayoutContext<'a>,
+ parent_thread_id: u8)
-> bool {
if self.base.flags.is_float() {
return false
@@ -1662,6 +1667,7 @@ impl Flow for BlockFlow {
}
if self.base.flags.impacted_by_floats() {
+ self.base.thread_id = parent_thread_id;
if self.base.restyle_damage.intersects(REFLOW_OUT_OF_FLOW | REFLOW) {
self.assign_block_size(layout_context);
// Don't remove the restyle damage; `assign_block_size` decides whether that is
diff --git a/components/layout/display_list_builder.rs b/components/layout/display_list_builder.rs
index beea14abca0..b41c407eb58 100644
--- a/components/layout/display_list_builder.rs
+++ b/components/layout/display_list_builder.rs
@@ -13,7 +13,7 @@
use block::BlockFlow;
use canvas::canvas_paint_task::CanvasMsg::SendPixelContents;
use context::LayoutContext;
-use flow::{self, Flow, IS_ABSOLUTELY_POSITIONED, NEEDS_LAYER};
+use flow::{self, BaseFlow, Flow, IS_ABSOLUTELY_POSITIONED, NEEDS_LAYER};
use fragment::{CoordinateSystem, Fragment, IframeFragmentInfo, ImageFragmentInfo};
use fragment::{ScannedTextFragmentInfo, SpecificFragmentInfo};
use inline::InlineFlow;
@@ -29,10 +29,9 @@ use gfx::display_list::{BorderRadii, BoxShadowDisplayItem, ClippingRegion};
use gfx::display_list::{DisplayItem, DisplayList, DisplayItemMetadata};
use gfx::display_list::{GradientDisplayItem};
use gfx::display_list::{GradientStop, ImageDisplayItem, LineDisplayItem};
-use gfx::display_list::TextOrientation;
-use gfx::display_list::{SolidColorDisplayItem};
-use gfx::display_list::{StackingContext, TextDisplayItem};
-use gfx::paint_task::PaintLayer;
+use gfx::display_list::{OpaqueNode, SolidColorDisplayItem};
+use gfx::display_list::{StackingContext, TextDisplayItem, TextOrientation};
+use gfx::paint_task::{PaintLayer, THREAD_TINT_COLORS};
use png;
use png::PixelsByColorType;
use msg::compositor_msg::ScrollPolicy;
@@ -720,7 +719,8 @@ impl FragmentDisplayListBuilding for Fragment {
relative_containing_block_size,
CoordinateSystem::Self);
- debug!("Fragment::build_display_list at rel={:?}, abs={:?}, dirty={:?}, flow origin={:?}: {:?}",
+ debug!("Fragment::build_display_list at rel={:?}, abs={:?}, dirty={:?}, flow origin={:?}: \
+ {:?}",
self.border_box,
stacking_relative_border_box,
layout_context.shared.dirty,
@@ -1118,6 +1118,8 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
for kid in self.base.children.iter_mut() {
flow::mut_base(kid).display_list_building_result.add_to(display_list);
}
+
+ self.base.build_display_items_for_debugging_tint(display_list, self.fragment.node);
}
fn build_display_list_for_static_block(&mut self,
@@ -1192,13 +1194,13 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
if self.base.flags.is_float() {
// TODO(#2009, pcwalton): This is a pseudo-stacking context. We need to merge `z-index:
// auto` kids into the parent stacking context, when that is supported.
- self.build_display_list_for_floating_block(display_list, layout_context)
+ self.build_display_list_for_floating_block(display_list, layout_context);
} else if self.base.flags.contains(IS_ABSOLUTELY_POSITIONED) {
- self.build_display_list_for_absolutely_positioned_block(display_list, layout_context)
+ self.build_display_list_for_absolutely_positioned_block(display_list, layout_context);
} else {
self.build_display_list_for_static_block(display_list,
layout_context,
- BackgroundAndBorderLevel::Block)
+ BackgroundAndBorderLevel::Block);
}
}
@@ -1246,6 +1248,7 @@ impl InlineFlowDisplayListBuilding for InlineFlow {
debug!("Flow: building display list for {} inline fragments", self.fragments.len());
let mut display_list = box DisplayList::new();
+
for fragment in self.fragments.fragments.iter_mut() {
fragment.build_display_list(&mut *display_list,
layout_context,
@@ -1270,6 +1273,11 @@ impl InlineFlowDisplayListBuilding for InlineFlow {
}
}
+ if !self.fragments.fragments.is_empty() {
+ self.base.build_display_items_for_debugging_tint(&mut *display_list,
+ self.fragments.fragments[0].node);
+ }
+
self.base.display_list_building_result = DisplayListBuildingResult::Normal(display_list);
if opts::get().validate_display_list_geometry {
@@ -1306,6 +1314,43 @@ impl ListItemFlowDisplayListBuilding for ListItemFlow {
}
}
+trait BaseFlowDisplayListBuilding {
+ fn build_display_items_for_debugging_tint(&self,
+ display_list: &mut DisplayList,
+ node: OpaqueNode);
+}
+
+impl BaseFlowDisplayListBuilding for BaseFlow {
+ fn build_display_items_for_debugging_tint(&self,
+ display_list: &mut DisplayList,
+ node: OpaqueNode) {
+ if !opts::get().show_debug_parallel_layout {
+ return
+ }
+
+ let thread_id = self.thread_id;
+ let stacking_context_relative_bounds =
+ Rect(self.stacking_relative_position,
+ self.position.size.to_physical(self.writing_mode));
+
+ let mut color = THREAD_TINT_COLORS[thread_id as usize % THREAD_TINT_COLORS.len()];
+ color.a = 1.0;
+ display_list.push(DisplayItem::BorderClass(box BorderDisplayItem {
+ base: BaseDisplayItem::new(stacking_context_relative_bounds.inflate(Au::from_px(2),
+ Au::from_px(2)),
+ DisplayItemMetadata {
+ node: node,
+ pointing: None,
+ },
+ self.clip.clone()),
+ border_widths: SideOffsets2D::new_all_same(Au::from_px(2)),
+ color: SideOffsets2D::new_all_same(color),
+ style: SideOffsets2D::new_all_same(border_style::T::solid),
+ radius: BorderRadii::all_same(Au(0)),
+ }), StackingLevel::Content);
+ }
+}
+
// A helper data structure for gradients.
#[derive(Copy)]
struct StopRun {
diff --git a/components/layout/flow.rs b/components/layout/flow.rs
index c8339b52762..19f1df86c3a 100644
--- a/components/layout/flow.rs
+++ b/components/layout/flow.rs
@@ -202,11 +202,17 @@ pub trait Flow: fmt::Debug + Sync {
/// Assigns block-sizes in-order; or, if this is a float, places the float. The default
/// implementation simply assigns block-sizes if this flow is impacted by floats. Returns true
/// if this child was impacted by floats or false otherwise.
+ ///
+ /// `parent_thread_id` is the thread ID of the parent. This is used for the layout tinting
+ /// debug mode; if the block size of this flow was determined by its parent, we should treat
+ /// it as laid out by its parent.
fn assign_block_size_for_inorder_child_if_necessary<'a>(&mut self,
- layout_context: &'a LayoutContext<'a>)
+ layout_context: &'a LayoutContext<'a>,
+ parent_thread_id: u8)
-> bool {
let impacted = base(self).flags.impacted_by_floats();
if impacted {
+ mut_base(self).thread_id = parent_thread_id;
self.assign_block_size(layout_context);
mut_base(self).restyle_damage.remove(REFLOW_OUT_OF_FLOW | REFLOW);
}
@@ -777,6 +783,9 @@ pub struct BaseFlow {
/// The writing mode for this flow.
pub writing_mode: WritingMode,
+ /// For debugging and profiling, the identifier of the thread that laid out this fragment.
+ pub thread_id: u8,
+
/// Various flags for flows, tightly packed to save space.
pub flags: FlowFlags,
}
@@ -918,6 +927,7 @@ impl BaseFlow {
clip: ClippingRegion::max(),
flags: flags,
writing_mode: writing_mode,
+ thread_id: 0,
}
}
diff --git a/components/layout/fragment.rs b/components/layout/fragment.rs
index 46002c946ff..dcfc408970c 100644
--- a/components/layout/fragment.rs
+++ b/components/layout/fragment.rs
@@ -109,12 +109,11 @@ pub struct Fragment {
/// that are part of an inline formatting context.
pub inline_context: Option<InlineFragmentContext>,
- /// A debug ID that is consistent for the life of
- /// this fragment (via transform etc).
- pub debug_id: u16,
-
/// How damaged this fragment is since last reflow.
pub restyle_damage: RestyleDamage,
+
+ /// A debug ID that is consistent for the life of this fragment (via transform etc).
+ pub debug_id: u16,
}
unsafe impl Send for Fragment {}
@@ -1667,14 +1666,23 @@ impl Fragment {
/// content per CSS 2.1 § 10.3.2.
pub fn assign_replaced_inline_size_if_necessary<'a>(&'a mut self, container_inline_size: Au) {
match self.specific {
- SpecificFragmentInfo::Generic | SpecificFragmentInfo::Table | SpecificFragmentInfo::TableCell |
- SpecificFragmentInfo::TableRow | SpecificFragmentInfo::TableWrapper => return,
- SpecificFragmentInfo::TableColumn(_) => panic!("Table column fragments do not have inline_size"),
+ SpecificFragmentInfo::Generic |
+ SpecificFragmentInfo::Table |
+ SpecificFragmentInfo::TableCell |
+ SpecificFragmentInfo::TableRow |
+ SpecificFragmentInfo::TableWrapper => return,
+ SpecificFragmentInfo::TableColumn(_) => {
+ panic!("Table column fragments do not have inline_size")
+ }
SpecificFragmentInfo::UnscannedText(_) => {
panic!("Unscanned text fragments should have been scanned by now!")
}
- SpecificFragmentInfo::Canvas(_) | SpecificFragmentInfo::Image(_) | SpecificFragmentInfo::ScannedText(_) | SpecificFragmentInfo::InlineBlock(_) |
- SpecificFragmentInfo::InlineAbsoluteHypothetical(_) | SpecificFragmentInfo::Iframe(_) => {}
+ SpecificFragmentInfo::Canvas(_) |
+ SpecificFragmentInfo::Image(_) |
+ SpecificFragmentInfo::ScannedText(_) |
+ SpecificFragmentInfo::InlineBlock(_) |
+ SpecificFragmentInfo::InlineAbsoluteHypothetical(_) |
+ SpecificFragmentInfo::Iframe(_) => {}
};
let style = self.style().clone();
@@ -1703,22 +1711,24 @@ impl Fragment {
SpecificFragmentInfo::Image(ref mut image_fragment_info) => {
let fragment_inline_size = image_fragment_info.image_inline_size();
let fragment_block_size = image_fragment_info.image_block_size();
- self.border_box.size.inline = image_fragment_info.replaced_image_fragment_info.
- calculate_replaced_inline_size(style,
- noncontent_inline_size,
- container_inline_size,
- fragment_inline_size,
- fragment_block_size);
+ self.border_box.size.inline =
+ image_fragment_info.replaced_image_fragment_info
+ .calculate_replaced_inline_size(style,
+ noncontent_inline_size,
+ container_inline_size,
+ fragment_inline_size,
+ fragment_block_size);
}
SpecificFragmentInfo::Canvas(ref mut canvas_fragment_info) => {
let fragment_inline_size = canvas_fragment_info.canvas_inline_size();
let fragment_block_size = canvas_fragment_info.canvas_block_size();
- self.border_box.size.inline = canvas_fragment_info.replaced_image_fragment_info.
- calculate_replaced_inline_size(style,
- noncontent_inline_size,
- container_inline_size,
- fragment_inline_size,
- fragment_block_size);
+ self.border_box.size.inline =
+ canvas_fragment_info.replaced_image_fragment_info
+ .calculate_replaced_inline_size(style,
+ noncontent_inline_size,
+ container_inline_size,
+ fragment_inline_size,
+ fragment_block_size);
}
SpecificFragmentInfo::Iframe(_) => {
self.border_box.size.inline = IframeFragmentInfo::calculate_replaced_inline_size(
@@ -1735,14 +1745,23 @@ impl Fragment {
/// Ideally, this should follow CSS 2.1 § 10.6.2.
pub fn assign_replaced_block_size_if_necessary(&mut self, containing_block_block_size: Au) {
match self.specific {
- SpecificFragmentInfo::Generic | SpecificFragmentInfo::Table | SpecificFragmentInfo::TableCell |
- SpecificFragmentInfo::TableRow | SpecificFragmentInfo::TableWrapper => return,
- SpecificFragmentInfo::TableColumn(_) => panic!("Table column fragments do not have block_size"),
+ SpecificFragmentInfo::Generic |
+ SpecificFragmentInfo::Table |
+ SpecificFragmentInfo::TableCell |
+ SpecificFragmentInfo::TableRow |
+ SpecificFragmentInfo::TableWrapper => return,
+ SpecificFragmentInfo::TableColumn(_) => {
+ panic!("Table column fragments do not have block_size")
+ }
SpecificFragmentInfo::UnscannedText(_) => {
panic!("Unscanned text fragments should have been scanned by now!")
}
- SpecificFragmentInfo::Canvas(_) | SpecificFragmentInfo::Image(_) | SpecificFragmentInfo::ScannedText(_) | SpecificFragmentInfo::InlineBlock(_) |
- SpecificFragmentInfo::InlineAbsoluteHypothetical(_) | SpecificFragmentInfo::Iframe(_) => {}
+ SpecificFragmentInfo::Canvas(_) |
+ SpecificFragmentInfo::Image(_) |
+ SpecificFragmentInfo::ScannedText(_) |
+ SpecificFragmentInfo::InlineBlock(_) |
+ SpecificFragmentInfo::InlineAbsoluteHypothetical(_) |
+ SpecificFragmentInfo::Iframe(_) => {}
}
let style = self.style().clone();
@@ -1752,22 +1771,24 @@ impl Fragment {
SpecificFragmentInfo::Image(ref mut image_fragment_info) => {
let fragment_inline_size = image_fragment_info.image_inline_size();
let fragment_block_size = image_fragment_info.image_block_size();
- self.border_box.size.block = image_fragment_info.replaced_image_fragment_info.
- calculate_replaced_block_size(style,
- noncontent_block_size,
- containing_block_block_size,
- fragment_inline_size,
- fragment_block_size);
+ self.border_box.size.block =
+ image_fragment_info.replaced_image_fragment_info.
+ calculate_replaced_block_size(style,
+ noncontent_block_size,
+ containing_block_block_size,
+ fragment_inline_size,
+ fragment_block_size);
}
SpecificFragmentInfo::Canvas(ref mut canvas_fragment_info) => {
let fragment_inline_size = canvas_fragment_info.canvas_inline_size();
let fragment_block_size = canvas_fragment_info.canvas_block_size();
- self.border_box.size.block = canvas_fragment_info.replaced_image_fragment_info.
- calculate_replaced_block_size(style,
- noncontent_block_size,
- containing_block_block_size,
- fragment_inline_size,
- fragment_block_size);
+ self.border_box.size.block =
+ canvas_fragment_info.replaced_image_fragment_info
+ .calculate_replaced_block_size(style,
+ noncontent_block_size,
+ containing_block_block_size,
+ fragment_inline_size,
+ fragment_block_size);
}
SpecificFragmentInfo::ScannedText(ref info) => {
// Scanned text fragments' content block-sizes are calculated by the text run
@@ -1794,14 +1815,16 @@ impl Fragment {
}
}
- /// Calculates block-size above baseline, depth below baseline, and ascent for this fragment when
- /// used in an inline formatting context. See CSS 2.1 § 10.8.1.
+ /// Calculates block-size above baseline, depth below baseline, and ascent for this fragment
+ /// when used in an inline formatting context. See CSS 2.1 § 10.8.1.
pub fn inline_metrics(&self, layout_context: &LayoutContext) -> InlineMetrics {
match self.specific {
SpecificFragmentInfo::Image(ref image_fragment_info) => {
- let computed_block_size = image_fragment_info.replaced_image_fragment_info.computed_block_size();
+ let computed_block_size = image_fragment_info.replaced_image_fragment_info
+ .computed_block_size();
InlineMetrics {
- block_size_above_baseline: computed_block_size + self.border_padding.block_start_end(),
+ block_size_above_baseline: computed_block_size +
+ self.border_padding.block_start_end(),
depth_below_baseline: Au(0),
ascent: computed_block_size + self.border_padding.block_end,
}
diff --git a/components/layout/inline.rs b/components/layout/inline.rs
index e0abc733b5a..a5ca5038c30 100644
--- a/components/layout/inline.rs
+++ b/components/layout/inline.rs
@@ -1301,12 +1301,13 @@ impl Flow for InlineFlow {
} // End of `lines.iter_mut()` loop.
// Assign block sizes for any inline-block descendants.
+ let thread_id = self.base.thread_id;
for kid in self.base.child_iter() {
if flow::base(kid).flags.contains(IS_ABSOLUTELY_POSITIONED) ||
flow::base(kid).flags.is_float() {
continue
}
- kid.assign_block_size_for_inorder_child_if_necessary(layout_context);
+ kid.assign_block_size_for_inorder_child_if_necessary(layout_context, thread_id);
}
self.base.position.size.block = match self.lines.as_slice().last() {
diff --git a/components/layout/parallel.rs b/components/layout/parallel.rs
index 5483a12594e..acc6b6fff9d 100644
--- a/components/layout/parallel.rs
+++ b/components/layout/parallel.rs
@@ -79,6 +79,9 @@ impl DomParallelInfo {
}
}
+pub type FlowTraversalFunction =
+ extern "Rust" fn(UnsafeFlow, &mut WorkerProxy<SharedLayoutContextWrapper,UnsafeLayoutNode>);
+
/// A parallel top-down DOM traversal.
pub trait ParallelPreorderDomTraversal : PreorderDomTraversal {
fn run_parallel(&self,
@@ -89,12 +92,8 @@ pub trait ParallelPreorderDomTraversal : PreorderDomTraversal {
fn run_parallel_helper(&self,
unsafe_node: UnsafeLayoutNode,
proxy: &mut WorkerProxy<SharedLayoutContextWrapper,UnsafeLayoutNode>,
- top_down_func: extern "Rust" fn(UnsafeFlow,
- &mut WorkerProxy<SharedLayoutContextWrapper,
- UnsafeLayoutNode>),
- bottom_up_func: extern "Rust" fn(UnsafeFlow,
- &mut WorkerProxy<SharedLayoutContextWrapper,
- UnsafeFlow>)) {
+ top_down_func: FlowTraversalFunction,
+ bottom_up_func: FlowTraversalFunction) {
// Get a real layout node.
let node: LayoutNode = unsafe {
layout_node_from_unsafe_layout_node(&unsafe_node)
@@ -156,11 +155,10 @@ trait ParallelPostorderDomTraversal : PostorderDomTraversal {
let shared_layout_context = unsafe { &*(proxy.user_data().0) };
let layout_context = LayoutContext::new(shared_layout_context);
- let parent =
- match node.layout_parent_node(layout_context.shared) {
- None => break,
- Some(parent) => parent,
- };
+ let parent = match node.layout_parent_node(layout_context.shared) {
+ None => break,
+ Some(parent) => parent,
+ };
unsafe {
let parent_layout_data =
@@ -265,21 +263,23 @@ trait ParallelPreorderFlowTraversal : PreorderFlowTraversal {
unsafe_flow: UnsafeFlow,
proxy: &mut WorkerProxy<SharedLayoutContextWrapper,UnsafeFlow>);
+ fn should_record_thread_ids(&self) -> bool;
+
#[inline(always)]
fn run_parallel_helper(&self,
unsafe_flow: UnsafeFlow,
proxy: &mut WorkerProxy<SharedLayoutContextWrapper,UnsafeFlow>,
- top_down_func: extern "Rust" fn(UnsafeFlow,
- &mut WorkerProxy<SharedLayoutContextWrapper,
- UnsafeFlow>),
- bottom_up_func: extern "Rust" fn(UnsafeFlow,
- &mut WorkerProxy<SharedLayoutContextWrapper,
- UnsafeFlow>)) {
+ top_down_func: FlowTraversalFunction,
+ bottom_up_func: FlowTraversalFunction) {
let mut had_children = false;
unsafe {
// Get a real flow.
let flow: &mut FlowRef = mem::transmute(&unsafe_flow);
+ if self.should_record_thread_ids() {
+ flow::mut_base(&mut **flow).thread_id = proxy.worker_index();
+ }
+
if self.should_process(&mut **flow) {
// Perform the appropriate traversal.
self.process(&mut **flow);
@@ -293,7 +293,6 @@ trait ParallelPreorderFlowTraversal : PreorderFlowTraversal {
data: borrowed_flow_to_unsafe_flow(kid),
});
}
-
}
// If there were no more children, start assigning block-sizes.
@@ -314,6 +313,10 @@ impl<'a> ParallelPreorderFlowTraversal for AssignISizes<'a> {
assign_inline_sizes,
assign_block_sizes_and_store_overflow)
}
+
+ fn should_record_thread_ids(&self) -> bool {
+ true
+ }
}
impl<'a> ParallelPostorderFlowTraversal for AssignBSizesAndStoreOverflow<'a> {}
@@ -327,6 +330,10 @@ impl<'a> ParallelPreorderFlowTraversal for ComputeAbsolutePositions<'a> {
compute_absolute_positions,
build_display_list)
}
+
+ fn should_record_thread_ids(&self) -> bool {
+ false
+ }
}
impl<'a> ParallelPostorderFlowTraversal for BuildDisplayList<'a> {}
diff --git a/components/layout/table_row.rs b/components/layout/table_row.rs
index 0d93dfc9a4b..d712d7e4945 100644
--- a/components/layout/table_row.rs
+++ b/components/layout/table_row.rs
@@ -94,10 +94,11 @@ impl TableRowFlow {
// Per CSS 2.1 § 17.5.3, find max_y = max(computed `block-size`, minimum block-size of all
// cells).
let mut max_y = Au(0);
+ let thread_id = self.block_flow.base.thread_id;
for kid in self.block_flow.base.child_iter() {
kid.place_float_if_applicable(layout_context);
if !flow::base(kid).flags.is_float() {
- kid.assign_block_size_for_inorder_child_if_necessary(layout_context);
+ kid.assign_block_size_for_inorder_child_if_necessary(layout_context, thread_id);
}
{
diff --git a/components/layout/table_wrapper.rs b/components/layout/table_wrapper.rs
index b66addae4b4..e849150bede 100644
--- a/components/layout/table_wrapper.rs
+++ b/components/layout/table_wrapper.rs
@@ -342,7 +342,8 @@ impl Flow for TableWrapperFlow {
}
fn assign_block_size_for_inorder_child_if_necessary<'a>(&mut self,
- layout_context: &'a LayoutContext<'a>)
+ layout_context: &'a LayoutContext<'a>,
+ parent_thread_id: u8)
-> bool {
if self.block_flow.base.flags.is_float() {
self.block_flow.place_float();
@@ -351,6 +352,7 @@ impl Flow for TableWrapperFlow {
let impacted = self.block_flow.base.flags.impacted_by_floats();
if impacted {
+ self.block_flow.base.thread_id = parent_thread_id;
self.assign_block_size(layout_context);
}
impacted
diff --git a/components/layout/util.rs b/components/layout/util.rs
index 481adb895c7..fca6fabb3ed 100644
--- a/components/layout/util.rs
+++ b/components/layout/util.rs
@@ -9,7 +9,7 @@ use incremental::RestyleDamage;
use parallel::DomParallelInfo;
use wrapper::{LayoutNode, TLayoutNode, ThreadSafeLayoutNode};
-use azure::azure_hl::{Color};
+use azure::azure_hl::Color;
use gfx::display_list::OpaqueNode;
use gfx;
use libc::{c_void, uintptr_t};
diff --git a/components/util/opts.rs b/components/util/opts.rs
index d868d47dd92..baad6654b8b 100644
--- a/components/util/opts.rs
+++ b/components/util/opts.rs
@@ -72,12 +72,16 @@ pub struct Opts {
/// debugging purposes (`--show-debug-borders`).
pub show_debug_borders: bool,
- /// True if we should show borders on all fragments for debugging purposes (`--show-debug-fragment-borders`).
+ /// True if we should show borders on all fragments for debugging purposes
+ /// (`--show-debug-fragment-borders`).
pub show_debug_fragment_borders: bool,
/// True if we should paint tiles with overlays based on which thread painted them.
pub show_debug_parallel_paint: bool,
+ /// True if we should paint borders around flows based on which thread painted them.
+ pub show_debug_parallel_layout: bool,
+
/// If set with --disable-text-aa, disable antialiasing on fonts. This is primarily useful for reftests
/// where pixel perfect results are required when using fonts such as the Ahem
/// font for layout tests.
@@ -132,6 +136,7 @@ pub fn print_debug_usage(app: &str) {
print_option("show-compositor-borders", "Paint borders along layer and tile boundaries.");
print_option("show-fragment-borders", "Paint borders along fragment boundaries.");
print_option("show-parallel-paint", "Overlay tiles with colors showing which thread painted them.");
+ print_option("show-parallel-layout", "Mark which thread laid each flow out with colors.");
print_option("trace-layout", "Write layout trace to an external file for debugging.");
print_option("validate-display-list-geometry",
"Display an error when display list geometry escapes overflow region.");
@@ -171,6 +176,7 @@ pub fn default_opts() -> Opts {
show_debug_borders: false,
show_debug_fragment_borders: false,
show_debug_parallel_paint: false,
+ show_debug_parallel_layout: false,
enable_text_antialiasing: false,
trace_layout: false,
devtools_port: None,
@@ -321,6 +327,7 @@ pub fn from_cmdline_args(args: &[String]) -> bool {
show_debug_borders: debug_options.contains(&"show-compositor-borders"),
show_debug_fragment_borders: debug_options.contains(&"show-fragment-borders"),
show_debug_parallel_paint: debug_options.contains(&"show-parallel-paint"),
+ show_debug_parallel_layout: debug_options.contains(&"show-parallel-layout"),
enable_text_antialiasing: !debug_options.contains(&"disable-text-aa"),
dump_flow_tree: debug_options.contains(&"dump-flow-tree"),
validate_display_list_geometry: debug_options.contains(&"validate-display-list-geometry"),
diff --git a/components/util/workqueue.rs b/components/util/workqueue.rs
index 69fbce97b7e..ad39b1e349f 100644
--- a/components/util/workqueue.rs
+++ b/components/util/workqueue.rs
@@ -157,6 +157,7 @@ impl<QueueData: Send, WorkData: Send> WorkerThread<QueueData, WorkData> {
worker: &mut deque,
ref_count: ref_count,
queue_data: queue_data,
+ worker_index: self.index as u8,
};
(work_unit.fun)(work_unit.data, &mut proxy);
@@ -180,6 +181,7 @@ pub struct WorkerProxy<'a, QueueData: 'a, WorkData: 'a> {
worker: &'a mut Worker<WorkUnit<QueueData, WorkData>>,
ref_count: *mut AtomicUint,
queue_data: *const QueueData,
+ worker_index: u8,
}
impl<'a, QueueData: 'static, WorkData: Send> WorkerProxy<'a, QueueData, WorkData> {
@@ -199,6 +201,12 @@ impl<'a, QueueData: 'static, WorkData: Send> WorkerProxy<'a, QueueData, WorkData
mem::transmute(self.queue_data)
}
}
+
+ /// Retrieves the index of the worker.
+ #[inline]
+ pub fn worker_index(&self) -> u8 {
+ self.worker_index
+ }
}
/// A work queue on which units of work can be submitted.
diff --git a/ports/cef/core.rs b/ports/cef/core.rs
index 4db155b36b3..f330a82a4fa 100644
--- a/ports/cef/core.rs
+++ b/ports/cef/core.rs
@@ -89,6 +89,7 @@ pub extern "C" fn cef_initialize(args: *const cef_main_args_t,
show_debug_borders: false,
show_debug_fragment_borders: false,
show_debug_parallel_paint: false,
+ show_debug_parallel_layout: false,
enable_text_antialiasing: true,
trace_layout: false,
devtools_port: None,