Expose high-resolution on requestAnimationFrame callback
authornduca@chromium.org <nduca@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 12 Oct 2012 02:45:10 +0000 (02:45 +0000)
committernduca@chromium.org <nduca@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 12 Oct 2012 02:45:10 +0000 (02:45 +0000)
https://bugs.webkit.org/show_bug.cgi?id=66683

This changes requestAnimationFrame's animationStartTime argument
to be a high resolution DOM timestamp, per disucssion here:
http://lists.w3.org/Archives/Public/public-web-perf/2012Apr/0004.html

Reviewed by James Robinson.

Source/WebCore:

Covered by existing requestAnimationFrame tests.

* dom/Document.cpp:
(WebCore::Document::serviceScriptedAnimations):
* dom/Document.h:
(Document):
* dom/ScriptedAnimationController.cpp:
(WebCore::ScriptedAnimationController::ScriptedAnimationController):
(WebCore::ScriptedAnimationController::serviceScriptedAnimations):
(WebCore):
(WebCore::ScriptedAnimationController::windowScreenDidChange):
(WebCore::ScriptedAnimationController::scheduleAnimation):
(WebCore::ScriptedAnimationController::animationTimerFired):
(WebCore::ScriptedAnimationController::displayRefreshFired):
* dom/ScriptedAnimationController.h:
(ScriptedAnimationController):
* page/FrameView.cpp:
(WebCore::FrameView::serviceScriptedAnimations):
* page/FrameView.h:
(FrameView):
* platform/graphics/DisplayRefreshMonitor.cpp:
(WebCore::DisplayRefreshMonitor::DisplayRefreshMonitor):
(WebCore::DisplayRefreshMonitor::notifyClients):
* platform/graphics/DisplayRefreshMonitor.h:
(DisplayRefreshMonitor):
* platform/graphics/blackberry/DisplayRefreshMonitorBlackBerry.cpp:
(WebCore::DisplayRefreshMonitor::displayLinkFired):
* platform/graphics/mac/DisplayRefreshMonitorMac.cpp:
(WebCore):
(WebCore::DisplayRefreshMonitor::requestRefreshCallback):
(WebCore::DisplayRefreshMonitor::displayLinkFired):

Source/WebKit/chromium:

* src/PageWidgetDelegate.cpp:
(WebKit::PageWidgetDelegate::animate):
* src/WebViewImpl.cpp:
(WebKit::WebViewImpl::updateAnimations):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@131131 268f45cc-cd09-0410-ab3c-d52691b4dbfc

18 files changed:
Source/WebCore/ChangeLog
Source/WebCore/WebCore.exp.in
Source/WebCore/bindings/js/JSRequestAnimationFrameCallbackCustom.cpp
Source/WebCore/dom/Document.cpp
Source/WebCore/dom/Document.h
Source/WebCore/dom/RequestAnimationFrameCallback.h
Source/WebCore/dom/RequestAnimationFrameCallback.idl
Source/WebCore/dom/ScriptedAnimationController.cpp
Source/WebCore/dom/ScriptedAnimationController.h
Source/WebCore/page/FrameView.cpp
Source/WebCore/page/FrameView.h
Source/WebCore/platform/graphics/DisplayRefreshMonitor.cpp
Source/WebCore/platform/graphics/DisplayRefreshMonitor.h
Source/WebCore/platform/graphics/blackberry/DisplayRefreshMonitorBlackBerry.cpp
Source/WebCore/platform/graphics/mac/DisplayRefreshMonitorMac.cpp
Source/WebKit/chromium/ChangeLog
Source/WebKit/chromium/src/PageWidgetDelegate.cpp
Source/WebKit/chromium/src/WebViewImpl.cpp

