Skip to content
Permalink
Browse files
requestAnimationFrame doesn't throttle on Mac
https://bugs.webkit.org/show_bug.cgi?id=67171

Reviewed by Simon Fraser.

Source/JavaScriptCore:

Added WTF_USE_REQUEST_ANIMATION_FRAME_TIMER to allow any platform to run
requestAnimationFrame callbacks on a Timer defined in ScriptedAnimationController.
Currently only enabled for PLATFORM(MAC)

* wtf/Platform.h:

Source/WebCore:

Changed requestAnimationFrame to use a Timer in ScriptedAnimationController
on Mac, rather than runLoopObservers. The Timer is throttled to fire no
faster than every 15ms. It is behind a WTF_USE_REQUEST_ANIMATION_FRAME_TIMER
flag and can be used by any implementation, but currently it is only enabled
by PLATFORM(MAC).

* dom/ScriptedAnimationController.cpp:
(WebCore::ScriptedAnimationController::ScriptedAnimationController):
(WebCore::ScriptedAnimationController::resume):
(WebCore::ScriptedAnimationController::registerCallback):
(WebCore::ScriptedAnimationController::serviceScriptedAnimations):
(WebCore::ScriptedAnimationController::scheduleAnimation):
(WebCore::ScriptedAnimationController::animationTimerFired):
* dom/ScriptedAnimationController.h:
* loader/EmptyClients.h:
* page/Chrome.cpp:
(WebCore::Chrome::scheduleAnimation):
* page/ChromeClient.h:

Source/WebKit/mac:

Removed runLoopObserver for requestAnimationFrame. It's now
done by a Timer in ScriptedAnimationController in WebCore.

* WebCoreSupport/WebChromeClient.h:
* WebCoreSupport/WebChromeClient.mm:
* WebView/WebView.mm:
(-[WebView _close]):
* WebView/WebViewData.h:
* WebView/WebViewInternal.h:

Source/WebKit2:

Removed runLoopObserver for requestAnimationFrame. It's now
done by a Timer in ScriptedAnimationController in WebCore.

* WebProcess/WebCoreSupport/WebChromeClient.cpp:
* WebProcess/WebCoreSupport/WebChromeClient.h:
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::~WebPage):
* WebProcess/WebPage/WebPage.h:
* WebProcess/WebPage/mac/WebPageMac.mm:

Canonical link: https://commits.webkit.org/83794@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@94908 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
Chris Marrin committed Sep 10, 2011
1 parent 85a754e commit 2ef936aba001c310139cc1b14c8c49be2e6ee65c
Showing 20 changed files with 129 additions and 142 deletions.
@@ -1,3 +1,16 @@
2011-09-09 Chris Marrin <cmarrin@apple.com>

requestAnimationFrame doesn't throttle on Mac
https://bugs.webkit.org/show_bug.cgi?id=67171

Reviewed by Simon Fraser.

Added WTF_USE_REQUEST_ANIMATION_FRAME_TIMER to allow any platform to run
requestAnimationFrame callbacks on a Timer defined in ScriptedAnimationController.
Currently only enabled for PLATFORM(MAC)

* wtf/Platform.h:

2011-09-09 Geoffrey Garen <ggaren@apple.com>

Reviewed by Dan Bernstein.
@@ -1159,4 +1159,8 @@
#define WTF_USE_AVFOUNDATION 1
#endif

#if PLATFORM(MAC)
#define WTF_USE_REQUEST_ANIMATION_FRAME_TIMER 1
#endif

#endif /* WTF_Platform_h */
@@ -1,3 +1,29 @@
2011-09-09 Chris Marrin <cmarrin@apple.com>

requestAnimationFrame doesn't throttle on Mac
https://bugs.webkit.org/show_bug.cgi?id=67171

Reviewed by Simon Fraser.

Changed requestAnimationFrame to use a Timer in ScriptedAnimationController
on Mac, rather than runLoopObservers. The Timer is throttled to fire no
faster than every 15ms. It is behind a WTF_USE_REQUEST_ANIMATION_FRAME_TIMER
flag and can be used by any implementation, but currently it is only enabled
by PLATFORM(MAC).

