diff --git a/gfx/2d/Logging.h b/gfx/2d/Logging.h index be0c89e9249b..7c171f99be63 100644 --- a/gfx/2d/Logging.h +++ b/gfx/2d/Logging.h @@ -135,6 +135,7 @@ enum class LogReason : int { PAllocTextureBackendMismatch, GetFontFileDataFailed, MessageChannelCloseFailure, + TextureAliveAfterShutdown, // End MustBeLessThanThis = 101, }; diff --git a/gfx/layers/client/ClientLayerManager.cpp b/gfx/layers/client/ClientLayerManager.cpp index 13f113f46083..f17e16786513 100644 --- a/gfx/layers/client/ClientLayerManager.cpp +++ b/gfx/layers/client/ClientLayerManager.cpp @@ -108,6 +108,7 @@ ClientLayerManager::ClientLayerManager(nsIWidget* aWidget) mMemoryPressureObserver = new MemoryPressureObserver(this); } + ClientLayerManager::~ClientLayerManager() { if (mTransactionIdAllocator) { @@ -128,6 +129,18 @@ ClientLayerManager::~ClientLayerManager() MOZ_COUNT_DTOR(ClientLayerManager); } +void +ClientLayerManager::Destroy() +{ + // It's important to call ClearCachedResource before Destroy because the + // former will early-return if the later has already run. + ClearCachedResources(); + for (size_t i = 0; i < mTexturePools.Length(); i++) { + mTexturePools[i]->Destroy(); + } + LayerManager::Destroy(); +} + int32_t ClientLayerManager::GetMaxTextureSize() const { @@ -707,6 +720,8 @@ ClientLayerManager::SetIsFirstPaint() TextureClientPool* ClientLayerManager::GetTexturePool(SurfaceFormat aFormat, TextureFlags aFlags) { + MOZ_DIAGNOSTIC_ASSERT(!mDestroyed); + for (size_t i = 0; i < mTexturePools.Length(); i++) { if (mTexturePools[i]->GetFormat() == aFormat && mTexturePools[i]->GetFlags() == aFlags) { diff --git a/gfx/layers/client/ClientLayerManager.h b/gfx/layers/client/ClientLayerManager.h index b88f37e68166..436587140803 100644 --- a/gfx/layers/client/ClientLayerManager.h +++ b/gfx/layers/client/ClientLayerManager.h @@ -44,13 +44,7 @@ class ClientLayerManager final : public LayerManager public: explicit ClientLayerManager(nsIWidget* aWidget); - virtual void Destroy() override - { - // It's important to call ClearCachedResource before Destroy because the - // former will early-return if the later has already run. - ClearCachedResources(); - LayerManager::Destroy(); - } + virtual void Destroy() override; protected: virtual ~ClientLayerManager(); diff --git a/gfx/layers/client/TextureClientPool.cpp b/gfx/layers/client/TextureClientPool.cpp index 689b4e99d3f5..aec63e311bbb 100644 --- a/gfx/layers/client/TextureClientPool.cpp +++ b/gfx/layers/client/TextureClientPool.cpp @@ -194,9 +194,9 @@ TextureClientPool::ShrinkToMaximumSize() } else { if (!mTextureClients.size()) { // Getting here means we're over our desired number of TextureClients - // with none in the pool. This can happen for pathological cases, or - // it could mean that mMaxTextureClients needs adjusting for whatever - // device we're running on. + // with none in the pool. This can happen during shutdown, or for + // pathological cases, or it could mean that mMaxTextureClients needs + // adjusting for whatever device we're running on. TCP_LOG("TexturePool %p encountering pathological case!\n", this); break; } @@ -269,5 +269,11 @@ TextureClientPool::Clear() } } +void TextureClientPool::Destroy() +{ + Clear(); + mMaxTextureClients = 0; +} + } // namespace layers } // namespace mozilla diff --git a/gfx/layers/client/TextureClientPool.h b/gfx/layers/client/TextureClientPool.h index d146ed6302c4..9c7203005511 100644 --- a/gfx/layers/client/TextureClientPool.h +++ b/gfx/layers/client/TextureClientPool.h @@ -105,6 +105,11 @@ public: gfx::SurfaceFormat GetFormat() { return mFormat; } TextureFlags GetFlags() const { return mFlags; } + /** + * Clear the pool and put it in a state where it won't recycle any new texture. + */ + void Destroy(); + private: // The minimum size of the pool (the number of tiles that will be kept after // shrinking). diff --git a/gfx/layers/ipc/LayerTransactionChild.cpp b/gfx/layers/ipc/LayerTransactionChild.cpp index 9f288830b87d..b044fb9b9b5f 100644 --- a/gfx/layers/ipc/LayerTransactionChild.cpp +++ b/gfx/layers/ipc/LayerTransactionChild.cpp @@ -6,6 +6,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "LayerTransactionChild.h" +#include "mozilla/gfx/Logging.h" #include "mozilla/layers/CompositableClient.h" // for CompositableChild #include "mozilla/layers/PCompositableChild.h" // for PCompositableChild #include "mozilla/layers/PLayerChild.h" // for PLayerChild @@ -39,7 +40,11 @@ LayerTransactionChild::Destroy() const ManagedContainer& textures = ManagedPTextureChild(); for (auto iter = textures.ConstIter(); !iter.Done(); iter.Next()) { TextureClient* texture = TextureClient::AsTextureClient(iter.Get()->GetKey()); + if (texture) { + // TODO: cf bug 1242448. + //gfxDevCrash(gfx::LogReason::TextureAliveAfterShutdown) + // << "A texture is held alive after shutdown (PCompositorBridge)"; texture->Destroy(); } } diff --git a/gfx/layers/ipc/LayerTransactionParent.cpp b/gfx/layers/ipc/LayerTransactionParent.cpp index edfa84bab5ee..027e693376a6 100644 --- a/gfx/layers/ipc/LayerTransactionParent.cpp +++ b/gfx/layers/ipc/LayerTransactionParent.cpp @@ -179,6 +179,8 @@ LayerTransactionParent::Destroy() } InfallibleTArray textures; ManagedPTextureParent(textures); + // We expect all textures to be destroyed by now. + MOZ_DIAGNOSTIC_ASSERT(textures.Length() == 0); for (unsigned int i = 0; i < textures.Length(); ++i) { RefPtr tex = TextureHost::AsTextureHost(textures[i]); tex->DeallocateDeviceData();