index cdcaa99..79de067 100644 (file)
@@ -1,3 +1,46 @@
+2012-10-11  Nat Duca  <nduca@chromium.org>
+
+        Expose high-resolution on requestAnimationFrame callback
+        https://bugs.webkit.org/show_bug.cgi?id=66683
+
+        This changes requestAnimationFrame's animationStartTime argument
+        to be a high resolution DOM timestamp, per disucssion here:
+        http://lists.w3.org/Archives/Public/public-web-perf/2012Apr/0004.html
+
+        Reviewed by James Robinson.
+
+        Covered by existing requestAnimationFrame tests.
+
+        * dom/Document.cpp:
+        (WebCore::Document::serviceScriptedAnimations):
+        * dom/Document.h:
+        (Document):
+        * dom/ScriptedAnimationController.cpp:
+        (WebCore::ScriptedAnimationController::ScriptedAnimationController):
+        (WebCore::ScriptedAnimationController::serviceScriptedAnimations):
+        (WebCore):
+        (WebCore::ScriptedAnimationController::windowScreenDidChange):
+        (WebCore::ScriptedAnimationController::scheduleAnimation):
+        (WebCore::ScriptedAnimationController::animationTimerFired):
+        (WebCore::ScriptedAnimationController::displayRefreshFired):
+        * dom/ScriptedAnimationController.h:
+        (ScriptedAnimationController):
+        * page/FrameView.cpp:
+        (WebCore::FrameView::serviceScriptedAnimations):
+        * page/FrameView.h:
+        (FrameView):
+        * platform/graphics/DisplayRefreshMonitor.cpp:
+        (WebCore::DisplayRefreshMonitor::DisplayRefreshMonitor):
+        (WebCore::DisplayRefreshMonitor::notifyClients):
+        * platform/graphics/DisplayRefreshMonitor.h:
+        (DisplayRefreshMonitor):
+        * platform/graphics/blackberry/DisplayRefreshMonitorBlackBerry.cpp:
+        (WebCore::DisplayRefreshMonitor::displayLinkFired):
+        * platform/graphics/mac/DisplayRefreshMonitorMac.cpp:
+        (WebCore):
+        (WebCore::DisplayRefreshMonitor::requestRefreshCallback):
+        (WebCore::DisplayRefreshMonitor::displayLinkFired):
+
 2012-10-11  Sheriff Bot  <webkit.review.bot@gmail.com>
 
         Unreviewed, rolling out r131100.
index fd2cd77..8b220d6 100644 (file)
@@ -2408,7 +2408,7 @@ __ZN7WebCore33QLPreviewGetSupportedMIMETypesSetEv
 #endif
 
 #if ENABLE(REQUEST_ANIMATION_FRAME)
-__ZN7WebCore9FrameView25serviceScriptedAnimationsEy
+__ZN7WebCore9FrameView25serviceScriptedAnimationsEd
 #endif
 
 #if ENABLE(SHADOW_DOM)
