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

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

Issue 179293004: Drive SVG Animations via requestAnimationFrame (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Use AnimationClock. Created 6 years, 10 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..a2e4d15c50a62be2aefb9851126b788711a2281b 100644
--- a/Source/core/svg/animation/SMILTimeContainer.cpp
+++ b/Source/core/svg/animation/SMILTimeContainer.cpp
@@ -26,17 +26,17 @@
#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)
@@ -44,7 +44,9 @@ SMILTimeContainer::SMILTimeContainer(SVGSVGElement* owner)
, m_accumulatedActiveTime(0)
, m_presetStartTime(0)
, m_documentOrderIndexesDirty(false)
- , m_timer(this, &SMILTimeContainer::timerFired)
+ , m_framePending(false)
+ , 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,6 +101,11 @@ void SMILTimeContainer::unschedule(SVGSMILElement* animation, SVGElement* target
scheduled->remove(idx);
}
+bool SMILTimeContainer::hasAnimations() const
+{
+ return !m_scheduledAnimations.isEmpty();
+}
+
void SMILTimeContainer::notifyIntervalsChanged()
{
// Schedule updateAnimations() to be called asynchronously so multiple intervals
@@ -114,7 +121,7 @@ SMILTime SMILTimeContainer::elapsed() const
if (isPaused())
return m_accumulatedActiveTime;
- return currentTime() + m_accumulatedActiveTime - lastResumeTime();
+ return m_animationClock->currentTime() + m_accumulatedActiveTime - lastResumeTime();
}
bool SMILTimeContainer::isPaused() const
@@ -130,7 +137,7 @@ bool SMILTimeContainer::isStarted() const
void SMILTimeContainer::begin()
{
ASSERT(!m_beginTime);
- double now = currentTime();
+ double now = m_animationClock->currentTime();
// If 'm_presetStartTime' is set, the timeline was modified via setElapsed() before the document began.
// In this case pass on 'seekToTime=true' to updateAnimations().
@@ -141,28 +148,33 @@ void SMILTimeContainer::begin()
if (m_pauseTime) {
m_pauseTime = now;
cancelAnimationFrame();
+ } else {
+ // Latch the clock to this time (0 or the preset start time).
+ m_animationClock->updateTime(now);
}
}
void SMILTimeContainer::pause()
{
ASSERT(!isPaused());
- m_pauseTime = currentTime();
+ m_pauseTime = m_animationClock->currentTime();
if (m_beginTime) {
m_accumulatedActiveTime += m_pauseTime - lastResumeTime();
cancelAnimationFrame();
}
m_resumeTime = 0;
+ m_animationClock->unfreeze();
}
void SMILTimeContainer::resume()
{
ASSERT(isPaused());
- m_resumeTime = currentTime();
+ m_resumeTime = m_animationClock->currentTime();
m_pauseTime = 0;
scheduleAnimationFrame();
+ m_animationClock->unfreeze();
}
void SMILTimeContainer::setElapsed(SMILTime time)
@@ -173,10 +185,11 @@ void SMILTimeContainer::setElapsed(SMILTime time)
return;
}
- if (m_beginTime)
- cancelAnimationFrame();
+ m_animationClock->unfreeze();
- double now = currentTime();
+ cancelAnimationFrame();
+
+ double now = m_animationClock->currentTime();
m_beginTime = now - time.value();
m_resumeTime = 0;
if (m_pauseTime) {
@@ -201,6 +214,8 @@ void SMILTimeContainer::setElapsed(SMILTime time)
#endif
updateAnimations(time, true);
+ // Latch the clock to wait for this frame to be sampled by the frame interval.
+ m_animationClock->updateTime(now);
}
bool SMILTimeContainer::isTimelineRunning() const
@@ -216,8 +231,11 @@ void SMILTimeContainer::scheduleAnimationFrame(SMILTime fireTime)
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
+ m_wakeupTimer.startOneShot(delay.value() - DocumentTimeline::s_minimumDelay);
}
void SMILTimeContainer::scheduleAnimationFrame()
@@ -225,18 +243,21 @@ void SMILTimeContainer::scheduleAnimationFrame()
if (!isTimelineRunning())
return;
- m_timer.startOneShot(0);
+ // Could also schedule a wakeup at +0 seconds, but that could still
+ // potentially race with the servicing of the next frame.
+ serviceOnNextFrame();
}
void SMILTimeContainer::cancelAnimationFrame()
{
- m_timer.stop();
+ m_framePending = false;
+ m_wakeupTimer.stop();
}
-void SMILTimeContainer::timerFired(Timer<SMILTimeContainer>*)
+void SMILTimeContainer::wakeupTimerFired(Timer<SMILTimeContainer>*)
{
ASSERT(isTimelineRunning());
- updateAnimations(elapsed());
+ serviceOnNextFrame();
}
void SMILTimeContainer::updateDocumentOrderIndexes()
@@ -266,6 +287,35 @@ struct PriorityCompare {
SMILTime m_elapsed;
};
+Document& SMILTimeContainer::document() const
+{
+ ASSERT(m_ownerSVGElement);
+ return m_ownerSVGElement->document();
+}
+
+void SMILTimeContainer::serviceOnNextFrame()
+{
+ if (document().view()) {
+ document().view()->scheduleAnimation();
+ m_framePending = true;
+ }
+}
+
+void SMILTimeContainer::serviceAnimations(double monotonicAnimationStartTime)
+{
+ if (!m_framePending)
+ return;
+
+ m_framePending = false;
+ // If the clock is frozen at this point, it means the timeline has been
+ // started, but the first animation frame hasn't yet been serviced. If so,
+ // then just keep the clock frozen for this update.
+ if (!m_animationClock->isFrozen())
+ m_animationClock->updateTime(monotonicAnimationStartTime);
+ updateAnimations(elapsed());
+ m_animationClock->unfreeze();
+}
+
void SMILTimeContainer::updateAnimations(SMILTime elapsed, bool seekToTime)
{
SMILTime earliestFireTime = SMILTime::unresolved();
« 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