diff --git a/gfx/layers/client/TextureClient.cpp b/gfx/layers/client/TextureClient.cpp index 556d28af134b..44383a980ab6 100644 --- a/gfx/layers/client/TextureClient.cpp +++ b/gfx/layers/client/TextureClient.cpp @@ -8,6 +8,7 @@ #include "Layers.h" // for Layer, etc #include "gfx2DGlue.h" #include "gfxPlatform.h" // for gfxPlatform +#include "mozilla/Atomics.h" #include "mozilla/ipc/SharedMemory.h" // for SharedMemory, etc #include "mozilla/layers/CompositableForwarder.h" #include "mozilla/layers/ISurfaceAllocator.h" @@ -101,9 +102,11 @@ public: TextureChild() : mForwarder(nullptr) - , mTextureClient(nullptr) , mMainThreadOnly(false) , mIPCOpen(false) + , mMonitor("TextureChild") + , mTextureClient(nullptr) + , mDestroyed(false) { } @@ -118,7 +121,10 @@ public: void WaitForCompositorRecycle() { - mWaitForRecycle = mTextureClient; + { + MonitorAutoLock mon(mMonitor); + mWaitForRecycle = mDestroyed ? nullptr : mTextureClient; + } RECYCLE_LOG("[CLIENT] Wait for recycle %p\n", mWaitForRecycle.get()); SendClientRecycle(); } @@ -148,10 +154,19 @@ private: Release(); } + void SetTextureClient(TextureClient* aTextureClient) { + MonitorAutoLock mon(mMonitor); + mTextureClient = aTextureClient; + } + RefPtr mForwarder; RefPtr mWaitForRecycle; + + // Monitor protecting mTextureClient. + Monitor mMonitor; TextureClient* mTextureClient; UniquePtr mKeep; + Atomic mDestroyed; bool mMainThreadOnly; bool mIPCOpen; @@ -210,7 +225,7 @@ TextureClient::AddFlags(TextureFlags aFlags) MOZ_ASSERT(!IsSharedWithCompositor() || ((GetFlags() & TextureFlags::RECYCLE) && !IsAddedToCompositableClient())); mFlags |= aFlags; - if (mValid && mActor && mActor->IPCOpen()) { + if (mValid && mActor && !mActor->mDestroyed && mActor->IPCOpen()) { mActor->SendRecycleTexture(mFlags); } } @@ -221,7 +236,7 @@ TextureClient::RemoveFlags(TextureFlags aFlags) MOZ_ASSERT(!IsSharedWithCompositor() || ((GetFlags() & TextureFlags::RECYCLE) && !IsAddedToCompositableClient())); mFlags &= ~aFlags; - if (mValid && mActor && mActor->IPCOpen()) { + if (mValid && mActor && !mActor->mDestroyed && mActor->IPCOpen()) { mActor->SendRecycleTexture(mFlags); } } @@ -234,7 +249,7 @@ TextureClient::RecycleTexture(TextureFlags aFlags) mAddedToCompositableClient = false; if (mFlags != aFlags) { mFlags = aFlags; - if (mValid && mActor && mActor->IPCOpen()) { + if (mValid && mActor && !mActor->mDestroyed && mActor->IPCOpen()) { mActor->SendRecycleTexture(mFlags); } } @@ -276,10 +291,10 @@ bool TextureClient::InitIPDLActor(CompositableForwarder* aForwarder) { MOZ_ASSERT(aForwarder && aForwarder->GetMessageLoop() == mAllocator->GetMessageLoop()); - if (mActor && mActor->GetForwarder() == aForwarder) { + if (mActor && !mActor->mDestroyed && mActor->GetForwarder() == aForwarder) { return true; } - MOZ_ASSERT(!mActor, "Cannot use a texture on several IPC channels."); + MOZ_ASSERT(!mActor || mActor->mDestroyed, "Cannot use a texture on several IPC channels."); SurfaceDescriptor desc; if (!ToSurfaceDescriptor(desc)) { @@ -562,6 +577,9 @@ TextureClient::KeepUntilFullDeallocation(UniquePtr aKeep, bool aMainT void TextureClient::ForceRemove(bool sync) { + if (mActor && mActor->mDestroyed) { + mActor = nullptr; + } if (mValid && mActor) { FinalizeOnIPDLThread(); if (sync || GetFlags() & TextureFlags::DEALLOCATE_CLIENT) { @@ -613,15 +631,20 @@ void TextureClient::Finalize() { MOZ_ASSERT(!IsLocked()); + // Always make a temporary strong reference to the actor before we use it, // in case TextureChild::ActorDestroy might null mActor concurrently. RefPtr actor = mActor; if (actor) { + if (actor->mDestroyed) { + actor = nullptr; + return; + } // The actor has a raw pointer to us, actor->mTextureClient. // Null it before RemoveTexture calls to avoid invalid actor->mTextureClient // when calling TextureChild::ActorDestroy() - actor->mTextureClient = nullptr; + actor->SetTextureClient(nullptr); // `actor->mWaitForRecycle` may not be null, as we may be being called from setting // this RefPtr to null! Clearing it here will double-Release() it.