[Web Animations] Schedule animations registered on the document timeline
authorgraouts@webkit.org <graouts@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 5 Nov 2017 22:34:10 +0000 (22:34 +0000)
committergraouts@webkit.org <graouts@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 5 Nov 2017 22:34:10 +0000 (22:34 +0000)
commitde95495ac7f2773e0efcc8ec11cfcb97a75dd108
tree0de225b92230990d63c61048d9d2a22ba46731c5
parente26752b17b47859648b295614891d24f7054d1fb
[Web Animations] Schedule animations registered on the document timeline
https://bugs.webkit.org/show_bug.cgi?id=179236
<rdar://problem/35332669>

Reviewed by Dean Jackson.

Source/WebCore:

We now schedule animations contained in the document timeline using a three-step approach.

1. Each time an object that is part of the timing model changes one of its timing properties, we call
   animationTimingModelDidChange() on the document timeline. This schedules performInvalidationTask()
   to be called when the current run loop completes, such that we invalidate the timing model just once
   per run loop.

2. Once performInvalidationTask() is called, the timing model is invalidated in updateAnimationSchedule().
   We iterate over the registered animations on the timineline and identify the shortest interval between
   the current time and the next moment one of the animations requires a tick to update its value. If we
   find a value below 15ms, we schedule animations to be resolved with scheduleAnimationResolution() right
   away. If the value is above 15ms, and not inifinity, we schedule a one-shot timer for that interval to
   call scheduleAnimationResolution().

3. Once scheduleAnimationResolution() is called, we call scheduleAnimation() on the shared DisplayRefreshMonitorManager
   to be notified when the next display refresh occurs to actually resolve animations with resolveAnimations().

Note that, in this patch, resolveAnimations() does nothing, we will add support for interpolating values in
a future patch.

Another important thing to note is that every time the document timeline's current time is requested, we cache
it for the duration of the run loop such that the timing model always uses the same value during a given run loop.

Finally, to support tests where we check the state of the timing model by manually advancing time, we expose a
new pause() method on AnimationTimeline for tests to call to avoid the timeline to self-advance.

* animation/AnimationTimeline.cpp:
(WebCore::AnimationTimeline::addAnimation): Mark that the timing model changed as a result of adding an animation.
(WebCore::AnimationTimeline::removeAnimation): Mark that the timing model changed as a result of removing an animation.
(WebCore::AnimationTimeline::bindingsCurrentTime): Update the method signature to no longer be const and call into
currentTime() instead of reading directly from the m_currentTime member variable since a subclass, like DocumentTimeline,
may have a custom currentTime() implementation.
(WebCore::AnimationTimeline::setCurrentTime): Mark that the timing model changed as a result of the timeline current time
changing.
(WebCore::AnimationTimeline::bindingsCurrentTime const): Deleted.
* animation/AnimationTimeline.h:
(WebCore::AnimationTimeline::currentTime): Change both methods signatures to no longer be const so that DocumentTimeline's
implementation of currentTime() may cache the current time in a member variable, enqueuing a callback when the run loop
completes for this member variable to be reset, and updating some states.
(WebCore::AnimationTimeline::pause): To be implemented by subclasses.
(WebCore::AnimationTimeline::animationTimingModelDidChange): Add a new virtual method to indicate that the timing model
needs invalidating.
(WebCore::AnimationTimeline::animations const): Add an accessor to allow animations to be accessed by a subclass.
* animation/DocumentTimeline.cpp:
(WebCore::DocumentTimeline::create):
(WebCore::DocumentTimeline::DocumentTimeline): Update the constructor signature to receive a Document and a PlatformDisplayID
since we need a reference to the Document to get at the nowTime() and a PlatformDisplayID to create the DisplayRefreshMonitor.
(WebCore::DocumentTimeline::~DocumentTimeline): Close the task queue when the timeline gets destroyed.
(WebCore::DocumentTimeline::currentTime): If we don't have a current cahed current time, compute one and schedule
the invalidation task if needed so that we may reset the cached value as the run loop completes.
(WebCore::DocumentTimeline::pause): Allows the timeline not to self-advance, for testing purposes only.
(WebCore::DocumentTimeline::animationTimingModelDidChange): If we haven't already done so, mark that we need to update our
animation schedule in the invalidation task and schedule that task if not scheduled yet.
(WebCore::DocumentTimeline::scheduleInvalidationTaskIfNeeded): Schedule the invalidation task to run as the run loop completes
if we haven't already done so.
(WebCore::DocumentTimeline::performInvalidationTask): Update the animation schedule if needed and reset the cached current
time value.
(WebCore::DocumentTimeline::updateAnimationSchedule): Iterate over registed animations and find the shortest interval until
one of them needs to update their animation. If the shortest interval is below 15ms, schedule the animation resolution right
away. If the shortest inverval is finite and above 15ms, then schedule a one-shot timer for that interval to perform the
animation resolution then.
(WebCore::DocumentTimeline::animationScheduleTimerFired): The one-shot timer to perform the animation resolution has fired,
we call scheduleAnimationResolution().
(WebCore::DocumentTimeline::scheduleAnimationResolution): We call scheduleAnimation() on the shared DisplayRefreshMonitorManager
so that we may resolve animations on the next display refresh, or start a timer if the DisplayRefreshMonitorManager is not available.
(WebCore::DocumentTimeline::displayRefreshFired): The display is about to refresh, we call resolveAnimations().
(WebCore::DocumentTimeline::animationResolutionTimerFired): The fallback animation resolution timer has fired, we call resolveAnimations().
(WebCore::DocumentTimeline::resolveAnimations): Currently do nothing, this is where we'll iterate over registered animations to
update them with the current time.
(WebCore::DocumentTimeline::windowScreenDidChange): Notify the shared DisplayRefreshMonitorManager that the PlatformDisplayID
changed.
(WebCore::DocumentTimeline::createDisplayRefreshMonitor const): Provide a DisplayRefreshMonitor as part of the
DisplayRefreshMonitorClient protocol.
* animation/DocumentTimeline.h:
* animation/WebAnimation.cpp:
(WebCore::WebAnimation::create): Remove extra white space.
(WebCore::WebAnimation::setStartTime): Mark that the timing model changed as a result of changing this animation's start time.
(WebCore::WebAnimation::timeToNextRequiredTick const): Compute the interval until the next time we need to resolve this animation.
If the provided current time is before this animation's start time, compute the delay until the start time. If the current time
is after the animation's start time but before the animation's end time, indicate that we want to resolve the animation again
right away and return 0ms. In any other case, return an infinite interval to indicate that we don't need to be refreshed after
the provided time.
* animation/WebAnimation.h:
* dom/Document.cpp:
(WebCore::Document::windowScreenDidChange): Notify the document timeline that the PlatformDisplayID changed.
(WebCore::Document::timeline): Provide the Document and the PlatformDisplayID to the DocumentTimeline.
* testing/Internals.cpp:
(WebCore::Internals::pauseTimeline):
* testing/Internals.h:
* testing/Internals.idl:

