Today, each animation or transition has a timer which fires 2 or more times per animation. The start timer always fires when the delay time is up. This is true even with a 0 delay - the timer fires as soon as possible. An end timer always fires as well when the duration is up, unless it is a repeating animation, in which case the timer fires after each iteration. These timers are used not only to send the animation events as needed, but they update the state machine as well. But they are really unnecessary because the AnimationController is already running a timer to do the animations themselves. So this timer can serve the purpose of handling state machine changes and event generation. This will not only be more efficient (one timer per document, rather than one timer per animation), but it will make it easier to deal with other issues on my plate, such as synchronizing multiple animations and making sure the end animation callback comes at the correct instant rather than several hundred ms later, which is sometimes the case today.
Created attachment 25848 [details] Patch to fix bug Fixed https://bugs.webkit.org/show_bug.cgi?id=22738 This gets rid of the per-animation timers which were used when an animation started, ended and looped. Their job is now done by the main AnimationController's timer. It is now set to fire as needed. For instance, if there is a delay, it will fire after the delay time and then every 30ms to run the animation. The start, loop and end events are generated as needed during the firing of this timer. I had to add one more bit of code. When animation timers used to fire the animation events. This would always happen from the RunLoop, so any style changes that happened in the event handler would get picked up on the next updateRendering() call. But now the start event is generated during the styleIsAvailable() call, which is in the middle of the updateRendering() cycle. And calling an event handler in the middle of updateRendering() is not allowed and causes style changes to get missed. We already have a mechanism in AnimationController to defer updateRendering() calls. So I added logic to defer all event handling to there. Now, I put any request for event handling into a list and ask for a deferred updateRendering() call. When that deferred timer fires, I go through that list, send all the events and then call updateRendering().
Comment on attachment 25848 [details] Patch to fix bug r=me
Sending WebCore/ChangeLog Sending WebCore/page/animation/AnimationBase.cpp Sending WebCore/page/animation/AnimationBase.h Sending WebCore/page/animation/AnimationController.cpp Sending WebCore/page/animation/AnimationController.h Sending WebCore/page/animation/CompositeAnimation.cpp Sending WebCore/page/animation/CompositeAnimation.h Sending WebCore/page/animation/ImplicitAnimation.cpp Sending WebCore/page/animation/ImplicitAnimation.h Sending WebCore/page/animation/KeyframeAnimation.cpp Sending WebCore/page/animation/KeyframeAnimation.h Transmitting file data ........... Committed revision 39211.