diff options
author | Josh Matthews <josh@joshmatthews.net> | 2014-09-17 19:09:31 -0400 |
---|---|---|
committer | Josh Matthews <josh@joshmatthews.net> | 2014-09-17 19:09:31 -0400 |
commit | 75caade8287bbe9ee25a71bea01e3da6a1d3c1b5 (patch) | |
tree | 69c5dec39e7c212ef25066c2c1b60c720ddc385a | |
parent | 787a68336524fb9585922b9ed319a8b194fb8ee1 (diff) | |
parent | 2bd93ed070e852dda57faf9954af1574060b995d (diff) | |
download | servo-75caade8287bbe9ee25a71bea01e3da6a1d3c1b5.tar.gz servo-75caade8287bbe9ee25a71bea01e3da6a1d3c1b5.zip |
Merge pull request #3358 from jdm/thespicemustnotreflow
Delay initiating layout operations for as long as possible.
-rw-r--r-- | components/script/dom/node.rs | 4 | ||||
-rw-r--r-- | components/script/dom/window.rs | 16 | ||||
-rw-r--r-- | components/script/page.rs | 36 | ||||
-rw-r--r-- | components/script/script_task.rs | 3 |
4 files changed, 46 insertions, 13 deletions
diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs index 8462d652e45..1fb0c52adeb 100644 --- a/components/script/dom/node.rs +++ b/components/script/dom/node.rs @@ -589,7 +589,7 @@ impl<'m, 'n> NodeHelpers<'m, 'n> for JSRef<'n, Node> { let page = window.deref().page(); let addr = self.to_trusted_node_address(); - let ContentBoxResponse(rect) = page.layout_rpc.content_box(addr); + let ContentBoxResponse(rect) = page.layout().content_box(addr); rect } @@ -597,7 +597,7 @@ impl<'m, 'n> NodeHelpers<'m, 'n> for JSRef<'n, Node> { let window = window_from_node(self).root(); let page = window.deref().page(); let addr = self.to_trusted_node_address(); - let ContentBoxesResponse(rects) = page.layout_rpc.content_boxes(addr); + let ContentBoxesResponse(rects) = page.layout().content_boxes(addr); rects } diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs index c201db45dcb..8e89f462f8f 100644 --- a/components/script/dom/window.rs +++ b/components/script/dom/window.rs @@ -19,7 +19,7 @@ use dom::location::Location; use dom::navigator::Navigator; use dom::performance::Performance; use dom::screen::Screen; -use layout_interface::{ReflowForDisplay, DocumentDamageLevel}; +use layout_interface::{ReflowGoal, DocumentDamageLevel}; use page::Page; use script_task::{ExitWindowMsg, FireTimerMsg, ScriptChan, TriggerLoadMsg, TriggerFragmentMsg}; use script_traits::ScriptControlChan; @@ -78,14 +78,14 @@ impl TimerHandle { pub struct Window { eventtarget: EventTarget, pub script_chan: ScriptChan, - control_chan: ScriptControlChan, + pub control_chan: ScriptControlChan, console: Cell<Option<JS<Console>>>, location: Cell<Option<JS<Location>>>, navigator: Cell<Option<JS<Navigator>>>, pub image_cache_task: ImageCacheTask, pub active_timers: Traceable<RefCell<HashMap<TimerId, TimerHandle>>>, next_timer_handle: Traceable<Cell<i32>>, - compositor: Untraceable<Box<ScriptListener>>, + pub compositor: Untraceable<Box<ScriptListener>>, pub browser_context: Traceable<RefCell<Option<BrowserContext>>>, pub page: Rc<Page>, performance: Cell<Option<JS<Performance>>>, @@ -365,6 +365,7 @@ impl Reflectable for Window { pub trait WindowHelpers { fn damage_and_reflow(&self, damage: DocumentDamageLevel); + fn flush_layout(&self, goal: ReflowGoal); fn wait_until_safe_to_modify_dom(&self); fn init_browser_context(&self, doc: &JSRef<Document>); fn load_url(&self, href: DOMString); @@ -397,11 +398,12 @@ impl<'a> WindowHelpers for JSRef<'a, Window> { } fn damage_and_reflow(&self, damage: DocumentDamageLevel) { - // FIXME This should probably be ReflowForQuery, not Display. All queries currently - // currently rely on the display list, which means we can't destroy it by - // doing a query reflow. self.page().damage(damage); - self.page().reflow(ReflowForDisplay, self.control_chan.clone(), *self.compositor); + self.page().avoided_reflows.set(self.page().avoided_reflows.get() + 1); + } + + fn flush_layout(&self, goal: ReflowGoal) { + self.page().flush_layout(goal); } fn wait_until_safe_to_modify_dom(&self) { diff --git a/components/script/page.rs b/components/script/page.rs index eca24e6d814..f2e77ac59fb 100644 --- a/components/script/page.rs +++ b/components/script/page.rs @@ -13,7 +13,7 @@ use dom::document::{Document, DocumentHelpers}; use dom::element::{Element, AttributeHandlers}; use dom::node::{Node, NodeHelpers}; use dom::window::Window; -use layout_interface::{DocumentDamage}; +use layout_interface::{DocumentDamage, ReflowForDisplay}; use layout_interface::{DocumentDamageLevel, HitTestResponse, MouseOverResponse}; use layout_interface::{GetRPCMsg, LayoutChan, LayoutRPC}; use layout_interface::{Reflow, ReflowGoal, ReflowMsg}; @@ -57,7 +57,7 @@ pub struct Page { pub layout_chan: Untraceable<LayoutChan>, /// A handle to perform RPC calls into the layout, quickly. - pub layout_rpc: Untraceable<Box<LayoutRPC>>, + layout_rpc: Untraceable<Box<LayoutRPC>>, /// The port that we will use to join layout. If this is `None`, then layout is not running. pub layout_join_port: Untraceable<RefCell<Option<Receiver<()>>>>, @@ -95,6 +95,9 @@ pub struct Page { /// Number of pending reflows that were sent while layout was active. pub pending_reflows: Cell<int>, + + /// Number of unnecessary potential reflows that were skipped since the last reflow + pub avoided_reflows: Cell<int>, } pub struct PageIterator { @@ -159,9 +162,31 @@ impl Page { constellation_chan: Untraceable::new(constellation_chan), children: Traceable::new(RefCell::new(vec!())), pending_reflows: Cell::new(0), + avoided_reflows: Cell::new(0), + } + } + + pub fn flush_layout(&self, goal: ReflowGoal) { + let damaged = self.damage.borrow().is_some(); + if damaged { + let frame = self.frame(); + let window = frame.get_ref().window.root(); + self.reflow(goal, window.control_chan.clone(), *window.compositor); + } else { + self.avoided_reflows.set(self.avoided_reflows.get() + 1); } } + pub fn layout(&self) -> &LayoutRPC { + // FIXME This should probably be ReflowForQuery, not Display. All queries currently + // currently rely on the display list, which means we can't destroy it by + // doing a query reflow. + self.flush_layout(ReflowForDisplay); + self.join_layout(); //FIXME: is this necessary, or is layout_rpc's mutex good enough? + let layout_rpc: &LayoutRPC = *self.layout_rpc; + layout_rpc + } + // must handle root case separately pub fn remove(&self, id: PipelineId) -> Option<Rc<Page>> { let remove_idx = { @@ -323,6 +348,9 @@ impl Page { match root.root() { None => {}, Some(root) => { + debug!("avoided {:d} reflows", self.avoided_reflows.get()); + self.avoided_reflows.set(0); + debug!("script: performing reflow for goal {:?}", goal); // Now, join the layout so that they will see the latest changes we have made. @@ -393,7 +421,7 @@ impl Page { } let root = root.unwrap(); let root: &JSRef<Node> = NodeCast::from_ref(&*root); - let address = match self.layout_rpc.hit_test(root.to_trusted_node_address(), *point) { + let address = match self.layout().hit_test(root.to_trusted_node_address(), *point) { Ok(HitTestResponse(node_address)) => { Some(node_address) } @@ -414,7 +442,7 @@ impl Page { } let root = root.unwrap(); let root: &JSRef<Node> = NodeCast::from_ref(&*root); - let address = match self.layout_rpc.mouse_over(root.to_trusted_node_address(), *point) { + let address = match self.layout().mouse_over(root.to_trusted_node_address(), *point) { Ok(MouseOverResponse(node_address)) => { Some(node_address) } diff --git a/components/script/script_task.rs b/components/script/script_task.rs index 8dc4578abb8..a1f2cd27b22 100644 --- a/components/script/script_task.rs +++ b/components/script/script_task.rs @@ -687,6 +687,7 @@ impl ScriptTask { // Kick off the initial reflow of the page. debug!("kicking off initial reflow of {}", url); document.deref().content_changed(); + window.flush_layout(ReflowForDisplay); let fragment = url.fragment.as_ref().map(|ref fragment| fragment.to_string()); @@ -716,6 +717,8 @@ impl ScriptTask { Ok(_) => (), Err(_) => println!("evaluate_script failed") } + + window.flush_layout(ReflowForDisplay); } }); |