index eb2ab3c..296ee8b 100644 (file)
@@ -33,7 +33,7 @@ using namespace JSC;
 
 namespace WebCore {
 
-bool JSRequestAnimationFrameCallback::handleEvent(DOMTimeStamp time)
+bool JSRequestAnimationFrameCallback::handleEvent(double highResNowMs)
 {
     if (!canInvokeCallback())
         return true;
@@ -43,7 +43,7 @@ bool JSRequestAnimationFrameCallback::handleEvent(DOMTimeStamp time)
     JSLockHolder lock(m_data->globalObject()->globalData());
 
     MarkedArgumentBuffer args;
-    args.append(jsNumber(time));
+    args.append(jsNumber(highResNowMs));
 
     bool raisedException = false;
     m_data->invokeCallback(args, &raisedException);
index f4d158d..b56005c 100644 (file)
@@ -5566,11 +5566,11 @@ void Document::webkitCancelAnimationFrame(int id)
     m_scriptedAnimationController->cancelCallback(id);
 }
 
-void Document::serviceScriptedAnimations(DOMTimeStamp time)
+void Document::serviceScriptedAnimations(double monotonicAnimationStartTime)
 {
     if (!m_scriptedAnimationController)
         return;
-    m_scriptedAnimationController->serviceScriptedAnimations(time);
+    m_scriptedAnimationController->serviceScriptedAnimations(monotonicAnimationStartTime);
 }
 #endif
 
index 5df5b6c..290f1c0 100644 (file)
@@ -1093,7 +1093,7 @@ public:
 #if ENABLE(REQUEST_ANIMATION_FRAME)
     int webkitRequestAnimationFrame(PassRefPtr<RequestAnimationFrameCallback>);
     void webkitCancelAnimationFrame(int id);
-    void serviceScriptedAnimations(DOMTimeStamp);
+    void serviceScriptedAnimations(double monotonicAnimationStartTime);
 #endif
 
     virtual EventTarget* errorEventTarget();
index a867922..f134726 100644 (file)
@@ -31,7 +31,6 @@
 #ifndef RequestAnimationFrameCallback_h
 #define RequestAnimationFrameCallback_h
 
-#include "DOMTimeStamp.h"
 #include <wtf/RefCounted.h>
 
 namespace WebCore {
@@ -39,7 +38,7 @@ namespace WebCore {
 class RequestAnimationFrameCallback : public RefCounted<RequestAnimationFrameCallback> {
 public:
     virtual ~RequestAnimationFrameCallback() { }
-    virtual bool handleEvent(DOMTimeStamp) = 0;
+    virtual bool handleEvent(double highResTimeMs) = 0;
 
     int m_id;
     bool m_firedOrCancelled;
@@ -48,4 +47,3 @@ public:
 }
 
 #endif // RequestAnimationFrameCallback_h
-
index 4da6820..7e8e1d7 100644 (file)
@@ -33,11 +33,13 @@ module core {
         Callback,
         Conditional=REQUEST_ANIMATION_FRAME,
     ] RequestAnimationFrameCallback{
+        // highResTime is passed as high resolution timestamp, see
+        // http://www.w3.org/TR/hr-time/ for details.
 #if defined(V8_BINDING) && V8_BINDING
-        boolean handleEvent(in DOMTimeStamp time);
+        boolean handleEvent(in double highResTime);
 #else
-        [Custom] boolean handleEvent(in DOMTimeStamp time);
+        [Custom] boolean handleEvent(in double highResTime);
 #endif
-        
+
     };
 }
index 628f109..2f7862b 100644 (file)
@@ -29,6 +29,7 @@
 #if ENABLE(REQUEST_ANIMATION_FRAME)
 
 #include "Document.h"
+#include "DocumentLoader.h"
 #include "FrameView.h"
 #include "InspectorInstrumentation.h"
 #include "RequestAnimationFrameCallback.h"
@@ -52,7 +53,7 @@ ScriptedAnimationController::ScriptedAnimationController(Document* document, Pla
     , m_suspendCount(0)
 #if USE(REQUEST_ANIMATION_FRAME_TIMER)
     , m_animationTimer(this, &ScriptedAnimationController::animationTimerFired)
-    , m_lastAnimationFrameTime(0)
+    , m_lastAnimationFrameTimeMonotonic(0)
 #if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
     , m_useTimer(false)
 #endif
@@ -107,11 +108,13 @@ void ScriptedAnimationController::cancelCallback(CallbackId id)
     }
 }
 
-void ScriptedAnimationController::serviceScriptedAnimations(DOMTimeStamp time)
+void ScriptedAnimationController::serviceScriptedAnimations(double monotonicTimeNow)
 {
     if (!m_callbacks.size() || m_suspendCount || (m_document->settings() && !m_document->settings()->requestAnimationFrameEnabled()))
         return;
 
+    double highResNowMs = 1000.0 * m_document->loader()->timing()->monotonicTimeToZeroBasedDocumentTime(monotonicTimeNow);
+
     // 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);
@@ -125,7 +128,7 @@ void ScriptedAnimationController::serviceScriptedAnimations(DOMTimeStamp time)
         if (!callback->m_firedOrCancelled) {
             callback->m_firedOrCancelled = true;
             InspectorInstrumentationCookie cookie = InspectorInstrumentation::willFireAnimationFrame(m_document, callback->m_id);
-            callback->handleEvent(time);
+            callback->handleEvent(highResNowMs);
             InspectorInstrumentation::didFireAnimationFrame(cookie);
         }
     }
@@ -141,7 +144,7 @@ void ScriptedAnimationController::serviceScriptedAnimations(DOMTimeStamp time)
     if (m_callbacks.size())
         scheduleAnimation();
 }
