mirror of
https://github.com/servo/servo.git
synced 2025-07-26 00:30:22 +01:00
Auto merge of #5936 - pcwalton:fast-resize, r=jdm
2.1x improvement on resizing on Reddit. r? @jdm <!-- Reviewable:start --> [<img src="https://reviewable.io/review_button.png" height=40 alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/servo/5936) <!-- Reviewable:end -->
This commit is contained in:
commit
bfd1698462
4 changed files with 61 additions and 38 deletions
|
@ -884,11 +884,8 @@ impl LayoutTask {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if needs_reflow {
|
if needs_reflow {
|
||||||
match self.try_get_layout_root(*node) {
|
if let Some(mut flow) = self.try_get_layout_root(*node) {
|
||||||
None => {}
|
LayoutTask::reflow_all_nodes(&mut *flow);
|
||||||
Some(mut flow) => {
|
|
||||||
LayoutTask::reflow_all_nodes(&mut *flow);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -899,28 +896,30 @@ impl LayoutTask {
|
||||||
&self.url,
|
&self.url,
|
||||||
data.reflow_info.goal);
|
data.reflow_info.goal);
|
||||||
|
|
||||||
// Recalculate CSS styles and rebuild flows and fragments.
|
if node.is_dirty() || node.has_dirty_descendants() || rw_data.stylist.is_dirty() {
|
||||||
profile(time::ProfilerCategory::LayoutStyleRecalc,
|
// Recalculate CSS styles and rebuild flows and fragments.
|
||||||
self.profiler_metadata(),
|
profile(time::ProfilerCategory::LayoutStyleRecalc,
|
||||||
self.time_profiler_chan.clone(),
|
self.profiler_metadata(),
|
||||||
|| {
|
self.time_profiler_chan.clone(),
|
||||||
// Perform CSS selector matching and flow construction.
|
|| {
|
||||||
let rw_data = &mut *rw_data;
|
// Perform CSS selector matching and flow construction.
|
||||||
match rw_data.parallel_traversal {
|
let rw_data = &mut *rw_data;
|
||||||
None => {
|
match rw_data.parallel_traversal {
|
||||||
sequential::traverse_dom_preorder(*node, &shared_layout_context);
|
None => {
|
||||||
|
sequential::traverse_dom_preorder(*node, &shared_layout_context);
|
||||||
|
}
|
||||||
|
Some(ref mut traversal) => {
|
||||||
|
parallel::traverse_dom_preorder(*node, &shared_layout_context, traversal);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Some(ref mut traversal) => {
|
});
|
||||||
parallel::traverse_dom_preorder(*node, &shared_layout_context, traversal);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Retrieve the (possibly rebuilt) root flow.
|
// Retrieve the (possibly rebuilt) root flow.
|
||||||
rw_data.root_flow = Some(self.get_layout_root((*node).clone()));
|
rw_data.root_flow = Some(self.get_layout_root((*node).clone()));
|
||||||
|
|
||||||
// Kick off animations if any were triggered.
|
// Kick off animations if any were triggered.
|
||||||
animation::process_new_animations(&mut *rw_data, self.id);
|
animation::process_new_animations(&mut *rw_data, self.id);
|
||||||
|
}
|
||||||
|
|
||||||
// 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,
|
||||||
|
|
|
@ -490,6 +490,7 @@ pub trait WindowHelpers {
|
||||||
fn init_browser_context(self, doc: JSRef<Document>, frame_element: Option<JSRef<Element>>);
|
fn init_browser_context(self, doc: JSRef<Document>, frame_element: Option<JSRef<Element>>);
|
||||||
fn load_url(self, href: DOMString);
|
fn load_url(self, href: DOMString);
|
||||||
fn handle_fire_timer(self, timer_id: TimerId);
|
fn handle_fire_timer(self, timer_id: TimerId);
|
||||||
|
fn force_reflow(self, goal: ReflowGoal, query_type: ReflowQueryType, reason: ReflowReason);
|
||||||
fn reflow(self, goal: ReflowGoal, query_type: ReflowQueryType, reason: ReflowReason);
|
fn reflow(self, goal: ReflowGoal, query_type: ReflowQueryType, reason: ReflowReason);
|
||||||
fn join_layout(self);
|
fn join_layout(self);
|
||||||
fn layout(&self) -> &LayoutRPC;
|
fn layout(&self) -> &LayoutRPC;
|
||||||
|
@ -566,24 +567,19 @@ impl<'a> WindowHelpers for JSRef<'a, Window> {
|
||||||
*self.browser_context.borrow_mut() = None;
|
*self.browser_context.borrow_mut() = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reflows the page if it's possible to do so and the page is dirty. This method will wait
|
/// Reflows the page unconditionally. This method will wait for the layout thread to complete
|
||||||
/// for the layout thread to complete (but see the `TODO` below). If there is no window size
|
/// (but see the `TODO` below). If there is no window size yet, the page is presumed invisible
|
||||||
/// yet, the page is presumed invisible and no reflow is performed.
|
/// and no reflow is performed.
|
||||||
///
|
///
|
||||||
/// TODO(pcwalton): Only wait for style recalc, since we have off-main-thread layout.
|
/// TODO(pcwalton): Only wait for style recalc, since we have off-main-thread layout.
|
||||||
fn reflow(self, goal: ReflowGoal, query_type: ReflowQueryType, reason: ReflowReason) {
|
fn force_reflow(self, goal: ReflowGoal, query_type: ReflowQueryType, reason: ReflowReason) {
|
||||||
let document = self.Document().root();
|
let document = self.Document().root();
|
||||||
let root = document.r().GetDocumentElement().root();
|
let root = document.r().GetDocumentElement().root();
|
||||||
let root = match root.r() {
|
let root = match root.r() {
|
||||||
Some(root) => root,
|
Some(root) => root,
|
||||||
None => return,
|
None => return,
|
||||||
};
|
};
|
||||||
|
|
||||||
let root: JSRef<Node> = NodeCast::from_ref(root);
|
let root: JSRef<Node> = NodeCast::from_ref(root);
|
||||||
if query_type == ReflowQueryType::NoQuery && !root.get_has_dirty_descendants() {
|
|
||||||
debug!("root has no dirty descendants; avoiding reflow (reason {:?})", reason);
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
let window_size = match self.window_size.get() {
|
let window_size = match self.window_size.get() {
|
||||||
Some(window_size) => window_size,
|
Some(window_size) => window_size,
|
||||||
|
@ -642,6 +638,28 @@ impl<'a> WindowHelpers for JSRef<'a, Window> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Reflows the page if it's possible to do so and the page is dirty. This method will wait
|
||||||
|
/// for the layout thread to complete (but see the `TODO` below). If there is no window size
|
||||||
|
/// yet, the page is presumed invisible and no reflow is performed.
|
||||||
|
///
|
||||||
|
/// TODO(pcwalton): Only wait for style recalc, since we have off-main-thread layout.
|
||||||
|
fn reflow(self, goal: ReflowGoal, query_type: ReflowQueryType, reason: ReflowReason) {
|
||||||
|
let document = self.Document().root();
|
||||||
|
let root = document.r().GetDocumentElement().root();
|
||||||
|
let root = match root.r() {
|
||||||
|
Some(root) => root,
|
||||||
|
None => return,
|
||||||
|
};
|
||||||
|
|
||||||
|
let root: JSRef<Node> = NodeCast::from_ref(root);
|
||||||
|
if query_type == ReflowQueryType::NoQuery && !root.get_has_dirty_descendants() {
|
||||||
|
debug!("root has no dirty descendants; avoiding reflow (reason {:?})", reason);
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
self.force_reflow(goal, query_type, reason)
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME(cgaebel): join_layout is racey. What if the compositor triggers a
|
// FIXME(cgaebel): join_layout is racey. What if the compositor triggers a
|
||||||
// reflow between the "join complete" message and returning from this
|
// reflow between the "join complete" message and returning from this
|
||||||
// function?
|
// function?
|
||||||
|
|
|
@ -820,7 +820,7 @@ impl ScriptTask {
|
||||||
let window = inner_page.window().root();
|
let window = inner_page.window().root();
|
||||||
if window.r().set_page_clip_rect_with_new_viewport(rect) {
|
if window.r().set_page_clip_rect_with_new_viewport(rect) {
|
||||||
let page = get_page(page, id);
|
let page = get_page(page, id);
|
||||||
self.force_reflow(&*page, ReflowReason::Viewport);
|
self.rebuild_and_force_reflow(&*page, ReflowReason::Viewport);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -884,7 +884,7 @@ impl ScriptTask {
|
||||||
|
|
||||||
let needed_reflow = page.set_reflow_status(false);
|
let needed_reflow = page.set_reflow_status(false);
|
||||||
if needed_reflow {
|
if needed_reflow {
|
||||||
self.force_reflow(&*page, ReflowReason::CachedPageNeededReflow);
|
self.rebuild_and_force_reflow(&*page, ReflowReason::CachedPageNeededReflow);
|
||||||
}
|
}
|
||||||
|
|
||||||
let window = page.window().root();
|
let window = page.window().root();
|
||||||
|
@ -1200,8 +1200,8 @@ impl ScriptTask {
|
||||||
self.compositor.borrow_mut().scroll_fragment_point(pipeline_id, LayerId::null(), point);
|
self.compositor.borrow_mut().scroll_fragment_point(pipeline_id, LayerId::null(), point);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reflows non-incrementally.
|
/// Reflows non-incrementally, rebuilding the entire layout tree in the process.
|
||||||
fn force_reflow(&self, page: &Page, reason: ReflowReason) {
|
fn rebuild_and_force_reflow(&self, page: &Page, reason: ReflowReason) {
|
||||||
let document = page.document().root();
|
let document = page.document().root();
|
||||||
document.r().dirty_all_nodes();
|
document.r().dirty_all_nodes();
|
||||||
let window = window_from_node(document.r()).root();
|
let window = window_from_node(document.r()).root();
|
||||||
|
@ -1322,7 +1322,9 @@ impl ScriptTask {
|
||||||
let page = get_page(&self.root_page(), pipeline_id);
|
let page = get_page(&self.root_page(), pipeline_id);
|
||||||
let window = page.window().root();
|
let window = page.window().root();
|
||||||
window.r().set_window_size(new_size);
|
window.r().set_window_size(new_size);
|
||||||
self.force_reflow(&*page, ReflowReason::WindowResize);
|
window.r().force_reflow(ReflowGoal::ForDisplay,
|
||||||
|
ReflowQueryType::NoQuery,
|
||||||
|
ReflowReason::WindowResize);
|
||||||
|
|
||||||
let document = page.document().root();
|
let document = page.document().root();
|
||||||
let fragment_node = window.r().steal_fragment_name()
|
let fragment_node = window.r().steal_fragment_name()
|
||||||
|
|
|
@ -251,6 +251,10 @@ impl Stylist {
|
||||||
|
|
||||||
shareable
|
shareable
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_dirty(&self) -> bool {
|
||||||
|
self.is_dirty
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct PerOriginSelectorMap {
|
struct PerOriginSelectorMap {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue