diff options
Diffstat (limited to 'components/script/dom')
-rw-r--r-- | components/script/dom/document.rs | 26 |
1 files changed, 22 insertions, 4 deletions
diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs index b7e7cf47cfb..866b698687d 100644 --- a/components/script/dom/document.rs +++ b/components/script/dom/document.rs @@ -201,6 +201,11 @@ pub struct Document { /// List of animation frame callbacks #[ignore_heap_size_of = "closures are hard"] animation_frame_list: DOMRefCell<BTreeMap<u32, Box<FnBox(f64)>>>, + /// Whether we're in the process of running animation callbacks. + /// + /// Tracking this is not necessary for correctness. Instead, it is an optimization to avoid + /// sending needless `ChangeRunningAnimationsState` messages to the compositor. + running_animation_callbacks: Cell<bool>, /// Tracks all outstanding loads related to this document. loader: DOMRefCell<DocumentLoader>, /// The current active HTML parser, to allow resuming after interruptions. @@ -1281,11 +1286,20 @@ impl Document { self.animation_frame_ident.set(ident); self.animation_frame_list.borrow_mut().insert(ident, callback); + // No need to send a `ChangeRunningAnimationsState` if we're running animation callbacks: + // we're guaranteed to already be in the "animation callbacks present" state. + // + // This reduces CPU usage by avoiding needless thread wakeups in the common case of + // repeated rAF. + // // TODO: Should tick animation only when document is visible - let ConstellationChan(ref chan) = *self.window.constellation_chan(); - let event = ConstellationMsg::ChangeRunningAnimationsState(self.window.pipeline(), - AnimationState::AnimationCallbacksPresent); - chan.send(event).unwrap(); + if !self.running_animation_callbacks.get() { + let ConstellationChan(ref chan) = *self.window.constellation_chan(); + let event = ConstellationMsg::ChangeRunningAnimationsState( + self.window.pipeline(), + AnimationState::AnimationCallbacksPresent); + chan.send(event).unwrap(); + } ident } @@ -1305,6 +1319,7 @@ impl Document { pub fn run_the_animation_frame_callbacks(&self) { let animation_frame_list = mem::replace(&mut *self.animation_frame_list.borrow_mut(), BTreeMap::new()); + self.running_animation_callbacks.set(true); let performance = self.window.Performance(); let performance = performance.r(); let timing = performance.Now(); @@ -1324,6 +1339,8 @@ impl Document { chan.send(event).unwrap(); } + self.running_animation_callbacks.set(false); + self.window.reflow(ReflowGoal::ForDisplay, ReflowQueryType::NoQuery, ReflowReason::RequestAnimationFrame); @@ -1676,6 +1693,7 @@ impl Document { scripting_enabled: Cell::new(browsing_context.is_some()), animation_frame_ident: Cell::new(0), animation_frame_list: DOMRefCell::new(BTreeMap::new()), + running_animation_callbacks: Cell::new(false), loader: DOMRefCell::new(doc_loader), current_parser: Default::default(), reflow_timeout: Cell::new(None), |