diff options
author | Patrick Walton <pcwalton@mimiga.net> | 2015-11-24 19:46:09 -0600 |
---|---|---|
committer | Patrick Walton <pcwalton@mimiga.net> | 2015-11-24 19:50:52 -0600 |
commit | e881f0feebeec31582b3fbb848aeeb8b7ed70a32 (patch) | |
tree | 203802e309f643e47e4ee0d22c64f87f94bad919 /components/layout/css | |
parent | 6f35b867c9c3bb7a345e2ac34e5970b93a1d3ea1 (diff) | |
download | servo-e881f0feebeec31582b3fbb848aeeb8b7ed70a32.tar.gz servo-e881f0feebeec31582b3fbb848aeeb8b7ed70a32.zip |
Write animated values into the `ComputedValues` structures when
animations complete or are interrupted.
This adds a new pair of reader-writer locks. I measured the performance
of style recalculation on Wikipedia and the overhead of the locks was
not measurable.
Closes #7816.
Diffstat (limited to 'components/layout/css')
-rw-r--r-- | components/layout/css/matching.rs | 74 |
1 files changed, 58 insertions, 16 deletions
diff --git a/components/layout/css/matching.rs b/components/layout/css/matching.rs index fc5e7aadb14..4d969e00fd8 100644 --- a/components/layout/css/matching.rs +++ b/components/layout/css/matching.rs @@ -414,6 +414,10 @@ trait PrivateMatchMethods { shareable: bool, animate_properties: bool) -> RestyleDamage; + fn update_animations_for_cascade(&self, + layout_context: &SharedLayoutContext, + style: &mut Option<Arc<ComputedValues>>) + -> bool; } trait PrivateElementMatchMethods { @@ -435,20 +439,12 @@ impl<'ln> PrivateMatchMethods for ServoLayoutNode<'ln> { shareable: bool, animate_properties: bool) -> RestyleDamage { - // Finish any transitions. + let mut cacheable = true; if animate_properties { - if let Some(ref mut style) = *style { - let this_opaque = self.opaque(); - if let Some(ref animations) = layout_context.running_animations.get(&this_opaque) { - for animation in *animations { - animation.property_animation.update(&mut *Arc::make_mut(style), 1.0); - } - } - } + cacheable = !self.update_animations_for_cascade(layout_context, style) && cacheable; } let mut this_style; - let cacheable; match parent_style { Some(ref parent_style) => { let cache_entry = applicable_declarations_cache.find(applicable_declarations); @@ -461,7 +457,7 @@ impl<'ln> PrivateMatchMethods for ServoLayoutNode<'ln> { shareable, Some(&***parent_style), cached_computed_values); - cacheable = is_cacheable; + cacheable = cacheable && is_cacheable; this_style = the_style } None => { @@ -470,7 +466,7 @@ impl<'ln> PrivateMatchMethods for ServoLayoutNode<'ln> { shareable, None, None); - cacheable = is_cacheable; + cacheable = cacheable && is_cacheable; this_style = the_style } }; @@ -479,10 +475,12 @@ impl<'ln> PrivateMatchMethods for ServoLayoutNode<'ln> { // it did trigger a transition. if animate_properties { if let Some(ref style) = *style { - animation::start_transitions_if_applicable(new_animations_sender, - self.opaque(), - &**style, - &mut this_style); + let animations_started = + animation::start_transitions_if_applicable(new_animations_sender, + self.opaque(), + &**style, + &mut this_style); + cacheable = cacheable && !animations_started } } @@ -500,6 +498,50 @@ impl<'ln> PrivateMatchMethods for ServoLayoutNode<'ln> { *style = Some(this_style); damage } + + fn update_animations_for_cascade(&self, + layout_context: &SharedLayoutContext, + style: &mut Option<Arc<ComputedValues>>) + -> bool { + let style = match *style { + None => return false, + Some(ref mut style) => style, + }; + + // Finish any expired transitions. + let this_opaque = self.opaque(); + let had_animations_to_expire; + { + let all_expired_animations = layout_context.expired_animations.read().unwrap(); + let animations_to_expire = all_expired_animations.get(&this_opaque); + had_animations_to_expire = animations_to_expire.is_some(); + if let Some(ref animations) = animations_to_expire { + for animation in *animations { + animation.property_animation.update(&mut *Arc::make_mut(style), 1.0); + } + } + } + + if had_animations_to_expire { + layout_context.expired_animations.write().unwrap().remove(&this_opaque); + } + + // Merge any running transitions into the current style, and cancel them. + let had_running_animations = layout_context.running_animations + .read() + .unwrap() + .get(&this_opaque) + .is_some(); + if had_running_animations { + let mut all_running_animations = layout_context.running_animations.write().unwrap(); + for running_animation in all_running_animations.get(&this_opaque).unwrap() { + animation::update_style_for_animation(running_animation, style, None); + } + all_running_animations.remove(&this_opaque); + } + + had_animations_to_expire || had_running_animations + } } impl<'ln> PrivateElementMatchMethods for ServoLayoutElement<'ln> { |