* dom/ScriptedAnimationController.cpp:
(WebCore::ScriptedAnimationController::ScriptedAnimationController):
(WebCore::ScriptedAnimationController::resume):
(WebCore::ScriptedAnimationController::registerCallback):
(WebCore::ScriptedAnimationController::serviceScriptedAnimations):
(WebCore::ScriptedAnimationController::scheduleAnimation):
(WebCore::ScriptedAnimationController::animationTimerFired):
* dom/ScriptedAnimationController.h:
* loader/EmptyClients.h:
* page/Chrome.cpp:
(WebCore::Chrome::scheduleAnimation):
* page/ChromeClient.h:

2011-09-10 Jarred Nicholls <jarred@sencha.com>

[Qt] QWebSettings::setUserStyleSheetUrl() does not work with windows paths that contain drive letters
@@ -33,12 +33,26 @@
#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,8 +65,7 @@ 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)
@@ -63,8 +76,7 @@ ScriptedAnimationController::CallbackId ScriptedAnimationController::registerCal
callback->m_element = animationElement;
m_callbacks.append(callback);
if (!m_suspendCount)
if (FrameView* view = m_document->view())
view->scheduleAnimation();
scheduleAnimation();
return id;
}

@@ -124,9 +136,27 @@ 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(m_lastAnimationFrameTime);
}
#endif

}

@@ -28,6 +28,9 @@

#if ENABLE(REQUEST_ANIMATION_FRAME)
#include "DOMTimeStamp.h"
#if USE(REQUEST_ANIMATION_FRAME_TIMER)
#include "Timer.h"
#endif
#include <wtf/Noncopyable.h>
#include <wtf/PassOwnPtr.h>
#include <wtf/RefPtr.h>
@@ -58,12 +61,21 @@ WTF_MAKE_NONCOPYABLE(ScriptedAnimationController);

private:
explicit ScriptedAnimationController(Document*);

typedef Vector<RefPtr<RequestAnimationFrameCallback> > CallbackList;
CallbackList m_callbacks;

Document* m_document;
CallbackId m_nextCallbackId;
int m_suspendCount;

void scheduleAnimation();