-    
+
 void ScriptedAnimationController::windowScreenDidChange(PlatformDisplayID displayID)
 {
     if (m_document->settings() && !m_document->settings()->requestAnimationFrameEnabled())
@@ -150,7 +153,7 @@ void ScriptedAnimationController::windowScreenDidChange(PlatformDisplayID displa
     DisplayRefreshMonitorManager::sharedManager()->windowScreenDidChange(displayID, this);
 #else
     UNUSED_PARAM(displayID);
-#endif    
+#endif
 }
 
 void ScriptedAnimationController::scheduleAnimation()
@@ -163,14 +166,14 @@ void ScriptedAnimationController::scheduleAnimation()
     if (!m_useTimer) {
         if (DisplayRefreshMonitorManager::sharedManager()->scheduleAnimation(this))
             return;
-            
+
         m_useTimer = true;
     }
 #endif
     if (m_animationTimer.isActive())
         return;
-        
-    double scheduleDelay = max<double>(MinimumAnimationInterval - (currentTime() - m_lastAnimationFrameTime), 0);
+
+    double scheduleDelay = max<double>(MinimumAnimationInterval - (monotonicallyIncreasingTime() - m_lastAnimationFrameTimeMonotonic), 0);
     m_animationTimer.startOneShot(scheduleDelay);
 #else
     if (FrameView* frameView = m_document->view())
@@ -181,12 +184,19 @@ void ScriptedAnimationController::scheduleAnimation()
 #if USE(REQUEST_ANIMATION_FRAME_TIMER)
 void ScriptedAnimationController::animationTimerFired(Timer<ScriptedAnimationController>*)
 {
-    m_lastAnimationFrameTime = currentTime();
-    serviceScriptedAnimations(convertSecondsToDOMTimeStamp(m_lastAnimationFrameTime));
+    m_lastAnimationFrameTimeMonotonic = monotonicallyIncreasingTime();
+    serviceScriptedAnimations(m_lastAnimationFrameTimeMonotonic);
+}
+#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
+void ScriptedAnimationController::displayRefreshFired(double monotonicTimeNow)
+{
+    serviceScriptedAnimations(monotonicTimeNow);
 }
 #endif
+#endif
+
+
 
 }
 
 #endif
-
index 51c36b9..450a87b 100644 (file)
@@ -61,7 +61,7 @@ public:
 
     CallbackId registerCallback(PassRefPtr<RequestAnimationFrameCallback>);
     void cancelCallback(CallbackId);
-    void serviceScriptedAnimations(DOMTimeStamp);
+    void serviceScriptedAnimations(double monotonicTimeNow);
 
     void suspend();
     void resume();
@@ -70,7 +70,7 @@ public:
 
 private:
     ScriptedAnimationController(Document*, PlatformDisplayID);
-    
+
     typedef Vector<RefPtr<RequestAnimationFrameCallback> > CallbackList;
     CallbackList m_callbacks;
 
@@ -83,11 +83,11 @@ private:
 #if USE(REQUEST_ANIMATION_FRAME_TIMER)
     void animationTimerFired(Timer<ScriptedAnimationController>*);
     Timer<ScriptedAnimationController> m_animationTimer;
-    double m_lastAnimationFrameTime;
+    double m_lastAnimationFrameTimeMonotonic;
 
 #if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
     // Override for DisplayRefreshMonitorClient
-    virtual void displayRefreshFired(double timestamp) { serviceScriptedAnimations(convertSecondsToDOMTimeStamp(timestamp)); }
+    virtual void displayRefreshFired(double timestamp);
 
     bool m_useTimer;
 #endif
@@ -99,4 +99,3 @@ private:
 #endif // ENABLE(REQUEST_ANIMATION_FRAME)
 
 #endif // ScriptedAnimationController_h
