diff options
-rw-r--r-- | components/gfx/display_list/mod.rs | 12 | ||||
-rw-r--r-- | components/gfx/paint_task.rs | 23 | ||||
-rw-r--r-- | components/layout/block.rs | 14 | ||||
-rw-r--r-- | components/layout/display_list_builder.rs | 63 | ||||
-rw-r--r-- | components/layout/flow.rs | 12 | ||||
-rw-r--r-- | components/layout/fragment.rs | 107 | ||||
-rw-r--r-- | components/layout/inline.rs | 3 | ||||
-rw-r--r-- | components/layout/parallel.rs | 43 | ||||
-rw-r--r-- | components/layout/table_row.rs | 3 | ||||
-rw-r--r-- | components/layout/table_wrapper.rs | 4 | ||||
-rw-r--r-- | components/layout/util.rs | 2 | ||||
-rw-r--r-- | components/util/opts.rs | 9 | ||||
-rw-r--r-- | components/util/workqueue.rs | 8 | ||||
-rw-r--r-- | ports/cef/core.rs | 1 |
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, |