aboutsummaryrefslogtreecommitdiffstats
path: root/components/layout_thread/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'components/layout_thread/lib.rs')
-rw-r--r--components/layout_thread/lib.rs107
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"));