-
index f3d7fec..5006b95 100644 (file)
@@ -2264,7 +2264,7 @@ void FrameView::unscheduleRelayout()
 }
 
 #if ENABLE(REQUEST_ANIMATION_FRAME)
-void FrameView::serviceScriptedAnimations(DOMTimeStamp time)
+void FrameView::serviceScriptedAnimations(double monotonicAnimationStartTime)
 {
     for (Frame* frame = m_frame.get(); frame; frame = frame->tree()->traverseNext()) {
         frame->view()->serviceScrollAnimations();
@@ -2276,7 +2276,7 @@ void FrameView::serviceScriptedAnimations(DOMTimeStamp time)
         documents.append(frame->document());
 
     for (size_t i = 0; i < documents.size(); ++i)
-        documents[i]->serviceScriptedAnimations(time);
+        documents[i]->serviceScriptedAnimations(monotonicAnimationStartTime);
 }
 #endif
 
index 7d060ef..944d9d1 100644 (file)
@@ -115,7 +115,7 @@ public:
     bool needsFullRepaint() const { return m_doFullRepaint; }
 
 #if ENABLE(REQUEST_ANIMATION_FRAME)
-    void serviceScriptedAnimations(DOMTimeStamp);
+    void serviceScriptedAnimations(double monotonicAnimationStartTime);
 #endif
 
 #if USE(ACCELERATED_COMPOSITING)
index b2c8b2d..423d147 100644 (file)
@@ -53,7 +53,7 @@ void DisplayRefreshMonitorClient::fireDisplayRefreshIfNeeded(double timestamp)
 }
 
 DisplayRefreshMonitor::DisplayRefreshMonitor(PlatformDisplayID displayID)
-    : m_timestamp(0)
+    : m_monotonicAnimationStartTime(0)
     , m_active(true)
     , m_scheduled(false)
     , m_previousFrameDone(true)
