REGRESSION (iOS WebKit2): requestAnimationFrame fires more than once between layer...
authortimothy_horton@apple.com <timothy_horton@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 24 May 2014 02:17:59 +0000 (02:17 +0000)
committertimothy_horton@apple.com <timothy_horton@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 24 May 2014 02:17:59 +0000 (02:17 +0000)
https://bugs.webkit.org/show_bug.cgi?id=132794
<rdar://problem/16877909>

Reviewed by Simon Fraser.

Virtualize DisplayRefreshMonitor so that WebKit2 can implement its own DisplayRefreshMonitor for UI-side compositing views.
This allows the synchronization of requestAnimationFrame callbacks with UI-side compositing painting.

* WebCore.exp.in:
* WebCore.xcodeproj/project.pbxproj:

* page/ChromeClient.h:
(WebCore::ChromeClient::graphicsLayerFactory):
(WebCore::ChromeClient::createDisplayRefreshMonitor):
* platform/graphics/DisplayRefreshMonitorFactory.h: Added.
* platform/graphics/GraphicsLayerUpdater.cpp:
(WebCore::GraphicsLayerUpdater::createDisplayRefreshMonitor):
* platform/graphics/GraphicsLayerUpdater.h:
* rendering/RenderLayerCompositor.cpp:
(WebCore::RenderLayerCompositor::createDisplayRefreshMonitor):
* rendering/RenderLayerCompositor.h:
Give the ChromeClient a chance to provide us with a custom DisplayRefreshMonitor.
If it does not, we'll fall back to making a DisplayRefreshMonitorMac or
DisplayRefreshMonitorIOS depending on the platform.

* dom/ScriptedAnimationController.cpp:
* dom/ScriptedAnimationController.h:
* platform/graphics/DisplayRefreshMonitor.cpp:
* platform/graphics/DisplayRefreshMonitor.h:
* platform/graphics/DisplayRefreshMonitorClient.cpp: Added.
* platform/graphics/DisplayRefreshMonitorClient.h: Added.
* platform/graphics/DisplayRefreshMonitorManager.cpp: Added.
* platform/graphics/DisplayRefreshMonitorManager.h: Added.
Split DisplayRefreshMonitor.cpp into one file per class.
Use references in a few places.
Remove some useless comments.

* platform/graphics/DisplayRefreshMonitor.cpp:
(WebCore::DisplayRefreshMonitor::displayDidRefresh):
Use takeAny() and remove a FIXME about it not existing.

* platform/graphics/DisplayRefreshMonitorClient.cpp: Added.
(WebCore::DisplayRefreshMonitorClient::fireDisplayRefreshIfNeeded):
Use an early return instead of having the whole function body in an if().

* platform/graphics/ios/DisplayRefreshMonitorIOS.h: Added.
* platform/graphics/ios/DisplayRefreshMonitorIOS.mm:
* platform/graphics/mac/DisplayRefreshMonitorMac.cpp:
* platform/graphics/mac/DisplayRefreshMonitorMac.h: Added.
Virtualize DisplayRefreshMonitorIOS and DisplayRefreshMonitorMac,
and move things specific to each of them out of DisplayRefreshMonitor itself.

* WebKit2.xcodeproj/project.pbxproj:
* WebProcess/WebCoreSupport/WebChromeClient.cpp:
(WebKit::WebChromeClient::createDisplayRefreshMonitor):
* WebProcess/WebCoreSupport/WebChromeClient.h:
* WebProcess/WebPage/DrawingArea.h:
(WebKit::DrawingArea::graphicsLayerFactory):
(WebKit::DrawingArea::createDisplayRefreshMonitor):
Plumb the DisplayRefreshMonitor request through to the DrawingArea.
RemoteLayerTreeDrawingArea will implement and return a RemoteLayerTreeDisplayRefreshMonitor.

* WebProcess/WebPage/Cocoa/RemoteLayerTreeDisplayRefreshMonitor.h: Added.
(WebKit::RemoteLayerTreeDisplayRefreshMonitor::create):
* WebProcess/WebPage/Cocoa/RemoteLayerTreeDisplayRefreshMonitor.mm: Added.
(WebKit::RemoteLayerTreeDisplayRefreshMonitor::RemoteLayerTreeDisplayRefreshMonitor):
(WebKit::RemoteLayerTreeDisplayRefreshMonitor::~RemoteLayerTreeDisplayRefreshMonitor):
(WebKit::RemoteLayerTreeDisplayRefreshMonitor::requestRefreshCallback):
When requesting a display refresh callback, schedule a layer commit.
It may end up being empty, but will still call us back with a didUpdate,
upon which we'll fire the callback.

(WebKit::RemoteLayerTreeDisplayRefreshMonitor::didUpdateLayers):

* WebProcess/WebPage/mac/RemoteLayerTreeDrawingArea.h:
* WebProcess/WebPage/mac/RemoteLayerTreeDrawingArea.mm:
(WebKit::RemoteLayerTreeDrawingArea::createDisplayRefreshMonitor):
(WebKit::RemoteLayerTreeDrawingArea::willDestroyDisplayRefreshMonitor):
Keep track of the set of DisplayRefreshMonitors.

(WebKit::RemoteLayerTreeDrawingArea::didUpdate):
Fire requestAnimationFrame callbacks once the UI process commits the new layer tree.

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

30 files changed:
Source/WebCore/ChangeLog
Source/WebCore/WebCore.exp.in
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/dom/ScriptedAnimationController.cpp
Source/WebCore/dom/ScriptedAnimationController.h
Source/WebCore/page/ChromeClient.h
Source/WebCore/platform/graphics/DisplayRefreshMonitor.cpp
Source/WebCore/platform/graphics/DisplayRefreshMonitor.h
Source/WebCore/platform/graphics/DisplayRefreshMonitorClient.cpp [new file with mode: 0644]
Source/WebCore/platform/graphics/DisplayRefreshMonitorClient.h [new file with mode: 0644]
Source/WebCore/platform/graphics/DisplayRefreshMonitorManager.cpp [new file with mode: 0644]
Source/WebCore/platform/graphics/DisplayRefreshMonitorManager.h [new file with mode: 0644]
Source/WebCore/platform/graphics/GraphicsLayerUpdater.cpp
Source/WebCore/platform/graphics/GraphicsLayerUpdater.h
Source/WebCore/platform/graphics/ios/DisplayRefreshMonitorIOS.h [new file with mode: 0644]
Source/WebCore/platform/graphics/ios/DisplayRefreshMonitorIOS.mm
Source/WebCore/platform/graphics/mac/DisplayRefreshMonitorMac.cpp
Source/WebCore/platform/graphics/mac/DisplayRefreshMonitorMac.h [new file with mode: 0644]
Source/WebCore/rendering/RenderLayerCompositor.cpp
Source/WebCore/rendering/RenderLayerCompositor.h
Source/WebKit2/ChangeLog
Source/WebKit2/WebKit2.xcodeproj/project.pbxproj
Source/WebKit2/WebProcess/WebCoreSupport/WebChromeClient.cpp
Source/WebKit2/WebProcess/WebCoreSupport/WebChromeClient.h
Source/WebKit2/WebProcess/WebPage/Cocoa/RemoteLayerTreeDisplayRefreshMonitor.h [new file with mode: 0644]
Source/WebKit2/WebProcess/WebPage/Cocoa/RemoteLayerTreeDisplayRefreshMonitor.mm [new file with mode: 0644]
Source/WebKit2/WebProcess/WebPage/DrawingArea.cpp
Source/WebKit2/WebProcess/WebPage/DrawingArea.h
Source/WebKit2/WebProcess/WebPage/mac/RemoteLayerTreeDrawingArea.h
Source/WebKit2/WebProcess/WebPage/mac/RemoteLayerTreeDrawingArea.mm

index cea66fa6f7289b03352215c61dcebd4196304d79..c1cccbd538bbcd5c0cd6fcf44169a6df399685e9 100644 (file)
@@ -1,3 +1,58 @@
+2014-05-23  Tim Horton  <timothy_horton@apple.com>
+
+        REGRESSION (iOS WebKit2): requestAnimationFrame fires more than once between layer tree commits
+        https://bugs.webkit.org/show_bug.cgi?id=132794
+        <rdar://problem/16877909>
+
+        Reviewed by Simon Fraser.
+
+        Virtualize DisplayRefreshMonitor so that WebKit2 can implement its own DisplayRefreshMonitor for UI-side compositing views.
+        This allows the synchronization of requestAnimationFrame callbacks with UI-side compositing painting.
+
+        * WebCore.exp.in:
+        * WebCore.xcodeproj/project.pbxproj:
+        
+        * page/ChromeClient.h:
+        (WebCore::ChromeClient::graphicsLayerFactory):
+        (WebCore::ChromeClient::createDisplayRefreshMonitor):
+        * platform/graphics/DisplayRefreshMonitorFactory.h: Added.
+        * platform/graphics/GraphicsLayerUpdater.cpp:
+        (WebCore::GraphicsLayerUpdater::createDisplayRefreshMonitor):
+        * platform/graphics/GraphicsLayerUpdater.h:
+        * rendering/RenderLayerCompositor.cpp:
+        (WebCore::RenderLayerCompositor::createDisplayRefreshMonitor):
+        * rendering/RenderLayerCompositor.h:
+        Give the ChromeClient a chance to provide us with a custom DisplayRefreshMonitor.
+        If it does not, we'll fall back to making a DisplayRefreshMonitorMac or
+        DisplayRefreshMonitorIOS depending on the platform.
+
+        * dom/ScriptedAnimationController.cpp:
+        * dom/ScriptedAnimationController.h:
+        * platform/graphics/DisplayRefreshMonitor.cpp:
+        * platform/graphics/DisplayRefreshMonitor.h:
+        * platform/graphics/DisplayRefreshMonitorClient.cpp: Added.
+        * platform/graphics/DisplayRefreshMonitorClient.h: Added.
+        * platform/graphics/DisplayRefreshMonitorManager.cpp: Added.
+        * platform/graphics/DisplayRefreshMonitorManager.h: Added.
+        Split DisplayRefreshMonitor.cpp into one file per class.
+        Use references in a few places.
+        Remove some useless comments.
+
+        * platform/graphics/DisplayRefreshMonitor.cpp:
+        (WebCore::DisplayRefreshMonitor::displayDidRefresh):
+        Use takeAny() and remove a FIXME about it not existing.
+
+        * platform/graphics/DisplayRefreshMonitorClient.cpp: Added.
+        (WebCore::DisplayRefreshMonitorClient::fireDisplayRefreshIfNeeded):
+        Use an early return instead of having the whole function body in an if().
+
+        * platform/graphics/ios/DisplayRefreshMonitorIOS.h: Added.
+        * platform/graphics/ios/DisplayRefreshMonitorIOS.mm:
+        * platform/graphics/mac/DisplayRefreshMonitorMac.cpp:
+        * platform/graphics/mac/DisplayRefreshMonitorMac.h: Added.
+        Virtualize DisplayRefreshMonitorIOS and DisplayRefreshMonitorMac,
+        and move things specific to each of them out of DisplayRefreshMonitor itself.
+
 2014-05-23  Yusuke Suzuki  <utatane.tea@gmail.com>
 
         CSS JIT: Apply backtracking optimization to adjacent backtracking
