WebIDL referes to KeyframeEffect::SetFrames(), which is derived from
KeyframeEffectReadOnly::SetFrames() in terms of implementation.
In addition, make KeyframeEffectReadOnly::ConstructKeyframeEffect call
KeyframeEffectReadOnly::SetFrames() to simplify the code.
MozReview-Commit-ID: 7ASbtoN7Tnp
--HG--
extra : rebase_source : c398ff7154c4533255f56c7ca13314e440eb6258
Add KeyframeEffectReadOnly::mTiming into the list of cycle collection to
avoid any possible memory leak.
MozReview-Commit-ID: C5mFQ7TsqC7
--HG--
extra : rebase_source : 8ee1e58d69a3becb0b8566fa3529154bb66d3064
Use the current document as the parent object of
AnimationEffectTiming(ReadOnly).
MozReview-Commit-ID: JfPLk95hsJ1
--HG--
extra : rebase_source : ee068d0eb8e26f4c1e83b87049be8060fcd27813
It turns out that std::stable_sort on Mac and Android use this.
Bug 1263500 tracks doing something more efficient on those platforms.
MozReview-Commit-ID: 3tGbnoW67QP
This is needed in order to use std::stable_sort with this type since some
implementations of std::stable_sort require this (as opposed to simply a move
constructor).
MozReview-Commit-ID: 5QmcIxkC4aB
Before switching CSS animations over to using KeyframeEffectReadOnly::SetFrames
we update the getFrames() API to return the set frame objects (when available)
so that we can test that we are setting the correct frames.
MozReview-Commit-ID: 4SpBRM7Ykyv
Earlier in this patch series we divided keyframe processing into two stages:
(1) Turning javascript objects into an array of Keyframe objects
(2) Calculating AnimationProperty arrays from the Keyframe objects
This patch creates a SetFrames method so that CSS animations and
CSS transitions can skip (1) and pass the frames constructed from CSS syntax
into (2).
It also adds the following additional processing:
a. Notifying animation mutation observers when the set of frames has changed.
This is currently performed by nsAnimationManager but ultimately we should
encapsulate this logic inside the effect itself. Furthermore, it will be
needed when we implement effect.setFrames() (i.e. the Javascript-facing
wrapper for this method).
b. Preserving the mWinsInCascade and mIsRunningOnCompositor state on properties
when updating them.
This is currently performed by:
bool KeyframeEffectReadOnly::UpdateProperties(
const InfallibleTArray<AnimationProperty>& aProperties)
which is what nsAnimationManager currently uses. We will ultimately remove
the above method and here we are just moving this code to the new version
of UpdateProperties.
c. Requesting a restyle when the set of AnimationProperty objects has changed.
Again, this is currently performed by the existing UpdateProperties method
so we are just moving it here. This behavior will also be required when
we implement effect.setFrames() and when we call UpdateProperties from
elsewhere in restyling code.
This is bug 1235002 but we fix it here and leave that bug to just do further
cleanup work (e.g. re-instating the check for an empty property set before
requesting a restyle in NotifyAnimationTimingUpdated).
d. Marking the cascade as needing an update when the set of AnimationProperty
objects has changed.
This is in preparation for calling UpdateProperties from elsewhere in
restyling (e.g. when the nsStyleContext is updated).
MozReview-Commit-ID: 2ll26lsWZTm
In KeyframeEffectReadOnly::ComposeStyle we call StyleAnimationValue::Interpolate
but assume that it always passes. That was true when that code was only used for
CSS animations and CSS transitions since they check that their animation values
can be interpolated before setting up segments.
However, when we set up animations using the Web Animations API we don't perform
that check so it is possible for this call to fail.
In that case, we could just bail, but, according to CSS Transitions we should
apply a 50% switch in this case:
https://drafts.csswg.org/css-transitions/#step-types
(In Web Animations, specifying this is an open issue. See:
https://w3c.github.io/web-animations/#specific-animation-behaviors).
Bug 1064937 tracks doing this in general (we'll likely need to mark various
properties as being no longer unanimatable but instead as supporting discrete
animation) but we can start to introduce it now.
Later in bug 1245748, CSS animations and transitions will likely start using
the same code path as the Web Animations API for setting up keyframes.
As a result, unless we take care to add checks that the values we set are
interpolable, the 50% switch behavior will begin to apply to CSS animations and
transitions too at that point.
Some concerns have been raised about possible web compatibility issues around
the 50% switch behavior (see [1] and [2]). For CSS animations, Chrome already
supports this behavior so it should be ok at least for CSS animations.
When we switch CSS transitions over to the same code path, however, we will need
to be careful to add checks that the transition endpoints are interpolable
(we can investigate introducing this behavior to transitions as a separate bug
that can be easily backed out / preffed off).
Regarding the naming of the test added here, going forward we would like to
restructure the tests under web-platform-tests to better match the structure of
the Web Animations since that seems to be the convention there.
However, this doesn't *quite* match the structure of the spec since there are
upcoming changes to the spec in this area (e.g. renaming animation behaviors to
animation types). However, it should be close enough that we don't have to move
it around too much in future.
[1] https://drafts.csswg.org/css-transitions/#step-types
[2] https://bugzilla.mozilla.org/show_bug.cgi?id=1064937#c0
MozReview-Commit-ID: KcxILrckJg9
In the next patch in this series, we would like to update the error handling of
the call to StyleAnimationValue::Interpolate in
KeyframeEffectReadOnly::ComposeStyle. Using AnimValuesStyleRule::AddEmptyValue
there, however, makes handling the error case difficult because we need a means
of clearing the allocated StyleAnimationValue.
However, simply using AnimationValuesStyleRule::AddValue means we will end up
doing needless allocations for StyleAnimationValue objects (the copy
constructor for which can result in performing potentially expensive heap
allocations, such as when lists are deep-copied).
Instead, we add a Move constructor to StyleAnimationValue and add an overload
of AnimValuesStyleRule::AddValue that takes an rvalue reference. This
provides a more consistent interface to AnimValuesStyleRule and avoids the
unnecessary allocations from copying StyleAnimationValue objects.
MozReview-Commit-ID: CaP1uPAgNnm
In promise chains, we don't have to use t.step_func. However, when there
are callbacks in promise chains, assertions in the callbacks need wrapped
in either t.step or t.step_func.
If we use t.step_func, a variable scope might be divided. This can be a
problem when an assertion uses local-scope variable (e.g. the callback
in MutationObserver uses an assertion which take `changedAnimation`).
Therefore, t.step is helpful in this case.
(There no t.step_func we should remove in web-platform tests.)
MozReview-Commit-ID: IiSizgCQjpG
--HG--
extra : rebase_source : bfe314c20763d0ea26127dd561c64388d6431bf3
Previously, every test and support file would be synced to the objdir
when running any test. Now that only those support files and tests requested
are synced, we note support files required beyond those in a test's
directory in ini manifests.
MozReview-Commit-ID: EmlDz9d4lqt
In some of these cases, this increase isn't strictly necessary, because we only
check state immediately after creating the animation, before it could have
completed (regardless of its duration). Still: we should consistently use long
durations for any animations that aren't expected to complete during the test
run, because short durations might accidentally get copypasted into new tests
where they might cause intermittent failures.
MozReview-Commit-ID: 8wSRqHMI12L
--HG--
extra : rebase_source : 12e6a054dce047351b06e064bcedd9cdec58150f
I have confirmed that by adding this, we end up calling SwapElements() on the
mPropertyValues member when we build up the nsTArray<Keyframe> result in
GetKeyframeListFromPropertyIndexedKeyframe. Without this explicit move
constructor (i.e. with only the default move constructor) the copy-constructor
for mPropertyValues is called.
MozReview-Commit-ID: 6IWkP97RFUr
--HG--
extra : rebase_source : 4ac4b6545337810a3047f2cfb1dac86074116cfb
StyleAnimationValue::ComputeValue(s) will automatically look up the style
context of the supplied element. This is mostly fine, but when we start using
this method in scenarios where we are building the initial style context
(as happens later in this patch series) it can easily land us in a situation
where we iterate indefinitely.
It would be better, instead, to just explicitly pass in the style context we
want to use, as we already do for StyleAnimationValue::ExtractComputedValue.
MozReview-Commit-ID: ZoVBlBRRBI
--HG--
extra : rebase_source : 9012cc2e405fc887f070fbfaa2f9853289882862
Once we tweak moz.build in the next patch, the grouping in the unified build
will change and expose these missing includes so we fix them here, first.
MozReview-Commit-ID: GebEEociwTo
--HG--
extra : rebase_source : 18158fdf8a3c1a1dcf446118371cad1a15fd4daf
Specifically, for the 'composite' member on keyframes, we now indicate "use the
composite value specified on the effect" using a missing/undefined 'composite'
member as opposed to a null value.
MozReview-Commit-ID: ZH45GvCTlP
--HG--
extra : rebase_source : 5acf081fb844f81280765a87ec019b7847ca1885
Before we begin re-arranging KeyframeEffect.h we move ComputedTiming aside
since putting it in a separate file should make navigating the source
easier.
MozReview-Commit-ID: L5GTFAo00sh
--HG--
extra : rebase_source : e88b6ea092c459afa90831de8469697454e00c5a
Add tests in test_animation_observers.html, so we can test elements and pseudo
elements together by setting subtree.
--HG--
extra : rebase_source : 1841d5db93657a07772bc73ce99cb6ab2a43a737
We use the parent element of a pseudo element as the subject to be notified.
Usage:
We record animations targeting to pseudo elements by setting subtree attribute
to true.
MutationObserver(Node, { subtree: ture });
So all the animations targeting to the pseudo elements whose parentElement is
the first argument will be recorded.
--HG--
extra : rebase_source : 3dc87802b65c74c3e5f2ed4504652ba14465fc02
Use NonOwningAnimationTarget as the returned type of
1. KeyframeEffectReadOnly::GetTarget()
2. nsNodeUtils::GetTargetForAnimation(...)
--HG--
extra : rebase_source : 3b0e117528035329fdf4bdbee127f095b710805a
NonOwningAnimationTarget is a struct made of two members:
1. mozilla::dom::Element*
2. mozilla::CSSPseudoElementType
--HG--
extra : rebase_source : df7ecf192c14f1973b064ffe8a31618df2e6955d
At the same time we also make the 'warning' member of AnimationPropertyDetails
no longer nullable and simply use the absence of the member to indicate "no
warning" (which is what we were already doing -- we were never actually setting
it to null).
MozReview-Commit-ID: HdRDbqhCdmw
--HG--
extra : rebase_source : 0282bd9f0e213aa0e1ed1f5b25d58b10fb3dbc0b
extra : histedit_source : 7d1f81dc57e2a55ab0ed6c4919a25b87819d9d58
I think the reason we originally didn't do this is that the
"isRunningOnCompositor" status might be misleading for animations that are
being overridden. That is, there are some animations we don't send to the
compositor because they are being overridden by another animation (e.g. a
CSS animation touching the 'transform' animation will cause a CSS transition
on the same property not to run, despite the fact that transitions apply
higher in the cascade). This is not merely a performance optimization but means
we don't have to do the cascade on the compositor.
In the future, once we introduce additive animation, we won't be able to handle
this so simply since it an animation will be able to be partially overridden.
Instead, consumers of this API will need to look at the 'composite' member of
the various animation values to see if an animation is being fully or partially
overridden.
As a result, this API really should return all running animations, even if they
are currently being overridden.
MozReview-Commit-ID: DwmbXdCqF32
--HG--
extra : rebase_source : 14e5412015b6c2c7ec6b7e105d414a89fc746c77
We are now extending this API to include more than just metadata about each
animated property but also the property values themselves.
Note that we can't use the name AnimationProperty for the dictionary since
we already use that name internally and [BinaryName] doesn't seem to apply to
dictionaries.
MozReview-Commit-ID: AcXeN4fsgTz
--HG--
extra : rebase_source : 714fdf85484775244daad6aaa288b1ec73ad6793
This better matches the order in the WebIDL and, once we rename
GetPropertyState to GetProperties it will make sense for GetFrames and
GetProperties to be side-by-side.
MozReview-Commit-ID: 67s9WGksPFv
--HG--
extra : rebase_source : f38ea60c0fec2f063126a0aa73422230189afbf5
Later in this patch series when we convert tests from web-platform tests to
mochitest-chrome tests, some of the test cases that use zero-length segments
(overlapping keyframes at certain offsets) would trigger failed assertions
in KeyframeEffectReadOnly::ComposeStyle. This is because this method was
originally written with CSS animations in mind where segments cannot be
zero-length. Furthermore, when these same tests cases are run as
web-platform-tests, the failed assertions are not visible.
This patch adjusts the handling of segments to allow zero-length segments and
adds a test to check that the handling matches that defined in Web Animations
which is summarized in the following informative note,
"this procedure permits overlapping keyframes. The behavior is that at the
point of overlap the output value jumps to the value of the last defined
keyframe at that offset. For overlapping frames at 0 or 1, the output value
for iteration progress values less than 0 or greater than or equal to 1 is the
value of the first keyframe or the last keyframe in keyframes
respectively."[1]
[1] https://w3c.github.io/web-animations/#the-effect-value-of-a-keyframe-animation-effect
MozReview-Commit-ID: JdyYbGZtbot
--HG--
extra : rebase_source : 00502ec8aec423196376e29bf4b70ef0ff178e29
The type name has been changed and re-ordered.
MozReview-Commit-ID: 78jrJ6a9Pro
--HG--
extra : rebase_source : f47e6bf27d8e48d10b3af123308c2ab89e71d8e1
As well as generally simplifying the different KeyframeEffect(ReadOnly)
constructor methods, this patch also means we will use the realm document for
parsing timing functions in all cases. Although this currently doesn't have
any impact (the current set of timing functions are expected to be parsed
identically regardless of the document used) it may become significant if, in
future, it becomes possible to register hooks with certain documents for
parsing CSS properties as part of the houdini efforts.
MozReview-Commit-ID: 4gAZi1G1uAD
--HG--
extra : rebase_source : f619592a02ddcbe56835344ec1fb3023219cd2d3
Once we update TimingParams to take a document, we will need to get an
appropriate document within the various constructor methods. This complicates
these methods and suggests they should be pushed into the .cpp file where
we can hide the complexity more easily and templatize the type of the options
argument so that we can share the document-fetching code.
By moving all uses of the declared template methods to the .cpp file we
can drop the explicit instantiations.
(We still need to declare the templated methods in the header file since
these methods need to be protected methods of KeyframeEffectReadOnly in
order to construct a KeyframeEffectReadOnly since its constructor is
protected.)
MozReview-Commit-ID: 8KrCWrWIb7X
--HG--
extra : rebase_source : c5b550b271cc68ceeb60a25243268a17b3ab7f65
Adds a utility function for getting the document on the global associated with
a JSContext. We will need this in various situations where we want to use
the CSS parser (which requires various bits of state we pull off a document)
to parse a timing function but might not have a target element.
Strictly speaking we currently always have a target element but in future we
expect to support creating KeyframeEffects without an associated target
element. Also, we will need this for some situations in bug 1245748 where we
need to parse CSS properties on keyframe objects when we may not have a
target element.
MozReview-Commit-ID: Klku1LFoRGp
--HG--
extra : rebase_source : f2aa06aafb8fa9b212791a3e602a168f5170fcd9
Each warning message is generated only when getPropertyState() is called.
MozReview-Commit-ID: C03ZSvPv9ff
--HG--
extra : rebase_source : 5932957f8f0b171c7b100b1c22e70513959c819e
Those message will be modified in part 4 (localization).
MozReview-Commit-ID: 6TMUxemVLcu
--HG--
extra : rebase_source : 65ef1879b3e606ae6dc279981b1e995c7b2cd40b
In order to convert CSSPseudoElementType into its underlying type easier,
we define CSSPseudoElementTypeBase. However, keep using uint8_t directly for
forward declarations.
Now we produce computed timing progress outside [0,1] range.
We use the last segment to calculate animation values if the value is greater than 1.
We use the first segment to calculate animation values if the value is lesser than 0.
Currently endTime is calculated when getComputedTiming() is called. As a
result, the value returned there doesn't necessarily reflect what we are using
in the model. It would be more simple, consistent and useful if we simply
calculate this as part of GetComputedTimingAt and use it both internally and in
the result to getComputedTiming().
With the added tests in part 4 we crash without this change because we end up
trying to multiply an infinite iteration duration by a zero iteration count
which trips an assertion in StickyTimeDuration. Hence we fix this behavior
before adding the tests.
Implement GetTarget() and functions of CSSPseudoElement.
We use a strong reference from CSSPseudoElement to Element and a non-owning
reference from Element to CSSPseudoElement.
This means that we won't associate animations with additional frames.
In this case, this fixes associating off-main-thread animations with a
table outer frame, when they should have been associated only with the
table frame.
Locally, the test fails without the patch (with opacity in the test
being 0.36 instead of the expected 0.6), and passes with the patch.
(Opacity 0.36 gives a color of rgb(163,163,255), whereas 0.6 gives
rgb(102,102,255).)
--HG--
extra : commitid : 7wtkIDLDHBF
We don't need observe restylings other than animations. If those restylings
happen, it's just noise for this test. We should drop them.
--HG--
extra : transplant_source : 9%0B%0B%B7O%E5R%86%D4%7F%29%90q%DDQ0%0B%FAuJ
Before this fix, sometimes an element which was removed in a prior test
would still visible when subsequent test starts.
We should wait for paints to complete after the element has been removed.
--HG--
extra : transplant_source : %C7%7F%03%0F%DA%05A%C1%CE%F0m%DA1%C5%1D%FA%06%FA%FE%CA
Nothing() represents linear function, i.e. skip calculation.
ParseEasing is changed to return a Maybe<ComputedTimingFunction>,
if timing function is linear function, ParseEasing returns Nothing().
This is also for compositor side.
we need a new class to share the function which converts TimingFunction
to ComputedTimingFunction for either keyframe's timing function or keyframe
effect's timing function.
This will allow us to re-use the constructor from Animatable.animate() since the
existing type, UnrestrictedDoubleOrKeyframeEffectOptions, is not compatible with
UnrestrictedDoubleOrKeyframeAnimationOptions (introduced in the next patch in
this series), as used by Animatable.animate()
In current our implemantation, animations which can run on compositor
in invisible element can not run on compositor on all desktop platforms.
*BUT* both on Android and B2G the animations still run on compositor somehow.
And one more thing. Animations can run on compositor in elements which are
scrolled out in the parent element *RUN* on compositor as well.
mochitest does not allow us to disable each test on specific platforms respectively.
One we have mozinfo in mochitest (bug 1150818), we can skip the tests on specific platforms.
In some circumstances when composing style, we tweak the time of the animation
before telling the effect to compose style. This is to avoid visual flicker in
certain situations where the main thread progress is being synchronized with an
animation running on the compositor.
In the past, effects would store their latest sample time locally so when
tweaking the animation time, we would need to call UpdateEffect() after tweaking
the time, and then again after restoring it as otherwise the style composed by
the effect would not reflect the adjusted time.
Now, however, effect's always query their animation for the time so this is no
longer necessary. Furthermore, the actions triggered by UpdateEffect are not
desirable in this case because they can, amongst other things, cause the
associated EffectSet to be destroyed and recreated.
Specifically, Animation::UpdateEffect() calls
KeyframeEffectReadOnly::NotifyAnimationTimingUpdated() which:
* Calls UpdateTargetRegistration which can trigger EffectSet
destruction/creation which is undesirable in this case because we intend to
restore whatever changes we make to the Animation's state and deleting and
recreating the EffectSet will cause any pointers to it to dangle.
* Cause us to possibly reset the "is running on compositor" status.
This too is undesirable since we intend to restore the state of the
Animation immediately after tweaking the hold time so we don't want to
act as if any state has changed.
* Similarly for marking the cascade as possibly needing an update or
requesting a restyle.
In summary, all the actions performed by NotifyAnimationTimingUpdated are
unnecessary and undesirable in this situation where we are temporarily tweaking
an Animation's current time only to restore it immediately afterwards since the
actions are all involved with recognizing actual changes in state.
Overload TimingParams::operator=() for AnimationEffectTimingProperties objects,
so we can assign an AnimationEffectTimingProperties/KeyframeEffectOption object
to a TimingParams object.
We also keep the uninitialized state of KeyframeEffectOptions::mDuration while
converting a KeyframeEffectOptions object into a TimingParams object.
We store the original value of duration in AnimationTiming, and add
computed duration in ComputedTiming, so both the Timing model and
AnimationEffectTimingReadOnly can get what they want.
By the way, replace mIterationDuration with mDuration.
--HG--
extra : rebase_source : f8e1fd648572e6d7b1cbecc2ac1888a2f74bbc7e
FillMode could be 'auto', and we should treat it as 'none' in the timing model.
However, AnimationEffectTimingReadOnly should get its original value.
By the way, replace mFillMode with mFill.
--HG--
extra : rebase_source : 5a397dd7fbb22ac76fe96003d82d097e398852c7
We want to store the original value from KeyframeEffectOptions whose
iterations is unrestricted double. Therefore, we can get the original value
of iterations by AnimationEffectTimingReadOnly.
By the way, replace mIterationCount with mIterations.
--HG--
extra : rebase_source : da2953056031079c41273ed977545dc926e1b83c
When updating animations, we shouldn't unnecessarily clobber the "wins in
cascade" state of their properties since this can lead to unnecessary restyles
when we then decide we need to update the cascade.
As of bug 1228229, the mWinsInCascade member of animation properties is set
consistently for both animations and transitions such that we only set this
to true if an animation is "in effect".
When an effect is initially created it is not "in effect" until it is attached
to a non-idle animation. We should, therefore, initialize this to false and,
when we become in effect, mark the cascade as needing an update.
RestyleManager currently has a piece of state for tracking if throttled
animations are up-to-date or not. Actually, it's not so much about throttled
animations but really about outstanding changes to animation styles (which
is typically expected to be due to throttling animations but there are
other cases that invalidate the animation style rule that we should be
considering here).
We now have that same information stored in the EffectCompositor so we can
remove the redundant state from RestyleManager. Furthermore, the state stored
in EffectCompositor is more accurate since it captures the case when animation
style needs to be updated twice within a tick, or when nothing needs to be
updated within a tick.
This patch, therefore, introduces EffectCompositor::HasPendingStyleUpdates in
place of setting RestyleManager::mLastUpdateForThrottledAnimations.
nsTransitionManager also uses mLastUpdateForThrottledAnimations to warn if we
have not processed throttled animations. We can't use HasPendingStyleUpdates
here however, since it will return true in the case where we have triggered new
transitions in the process of restyling. However, any new transitions will
trigger "standard" (i.e. not throttled) restyles so we introduce another
method, HasThrottledStyleUpdates, that returns true only if we have outstanding
throttled updates and use this for the warning inside nsTransitionManager.
nsPresContext contains a mLastStyleUpdateForAllAnimations flag which is simply
used to prevent unnecessarily posting restyles when throttled animations are
already up to date. Since part 13 we now accurately record whether we have
posted a restyle for each throttled animation and only post a restyle if we
have not done so already. As a result, this flag is no longer needed since
calling PostRestyleForThrottledAnimations is effectively a noop when throttled
animations are up-to-date.
This flag is no longer needed because in bug 1232563 we introduced a more
thorough optimization that detects when the animation is not changing by
comparing the progress value between samples and avoids requesting restyles
when it does not change.
Now that we track whether or not animations are up to date using the hashset in
EffectCompositor, we can remove the mStyleRuleRefreshTime flag that is, as of
part 5 of this patch series, now only used for detecting whether or not
animations are up to date.
In order to preserve the existing behavior of FlushAnimations, however, this
patch temporarily introduces a method to indicate if there are throttled
animations or not.
It might not be obvious that FlushAnimations is only concerned with throttled
animations due to its name. FlushAnimations is simply intended to post
animation restyles for out-of-date animations. Any animations that are *not*
throttled will either be up to date, or we will have already posted an
animation restyle so we only need to consider throttled animations in this case.
This patch continues to migrate functionality from
AnimationCollection::RequestRestyle to EffectCompositor::RequestRestyle.
In order to post the animation restyle from the EffectCompositor, this patch
also moves the PostRestyleForAnimation method to EffectCompositor.
The GetElementToRestyle method is temporarily duplicated in both
EffectCompositor and AnimationCollection however we will remove the version in
AnimationCollection later in this patch series.
In this patch series we are gradually migrating style rule updating
functionality from AnimationCollection to EffectCompositor. This patch moves
part of the RequestRestyle method from one class to the other.
Note that in both cases we only call SetNeedsStyleFlush if we haven't already
posted an animation restyle. (In the case of AnimationCollection we check this
using the mHasPendingAnimationRestyle flag, and in EffectCompositor case we
simply check if the element is already in the "needs restyle" hashmap. If it is,
either we already have a throttled restyle and have called SetNeedsStyleFlush or
we have a standard restyle and have posted an animation restyle.)
The added check for a null pres context matches the behavior of
AnimationCollection::RequestRestyle which has an equivalent early return at the
beginning of the function.
AnimationCollection keeps a TimeStamp that records the refresh driver time when
the animation style rule was last updated. This is used for two purposes:
1. To determine when the style rule is out of date.
2. For animations that are partially throttled on the main thread, e.g.
transform animations that affect the scrollable region which we update every
200ms on the main thread.
In this bug we are removing all the overlapping bits of state used to track if
animations are up-to-date or not and replacing them with the hashmap stored on
the EffectCompositor which tracks which animations are currently in need of an
update. As a result, we would like to remove this style rule refresh time.
However, we will need something for case (2) from above.
This patch adds an animation rule refresh time to the EffectSet purely for the
purposes of partially-throttled animations so that we can later remove the style
rule refresh time from AnimationCollection.
This patch uses the presence/absence of (pseudo-)elements in the "needs
animation rule update" hashmap on EffectCompositor to detect if a style update
is required. The various flags in AnimationCollection that do a similar job
still remain so that we can remove them one-by-one in subsequent patches in
this series.
This is in preparation for moving RequestRestyle to EffectCompositor (and
because we'll run into compile issues if we don't since AnimationCommon.h
includes too many interdependent definitions).
We will eventually use this in place of the various state flags stored on
AnimationCollection (e.g. mStyleRuleRefreshTime, mStyleChanging,
mHasPendingAnimationRestyle) as well as to do a more targetted update in
FlushAnimations and AddStyleUpdatesTo.
Since we want to track elements needing a restyle on EffectCompositor we need
to scope it to an nsPresContext rather than just making if a collection of
static methods.
Now that restyle requests are handled by the effect, we can more easily detect
cases where we don't need to trigger a style update by looking for when the
output of the effect could actually differ.
Currently, any changes that require updates where the progress does *not* change
(e.g. pausing) are triggered by the Animation. The exception is when we
update timing properties (e.g. animation-iteration-count) from CSS but
current nsAnimationManager takes care to adjust the animation generation in
this case.
--HG--
extra : rebase_source : ecc0b5c80e52ce17214ab8c6ac9681477e3f80ca
This is because rather than simply requesting a throttled restyle when there
were no properties, as of the previous patch, we no longer request a restyle at
all in this case.
We should be able to restore this optimization in bug 1235002 when we properly
encapsulate the properties of a keyframe effect.
--HG--
extra : rebase_source : 1774698e15178cf8f8295160b96adea8ca5a2ed2
When requesting restyles we take special care to detect when an animation has
newly finished so we perform the necessary restyle to represent the fill state.
However, we should really explicitly pull the animation off the layer at this
point by requesting a layer update. (That is, when an animation is
newly-finished we should use RestyleType::Layer instead of
RestyleType::Standard. Currently we just use RestyleType::Standard.)
In this bug we plan to move restyle requests down to the effect (since it is
the *effect* that is restyled). However, only the Animation has the notion of
"finished" or not so we detect this particular case in the Animation and
request the layer update there. We already request layer updates in the
Animation for other situations such as pausing so doing *layer* updates in the
Animation and regular restyles in the effect is not inconsistent.
This patch also tweaks test_animations_omta.html since it was previously
erroneously testing that a finished animation was still running on the
compositor.
--HG--
extra : rebase_source : 3cd1abe2a10370e90cde64b4b42b27326082f6f0
This patch just moves a piece of functionality from
AnimationCollection::EnsureStyleRuleFor to the EffectCompositor. In subsequent
bugs we will move more and more of this functionality across until this
logic is fully contained in the EffectCompositor.
--HG--
extra : rebase_source : 7ffe91adb4ca3d57fc8f6ae3f7e5f7bec91f350b
As we gradually move logic from layout/style/AnimationCommon.cpp to
dom/animation/EffectSet and EffectCompositor it makes sense to let this class
live in its own file inside dom/animation where it is used.
--HG--
extra : rebase_source : aed0632a19800e0ef9d8fe1d03d0364bf1ccc4dc
This is needed in order to support script-generated animations since they do not
belong to any AnimationCollection.
This patch adopts the naming "animation rule" over "style rule". Currently we
are inconsistent about this (e.g. GetAnimationRule vs EnsureStyleRuleFor).
We don't do a mass rename here but just a few places near where we're touching.
Many of the other references to "style rule" will be revised in this bug or
related bugs so we can fix those references when we come to them.
--HG--
extra : rebase_source : e1f824029b39960915e056328447de256b6c1c6d
Introducing an enum will simplify further patches in this series by providing
a common vocabulary for this distinction.
--HG--
extra : rebase_source : 4afbd358a401853df3ad401f2b1c3454ccff26cd
This restores the code removed in part 3 but adjusts it to iterate over
an effect set instead of an AnimationCollection. It also adds an early return
for the case where no compositor-animatable properties are found.
--HG--
extra : rebase_source : 5e73374c8fb7df4e946f73512337a55f5dae94f2
This patch implements "case 2" described in the commit message from part 4 of
this patch series.
--HG--
extra : rebase_source : 805f24376fa4648f094fb04247d48d075a73400c
KeyframeEffectReadOnly::NotifyAnimationTimingUpdated currently just acts as an
alias for UpdateTargetRegistration. However, bug 1226118 added logic to
UpdateTargetRegistration which is not strictly related to updating the target
element registration. This patch tidies this up so that UpdateTargetRegistration
only does what its name suggests. This is in preparation for adding more
logic to NotifyAnimationTimingUpdated.
--HG--
extra : rebase_source : c6162e8415613d7ec16744228d7cf498b4c19e2c
There are three situations when the cascade results of effects needs to be
updated.
1. The sets of effects (animations) has changed.
2. One or more effects have changed their "in effect" status.
3. Other style properties affecting the element have changing meaning that
animations applied at the animations-level of the cascade may now be
overridden or become active again.
We want to detect these situations so we can avoid updating the cascade when
none of these possibilities exist.
Currently we handle case 1 by calling UpdateCascadeResults at the appropriate
point in nsAnimationManager and nsTransitionManager when we build
animations/transtiions.
Case 2 only affects animations (since whether transitions are in effect or not
makes no difference to the cascade--they have a lower "composite order" than
animations and never overlap with each other so they can't override anything).
As a result, we handle it by adding a flag to CSSAnimation to track when an
animation was in effect last time we checked or not.
For case 3, we take care to call UpdateCascadeResults when the style context
changed in nsAnimationManager::CheckAnimationRule (called from
nsStyleSet::GetContext).
We want to generalize this detection to handle script-generated animations too.
In order to do that this patch introduces a flag to EffectSet that we will use
to mark when the cascade needs to be updated in cases 1 and 2. This patch also
sets the flag when we detect case 1. A subsequent patch sets the flag for
case 2.
Case 3 is more difficult to detect and so we simply maintain the existing
behavior of making nsAnimationManager::CheckAnimationRule unconditionally
update the cascade without checking if the "needs update" flag is set.
--HG--
extra : rebase_source : fc56b1bb5a98ae78b93a179c7a3b8af4724a06a1
This patch also simplifies this logic by simply always looking for overrides of
'transform' and 'opacity'.
--HG--
extra : rebase_source : d1e432e629e2b97651f14c784f97c03f55d217be
We will use similar logic later in this patch series so we separate it out into
a separate helper function here.
--HG--
extra : rebase_source : 00cb49e7829bdef7a6084059b31fe2ef4b921af5
Since part 3 in this patch series updated the way we clear the "running on
compositor" flag, we can update these tests so they no longer wait for this
flag (see bug 1226118 comment 21).
This is to align with the existing GetAnimationCollection method that takes
a frame. Also, by making this name more specific hopefully it will be used less
since we are trying to move as much code as possible over to using EffectSet
instead of AnimationCollection.
This added method should behave in an equivalent manner to the existing
CommonAnimationManager::GetAnimationsForCompositor except for the following
differences:
* It uses the EffectSet attached to a target element rather than one of the
AnimationCollection object on the owning element.
* It returns an array of Animation objects consisting of only those Animations
that actually have the specified property as opposed to the
AnimationCollection consisting of *all* CSS animations or *all* CSS
transitions for the element regardless of whether they run on the compositor
or not.
It may not be obvious why these two methods otherwise behave in an equivalent
fashion so the following explains how the existing code is mirrored in the new
method.
The existing code is as follows:
> AnimationCollection*
> CommonAnimationManager::GetAnimationsForCompositor(const nsIFrame* aFrame,
> nsCSSProperty aProperty)
> {
> AnimationCollection* collection = GetAnimationCollection(aFrame);
> if (!collection ||
> !collection->HasCurrentAnimationOfProperty(aProperty) ||
> !collection->CanPerformOnCompositorThread(aFrame)) {
> return nullptr;
> }
>
> // This animation can be done on the compositor.
> return collection;
> }
The new EffectCompositor::GetAnimationsForCompositor begins with two checks
performed at the beginning of CanPerformOnCompositorThread: the checks for
whether async animations are enabled or not and whether the frame has refused
async animations since these are cheap and it makes sense to check them first.
The next part of EffectCompositor::GetAnimationsForCompositor checks if there is
an EffectSet associated with the frame. This is equivalent to the check whether
|collection| is null or not above.
Following, we iterate through the effects in the EffectSet.
We first check if each effect is playing or not. In the above code,
HasCurrentAnimationOfProperty only checks if the effect is *current* or not.
However, CanPerformOnCompositorThread will only return true if it finds an
animation that can run on the compositor that is *playing*. Since playing is
a strict subset of current we only need to perform the more restrictive test.
Next we check if the effect should block running other animations on the
compositor. This is equivalent to the remainder of CanPerformOnCompositorThread.
Note that the order is important here. Only playing animations should block
other animations from running on the compositor. Furthermore, this needs to
happen before the following step since animations of property other than
|aProperty| can still block animations from running on the compositor.
Finally, we check if the effect has an animation of |aProperty|. This is
equivalent to the remainder of HasCurrentAnimationOfProperty.
If all these checks succeed, we add the effect's animation to the result to
return.
KeyframeEffectReadOnly::CanAnimatePropertyOnCompositor has a comment that says
it, "Returns true |aProperty| can be run on compositor for |aFrame|" but it
does nothing of the sort.
What it *does* do is check answer the question, "If there happened to be an
animation of |aProperty| on |aFrame|, should we still run animations on the
compositor for this element?".
This patch renames the method accordingly and moves the step where we iterate
over a given effect's animated properties from
AnimationCollection::CanPerformOnCompositor to inside this method, making this
method a class method rather than a static method at the same time.
As noted in the expanded comment, the approach of blocking opacity animations
in these situations seems unnecessary but for now this patch just preserves the
existing behavior.
This patch also moves AnimationUtils out of the dom namespace since it seems
unnecessary. We typically only put actual DOM interfaces in the dom namespace.
This is so that when we have code like:
elem.animate({ opacity: 0 }, 1000)
the resulting Animation object is kept alive by |elem| based on the following
ownership chain:
elem --(strong)--> KeyframeEffectReadOnly --(strong)--> Animation
Now, there is an ownership cycle introduced here because KeyframeEffectReadOnly
objects also store owning references to their target elements. This is broken
when the Animation finishes (if it does not fill forwards) or is cancelled
since either event will trigger a call to
KeyframeEffectReadOnly::UpdateTargetRegistration.
If the Animation fills forwards, the resource will not be released until
it is cancelled. For Animations corresponding to CSS Animations / CSS
Transitions this happens when the Element is unbound or when the corresponding
style property is updated causing the animation to be replaced or removed.
For the general case of script-generated animations, however, this cycle won't
be broken until the Element is unbound and all external references to the
Animation or KeyframeEffectReadOnly are dropped.
It's unfortunate that we can't more aggressively prune these objects but it's
what the spec currently says. I've posted to the mailing list[1] about this but
have yet to find a good solution.
[1] https://lists.w3.org/Archives/Public/public-fx/2015OctDec/0029.html
Use mozilla::dom::FillMode and mozilla::dom::PlaybackDirection
in AnimationTiming.
--HG--
extra : rebase_source : 8210d002d6f116793f439d88b0325ab6fb880048
Fix: INFO TEST-UNEXPECTED-FAIL | dom/animation/test/chrome/test_animation_observers.html | Test timed out.
By extending animation observer timeout.
--HG--
extra : commitid : GEfsdBOqqsu
The behavior of unthrottling in case of not current animations there is the
same as on current trunk.
There are two cases to reach there I can think of:
a) 0s duration time and fill-forwards animation
b) Calling pause() after fill-forwards animation finished.
I can provide these automation tests once bug 1222326 is fixed.
The preference check has been removed from CanThrottleTransformChanges
because we already perform that check that when deciding if we should run
an animation on the compositor (in CanPerformOnCompositorThread, as called
by GetAnimationsForCompositor). Hence if the "is running on compositor" flag
is true, we can assume the preference is set (or was set when we decided to
put the animation on the compositor-- we don't worry about pulling the
animation off the compositor immediately if the preference changes while
it is running)
Based on AnimationCollection::CanAnimatePropertyOnCompositor.
The first argument has been changed to nsIFrame* so that we don't need to
get style frame for CanAnimateTransformOnCompositor again.
If this patch (and part 9) is an overkill to throttle animations having both
of properties, one can be run on compositor and another can not be, a test
case in test_running_on_compositor[1] will fail.
The test case is for an animation which has transform and background-color
properties.
Animation::CanThrottle() returns true
(then, AnimationCollection::CanPerformOnCompositorThread() returns false)
on current trunk in the test case.
Animation::CanThrottle() returns false with this patch in the test case.
If the test passes, it proves the transform animation is running on compositor
in both cases.
[1] http://hg.mozilla.org/mozilla-central/file/6c7c983bce46/dom/animation/test/chrome/test_running_on_compositor.html#l77
Do some minor revisions in struct ComputedTiming.
1. Use Nullable<double> mProgress, so remove the static const kNullProgress.
The generated ComputedTimingProperties dictionary uses "Nullable" variable,
so we replace the origin type in ComputedTiming to make it more consistent
with that in ComputedTimingProperties dictionary.
2. Use scoped enums for AnimationPhase.
--HG--
extra : rebase_source : 31280c867a30e7bcdcfe831cbc72ca08c8ddc762
Add two dictionaries into AnimationEffectReadOnly.webidl:
1. AnimationEffectTimingProperties
2. ComputedTimingProperties
And then re-generate this class.
--HG--
extra : rebase_source : 81b2a3c08453cabcb2ac1334e6d4bde2c1bafeea
The Animation.pause() method operates asynchronously since, if the animation is
currently running on the compositor, we should wait for the animation to stop
on the compositor before establishing the pause time. Otherwise, if the
compositor is ahead of the main thread and we use the main thread's notion of
the current time to establish the pause time, the animation will jump backwards
when we take it off the compositor.
This pause time is represented using the "hold time".
However, when we have a finished animation, its current time is not advancing
but rather its current time is fixed to its end time. This too is represented
using the hold time. As a result, if we pause a finished animation we should
not update its hold time (by calculating the current time from the start time)
but just continue to use the existing hold time. This is true of any other
situation where we might have set the hold time before or during pausing.
In a subsequent patch, we will have another struct like
KeyframeValueEntry, but storing an StyleAnimationValue and an
ComputingTimingFunction object (not a pointer). So we split
KeyframeValueEntry into two, retaining the KeyframeValueEntry name for
the base class and naming the current one KeyframeStringValueEntry.