layout_thread: Don't build the display list for script queries unless

it's needed.

Makes cnn.com faster.
This commit is contained in:
Patrick Walton 2016-09-20 16:19:31 -07:00
parent 83a73a979e
commit 031a4ed6ca

View file

@ -65,7 +65,7 @@ use layout::animation;
use layout::construct::ConstructionResult; use layout::construct::ConstructionResult;
use layout::context::{LayoutContext, SharedLayoutContext, heap_size_of_local_context}; use layout::context::{LayoutContext, SharedLayoutContext, heap_size_of_local_context};
use layout::display_list_builder::ToGfxColor; use layout::display_list_builder::ToGfxColor;
use layout::flow::{self, Flow, ImmutableFlowUtils, MutableOwnedFlowUtils}; use layout::flow::{self, Flow, ImmutableFlowUtils, MutableFlowUtils, MutableOwnedFlowUtils};
use layout::flow_ref::{self, FlowRef}; use layout::flow_ref::{self, FlowRef};
use layout::incremental::{LayoutDamageComputation, REFLOW_ENTIRE_DOCUMENT}; use layout::incremental::{LayoutDamageComputation, REFLOW_ENTIRE_DOCUMENT};
use layout::layout_debug; use layout::layout_debug;
@ -630,6 +630,7 @@ impl LayoutThread {
reflow_info.goal); reflow_info.goal);
self.perform_post_style_recalc_layout_passes(&reflow_info, self.perform_post_style_recalc_layout_passes(&reflow_info,
None,
None, None,
&mut *rw_data, &mut *rw_data,
&mut layout_context); &mut layout_context);
@ -901,8 +902,11 @@ impl LayoutThread {
traversal); traversal);
} }
/// Computes the stacking-relative positions of all flows and, if the painting is dirty and the
/// reflow goal and query type need it, builds the display list.
fn compute_abs_pos_and_build_display_list(&mut self, fn compute_abs_pos_and_build_display_list(&mut self,
data: &Reflow, data: &Reflow,
query_type: Option<&ReflowQueryType>,
document: Option<&ServoLayoutDocument>, document: Option<&ServoLayoutDocument>,
layout_root: &mut Flow, layout_root: &mut Flow,
shared_layout_context: &mut SharedLayoutContext, shared_layout_context: &mut SharedLayoutContext,
@ -928,7 +932,12 @@ impl LayoutThread {
if flow::base(layout_root).restyle_damage.contains(REPAINT) || if flow::base(layout_root).restyle_damage.contains(REPAINT) ||
rw_data.display_list.is_none() { rw_data.display_list.is_none() {
let mut root_stacking_context = StackingContext::new(StackingContextId::new(0), let display_list_needed = query_type.map(reflow_query_type_needs_display_list)
.unwrap_or(false);
match (data.goal, display_list_needed) {
(ReflowGoal::ForDisplay, _) | (ReflowGoal::ForScriptQuery, true) => {
let mut root_stacking_context =
StackingContext::new(StackingContextId::new(0),
StackingContextType::Real, StackingContextType::Real,
&Rect::zero(), &Rect::zero(),
&Rect::zero(), &Rect::zero(),
@ -968,7 +977,11 @@ impl LayoutThread {
root_background_color)); root_background_color));
rw_data.display_list = rw_data.display_list =
Some(Arc::new(DisplayList::new(root_stacking_context, display_list_entries))) Some(Arc::new(DisplayList::new(root_stacking_context,
display_list_entries)))
}
(ReflowGoal::ForScriptQuery, false) => {}
}
} }
if data.goal != ReflowGoal::ForDisplay { if data.goal != ReflowGoal::ForDisplay {
@ -1230,13 +1243,26 @@ impl LayoutThread {
// Perform post-style recalculation layout passes. // Perform post-style recalculation layout passes.
self.perform_post_style_recalc_layout_passes(&data.reflow_info, self.perform_post_style_recalc_layout_passes(&data.reflow_info,
Some(&data.query_type),
Some(&document), Some(&document),
&mut rw_data, &mut rw_data,
&mut shared_layout_context); &mut shared_layout_context);
if let Some(mut root_flow) = self.root_flow.clone() { self.respond_to_query_if_necessary(&data.query_type,
&mut *rw_data,
&mut shared_layout_context);
}
fn respond_to_query_if_necessary(&mut self,
query_type: &ReflowQueryType,
rw_data: &mut LayoutThreadData,
shared_layout_context: &mut SharedLayoutContext) {
let mut root_flow = match self.root_flow.clone() {
Some(root_flow) => root_flow,
None => return,
};
let root_flow = flow_ref::deref_mut(&mut root_flow); let root_flow = flow_ref::deref_mut(&mut root_flow);
match data.query_type { match *query_type {
ReflowQueryType::ContentBoxQuery(node) => { ReflowQueryType::ContentBoxQuery(node) => {
let node = unsafe { ServoLayoutNode::new(&node) }; let node = unsafe { ServoLayoutNode::new(&node) };
rw_data.content_box_response = process_content_box_request(node, root_flow); rw_data.content_box_response = process_content_box_request(node, root_flow);
@ -1246,12 +1272,10 @@ impl LayoutThread {
rw_data.content_boxes_response = process_content_boxes_request(node, root_flow); rw_data.content_boxes_response = process_content_boxes_request(node, root_flow);
}, },
ReflowQueryType::HitTestQuery(translated_point, client_point, update_cursor) => { ReflowQueryType::HitTestQuery(translated_point, client_point, update_cursor) => {
let translated_point = let translated_point = Point2D::new(Au::from_f32_px(translated_point.x),
Point2D::new(Au::from_f32_px(translated_point.x),
Au::from_f32_px(translated_point.y)); Au::from_f32_px(translated_point.y));
let client_point = let client_point = Point2D::new(Au::from_f32_px(client_point.x),
Point2D::new(Au::from_f32_px(client_point.x),
Au::from_f32_px(client_point.y)); Au::from_f32_px(client_point.y));
let result = rw_data.display_list let result = rw_data.display_list
@ -1299,7 +1323,6 @@ impl LayoutThread {
ReflowQueryType::NoQuery => {} ReflowQueryType::NoQuery => {}
} }
} }
}
fn set_visible_rects<'a, 'b>(&mut self, fn set_visible_rects<'a, 'b>(&mut self,
new_visible_rects: Vec<(LayerId, Rect<Au>)>, new_visible_rects: Vec<(LayerId, Rect<Au>)>,
@ -1353,7 +1376,11 @@ impl LayoutThread {
false, false,
reflow_info.goal); reflow_info.goal);
self.perform_post_main_layout_passes(&reflow_info, None, &mut *rw_data, &mut layout_context); self.perform_post_main_layout_passes(&reflow_info,
None,
None,
&mut *rw_data,
&mut layout_context);
true true
} }
@ -1411,6 +1438,7 @@ impl LayoutThread {
} }
self.perform_post_style_recalc_layout_passes(&reflow_info, self.perform_post_style_recalc_layout_passes(&reflow_info,
None,
None, None,
&mut *rw_data, &mut *rw_data,
&mut layout_context); &mut layout_context);
@ -1434,6 +1462,7 @@ impl LayoutThread {
return return
} }
self.perform_post_style_recalc_layout_passes(&reflow_info, self.perform_post_style_recalc_layout_passes(&reflow_info,
None,
None, None,
&mut *rw_data, &mut *rw_data,
&mut layout_context); &mut layout_context);
@ -1441,6 +1470,7 @@ impl LayoutThread {
fn perform_post_style_recalc_layout_passes(&mut self, fn perform_post_style_recalc_layout_passes(&mut self,
data: &Reflow, data: &Reflow,
query_type: Option<&ReflowQueryType>,
document: Option<&ServoLayoutDocument>, document: Option<&ServoLayoutDocument>,
rw_data: &mut LayoutThreadData, rw_data: &mut LayoutThreadData,
layout_context: &mut SharedLayoutContext) { layout_context: &mut SharedLayoutContext) {
@ -1516,18 +1546,24 @@ impl LayoutThread {
flow_ref::deref_mut(&mut root_flow) as &mut Flow); flow_ref::deref_mut(&mut root_flow) as &mut Flow);
}); });
self.perform_post_main_layout_passes(data, document, rw_data, layout_context); self.perform_post_main_layout_passes(data,
query_type,
document,
rw_data,
layout_context);
} }
} }
fn perform_post_main_layout_passes(&mut self, fn perform_post_main_layout_passes(&mut self,
data: &Reflow, data: &Reflow,
query_type: Option<&ReflowQueryType>,
document: Option<&ServoLayoutDocument>, document: Option<&ServoLayoutDocument>,
rw_data: &mut LayoutThreadData, rw_data: &mut LayoutThreadData,
layout_context: &mut SharedLayoutContext) { layout_context: &mut SharedLayoutContext) {
// Build the display list if necessary, and send it to the painter. // Build the display list if necessary, and send it to the painter.
if let Some(mut root_flow) = self.root_flow.clone() { if let Some(mut root_flow) = self.root_flow.clone() {
self.compute_abs_pos_and_build_display_list(data, self.compute_abs_pos_and_build_display_list(data,
query_type,
document, document,
flow_ref::deref_mut(&mut root_flow), flow_ref::deref_mut(&mut root_flow),
&mut *layout_context, &mut *layout_context,
@ -1645,6 +1681,18 @@ fn get_ua_stylesheets() -> Result<UserAgentStylesheets, &'static str> {
}) })
} }
/// Returns true if the given reflow query type needs a full, up-to-date display list to be present
/// or false if it only needs stacking-relative positions.
fn reflow_query_type_needs_display_list(query_type: &ReflowQueryType) -> bool {
match *query_type {
ReflowQueryType::HitTestQuery(..) => true,
ReflowQueryType::ContentBoxQuery(_) | ReflowQueryType::ContentBoxesQuery(_) |
ReflowQueryType::NodeGeometryQuery(_) | ReflowQueryType::NodeScrollGeometryQuery(_) |
ReflowQueryType::NodeOverflowQuery(_) | ReflowQueryType::NodeLayerIdQuery(_) |
ReflowQueryType::ResolvedStyleQuery(..) | ReflowQueryType::OffsetParentQuery(_) |
ReflowQueryType::MarginStyleQuery(_) | ReflowQueryType::NoQuery => false,
}
}
lazy_static! { lazy_static! {
static ref UA_STYLESHEETS: UserAgentStylesheets = { static ref UA_STYLESHEETS: UserAgentStylesheets = {