@@ -91,7 +91,7 @@ bool DisplayRefreshMonitor::removeClient(DisplayRefreshMonitorClient* client)
 
 void DisplayRefreshMonitor::displayDidRefresh()
 {
-    double timestamp;
+    double monotonicAnimationStartTime;
     {
         MutexLocker lock(m_mutex);
          if (!m_scheduled)
@@ -100,7 +100,7 @@ void DisplayRefreshMonitor::displayDidRefresh()
             m_unscheduledFireCount = 0;
 
         m_scheduled = false;
-        timestamp = m_timestamp;
+        monotonicAnimationStartTime = m_monotonicAnimationStartTime;
     }
 
     // The call back can cause all our clients to be unregistered, so we need to protect
@@ -110,7 +110,7 @@ void DisplayRefreshMonitor::displayDidRefresh()
     Vector<DisplayRefreshMonitorClient*> clients;
     copyToVector(m_clients, clients);
     for (size_t i = 0; i < clients.size(); ++i)
-        clients[i]->fireDisplayRefreshIfNeeded(timestamp);
+        clients[i]->fireDisplayRefreshIfNeeded(monotonicAnimationStartTime);
 
     {
         MutexLocker lock(m_mutex);
index 6917d6e..ddf4b35 100644 (file)
@@ -121,7 +121,7 @@ private:
     void displayDidRefresh();
     static void handleDisplayRefreshedNotificationOnMainThread(void* data);
 
-    double m_timestamp;
+    double m_monotonicAnimationStartTime;
     bool m_active;
     bool m_scheduled;
     bool m_previousFrameDone;
index b85afc3..0281aa1 100644 (file)
@@ -84,7 +84,7 @@ void DisplayRefreshMonitor::displayLinkFired()
 
     m_previousFrameDone = false;
 
-    m_timestamp = currentTime();
+    m_monotonicAnimationStartTime = monotonicallyIncreasingTime();
 
     callOnMainThread(handleDisplayRefreshedNotificationOnMainThread, this);
     m_mutex.unlock();
index dfdd8de..e5c1ad3 100644 (file)
@@ -45,7 +45,7 @@ static CVReturn displayLinkCallback(CVDisplayLinkRef, const CVTimeStamp* now, co
 
     return kCVReturnSuccess;
 }
+
 DisplayRefreshMonitor::~DisplayRefreshMonitor()
 {
     if (m_displayLink) {
@@ -61,7 +61,7 @@ bool DisplayRefreshMonitor::requestRefreshCallback()
 {
     if (!m_active)
         return false;
-        
+
     if (!m_displayLink) {
         m_active = false;
         CVReturn error = CVDisplayLinkCreateWithCGDisplay(m_displayID, &m_displayLink);
@@ -78,7 +78,7 @@ bool DisplayRefreshMonitor::requestRefreshCallback()
 
         m_active = true;
     }
-    
+
     MutexLocker lock(m_mutex);
     m_scheduled = true;
     return true;
@@ -92,9 +92,11 @@ void DisplayRefreshMonitor::displayLinkFired(double nowSeconds, double outputTim
 
     m_previousFrameDone = false;
 
-    double webKitNow = currentTime();
-    m_timestamp = webKitNow - nowSeconds + outputTimeSeconds;
-    
+    double webKitMonotonicNow = monotonicallyIncreasingTime();
+    double timeUntilOutput = outputTimeSeconds - nowSeconds;
+    // FIXME: Should this be using webKitMonotonicNow?
+    m_monotonicAnimationStartTime = webKitMonotonicNow + timeUntilOutput;
+
     callOnMainThread(handleDisplayRefreshedNotificationOnMainThread, this);
 }
 
index c10f171..eed4965 100644 (file)
@@ -1,3 +1,19 @@
+2012-10-11  Nat Duca  <nduca@chromium.org>
+
+        Expose high-resolution on requestAnimationFrame callback
+        https://bugs.webkit.org/show_bug.cgi?id=66683
+
+        This changes requestAnimationFrame's animationStartTime argument
+        to be a high resolution DOM timestamp, per disucssion here:
+        http://lists.w3.org/Archives/Public/public-web-perf/2012Apr/0004.html
+
+        Reviewed by James Robinson.
+
+        * src/PageWidgetDelegate.cpp:
+        (WebKit::PageWidgetDelegate::animate):
+        * src/WebViewImpl.cpp:
+        (WebKit::WebViewImpl::updateAnimations):
+
 2012-10-11  Jay Civelli  <jcivelli@chromium.org>
 
         Test for a fix for a crasher when generating MHTML for a page containing SVG images.
index 0c377c7..071c22a 100644 (file)
@@ -59,8 +59,7 @@ void PageWidgetDelegate::animate(Page* page, double monotonicFrameBeginTime)
     FrameView* view = mainFrameView(page);
     if (!view)
         return;
-    double timeShift = currentTime() - monotonicallyIncreasingTime();
-    view->serviceScriptedAnimations(convertSecondsToDOMTimeStamp(monotonicFrameBeginTime + timeShift));
+    view->serviceScriptedAnimations(monotonicFrameBeginTime);
 #endif
 }
 
index 8c34e12..c1c9c82 100644 (file)
@@ -1743,13 +1743,6 @@ void WebViewImpl::updateAnimations(double monotonicFrameBeginTime)
 #if ENABLE(REQUEST_ANIMATION_FRAME)
     TRACE_EVENT0("webkit", "WebViewImpl::updateAnimations");
 
-    WebFrameImpl* webframe = mainFrameImpl();
-    if (!webframe)
-        return;
-    FrameView* view = webframe->frameView();
-    if (!view)
-        return;
-
     // Create synthetic wheel events as necessary for fling.
     if (m_gestureAnimation) {
         if (m_gestureAnimation->animate(monotonicFrameBeginTime))
@@ -1758,6 +1751,9 @@ void WebViewImpl::updateAnimations(double monotonicFrameBeginTime)
             m_gestureAnimation.clear();
     }
 
+    if (!m_page)
+        return;
+
     PageWidgetDelegate::animate(m_page.get(), monotonicFrameBeginTime);
 #endif
 }