index 2f085a3f3781bc574a8448ee1be066892abfa01f..db4bd849042c86265bab7615a96ac93580eec22b 100644 (file)
@@ -875,6 +875,9 @@ __ZN7WebCore21BlobDataFileReferenceC2ERKN3WTF6StringE
 __ZN7WebCore21BlobDataFileReferenceD2Ev
 __ZN7WebCore21CrossThreadCopierBaseILb0ELb0EN3WTF6StringEE4copyERKS2_
 __ZN7WebCore21CrossThreadCopierBaseILb0ELb0ENS_19IDBDatabaseMetadataEE4copyERKS1_
+__ZN7WebCore21DisplayRefreshMonitor46handleDisplayRefreshedNotificationOnMainThreadEPv
+__ZN7WebCore21DisplayRefreshMonitorC2Ej
+__ZN7WebCore21DisplayRefreshMonitorD2Ev
 __ZN7WebCore21MemoryPressureHandler12ReliefLogger16s_loggingEnabledE
 __ZN7WebCore21MemoryPressureHandler13releaseMemoryEb
 __ZN7WebCore21MemoryPressureHandler7installEv
index 52b1df9320056b67982bf55d94bacb88ef524e28..7b0bc8d3be23a07ade98d8a88d1b53167a1e029d 100644 (file)
                2D0B4AAC18DA1CCD00434DE1 /* IOSurface.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2D0B4AAA18DA1CCD00434DE1 /* IOSurface.mm */; };
                2D25396218CE7F6200270222 /* ImageControlsButtonElementMac.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2D25396018CE7F6200270222 /* ImageControlsButtonElementMac.cpp */; };
                2D25396318CE7F6200270222 /* ImageControlsButtonElementMac.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D25396118CE7F6200270222 /* ImageControlsButtonElementMac.h */; };
+               2D29ECC5192ECC8300984B78 /* DisplayRefreshMonitorClient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2D29ECC1192ECC8300984B78 /* DisplayRefreshMonitorClient.cpp */; };
+               2D29ECC6192ECC8300984B78 /* DisplayRefreshMonitorClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D29ECC2192ECC8300984B78 /* DisplayRefreshMonitorClient.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               2D29ECC7192ECC8300984B78 /* DisplayRefreshMonitorManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2D29ECC3192ECC8300984B78 /* DisplayRefreshMonitorManager.cpp */; };
+               2D29ECC8192ECC8300984B78 /* DisplayRefreshMonitorManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D29ECC4192ECC8300984B78 /* DisplayRefreshMonitorManager.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               2D29ECCA192F1F1D00984B78 /* DisplayRefreshMonitorIOS.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D29ECC9192F1F1D00984B78 /* DisplayRefreshMonitorIOS.h */; };
                2D3A0E3613A7D76100E85AF0 /* SVGParsingError.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D3A0E3513A7D76100E85AF0 /* SVGParsingError.h */; settings = {ATTRIBUTES = (Private, ); }; };
                2D3EF4481917915C00034184 /* WebActionDisablingCALayerDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D3EF4441917915C00034184 /* WebActionDisablingCALayerDelegate.h */; settings = {ATTRIBUTES = (Private, ); }; };
                2D3EF4491917915C00034184 /* WebActionDisablingCALayerDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2D3EF4451917915C00034184 /* WebActionDisablingCALayerDelegate.mm */; };
                2D9A247515B9C2E300D34527 /* DOMDOMSecurityPolicyInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D9A247115B9C29500D34527 /* DOMDOMSecurityPolicyInternal.h */; };
                2D9A247615B9C2F400D34527 /* DOMDOMSecurityPolicy.h in Copy Generated Headers */ = {isa = PBXBuildFile; fileRef = 2D9A247015B9C29500D34527 /* DOMDOMSecurityPolicy.h */; };
                2D9F0E1314FF1CBF00BA0FF7 /* linearSRGB.icc in Resources */ = {isa = PBXBuildFile; fileRef = 2D9F0E1214FF1CBF00BA0FF7 /* linearSRGB.icc */; };
+               2DE70023192FE82A00B0975C /* DisplayRefreshMonitorMac.h in Headers */ = {isa = PBXBuildFile; fileRef = 2DE70022192FE82A00B0975C /* DisplayRefreshMonitorMac.h */; };
                2E0888D41148848A00AF4265 /* JSDOMFormData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2E0888D21148848A00AF4265 /* JSDOMFormData.cpp */; };
                2E0888D51148848A00AF4265 /* JSDOMFormData.h in Headers */ = {isa = PBXBuildFile; fileRef = 2E0888D31148848A00AF4265 /* JSDOMFormData.h */; };
                2E0888E6114884E200AF4265 /* JSDOMFormDataCustom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2E0888E5114884E200AF4265 /* JSDOMFormDataCustom.cpp */; };
                2D0B4AAA18DA1CCD00434DE1 /* IOSurface.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = IOSurface.mm; sourceTree = "<group>"; };
                2D25396018CE7F6200270222 /* ImageControlsButtonElementMac.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ImageControlsButtonElementMac.cpp; sourceTree = "<group>"; };
                2D25396118CE7F6200270222 /* ImageControlsButtonElementMac.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageControlsButtonElementMac.h; sourceTree = "<group>"; };
+               2D29ECC1192ECC8300984B78 /* DisplayRefreshMonitorClient.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DisplayRefreshMonitorClient.cpp; sourceTree = "<group>"; };
+               2D29ECC2192ECC8300984B78 /* DisplayRefreshMonitorClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DisplayRefreshMonitorClient.h; sourceTree = "<group>"; };
+               2D29ECC3192ECC8300984B78 /* DisplayRefreshMonitorManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DisplayRefreshMonitorManager.cpp; sourceTree = "<group>"; };
+               2D29ECC4192ECC8300984B78 /* DisplayRefreshMonitorManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DisplayRefreshMonitorManager.h; sourceTree = "<group>"; };
+               2D29ECC9192F1F1D00984B78 /* DisplayRefreshMonitorIOS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DisplayRefreshMonitorIOS.h; sourceTree = "<group>"; };
                2D2FC0541460CD6F00263633 /* CrossfadeGeneratedImage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CrossfadeGeneratedImage.cpp; sourceTree = "<group>"; };
                2D2FC0551460CD6F00263633 /* CrossfadeGeneratedImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CrossfadeGeneratedImage.h; sourceTree = "<group>"; };
                2D2FC0561460CD6F00263633 /* GradientImage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GradientImage.cpp; sourceTree = "<group>"; };
                2D9A247115B9C29500D34527 /* DOMDOMSecurityPolicyInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOMDOMSecurityPolicyInternal.h; sourceTree = "<group>"; };
                2D9A247215B9C2C700D34527 /* DOMDOMSecurityPolicy.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DOMDOMSecurityPolicy.mm; sourceTree = "<group>"; };
                2D9F0E1214FF1CBF00BA0FF7 /* linearSRGB.icc */ = {isa = PBXFileReference; lastKnownFileType = file; path = linearSRGB.icc; sourceTree = "<group>"; };
