Bug 1285238 - Add TextureClientRecycleAllocator::Destroy() r=nical
authorSotaro Ikeda <sotaro.ikeda.g@gmail.com>
Sun, 17 Jul 2016 19:23:12 -0700
changeset 305250 0659b20212650c5c3321a7e3aad9e44410fda10e
parent 305249 5102f1b9bccae81f88e8431c817d6ecce5c45529
child 305251 a10a4bbf8728d1802d72876c885726b910faff28
push id79530
push usersikeda@mozilla.com
push dateMon, 18 Jul 2016 02:23:25 +0000
treeherdermozilla-inbound@0659b2021265 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnical
bugs1285238
milestone50.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 1285238 - Add TextureClientRecycleAllocator::Destroy() r=nical
gfx/layers/client/CompositableClient.cpp
gfx/layers/client/TextureClientRecycleAllocator.cpp
gfx/layers/client/TextureClientRecycleAllocator.h
--- a/gfx/layers/client/CompositableClient.cpp
+++ b/gfx/layers/client/CompositableClient.cpp
@@ -155,16 +155,19 @@ CompositableClient::IsConnected() const
 
 void
 CompositableClient::Destroy()
 {
   if (!IsConnected()) {
     return;
   }
 
+  if (mTextureClientRecycler) {
+    mTextureClientRecycler->Destroy();
+  }
   mCompositableChild->mCompositableClient = nullptr;
   mCompositableChild->Destroy(mForwarder);
   mCompositableChild = nullptr;
 }
 
 bool
 CompositableClient::DestroyFallback(PCompositableChild* aActor)
 {
--- a/gfx/layers/client/TextureClientRecycleAllocator.cpp
+++ b/gfx/layers/client/TextureClientRecycleAllocator.cpp
@@ -109,16 +109,17 @@ YCbCrTextureClientAllocationHelper::Allo
                                        mData.mStereoMode,
                                        mTextureFlags);
 }
 
 TextureClientRecycleAllocator::TextureClientRecycleAllocator(CompositableForwarder* aAllocator)
   : mSurfaceAllocator(aAllocator)
   , mMaxPooledSize(kMaxPooledSized)
   , mLock("TextureClientRecycleAllocatorImp.mLock")
+  , mIsDestroyed(false)
 {
 }
 
 TextureClientRecycleAllocator::~TextureClientRecycleAllocator()
 {
   MutexAutoLock lock(mLock);
   while (!mPooledClients.empty()) {
     mPooledClients.pop();
@@ -159,16 +160,19 @@ TextureClientRecycleAllocator::CreateOrR
              aHelper.mAllocationFlags == TextureAllocationFlags::ALLOC_FOR_OUT_OF_BAND_CONTENT ||
              aHelper.mAllocationFlags == TextureAllocationFlags::ALLOC_MANUAL_SYNCHRONIZATION);
   MOZ_ASSERT(aHelper.mTextureFlags & TextureFlags::RECYCLE);
 
   RefPtr<TextureClientHolder> textureHolder;
 
   {
     MutexAutoLock lock(mLock);
+    if (mIsDestroyed) {
+      return nullptr;
+    }
     if (!mPooledClients.empty()) {
       textureHolder = mPooledClients.top();
       mPooledClients.pop();
       // If a pooled TextureClient is not compatible, release it.
       if (!aHelper.IsCompatible(textureHolder->GetTextureClient())) {
         // Release TextureClient.
         RefPtr<Runnable> task = new TextureClientReleaseTask(textureHolder->GetTextureClient());
         textureHolder->ClearTextureClient();
@@ -219,29 +223,39 @@ TextureClientRecycleAllocator::ShrinkToM
 {
   MutexAutoLock lock(mLock);
   while (!mPooledClients.empty()) {
     mPooledClients.pop();
   }
 }
 
 void
+TextureClientRecycleAllocator::Destroy()
+{
+  MutexAutoLock lock(mLock);
+  while (!mPooledClients.empty()) {
+    mPooledClients.pop();
+  }
+  mIsDestroyed = true;
+}
+
+void
 TextureClientRecycleAllocator::RecycleTextureClient(TextureClient* aClient)
 {
   // 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);
     if (mInUseClients.find(aClient) != mInUseClients.end()) {
       textureHolder = mInUseClients[aClient]; // Keep reference count of TextureClientHolder within lock.
-      if (mPooledClients.size() < mMaxPooledSize) {
+      if (!mIsDestroyed && mPooledClients.size() < mMaxPooledSize) {
         mPooledClients.push(textureHolder);
       }
       mInUseClients.erase(aClient);
     }
   }
 }
 
 } // namespace layers
--- a/gfx/layers/client/TextureClientRecycleAllocator.h
+++ b/gfx/layers/client/TextureClientRecycleAllocator.h
@@ -100,16 +100,18 @@ public:
                   TextureFlags aTextureFlags,
                   TextureAllocationFlags flags = ALLOC_DEFAULT);
 
   already_AddRefed<TextureClient>
   CreateOrRecycle(ITextureClientAllocationHelper& aHelper);
 
   void ShrinkToMinimumSize();
 
+  void Destroy();
+
 protected:
   virtual already_AddRefed<TextureClient>
   Allocate(gfx::SurfaceFormat aFormat,
            gfx::IntSize aSize,
            BackendSelector aSelector,
            TextureFlags aTextureFlags,
            TextureAllocationFlags aAllocFlags);
 
@@ -124,14 +126,15 @@ protected:
   std::map<TextureClient*, RefPtr<TextureClientHolder> > mInUseClients;
 
   // On b2g gonk, std::queue might be a better choice.
   // On ICS, fence wait happens implicitly before drawing.
   // Since JB, fence wait happens explicitly when fetching a client from the pool.
   // stack is good from Graphics cache usage point of view.
   std::stack<RefPtr<TextureClientHolder> > mPooledClients;
   Mutex mLock;
+  bool mIsDestroyed;
 };
 
 } // namespace layers
 } // namespace mozilla
 
 #endif /* MOZILLA_GFX_TEXTURECLIENT_RECYCLE_ALLOCATOR_H */