Commit d9dca741 authored by cmarrin@apple.com's avatar cmarrin@apple.com

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:

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@94908 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 1542f550
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 */
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 @@ public:
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 @@ public:
#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.
......
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 @@ public:
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 @@ void WebChromeClient::scheduleCompositingLayerSync()
#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 @@ FindOptions coreOptions(WebFindOptions options)
#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 @@ static bool fastDocumentTeardownEnabled()
[self _clearLayerSyncLoopObserver];
#endif
#if ENABLE(REQUEST_ANIMATION_FRAME)
[self _unscheduleAnimation];
#endif
#if ENABLE(GLIB_SUPPORT)
[self _clearGlibLoopObserver];
#endif
......@@ -5921,18 +5914,6 @@ static inline uint64_t roundUpToPowerOf2(uint64_t num)
}
#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 @@ static void layerSyncRunLoopObserverCallBack(CFRunLoopObserverRef, CFRunLoopActi
#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
......
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 @@ private:
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
......
......@@ -351,10 +351,6 @@ public:
void acceptsFirstMouse(int eventNumber, const WebKit::WebMouseEvent&, bool& result);
bool performNonEditingBehaviorForSelector(const String&);
#if ENABLE(REQUEST_ANIMATION_FRAME)
void scheduleAnimation();
void unscheduleAnimation();
#endif
#elif PLATFORM(WIN)
void confirmComposition(const String& compositionString);
void setComposition(const WTF::String& compositionString, const WTF::Vector<WebCore::CompositionUnderline>& underlines, uint64_t cursorPosition);
......@@ -612,11 +608,6 @@ private:
WebCore::KeyboardEvent* m_keyboardEventBeingInterpreted;
#if ENABLE(REQUEST_ANIMATION_FRAME)
static void requestAnimationFrameRunLoopObserverCallback(CFRunLoopObserverRef, CFRunLoopActivity, void*);
RetainPtr<CFRunLoopObserverRef> m_requestAnimationFrameRunLoopObserver;
#endif
#elif PLATFORM(WIN)
// Our view's window (in the UI process).
HWND m_nativeWindow;
......
......@@ -30,7 +30,6 @@
#import "AttributedString.h"
#import "DataReference.h"
#import "EditorState.h"
#import "LayerTreeHostCAMac.h"
#import "PluginView.h"
#import "WebCoreArgumentCoders.h"
#import "WebEvent.h"
......@@ -584,45 +583,6 @@ bool WebPage::performNonEditingBehaviorForSelector(const String& selector)
return true;
}
#if ENABLE(REQUEST_ANIMATION_FRAME)
void WebPage::requestAnimationFrameRunLoopObserverCallback(CFRunLoopObserverRef, CFRunLoopActivity, void* context)
{
WebPage* webPage = static_cast<WebPage*>(context);
webPage->unscheduleAnimation();
// This gets called outside of the normal event loop so wrap in an autorelease pool
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
if (webPage->corePage()->mainFrame() && webPage->corePage()->mainFrame()->view())
webPage->corePage()->mainFrame()->view()->serviceScriptedAnimations(convertSecondsToDOMTimeStamp(currentTime()));
[pool drain];
}
void WebPage::scheduleAnimation()
{
if (!m_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 flushPendingLayerChangesRunLoopObserver, which has order CoreAnimationRunLoopOrder - 1.
const CFIndex runLoopOrder = CoreAnimationRunLoopOrder - 2;
CFRunLoopObserverContext context = { 0, this, 0, 0, 0 };
m_requestAnimationFrameRunLoopObserver.adoptCF(CFRunLoopObserverCreate(0, kCFRunLoopBeforeWaiting | kCFRunLoopExit, false, runLoopOrder, requestAnimationFrameRunLoopObserverCallback, &context));
CFRunLoopAddObserver(currentRunLoop, m_requestAnimationFrameRunLoopObserver.get(), kCFRunLoopCommonModes);
}
}
void WebPage::unscheduleAnimation()
{
if (m_requestAnimationFrameRunLoopObserver) {
CFRunLoopObserverInvalidate(m_requestAnimationFrameRunLoopObserver.get());
m_requestAnimationFrameRunLoopObserver = nullptr;
}
}
#endif
bool WebPage::performDefaultBehaviorForKeyEvent(const WebKeyboardEvent&)
{
return false;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment