diff options
Diffstat (limited to 'components/layout_thread/lib.rs')
-rw-r--r-- | components/layout_thread/lib.rs | 107 |
1 files changed, 64 insertions, 43 deletions
diff --git a/components/layout_thread/lib.rs b/components/layout_thread/lib.rs index 04f35183ff4..f9f4c371a94 100644 --- a/components/layout_thread/lib.rs +++ b/components/layout_thread/lib.rs @@ -40,9 +40,10 @@ extern crate script_layout_interface; extern crate script_traits; extern crate selectors; extern crate serde_json; +extern crate servo_config; +extern crate servo_geometry; extern crate servo_url; extern crate style; -extern crate util; extern crate webrender_traits; use app_units::Au; @@ -62,7 +63,8 @@ use ipc_channel::ipc::{self, IpcReceiver, IpcSender}; use ipc_channel::router::ROUTER; use layout::animation; use layout::construct::ConstructionResult; -use layout::context::{LayoutContext, SharedLayoutContext, heap_size_of_local_context}; +use layout::context::{LayoutContext, SharedLayoutContext}; +use layout::context::heap_size_of_persistent_local_context; use layout::display_list_builder::ToGfxColor; use layout::flow::{self, Flow, ImmutableFlowUtils, MutableFlowUtils, MutableOwnedFlowUtils}; use layout::flow_ref::FlowRef; @@ -94,6 +96,10 @@ use script_layout_interface::wrapper_traits::LayoutNode; use script_traits::{ConstellationControlMsg, LayoutControlMsg, LayoutMsg as ConstellationMsg}; use script_traits::{StackingContextScrollState, UntrustedNodeAddress}; use selectors::Element; +use servo_config::opts; +use servo_config::prefs::PREFS; +use servo_config::resource_files::read_resource_file; +use servo_geometry::max_rect; use servo_url::ServoUrl; use std::borrow::ToOwned; use std::collections::HashMap; @@ -103,10 +109,11 @@ use std::process; use std::sync::{Arc, Mutex, MutexGuard}; use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::mpsc::{Receiver, Sender, channel}; +use std::thread; use style::animation::Animation; -use style::context::{LocalStyleContextCreationInfo, ReflowGoal, SharedStyleContext}; +use style::context::{QuirksMode, ReflowGoal, SharedStyleContext, ThreadLocalStyleContextCreationInfo}; use style::data::StoredRestyleHint; -use style::dom::{StylingMode, TElement, TNode}; +use style::dom::{ShowSubtree, ShowSubtreeDataAndPrimaryValues, TElement, TNode}; use style::error_reporting::{ParseErrorReporter, StdoutErrorReporter}; use style::logical_geometry::LogicalPoint; use style::media_queries::{Device, MediaType}; @@ -116,11 +123,7 @@ use style::stylesheets::{Origin, Stylesheet, UserAgentStylesheets}; use style::stylist::Stylist; use style::thread_state; use style::timer::Timer; -use util::geometry::max_rect; -use util::opts; -use util::prefs::PREFS; -use util::resource_files::read_resource_file; -use util::thread; +use style::traversal::DomTraversal; /// Information needed by the layout thread. pub struct LayoutThread { @@ -228,9 +231,12 @@ pub struct LayoutThread { /// only be a test-mode timer during testing for animations. timer: Timer, - // Number of layout threads. This is copied from `util::opts`, but we'd + // Number of layout threads. This is copied from `servo_config::opts`, but we'd // rather limit the dependency on that module here. layout_threads: usize, + + /// Which quirks mode are we rendering the document in? + quirks_mode: Option<QuirksMode> } impl LayoutThreadFactory for LayoutThread { @@ -252,8 +258,7 @@ impl LayoutThreadFactory for LayoutThread { content_process_shutdown_chan: Option<IpcSender<()>>, webrender_api_sender: webrender_traits::RenderApiSender, layout_threads: usize) { - thread::spawn_named(format!("LayoutThread {:?}", id), - move || { + thread::Builder::new().name(format!("LayoutThread {:?}", id)).spawn(move || { thread_state::initialize(thread_state::LAYOUT); if let Some(top_level_frame_id) = top_level_frame_id { @@ -284,7 +289,7 @@ impl LayoutThreadFactory for LayoutThread { if let Some(content_process_shutdown_chan) = content_process_shutdown_chan { let _ = content_process_shutdown_chan.send(()); } - }); + }).expect("Thread spawning failed"); } } @@ -465,7 +470,7 @@ impl LayoutThread { scroll_root_id_response: None, scroll_area_response: Rect::zero(), overflow_response: NodeOverflowResponse(None), - resolved_style_response: None, + resolved_style_response: String::new(), offset_parent_response: OffsetParentResponse::empty(), margin_style_response: MarginStyleResponse::empty(), stacking_context_scroll_offsets: HashMap::new(), @@ -484,6 +489,7 @@ impl LayoutThread { Timer::new() }, layout_threads: layout_threads, + quirks_mode: None, } } @@ -506,20 +512,21 @@ impl LayoutThread { screen_size_changed: bool, goal: ReflowGoal) -> SharedLayoutContext { - let local_style_context_creation_data = LocalStyleContextCreationInfo::new(self.new_animations_sender.clone()); + let thread_local_style_context_creation_data = + ThreadLocalStyleContextCreationInfo::new(self.new_animations_sender.clone()); SharedLayoutContext { style_context: SharedStyleContext { viewport_size: self.viewport_size.clone(), screen_size_changed: screen_size_changed, stylist: rw_data.stylist.clone(), - generation: self.generation, goal: goal, running_animations: self.running_animations.clone(), expired_animations: self.expired_animations.clone(), error_reporter: self.error_reporter.clone(), - local_context_creation_data: Mutex::new(local_style_context_creation_data), + local_context_creation_data: Mutex::new(thread_local_style_context_creation_data), timer: self.timer.clone(), + quirks_mode: self.quirks_mode.unwrap(), }, image_cache_thread: Mutex::new(self.image_cache_thread.clone()), image_cache_sender: Mutex::new(self.image_cache_sender.clone()), @@ -716,11 +723,11 @@ impl LayoutThread { size: stylist.heap_size_of_children(), }); - // The LayoutThread has a context in TLS... + // The LayoutThread has data in Persistent TLS... reports.push(Report { path: path![formatted_url, "layout-thread", "local-context"], kind: ReportKind::ExplicitJemallocHeapSize, - size: heap_size_of_local_context(), + size: heap_size_of_persistent_local_context(), }); reports_chan.send(reports); @@ -960,8 +967,9 @@ impl LayoutThread { self.epoch.next(); let Epoch(epoch_number) = self.epoch; + let viewport_size = webrender_traits::LayoutSize::from_untyped(&viewport_size); self.webrender_api.set_root_display_list( - get_root_flow_background_color(layout_root), + Some(get_root_flow_background_color(layout_root)), webrender_traits::Epoch(epoch_number), viewport_size, builder); @@ -974,6 +982,7 @@ impl LayoutThread { possibly_locked_rw_data: &mut RwData<'a, 'b>) { let document = unsafe { ServoLayoutNode::new(&data.document) }; let document = document.as_document().unwrap(); + self.quirks_mode = Some(document.quirks_mode()); // FIXME(pcwalton): Combine `ReflowGoal` and `ReflowQueryType`. Then remove this assert. debug_assert!((data.reflow_info.goal == ReflowGoal::ForDisplay && @@ -1017,7 +1026,7 @@ impl LayoutThread { rw_data.scroll_root_id_response = None; }, ReflowQueryType::ResolvedStyleQuery(_, _, _) => { - rw_data.resolved_style_response = None; + rw_data.resolved_style_response = String::new(); }, ReflowQueryType::OffsetParentQuery(_) => { rw_data.offset_parent_response = OffsetParentResponse::empty(); @@ -1034,9 +1043,7 @@ impl LayoutThread { debug!("layout: processing reflow request for: {:?} ({}) (query={:?})", element, self.url, data.query_type); - if log_enabled!(log::LogLevel::Debug) { - element.as_node().dump(); - } + debug!("{:?}", ShowSubtree(element.as_node())); let initial_viewport = data.window_size.initial_viewport; let old_viewport_size = self.viewport_size; @@ -1122,7 +1129,7 @@ impl LayoutThread { None => continue, }; let mut style_data = &mut data.base.style_data; - debug_assert!(!style_data.is_restyle()); + debug_assert!(style_data.has_current_styles()); let mut restyle_data = match style_data.restyle() { Some(d) => d, None => continue, @@ -1131,7 +1138,9 @@ impl LayoutThread { // Stash the data on the element for processing by the style system. restyle_data.hint = restyle.hint.into(); restyle_data.damage = restyle.damage; - restyle_data.snapshot = restyle.snapshot; + if let Some(s) = restyle.snapshot { + restyle_data.snapshot.ensure(move || s); + } debug!("Noting restyle for {:?}: {:?}", el, restyle_data); } } @@ -1141,22 +1150,31 @@ impl LayoutThread { viewport_size_changed, data.reflow_info.goal); + // NB: Type inference falls apart here for some reason, so we need to be very verbose. :-( + let traversal = RecalcStyleAndConstructFlows::new(shared_layout_context); let dom_depth = Some(0); // This is always the root node. - if element.styling_mode() != StylingMode::Stop { + let token = { + let stylist = &<RecalcStyleAndConstructFlows as + DomTraversal<ServoLayoutNode>>::shared_context(&traversal).stylist; + <RecalcStyleAndConstructFlows as + DomTraversal<ServoLayoutNode>>::pre_traverse(element, stylist, /* skip_root = */ false) + }; + + if token.should_traverse() { // Recalculate CSS styles and rebuild flows and fragments. profile(time::ProfilerCategory::LayoutStyleRecalc, self.profiler_metadata(), self.time_profiler_chan.clone(), || { // Perform CSS selector matching and flow construction. - if let (true, Some(traversal)) = (self.parallel_flag, self.parallel_traversal.as_mut()) { + if let (true, Some(pool)) = (self.parallel_flag, self.parallel_traversal.as_mut()) { // Parallel mode parallel::traverse_dom::<ServoLayoutNode, RecalcStyleAndConstructFlows>( - element.as_node(), dom_depth, &shared_layout_context, traversal); + &traversal, element, dom_depth, token, pool); } else { // Sequential mode sequential::traverse_dom::<ServoLayoutNode, RecalcStyleAndConstructFlows>( - element.as_node(), &shared_layout_context); + &traversal, element, token); } }); // TODO(pcwalton): Measure energy usage of text shaping, perhaps? @@ -1175,8 +1193,10 @@ impl LayoutThread { self.root_flow = self.try_get_layout_root(element.as_node()); } + shared_layout_context = traversal.destroy(); + if opts::get().dump_style_tree { - element.as_node().dump_style(); + println!("{:?}", ShowSubtreeDataAndPrimaryValues(element.as_node())); } if opts::get().dump_rule_tree { @@ -1201,7 +1221,7 @@ impl LayoutThread { fn respond_to_query_if_necessary(&mut self, query_type: &ReflowQueryType, rw_data: &mut LayoutThreadData, - shared_layout_context: &mut SharedLayoutContext) { + shared: &mut SharedLayoutContext) { let mut root_flow = match self.root_flow.clone() { Some(root_flow) => root_flow, None => return, @@ -1249,10 +1269,9 @@ impl LayoutThread { }, ReflowQueryType::ResolvedStyleQuery(node, ref pseudo, ref property) => { let node = unsafe { ServoLayoutNode::new(&node) }; - let layout_context = LayoutContext::new(&shared_layout_context); rw_data.resolved_style_response = - process_resolved_style_request(node, - &layout_context, + process_resolved_style_request(shared, + node, pseudo, property, root_flow); @@ -1361,7 +1380,7 @@ impl LayoutThread { query_type: Option<&ReflowQueryType>, document: Option<&ServoLayoutDocument>, rw_data: &mut LayoutThreadData, - layout_context: &mut SharedLayoutContext) { + shared: &mut SharedLayoutContext) { if let Some(mut root_flow) = self.root_flow.clone() { // Kick off animations if any were triggered, expire completed ones. animation::update_animation_state(&self.constellation_chan, @@ -1393,7 +1412,7 @@ impl LayoutThread { profile(time::ProfilerCategory::LayoutGeneratedContent, self.profiler_metadata(), self.time_profiler_chan.clone(), - || sequential::resolve_generated_content(FlowRef::deref_mut(&mut root_flow), &layout_context)); + || sequential::resolve_generated_content(FlowRef::deref_mut(&mut root_flow), &shared)); // Guess float placement. profile(time::ProfilerCategory::LayoutFloatPlacementSpeculation, @@ -1416,10 +1435,10 @@ impl LayoutThread { FlowRef::deref_mut(&mut root_flow), profiler_metadata, self.time_profiler_chan.clone(), - &*layout_context); + &*shared); } else { //Sequential mode - LayoutThread::solve_constraints(FlowRef::deref_mut(&mut root_flow), &layout_context) + LayoutThread::solve_constraints(FlowRef::deref_mut(&mut root_flow), &shared) } }); } @@ -1428,8 +1447,8 @@ impl LayoutThread { self.profiler_metadata(), self.time_profiler_chan.clone(), || { - let layout_context = LayoutContext::new(&*layout_context); - sequential::store_overflow(&layout_context, + let context = LayoutContext::new(&shared); + sequential::store_overflow(&context, FlowRef::deref_mut(&mut root_flow) as &mut Flow); }); @@ -1437,7 +1456,7 @@ impl LayoutThread { query_type, document, rw_data, - layout_context); + shared); } } @@ -1538,6 +1557,7 @@ fn get_ua_stylesheets() -> Result<UserAgentStylesheets, &'static str> { None, Origin::UserAgent, Default::default(), + None, Box::new(StdoutErrorReporter), ParserContextExtraData::default())) } @@ -1551,7 +1571,8 @@ fn get_ua_stylesheets() -> Result<UserAgentStylesheets, &'static str> { for &(ref contents, ref url) in &opts::get().user_stylesheets { user_or_user_agent_stylesheets.push(Stylesheet::from_bytes( &contents, url.clone(), None, None, Origin::User, Default::default(), - Box::new(StdoutErrorReporter), ParserContextExtraData::default())); + None, Box::new(StdoutErrorReporter), + ParserContextExtraData::default())); } let quirks_mode_stylesheet = try!(parse_ua_stylesheet("quirks-mode.css")); |