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.
This commit is contained in:
Patrick Walton 2015-11-24 19:46:09 -06:00
parent 6f35b867c9
commit e881f0feeb
5 changed files with 134 additions and 56 deletions

View file

@ -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> {