+               2DE70022192FE82A00B0975C /* DisplayRefreshMonitorMac.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DisplayRefreshMonitorMac.h; sourceTree = "<group>"; };
                2E0888C3114883A900AF4265 /* DOMFormData.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = DOMFormData.idl; sourceTree = "<group>"; };
                2E0888D21148848A00AF4265 /* JSDOMFormData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSDOMFormData.cpp; sourceTree = "<group>"; };
                2E0888D31148848A00AF4265 /* JSDOMFormData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSDOMFormData.h; sourceTree = "<group>"; };
                441AF0A70EBA7BBF0044ED4B /* ios */ = {
                        isa = PBXGroup;
                        children = (
+                               2D29ECC9192F1F1D00984B78 /* DisplayRefreshMonitorIOS.h */,
                                0F97A657155DA81E00FADD4C /* DisplayRefreshMonitorIOS.mm */,
                                3727DFD4142AAE4500D449CB /* FontCacheIOS.mm */,
                                C58361A71744523F00173511 /* FontServicesIOS.h */,
                                37C2360E1097EE7700EF9F72 /* ComplexTextController.cpp */,
                                37C2360F1097EE7700EF9F72 /* ComplexTextController.h */,
                                37C238201098C84200EF9F72 /* ComplexTextControllerCoreText.mm */,
+                               2DE70022192FE82A00B0975C /* DisplayRefreshMonitorMac.h */,
                                49AF2D6B14435D210016A784 /* DisplayRefreshMonitorMac.cpp */,
                                B275354B0B053814002CE64F /* FloatPointMac.mm */,
                                B275354C0B053814002CE64F /* FloatRectMac.mm */,
                                A8CB41020E85B8A50032C4F0 /* DashArray.h */,
                                49FC7A4F1444AF5F00A5D864 /* DisplayRefreshMonitor.cpp */,
                                49AF2D6814435D050016A784 /* DisplayRefreshMonitor.h */,
+                               2D29ECC1192ECC8300984B78 /* DisplayRefreshMonitorClient.cpp */,
+                               2D29ECC2192ECC8300984B78 /* DisplayRefreshMonitorClient.h */,
+                               2D29ECC3192ECC8300984B78 /* DisplayRefreshMonitorManager.cpp */,
+                               2D29ECC4192ECC8300984B78 /* DisplayRefreshMonitorManager.h */,
                                6E67D2A81280E8BD008758F7 /* Extensions3D.h */,
                                B275353A0B053814002CE64F /* FloatPoint.cpp */,
                                B275353B0B053814002CE64F /* FloatPoint.h */,
                                BE88E0D91715D2A200658D98 /* AudioTrack.h in Headers */,
                                BE88E0DC1715D2A200658D98 /* AudioTrackList.h in Headers */,
                                CD8B5A4C180E17C0008B8E65 /* AudioTrackMediaSource.h in Headers */,
+                               2DE70023192FE82A00B0975C /* DisplayRefreshMonitorMac.h in Headers */,
                                BEF29EEB1715DD0900C4B4C9 /* AudioTrackPrivate.h in Headers */,
                                CDE3A85417F5FCE600C5BE20 /* AudioTrackPrivateAVF.h in Headers */,
                                CDE3A85817F6020400C5BE20 /* AudioTrackPrivateAVFObjC.h in Headers */,
                                A584FE351864D5AF00843B10 /* CommandLineAPIHost.h in Headers */,
                                A584FE2C1863870F00843B10 /* CommandLineAPIModule.h in Headers */,
                                A584FE2618637DAB00843B10 /* CommandLineAPIModuleSource.h in Headers */,
+                               2D29ECC8192ECC8300984B78 /* DisplayRefreshMonitorManager.h in Headers */,
                                6550B6A2099DF0270090D781 /* Comment.h in Headers */,
                                E1FE137518402A6700892F13 /* CommonCryptoUtilities.h in Headers */,
                                37C236111097EE7700EF9F72 /* ComplexTextController.h in Headers */,
                                85E7119D0AC5D5350053270F /* DOMHTMLBaseElementInternal.h in Headers */,
                                85ECBEED0AA7626900544F0B /* DOMHTMLBaseFontElement.h in Headers */,
                                85E7119E0AC5D5350053270F /* DOMHTMLBaseFontElementInternal.h in Headers */,
+                               2D29ECCA192F1F1D00984B78 /* DisplayRefreshMonitorIOS.h in Headers */,
                                859A9C490AA5E3BD00B694B2 /* DOMHTMLBodyElement.h in Headers */,
                                85E7119F0AC5D5350053270F /* DOMHTMLBodyElementInternal.h in Headers */,
                                85183B420AA6926100F19FA3 /* DOMHTMLBRElement.h in Headers */,
                                B2FA3DAD0AB75A6F000E5AC4 /* JSSVGMatrix.h in Headers */,
                                B2FA3DAF0AB75A6F000E5AC4 /* JSSVGMetadataElement.h in Headers */,
                                B27B282A0CEF0C0700D39D54 /* JSSVGMissingGlyphElement.h in Headers */,
+                               2D29ECC6192ECC8300984B78 /* DisplayRefreshMonitorClient.h in Headers */,
                                4496E3A0139813A5003EE32A /* JSSVGMPathElement.h in Headers */,
                                8542A7970AE5C94300DF58DF /* JSSVGNumber.h in Headers */,
                                B2FA3DB10AB75A6F000E5AC4 /* JSSVGNumberList.h in Headers */,
                                BE8EF04C171C9014009B48C3 /* JSVideoTrackList.cpp in Sources */,
                                BE6DF70D171CA2C500DD52B8 /* JSVideoTrackListCustom.cpp in Sources */,
                                9703E1BF15DC4E37001F24C8 /* JSVoidCallback.cpp in Sources */,
+                               2D29ECC5192ECC8300984B78 /* DisplayRefreshMonitorClient.cpp in Sources */,
                                BE20508118A460BC0080647E /* JSVTTCue.cpp in Sources */,
                                FD82D7F713D4C8BD004E4372 /* JSWaveShaperNode.cpp in Sources */,
                                A7D20F62107F406900A80392 /* JSWebGLActiveInfo.cpp in Sources */,
                                93309E13099E64920056E581 /* SplitTextNodeCommand.cpp in Sources */,
                                93309E15099E64920056E581 /* SplitTextNodeContainingElementCommand.cpp in Sources */,
                                A1E1154813015C5D0054AC8C /* SpotLightSource.cpp in Sources */,
+                               2D29ECC7192ECC8300984B78 /* DisplayRefreshMonitorManager.cpp in Sources */,
                                97BC6A3E1505F081001B74AC /* SQLException.cpp in Sources */,
                                1A2E6E7A0CC556D5004A2062 /* SQLiteAuthorizer.cpp in Sources */,
                                1A2246490CC98DDB00C05240 /* SQLiteDatabase.cpp in Sources */,
index ca582adddc4b335a6849752491b4db7e4c9bff2c..626bd4fbbe0ca8aec2f8fd443aa112d898129a50 100644 (file)
@@ -28,6 +28,8 @@
 
 #if ENABLE(REQUEST_ANIMATION_FRAME)
 
+#include "DisplayRefreshMonitor.h"
+#include "DisplayRefreshMonitorManager.h"
 #include "Document.h"
 #include "DocumentLoader.h"
 #include "FrameView.h"
@@ -171,7 +173,7 @@ void ScriptedAnimationController::windowScreenDidChange(PlatformDisplayID displa
     if (m_document->settings() && !m_document->settings()->requestAnimationFrameEnabled())
         return;
 #if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
-    DisplayRefreshMonitorManager::sharedManager()->windowScreenDidChange(displayID, this);
+    DisplayRefreshMonitorManager::sharedManager().windowScreenDidChange(displayID, this);
 #else
     UNUSED_PARAM(displayID);
 #endif
@@ -185,7 +187,7 @@ void ScriptedAnimationController::scheduleAnimation()
 #if USE(REQUEST_ANIMATION_FRAME_TIMER)
 #if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
     if (!m_isUsingTimer && !m_isThrottled) {
-        if (DisplayRefreshMonitorManager::sharedManager()->scheduleAnimation(this))
+        if (DisplayRefreshMonitorManager::sharedManager().scheduleAnimation(this))
             return;
 
         m_isUsingTimer = true;
@@ -223,6 +225,13 @@ void ScriptedAnimationController::displayRefreshFired(double monotonicTimeNow)
 #endif
 
 
+#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
+PassRefPtr<DisplayRefreshMonitor> ScriptedAnimationController::createDisplayRefreshMonitor(PlatformDisplayID displayID) const
+{
+    return m_document->page()->chrome().client().createDisplayRefreshMonitor(displayID);
+}
+#endif
+
 
 }
 
index f2808e78dc6c11b3f15d25af2f096b9d9a46ce1b..73296e98655d888e831bed5897916bb20d71721a 100644 (file)
@@ -30,7 +30,9 @@
 #include "DOMTimeStamp.h"
 #if USE(REQUEST_ANIMATION_FRAME_TIMER)
 #if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
-#include "DisplayRefreshMonitor.h"
+#include "Chrome.h"
+#include "ChromeClient.h"
+#include "DisplayRefreshMonitorClient.h"
 #endif
 #include "Timer.h"
 #endif
@@ -89,6 +91,7 @@ private:
 #if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
     // Override for DisplayRefreshMonitorClient
     virtual void displayRefreshFired(double timestamp) override;
+    virtual PassRefPtr<DisplayRefreshMonitor> createDisplayRefreshMonitor(PlatformDisplayID) const override;
 
     bool m_isUsingTimer;
     bool m_isThrottled;
index 61d5bab02b3a152e50fb20f12ba716a6c6bd29cb..c4f5f09521ea34c26b330e644fca4e3d5f9b8630 100644 (file)
@@ -24,6 +24,7 @@
 
 #include "AXObjectCache.h"
 #include "Cursor.h"
+#include "DisplayRefreshMonitor.h"
 #include "FocusDirection.h"
 #include "FrameLoader.h"
 #include "GraphicsContext.h"
@@ -279,7 +280,11 @@ public:
     virtual bool shouldPaintEntireContents() const { return false; }
 
     // Allows ports to customize the type of graphics layers created by this page.
-    virtual GraphicsLayerFactory* graphicsLayerFactory() const { return 0; }
+    virtual GraphicsLayerFactory* graphicsLayerFactory() const { return nullptr; }
+
+#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
+    virtual PassRefPtr<DisplayRefreshMonitor> createDisplayRefreshMonitor(PlatformDisplayID) const { return nullptr; }
+#endif
 
     // Pass 0 as the GraphicsLayer to detatch the root layer.
     virtual void attachRootGraphicsLayer(Frame*, GraphicsLayer*) = 0;
index b786c748d93f53c974723992237ec17a5df0cdb8..0559dc525fdd6f75784f7732c1a9bc016dd6b4ff 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2010, 2014 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  */
 
 #include "config.h"
+#include "DisplayRefreshMonitor.h"
 
 #if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
 
-#include "DisplayRefreshMonitor.h"
-#include <wtf/CurrentTime.h>
-#include <wtf/Ref.h>
+#include "DisplayRefreshMonitorClient.h"
+#include "DisplayRefreshMonitorIOS.h"
+#include "DisplayRefreshMonitorMac.h"
+#include "DisplayRefreshMonitorManager.h"
 
 namespace WebCore {
 
-DisplayRefreshMonitorClient::DisplayRefreshMonitorClient()
-    : m_scheduled(false)
-    , m_displayIDIsSet(false)
+PassRefPtr<DisplayRefreshMonitor> DisplayRefreshMonitor::create(DisplayRefreshMonitorClient* client)
 {
-}
+    PlatformDisplayID displayID = client->displayID();
 
-DisplayRefreshMonitorClient::~DisplayRefreshMonitorClient()
-{
-    DisplayRefreshMonitorManager::sharedManager()->unregisterClient(this);
-}
+    if (RefPtr<DisplayRefreshMonitor> monitor = client->createDisplayRefreshMonitor(displayID))
+        return monitor.release();
 
-void DisplayRefreshMonitorClient::fireDisplayRefreshIfNeeded(double timestamp)
-{
-    if (m_scheduled) {
-        m_scheduled = false;
-        displayRefreshFired(timestamp);
-    }
+#if PLATFORM(MAC)
+    return DisplayRefreshMonitorMac::create(displayID);
+#endif
+#if PLATFORM(IOS)
+    return DisplayRefreshMonitorIOS::create(displayID);
+#endif
 }
 
 DisplayRefreshMonitor::DisplayRefreshMonitor(PlatformDisplayID displayID)
@@ -60,9 +58,10 @@ DisplayRefreshMonitor::DisplayRefreshMonitor(PlatformDisplayID displayID)
     , m_unscheduledFireCount(0)
     , m_displayID(displayID)
     , m_clientsToBeNotified(nullptr)
-#if PLATFORM(COCOA)
-    , m_displayLink(0)
-#endif
+{
+}
+
+DisplayRefreshMonitor::~DisplayRefreshMonitor()
 {
 }
 
@@ -87,6 +86,7 @@ bool DisplayRefreshMonitor::removeClient(DisplayRefreshMonitorClient* client)
 void DisplayRefreshMonitor::displayDidRefresh()
 {
     double monotonicAnimationStartTime;
+
     {
         MutexLocker lock(m_mutex);
         if (!m_scheduled)
@@ -107,12 +107,7 @@ void DisplayRefreshMonitor::displayDidRefresh()
     HashSet<DisplayRefreshMonitorClient*> clientsToBeNotified = m_clients;
     m_clientsToBeNotified = &clientsToBeNotified;
     while (!clientsToBeNotified.isEmpty()) {
-        // Take a random client out of the set. Ordering doesn't matter.
-        // FIXME: Would read more cleanly if HashSet had a take function.
-        auto it = clientsToBeNotified.begin();
-        DisplayRefreshMonitorClient* client = *it;
-        clientsToBeNotified.remove(it);
-
+        DisplayRefreshMonitorClient* client = clientsToBeNotified.takeAny();
         client->fireDisplayRefreshIfNeeded(monotonicAnimationStartTime);
 
         // This checks if this function was reentered. In that case, stop iterating
@@ -120,6 +115,7 @@ void DisplayRefreshMonitor::displayDidRefresh()
         if (m_clientsToBeNotified != &clientsToBeNotified)
             break;
     }
+
     if (m_clientsToBeNotified == &clientsToBeNotified)
         m_clientsToBeNotified = nullptr;
 
@@ -128,82 +124,7 @@ void DisplayRefreshMonitor::displayDidRefresh()
         m_previousFrameDone = true;
     }
     
-    DisplayRefreshMonitorManager::sharedManager()->displayDidRefresh(this);
-}
-
-DisplayRefreshMonitorManager* DisplayRefreshMonitorManager::sharedManager()
-{
-    DEPRECATED_DEFINE_STATIC_LOCAL(DisplayRefreshMonitorManager, manager, ());
-    return &manager;
-}
-
-DisplayRefreshMonitor* DisplayRefreshMonitorManager::ensureMonitorForClient(DisplayRefreshMonitorClient* client)
-{
-    DisplayRefreshMonitorMap::iterator it = m_monitors.find(client->m_displayID);
-    if (it == m_monitors.end()) {
-        RefPtr<DisplayRefreshMonitor> monitor = DisplayRefreshMonitor::create(client->m_displayID);
-        monitor->addClient(client);
-        DisplayRefreshMonitor* result = monitor.get();
-        m_monitors.add(client->m_displayID, monitor.release());
-        return result;
-    }
-    it->value->addClient(client);
-    return it->value.get();
-}
-
-void DisplayRefreshMonitorManager::registerClient(DisplayRefreshMonitorClient* client)
-{
-    if (!client->m_displayIDIsSet)
-        return;
-        
-    ensureMonitorForClient(client);
-}
-
-void DisplayRefreshMonitorManager::unregisterClient(DisplayRefreshMonitorClient* client)
-{
-    if (!client->m_displayIDIsSet)
-        return;
-
-    DisplayRefreshMonitorMap::iterator it = m_monitors.find(client->m_displayID);
-    if (it == m_monitors.end())
-        return;
-    
-    DisplayRefreshMonitor* monitor = it->value.get();
-    if (monitor->removeClient(client)) {
-        if (!monitor->hasClients())
-            m_monitors.remove(it);
-    }
-}
-
-bool DisplayRefreshMonitorManager::scheduleAnimation(DisplayRefreshMonitorClient* client)
-{
-    if (!client->m_displayIDIsSet)
-        return false;
-        
-    DisplayRefreshMonitor* monitor = ensureMonitorForClient(client);
-
-    client->m_scheduled = true;
-    return monitor->requestRefreshCallback();
-}
-
-void DisplayRefreshMonitorManager::displayDidRefresh(DisplayRefreshMonitor* monitor)
-{
-    if (monitor->shouldBeTerminated()) {
-        ASSERT(m_monitors.contains(monitor->displayID()));
-        m_monitors.remove(monitor->displayID());
-    }
-}
-
-void DisplayRefreshMonitorManager::windowScreenDidChange(PlatformDisplayID displayID, DisplayRefreshMonitorClient* client)
-{
-    if (client->m_displayIDIsSet && client->m_displayID == displayID)
-        return;
-    
-    unregisterClient(client);
-    client->setDisplayID(displayID);
-    registerClient(client);
-    if (client->m_scheduled)
-        scheduleAnimation(client);
+    DisplayRefreshMonitorManager::sharedManager().displayDidRefresh(this);
 }
 
 }
index 2d9518448dc58d3decbe7adbef92a1d97320ac23..8feb38763b2a8937175d3fbe340c852715b6f186 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2010, 2014 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
 #if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
 
 #include "PlatformScreen.h"
-#include <wtf/HashMap.h>
 #include <wtf/HashSet.h>
 #include <wtf/RefCounted.h>
 #include <wtf/RefPtr.h>
 #include <wtf/Threading.h>
 
-#if PLATFORM(COCOA)
-typedef struct __CVDisplayLink *CVDisplayLinkRef;
-#endif
-
 namespace WebCore {
 
 class DisplayAnimationClient;
-class DisplayRefreshMonitor;
-class DisplayRefreshMonitorManager;
-
-//
-// Abstract virtual client which receives refresh fired messages on the main thread
-//
-class DisplayRefreshMonitorClient {
-    friend class DisplayRefreshMonitor;
-    friend class DisplayRefreshMonitorManager;
-    
-public:
-    DisplayRefreshMonitorClient();
-    virtual ~DisplayRefreshMonitorClient();
-    
-    virtual void displayRefreshFired(double timestamp) = 0;
-
-private:
-    void fireDisplayRefreshIfNeeded(double timestamp);
-    
-    void setDisplayID(PlatformDisplayID displayID)
-    {
-        m_displayID = displayID;
-        m_displayIDIsSet = true;
-    }
-    
-    bool m_scheduled;
-    bool m_displayIDIsSet;
-    PlatformDisplayID m_displayID;
-};
-
-//
-// Monitor for display refresh messages for a given screen
-//
+class DisplayRefreshMonitorClient;
 
 class DisplayRefreshMonitor : public RefCounted<DisplayRefreshMonitor> {
 public:
-    static PassRefPtr<DisplayRefreshMonitor> create(PlatformDisplayID displayID)
-    {
-        return adoptRef(new DisplayRefreshMonitor(displayID));
-    }
-    
-    ~DisplayRefreshMonitor();
+    static PassRefPtr<DisplayRefreshMonitor> create(DisplayRefreshMonitorClient*);
+    virtual ~DisplayRefreshMonitor();
     
     // Return true if callback request was scheduled, false if it couldn't be
     // (e.g., hardware refresh is not available)
-    bool requestRefreshCallback();
+    virtual bool requestRefreshCallback() = 0;
     void windowScreenDidChange(PlatformDisplayID);
     
     bool hasClients() const { return m_clients.size(); }
@@ -101,12 +60,26 @@ public:
         const int maxInactiveFireCount = 10;
         return !m_scheduled && m_unscheduledFireCount > maxInactiveFireCount;
     }
-    
-private:
+
+    bool isActive() const { return m_active; }
+    void setIsActive(bool active) { m_active = active; }
+
+    bool isScheduled() const { return m_scheduled; }
+    void setIsScheduled(bool scheduled) { m_scheduled = scheduled; }
+
+    bool isPreviousFrameDone() const { return m_previousFrameDone; }
+    void setIsPreviousFrameDone(bool done) { m_previousFrameDone = done; }
+
+    void setMonotonicAnimationStartTime(double startTime) { m_monotonicAnimationStartTime = startTime; }
+
+    Mutex& mutex() { return m_mutex; }
+
+protected:
     explicit DisplayRefreshMonitor(PlatformDisplayID);
+    static void handleDisplayRefreshedNotificationOnMainThread(void* data);
 
+private:
     void displayDidRefresh();
-    static void handleDisplayRefreshedNotificationOnMainThread(void* data);
 
     double m_monotonicAnimationStartTime;
     bool m_active;
@@ -118,50 +91,6 @@ private:
 
     HashSet<DisplayRefreshMonitorClient*> m_clients;
     HashSet<DisplayRefreshMonitorClient*>* m_clientsToBeNotified;
-
-#if PLATFORM(MAC)
-public:
-    void displayLinkFired(double nowSeconds, double outputTimeSeconds);
-private:
-    CVDisplayLinkRef m_displayLink;
-#endif
-
-#if PLATFORM(IOS)
-public:
-    void displayLinkFired(double nowSeconds);
-private:
-    void* m_displayLink;
-#endif
-};
-
-//
-// Singleton manager for all the DisplayRefreshMonitors. This is the interface to the 
-// outside world. It distributes requests to the appropriate monitor. When the display
-// refresh event fires, the passed DisplayRefreshMonitorClient is called directly on
-// the main thread.
-//
-class DisplayRefreshMonitorManager {
-public:
-    static DisplayRefreshMonitorManager* sharedManager();
-    
-    void registerClient(DisplayRefreshMonitorClient*);
-    void unregisterClient(DisplayRefreshMonitorClient*);
-
-    bool scheduleAnimation(DisplayRefreshMonitorClient*);
-    void windowScreenDidChange(PlatformDisplayID, DisplayRefreshMonitorClient*);
-
-private:
-    friend class DisplayRefreshMonitor;
-    void displayDidRefresh(DisplayRefreshMonitor*);
-    
-    DisplayRefreshMonitorManager() { }
-    DisplayRefreshMonitor* ensureMonitorForClient(DisplayRefreshMonitorClient*);
-
-    // We know nothing about the values of PlatformDisplayIDs, so use UnsignedWithZeroKeyHashTraits.
-    // FIXME: Since we know nothing about these values, this is not sufficient.
-    // Even with UnsignedWithZeroKeyHashTraits, there are still two special values used for empty and deleted hash table slots.
-    typedef HashMap<uint64_t, RefPtr<DisplayRefreshMonitor>, WTF::IntHash<uint64_t>, WTF::UnsignedWithZeroKeyHashTraits<uint64_t>> DisplayRefreshMonitorMap;
-    DisplayRefreshMonitorMap m_monitors;
 };
 
 }
diff --git a/Source/WebCore/platform/graphics/DisplayRefreshMonitorClient.cpp b/Source/WebCore/platform/graphics/DisplayRefreshMonitorClient.cpp
new file mode 100644 (file)
index 0000000..c2cda38
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2010, 2014 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "DisplayRefreshMonitorClient.h"
+
+#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
+
+#include "DisplayRefreshMonitor.h"
+#include "DisplayRefreshMonitorManager.h"
+
+namespace WebCore {
+
+DisplayRefreshMonitorClient::DisplayRefreshMonitorClient()
+    : m_scheduled(false)
+    , m_displayIDIsSet(false)
+{
+}
+
+DisplayRefreshMonitorClient::~DisplayRefreshMonitorClient()
+{
+    DisplayRefreshMonitorManager::sharedManager().unregisterClient(this);
+}
+
+void DisplayRefreshMonitorClient::fireDisplayRefreshIfNeeded(double timestamp)
+{
+    if (!m_scheduled)
+        return;
+
+    m_scheduled = false;
+    displayRefreshFired(timestamp);
+}
+
+}
+
+#endif // USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
diff --git a/Source/WebCore/platform/graphics/DisplayRefreshMonitorClient.h b/Source/WebCore/platform/graphics/DisplayRefreshMonitorClient.h
new file mode 100644 (file)
index 0000000..b6ee8d6
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2010, 2014 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef DisplayRefreshMonitorClient_h
+#define DisplayRefreshMonitorClient_h
+
+#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
+
+#include "PlatformScreen.h"
+
+namespace WebCore {
+
+class DisplayRefreshMonitor;
+class DisplayRefreshMonitorManager;
+
+class DisplayRefreshMonitorClient {
+public:
+    DisplayRefreshMonitorClient();
+    virtual ~DisplayRefreshMonitorClient();
+
+    // Always called on the main thread.
+    virtual void displayRefreshFired(double timestamp) = 0;
+
+    virtual PassRefPtr<DisplayRefreshMonitor> createDisplayRefreshMonitor(PlatformDisplayID) const = 0;
+
+    PlatformDisplayID displayID() const { return m_displayID; }
+    bool hasDisplayID() const { return m_displayIDIsSet; }
+    void setDisplayID(PlatformDisplayID displayID)
+    {
+        m_displayID = displayID;
+        m_displayIDIsSet = true;
+    }
+
+    void setIsScheduled(bool isScheduled) { m_scheduled = isScheduled; }
+    bool isScheduled() const { return m_scheduled; }
+
+    void fireDisplayRefreshIfNeeded(double timestamp);
+
+private:
+    bool m_scheduled;
+    bool m_displayIDIsSet;
+    PlatformDisplayID m_displayID;
+};
+
+}
+
+#endif // USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
+
+#endif
diff --git a/Source/WebCore/platform/graphics/DisplayRefreshMonitorManager.cpp b/Source/WebCore/platform/graphics/DisplayRefreshMonitorManager.cpp
new file mode 100644 (file)
index 0000000..137eb92
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2010, 2014 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "DisplayRefreshMonitorManager.h"
+
+#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
+
+#include "DisplayRefreshMonitor.h"
+#include "DisplayRefreshMonitorClient.h"
+#include <wtf/CurrentTime.h>
+
+namespace WebCore {
+
+DisplayRefreshMonitorManager::~DisplayRefreshMonitorManager()
+{
+}
+
+DisplayRefreshMonitorManager& DisplayRefreshMonitorManager::sharedManager()
+{
+    static NeverDestroyed<DisplayRefreshMonitorManager> manager;
+    return manager.get();
+}
+
+DisplayRefreshMonitor* DisplayRefreshMonitorManager::ensureMonitorForClient(DisplayRefreshMonitorClient* client)
+{
+    DisplayRefreshMonitorMap::iterator it = m_monitors.find(client->displayID());
+    if (it == m_monitors.end()) {
+        RefPtr<DisplayRefreshMonitor> monitor = DisplayRefreshMonitor::create(client);
+        monitor->addClient(client);
+        DisplayRefreshMonitor* result = monitor.get();
+        m_monitors.add(client->displayID(), monitor.release());
+        return result;
+    }
+    it->value->addClient(client);
+    return it->value.get();
+}
+
+void DisplayRefreshMonitorManager::registerClient(DisplayRefreshMonitorClient* client)
+{
+    if (!client->hasDisplayID())
+        return;
+
+    ensureMonitorForClient(client);
+}
+
+void DisplayRefreshMonitorManager::unregisterClient(DisplayRefreshMonitorClient* client)
+{
+    if (!client->hasDisplayID())
+        return;
+
+    DisplayRefreshMonitorMap::iterator it = m_monitors.find(client->displayID());
+    if (it == m_monitors.end())
+        return;
+
+    DisplayRefreshMonitor* monitor = it->value.get();
+    if (monitor->removeClient(client)) {
+        if (!monitor->hasClients())
+            m_monitors.remove(it);
+    }
+}
+
+bool DisplayRefreshMonitorManager::scheduleAnimation(DisplayRefreshMonitorClient* client)
+{
+    if (!client->hasDisplayID())
+        return false;
+
+    DisplayRefreshMonitor* monitor = ensureMonitorForClient(client);
+
+    client->setIsScheduled(true);
+    return monitor->requestRefreshCallback();
+}
+
+void DisplayRefreshMonitorManager::displayDidRefresh(DisplayRefreshMonitor* monitor)
+{
+    if (monitor->shouldBeTerminated()) {
+        ASSERT(m_monitors.contains(monitor->displayID()));
+        m_monitors.remove(monitor->displayID());
+    }
+}
+
+void DisplayRefreshMonitorManager::windowScreenDidChange(PlatformDisplayID displayID, DisplayRefreshMonitorClient* client)
+{
+    if (client->hasDisplayID() && client->displayID() == displayID)
+        return;
+    
+    unregisterClient(client);
+    client->setDisplayID(displayID);
+    registerClient(client);
+    if (client->isScheduled())
+        scheduleAnimation(client);
+}
+
+}
+
+#endif // USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
diff --git a/Source/WebCore/platform/graphics/DisplayRefreshMonitorManager.h b/Source/WebCore/platform/graphics/DisplayRefreshMonitorManager.h
new file mode 100644 (file)
index 0000000..296a7c9
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2010, 2014 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef DisplayRefreshMonitorManager_h
+#define DisplayRefreshMonitorManager_h
+
+#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
+
+#include "DisplayRefreshMonitor.h"
+#include "PlatformScreen.h"
+#include <wtf/HashMap.h>
+#include <wtf/NeverDestroyed.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+class DisplayRefreshMonitorManager {
+    friend class NeverDestroyed<DisplayRefreshMonitorManager>;
+public:
+    static DisplayRefreshMonitorManager& sharedManager();
+    
+    void registerClient(DisplayRefreshMonitorClient*);
+    void unregisterClient(DisplayRefreshMonitorClient*);
+
+    bool scheduleAnimation(DisplayRefreshMonitorClient*);
+    void windowScreenDidChange(PlatformDisplayID, DisplayRefreshMonitorClient*);
+
+private:
+    friend class DisplayRefreshMonitor;
+    void displayDidRefresh(DisplayRefreshMonitor*);
+    
+    DisplayRefreshMonitorManager() { }
+    virtual ~DisplayRefreshMonitorManager();
+
+    DisplayRefreshMonitor* ensureMonitorForClient(DisplayRefreshMonitorClient*);
+
+    // We know nothing about the values of PlatformDisplayIDs, so use UnsignedWithZeroKeyHashTraits.
+    // FIXME: Since we know nothing about these values, this is not sufficient.
+    // Even with UnsignedWithZeroKeyHashTraits, there are still two special values used for empty and deleted hash table slots.
+    typedef HashMap<uint64_t, RefPtr<DisplayRefreshMonitor>, WTF::IntHash<uint64_t>, WTF::UnsignedWithZeroKeyHashTraits<uint64_t>> DisplayRefreshMonitorMap;
+    DisplayRefreshMonitorMap m_monitors;
+};
+
+}
+
+#endif // USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
+
+#endif
index 89867df168c531391ebead4f516a1704b99cef43..cb66f40009c151db4645254cb7d77c93a0e5cedd 100644 (file)
@@ -24,9 +24,9 @@
  */
 
 #include "config.h"
