aboutsummaryrefslogtreecommitdiffstats
path: root/components/layout/css
diff options
context:
space:
mode:
authorPatrick Walton <pcwalton@mimiga.net>2015-11-24 19:46:09 -0600
committerPatrick Walton <pcwalton@mimiga.net>2015-11-24 19:50:52 -0600
commite881f0feebeec31582b3fbb848aeeb8b7ed70a32 (patch)
tree203802e309f643e47e4ee0d22c64f87f94bad919 /components/layout/css
parent6f35b867c9c3bb7a345e2ac34e5970b93a1d3ea1 (diff)
downloadservo-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.rs74
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> {