This patch moves the additional checks (beyond those of Animation::CanThrottle)
from FlushAnimations/FlushTransitions to AnimationCollection::RequestRestyle.
These checks are on a per-collection basis hence it makes sense for the
collection to perform them. This also moves logic out of the managers which is
needed if we want to support script-based animations without introducing another
manager.
Ultimately we want to move throttling logic to AnimationCollection and
Animation::Tick (and later to KeyframeEffect::SetParentTime). This is so that
we can support script-generated animations without having to introduce yet
another manager.
To that end this patch introduces a method on AnimationCollection that can be
called from Animation::Tick to perform the necessary notifications needed to
update style.
Later in this patch series we will extend RequestRestyle to incorporate more of
the throttling logic and further extend it to cover some of the other
notifications such as updating layers.
This patch tracks whether or not we have already posted a restyle for animation
to avoid making redundant calls. Calls to nsIDocument::SetNeedStyleFlush are
cheap and more difficult to detect when they have completed so we don't filter
redundant calls in the Restyle::Throttled case.
If mHasPendingAnimationRestyle is set and AnimationCommon::EnsureStyleRuleFor
is *never* called then we could arrive at situation where we fail to make post
further restyles for animation.
I have verified that if we fail to reset mHasPendingAnimationRestyle at the
appropriate point (e.g. resetting it at the end of EnsureStyleRuleFor *after*
the early-returns) then a number of existing tests fail.
Furthermore, I have observed that it is reset by the beginning of each tick
in almost every case except for a few instances of browser mochitests such as
browser/components/customizableui/test/browser_1007336_lwthemes_in_customize_mode.js.
In this case, during the async cleanup of the test, we have an opacity
transition on a vbox element that becomes display:none and appears to be skipped
during restyling. However, even in this case, EnsureStyleRuleFor is called
within one or at most two ticks and mHasPendingAnimationRestyle flag is cleared
(i.e. it does not get stuck).
AnimationCollection::HasAnimationOfProperty uses IsFinishedTransition to filter
out transitions that should otherwise be ignored. This is used in the following
places:
1. nsLayoutUtils::HasAnimations
The is only used by nsIFrame::BuildDisplayListForStackingContext to see if
there are any opacity animations
For this case, simply returning *current* animations would be sufficient
(since finished but filling animations should have already filled in the
display opacity)
2. CommonAnimationManager::GetAnimationsForCompositor
This should really only return *current* animations--that is, animations that
are running or scheduled to run. Finished animations never run on the
compositor. Indeed, only *playing* animations run on the compositor but, as
we will see in some of the cases below, it is sometimes useful to know that
an animation *will* run on the compositor in the near future (e.g. so we can
pre-render content).
The places where GetAnimationsForCompositor is used are:
- When building layers to add animations to layers in nsDisplayList--in this
case we skip any animations that aren't playing so if
GetAnimationsForCompositor only returned current animations that would be
more than sufficient.
- In nsLayoutUtils::HasAnimationsForCompositor. This in turn is used:
- In ChooseScaleAndSetTransform to see if the transform is being animated
on the compositor. If so, it calls
nsLayoutUtils::ComputeSuitableScaleForAnimation (which also calls
GetAnimationsForCompositor) and passes the result to
GetMinAndMaxScaleForAnimationProperty which we have already adjusted in
part 4 of this patch series to only deal with *relevant* animations
Relevant animations include both current animations and in effect
animations but we don't run forwards-filling animations on the compositor
so GetAnimationsForCompositor should NOT return them. Current animations
should be enough. In fact, playing animations should be enough but we
might want to pre-render layers at a suitable size during their delay
phase so returning current animations is probably ok.
- In nsDisplayListBuilder::MarkOutOfFlowFrameForDisplay to add a fuzz
factor to the overflow rect for frames undergoing a transform animation
on the compositor. In this case too current animations should be
sufficient.
- In nsDisplayOpacity::NeedsActiveLayer to say "yes" if we are animating
opacity on the compositor. Presumably in this case it would be good to
say "yes" if the animation is in the delay phase too (as it currently
does). After the animation is finished, we should drop the layer, i.e.
current animations should be sufficient.
- In nsDisplayTransform::ShouldPrerenderTransformedContent. As with
nsDisplayOpacity::NeedsActiveLayer, we only need to pre-render
transformed content for animations that are current.
- In nsDisplayTransform::GetLayerState. As with
nsDisplayOpacity::NeedsActiveLayer, we only need to return active here
for current animations.
- In nsIFrame::IsTransformed. Here we test the display style to see if
there is a transform and also check if transform is being animated on the
compositor. As a result, we really only need HasAnimationsForCompositor
to return true for animations that are playing--otherwise the display
style will tell us if we're transformed or not. Returning true for all
current compositor animations (which is a superset of playing), however,
should not cause problems (we already return true for even more than
that).
- In nsIFrame::HasOpacityInternal which is much the same as
nsIFrame::IsTransformed and hence current should be fine.
3. AnimationCollection::CanThrottleAnimation
Here, HasAnimationOfProperty is used when looking for animations that would
disqualify us from throttling the animation by having an out-of-date layer
generation or being a transform animation that affects scroll and so requires
that we do the occasional main thread sample to update scrollbars.
It would seem like current animations are enough here too. One interesting
case is where we *had* a compositor animation but it has finished or been
cancelled. In that case, the animation won't be current and we should not
throttle the animation since we need to take it off its layer.
It turns out checking for current animations is still ok in this case too.
The reasoning is as follows:
- If the animation is newly-finished, we'll pick that up in
Animation::CanThrottle and return false then.
- If the animation is newly-idle then there are two cases:
If the cancelled animation was the only compositor animation then
AnimationCollection::CanPerformOnCompositorThread will notice that there
are no playing compositor animations and return false and
AnimationCollection::CanThrottleAnimation will never be called.
If there are other compositor animations running, then
AnimationCollection::CanThrottleAnimation will still return false because
whatever cancelled the animation will update the animation generation and
we'll notice the mismatch between the layer animation generation and the
animation generation on the collection.
Based on the above analysis it appears that making
AnimationCollection::HasAnimationOfProperty return only current animations (and
simulatneously renaming it to HasCurrentAnimationOfProperty) is safe. Indeed, in
effect, we already do this for transitions but not for animations. This patch
generalizes this behavior to all animations.
This patch also updates test_animations_omta.html since it was incorrectly
testing that a finished opacity animation was still running on the compositor.
Finished animations should not run on the compositor and the changes in this
patch cause that to happen. The reason we don't just update this test to check
for RunningOn.MainThread is that for opacity animations, unlike transform
animations, we can't detect if an opacity on a layer was set by animation or
not. As a result, for opacity animations we typically test the opacity on
either the main thread or compositor in order to allow for the case where an
animation-set opacity is still lingering on the compositor.
Prior to this patch, CSSAnimation defined a method for converting an
nsCSSPseudoElements::Type to a nsString (but only for the set of
pseudo-elements that can have animations). We would like to re-use this
when setting up transition events so this patch moves it to
AnimationCollection. Re-using this method more widely means we can make
a few further simplifications to the code.
The long-term plan is to drop the mozilla::css namespace altogether. Before we
go to much further with refactoring code in AnimationCommon, we should drop
usage of the mozilla::css namespace. Specifically, this patch moves the
CommonAnimationManager and AnimValuesStyleRule classes to the mozilla namespace.
This patch prepares the way for script-generated events by making
event dispatch a separate process that happens after sampling animations.
This will allow us to sample animations from their associated timeline
(removing the need for a further manager to tracker script-generated
animations).
Furthermore, once we sample animations from timelines the order in which they
are sampled is likely to be more or less random so by making event dispatch at
separate step, we have an opportunity to sort the events and dispatch in
a consistent and sensible order. It also ensures that event callbacks will
not be run until all animations (including transitions) have been updated
ensuring they see a consistent view of timing properties.
This patch only affects event handling for CSS animations. Transitions will
be dealt with in a subsequent patch.
Prior to this patch, CSSAnimation defined a method for converting an
nsCSSPseudoElements::Type to a nsString (but only for the set of
pseudo-elements that can have animations). We would like to re-use this
when setting up transition events so this patch moves it to
AnimationCollection. Re-using this method more widely means we can make
a few further simplifications to the code.
The long-term plan is to drop the mozilla::css namespace altogether. Before we
go to much further with refactoring code in AnimationCommon, we should drop
usage of the mozilla::css namespace. Specifically, this patch moves the
CommonAnimationManager and AnimValuesStyleRule classes to the mozilla namespace.
This patch prepares the way for script-generated events by making
event dispatch a separate process that happens after sampling animations.
This will allow us to sample animations from their associated timeline
(removing the need for a further manager to tracker script-generated
animations).
Furthermore, once we sample animations from timelines the order in which they
are sampled is likely to be more or less random so by making event dispatch at
separate step, we have an opportunity to sort the events and dispatch in
a consistent and sensible order. It also ensures that event callbacks will
not be run until all animations (including transitions) have been updated
ensuring they see a consistent view of timing properties.
This patch only affects event handling for CSS animations. Transitions will
be dealt with in a subsequent patch.
We don't currently have a mechanism for rerendering when the front/back
flips, so we should disable running such animations on the compositor
thread for now until we do.
Bug 1186204 covers reenabling.
The reftest fails without the patch (showing a blue almost-square
rectangle), and passes with the patch.
The use of reftest-no-flush (added in patch 1) is needed to achieve the
failure without the patch, because the flushWindow() function in
reftest-content.js calls getBoundingClientRect() to flush rendering,
which has the side-effect of flushing style updates that have been
suppressed on the main thread while we're running an animation off the
main thread, which in turn covers up the bug.
--HG--
rename : layout/reftests/transform-3d/animate-preserve3d-child.html => layout/reftests/transform-3d/animate-backface-hidden.html
The bulk of this commit was generated by running:
run-clang-tidy.py \
-checks='-*,llvm-namespace-comment' \
-header-filter=^/.../mozilla-central/.* \
-fix
Prior to this patch we cancel animations in AnimationCollection::Destroy but
this is not called automatically when the property holding the collection is
destroyed via its destructor. When an element is unbound from the tree we
destroy its animation properties but don't call AnimationCollection::Destroy.
This means, that in such circumstances:
* We won't create animation mutation records for the removed animations
* Once we start registering animations with a timeline they won't have a
chance to remove themselves from the timeline (meaning
document.timeline.getAnimations()) will keep returning them
* Once we go to implement the animationcancel and transitioncancel events we
won't fire them in this case (assuming we implement the queueing/dispatch of
those events as part of the cancel code)
This patch addresses this by moving the call to cancel each animations to the
property destructor for the animation properties.
We do this first so we can land this change separately to ease bisecting any
regressions it might trigger.
--HG--
extra : commitid : KzukSO91RMH
extra : rebase_source : 54ed2aeb69d8bceca424c70c7f33d4bf92d54546
frame->Preserves3D() is whether the frame's parent has transform-style:
preserve-3d, which means that the frame is part of the same 3-D scene as
its parent. frame->Preserves3DChildren() is whether the frame itself
has transform-style: preserve-3d, which means that the frame is part of
the same 3-D scene as its children.
Neither of these are valid cases for doing off-main-thread (OMT)
animation because all of the layers in a preserve-3d scene are currently
siblings of each other, rather than preserving ancestor/descendant
relationships. This means that it's not valid to animate transform of
the parent on the compositor because the compositor animation won't
update any of its children that have layers. Likewise, it's not valid
to animate transform of the child on the compositor because the code
that sends transform information to the compositor doesn't handle the
accumulation of transforms needed to get the "right" transform for the
child (i.e., with the transforms of its ancestors up to the top of the
3-D scene merged in).
This means that we do OMT animation for slightly fewer cases with the
patch than we did without the patch. This means it's pretty low risk in
terms of correctness, although there's a chance it might regress
performance on one of the (somewhat limited) set of cases where the
optimization was valid. (Bug 779598 covers doing OMT animation for
preserve-3d cases, and depends on the work ongoing in bug 1097464.)
The animate-preserve3d-parent.html reftest doesn't fail without the
patch, since something seems to invalidate in the test; it was testing
the testcase that showed correct behavior when the mouse was moving, so
this isn't incredibly surprising (although that invalidation from mouse
movement is itself worth debugging). The animate-preserve3d-child.html
test does fail without the patch, though.
(With an initial transform of none instead of the 30deg transform, both
tests also show an invalidation bug without the patch.)
This patch seems to be leading to too many complications; it requires us
to predict whether a layer that would be created for an element will use
off-main-thread compositing prior to the creation of that layer, which
has led to complications on both Mac (fixed by the other patches in bug
947753) and Android (bug 1161049).
This moves the test for whether off-main-thread compositor is enabled
*earlier* in CanPerformOnCompositorThread, since
CanAnimatePropertyOnCompositor is called only from
CanPerformOnCompositorThread. This change means we're using a more
accurate test for whether we actually have off-main-thread compositing
than the pref, since in some cases we won't use off-main-thread
compositing for certain widgets (e.g., transparent widgets on Windows)
even when the pref is enabled.
--HG--
extra : amend_source : 0f286f6d05a1ebe706c14dba94ae35449ea898c9
This patch is a fairly minimal rename of the AnimationPlayer interface. It
leaves a bunch of local variables and helper classes still using the word
"player". These will be addressed in subsequent patches that don't require DOM
peer review.
--HG--
rename : dom/animation/AnimationPlayer.cpp => dom/animation/Animation.cpp
rename : dom/animation/AnimationPlayer.h => dom/animation/Animation.h
rename : dom/webidl/AnimationPlayer.webidl => dom/webidl/Animation.webidl
The failure was:
TEST-UNEXPECTED-FAIL | gfx/tests/mochitest/test_acceleration.html | Acceleration enabled on x86-64 OS X - didn't expect 0, but got it
I'm guessing this is because we're calling GetLayerManager earlier than
we were before.
CLOSED TREE
This moves the test for whether off-main-thread compositor is enabled
*earlier* in CanPerformOnCompositorThread, since
CanAnimatePropertyOnCompositor is called only from
CanPerformOnCompositorThread. This change means we're using a more
accurate test for whether we actually have off-main-thread compositing
than the pref, since in some cases we won't use off-main-thread
compositing for certain widgets (e.g., transparent widgets on Windows)
even when the pref is enabled.
This patch also tightens up a one or two references to 'target effect' replacing
them with just 'effect'. This is because 'target effect' is longer and easily
confused with 'target element'. 'effect' should be sufficient. 'target element'
is a term from the Web Animations specification and in that context, simply
referring to the 'effect' would sound a little odd.
There are still some other references to "source" in AnimationPlayer such as
HasInPlayerSource and UpdateSourceContent. These are renamed in a subsequent
patch (that doesn't require DOM peer review).
We define KeyframeEffectReadonly in KeyframeEffect.cpp since Web Animations also
defines KeyframeEffect and when we come to implement that I expect we'll define
it in the same class, maybe even using the same object.
This patch also adds a few missing includes in places where
KeyframeEffectReadonly is used so that we're not just cargo-culting it in.
--HG--
rename : dom/animation/Animation.cpp => dom/animation/KeyframeEffect.cpp
rename : dom/animation/Animation.h => dom/animation/KeyframeEffect.h
rename : dom/animation/test/css-animations/test_animation-name.html => dom/animation/test/css-animations/test_effect-name.html
rename : dom/animation/test/css-animations/test_animation-target.html => dom/animation/test/css-animations/test_effect-target.html
rename : dom/animation/test/css-transitions/test_animation-name.html => dom/animation/test/css-transitions/test_effect-name.html
rename : dom/animation/test/css-transitions/test_animation-target.html => dom/animation/test/css-transitions/test_effect-target.html
rename : dom/webidl/Animation.webidl => dom/webidl/KeyframeEffect.webidl
Typically when GetAnimationRule is called, at least for CSS Animations, the
animation style rule will have been refreshed. However, in some cases such as
when the Web Animations API is used, the style rule will be marked as needing
to be refreshed outside of the usual flow. This rule will be refreshed when
nsAnimationManager::WillRefresh flushes animations but if the refresh driver
for the chrome document fires first, we will visit GetAnimationRule before
this happens.
This patch removes the assertion that expects animations to have been
refreshed by the time we reach GetAnimationRule causing it to update
the animation style rule as necessary.
This patch adds an options flag to GetAnimationsForCompositor for two reasons.
a) We want to reuse this functionality in nsLayoutUtils.cpp rather than
duplicating the same logic. To do that and maintain the existing behavior,
however, we need to *not* update the active layer tracker when calling this
from nsLayoutUtils.cpp.
b) It's surprising that GetAnimationsForCompositor also has this side effect of
updating the active layer tracker. Adding this as an option makes it clear at
the call site that this is what will happen.
This saves some extra work that we don't need to do.
Mechanically, the patch moves a chunk of code that is around the last
part of the function and converts it to an early return that's slightly
earlier than that last part, thus also including the skipping of the
throttling checks in what we skip for the early return.
I want to do this here since patch 9 introduces a new call to
EnsureStyleRuleFor.
This avoids some extra work that was added in bug 1125455 now that we
have a mechanism for detecting when animations start and stop being in
effect (introduced in patch 7).
This is also needed to prevent infinite recursion in patch 9.
This does somewhat less work than PostRestyleForAnimation, although I
believe PostRestyleForAnimation would be a sufficient alternative.
This is used in patch 6.