As a result, transitions are now stored using a pointer to the base class,
mozilla::ElementAnimation. We downcast to a transition only when necessary. No
error-checking of the result of AsTransition is performed since we only ever
call it on the mAnimations member of ElementTransitions.
Add a method for downcasting from an ElementAnimation to an
ElementPropertyTransition (when the underlying object is an
ElementPropertyTransition).
This, unfortunately, adds a vtable to ElementAnimation but in the long term
I hope we will be able to isolate transition-specific code to a specific kind of
TransitionEffect that hangs off ElementAnimation and put the vtable on
AnimationEffect instead. (The AnimationEffect concept is part of the Web
Animations API.)
We currently have mozilla::StyleAnimation as well as nsStyleAnimation. This
patch renames StyleAnimation back to ElementAnimation.
Although ElementAnimation is very similar to ElementAnimations, in the near
future we expect to retire ElementAnimations and replace it with a common
AnimationSet-like structure that is covers the features of ElementAnimations and
ElementTransitions.
This patch takes StyleAnimation and makes it ref-counted heap object. This
should allow us to store StyleAnimation and its subclasses (transitions only
currently) in a consistent fashion (an array of base-class pointers).
Furthermore, this will be helpful if we want these things to be pointed to
from Javascript objects that may, for example, preserve their lifetime beyond
that of the element that currently owns them.
This patch also introduces a typedef for an array of refptrs to StyleAnimation
objects (and similarly for the subclass ElementPropertyTransition) to simplify
the code somewhat.
We need a basic representation of animations from which we can derive subclasses
to represent specific cases such as transitions. For now we will retrofit
ElementAnimation for that purpose hence renaming it to StyleAnimation.
This patch removes the "using namespace mozilla::layers" line from
AnimationCommon.cpp since the unified build system concatenates several files
together before compiling making using declarations like this leak into other
files potentially creating ambiguities. Previously, when we were calling
ElementAnimation, 'Animation', there were ambiguities between
mozilla::layers::Animation and this new 'Animation' class. In general, it is
probably a good idea to limit the scope of these using declarations so I've kept
that change.
This patch relocates ElementAnimation from nsAnimationManager.{h,cpp} to
AnimationCommon.{h,cpp} and in the process moves it into the mozilla::css
namespace.
Both ElementPropertyTransition and ElementAnimation specify an IsRunningAt
method which have the same purpose but with two subtle differences:
a) ElementPropertyTransition::IsRunningAt checks if the transition is a removed
sentinel and if so returns false. This patch adds a check for a null start time
to IsRunningAt since I think in future we will want to allow null times in
various places to represent, for example, animations that are not connected to
a timeline. (However, ultimately we will probably not allow start times on
*animations* to be null, only on their associated player.)
Should we later use a different mechanism for marking sentinel transitions (e.g.
a boolean flag) this method should still be correct as it checks if aTime is
inside the transition interval before returning true.
b) ElementPropertyTransition::IsRunningAt returns false if the transition is in
the delay phase, that is, waiting to start. This patch changes this behavior so
that transitions are considered running even if they are in the delay phase.
This brings their behavior into line with animations and removes the need for
the ElementPropertyTransition::mIsRunningOnCompositor since it is only used to
determine when a transition in the delay phase has begun.
ElementAnimation::IsRunningAt also handles pause state and iterations but this
logic should still be correct for transitions which, in this area, only use
a subset of the functionality of animations since their pause state is always
playing and their iteration count is 1.
As part of moving towards more shared data structures for animation, this patch
makes ElementPropertyTransition inherit from ElementAnimation. At the same time
we switch from storing the target property, start/end values, start time, delay,
and timing function on the transition to the corresponding location in
ElementAnimation.
Since nsDisplayList::AddAnimationsAndTransitionsToLayer was already doing this
conversion in order to create animations to pass to the compositor thread, we
can remove the conversion code from there and just use the ElementAnimation data
structures as-is.
A number of assertions are added to verify that transitions are set up as
expected (namely, they have only a single property-animation with a single
segment). As we move to more generic handling of animations and transitions
these assertions should disappear.
As a first step towards making CSS animations and CSS transitions use the same
data structures, this patch aligns their behavior with regards to start time and
delay handling.
Previously, ElementAnimation objects maintained separate mStartTime and mDelay
members whilst ElementPropertyTransition objects maintained a single mStartTime
property that incorporated the delay. This patch adds an mDelay member to
ElementPropertyTransition and stores the delay and start time separately.
Calculations involving ElementPropertyTransition::mStartTime are adjusted to
incorporate mDelay.
This changes the behavior of the CanPerformOnCompositorThread methods of
both ElementAnimations and ElementTransitions to check that the
respective animations or transitions are actually running. This is ok
because:
- The main caller is nsLayoutUtils::HasAnimationsForCompositor, and all
of its callers pretty clearly want the more restricted behavior (they're
concerned with layer activity)
- The only other callers of these functions are
nsAnimationManager::FlushAnimations and
nsTransitionManager::FlushTransitions (determining when to do
throttling), nsAnimationManager::GetAnimationsForCompositor (whose
only caller,
nsDisplayListBuilder::AddAnimationsAndTransitionsToLayer, also checks
IsRunningAt). I think these also all want or are fine with having
the IsRunningAt check.
As to the actual changes:
- In the animation manager, I think it's a mistake that
ElementAnimation::IsRunningAt didn't already check
mIterationDuration, since we throw out animations with a bad
iteration-duration in ElementAnimations::EnsureStyleRuleFor. So this
makes that change as well.
- In the transition manager, IsRunningAt already checks
!IsRemovedSentinel().
I've confirmed in gdb on a device that this fixes the repeated
nsIFrame::SchedulePaint calls that were the symptom of this bug.
I believe this patch also makes it so that a short animation of a
property that can't be animated on the compositor doesn't prevent the
entire duration of the animation of a property that can from being
throttled (having the main thread style updates suppressed).
The CalcStyleDifference call is absolutely necessary even if we didn't
need to process the change list, because it causes the new style
context to have cached structs that we might need for a later
comparison. This is important because, as an optimization, we only
compare structs that have been retrieved. This optimization requires
that when we replace a style context, we fetch all the structs on the
new style context that had been fetched on the old style context (which
is normally necessary anyway in order to do comparison so we can process
the changes appropriately).
However, actually processing the change list is also necessary to fix
the bug; it's the actual change from the miniflush that matters here.
Based on dholbert's debugging information, I think it's mostly likely
because we were failing to process the UpdateOverflow hint.