REGRESSION (r206247): Painting milestones can be delayed until the next layer flush
authormitz@apple.com <mitz@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 3 Nov 2016 16:19:48 +0000 (16:19 +0000)
committermitz@apple.com <mitz@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 3 Nov 2016 16:19:48 +0000 (16:19 +0000)
https://bugs.webkit.org/show_bug.cgi?id=164340
<rdar://problem/29074344>

Reviewed by Tim Horton.

Source/WebCore:

To give WebKit a chance to deliver the painting milestones to its client after the commit,
we must tell it about them before or during the commit. To that end, we should not defer
the call to firePaintRelatedMilestonesIfNeeded until after the commit.

* rendering/RenderLayerCompositor.cpp:
(WebCore::RenderLayerCompositor::RenderLayerCompositor): Removed
  m_paintRelatedMilestonesTimer initializer.
(WebCore::RenderLayerCompositor::didPaintBacking): Call
  FrameView::firePaintRelatedMilestonesIfNeeded directly from here.
(WebCore::RenderLayerCompositor::paintRelatedMilestonesTimerFired): Deleted.
* rendering/RenderLayerCompositor.h:

Source/WebKit2:

* WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.h: Declared new helper function.
* WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.mm:
(WebKit::TiledCoreAnimationDrawingArea::sendPendingNewlyReachedLayoutMilestones): Helper
  function that sends the message to the UI process and resets
  m_pendingNewlyReachedLayoutMilestones.
(WebKit::TiledCoreAnimationDrawingArea::flushLayers): Wait until after the commit to get the
  pending milestones and send them to the UI process. This way we don’t miss milestones that
  fire during the commit.

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

Source/WebCore/ChangeLog
Source/WebCore/rendering/RenderLayerCompositor.cpp
Source/WebCore/rendering/RenderLayerCompositor.h
Source/WebKit2/ChangeLog
Source/WebKit2/WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.h
Source/WebKit2/WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.mm

index e645f19..d786e2e 100644 (file)
@@ -1,3 +1,23 @@
+2016-11-03  Dan Bernstein  <mitz@apple.com>
+
+        REGRESSION (r206247): Painting milestones can be delayed until the next layer flush
+        https://bugs.webkit.org/show_bug.cgi?id=164340
+        <rdar://problem/29074344>
+
+        Reviewed by Tim Horton.
+
+        To give WebKit a chance to deliver the painting milestones to its client after the commit,
+        we must tell it about them before or during the commit. To that end, we should not defer
+        the call to firePaintRelatedMilestonesIfNeeded until after the commit.
+
+        * rendering/RenderLayerCompositor.cpp:
+        (WebCore::RenderLayerCompositor::RenderLayerCompositor): Removed
+          m_paintRelatedMilestonesTimer initializer.
+        (WebCore::RenderLayerCompositor::didPaintBacking): Call
+          FrameView::firePaintRelatedMilestonesIfNeeded directly from here.
+        (WebCore::RenderLayerCompositor::paintRelatedMilestonesTimerFired): Deleted.
+        * rendering/RenderLayerCompositor.h:
+
 2016-11-03  Antti Koivisto  <antti@apple.com>
 
         imported/mozilla/svg/paint-order-01.svg and imported/mozilla/svg/paint-order-02.svg are flaky failures
index 3333ece..8b4fe33 100644 (file)
@@ -274,7 +274,6 @@ static inline bool compositingLogEnabled()
 RenderLayerCompositor::RenderLayerCompositor(RenderView& renderView)
     : m_renderView(renderView)
     , m_updateCompositingLayersTimer(*this, &RenderLayerCompositor::updateCompositingLayersTimerFired)
-    , m_paintRelatedMilestonesTimer(*this, &RenderLayerCompositor::paintRelatedMilestonesTimerFired)
     , m_layerFlushTimer(*this, &RenderLayerCompositor::layerFlushTimerFired)
 {
 }
@@ -569,8 +568,8 @@ void RenderLayerCompositor::didPaintBacking(RenderLayerBacking*)
 {
     FrameView& frameView = m_renderView.frameView();
     frameView.setLastPaintTime(monotonicallyIncreasingTime());
-    if (frameView.milestonesPendingPaint() && !m_paintRelatedMilestonesTimer.isActive())
-        m_paintRelatedMilestonesTimer.startOneShot(0);
+    if (frameView.milestonesPendingPaint())
+        frameView.firePaintRelatedMilestonesIfNeeded();
 }
 
 void RenderLayerCompositor::didChangeVisibleRect()
@@ -4200,20 +4199,6 @@ void RenderLayerCompositor::layerFlushTimerFired()
     scheduleLayerFlushNow();
 }
 
