Bug 1283947 - Clear pending transactions when ClientLayerManager is assigning to a different refresh driver. r=mattwoodrow
☠☠ backed out by cc5a5a7e5331 ☠ ☠
authorSamael Wang <freesamael@gmail.com>
Mon, 20 Feb 2017 16:25:09 +0800
changeset 390555 3a8c78a6146fa9fb3fa9f73d0547b6520e26a470
parent 390554 711456564e1e73cc1e5c101e55a8f28bfb43a108
child 390556 96b7a3ed364bab98ace2bdc9a0d4a57ee55d6121
push id7198
push userjlorenzo@mozilla.com
push dateTue, 18 Apr 2017 12:07:49 +0000
treeherdermozilla-beta@d57aa49c3948 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmattwoodrow
bugs1283947
milestone54.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 1283947 - Clear pending transactions when ClientLayerManager is assigning to a different refresh driver. r=mattwoodrow
gfx/layers/TransactionIdAllocator.h
gfx/layers/client/ClientLayerManager.cpp
gfx/layers/client/ClientLayerManager.h
layout/base/nsRefreshDriver.cpp
layout/base/nsRefreshDriver.h
--- a/gfx/layers/TransactionIdAllocator.h
+++ b/gfx/layers/TransactionIdAllocator.h
@@ -49,16 +49,25 @@ public:
    * Revoke a transaction id that isn't needed to track
    * completion of asynchronous work. This is similar
    * to NotifyTransactionCompleted except avoids
    * return ordering issues.
    */
   virtual void RevokeTransactionId(uint64_t aTransactionId) = 0;
 
   /**
+   * Stop waiting for pending transactions, if any.
+   *
+   * This is used when ClientLayerManager is assigning to another refresh
+   * driver, and the current refresh driver may never receive transaction
+   * completed notifications.
+   */
+  virtual void ClearPendingTransactions() = 0;
+
+  /**
    * Get the start time of the current refresh tick.
    */
   virtual mozilla::TimeStamp GetTransactionStart() = 0;
 };
 
 } // namespace layers
 } // namespace mozilla
 
--- a/gfx/layers/client/ClientLayerManager.cpp
+++ b/gfx/layers/client/ClientLayerManager.cpp
@@ -506,16 +506,29 @@ ClientLayerManager::GetCompositorSideAPZ
 {
   if (mForwarder->HasShadowManager()) {
     if (!mForwarder->GetShadowManager()->SendGetAPZTestData(aData)) {
       NS_WARNING("Call to PLayerTransactionChild::SendGetAPZTestData() failed");
     }
   }
 }
 
+void
+ClientLayerManager::SetTransactionIdAllocator(TransactionIdAllocator* aAllocator)
+{
+  // When changing the refresh driver, the previous refresh driver may never
+  // receive updates of pending transactions it's waiting for. So clear the
+  // waiting state before assigning another refresh driver.
+  if (mTransactionIdAllocator) {
+    mTransactionIdAllocator->ClearPendingTransactions();
+  }
+
+  mTransactionIdAllocator = aAllocator;
+}
+
 float
 ClientLayerManager::RequestProperty(const nsAString& aProperty)
 {
   if (mForwarder->HasShadowManager()) {
     float value;
     if (!mForwarder->GetShadowManager()->SendRequestProperty(nsString(aProperty), &value)) {
       NS_WARNING("Call to PLayerTransactionChild::SendGetAPZTestData() failed");
     }
--- a/gfx/layers/client/ClientLayerManager.h
+++ b/gfx/layers/client/ClientLayerManager.h
@@ -215,20 +215,17 @@ public:
   // LogTestData...() functions.
   const APZTestData& GetAPZTestData() const {
     return mApzTestData;
   }
 
   // Get a copy of the compositor-side APZ test data for our layers ID.
   void GetCompositorSideAPZTestData(APZTestData* aData) const;
 
-  virtual void SetTransactionIdAllocator(TransactionIdAllocator* aAllocator) override
-  {
-     mTransactionIdAllocator = aAllocator;
-  }
+  virtual void SetTransactionIdAllocator(TransactionIdAllocator* aAllocator) override;
 
   virtual uint64_t GetLastTransactionId() override { return mLatestTransactionId; }
 
   float RequestProperty(const nsAString& aProperty) override;
 
   bool AsyncPanZoomEnabled() const override;
 
   void SetNextPaintSyncId(int32_t aSyncId);
--- a/layout/base/nsRefreshDriver.cpp
+++ b/layout/base/nsRefreshDriver.cpp
@@ -2180,16 +2180,23 @@ nsRefreshDriver::RevokeTransactionId(uin
   if (mPendingTransaction == mCompletedTransaction + 2 &&
       mWaitingForTransaction) {
     MOZ_ASSERT(!mSkippedPaints, "How did we skip a paint when we're in the middle of one?");
     FinishedWaitingForTransaction();
   }
   mPendingTransaction--;
 }
 
+void
+nsRefreshDriver::ClearPendingTransactions()
+{
+  mCompletedTransaction = mPendingTransaction;
+  mWaitingForTransaction = false;
+}
+
 mozilla::TimeStamp
 nsRefreshDriver::GetTransactionStart()
 {
   return mTickStart;
 }
 
 void
 nsRefreshDriver::NotifyTransactionCompleted(uint64_t aTransactionId)
--- a/layout/base/nsRefreshDriver.h
+++ b/layout/base/nsRefreshDriver.h
@@ -304,16 +304,17 @@ public:
    */
   static bool GetJankLevels(mozilla::Vector<uint64_t>& aJank);
 
   // mozilla::layers::TransactionIdAllocator
   uint64_t GetTransactionId() override;
   uint64_t LastTransactionId() const override;
   void NotifyTransactionCompleted(uint64_t aTransactionId) override;
   void RevokeTransactionId(uint64_t aTransactionId) override;
+  void ClearPendingTransactions() override;
   mozilla::TimeStamp GetTransactionStart() override;
 
   bool IsWaitingForPaint(mozilla::TimeStamp aTime);
 
   // nsARefreshObserver
   NS_IMETHOD_(MozExternalRefCountType) AddRef(void) override { return TransactionIdAllocator::AddRef(); }
   NS_IMETHOD_(MozExternalRefCountType) Release(void) override { return TransactionIdAllocator::Release(); }
   virtual void WillRefresh(mozilla::TimeStamp aTime) override;