зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1205559: Make TextureChild/TextureClient thread-safe. r=nical
This commit is contained in:
Родитель
077cb7307e
Коммит
70773dbaa0
|
@ -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<CompositableForwarder> mForwarder;
|
||||
RefPtr<TextureClient> mWaitForRecycle;
|
||||
|
||||
// Monitor protecting mTextureClient.
|
||||
Monitor mMonitor;
|
||||
TextureClient* mTextureClient;
|
||||
UniquePtr<KeepAlive> mKeep;
|
||||
Atomic<bool> 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<KeepAlive> 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<TextureChild> 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.
|
||||
|
|
Загрузка…
Ссылка в новой задаче