Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1068)

Unified Diff: Source/core/svg/animation/SMILTimeContainer.cpp

Issue 190963003: Drive SVG Animations via requestAnimationFrame (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « Source/core/svg/animation/SMILTimeContainer.h ('k') | Source/core/svg/graphics/SVGImage.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: Source/core/svg/animation/SMILTimeContainer.cpp
diff --git a/Source/core/svg/animation/SMILTimeContainer.cpp b/Source/core/svg/animation/SMILTimeContainer.cpp
index c41555d4d18203e592dc1c81d5ce2f275f8c3608..02a6444e36d13bfda217f4f73f0d7ac8341dbc6f 100644
--- a/Source/core/svg/animation/SMILTimeContainer.cpp
+++ b/Source/core/svg/animation/SMILTimeContainer.cpp
@@ -26,25 +26,27 @@
#include "config.h"
#include "core/svg/animation/SMILTimeContainer.h"
+#include "core/animation/AnimationClock.h"
+#include "core/animation/DocumentTimeline.h"
#include "core/dom/ElementTraversal.h"
+#include "core/frame/FrameView.h"
#include "core/svg/SVGSVGElement.h"
#include "core/svg/animation/SVGSMILElement.h"
-#include "wtf/CurrentTime.h"
using namespace std;
namespace WebCore {
-static const double animationFrameDelay = 0.025;
-
SMILTimeContainer::SMILTimeContainer(SVGSVGElement* owner)
: m_beginTime(0)
, m_pauseTime(0)
, m_resumeTime(0)
, m_accumulatedActiveTime(0)
, m_presetStartTime(0)
+ , m_frameSchedulingState(Idle)
, m_documentOrderIndexesDirty(false)
- , m_timer(this, &SMILTimeContainer::timerFired)
+ , m_animationClock(AnimationClock::create())
+ , m_wakeupTimer(this, &SMILTimeContainer::wakeupTimerFired)
, m_ownerSVGElement(owner)
#ifndef NDEBUG
, m_preventScheduledAnimationsChanges(false)
@@ -55,7 +57,7 @@ SMILTimeContainer::SMILTimeContainer(SVGSVGElement* owner)
SMILTimeContainer::~SMILTimeContainer()
{
cancelAnimationFrame();
- ASSERT(!m_timer.isActive());
+ ASSERT(!m_wakeupTimer.isActive());
#ifndef NDEBUG
ASSERT(!m_preventScheduledAnimationsChanges);
#endif
@@ -99,11 +101,21 @@ void SMILTimeContainer::unschedule(SVGSMILElement* animation, SVGElement* target
scheduled->remove(idx);
}
+bool SMILTimeContainer::hasAnimations() const
+{
+ return !m_scheduledAnimations.isEmpty();
+}
+
void SMILTimeContainer::notifyIntervalsChanged()
{
+ if (!isStarted())
+ return;
// Schedule updateAnimations() to be called asynchronously so multiple intervals
// can change with updateAnimations() only called once at the end.
- scheduleAnimationFrame();
+ if (m_frameSchedulingState == SynchronizeAnimations && m_wakeupTimer.isActive() && !m_wakeupTimer.nextFireInterval())
+ return;
+ cancelAnimationFrame();
+ scheduleWakeUp(0, SynchronizeAnimations);
}
SMILTime SMILTimeContainer::elapsed() const
@@ -135,12 +147,20 @@ void SMILTimeContainer::begin()
// If 'm_presetStartTime' is set, the timeline was modified via setElapsed() before the document began.
// In this case pass on 'seekToTime=true' to updateAnimations().
m_beginTime = now - m_presetStartTime;
- updateAnimations(SMILTime(m_presetStartTime), m_presetStartTime ? true : false);
+ SMILTime earliestFireTime = updateAnimations(SMILTime(m_presetStartTime), m_presetStartTime ? true : false);
m_presetStartTime = 0;
if (m_pauseTime) {
m_pauseTime = now;
cancelAnimationFrame();
+ } else {
+ ASSERT(isTimelineRunning());
+ // If the timeline is running, and there's pending animation updates,
+ // always perform the first update after the timeline was started using
+ // the wake-up mechanism.
+ if (earliestFireTime.isFinite()) {
+ scheduleWakeUp(DocumentTimeline::s_minimumDelay, SynchronizeAnimations);
+ }
}
}
@@ -162,7 +182,7 @@ void SMILTimeContainer::resume()
m_resumeTime = currentTime();
m_pauseTime = 0;
- scheduleAnimationFrame();
+ serviceOnNextFrame();
}
void SMILTimeContainer::setElapsed(SMILTime time)
@@ -173,8 +193,7 @@ void SMILTimeContainer::setElapsed(SMILTime time)
return;
}
- if (m_beginTime)
- cancelAnimationFrame();
+ cancelAnimationFrame();
double now = currentTime();
m_beginTime = now - time.value();
@@ -200,7 +219,7 @@ void SMILTimeContainer::setElapsed(SMILTime time)
m_preventScheduledAnimationsChanges = false;
#endif
- updateAnimations(time, true);
+ updateAnimationsAndScheduleFrameIfNeeded(time, true);
}
bool SMILTimeContainer::isTimelineRunning() const
@@ -210,33 +229,40 @@ bool SMILTimeContainer::isTimelineRunning() const
void SMILTimeContainer::scheduleAnimationFrame(SMILTime fireTime)
{
- if (!isTimelineRunning())
- return;
+ ASSERT(isTimelineRunning() && fireTime.isFinite());
- if (!fireTime.isFinite())
- return;
-
- SMILTime delay = max(fireTime - elapsed(), SMILTime(animationFrameDelay));
- m_timer.startOneShot(delay.value());
+ SMILTime delay = fireTime - elapsed();
+ if (delay.value() < DocumentTimeline::s_minimumDelay) {
+ serviceOnNextFrame();
+ } else {
+ scheduleWakeUp(delay.value() - DocumentTimeline::s_minimumDelay, AnimationFrame);
+ }
}
-void SMILTimeContainer::scheduleAnimationFrame()
+void SMILTimeContainer::cancelAnimationFrame()
{
- if (!isTimelineRunning())
- return;
-
- m_timer.startOneShot(0);
+ m_frameSchedulingState = Idle;
+ m_wakeupTimer.stop();
}
-void SMILTimeContainer::cancelAnimationFrame()
+void SMILTimeContainer::scheduleWakeUp(double delayTime, FrameSchedulingState frameSchedulingState)
{
- m_timer.stop();
+ ASSERT(frameSchedulingState != Idle);
+ m_wakeupTimer.startOneShot(delayTime);
+ m_frameSchedulingState = frameSchedulingState;
}
-void SMILTimeContainer::timerFired(Timer<SMILTimeContainer>*)
+void SMILTimeContainer::wakeupTimerFired(Timer<SMILTimeContainer>*)
{
- ASSERT(isTimelineRunning());
- updateAnimations(elapsed());
+ if (m_frameSchedulingState == AnimationFrame) {
+ ASSERT(isTimelineRunning());
+ m_frameSchedulingState = Idle;
+ serviceOnNextFrame();
+ } else {
+ ASSERT(m_frameSchedulingState == SynchronizeAnimations);
+ m_frameSchedulingState = Idle;
+ updateAnimationsAndScheduleFrameIfNeeded(elapsed());
+ }
}
void SMILTimeContainer::updateDocumentOrderIndexes()
@@ -266,7 +292,55 @@ struct PriorityCompare {
SMILTime m_elapsed;
};
-void SMILTimeContainer::updateAnimations(SMILTime elapsed, bool seekToTime)
+Document& SMILTimeContainer::document() const
+{
+ ASSERT(m_ownerSVGElement);
+ return m_ownerSVGElement->document();
+}
+
+AnimationClock& SMILTimeContainer::animationClock() const
+{
+ ASSERT(m_animationClock);
+ return *m_animationClock;
+}
+
+double SMILTimeContainer::currentTime() const
+{
+ return animationClock().currentTime();
+}
+
+void SMILTimeContainer::serviceOnNextFrame()
+{
+ if (document().view()) {
+ document().view()->scheduleAnimation();
+ m_frameSchedulingState = AnimationFrame;
+ }
+}
+
+void SMILTimeContainer::serviceAnimations(double monotonicAnimationStartTime)
+{
+ if (m_frameSchedulingState != AnimationFrame)
+ return;
+
+ m_frameSchedulingState = Idle;
+ animationClock().updateTime(monotonicAnimationStartTime);
+ updateAnimationsAndScheduleFrameIfNeeded(elapsed());
+ animationClock().unfreeze();
+}
+
+void SMILTimeContainer::updateAnimationsAndScheduleFrameIfNeeded(SMILTime elapsed, bool seekToTime)
+{
+ SMILTime earliestFireTime = updateAnimations(elapsed, seekToTime);
+ if (!isTimelineRunning())
+ return;
+
+ if (!earliestFireTime.isFinite())
+ return;
+
+ scheduleAnimationFrame(earliestFireTime);
+}
+
+SMILTime SMILTimeContainer::updateAnimations(SMILTime elapsed, bool seekToTime)
{
SMILTime earliestFireTime = SMILTime::unresolved();
@@ -326,8 +400,7 @@ void SMILTimeContainer::updateAnimations(SMILTime elapsed, bool seekToTime)
#ifndef NDEBUG
m_preventScheduledAnimationsChanges = false;
#endif
- scheduleAnimationFrame(earliestFireTime);
- return;
+ return earliestFireTime;
}
// Apply results to target elements.
@@ -338,8 +411,6 @@ void SMILTimeContainer::updateAnimations(SMILTime elapsed, bool seekToTime)
m_preventScheduledAnimationsChanges = false;
#endif
- scheduleAnimationFrame(earliestFireTime);
-
for (unsigned i = 0; i < animationsToApplySize; ++i) {
if (animationsToApply[i]->inDocument() && animationsToApply[i]->isSVGDiscardElement()) {
RefPtr<SVGSMILElement> animDiscard = animationsToApply[i];
@@ -355,6 +426,7 @@ void SMILTimeContainer::updateAnimations(SMILTime elapsed, bool seekToTime)
}
}
}
+ return earliestFireTime;
}
}
« no previous file with comments | « Source/core/svg/animation/SMILTimeContainer.h ('k') | Source/core/svg/graphics/SVGImage.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698