#if USE(REQUEST_ANIMATION_FRAME_TIMER)
void animationTimerFired(Timer<ScriptedAnimationController>*);
Timer<ScriptedAnimationController> m_animationTimer;
double m_lastAnimationFrameTime;
#endif
};

}
@@ -164,7 +164,7 @@ class EmptyChromeClient : public ChromeClient {
#if ENABLE(TILED_BACKING_STORE)
virtual void delegatedScrollRequested(const IntPoint&) { }
#endif
#if ENABLE(REQUEST_ANIMATION_FRAME)
#if ENABLE(REQUEST_ANIMATION_FRAME) && !USE(REQUEST_ANIMATION_FRAME_TIMER)
virtual void scheduleAnimation() { }
#endif

@@ -514,7 +514,9 @@ void Chrome::setCursorHiddenUntilMouseMoves(bool hiddenUntilMouseMoves)
#if ENABLE(REQUEST_ANIMATION_FRAME)
void Chrome::scheduleAnimation()
{
#if !USE(REQUEST_ANIMATION_FRAME_TIMER)
m_client->scheduleAnimation();
#endif
}
#endif

@@ -159,7 +159,7 @@ namespace WebCore {
virtual void scrollbarsModeDidChange() const = 0;
virtual void setCursor(const Cursor&) = 0;
virtual void setCursorHiddenUntilMouseMoves(bool) = 0;
#if ENABLE(REQUEST_ANIMATION_FRAME)
#if ENABLE(REQUEST_ANIMATION_FRAME) && !USE(REQUEST_ANIMATION_FRAME_TIMER)
virtual void scheduleAnimation() = 0;
#endif
// End methods used by HostWindow.
@@ -1,3 +1,20 @@
2011-09-09 Chris Marrin <cmarrin@apple.com>

requestAnimationFrame doesn't throttle on Mac
https://bugs.webkit.org/show_bug.cgi?id=67171

Reviewed by Simon Fraser.

Removed runLoopObserver for requestAnimationFrame. It's now
done by a Timer in ScriptedAnimationController in WebCore.

* WebCoreSupport/WebChromeClient.h:
* WebCoreSupport/WebChromeClient.mm:
* WebView/WebView.mm:
(-[WebView _close]):
* WebView/WebViewData.h:
* WebView/WebViewInternal.h:

2011-09-09 Fady Samuel <fsamuel@chromium.org>

Move pageScaleFactor code from Frame.{h|cpp} to Page.{h|cpp}
@@ -128,10 +128,6 @@ class WebChromeClient : public WebCore::ChromeClient {
virtual void setCursor(const WebCore::Cursor&);
virtual void setCursorHiddenUntilMouseMoves(bool);

#if ENABLE(REQUEST_ANIMATION_FRAME)
virtual void scheduleAnimation();
#endif

virtual WebCore::FloatRect customHighlightRect(WebCore::Node*, const WTF::AtomicString& type,
const WebCore::FloatRect& lineRect);
virtual void paintCustomHighlight(WebCore::Node*, const WTF::AtomicString& type,
@@ -942,15 +942,6 @@ - (id)initWithElement:(Element*)element;

#endif

#if ENABLE(REQUEST_ANIMATION_FRAME)
void WebChromeClient::scheduleAnimation()
{
BEGIN_BLOCK_OBJC_EXCEPTIONS;
[m_webView _scheduleAnimation];
END_BLOCK_OBJC_EXCEPTIONS;
}
#endif

#if ENABLE(VIDEO)

bool WebChromeClient::supportsFullscreenForNode(const Node* node)
@@ -395,9 +395,6 @@ - (NSResponder *)_responderForResponderOperations;
#if USE(ACCELERATED_COMPOSITING)
- (void)_clearLayerSyncLoopObserver;
#endif
#if ENABLE(REQUEST_ANIMATION_FRAME)
- (void)_unscheduleAnimation;
#endif
#if ENABLE(GLIB_SUPPORT)
- (void)_clearGlibLoopObserver;
#endif
@@ -1226,10 +1223,6 @@ - (void)_close
[self _clearLayerSyncLoopObserver];
#endif

#if ENABLE(REQUEST_ANIMATION_FRAME)
[self _unscheduleAnimation];
#endif

#if ENABLE(GLIB_SUPPORT)
[self _clearGlibLoopObserver];
#endif
@@ -5921,18 +5914,6 @@ - (void)_clearLayerSyncLoopObserver
}
#endif

#if ENABLE(REQUEST_ANIMATION_FRAME)
- (void)_unscheduleAnimation
{
if (!_private->requestAnimationFrameRunLoopObserver)
return;

CFRunLoopObserverInvalidate(_private->requestAnimationFrameRunLoopObserver);
CFRelease(_private->requestAnimationFrameRunLoopObserver);
_private->requestAnimationFrameRunLoopObserver = 0;
}
#endif

#if ENABLE(GLIB_SUPPORT)
- (void)_clearGlibLoopObserver
{
@@ -6212,34 +6193,6 @@ - (void)_scheduleCompositingLayerSync

#endif

#if ENABLE(REQUEST_ANIMATION_FRAME)
static void requestAnimationFrameRunLoopObserverCallback(CFRunLoopObserverRef, CFRunLoopActivity, void* info)
{
WebView *webView = reinterpret_cast<WebView*>(info);
[webView _unscheduleAnimation];

if (Frame* frame = [webView _mainCoreFrame])
if (FrameView* frameView = frame->view())
frameView->serviceScriptedAnimations(convertSecondsToDOMTimeStamp(currentTime()));
}

- (void)_scheduleAnimation
{
if (!_private->requestAnimationFrameRunLoopObserver) {
CFRunLoopRef currentRunLoop = CFRunLoopGetCurrent();

// Make sure we wake up the loop or the observer could be delayed until some other source fires.
CFRunLoopWakeUp(currentRunLoop);

// Run before the layerSyncRunLoopObserver, which has order NSDisplayWindowRunLoopOrdering + 2.
const CFIndex runLoopOrder = NSDisplayWindowRunLoopOrdering + 1;
CFRunLoopObserverContext context = { 0, self, 0, 0, 0 };
_private->requestAnimationFrameRunLoopObserver = CFRunLoopObserverCreate(0, kCFRunLoopBeforeWaiting | kCFRunLoopExit, NO, runLoopOrder, requestAnimationFrameRunLoopObserverCallback, &context);
CFRunLoopAddObserver(currentRunLoop, _private->requestAnimationFrameRunLoopObserver, kCFRunLoopCommonModes);
}
}
#endif

#if ENABLE(VIDEO)

- (void)_enterFullscreenForNode:(WebCore::Node*)node
@@ -155,10 +155,6 @@ extern int pluginDatabaseClientCount;
CFRunLoopObserverRef layerSyncRunLoopObserver;
#endif

#if ENABLE(REQUEST_ANIMATION_FRAME)
CFRunLoopObserverRef requestAnimationFrameRunLoopObserver;
#endif

NSPasteboard *insertionPasteboard;

NSSize lastLayoutSize;
@@ -93,10 +93,6 @@ WebCore::FindOptions coreOptions(WebFindOptions options);
- (void)_scheduleCompositingLayerSync;
#endif

#if ENABLE(REQUEST_ANIMATION_FRAME)
- (void)_scheduleAnimation;
#endif

#if ENABLE(GLIB_SUPPORT)
- (void)_scheduleGlibContextIterations;
#endif
@@ -1,3 +1,20 @@
2011-09-09 Chris Marrin <cmarrin@apple.com>

requestAnimationFrame doesn't throttle on Mac
https://bugs.webkit.org/show_bug.cgi?id=67171

Reviewed by Simon Fraser.

Removed runLoopObserver for requestAnimationFrame. It's now
done by a Timer in ScriptedAnimationController in WebCore.

* WebProcess/WebCoreSupport/WebChromeClient.cpp:
* WebProcess/WebCoreSupport/WebChromeClient.h:
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::~WebPage):
* WebProcess/WebPage/WebPage.h:
* WebProcess/WebPage/mac/WebPageMac.mm:

2011-09-09 Fady Samuel <fsamuel@chromium.org>

Move pageScaleFactor code from Frame.{h|cpp} to Page.{h|cpp}
@@ -654,13 +654,6 @@ void WebChromeClient::setCursorHiddenUntilMouseMoves(bool hiddenUntilMouseMoves)
m_page->send(Messages::WebPageProxy::SetCursorHiddenUntilMouseMoves(hiddenUntilMouseMoves));
}

#if ENABLE(REQUEST_ANIMATION_FRAME)
void WebChromeClient::scheduleAnimation()
{
m_page->scheduleAnimation();
}
#endif

void WebChromeClient::formStateDidChange(const Node*)
{
notImplemented();
@@ -172,10 +172,6 @@ class WebChromeClient : public WebCore::ChromeClient {
virtual void setCursor(const WebCore::Cursor&);
virtual void setCursorHiddenUntilMouseMoves(bool);

#if ENABLE(REQUEST_ANIMATION_FRAME)
virtual void scheduleAnimation();
#endif

// Notification that the given form element has changed. This function
// will be called frequently, so handling should be very fast.
virtual void formStateDidChange(const WebCore::Node*);
@@ -262,12 +262,6 @@ WebPage::~WebPage()

#if PLATFORM(MAC)
ASSERT(m_pluginViews.isEmpty());

#if ENABLE(REQUEST_ANIMATION_FRAME)
unscheduleAnimation();
ASSERT(!m_requestAnimationFrameRunLoopObserver);
#endif

#endif

#ifndef NDEBUG

0 comments on commit 2ef936a

Please sign in to comment.