LayoutTests:

Adopt the new internals.pauseTimeline() method to ensure that the existing
tests do not have a self-advancing timeline since we're interested in checking
the timing model state based on manually setting the timeline current time.

Also update some WPT expectations with some progressions.

* TestExpectations: Mark two tests as flaky due to the sample time being logged
in the failure.
* http/wpt/web-animations/interfaces/AnimationTimeline/document-timeline-expected.txt:
* http/wpt/web-animations/timing-model/animations/current-time-expected.txt:
* http/wpt/web-animations/timing-model/animations/set-the-animation-start-time-expected.txt:
* http/wpt/wk-web-animations/timing-model/animation-creation-basic.html:
* http/wpt/wk-web-animations/timing-model/animation-current-time.html:
* http/wpt/wk-web-animations/timing-model/animation-effect-timing.html:
* http/wpt/wk-web-animations/timing-model/animation-effect.html:
* http/wpt/wk-web-animations/timing-model/animation-interface-effect-property.html:
* http/wpt/wk-web-animations/timing-model/animation-interface-start-time-property.html:
* http/wpt/wk-web-animations/timing-model/animation-playback-rate.html:
* http/wpt/wk-web-animations/timing-model/document-timeline.html:
* http/wpt/wk-web-animations/timing-model/keyframe-effect-interface-timing-duration.html:
* http/wpt/wk-web-animations/timing-model/keyframe-effect.html:
* http/wpt/wk-web-animations/timing-model/timeline-current-time.html:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@224472 268f45cc-cd09-0410-ab3c-d52691b4dbfc
27 files changed:
LayoutTests/ChangeLog
LayoutTests/TestExpectations
LayoutTests/http/wpt/web-animations/interfaces/AnimationTimeline/document-timeline-expected.txt
LayoutTests/http/wpt/web-animations/timing-model/animations/current-time-expected.txt
LayoutTests/http/wpt/web-animations/timing-model/animations/set-the-animation-start-time-expected.txt
LayoutTests/http/wpt/wk-web-animations/timing-model/animation-creation-basic.html
LayoutTests/http/wpt/wk-web-animations/timing-model/animation-current-time.html
LayoutTests/http/wpt/wk-web-animations/timing-model/animation-effect-timing.html
LayoutTests/http/wpt/wk-web-animations/timing-model/animation-effect.html
LayoutTests/http/wpt/wk-web-animations/timing-model/animation-interface-effect-property.html
LayoutTests/http/wpt/wk-web-animations/timing-model/animation-interface-start-time-property.html
LayoutTests/http/wpt/wk-web-animations/timing-model/animation-playback-rate.html
LayoutTests/http/wpt/wk-web-animations/timing-model/document-timeline.html
LayoutTests/http/wpt/wk-web-animations/timing-model/keyframe-effect-interface-timing-duration.html
LayoutTests/http/wpt/wk-web-animations/timing-model/keyframe-effect.html
LayoutTests/http/wpt/wk-web-animations/timing-model/timeline-current-time.html
Source/WebCore/ChangeLog
Source/WebCore/animation/AnimationTimeline.cpp
Source/WebCore/animation/AnimationTimeline.h
Source/WebCore/animation/DocumentTimeline.cpp
Source/WebCore/animation/DocumentTimeline.h
Source/WebCore/animation/WebAnimation.cpp
Source/WebCore/animation/WebAnimation.h
Source/WebCore/dom/Document.cpp
Source/WebCore/testing/Internals.cpp
Source/WebCore/testing/Internals.h
Source/WebCore/testing/Internals.idl