diff options
Diffstat (limited to 'Source/WebCore/dom/ScriptedAnimationController.cpp')
-rw-r--r-- | Source/WebCore/dom/ScriptedAnimationController.cpp | 78 |
1 files changed, 44 insertions, 34 deletions
diff --git a/Source/WebCore/dom/ScriptedAnimationController.cpp b/Source/WebCore/dom/ScriptedAnimationController.cpp index 0c70359..4fbf6d9 100644 --- a/Source/WebCore/dom/ScriptedAnimationController.cpp +++ b/Source/WebCore/dom/ScriptedAnimationController.cpp @@ -29,16 +29,29 @@ #if ENABLE(REQUEST_ANIMATION_FRAME) #include "Document.h" -#include "Element.h" #include "FrameView.h" #include "RequestAnimationFrameCallback.h" +#if USE(REQUEST_ANIMATION_FRAME_TIMER) +#include <algorithm> +#include <wtf/CurrentTime.h> + +using namespace std; + +// Allow a little more than 60fps to make sure we can at least hit that frame rate. +#define MinimumAnimationInterval 0.015 +#endif + namespace WebCore { ScriptedAnimationController::ScriptedAnimationController(Document* document) : m_document(document) , m_nextCallbackId(0) , m_suspendCount(0) +#if USE(REQUEST_ANIMATION_FRAME_TIMER) + , m_animationTimer(this, &ScriptedAnimationController::animationTimerFired) + , m_lastAnimationFrameTime(0) +#endif { } @@ -51,20 +64,17 @@ void ScriptedAnimationController::resume() { --m_suspendCount; if (!m_suspendCount && m_callbacks.size()) - if (FrameView* fv = m_document->view()) - fv->scheduleAnimation(); + scheduleAnimation(); } -ScriptedAnimationController::CallbackId ScriptedAnimationController::registerCallback(PassRefPtr<RequestAnimationFrameCallback> callback, Element* animationElement) +ScriptedAnimationController::CallbackId ScriptedAnimationController::registerCallback(PassRefPtr<RequestAnimationFrameCallback> callback) { ScriptedAnimationController::CallbackId id = m_nextCallbackId++; callback->m_firedOrCancelled = false; callback->m_id = id; - callback->m_element = animationElement; m_callbacks.append(callback); if (!m_suspendCount) - if (FrameView* view = m_document->view()) - view->scheduleAnimation(); + scheduleAnimation(); return id; } @@ -83,37 +93,19 @@ void ScriptedAnimationController::serviceScriptedAnimations(DOMTimeStamp time) { if (!m_callbacks.size() || m_suspendCount) return; - // We want to run the callback for all elements in the document that have registered - // for a callback and that are visible. Running the callbacks can cause new callbacks - // to be registered, existing callbacks to be cancelled, and elements to gain or lose - // visibility so this code has to iterate carefully. - - // FIXME: Currently, this code doesn't do any visibility tests beyond checking display: // First, generate a list of callbacks to consider. Callbacks registered from this point // on are considered only for the "next" frame, not this one. CallbackList callbacks(m_callbacks); - // Firing the callback may cause the visibility of other elements to change. To avoid - // missing any callbacks, we keep iterating through the list of candiate callbacks and firing - // them until nothing new becomes visible. - bool firedCallback; - do { - firedCallback = false; - // A previous iteration may have invalidated style (or layout). Update styles for each iteration - // for now since all we check is the existence of a renderer. - m_document->updateStyleIfNeeded(); - for (size_t i = 0; i < callbacks.size(); ++i) { - RequestAnimationFrameCallback* callback = callbacks[i].get(); - if (!callback->m_firedOrCancelled && (!callback->m_element || callback->m_element->renderer())) { - callback->m_firedOrCancelled = true; - callback->handleEvent(time); - firedCallback = true; - callbacks.remove(i); - break; - } + for (size_t i = 0; i < callbacks.size(); ++i) { + RequestAnimationFrameCallback* callback = callbacks[i].get(); + if (!callback->m_firedOrCancelled) { + callback->m_firedOrCancelled = true; + callback->handleEvent(time); } - } while (firedCallback); + } + m_document->updateStyleIfNeeded(); // Remove any callbacks we fired from the list of pending callbacks. for (size_t i = 0; i < m_callbacks.size();) { @@ -124,10 +116,28 @@ void ScriptedAnimationController::serviceScriptedAnimations(DOMTimeStamp time) } if (m_callbacks.size()) - if (FrameView* view = m_document->view()) - view->scheduleAnimation(); + scheduleAnimation(); } +void ScriptedAnimationController::scheduleAnimation() +{ +#if USE(REQUEST_ANIMATION_FRAME_TIMER) + double scheduleDelay = max<double>(MinimumAnimationInterval - (currentTime() - m_lastAnimationFrameTime), 0); + m_animationTimer.startOneShot(scheduleDelay); +#else + if (FrameView* frameView = m_document->view()) + frameView->scheduleAnimation(); +#endif +} + +#if USE(REQUEST_ANIMATION_FRAME_TIMER) +void ScriptedAnimationController::animationTimerFired(Timer<ScriptedAnimationController>*) +{ + m_lastAnimationFrameTime = currentTime(); + serviceScriptedAnimations(convertSecondsToDOMTimeStamp(m_lastAnimationFrameTime)); +} +#endif + } #endif |