mirror of
https://github.com/servo/servo.git
synced 2025-08-04 13:10:20 +01:00
layout_thread: Don't build the display list for script queries unless
it's needed. Makes cnn.com faster.
This commit is contained in:
parent
83a73a979e
commit
031a4ed6ca
1 changed files with 150 additions and 102 deletions
|
@ -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,47 +932,56 @@ 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)
|
||||||
StackingContextType::Real,
|
.unwrap_or(false);
|
||||||
&Rect::zero(),
|
match (data.goal, display_list_needed) {
|
||||||
&Rect::zero(),
|
(ReflowGoal::ForDisplay, _) | (ReflowGoal::ForScriptQuery, true) => {
|
||||||
0,
|
let mut root_stacking_context =
|
||||||
filter::T::new(Vec::new()),
|
StackingContext::new(StackingContextId::new(0),
|
||||||
mix_blend_mode::T::normal,
|
StackingContextType::Real,
|
||||||
Matrix4D::identity(),
|
&Rect::zero(),
|
||||||
Matrix4D::identity(),
|
&Rect::zero(),
|
||||||
true,
|
0,
|
||||||
false,
|
filter::T::new(Vec::new()),
|
||||||
None);
|
mix_blend_mode::T::normal,
|
||||||
|
Matrix4D::identity(),
|
||||||
|
Matrix4D::identity(),
|
||||||
|
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);
|
||||||
|
|
||||||
debug!("Done building display list.");
|
debug!("Done building display list.");
|
||||||
|
|
||||||
let root_background_color = get_root_flow_background_color(layout_root);
|
let root_background_color = get_root_flow_background_color(layout_root);
|
||||||
let root_size = {
|
let root_size = {
|
||||||
let root_flow = flow::base(layout_root);
|
let root_flow = flow::base(layout_root);
|
||||||
if rw_data.stylist.viewport_constraints().is_some() {
|
if rw_data.stylist.viewport_constraints().is_some() {
|
||||||
root_flow.position.size.to_physical(root_flow.writing_mode)
|
root_flow.position.size.to_physical(root_flow.writing_mode)
|
||||||
} else {
|
} else {
|
||||||
root_flow.overflow.scroll.size
|
root_flow.overflow.scroll.size
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let origin = Rect::new(Point2D::new(Au(0), Au(0)), root_size);
|
||||||
|
root_stacking_context.bounds = origin;
|
||||||
|
root_stacking_context.overflow = origin;
|
||||||
|
root_stacking_context.layer_info =
|
||||||
|
Some(LayerInfo::new(layout_root.layer_id(),
|
||||||
|
ScrollPolicy::Scrollable,
|
||||||
|
None,
|
||||||
|
root_background_color));
|
||||||
|
|
||||||
|
rw_data.display_list =
|
||||||
|
Some(Arc::new(DisplayList::new(root_stacking_context,
|
||||||
|
display_list_entries)))
|
||||||
}
|
}
|
||||||
};
|
(ReflowGoal::ForScriptQuery, false) => {}
|
||||||
|
}
|
||||||
let origin = Rect::new(Point2D::new(Au(0), Au(0)), root_size);
|
|
||||||
root_stacking_context.bounds = origin;
|
|
||||||
root_stacking_context.overflow = origin;
|
|
||||||
root_stacking_context.layer_info =
|
|
||||||
Some(LayerInfo::new(layout_root.layer_id(),
|
|
||||||
ScrollPolicy::Scrollable,
|
|
||||||
None,
|
|
||||||
root_background_color));
|
|
||||||
|
|
||||||
rw_data.display_list =
|
|
||||||
Some(Arc::new(DisplayList::new(root_stacking_context, display_list_entries)))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if data.goal != ReflowGoal::ForDisplay {
|
if data.goal != ReflowGoal::ForDisplay {
|
||||||
|
@ -1230,74 +1243,84 @@ 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,
|
||||||
let root_flow = flow_ref::deref_mut(&mut root_flow);
|
&mut *rw_data,
|
||||||
match data.query_type {
|
&mut shared_layout_context);
|
||||||
ReflowQueryType::ContentBoxQuery(node) => {
|
}
|
||||||
let node = unsafe { ServoLayoutNode::new(&node) };
|
|
||||||
rw_data.content_box_response = process_content_box_request(node, root_flow);
|
|
||||||
},
|
|
||||||
ReflowQueryType::ContentBoxesQuery(node) => {
|
|
||||||
let node = unsafe { ServoLayoutNode::new(&node) };
|
|
||||||
rw_data.content_boxes_response = process_content_boxes_request(node, root_flow);
|
|
||||||
},
|
|
||||||
ReflowQueryType::HitTestQuery(translated_point, client_point, update_cursor) => {
|
|
||||||
let translated_point =
|
|
||||||
Point2D::new(Au::from_f32_px(translated_point.x),
|
|
||||||
Au::from_f32_px(translated_point.y));
|
|
||||||
|
|
||||||
let client_point =
|
fn respond_to_query_if_necessary(&mut self,
|
||||||
Point2D::new(Au::from_f32_px(client_point.x),
|
query_type: &ReflowQueryType,
|
||||||
Au::from_f32_px(client_point.y));
|
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);
|
||||||
|
match *query_type {
|
||||||
|
ReflowQueryType::ContentBoxQuery(node) => {
|
||||||
|
let node = unsafe { ServoLayoutNode::new(&node) };
|
||||||
|
rw_data.content_box_response = process_content_box_request(node, root_flow);
|
||||||
|
},
|
||||||
|
ReflowQueryType::ContentBoxesQuery(node) => {
|
||||||
|
let node = unsafe { ServoLayoutNode::new(&node) };
|
||||||
|
rw_data.content_boxes_response = process_content_boxes_request(node, root_flow);
|
||||||
|
},
|
||||||
|
ReflowQueryType::HitTestQuery(translated_point, client_point, update_cursor) => {
|
||||||
|
let translated_point = Point2D::new(Au::from_f32_px(translated_point.x),
|
||||||
|
Au::from_f32_px(translated_point.y));
|
||||||
|
|
||||||
let result = rw_data.display_list
|
let client_point = Point2D::new(Au::from_f32_px(client_point.x),
|
||||||
.as_ref()
|
Au::from_f32_px(client_point.y));
|
||||||
.expect("Tried to hit test with no display list")
|
|
||||||
.hit_test(&translated_point,
|
let result = rw_data.display_list
|
||||||
&client_point,
|
.as_ref()
|
||||||
&rw_data.stacking_context_scroll_offsets);
|
.expect("Tried to hit test with no display list")
|
||||||
rw_data.hit_test_response = (result.last().cloned(), update_cursor);
|
.hit_test(&translated_point,
|
||||||
},
|
&client_point,
|
||||||
ReflowQueryType::NodeGeometryQuery(node) => {
|
&rw_data.stacking_context_scroll_offsets);
|
||||||
let node = unsafe { ServoLayoutNode::new(&node) };
|
rw_data.hit_test_response = (result.last().cloned(), update_cursor);
|
||||||
rw_data.client_rect_response = process_node_geometry_request(node, root_flow);
|
},
|
||||||
},
|
ReflowQueryType::NodeGeometryQuery(node) => {
|
||||||
ReflowQueryType::NodeScrollGeometryQuery(node) => {
|
let node = unsafe { ServoLayoutNode::new(&node) };
|
||||||
let node = unsafe { ServoLayoutNode::new(&node) };
|
rw_data.client_rect_response = process_node_geometry_request(node, root_flow);
|
||||||
rw_data.scroll_area_response = process_node_scroll_area_request(node, root_flow);
|
},
|
||||||
},
|
ReflowQueryType::NodeScrollGeometryQuery(node) => {
|
||||||
ReflowQueryType::NodeOverflowQuery(node) => {
|
let node = unsafe { ServoLayoutNode::new(&node) };
|
||||||
let node = unsafe { ServoLayoutNode::new(&node) };
|
rw_data.scroll_area_response = process_node_scroll_area_request(node, root_flow);
|
||||||
rw_data.overflow_response = process_node_overflow_request(node);
|
},
|
||||||
},
|
ReflowQueryType::NodeOverflowQuery(node) => {
|
||||||
ReflowQueryType::NodeLayerIdQuery(node) => {
|
let node = unsafe { ServoLayoutNode::new(&node) };
|
||||||
let node = unsafe { ServoLayoutNode::new(&node) };
|
rw_data.overflow_response = process_node_overflow_request(node);
|
||||||
rw_data.layer_id_response = Some(process_node_layer_id_request(node));
|
},
|
||||||
},
|
ReflowQueryType::NodeLayerIdQuery(node) => {
|
||||||
ReflowQueryType::ResolvedStyleQuery(node, ref pseudo, ref property) => {
|
let node = unsafe { ServoLayoutNode::new(&node) };
|
||||||
let node = unsafe { ServoLayoutNode::new(&node) };
|
rw_data.layer_id_response = Some(process_node_layer_id_request(node));
|
||||||
let layout_context = LayoutContext::new(&shared_layout_context);
|
},
|
||||||
rw_data.resolved_style_response =
|
ReflowQueryType::ResolvedStyleQuery(node, ref pseudo, ref property) => {
|
||||||
process_resolved_style_request(node,
|
let node = unsafe { ServoLayoutNode::new(&node) };
|
||||||
&layout_context,
|
let layout_context = LayoutContext::new(&shared_layout_context);
|
||||||
pseudo,
|
rw_data.resolved_style_response =
|
||||||
property,
|
process_resolved_style_request(node,
|
||||||
root_flow);
|
&layout_context,
|
||||||
},
|
pseudo,
|
||||||
ReflowQueryType::OffsetParentQuery(node) => {
|
property,
|
||||||
let node = unsafe { ServoLayoutNode::new(&node) };
|
root_flow);
|
||||||
rw_data.offset_parent_response = process_offset_parent_query(node, root_flow);
|
},
|
||||||
},
|
ReflowQueryType::OffsetParentQuery(node) => {
|
||||||
ReflowQueryType::MarginStyleQuery(node) => {
|
let node = unsafe { ServoLayoutNode::new(&node) };
|
||||||
let node = unsafe { ServoLayoutNode::new(&node) };
|
rw_data.offset_parent_response = process_offset_parent_query(node, root_flow);
|
||||||
rw_data.margin_style_response = process_margin_style_query(node);
|
},
|
||||||
},
|
ReflowQueryType::MarginStyleQuery(node) => {
|
||||||
ReflowQueryType::NoQuery => {}
|
let node = unsafe { ServoLayoutNode::new(&node) };
|
||||||
}
|
rw_data.margin_style_response = process_margin_style_query(node);
|
||||||
|
},
|
||||||
|
ReflowQueryType::NoQuery => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 = {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue