mirror of
https://github.com/servo/servo.git
synced 2025-08-03 20:50:07 +01:00
Auto merge of #10021 - pcwalton:skip-layout-traversals, r=mbrubeck
layout: Skip layout traversals that obviously won't do anything. This reduces CPU usage when mousing over simple pages (example.com). More complex pages (Wikipedia) still reflow a lot due to other bugs. Additionally, this change causes Servo to stop painting the results of hit test queries. This is also a win for CPU usage. This significantly improves #9999, though there's more that can be done. I'll leave it open in case @paulrouget thinks this PR isn't enough. r? @mbrubeck <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="35" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/10021) <!-- Reviewable:end -->
This commit is contained in:
commit
9813d11f86
4 changed files with 71 additions and 56 deletions
|
@ -167,7 +167,8 @@ pub fn compute_damage(old: Option<&Arc<ComputedValues>>, new: &ComputedValues) -
|
||||||
[ REPAINT ], [
|
[ REPAINT ], [
|
||||||
get_color.color, get_background.background_color,
|
get_color.color, get_background.background_color,
|
||||||
get_border.border_top_color, get_border.border_right_color,
|
get_border.border_top_color, get_border.border_right_color,
|
||||||
get_border.border_bottom_color, get_border.border_left_color
|
get_border.border_bottom_color, get_border.border_left_color,
|
||||||
|
get_effects.transform, get_box.z_index
|
||||||
]);
|
]);
|
||||||
|
|
||||||
add_if_not_equal!(old, new, damage,
|
add_if_not_equal!(old, new, damage,
|
||||||
|
@ -252,7 +253,6 @@ impl<'a> LayoutDamageComputation for &'a mut Flow {
|
||||||
has_counter_affecting_children = has_counter_affecting_children ||
|
has_counter_affecting_children = has_counter_affecting_children ||
|
||||||
flow::base(kid).flags.intersects(AFFECTS_COUNTERS |
|
flow::base(kid).flags.intersects(AFFECTS_COUNTERS |
|
||||||
HAS_COUNTER_AFFECTING_CHILDREN);
|
HAS_COUNTER_AFFECTING_CHILDREN);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,8 @@ use gfx::font_context;
|
||||||
use gfx::paint_thread::LayoutToPaintMsg;
|
use gfx::paint_thread::LayoutToPaintMsg;
|
||||||
use gfx_traits::{color, Epoch, LayerId, ScrollPolicy};
|
use gfx_traits::{color, Epoch, LayerId, ScrollPolicy};
|
||||||
use heapsize::HeapSizeOf;
|
use heapsize::HeapSizeOf;
|
||||||
use incremental::{LayoutDamageComputation, REFLOW, REFLOW_ENTIRE_DOCUMENT, REPAINT};
|
use incremental::{LayoutDamageComputation, REFLOW, REFLOW_ENTIRE_DOCUMENT, REFLOW_OUT_OF_FLOW};
|
||||||
|
use incremental::{REPAINT};
|
||||||
use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
|
use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
|
||||||
use ipc_channel::router::ROUTER;
|
use ipc_channel::router::ROUTER;
|
||||||
use layout_debug;
|
use layout_debug;
|
||||||
|
@ -869,26 +870,27 @@ impl LayoutThread {
|
||||||
flow::mut_base(flow_ref::deref_mut(layout_root)).clip =
|
flow::mut_base(flow_ref::deref_mut(layout_root)).clip =
|
||||||
ClippingRegion::from_rect(&data.page_clip_rect);
|
ClippingRegion::from_rect(&data.page_clip_rect);
|
||||||
|
|
||||||
let mut root_stacking_context =
|
if flow::base(&**layout_root).restyle_damage.contains(REPAINT) ||
|
||||||
StackingContext::new(StackingContextId::new(0),
|
rw_data.display_list.is_none() {
|
||||||
StackingContextType::Real,
|
let mut root_stacking_context =
|
||||||
&Rect::zero(),
|
StackingContext::new(StackingContextId::new(0),
|
||||||
&Rect::zero(),
|
StackingContextType::Real,
|
||||||
0,
|
&Rect::zero(),
|
||||||
filter::T::new(Vec::new()),
|
&Rect::zero(),
|
||||||
mix_blend_mode::T::normal,
|
0,
|
||||||
Matrix4::identity(),
|
filter::T::new(Vec::new()),
|
||||||
Matrix4::identity(),
|
mix_blend_mode::T::normal,
|
||||||
true,
|
Matrix4::identity(),
|
||||||
false,
|
Matrix4::identity(),
|
||||||
None);
|
true,
|
||||||
|
false,
|
||||||
|
None);
|
||||||
|
|
||||||
let display_list_entries =
|
let display_list_entries =
|
||||||
sequential::build_display_list_for_subtree(layout_root,
|
sequential::build_display_list_for_subtree(layout_root,
|
||||||
&mut root_stacking_context,
|
&mut root_stacking_context,
|
||||||
shared_layout_context);
|
shared_layout_context);
|
||||||
|
|
||||||
if data.goal == ReflowGoal::ForDisplay {
|
|
||||||
debug!("Done building display list.");
|
debug!("Done building display list.");
|
||||||
|
|
||||||
let root_background_color = get_root_flow_background_color(
|
let root_background_color = get_root_flow_background_color(
|
||||||
|
@ -905,13 +907,20 @@ impl LayoutThread {
|
||||||
let origin = Rect::new(Point2D::new(Au(0), Au(0)), root_size);
|
let origin = Rect::new(Point2D::new(Au(0), Au(0)), root_size);
|
||||||
root_stacking_context.bounds = origin;
|
root_stacking_context.bounds = origin;
|
||||||
root_stacking_context.overflow = origin;
|
root_stacking_context.overflow = origin;
|
||||||
root_stacking_context.layer_info = Some(LayerInfo::new(layout_root.layer_id(),
|
root_stacking_context.layer_info =
|
||||||
ScrollPolicy::Scrollable,
|
Some(LayerInfo::new(layout_root.layer_id(),
|
||||||
None,
|
ScrollPolicy::Scrollable,
|
||||||
root_background_color));
|
None,
|
||||||
|
root_background_color));
|
||||||
|
|
||||||
|
rw_data.display_list =
|
||||||
|
Some(Arc::new(DisplayList::new(root_stacking_context,
|
||||||
|
&mut Some(display_list_entries))))
|
||||||
|
}
|
||||||
|
|
||||||
|
if data.goal == ReflowGoal::ForDisplay {
|
||||||
|
let display_list = (*rw_data.display_list.as_ref().unwrap()).clone();
|
||||||
|
|
||||||
let display_list = DisplayList::new(root_stacking_context,
|
|
||||||
&mut Some(display_list_entries));
|
|
||||||
if opts::get().dump_display_list {
|
if opts::get().dump_display_list {
|
||||||
display_list.print();
|
display_list.print();
|
||||||
}
|
}
|
||||||
|
@ -919,9 +928,6 @@ impl LayoutThread {
|
||||||
println!("{}", serde_json::to_string_pretty(&display_list).unwrap());
|
println!("{}", serde_json::to_string_pretty(&display_list).unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
let display_list = Arc::new(display_list);
|
|
||||||
rw_data.display_list = Some(display_list.clone());
|
|
||||||
|
|
||||||
debug!("Layout done!");
|
debug!("Layout done!");
|
||||||
|
|
||||||
self.epoch.next();
|
self.epoch.next();
|
||||||
|
@ -942,10 +948,13 @@ impl LayoutThread {
|
||||||
epoch,
|
epoch,
|
||||||
Some(root_scroll_layer_id),
|
Some(root_scroll_layer_id),
|
||||||
&mut auxiliary_lists_builder);
|
&mut auxiliary_lists_builder);
|
||||||
let root_background_color = webrender_traits::ColorF::new(root_background_color.r,
|
let root_background_color = get_root_flow_background_color(
|
||||||
root_background_color.g,
|
flow_ref::deref_mut(layout_root));
|
||||||
root_background_color.b,
|
let root_background_color =
|
||||||
root_background_color.a);
|
webrender_traits::ColorF::new(root_background_color.r,
|
||||||
|
root_background_color.g,
|
||||||
|
root_background_color.b,
|
||||||
|
root_background_color.a);
|
||||||
|
|
||||||
let viewport_size = Size2D::new(self.viewport_size.width.to_f32_px(),
|
let viewport_size = Size2D::new(self.viewport_size.width.to_f32_px(),
|
||||||
self.viewport_size.height.to_f32_px());
|
self.viewport_size.height.to_f32_px());
|
||||||
|
@ -1323,26 +1332,28 @@ impl LayoutThread {
|
||||||
|
|
||||||
// Perform the primary layout passes over the flow tree to compute the locations of all
|
// Perform the primary layout passes over the flow tree to compute the locations of all
|
||||||
// the boxes.
|
// the boxes.
|
||||||
profile(time::ProfilerCategory::LayoutMain,
|
if flow::base(&*root_flow).restyle_damage.intersects(REFLOW | REFLOW_OUT_OF_FLOW) {
|
||||||
self.profiler_metadata(),
|
profile(time::ProfilerCategory::LayoutMain,
|
||||||
self.time_profiler_chan.clone(),
|
self.profiler_metadata(),
|
||||||
|| {
|
self.time_profiler_chan.clone(),
|
||||||
let profiler_metadata = self.profiler_metadata();
|
|| {
|
||||||
match self.parallel_traversal {
|
let profiler_metadata = self.profiler_metadata();
|
||||||
None => {
|
match self.parallel_traversal {
|
||||||
// Sequential mode.
|
None => {
|
||||||
LayoutThread::solve_constraints(&mut root_flow, &layout_context)
|
// Sequential mode.
|
||||||
|
LayoutThread::solve_constraints(&mut root_flow, &layout_context)
|
||||||
|
}
|
||||||
|
Some(ref mut parallel) => {
|
||||||
|
// Parallel mode.
|
||||||
|
LayoutThread::solve_constraints_parallel(parallel,
|
||||||
|
&mut root_flow,
|
||||||
|
profiler_metadata,
|
||||||
|
self.time_profiler_chan.clone(),
|
||||||
|
&*layout_context);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Some(ref mut parallel) => {
|
});
|
||||||
// Parallel mode.
|
}
|
||||||
LayoutThread::solve_constraints_parallel(parallel,
|
|
||||||
&mut root_flow,
|
|
||||||
profiler_metadata,
|
|
||||||
self.time_profiler_chan.clone(),
|
|
||||||
&*layout_context);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
profile(time::ProfilerCategory::LayoutStoreOverflow,
|
profile(time::ProfilerCategory::LayoutStoreOverflow,
|
||||||
self.profiler_metadata(),
|
self.profiler_metadata(),
|
||||||
|
|
|
@ -234,6 +234,6 @@ impl<'a> BuildDisplayList<'a> {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn should_process(&self) -> bool {
|
fn should_process(&self) -> bool {
|
||||||
self.state.layout_context.shared_context().goal == ReflowGoal::ForDisplay
|
true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1021,7 +1021,11 @@ impl Window {
|
||||||
|
|
||||||
debug!("script: layout joined");
|
debug!("script: layout joined");
|
||||||
|
|
||||||
self.pending_reflow_count.set(0);
|
// Pending reflows require display, so only reset the pending reflow count if this reflow
|
||||||
|
// was to be displayed.
|
||||||
|
if goal == ReflowGoal::ForDisplay {
|
||||||
|
self.pending_reflow_count.set(0);
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(marker) = marker {
|
if let Some(marker) = marker {
|
||||||
self.emit_timeline_marker(marker.end());
|
self.emit_timeline_marker(marker.end());
|
||||||
|
@ -1104,7 +1108,7 @@ impl Window {
|
||||||
|
|
||||||
pub fn hit_test_query(&self, hit_test_request: Point2D<f32>, update_cursor: bool)
|
pub fn hit_test_query(&self, hit_test_request: Point2D<f32>, update_cursor: bool)
|
||||||
-> Option<UntrustedNodeAddress> {
|
-> Option<UntrustedNodeAddress> {
|
||||||
self.reflow(ReflowGoal::ForDisplay,
|
self.reflow(ReflowGoal::ForScriptQuery,
|
||||||
ReflowQueryType::HitTestQuery(hit_test_request, update_cursor),
|
ReflowQueryType::HitTestQuery(hit_test_request, update_cursor),
|
||||||
ReflowReason::Query);
|
ReflowReason::Query);
|
||||||
self.layout_rpc.hit_test().node_address
|
self.layout_rpc.hit_test().node_address
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue