Bug 1260611 - Part 1: Opt-in to waiting for compositor recycling for TextureClientRecycleAllocator. r=sotaro a=ritu
☠☠ backed out by 4f7c3a2567f8 ☠ ☠
authorMatt Woodrow <mwoodrow@mozilla.com>
Fri, 22 Apr 2016 15:39:56 +1200
changeset 333020 4a4cf532f07c9ae9c880f8c1920ef9211d48922a
parent 333019 94c2c4e5400676f5a3493b104debb38f0ba3d77f
child 333021 e5dc1c7fcb08356caa6f5dd7568e52463f1f0459
push id6048
push userkmoir@mozilla.com
push dateMon, 06 Jun 2016 19:02:08 +0000
treeherdermozilla-beta@46d72a56c57d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssotaro, ritu
bugs1260611
milestone48.0a2
Bug 1260611 - Part 1: Opt-in to waiting for compositor recycling for TextureClientRecycleAllocator. r=sotaro a=ritu
gfx/layers/client/TextureClient.cpp
gfx/layers/client/TextureClient.h
gfx/layers/client/TextureClientRecycleAllocator.cpp
--- a/gfx/layers/client/TextureClient.cpp
+++ b/gfx/layers/client/TextureClient.cpp
@@ -910,16 +910,17 @@ TextureClient::TextureClient(TextureData
 , mActor(nullptr)
 , mData(aData)
 , mFlags(aFlags)
 , mOpenMode(OpenMode::OPEN_NONE)
 #ifdef DEBUG
 , mExpectedDtRefs(0)
 #endif
 , mIsLocked(false)
+, mInUse(false)
 , mAddedToCompositableClient(false)
 , mWorkaroundAnnoyingSharedSurfaceLifetimeIssues(false)
 , mWorkaroundAnnoyingSharedSurfaceOwnershipIssues(false)
 #ifdef GFX_DEBUG_TRACK_CLIENTS_IN_POOL
 , mPoolTracker(nullptr)
 #endif
 {
   mFlags |= mData->GetTextureFlags();
--- a/gfx/layers/client/TextureClient.h
+++ b/gfx/layers/client/TextureClient.h
@@ -326,16 +326,23 @@ public:
   void Unlock();
 
   bool IsLocked() const { return mIsLocked; }
 
   bool CanExposeDrawTarget() const { return mData->SupportsMoz2D(); }
 
   bool CanExposeMappedData() const { return mData->CanExposeMappedData(); }
 
+  /* TextureClientRecycleAllocator tracking to decide if we need
+   * to check with the compositor before recycling.
+   * Should be superceeded (and removed) by bug 1252835.
+   */
+  void SetInUse(bool aInUse) { mInUse = aInUse; }
+  bool IsInUse() { return mInUse; }
+
   /**
    * Returns a DrawTarget to draw into the TextureClient.
    * This function should never be called when not on the main thread!
    *
    * This must never be called on a TextureClient that is not sucessfully locked.
    * When called several times within one Lock/Unlock pair, this method should
    * return the same DrawTarget.
    * The DrawTarget is automatically flushed by the TextureClient when the latter
@@ -632,16 +639,17 @@ protected:
   FenceHandle mAcquireFenceHandle;
   gl::GfxTextureWasteTracker mWasteTracker;
 
   OpenMode mOpenMode;
 #ifdef DEBUG
   uint32_t mExpectedDtRefs;
 #endif
   bool mIsLocked;
+  bool mInUse;
 
   bool mAddedToCompositableClient;
   bool mWorkaroundAnnoyingSharedSurfaceLifetimeIssues;
   bool mWorkaroundAnnoyingSharedSurfaceOwnershipIssues;
 
   RefPtr<TextureReadbackSink> mReadbackSink;
 
   friend class TextureChild;
--- a/gfx/layers/client/TextureClientRecycleAllocator.cpp
+++ b/gfx/layers/client/TextureClientRecycleAllocator.cpp
@@ -175,16 +175,17 @@ TextureClientRecycleAllocator::CreateOrR
     // Register TextureClient
     mInUseClients[textureHolder->GetTextureClient()] = textureHolder;
   }
   RefPtr<TextureClient> client(textureHolder->GetTextureClient());
 
   // Make sure the texture holds a reference to us, and ask it to call RecycleTextureClient when its
   // ref count drops to 1.
   client->SetRecycleAllocator(this);
+  client->SetInUse(true);
   return client.forget();
 }
 
 already_AddRefed<TextureClient>
 TextureClientRecycleAllocator::Allocate(gfx::SurfaceFormat aFormat,
                                         gfx::IntSize aSize,
                                         BackendSelector aSelector,
                                         TextureFlags aTextureFlags,
@@ -198,19 +199,45 @@ void
 TextureClientRecycleAllocator::ShrinkToMinimumSize()
 {
   MutexAutoLock lock(mLock);
   while (!mPooledClients.empty()) {
     mPooledClients.pop();
   }
 }
 
+class TextureClientWaitTask : public Runnable
+{
+public:
+  explicit TextureClientWaitTask(TextureClient* aClient)
+    : mTextureClient(aClient)
+  {}
+
+  NS_IMETHOD Run() override
+  {
+    mTextureClient->WaitForCompositorRecycle();
+    return NS_OK;
+  }
+
+private:
+  RefPtr<TextureClient> mTextureClient;
+};
+
 void
 TextureClientRecycleAllocator::RecycleTextureClient(TextureClient* aClient)
 {
+  if (aClient->IsInUse()) {
+    aClient->SetInUse(false);
+    // This adds another ref to aClient, and drops it after a round trip
+    // to the compositor. We should then get this callback a second time
+    // and can recycle properly.
+    RefPtr<Runnable> task = new TextureClientWaitTask(aClient);
+    mSurfaceAllocator->GetMessageLoop()->PostTask(task.forget());
+    return;
+  }
   // Clearing the recycle allocator drops a reference, so make sure we stay alive
   // for the duration of this function.
   RefPtr<TextureClientRecycleAllocator> kungFuDeathGrip(this);
   aClient->SetRecycleAllocator(nullptr);
 
   RefPtr<TextureClientHolder> textureHolder;
   {
     MutexAutoLock lock(mLock);