From f6cb6c3b867306b994982e73b11e528a65f065e9 Mon Sep 17 00:00:00 2001 From: Glenn Watson Date: Thu, 24 Sep 2015 10:29:58 +1000 Subject: [PATCH] Ensure that animations expire correctly and stop compositing occurring after they finish. There were two problems here: (1) The animation state update function was only called when nodes were dirty or there were new animations. (2) When all animations for a node expired, the entry from the hash table was not removed. The result was that once an animation began, the compositor would be running as fast as it can forever. Fixes #7721. --- components/layout/animation.rs | 47 +++++++++++++++++------------ components/layout/layout_task.rs | 6 ++-- components/msg/constellation_msg.rs | 2 +- 3 files changed, 32 insertions(+), 23 deletions(-) diff --git a/components/layout/animation.rs b/components/layout/animation.rs index dcb860308ef..863b1eb325a 100644 --- a/components/layout/animation.rs +++ b/components/layout/animation.rs @@ -49,32 +49,41 @@ pub fn start_transitions_if_applicable(new_animations_sender: &Sender } /// Processes any new animations that were discovered after style recalculation. -pub fn process_new_animations(rw_data: &mut LayoutTaskData, pipeline_id: PipelineId) { +/// Also expire any old animations that have completed. +pub fn update_animation_state(rw_data: &mut LayoutTaskData, pipeline_id: PipelineId) { let mut new_running_animations = Vec::new(); while let Ok(animation) = rw_data.new_animations_receiver.try_recv() { new_running_animations.push(animation) } - if !new_running_animations.is_empty() { - let mut running_animations = (*rw_data.running_animations).clone(); - // Expire old running animations. - let now = clock_ticks::precise_time_s(); - for (_, running_animations) in &mut running_animations { - running_animations.retain(|running_animation| now < running_animation.end_time); + let mut running_animations_hash = (*rw_data.running_animations).clone(); + + // Expire old running animations. + let now = clock_ticks::precise_time_s(); + let mut keys_to_remove = Vec::new(); + for (key, running_animations) in &mut running_animations_hash { + running_animations.retain(|running_animation| { + now < running_animation.end_time + }); + if running_animations.len() == 0 { + keys_to_remove.push(*key); } - - // Add new running animations. - for new_running_animation in new_running_animations { - match running_animations.entry(OpaqueNode(new_running_animation.node)) { - Entry::Vacant(entry) => { - entry.insert(vec![new_running_animation]); - } - Entry::Occupied(mut entry) => entry.get_mut().push(new_running_animation), - } - } - - rw_data.running_animations = Arc::new(running_animations); } + for key in keys_to_remove { + running_animations_hash.remove(&key).unwrap(); + } + + // Add new running animations. + for new_running_animation in new_running_animations { + match running_animations_hash.entry(OpaqueNode(new_running_animation.node)) { + Entry::Vacant(entry) => { + entry.insert(vec![new_running_animation]); + } + Entry::Occupied(mut entry) => entry.get_mut().push(new_running_animation), + } + } + + rw_data.running_animations = Arc::new(running_animations_hash); let animation_state; if rw_data.running_animations.is_empty() { diff --git a/components/layout/layout_task.rs b/components/layout/layout_task.rs index 2bf311647c0..82b8a4add46 100644 --- a/components/layout/layout_task.rs +++ b/components/layout/layout_task.rs @@ -1183,9 +1183,6 @@ impl LayoutTask { // Retrieve the (possibly rebuilt) root flow. rw_data.root_flow = self.try_get_layout_root((*node).clone()); - - // Kick off animations if any were triggered. - animation::process_new_animations(&mut *rw_data, self.id); } // Send new canvas renderers to the paint task @@ -1327,6 +1324,9 @@ impl LayoutTask { rw_data: &mut LayoutTaskData, layout_context: &mut SharedLayoutContext) { if let Some(mut root_flow) = rw_data.layout_root() { + // Kick off animations if any were triggered, expire completed ones. + animation::update_animation_state(&mut *rw_data, self.id); + profile(time::ProfilerCategory::LayoutRestyleDamagePropagation, self.profiler_metadata(), self.time_profiler_chan.clone(), diff --git a/components/msg/constellation_msg.rs b/components/msg/constellation_msg.rs index dc42e2deca5..f1cda6b218d 100644 --- a/components/msg/constellation_msg.rs +++ b/components/msg/constellation_msg.rs @@ -275,7 +275,7 @@ pub enum Msg { NodeStatus(Option), } -#[derive(Clone, Eq, PartialEq, Deserialize, Serialize)] +#[derive(Clone, Eq, PartialEq, Deserialize, Serialize, Debug)] pub enum AnimationState { AnimationsPresent, AnimationCallbacksPresent,