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

Side by Side Diff: Source/core/svg/animation/SMILTimeContainer.cpp

Issue 193053002: Tweaks and fixes to the SMILTimeContainer frame scheduling logic (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Rebase. 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « Source/core/svg/animation/SMILTimeContainer.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2008 Apple Inc. All rights reserved. 2 * Copyright (C) 2008 Apple Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions 5 * modification, are permitted provided that the following conditions
6 * are met: 6 * are met:
7 * 1. Redistributions of source code must retain the above copyright 7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer. 8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright 9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the 10 * notice, this list of conditions and the following disclaimer in the
(...skipping 19 matching lines...) Expand all
30 #include "core/animation/DocumentTimeline.h" 30 #include "core/animation/DocumentTimeline.h"
31 #include "core/dom/ElementTraversal.h" 31 #include "core/dom/ElementTraversal.h"
32 #include "core/frame/FrameView.h" 32 #include "core/frame/FrameView.h"
33 #include "core/svg/SVGSVGElement.h" 33 #include "core/svg/SVGSVGElement.h"
34 #include "core/svg/animation/SVGSMILElement.h" 34 #include "core/svg/animation/SVGSMILElement.h"
35 35
36 using namespace std; 36 using namespace std;
37 37
38 namespace WebCore { 38 namespace WebCore {
39 39
40 static const double initialFrameDelay = 0.025;
41
40 // Every entry-point that calls updateAnimations() should instantiate a 42 // Every entry-point that calls updateAnimations() should instantiate a
41 // DiscardScope to prevent deletion of the ownerElement (and hence itself.) 43 // DiscardScope to prevent deletion of the ownerElement (and hence itself.)
42 class DiscardScope { 44 class DiscardScope {
43 public: 45 public:
44 explicit DiscardScope(SVGSVGElement& timeContainerOwner) : m_discardScopeEle ment(&timeContainerOwner) { } 46 explicit DiscardScope(SVGSVGElement& timeContainerOwner) : m_discardScopeEle ment(&timeContainerOwner) { }
45 47
46 private: 48 private:
47 RefPtr<SVGSVGElement> m_discardScopeElement; 49 RefPtr<SVGSVGElement> m_discardScopeElement;
48 }; 50 };
49 51
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
109 size_t idx = scheduled->find(animation); 111 size_t idx = scheduled->find(animation);
110 ASSERT(idx != kNotFound); 112 ASSERT(idx != kNotFound);
111 scheduled->remove(idx); 113 scheduled->remove(idx);
112 } 114 }
113 115
114 bool SMILTimeContainer::hasAnimations() const 116 bool SMILTimeContainer::hasAnimations() const
115 { 117 {
116 return !m_scheduledAnimations.isEmpty(); 118 return !m_scheduledAnimations.isEmpty();
117 } 119 }
118 120
121 bool SMILTimeContainer::hasPendingSynchronization() const
122 {
123 return m_frameSchedulingState == SynchronizeAnimations && m_wakeupTimer.isAc tive() && !m_wakeupTimer.nextFireInterval();
124 }
125
119 void SMILTimeContainer::notifyIntervalsChanged() 126 void SMILTimeContainer::notifyIntervalsChanged()
120 { 127 {
121 if (!isStarted()) 128 if (!isStarted())
122 return; 129 return;
123 // Schedule updateAnimations() to be called asynchronously so multiple inter vals 130 // Schedule updateAnimations() to be called asynchronously so multiple inter vals
124 // can change with updateAnimations() only called once at the end. 131 // can change with updateAnimations() only called once at the end.
125 if (m_frameSchedulingState == SynchronizeAnimations && m_wakeupTimer.isActiv e() && !m_wakeupTimer.nextFireInterval()) 132 if (hasPendingSynchronization())
126 return; 133 return;
127 cancelAnimationFrame(); 134 cancelAnimationFrame();
128 scheduleWakeUp(0, SynchronizeAnimations); 135 scheduleWakeUp(0, SynchronizeAnimations);
129 } 136 }
130 137
131 SMILTime SMILTimeContainer::elapsed() const 138 SMILTime SMILTimeContainer::elapsed() const
132 { 139 {
133 if (!m_beginTime) 140 if (!m_beginTime)
134 return 0; 141 return 0;
135 142
(...skipping 20 matching lines...) Expand all
156 163
157 // If 'm_presetStartTime' is set, the timeline was modified via setElapsed() before the document began. 164 // If 'm_presetStartTime' is set, the timeline was modified via setElapsed() before the document began.
158 // In this case pass on 'seekToTime=true' to updateAnimations(). 165 // In this case pass on 'seekToTime=true' to updateAnimations().
159 m_beginTime = now - m_presetStartTime; 166 m_beginTime = now - m_presetStartTime;
160 DiscardScope discardScope(m_ownerSVGElement); 167 DiscardScope discardScope(m_ownerSVGElement);
161 SMILTime earliestFireTime = updateAnimations(SMILTime(m_presetStartTime), m_ presetStartTime ? true : false); 168 SMILTime earliestFireTime = updateAnimations(SMILTime(m_presetStartTime), m_ presetStartTime ? true : false);
162 m_presetStartTime = 0; 169 m_presetStartTime = 0;
163 170
164 if (m_pauseTime) { 171 if (m_pauseTime) {
165 m_pauseTime = now; 172 m_pauseTime = now;
166 cancelAnimationFrame(); 173 // If updateAnimations() caused new syncbase instance to be generated,
167 } else { 174 // we don't want to cancel those. Excepting that, no frame should've
175 // been scheduled at this point.
176 ASSERT(m_frameSchedulingState == Idle || m_frameSchedulingState == Synch ronizeAnimations);
177 } else if (!hasPendingSynchronization()) {
168 ASSERT(isTimelineRunning()); 178 ASSERT(isTimelineRunning());
169 // If the timeline is running, and there's pending animation updates, 179 // If the timeline is running, and there's pending animation updates,
170 // always perform the first update after the timeline was started using 180 // always perform the first update after the timeline was started using
171 // the wake-up mechanism. 181 // the wake-up mechanism.
172 if (earliestFireTime.isFinite()) { 182 if (earliestFireTime.isFinite()) {
173 scheduleWakeUp(DocumentTimeline::s_minimumDelay, SynchronizeAnimatio ns); 183 SMILTime delay = earliestFireTime - elapsed();
184 scheduleWakeUp(std::max(initialFrameDelay, delay.value()), Synchroni zeAnimations);
174 } 185 }
175 } 186 }
176 } 187 }
177 188
178 void SMILTimeContainer::pause() 189 void SMILTimeContainer::pause()
179 { 190 {
180 ASSERT(!isPaused()); 191 ASSERT(!isPaused());
181 m_pauseTime = currentTime(); 192 m_pauseTime = currentTime();
182 193
183 if (m_beginTime) { 194 if (m_beginTime) {
184 m_accumulatedActiveTime += m_pauseTime - lastResumeTime(); 195 m_accumulatedActiveTime += m_pauseTime - lastResumeTime();
185 cancelAnimationFrame(); 196 cancelAnimationFrame();
186 } 197 }
187 m_resumeTime = 0; 198 m_resumeTime = 0;
188 } 199 }
189 200
190 void SMILTimeContainer::resume() 201 void SMILTimeContainer::resume()
191 { 202 {
192 ASSERT(isPaused()); 203 ASSERT(isPaused());
193 m_resumeTime = currentTime(); 204 m_resumeTime = currentTime();
194 205
195 m_pauseTime = 0; 206 m_pauseTime = 0;
196 serviceOnNextFrame(); 207 scheduleWakeUp(0, SynchronizeAnimations);
197 } 208 }
198 209
199 void SMILTimeContainer::setElapsed(SMILTime time) 210 void SMILTimeContainer::setElapsed(SMILTime time)
200 { 211 {
201 // If the documment didn't begin yet, record a new start time, we'll seek to once its possible. 212 // If the documment didn't begin yet, record a new start time, we'll seek to once its possible.
202 if (!m_beginTime) { 213 if (!m_beginTime) {
203 m_presetStartTime = time.value(); 214 m_presetStartTime = time.value();
204 return; 215 return;
205 } 216 }
206 217
(...skipping 28 matching lines...) Expand all
235 } 246 }
236 247
237 bool SMILTimeContainer::isTimelineRunning() const 248 bool SMILTimeContainer::isTimelineRunning() const
238 { 249 {
239 return m_beginTime && !isPaused(); 250 return m_beginTime && !isPaused();
240 } 251 }
241 252
242 void SMILTimeContainer::scheduleAnimationFrame(SMILTime fireTime) 253 void SMILTimeContainer::scheduleAnimationFrame(SMILTime fireTime)
243 { 254 {
244 ASSERT(isTimelineRunning() && fireTime.isFinite()); 255 ASSERT(isTimelineRunning() && fireTime.isFinite());
256 ASSERT(!m_wakeupTimer.isActive());
245 257
246 SMILTime delay = fireTime - elapsed(); 258 SMILTime delay = fireTime - elapsed();
247 if (delay.value() < DocumentTimeline::s_minimumDelay) { 259 if (delay.value() < DocumentTimeline::s_minimumDelay) {
248 serviceOnNextFrame(); 260 serviceOnNextFrame();
249 } else { 261 } else {
250 scheduleWakeUp(delay.value() - DocumentTimeline::s_minimumDelay, Animati onFrame); 262 scheduleWakeUp(delay.value() - DocumentTimeline::s_minimumDelay, FutureA nimationFrame);
251 } 263 }
252 } 264 }
253 265
254 void SMILTimeContainer::cancelAnimationFrame() 266 void SMILTimeContainer::cancelAnimationFrame()
255 { 267 {
256 m_frameSchedulingState = Idle; 268 m_frameSchedulingState = Idle;
257 m_wakeupTimer.stop(); 269 m_wakeupTimer.stop();
258 } 270 }
259 271
260 void SMILTimeContainer::scheduleWakeUp(double delayTime, FrameSchedulingState fr ameSchedulingState) 272 void SMILTimeContainer::scheduleWakeUp(double delayTime, FrameSchedulingState fr ameSchedulingState)
261 { 273 {
262 ASSERT(frameSchedulingState != Idle); 274 ASSERT(frameSchedulingState == SynchronizeAnimations || frameSchedulingState == FutureAnimationFrame);
263 m_wakeupTimer.startOneShot(delayTime, FROM_HERE); 275 m_wakeupTimer.startOneShot(delayTime, FROM_HERE);
264 m_frameSchedulingState = frameSchedulingState; 276 m_frameSchedulingState = frameSchedulingState;
265 } 277 }
266 278
267 void SMILTimeContainer::wakeupTimerFired(Timer<SMILTimeContainer>*) 279 void SMILTimeContainer::wakeupTimerFired(Timer<SMILTimeContainer>*)
268 { 280 {
269 if (m_frameSchedulingState == AnimationFrame) { 281 ASSERT(m_frameSchedulingState == SynchronizeAnimations || m_frameSchedulingS tate == FutureAnimationFrame);
282 if (m_frameSchedulingState == FutureAnimationFrame) {
270 ASSERT(isTimelineRunning()); 283 ASSERT(isTimelineRunning());
271 m_frameSchedulingState = Idle; 284 m_frameSchedulingState = Idle;
272 serviceOnNextFrame(); 285 serviceOnNextFrame();
273 } else { 286 } else {
274 ASSERT(m_frameSchedulingState == SynchronizeAnimations);
275 m_frameSchedulingState = Idle; 287 m_frameSchedulingState = Idle;
276 DiscardScope discardScope(m_ownerSVGElement); 288 DiscardScope discardScope(m_ownerSVGElement);
277 updateAnimationsAndScheduleFrameIfNeeded(elapsed()); 289 updateAnimationsAndScheduleFrameIfNeeded(elapsed());
278 } 290 }
279 } 291 }
280 292
281 void SMILTimeContainer::updateDocumentOrderIndexes() 293 void SMILTimeContainer::updateDocumentOrderIndexes()
282 { 294 {
283 unsigned timingElementCount = 0; 295 unsigned timingElementCount = 0;
284 for (SVGSMILElement* element = Traversal<SVGSMILElement>::firstWithin(m_owne rSVGElement); element; element = Traversal<SVGSMILElement>::next(*element, &m_ow nerSVGElement)) 296 for (SVGSMILElement* element = Traversal<SVGSMILElement>::firstWithin(m_owne rSVGElement); element; element = Traversal<SVGSMILElement>::next(*element, &m_ow nerSVGElement))
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
335 m_frameSchedulingState = Idle; 347 m_frameSchedulingState = Idle;
336 animationClock().updateTime(monotonicAnimationStartTime); 348 animationClock().updateTime(monotonicAnimationStartTime);
337 DiscardScope discardScope(m_ownerSVGElement); 349 DiscardScope discardScope(m_ownerSVGElement);
338 updateAnimationsAndScheduleFrameIfNeeded(elapsed()); 350 updateAnimationsAndScheduleFrameIfNeeded(elapsed());
339 animationClock().unfreeze(); 351 animationClock().unfreeze();
340 } 352 }
341 353
342 void SMILTimeContainer::updateAnimationsAndScheduleFrameIfNeeded(SMILTime elapse d, bool seekToTime) 354 void SMILTimeContainer::updateAnimationsAndScheduleFrameIfNeeded(SMILTime elapse d, bool seekToTime)
343 { 355 {
344 SMILTime earliestFireTime = updateAnimations(elapsed, seekToTime); 356 SMILTime earliestFireTime = updateAnimations(elapsed, seekToTime);
357 // If updateAnimations() ended up triggering a synchronization (most likely
358 // via syncbases), then give that priority.
359 if (hasPendingSynchronization())
360 return;
361
345 if (!isTimelineRunning()) 362 if (!isTimelineRunning())
346 return; 363 return;
347 364
348 if (!earliestFireTime.isFinite()) 365 if (!earliestFireTime.isFinite())
349 return; 366 return;
350 367
351 scheduleAnimationFrame(earliestFireTime); 368 scheduleAnimationFrame(earliestFireTime);
352 } 369 }
353 370
354 SMILTime SMILTimeContainer::updateAnimations(SMILTime elapsed, bool seekToTime) 371 SMILTime SMILTimeContainer::updateAnimations(SMILTime elapsed, bool seekToTime)
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
434 if (animDiscard->inDocument()) { 451 if (animDiscard->inDocument()) {
435 animDiscard->remove(IGNORE_EXCEPTION); 452 animDiscard->remove(IGNORE_EXCEPTION);
436 ASSERT(!animDiscard->inDocument()); 453 ASSERT(!animDiscard->inDocument());
437 } 454 }
438 } 455 }
439 } 456 }
440 return earliestFireTime; 457 return earliestFireTime;
441 } 458 }
442 459
443 } 460 }
OLDNEW
« no previous file with comments | « Source/core/svg/animation/SMILTimeContainer.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698