Bug 1074401 - Ensure that the repaint request is always dispatched from the APZ on the main thread. r=botond
authorKartikaya Gupta <kgupta@mozilla.com>
Fri, 03 Oct 2014 13:39:37 -0400
changeset 231984 0dbe7877aaef0932c61140c3dadae32e37b45f18
parent 231983 d84db3f0c1abb252ee23e922c1d6b17515bc928d
child 231985 e057f4f45d357d1ebfdc69ed681f59f831211e3c
push id4187
push userbhearsum@mozilla.com
push dateFri, 28 Nov 2014 15:29:12 +0000
treeherdermozilla-beta@f23cc6a30c11 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbotond
bugs1074401
milestone35.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1074401 - Ensure that the repaint request is always dispatched from the APZ on the main thread. r=botond
gfx/layers/apz/public/GeckoContentController.h
gfx/layers/apz/src/AsyncPanZoomController.cpp
layout/ipc/RenderFrameParent.cpp
widget/android/APZCCallbackHandler.cpp
widget/cocoa/nsChildView.mm
widget/gonk/ParentProcessController.cpp
widget/windows/winrt/APZController.cpp
--- a/gfx/layers/apz/public/GeckoContentController.h
+++ b/gfx/layers/apz/public/GeckoContentController.h
@@ -20,16 +20,17 @@ namespace layers {
 class GeckoContentController
 {
 public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GeckoContentController)
 
   /**
    * Requests a paint of the given FrameMetrics |aFrameMetrics| from Gecko.
    * Implementations per-platform are responsible for actually handling this.
+   * This method will always be called on the Gecko main thread.
    */
   virtual void RequestContentRepaint(const FrameMetrics& aFrameMetrics) = 0;
 
   /**
    * Acknowledges the recipt of a scroll offset update for the scrollable
    * frame with the given scroll id. This is used to maintain consistency
    * between APZ and other sources of scroll changes.
    */
--- a/gfx/layers/apz/src/AsyncPanZoomController.cpp
+++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp
@@ -2398,17 +2398,22 @@ GetDisplayPortRect(const FrameMetrics& a
 
 void
 AsyncPanZoomController::DispatchRepaintRequest(const FrameMetrics& aFrameMetrics) {
   nsRefPtr<GeckoContentController> controller = GetGeckoContentController();
   if (controller) {
     APZC_LOG_FM(aFrameMetrics, "%p requesting content repaint", this);
     LogRendertraceRect(GetGuid(), "requested displayport", "yellow", GetDisplayPortRect(aFrameMetrics));
 
-    controller->RequestContentRepaint(aFrameMetrics);
+    if (NS_IsMainThread()) {
+      controller->RequestContentRepaint(aFrameMetrics);
+    } else {
+      NS_DispatchToMainThread(NS_NewRunnableMethodWithArg<FrameMetrics>(
+        controller, &GeckoContentController::RequestContentRepaint, aFrameMetrics));
+    }
     mLastDispatchedPaintMetrics = aFrameMetrics;
   }
 }
 
 void
 AsyncPanZoomController::FireAsyncScrollOnTimeout()
 {
   if (mCurrentAsyncScrollOffset != mLastAsyncScrollOffset) {
--- a/layout/ipc/RenderFrameParent.cpp
+++ b/layout/ipc/RenderFrameParent.cpp
@@ -81,22 +81,21 @@ public:
   explicit RemoteContentController(RenderFrameParent* aRenderFrame)
     : mUILoop(MessageLoop::current())
     , mRenderFrame(aRenderFrame)
     , mHaveZoomConstraints(false)
   { }
 
   virtual void RequestContentRepaint(const FrameMetrics& aFrameMetrics) MOZ_OVERRIDE
   {
-    // We always need to post requests into the "UI thread" otherwise the
-    // requests may get processed out of order.
-    mUILoop->PostTask(
-      FROM_HERE,
-      NewRunnableMethod(this, &RemoteContentController::DoRequestContentRepaint,
-                        aFrameMetrics));
+    MOZ_ASSERT(NS_IsMainThread());
+    if (mRenderFrame) {
+      TabParent* browser = static_cast<TabParent*>(mRenderFrame->Manager());
+      browser->UpdateFrame(aFrameMetrics);
+    }
   }
 
   virtual void AcknowledgeScrollUpdate(const FrameMetrics::ViewID& aScrollId,
                                        const uint32_t& aScrollGeneration) MOZ_OVERRIDE
   {
     if (MessageLoop::current() != mUILoop) {
       // We have to send this message from the "UI thread" (main
       // thread).
@@ -256,24 +255,16 @@ public:
     mZoomConstraints = aConstraints;
   }
 
   void SetTouchSensitiveRegion(const nsRegion& aRegion)
   {
     mTouchSensitiveRegion = aRegion;
   }
 private:
-  void DoRequestContentRepaint(const FrameMetrics& aFrameMetrics)
-  {
-    if (mRenderFrame) {
-      TabParent* browser = static_cast<TabParent*>(mRenderFrame->Manager());
-      browser->UpdateFrame(aFrameMetrics);
-    }
-  }
-
   MessageLoop* mUILoop;
   RenderFrameParent* mRenderFrame;
 
   bool mHaveZoomConstraints;
   ZoomConstraints mZoomConstraints;
   nsRegion mTouchSensitiveRegion;
 };
 
--- a/widget/android/APZCCallbackHandler.cpp
+++ b/widget/android/APZCCallbackHandler.cpp
@@ -77,22 +77,16 @@ APZCCallbackHandler::GetDOMWindowUtils()
     }
     nsCOMPtr<nsIDOMWindowUtils> utils = do_GetInterface(window);
     return utils.get();
 }
 
 void
 APZCCallbackHandler::RequestContentRepaint(const FrameMetrics& aFrameMetrics)
 {
-    if (!NS_IsMainThread()) {
-        NS_DispatchToMainThread(NS_NewRunnableMethodWithArg<FrameMetrics>(
-            this, &APZCCallbackHandler::RequestContentRepaint, aFrameMetrics));
-        return;
-    }
-
     MOZ_ASSERT(NS_IsMainThread());
     MOZ_ASSERT(aFrameMetrics.GetScrollId() != FrameMetrics::NULL_SCROLL_ID);
 
     if (aFrameMetrics.GetIsRoot()) {
         nsIDOMWindowUtils* utils = GetDOMWindowUtils();
         if (utils && APZCCallbackHelper::HasValidPresShellId(utils, aFrameMetrics)) {
             FrameMetrics metrics = aFrameMetrics;
             APZCCallbackHelper::UpdateRootFrame(utils, metrics);
--- a/widget/cocoa/nsChildView.mm
+++ b/widget/cocoa/nsChildView.mm
@@ -397,48 +397,26 @@ protected:
   GLuint mQuadVBO;
 };
 
 class APZCTMController : public mozilla::layers::GeckoContentController
 {
   typedef mozilla::layers::FrameMetrics FrameMetrics;
   typedef mozilla::layers::ScrollableLayerGuid ScrollableLayerGuid;
 
-  class RequestContentRepaintEvent : public nsRunnable
-  {
-  public:
-    explicit RequestContentRepaintEvent(const FrameMetrics& aFrameMetrics)
-      : mFrameMetrics(aFrameMetrics)
-    {
-    }
-
-    NS_IMETHOD Run()
-    {
-      MOZ_ASSERT(NS_IsMainThread());
-
-      nsCOMPtr<nsIContent> targetContent = nsLayoutUtils::FindContentFor(mFrameMetrics.GetScrollId());
-      if (targetContent) {
-        APZCCallbackHelper::UpdateSubFrame(targetContent, mFrameMetrics);
-      }
-
-      return NS_OK;
-    }
-  protected:
-    FrameMetrics mFrameMetrics;
-  };
-
 public:
   // GeckoContentController interface
   virtual void RequestContentRepaint(const FrameMetrics& aFrameMetrics)
   {
-    nsCOMPtr<nsIRunnable> r1 = new RequestContentRepaintEvent(aFrameMetrics);
-    if (!NS_IsMainThread()) {
-      NS_DispatchToMainThread(r1);
-    } else {
-      r1->Run();
+    MOZ_ASSERT(NS_IsMainThread());
+
+    nsCOMPtr<nsIContent> targetContent = nsLayoutUtils::FindContentFor(aFrameMetrics.GetScrollId());
+    if (targetContent) {
+      FrameMetrics metrics = aFrameMetrics;
+      APZCCallbackHelper::UpdateSubFrame(targetContent, metrics);
     }
   }
 
   virtual void PostDelayedTask(Task* aTask, int aDelayMs) MOZ_OVERRIDE
   {
     MessageLoop::current()->PostDelayedTask(FROM_HERE, aTask, aDelayMs);
   }
 
--- a/widget/gonk/ParentProcessController.cpp
+++ b/widget/gonk/ParentProcessController.cpp
@@ -7,51 +7,29 @@
 #include "nsIContent.h"
 #include "nsLayoutUtils.h"
 #include "mozilla/layers/APZCCallbackHelper.h"
 #include "base/message_loop.h"
 
 namespace mozilla {
 namespace widget {
 
-class RequestContentRepaintEvent : public nsRunnable
-{
-    typedef mozilla::layers::FrameMetrics FrameMetrics;
-
-public:
-    RequestContentRepaintEvent(const FrameMetrics& aFrameMetrics)
-        : mFrameMetrics(aFrameMetrics)
-    {
-    }
-
-    NS_IMETHOD Run() {
-        MOZ_ASSERT(NS_IsMainThread());
-        nsCOMPtr<nsIContent> content = nsLayoutUtils::FindContentFor(mFrameMetrics.GetScrollId());
-        if (content) {
-            mozilla::layers::APZCCallbackHelper::UpdateSubFrame(content, mFrameMetrics);
-        }
-        return NS_OK;
-    }
-
-protected:
-    FrameMetrics mFrameMetrics;
-};
-
 void
 ParentProcessController::RequestContentRepaint(const FrameMetrics& aFrameMetrics)
 {
+    MOZ_ASSERT(NS_IsMainThread());
+
     if (aFrameMetrics.GetScrollId() == FrameMetrics::NULL_SCROLL_ID) {
         return;
     }
 
-    nsCOMPtr<nsIRunnable> r = new RequestContentRepaintEvent(aFrameMetrics);
-    if (!NS_IsMainThread()) {
-        NS_DispatchToMainThread(r);
-    } else {
-        r->Run();
+    nsCOMPtr<nsIContent> content = nsLayoutUtils::FindContentFor(aFrameMetrics.GetScrollId());
+    if (content) {
+        FrameMetrics metrics = aFrameMetrics;
+        mozilla::layers::APZCCallbackHelper::UpdateSubFrame(content, metrics);
     }
 }
 
 void
 ParentProcessController::AcknowledgeScrollUpdate(const FrameMetrics::ViewID& aScrollId,
                                                  const uint32_t& aScrollGeneration)
 {
     mozilla::layers::APZCCallbackHelper::AcknowledgeScrollUpdate(aScrollId, aScrollGeneration);
--- a/widget/windows/winrt/APZController.cpp
+++ b/widget/windows/winrt/APZController.cpp
@@ -74,80 +74,16 @@ GetDOMTargets(uint64_t aScrollId,
   // a document, vs. an element within a document.
   if (aSubDocument->GetRootElement() == domElement && IsTab(aSubDocument)) {
     aTargetContent = nullptr;
   }
 
   return true;
 }
 
-class RequestContentRepaintEvent : public nsRunnable
-{
-  typedef mozilla::layers::FrameMetrics FrameMetrics;
-
-public:
-  RequestContentRepaintEvent(const FrameMetrics& aFrameMetrics) :
-    mFrameMetrics(aFrameMetrics)
-  {
-  }
-
-  NS_IMETHOD Run() {
-    // This must be on the gecko thread since we access the dom
-    MOZ_ASSERT(NS_IsMainThread());
-
-#ifdef DEBUG_CONTROLLER
-    WinUtils::Log("APZController: mScrollOffset: %f %f", mFrameMetrics.mScrollOffset.x,
-      mFrameMetrics.mScrollOffset.y);
-#endif
-
-    nsCOMPtr<nsIDocument> subDocument;
-    nsCOMPtr<nsIContent> targetContent;
-    if (!GetDOMTargets(mFrameMetrics.GetScrollId(),
-                       subDocument, targetContent)) {
-      return NS_OK;
-    }
-
-    // If we're dealing with a sub frame or content editable element,
-    // call UpdateSubFrame.
-    if (targetContent) {
-#ifdef DEBUG_CONTROLLER
-      WinUtils::Log("APZController: detected subframe or content editable");
-#endif
-      mozilla::layers::APZCCallbackHelper::UpdateSubFrame(targetContent, mFrameMetrics);
-      return NS_OK;
-    }
-
-#ifdef DEBUG_CONTROLLER
-    WinUtils::Log("APZController: detected tab");
-#endif
-
-    // We're dealing with a tab, call UpdateRootFrame.
-    nsCOMPtr<nsIDOMWindowUtils> utils;
-    nsCOMPtr<nsIDOMWindow> window = subDocument->GetDefaultView();
-    if (window) {
-      utils = do_GetInterface(window);
-      if (utils) {
-        mozilla::layers::APZCCallbackHelper::UpdateRootFrame(utils, mFrameMetrics);
-
-#ifdef DEBUG_CONTROLLER
-        WinUtils::Log("APZController: %I64d mDisplayPortMargins: %0.2f %0.2f %0.2f %0.2f",
-          mFrameMetrics.GetScrollId(),
-          mFrameMetrics.GetDisplayPortMargins().left,
-          mFrameMetrics.GetDisplayPortMargins().top,
-          mFrameMetrics.GetDisplayPortMargins().right,
-          mFrameMetrics.GetDisplayPortMargins().bottom);
-#endif
-      }
-    }
-    return NS_OK;
-  }
-protected:
-  FrameMetrics mFrameMetrics;
-};
-
 void
 APZController::SetPendingResponseFlusher(APZPendingResponseFlusher* aFlusher)
 {
   mFlusher = aFlusher;
 }
 
 void
 APZController::ContentReceivedTouch(const ScrollableLayerGuid& aGuid, bool aPreventDefault)
@@ -193,21 +129,65 @@ APZController::ReceiveInputEvent(WidgetI
 // the scrollable frame the apzc is managing.
 void
 APZController::RequestContentRepaint(const FrameMetrics& aFrameMetrics)
 {
 #ifdef DEBUG_CONTROLLER
   WinUtils::Log("APZController::RequestContentRepaint scrollid=%I64d",
     aFrameMetrics.GetScrollId());
 #endif
-  nsCOMPtr<nsIRunnable> r1 = new RequestContentRepaintEvent(aFrameMetrics);
-  if (!NS_IsMainThread()) {
-    NS_DispatchToMainThread(r1);
-  } else {
-    r1->Run();
+
+  // This must be on the gecko thread since we access the dom
+  MOZ_ASSERT(NS_IsMainThread());
+
+#ifdef DEBUG_CONTROLLER
+  WinUtils::Log("APZController: mScrollOffset: %f %f", aFrameMetrics.mScrollOffset.x,
+    aFrameMetrics.mScrollOffset.y);
+#endif
+
+  nsCOMPtr<nsIDocument> subDocument;
+  nsCOMPtr<nsIContent> targetContent;
+  if (!GetDOMTargets(aFrameMetrics.GetScrollId(),
+                     subDocument, targetContent)) {
+    return NS_OK;
+  }
+
+  // If we're dealing with a sub frame or content editable element,
+  // call UpdateSubFrame.
+  if (targetContent) {
+#ifdef DEBUG_CONTROLLER
+    WinUtils::Log("APZController: detected subframe or content editable");
+#endif
+    FrameMetrics metrics = aFrameMetrics;
+    mozilla::layers::APZCCallbackHelper::UpdateSubFrame(targetContent, metrics);
+    return NS_OK;
+  }
+
+#ifdef DEBUG_CONTROLLER
+  WinUtils::Log("APZController: detected tab");
+#endif
+
+  // We're dealing with a tab, call UpdateRootFrame.
+  nsCOMPtr<nsIDOMWindowUtils> utils;
+  nsCOMPtr<nsIDOMWindow> window = subDocument->GetDefaultView();
+  if (window) {
+    utils = do_GetInterface(window);
+    if (utils) {
+      FrameMetrics metrics = aFrameMetrics;
+      mozilla::layers::APZCCallbackHelper::UpdateRootFrame(utils, metrics);
+
+#ifdef DEBUG_CONTROLLER
+      WinUtils::Log("APZController: %I64d mDisplayPortMargins: %0.2f %0.2f %0.2f %0.2f",
+        metrics.GetScrollId(),
+        metrics.GetDisplayPortMargins().left,
+        metrics.GetDisplayPortMargins().top,
+        metrics.GetDisplayPortMargins().right,
+        metrics.GetDisplayPortMargins().bottom);
+#endif
+    }
   }
 }
 
 void
 APZController::AcknowledgeScrollUpdate(const FrameMetrics::ViewID& aScrollId,
                                        const uint32_t& aScrollGeneration)
 {
 #ifdef DEBUG_CONTROLLER