-void RenderLayerCompositor::paintRelatedMilestonesTimerFired()
-{
-    Frame& frame = m_renderView.frameView().frame();
-    Page* page = frame.page();
-    if (!page)
-        return;
-
-    // If the layer tree is frozen, we'll paint when it's unfrozen and schedule the timer again.
-    if (page->chrome().client().layerTreeStateIsFrozen())
-        return;
-
-    m_renderView.frameView().firePaintRelatedMilestonesIfNeeded();
-}
-
 #if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
 RefPtr<DisplayRefreshMonitor> RenderLayerCompositor::createDisplayRefreshMonitor(PlatformDisplayID displayID) const
 {
index 490fcfc..2ef49da 100644 (file)
@@ -475,8 +475,6 @@ private:
     void startLayerFlushTimerIfNeeded();
     void layerFlushTimerFired();
 
-    void paintRelatedMilestonesTimerFired();
-
 #if !LOG_DISABLED
     const char* logReasonsForCompositing(const RenderLayer&);
     void logLayerInfo(const RenderLayer&, int depth);
@@ -548,7 +546,6 @@ private:
 
     std::unique_ptr<GraphicsLayerUpdater> m_layerUpdater; // Updates tiled layer visible area periodically while animations are running.
 
-    Timer m_paintRelatedMilestonesTimer;
     Timer m_layerFlushTimer;
 
     bool m_layerFlushThrottlingEnabled { false };
index 55b71c6..d17dcee 100644 (file)
@@ -1,3 +1,20 @@
+2016-11-03  Dan Bernstein  <mitz@apple.com>
+
+        REGRESSION (r206247): Painting milestones can be delayed until the next layer flush
+        https://bugs.webkit.org/show_bug.cgi?id=164340
+        <rdar://problem/29074344>
+
+        Reviewed by Tim Horton.
+
+        * WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.h: Declared new helper function.
+        * WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.mm:
+        (WebKit::TiledCoreAnimationDrawingArea::sendPendingNewlyReachedLayoutMilestones): Helper
+          function that sends the message to the UI process and resets
+          m_pendingNewlyReachedLayoutMilestones.
+        (WebKit::TiledCoreAnimationDrawingArea::flushLayers): Wait until after the commit to get the
+          pending milestones and send them to the UI process. This way we don’t miss milestones that
+          fire during the commit.
+
 2016-11-02  David Kilzer  <ddkilzer@apple.com>
 
         Bug 164333: Add logging for "WebKit encountered an internal error" messages due to Network process crashes
index aa220fc..7a6b0e2 100644 (file)
@@ -122,6 +122,8 @@ private:
     void updateScrolledExposedRect();
     void scaleViewToFitDocumentIfNeeded();
 
+    void sendPendingNewlyReachedLayoutMilestones();
+
     bool m_layerTreeStateIsFrozen;
     WebCore::LayerFlushScheduler m_layerFlushScheduler;
 
index c838581..23ee56d 100644 (file)
@@ -394,6 +394,15 @@ void TiledCoreAnimationDrawingArea::dispatchAfterEnsuringUpdatedScrollPosition(s
 #endif
 }
 
+void TiledCoreAnimationDrawingArea::sendPendingNewlyReachedLayoutMilestones()
+{
+    if (!m_pendingNewlyReachedLayoutMilestones)
+        return;
+
+    m_webPage.send(Messages::WebPageProxy::DidReachLayoutMilestone(m_pendingNewlyReachedLayoutMilestones));
+    m_pendingNewlyReachedLayoutMilestones = 0;
+}
+
 bool TiledCoreAnimationDrawingArea::flushLayers()
 {
     ASSERT(!m_layerTreeStateIsFrozen);
@@ -418,14 +427,21 @@ bool TiledCoreAnimationDrawingArea::flushLayers()
         if (m_viewOverlayRootLayer)
             m_viewOverlayRootLayer->flushCompositingState(visibleRect, m_webPage.mainFrameView()->viewportIsStable());
 
-#if TARGET_OS_IPHONE || (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101100)
         RefPtr<WebPage> retainedPage = &m_webPage;
+#if TARGET_OS_IPHONE || (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101100)
         [CATransaction addCommitHandler:[retainedPage] {
             if (Page* corePage = retainedPage->corePage()) {
                 if (Frame* coreFrame = retainedPage->mainFrame())
                     corePage->inspectorController().didComposite(*coreFrame);
             }
+            if (auto drawingArea = static_cast<TiledCoreAnimationDrawingArea*>(retainedPage->drawingArea()))
+                drawingArea->sendPendingNewlyReachedLayoutMilestones();
         } forPhase:kCATransactionPhasePostCommit];
+#else
+        dispatch_async(dispatch_get_main_queue(), [retainedPage] {
+            if (auto drawingArea = static_cast<TiledCoreAnimationDrawingArea*>(retainedPage->drawingArea()))
+                drawingArea->sendPendingNewlyReachedLayoutMilestones();
+        });
 #endif
 
         bool returnValue = m_webPage.mainFrameView()->flushCompositingStateIncludingSubframes();
@@ -439,10 +455,6 @@ bool TiledCoreAnimationDrawingArea::flushLayers()
         if (m_transientZoomScale != 1)
             applyTransientZoomToLayers(m_transientZoomScale, m_transientZoomOrigin);
 
-        if (m_pendingNewlyReachedLayoutMilestones)
-            m_webPage.send(Messages::WebPageProxy::DidReachLayoutMilestone(m_pendingNewlyReachedLayoutMilestones));
-        m_pendingNewlyReachedLayoutMilestones = 0;
-
         return returnValue;
     }
 }