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.rs75
1 files changed, 39 insertions, 36 deletions
diff --git a/components/layout_thread/lib.rs b/components/layout_thread/lib.rs
index 9d576e3bd02..403f30a96f5 100644
--- a/components/layout_thread/lib.rs
+++ b/components/layout_thread/lib.rs
@@ -232,6 +232,10 @@ pub struct LayoutThread {
/// The timer object to control the timing of the animations. This should
/// 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
+ // rather limit the dependency on that module here.
+ layout_threads: usize,
}
impl LayoutThreadFactory for LayoutThread {
@@ -251,7 +255,8 @@ impl LayoutThreadFactory for LayoutThread {
time_profiler_chan: time::ProfilerChan,
mem_profiler_chan: mem::ProfilerChan,
content_process_shutdown_chan: IpcSender<()>,
- webrender_api_sender: Option<webrender_traits::RenderApiSender>) {
+ webrender_api_sender: Option<webrender_traits::RenderApiSender>,
+ layout_threads: usize) {
thread::spawn_named(format!("LayoutThread {:?}", id),
move || {
thread_state::initialize(thread_state::LAYOUT);
@@ -270,7 +275,8 @@ impl LayoutThreadFactory for LayoutThread {
font_cache_thread,
time_profiler_chan,
mem_profiler_chan.clone(),
- webrender_api_sender);
+ webrender_api_sender,
+ layout_threads);
let reporter_name = format!("layout-reporter-{}", id);
mem_profiler_chan.run_with_memory_reporting(|| {
@@ -381,14 +387,14 @@ impl LayoutThread {
font_cache_thread: FontCacheThread,
time_profiler_chan: time::ProfilerChan,
mem_profiler_chan: mem::ProfilerChan,
- webrender_api_sender: Option<webrender_traits::RenderApiSender>)
+ webrender_api_sender: Option<webrender_traits::RenderApiSender>,
+ layout_threads: usize)
-> LayoutThread {
let device = Device::new(
MediaType::Screen,
opts::get().initial_window_size.as_f32() * ScaleFactor::new(1.0));
- let parallel_traversal = if opts::get().layout_threads != 1 {
- Some(WorkQueue::new("LayoutWorker", thread_state::LAYOUT,
- opts::get().layout_threads))
+ let parallel_traversal = if layout_threads != 1 {
+ Some(WorkQueue::new("LayoutWorker", thread_state::LAYOUT, layout_threads))
} else {
None
};
@@ -479,6 +485,7 @@ impl LayoutThread {
} else {
Timer::new()
},
+ layout_threads: layout_threads,
}
}
@@ -754,7 +761,8 @@ impl LayoutThread {
self.time_profiler_chan.clone(),
self.mem_profiler_chan.clone(),
info.content_process_shutdown_chan,
- self.webrender_api.as_ref().map(|wr| wr.clone_sender()));
+ self.webrender_api.as_ref().map(|wr| wr.clone_sender()),
+ info.layout_threads);
}
/// Enters a quiescent state in which no new messages will be processed until an `ExitNow` is
@@ -961,7 +969,7 @@ impl LayoutThread {
self.epoch.next();
- if opts::get().use_webrender {
+ if let Some(ref mut webrender_api) = self.webrender_api {
// TODO: Avoid the temporary conversion and build webrender sc/dl directly!
let Epoch(epoch_number) = self.epoch;
let epoch = webrender_traits::Epoch(epoch_number);
@@ -971,7 +979,7 @@ impl LayoutThread {
let mut frame_builder = WebRenderFrameBuilder::new(pipeline_id);
let root_scroll_layer_id = frame_builder.next_scroll_layer_id();
let sc_id = rw_data.display_list.as_ref().unwrap().convert_to_webrender(
- &mut self.webrender_api.as_mut().unwrap(),
+ webrender_api,
pipeline_id,
epoch,
Some(root_scroll_layer_id),
@@ -987,16 +995,15 @@ impl LayoutThread {
let viewport_size = Size2D::new(self.viewport_size.width.to_f32_px(),
self.viewport_size.height.to_f32_px());
- let api = self.webrender_api.as_ref().unwrap();
- api.set_root_stacking_context(sc_id,
- root_background_color,
- epoch,
- pipeline_id,
- viewport_size,
- frame_builder.stacking_contexts,
- frame_builder.display_lists,
- frame_builder.auxiliary_lists_builder
- .finalize());
+ webrender_api.set_root_stacking_context(
+ sc_id,
+ root_background_color,
+ epoch,
+ pipeline_id,
+ viewport_size,
+ frame_builder.stacking_contexts,
+ frame_builder.display_lists,
+ frame_builder.auxiliary_lists_builder.finalize());
} else {
self.paint_chan
.send(LayoutToPaintMsg::PaintInit(self.epoch, display_list))
@@ -1097,12 +1104,16 @@ impl LayoutThread {
.unwrap();
}
if data.document_stylesheets.iter().any(|sheet| sheet.dirty_on_viewport_size_change) {
- for node in node.traverse_preorder() {
+ let mut iter = node.traverse_preorder();
+
+ let mut next = iter.next();
+ while let Some(node) = next {
if node.needs_dirty_on_viewport_size_changed() {
- node.dirty_self();
- node.dirty_descendants();
- // TODO(shinglyu): We can skip the traversal if the descendants were already
- // dirtied
+ // NB: The dirty bit is propagated down the tree.
+ unsafe { node.set_dirty(true); }
+ next = iter.next_skipping_children();
+ } else {
+ next = iter.next();
}
}
}
@@ -1114,7 +1125,9 @@ impl LayoutThread {
let needs_reflow = viewport_size_changed && !needs_dirtying;
unsafe {
if needs_dirtying {
- LayoutThread::dirty_all_nodes(node);
+ // NB: The dirty flag is propagated down during the restyle
+ // process.
+ node.set_dirty(true);
}
}
if needs_reflow {
@@ -1158,7 +1171,7 @@ impl LayoutThread {
// TODO(pcwalton): Measure energy usage of text shaping, perhaps?
let text_shaping_time =
(font::get_and_reset_text_shaping_performance_counter() as u64) /
- (opts::get().layout_threads as u64);
+ (self.layout_threads as u64);
time::send_profile_data(time::ProfilerCategory::LayoutTextShaping,
self.profiler_metadata(),
self.time_profiler_chan.clone(),
@@ -1468,16 +1481,6 @@ impl LayoutThread {
}
}
- unsafe fn dirty_all_nodes<N: LayoutNode>(node: N) {
- for node in node.traverse_preorder() {
- // TODO(cgaebel): mark nodes which are sensitive to media queries as
- // "changed":
- // > node.set_changed(true);
- node.set_dirty(true);
- node.set_dirty_descendants(true);
- }
- }
-
fn reflow_all_nodes(flow: &mut Flow) {
debug!("reflowing all nodes!");
flow::mut_base(flow).restyle_damage.insert(REPAINT | STORE_OVERFLOW | REFLOW);