-
 #include "GraphicsLayerUpdater.h"
 
+#include "DisplayRefreshMonitorManager.h"
 #include "GraphicsLayer.h"
 
 namespace WebCore {
@@ -36,9 +36,9 @@ GraphicsLayerUpdater::GraphicsLayerUpdater(GraphicsLayerUpdaterClient* client, P
     , m_scheduled(false)
 {
 #if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
-    DisplayRefreshMonitorManager::sharedManager()->registerClient(this);
-    DisplayRefreshMonitorManager::sharedManager()->windowScreenDidChange(displayID, this);
-    DisplayRefreshMonitorManager::sharedManager()->scheduleAnimation(this);
+    DisplayRefreshMonitorManager::sharedManager().registerClient(this);
+    DisplayRefreshMonitorManager::sharedManager().windowScreenDidChange(displayID, this);
+    DisplayRefreshMonitorManager::sharedManager().scheduleAnimation(this);
 #else
     UNUSED_PARAM(displayID);
 #endif
@@ -55,7 +55,7 @@ void GraphicsLayerUpdater::scheduleUpdate()
         return;
 
 #if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
-    DisplayRefreshMonitorManager::sharedManager()->scheduleAnimation(this);
+    DisplayRefreshMonitorManager::sharedManager().scheduleAnimation(this);
 #endif
     m_scheduled = true;
 }
@@ -63,7 +63,7 @@ void GraphicsLayerUpdater::scheduleUpdate()
 void GraphicsLayerUpdater::screenDidChange(PlatformDisplayID displayID)
 {
 #if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
-    DisplayRefreshMonitorManager::sharedManager()->windowScreenDidChange(displayID, this);
+    DisplayRefreshMonitorManager::sharedManager().windowScreenDidChange(displayID, this);
 #else
     UNUSED_PARAM(displayID);
 #endif
@@ -78,4 +78,11 @@ void GraphicsLayerUpdater::displayRefreshFired(double timestamp)
         m_client->flushLayersSoon(this);
 }
 
+#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
+PassRefPtr<DisplayRefreshMonitor> GraphicsLayerUpdater::createDisplayRefreshMonitor(PlatformDisplayID displayID) const
+{
+    return m_client ? m_client->createDisplayRefreshMonitor(displayID) : nullptr;
+}
+#endif
+
 } // namespace WebCore
index 58e190ddc0a6d18f2b191e5a9963dfbd58e9c911..c3d73a80a7c5c938bec0415b0de4281a6ed06a7a 100644 (file)
@@ -26,7 +26,7 @@
 #ifndef GraphicsLayerUpdater_h
 #define GraphicsLayerUpdater_h
 
-#include "DisplayRefreshMonitor.h"
+#include "DisplayRefreshMonitorClient.h"
 #include "PlatformScreen.h"
 
 namespace WebCore {
@@ -37,6 +37,9 @@ class GraphicsLayerUpdaterClient {
 public:
     virtual ~GraphicsLayerUpdaterClient() { }
     virtual void flushLayersSoon(GraphicsLayerUpdater*) = 0;
+#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
+    virtual PassRefPtr<DisplayRefreshMonitor> createDisplayRefreshMonitor(PlatformDisplayID) const = 0;
+#endif
 };
 
 class GraphicsLayerUpdater
@@ -51,6 +54,10 @@ public:
     void scheduleUpdate();
     void screenDidChange(PlatformDisplayID);
 
+#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
+    virtual PassRefPtr<DisplayRefreshMonitor> createDisplayRefreshMonitor(PlatformDisplayID) const override;
+#endif
+
 private:
     virtual void displayRefreshFired(double timestamp);
 
diff --git a/Source/WebCore/platform/graphics/ios/DisplayRefreshMonitorIOS.h b/Source/WebCore/platform/graphics/ios/DisplayRefreshMonitorIOS.h
new file mode 100644 (file)
index 0000000..bae2a52
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2014 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef DisplayRefreshMonitorIOS_h
+#define DisplayRefreshMonitorIOS_h
+
+#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
+
+#include "DisplayRefreshMonitor.h"
+#include <wtf/RetainPtr.h>
+
+OBJC_CLASS WebDisplayLinkHandler;
+
+namespace WebCore {
+
+class DisplayRefreshMonitorIOS : public DisplayRefreshMonitor {
+public:
+    static PassRefPtr<DisplayRefreshMonitorIOS> create(PlatformDisplayID displayID)
+    {
+        return adoptRef(new DisplayRefreshMonitorIOS(displayID));
+    }
+    
+    virtual ~DisplayRefreshMonitorIOS();
+
+    void displayLinkFired(double nowSeconds);
+    virtual bool requestRefreshCallback() override;
+
+private:
+    explicit DisplayRefreshMonitorIOS(PlatformDisplayID);
+    RetainPtr<WebDisplayLinkHandler> m_handler;
+};
+
+}
+
+#endif // USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
+
+#endif
index c338e0f5e8d2ff6e1dd9c57bff21c82f490696eb..e8e275b4d08c96d6d6d3435884a0b4d2cde62ed0 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2010, 2014 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
  */
 
-#include "config.h"
+#import "config.h"
+#import "DisplayRefreshMonitorIOS.h"
 
 #if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
 
-#include "DisplayRefreshMonitor.h"
-
-#include <QuartzCore/QuartzCore.h>
-#include <wtf/CurrentTime.h>
-#include <wtf/MainThread.h>
-
 #import "WebCoreThread.h"
+#import <QuartzCore/QuartzCore.h>
+#import <wtf/CurrentTime.h>
+#import <wtf/MainThread.h>
+
+using namespace WebCore;
 
 @interface WebDisplayLinkHandler : NSObject
 {
-    WebCore::DisplayRefreshMonitor* m_monitor;
-    CADisplayLinkm_displayLink;
+    DisplayRefreshMonitorIOS* m_monitor;
+    CADisplayLink *m_displayLink;
 }
 
-- (id)initWithMonitor:(WebCore::DisplayRefreshMonitor*)monitor;
+- (id)initWithMonitor:(DisplayRefreshMonitorIOS*)monitor;
 - (void)handleDisplayLink:(CADisplayLink *)sender;
 - (void)invalidate;
 
 @end
 
-static double mediaTimeToCurrentTime(CFTimeInterval t)
-{
-    return monotonicallyIncreasingTime() + t - CACurrentMediaTime();
-}
-
 @implementation WebDisplayLinkHandler
 
-- (id)initWithMonitor:(WebCore::DisplayRefreshMonitor*)monitor
+- (id)initWithMonitor:(DisplayRefreshMonitorIOS*)monitor
 {
     if (self = [super init]) {
         m_monitor = monitor;
@@ -86,34 +81,44 @@ static double mediaTimeToCurrentTime(CFTimeInterval t)
 @end
 
 namespace WebCore {
-DisplayRefreshMonitor::~DisplayRefreshMonitor()
+
+DisplayRefreshMonitorIOS::DisplayRefreshMonitorIOS(PlatformDisplayID displayID)
+    : DisplayRefreshMonitor(displayID)
 {
-    [(WebDisplayLinkHandler*) m_displayLink invalidate];
-    [(WebDisplayLinkHandler*) m_displayLink release];
 }
 
-bool DisplayRefreshMonitor::requestRefreshCallback()
+DisplayRefreshMonitorIOS::~DisplayRefreshMonitorIOS()
 {
-    if (!m_active)
+    [m_handler invalidate];
+}
+
+bool DisplayRefreshMonitorIOS::requestRefreshCallback()
+{
+    if (!isActive())
         return false;
-        
-    if (!m_displayLink) {
-        m_displayLink = [[WebDisplayLinkHandler alloc] initWithMonitor:this];
-        m_active = true;
+
+    if (!m_handler) {
+        m_handler = adoptNS([[WebDisplayLinkHandler alloc] initWithMonitor:this]);
+        setIsActive(true);
     }
 
-    m_scheduled = true;
+    setIsScheduled(true);
     return true;
 }
 
-void DisplayRefreshMonitor::displayLinkFired(double nowSeconds)
+static double mediaTimeToCurrentTime(CFTimeInterval t)
+{
+    // FIXME: This may be a no-op if CACurrentMediaTime is *guaranteed* to be mach_absolute_time.
+    return monotonicallyIncreasingTime() + t - CACurrentMediaTime();
+}
+
+void DisplayRefreshMonitorIOS::displayLinkFired(double nowSeconds)
 {
-    if (!m_previousFrameDone)
+    if (!isPreviousFrameDone())
         return;
 
-    m_previousFrameDone = false;
-    m_monotonicAnimationStartTime = mediaTimeToCurrentTime(nowSeconds);
+    setIsPreviousFrameDone(false);
+    setMonotonicAnimationStartTime(mediaTimeToCurrentTime(nowSeconds));
 
     handleDisplayRefreshedNotificationOnMainThread(this);
 }
index e542cbf910ac05ad0dbd5421b21727794f47fe5f..5125bb4961f877428fab170148f248c24bf67c96 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2010, 2014 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  */
 
 #include "config.h"
+#include "DisplayRefreshMonitorMac.h"
 
 #if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
 
-#include "DisplayRefreshMonitor.h"
-
 #include <QuartzCore/QuartzCore.h>
 #include <wtf/CurrentTime.h>
 #include <wtf/MainThread.h>
 
 namespace WebCore {
 
-static CVReturn displayLinkCallback(CVDisplayLinkRef, const CVTimeStamp* now, const CVTimeStamp* outputTime, CVOptionFlags, CVOptionFlags*, void* data)
+DisplayRefreshMonitorMac::DisplayRefreshMonitorMac(PlatformDisplayID displayID)
+    : DisplayRefreshMonitor(displayID)
+    , m_displayLink(nullptr)
 {
-    DisplayRefreshMonitor* monitor = static_cast<DisplayRefreshMonitor*>(data);
-
-    double nowSeconds = static_cast<double>(now->videoTime) / static_cast<double>(now->videoTimeScale);
-    double outputTimeSeconds = static_cast<double>(outputTime->videoTime) / static_cast<double>(outputTime->videoTimeScale);
-    monitor->displayLinkFired(nowSeconds, outputTimeSeconds);
-
-    return kCVReturnSuccess;
 }
 
-DisplayRefreshMonitor::~DisplayRefreshMonitor()
+DisplayRefreshMonitorMac::~DisplayRefreshMonitorMac()
 {
     if (m_displayLink) {
         CVDisplayLinkStop(m_displayLink);
         CVDisplayLinkRelease(m_displayLink);
-        m_displayLink = 0;
+        m_displayLink = nullptr;
     }
 
     cancelCallOnMainThread(DisplayRefreshMonitor::handleDisplayRefreshedNotificationOnMainThread, this);
 }
 
-bool DisplayRefreshMonitor::requestRefreshCallback()
+static CVReturn displayLinkCallback(CVDisplayLinkRef, const CVTimeStamp* now, const CVTimeStamp* outputTime, CVOptionFlags, CVOptionFlags*, void* data)
+{
+    DisplayRefreshMonitorMac* monitor = static_cast<DisplayRefreshMonitorMac*>(data);
+
+    double nowSeconds = static_cast<double>(now->videoTime) / static_cast<double>(now->videoTimeScale);
+    double outputTimeSeconds = static_cast<double>(outputTime->videoTime) / static_cast<double>(outputTime->videoTimeScale);
+    monitor->displayLinkFired(nowSeconds, outputTimeSeconds);
+
+    return kCVReturnSuccess;
+}
+
+bool DisplayRefreshMonitorMac::requestRefreshCallback()
 {
-    if (!m_active)
+    if (!isActive())
         return false;
 
     if (!m_displayLink) {
-        m_active = false;
-        CVReturn error = CVDisplayLinkCreateWithCGDisplay(m_displayID, &m_displayLink);
+        setIsActive(false);
+        CVReturn error = CVDisplayLinkCreateWithCGDisplay(displayID(), &m_displayLink);
         if (error)
             return false;
 
@@ -76,26 +81,26 @@ bool DisplayRefreshMonitor::requestRefreshCallback()
         if (error)
             return false;
 
-        m_active = true;
+        setIsActive(true);
     }
 
-    MutexLocker lock(m_mutex);
-    m_scheduled = true;
+    MutexLocker lock(mutex());
+    setIsScheduled(true);
     return true;
 }
 
-void DisplayRefreshMonitor::displayLinkFired(double nowSeconds, double outputTimeSeconds)
+void DisplayRefreshMonitorMac::displayLinkFired(double nowSeconds, double outputTimeSeconds)
 {
-    MutexLocker lock(m_mutex);
-    if (!m_previousFrameDone)
+    MutexLocker lock(mutex());
+    if (!isPreviousFrameDone())
         return;
 
-    m_previousFrameDone = false;
+    setIsPreviousFrameDone(false);
 
     double webKitMonotonicNow = monotonicallyIncreasingTime();
     double timeUntilOutput = outputTimeSeconds - nowSeconds;
     // FIXME: Should this be using webKitMonotonicNow?
-    m_monotonicAnimationStartTime = webKitMonotonicNow + timeUntilOutput;
+    setMonotonicAnimationStartTime(webKitMonotonicNow + timeUntilOutput);
 
     callOnMainThread(handleDisplayRefreshedNotificationOnMainThread, this);
 }
diff --git a/Source/WebCore/platform/graphics/mac/DisplayRefreshMonitorMac.h b/Source/WebCore/platform/graphics/mac/DisplayRefreshMonitorMac.h
new file mode 100644 (file)
index 0000000..92ff393
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2014 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef DisplayRefreshMonitorMac_h
+#define DisplayRefreshMonitorMac_h
+
+#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
+
+#include "DisplayRefreshMonitor.h"
+
+typedef struct __CVDisplayLink *CVDisplayLinkRef;
+
+namespace WebCore {
+
+class DisplayRefreshMonitorMac : public DisplayRefreshMonitor {
+public:
+    static PassRefPtr<DisplayRefreshMonitorMac> create(PlatformDisplayID displayID)
+    {
+        return adoptRef(new DisplayRefreshMonitorMac(displayID));
+    }
+    
+    virtual ~DisplayRefreshMonitorMac();
+
+    void displayLinkFired(double nowSeconds, double outputTimeSeconds);
+    virtual bool requestRefreshCallback() override;
+
+private:
+    explicit DisplayRefreshMonitorMac(PlatformDisplayID);
+    CVDisplayLinkRef m_displayLink;
+};
+
+}
+
+#endif // USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
+
+#endif
index 10ac093bf97a0877a5439a0ff3d2e1cd707562ca..755d624c388aadf59d92fde682179056e8c49e21 100644 (file)
@@ -3925,4 +3925,16 @@ void RenderLayerCompositor::paintRelatedMilestonesTimerFired(Timer<RenderLayerCo
     m_renderView.frameView().firePaintRelatedMilestonesIfNeeded();
 }
 
+#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
+PassRefPtr<DisplayRefreshMonitor> RenderLayerCompositor::createDisplayRefreshMonitor(PlatformDisplayID displayID) const
+{
+    Frame& frame = m_renderView.frameView().frame();
+    Page* page = frame.page();
+    if (!page)
+        return nullptr;
+
+    return page->chrome().client().createDisplayRefreshMonitor(displayID);
+}
+#endif
+
 } // namespace WebCore
index e70f558ddc550b2f1e7624d49fdaf8318b794ce7..10573b854c9358999976d77671796cfa3f97e6ad 100644 (file)
@@ -391,6 +391,10 @@ private:
     GraphicsLayerFactory* graphicsLayerFactory() const;
     ScrollingCoordinator* scrollingCoordinator() const;
 
+#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
+    PassRefPtr<DisplayRefreshMonitor> createDisplayRefreshMonitor(PlatformDisplayID) const;
+#endif
+
     // Whether a running transition or animation enforces the need for a compositing layer.
     bool requiresCompositingForAnimation(RenderLayerModelObject&) const;
     bool requiresCompositingForTransform(RenderLayerModelObject&) const;
index 926ae1bbc38cf37d0481a9fe5dff75372c69a678..4323e1be31b82efbf108f6768f3705de27a7a880 100644 (file)
@@ -1,3 +1,42 @@
+2014-05-23  Tim Horton  <timothy_horton@apple.com>
+
+        REGRESSION (iOS WebKit2): requestAnimationFrame fires more than once between layer tree commits
+        https://bugs.webkit.org/show_bug.cgi?id=132794
+        <rdar://problem/16877909>
+
+        Reviewed by Simon Fraser.
+
+        * WebKit2.xcodeproj/project.pbxproj:
+        * WebProcess/WebCoreSupport/WebChromeClient.cpp:
+        (WebKit::WebChromeClient::createDisplayRefreshMonitor):
+        * WebProcess/WebCoreSupport/WebChromeClient.h:
+        * WebProcess/WebPage/DrawingArea.h:
+        (WebKit::DrawingArea::graphicsLayerFactory):
+        (WebKit::DrawingArea::createDisplayRefreshMonitor):
+        Plumb the DisplayRefreshMonitor request through to the DrawingArea.
+        RemoteLayerTreeDrawingArea will implement and return a RemoteLayerTreeDisplayRefreshMonitor.
+
+        * WebProcess/WebPage/Cocoa/RemoteLayerTreeDisplayRefreshMonitor.h: Added.
+        (WebKit::RemoteLayerTreeDisplayRefreshMonitor::create):
+        * WebProcess/WebPage/Cocoa/RemoteLayerTreeDisplayRefreshMonitor.mm: Added.
+        (WebKit::RemoteLayerTreeDisplayRefreshMonitor::RemoteLayerTreeDisplayRefreshMonitor):
+        (WebKit::RemoteLayerTreeDisplayRefreshMonitor::~RemoteLayerTreeDisplayRefreshMonitor):
+        (WebKit::RemoteLayerTreeDisplayRefreshMonitor::requestRefreshCallback):
+        When requesting a display refresh callback, schedule a layer commit.
+        It may end up being empty, but will still call us back with a didUpdate,
+        upon which we'll fire the callback.
+
+        (WebKit::RemoteLayerTreeDisplayRefreshMonitor::didUpdateLayers):
+
+        * WebProcess/WebPage/mac/RemoteLayerTreeDrawingArea.h:
+        * WebProcess/WebPage/mac/RemoteLayerTreeDrawingArea.mm:
+        (WebKit::RemoteLayerTreeDrawingArea::createDisplayRefreshMonitor):
+        (WebKit::RemoteLayerTreeDrawingArea::willDestroyDisplayRefreshMonitor):
+        Keep track of the set of DisplayRefreshMonitors.
+
+        (WebKit::RemoteLayerTreeDrawingArea::didUpdate):
+        Fire requestAnimationFrame callbacks once the UI process commits the new layer tree.
+
 2014-05-23  Jeremy Jones  <jeremyj@apple.com>
 
         Hide fullscreen immediately when switching tabs.
index 27848349901bd03321fdba0be837ea4b9304aee9..426ba81f8103ccaa6747037f0ca60d45588dfd8f 100644 (file)
                2D28F3E51885CCC1004B9EAE /* WebDatabaseManagerIOS.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2D28F3E11885CCC1004B9EAE /* WebDatabaseManagerIOS.mm */; };
                2D28F3E61885CCC1004B9EAE /* WebEditorClientIOS.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2D28F3E21885CCC1004B9EAE /* WebEditorClientIOS.mm */; };
                2D28F3E71885CCC1004B9EAE /* WebFrameLoaderClientIOS.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2D28F3E31885CCC1004B9EAE /* WebFrameLoaderClientIOS.mm */; };
+               2D29ECD0192F2C2E00984B78 /* RemoteLayerTreeDisplayRefreshMonitor.h in Headers */ = {isa = PBXBuildFile; fileRef = 2D29ECCE192F2C2E00984B78 /* RemoteLayerTreeDisplayRefreshMonitor.h */; };
+               2D29ECD1192F2C2E00984B78 /* RemoteLayerTreeDisplayRefreshMonitor.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2D29ECCF192F2C2E00984B78 /* RemoteLayerTreeDisplayRefreshMonitor.mm */; };
                2D2ADF0916362DD500197E47 /* PDFPluginTextAnnotation.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2D2ADF0616362DC700197E47 /* PDFPluginTextAnnotation.mm */; };
                2D2ADF0B16362DDB00197E47 /* PDFPluginAnnotation.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2D2ADF031636243500197E47 /* PDFPluginAnnotation.mm */; };
                2D2ADF1016364D8200197E47 /* PDFPluginChoiceAnnotation.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2D2ADF0E16364D8200197E47 /* PDFPluginChoiceAnnotation.mm */; };
                2D28F3E11885CCC1004B9EAE /* WebDatabaseManagerIOS.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = WebDatabaseManagerIOS.mm; path = ios/WebDatabaseManagerIOS.mm; sourceTree = "<group>"; };
                2D28F3E21885CCC1004B9EAE /* WebEditorClientIOS.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = WebEditorClientIOS.mm; path = ios/WebEditorClientIOS.mm; sourceTree = "<group>"; };
                2D28F3E31885CCC1004B9EAE /* WebFrameLoaderClientIOS.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = WebFrameLoaderClientIOS.mm; path = ios/WebFrameLoaderClientIOS.mm; sourceTree = "<group>"; };
+               2D29ECCE192F2C2E00984B78 /* RemoteLayerTreeDisplayRefreshMonitor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RemoteLayerTreeDisplayRefreshMonitor.h; sourceTree = "<group>"; };
+               2D29ECCF192F2C2E00984B78 /* RemoteLayerTreeDisplayRefreshMonitor.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = RemoteLayerTreeDisplayRefreshMonitor.mm; sourceTree = "<group>"; };
                2D2ADF021636243500197E47 /* PDFPluginAnnotation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PDFPluginAnnotation.h; path = PDF/PDFPluginAnnotation.h; sourceTree = "<group>"; };
                2D2ADF031636243500197E47 /* PDFPluginAnnotation.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = PDFPluginAnnotation.mm; path = PDF/PDFPluginAnnotation.mm; sourceTree = "<group>"; };
                2D2ADF0516362DC700197E47 /* PDFPluginTextAnnotation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PDFPluginTextAnnotation.h; path = PDF/PDFPluginTextAnnotation.h; sourceTree = "<group>"; };
                        name = ios;
                        sourceTree = "<group>";
                };
+               2D29ECCD192F2C2E00984B78 /* Cocoa */ = {
+                       isa = PBXGroup;
+                       children = (
+                               2D29ECCE192F2C2E00984B78 /* RemoteLayerTreeDisplayRefreshMonitor.h */,
+                               2D29ECCF192F2C2E00984B78 /* RemoteLayerTreeDisplayRefreshMonitor.mm */,
+                       );
+                       path = Cocoa;
+                       sourceTree = "<group>";
+               };
                2DA944771884E3AB00ED86DB /* ios */ = {
                        isa = PBXGroup;
                        children = (
                BC032D5E10F4372B0058C15A /* WebPage */ = {
                        isa = PBXGroup;
                        children = (
+                               2D29ECCD192F2C2E00984B78 /* Cocoa */,
                                2DA944B41884EA2A00ED86DB /* ios */,
                                BC963D6C113DD19500574BE2 /* mac */,
                                93FC679D12D3CC7400A60610 /* DecoderAdapter.cpp */,
                                2684054418B85A630022C38B /* VisibleContentRectUpdateInfo.h in Headers */,
                                37948404150C350600E52CE9 /* WebRenderLayer.h in Headers */,
                                51E351F6180F5C7500E53BE9 /* WebIDBFactoryBackend.h in Headers */,
+                               2D29ECD0192F2C2E00984B78 /* RemoteLayerTreeDisplayRefreshMonitor.h in Headers */,
                                3760881F150413E900FC82C7 /* WebRenderObject.h in Headers */,
                                51217465164C21370037A5C1 /* WebResourceBuffer.h in Headers */,
                                33367630130C9998006C9DE2 /* WebResourceCacheManager.h in Headers */,
                                1AE117F611DBB30900981615 /* ProcessLauncher.cpp in Sources */,
                                BC111B1D112F5FE600337BAB /* ProcessLauncherMac.mm in Sources */,
                                1AB16AE9164B3A8800290D62 /* RemoteLayerTreeContext.mm in Sources */,
+                               2D29ECD1192F2C2E00984B78 /* RemoteLayerTreeDisplayRefreshMonitor.mm in Sources */,
                                1AAB0379185A7C6A00EDF501 /* MessageSender.cpp in Sources */,
                                1AB16ADD1648598400290D62 /* RemoteLayerTreeDrawingArea.mm in Sources */,
                                1AB16AE11648656D00290D62 /* RemoteLayerTreeDrawingAreaProxy.mm in Sources */,
index 1bef85aff93cd6fbf859c77c4f85bdaf6d20503b..67d21427ca8fba7f2e78b06dbb963bd572b215e4 100644 (file)
@@ -780,6 +780,13 @@ GraphicsLayerFactory* WebChromeClient::graphicsLayerFactory() const
     return m_page->drawingArea()->graphicsLayerFactory();
 }
 
+#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
+PassRefPtr<WebCore::DisplayRefreshMonitor> WebChromeClient::createDisplayRefreshMonitor(PlatformDisplayID displayID) const
+{
+    return m_page->drawingArea()->createDisplayRefreshMonitor(displayID);
+}
+#endif
+
 void WebChromeClient::attachRootGraphicsLayer(Frame*, GraphicsLayer* layer)
 {
     if (layer)
index 13cb82dd30df141a8d2f4532d1bea3161364735c..eb4d1f8f504389b626e9cb6ffaebcc7630de83b5 100644 (file)
@@ -204,6 +204,10 @@ private:
     virtual void scheduleCompositingLayerFlush() override;
     virtual WebCore::GraphicsLayer* documentOverlayLayerForFrame(WebCore::Frame&) override;
 
+#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
+    virtual PassRefPtr<WebCore::DisplayRefreshMonitor> createDisplayRefreshMonitor(PlatformDisplayID) const override;
+#endif
+
     virtual CompositingTriggerFlags allowedCompositingTriggers() const
     {
         return static_cast<CompositingTriggerFlags>(
diff --git a/Source/WebKit2/WebProcess/WebPage/Cocoa/RemoteLayerTreeDisplayRefreshMonitor.h b/Source/WebKit2/WebProcess/WebPage/Cocoa/RemoteLayerTreeDisplayRefreshMonitor.h
new file mode 100644 (file)
index 0000000..a86e7b2
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2014 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef RemoteLayerTreeDisplayRefreshMonitor_h
+#define RemoteLayerTreeDisplayRefreshMonitor_h
+
+#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
+
+#include "RemoteLayerTreeDrawingArea.h"
+#include <WebCore/DisplayRefreshMonitor.h>
+
+namespace WebKit {
+
+class RemoteLayerTreeDisplayRefreshMonitor : public WebCore::DisplayRefreshMonitor {
+public:
+    static PassRefPtr<RemoteLayerTreeDisplayRefreshMonitor> create(PlatformDisplayID displayID, RemoteLayerTreeDrawingArea& drawingArea)
+    {
+        return adoptRef(new RemoteLayerTreeDisplayRefreshMonitor(displayID, drawingArea));
+    }
+    
+    virtual ~RemoteLayerTreeDisplayRefreshMonitor();
+
+    virtual bool requestRefreshCallback() override;
+
+    void didUpdateLayers();
+
+private:
+    explicit RemoteLayerTreeDisplayRefreshMonitor(PlatformDisplayID, RemoteLayerTreeDrawingArea&);
+
+    RemoteLayerTreeDrawingArea& m_drawingArea;
+};
+
+}
+
+#endif // USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
+
+#endif // RemoteLayerTreeDisplayRefreshMonitor_h
diff --git a/Source/WebKit2/WebProcess/WebPage/Cocoa/RemoteLayerTreeDisplayRefreshMonitor.mm b/Source/WebKit2/WebProcess/WebPage/Cocoa/RemoteLayerTreeDisplayRefreshMonitor.mm
new file mode 100644 (file)
index 0000000..e4c64c4
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2014 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#import "config.h"
+#import "RemoteLayerTreeDisplayRefreshMonitor.h"
+
+#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
+
+#import <wtf/CurrentTime.h>
+
+using namespace WebCore;
+
+namespace WebKit {
+
+RemoteLayerTreeDisplayRefreshMonitor::RemoteLayerTreeDisplayRefreshMonitor(PlatformDisplayID displayID, RemoteLayerTreeDrawingArea& drawingArea)
+    : DisplayRefreshMonitor(displayID)
+    , m_drawingArea(drawingArea)
+{
+}
+
+RemoteLayerTreeDisplayRefreshMonitor::~RemoteLayerTreeDisplayRefreshMonitor()
+{
+    m_drawingArea.willDestroyDisplayRefreshMonitor(this);
+}
+
+bool RemoteLayerTreeDisplayRefreshMonitor::requestRefreshCallback()
+{
+    if (!isActive())
+        return false;
+
+    if (!isScheduled())
+        static_cast<DrawingArea&>(m_drawingArea).scheduleCompositingLayerFlush();
+
+    setIsActive(true);
+    setIsScheduled(true);
+    return true;
+}
+
+void RemoteLayerTreeDisplayRefreshMonitor::didUpdateLayers()
+{
+    setIsScheduled(false);
+
+    if (!isPreviousFrameDone())
+        return;
+
+    setIsPreviousFrameDone(false);
+    setMonotonicAnimationStartTime(monotonicallyIncreasingTime());
+
+    handleDisplayRefreshedNotificationOnMainThread(this);
+}
+
+}
+
+#endif // USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
index 149a995ea28185aa98e161613fab86b5b2f90cb6..898af7139bb605b0503daf7254e635201fae7984 100644 (file)
@@ -25,6 +25,7 @@
 
 #include "config.h"
 #include "DrawingArea.h"
+#include <WebCore/DisplayRefreshMonitor.h>
 #include <WebCore/TransformationMatrix.h>
 #include <wtf/Functional.h>
 
@@ -91,4 +92,11 @@ TransformationMatrix DrawingArea::rootLayerTransform() const
     return TransformationMatrix();
 }
 
+#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
+PassRefPtr<WebCore::DisplayRefreshMonitor> DrawingArea::createDisplayRefreshMonitor(PlatformDisplayID)
+{
+    return nullptr;
+}
+#endif
+
 } // namespace WebKit
index 8267863b3a49cb0736622c7918a8eeeeda54ca0d..8d0dd137ef3ce4b6a7ab0f1be0ace391c115ded4 100644 (file)
@@ -30,6 +30,7 @@
 #include "LayerTreeContext.h"
 #include <WebCore/FloatRect.h>
 #include <WebCore/IntRect.h>
+#include <WebCore/PlatformScreen.h>
 #include <WebCore/ViewState.h>
 #include <functional>
 #include <wtf/Forward.h>
@@ -41,6 +42,7 @@ class MessageDecoder;
 }
 
 namespace WebCore {
+class DisplayRefreshMonitor;
 class FrameView;
 class GraphicsLayer;
 class GraphicsLayerFactory;
@@ -95,10 +97,14 @@ public:
 
     virtual bool shouldUseTiledBackingForFrameView(const WebCore::FrameView*) { return false; }
 
-    virtual WebCore::GraphicsLayerFactory* graphicsLayerFactory() { return 0; }
+    virtual WebCore::GraphicsLayerFactory* graphicsLayerFactory() { return nullptr; }
     virtual void setRootCompositingLayer(WebCore::GraphicsLayer*) = 0;
     virtual void scheduleCompositingLayerFlush() = 0;
 
+#if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
+    virtual PassRefPtr<WebCore::DisplayRefreshMonitor> createDisplayRefreshMonitor(PlatformDisplayID);
+#endif
+
     virtual WebCore::TransformationMatrix rootLayerTransform() const;
     virtual void setRootLayerTransform(const WebCore::TransformationMatrix&) { }
 
index 9ac14ddfa27339bcac1620733bffa30b21313a2b..712b27e01afab486075934c71e97a713d810d428 100644 (file)
@@ -45,8 +45,10 @@ class MessageEncoder;
 namespace WebKit {
 
 class RemoteLayerTreeContext;
+class RemoteLayerTreeDisplayRefreshMonitor;
 
 class RemoteLayerTreeDrawingArea : public DrawingArea, public WebCore::GraphicsLayerClient {
+    friend class RemoteLayerTreeDisplayRefreshMonitor;
 public:
     RemoteLayerTreeDrawingArea(WebPage*, const WebPageCreationParameters&);
     virtual ~RemoteLayerTreeDrawingArea();
@@ -62,6 +64,9 @@ private:
     virtual void setRootCompositingLayer(WebCore::GraphicsLayer*) override;
     virtual void scheduleCompositingLayerFlush() override;
 
+    virtual PassRefPtr<WebCore::DisplayRefreshMonitor> createDisplayRefreshMonitor(PlatformDisplayID) override;
+    void willDestroyDisplayRefreshMonitor(WebCore::DisplayRefreshMonitor*);
+
     virtual bool shouldUseTiledBackingForFrameView(const WebCore::FrameView*) override;
 
     virtual void updatePreferences(const WebPreferencesStore&) override;
@@ -136,6 +141,8 @@ private:
 
     dispatch_queue_t m_commitQueue;
     RefPtr<BackingStoreFlusher> m_pendingBackingStoreFlusher;
+
+    HashSet<RemoteLayerTreeDisplayRefreshMonitor*> m_displayRefreshMonitors;
 };
 
 DRAWING_AREA_TYPE_CASTS(RemoteLayerTreeDrawingArea, type() == DrawingAreaTypeRemoteLayerTree);
index 9f5f7c1a1d12169f629a65e9c80e4163e586bc09..6c0169921fb70124687325491014c4e366d46a55 100644 (file)
@@ -31,6 +31,7 @@
 #import "PlatformCALayerRemote.h"
 #import "RemoteLayerBackingStoreCollection.h"
 #import "RemoteLayerTreeContext.h"
+#import "RemoteLayerTreeDisplayRefreshMonitor.h"
 #import "RemoteLayerTreeDrawingAreaProxyMessages.h"
 #import "RemoteScrollingCoordinator.h"
 #import "RemoteScrollingCoordinatorTransaction.h"
@@ -91,6 +92,18 @@ GraphicsLayerFactory* RemoteLayerTreeDrawingArea::graphicsLayerFactory()
     return m_remoteLayerTreeContext.get();
 }
 
+PassRefPtr<DisplayRefreshMonitor> RemoteLayerTreeDrawingArea::createDisplayRefreshMonitor(PlatformDisplayID displayID)
+{
+    RefPtr<RemoteLayerTreeDisplayRefreshMonitor> monitor = RemoteLayerTreeDisplayRefreshMonitor::create(displayID, *this);
+    m_displayRefreshMonitors.add(monitor.get());
+    return monitor.release();
+}
+
+void RemoteLayerTreeDrawingArea::willDestroyDisplayRefreshMonitor(DisplayRefreshMonitor* monitor)
+{
+    m_displayRefreshMonitors.remove(static_cast<RemoteLayerTreeDisplayRefreshMonitor*>(monitor));
+}
+
 void RemoteLayerTreeDrawingArea::setRootCompositingLayer(GraphicsLayer* rootLayer)
 {
     Vector<GraphicsLayer *> children;
@@ -309,6 +322,9 @@ void RemoteLayerTreeDrawingArea::didUpdate()
     // This empty transaction serves to trigger CA's garbage collection of IOSurfaces. See <rdar://problem/16110687>
     [CATransaction begin];
     [CATransaction commit];
+
+    for (auto& monitor : m_displayRefreshMonitors)
+        monitor->didUpdateLayers();
 }
 
 void RemoteLayerTreeDrawingArea::mainFrameContentSizeChanged(const IntSize& contentsSize)