mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1200595 - Consolidate the TextureClient's destruction logic. r=mattwoodrow
This commit is contained in:
parent
c12c0c1984
commit
8278de119c
@ -279,7 +279,6 @@ SharedSurface_Gralloc::WaitForBufferOwnership()
|
||||
bool
|
||||
SharedSurface_Gralloc::ToSurfaceDescriptor(layers::SurfaceDescriptor* const out_descriptor)
|
||||
{
|
||||
mTextureClient->MarkShared();
|
||||
return mTextureClient->ToSurfaceDescriptor(*out_descriptor);
|
||||
}
|
||||
|
||||
|
@ -149,7 +149,7 @@ AsyncCanvasRenderer::CopyFromTextureClient(TextureClient* aTextureClient)
|
||||
{
|
||||
MutexAutoLock lock(mMutex);
|
||||
TextureClientAutoLock texLock(aTextureClient, layers::OpenMode::OPEN_READ);
|
||||
if (texLock.Succeeded()) {
|
||||
if (!texLock.Succeeded()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -51,19 +51,21 @@ enum class TextureFlags : uint32_t {
|
||||
// deallocation.
|
||||
// The default behaviour is to deallocate on the host side.
|
||||
DEALLOCATE_CLIENT = 1 << 6,
|
||||
DEALLOCATE_SYNC = 1 << 6, // XXX - make it a separate flag.
|
||||
DEALLOCATE_MAIN_THREAD = 1 << 8,
|
||||
// After being shared ith the compositor side, an immutable texture is never
|
||||
// modified, it can only be read. It is safe to not Lock/Unlock immutable
|
||||
// textures.
|
||||
IMMUTABLE = 1 << 7,
|
||||
IMMUTABLE = 1 << 9,
|
||||
// The contents of the texture must be uploaded or copied immediately
|
||||
// during the transaction, because the producer may want to write
|
||||
// to it again.
|
||||
IMMEDIATE_UPLOAD = 1 << 8,
|
||||
IMMEDIATE_UPLOAD = 1 << 10,
|
||||
// The texture is part of a component-alpha pair
|
||||
COMPONENT_ALPHA = 1 << 9,
|
||||
COMPONENT_ALPHA = 1 << 11,
|
||||
|
||||
// OR union of all valid bits
|
||||
ALL_BITS = (1 << 10) - 1,
|
||||
ALL_BITS = (1 << 12) - 1,
|
||||
// the default flags
|
||||
DEFAULT = NO_FLAGS
|
||||
};
|
||||
|
@ -21,17 +21,6 @@ using namespace mozilla::gfx;
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
already_AddRefed<TextureClient>
|
||||
CreateX11TextureClient(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
|
||||
TextureFlags aFlags, ISurfaceAllocator* aAllocator)
|
||||
{
|
||||
TextureData* data = X11TextureData::Create(aSize, aFormat, aFlags, aAllocator);
|
||||
if (!data) {
|
||||
return nullptr;
|
||||
}
|
||||
return MakeAndAddRef<TextureClient>(data, aFlags, aAllocator);
|
||||
}
|
||||
|
||||
X11TextureData::X11TextureData(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
|
||||
bool aClientDeallocation, bool aIsCrossProcess,
|
||||
gfxXlibSurface* aSurface)
|
||||
|
@ -56,10 +56,6 @@ protected:
|
||||
bool mIsCrossProcess;
|
||||
};
|
||||
|
||||
already_AddRefed<TextureClient>
|
||||
CreateX11TextureClient(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
|
||||
TextureFlags aFlags, ISurfaceAllocator* aAllocator);
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
||||
|
@ -67,17 +67,17 @@ using namespace mozilla::ipc;
|
||||
using namespace mozilla::gl;
|
||||
using namespace mozilla::gfx;
|
||||
|
||||
struct ReleaseKeepAlive : public nsRunnable
|
||||
struct TextureDeallocParams
|
||||
{
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
mKeep = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
UniquePtr<KeepAlive> mKeep;
|
||||
TextureData* data;
|
||||
RefPtr<TextureChild> actor;
|
||||
RefPtr<ISurfaceAllocator> allocator;
|
||||
bool clientDeallocation;
|
||||
bool syncDeallocation;
|
||||
};
|
||||
|
||||
void DeallocateTextureClient(TextureDeallocParams params);
|
||||
|
||||
/**
|
||||
* TextureChild is the content-side incarnation of the PTexture IPDL actor.
|
||||
*
|
||||
@ -93,11 +93,8 @@ class TextureChild final : public ChildActor<PTextureChild>
|
||||
{
|
||||
~TextureChild()
|
||||
{
|
||||
if (mKeep && mMainThreadOnly && !NS_IsMainThread()) {
|
||||
RefPtr<ReleaseKeepAlive> release = new ReleaseKeepAlive();
|
||||
release->mKeep = Move(mKeep);
|
||||
NS_DispatchToMainThread(release);
|
||||
}
|
||||
// We should have deallocated mTextureData in ActorDestroy
|
||||
MOZ_ASSERT(!mTextureData);
|
||||
}
|
||||
public:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TextureChild)
|
||||
@ -106,13 +103,14 @@ public:
|
||||
: mForwarder(nullptr)
|
||||
, mMonitor("TextureChild")
|
||||
, mTextureClient(nullptr)
|
||||
, mTextureData(nullptr)
|
||||
, mDestroyed(false)
|
||||
, mMainThreadOnly(false)
|
||||
, mIPCOpen(false)
|
||||
{
|
||||
}
|
||||
, mOwnsTextureData(false)
|
||||
{}
|
||||
|
||||
bool Recv__delete__() override;
|
||||
bool Recv__delete__() override { return true; }
|
||||
|
||||
bool RecvCompositorRecycle() override
|
||||
{
|
||||
@ -168,41 +166,191 @@ private:
|
||||
// Monitor protecting mTextureClient.
|
||||
Monitor mMonitor;
|
||||
TextureClient* mTextureClient;
|
||||
UniquePtr<KeepAlive> mKeep;
|
||||
TextureData* mTextureData;
|
||||
Atomic<bool> mDestroyed;
|
||||
bool mMainThreadOnly;
|
||||
bool mIPCOpen;
|
||||
bool mOwnsTextureData;
|
||||
|
||||
friend class TextureClient;
|
||||
friend void DeallocateTextureClient(TextureDeallocParams params);
|
||||
};
|
||||
|
||||
bool
|
||||
TextureChild::Recv__delete__()
|
||||
|
||||
static void DestroyTextureData(TextureData* aTextureData, ISurfaceAllocator* aAllocator,
|
||||
bool aDeallocate, bool aMainThreadOnly)
|
||||
{
|
||||
return true;
|
||||
MOZ_ASSERT(aTextureData);
|
||||
if (!aTextureData) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (aMainThreadOnly && !NS_IsMainThread()) {
|
||||
RefPtr<ISurfaceAllocator> allocatorRef = aAllocator;
|
||||
NS_DispatchToMainThread(NS_NewRunnableFunction([aTextureData, allocatorRef, aDeallocate]() -> void {
|
||||
DestroyTextureData(aTextureData, allocatorRef, aDeallocate, true);
|
||||
}));
|
||||
return;
|
||||
}
|
||||
|
||||
if (aDeallocate) {
|
||||
aTextureData->Deallocate(aAllocator);
|
||||
} else {
|
||||
aTextureData->Forget(aAllocator);
|
||||
}
|
||||
delete aTextureData;
|
||||
}
|
||||
|
||||
void
|
||||
TextureChild::ActorDestroy(ActorDestroyReason why)
|
||||
{
|
||||
if (mTextureClient) {
|
||||
mTextureClient->mActor = nullptr;
|
||||
mTextureClient->mAllocator = nullptr;
|
||||
}
|
||||
mWaitForRecycle = nullptr;
|
||||
mKeep = nullptr;
|
||||
|
||||
if (mTextureData) {
|
||||
DestroyTextureData(mTextureData, GetAllocator(), mOwnsTextureData, mMainThreadOnly);
|
||||
mTextureData = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void DeallocateTextureClientSyncProxy(TextureDeallocParams params,
|
||||
ReentrantMonitor* aBarrier, bool* aDone)
|
||||
{
|
||||
DeallocateTextureClient(params);
|
||||
ReentrantMonitorAutoEnter autoMon(*aBarrier);
|
||||
*aDone = true;
|
||||
aBarrier->NotifyAll();
|
||||
}
|
||||
|
||||
/// The logic for synchronizing a TextureClient's deallocation goes here.
|
||||
///
|
||||
/// This funciton takes care of dispatching work to the right thread using
|
||||
/// a synchronous proxy if needed, and handles client/host deallocation.
|
||||
void
|
||||
DeallocateTextureClient(TextureDeallocParams params)
|
||||
{
|
||||
TextureChild* actor = params.actor;
|
||||
MessageLoop* ipdlMsgLoop = nullptr;
|
||||
|
||||
if (params.allocator) {
|
||||
ipdlMsgLoop = params.allocator->GetMessageLoop();
|
||||
if (!ipdlMsgLoop) {
|
||||
// An allocator with no message loop means we are too late in the shutdown
|
||||
// sequence.
|
||||
gfxCriticalError() << "Texture deallocated too late during shutdown";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// First make sure that the work is happening on the IPDL thread.
|
||||
if (ipdlMsgLoop && MessageLoop::current() != ipdlMsgLoop) {
|
||||
if (params.syncDeallocation) {
|
||||
bool done = false;
|
||||
ReentrantMonitor barrier("DeallocateTextureClient");
|
||||
ReentrantMonitorAutoEnter autoMon(barrier);
|
||||
ipdlMsgLoop->PostTask(FROM_HERE,
|
||||
NewRunnableFunction(DeallocateTextureClientSyncProxy,
|
||||
params, &barrier, &done));
|
||||
while (!done) {
|
||||
barrier.Wait();
|
||||
}
|
||||
} else {
|
||||
ipdlMsgLoop->PostTask(FROM_HERE,
|
||||
NewRunnableFunction(DeallocateTextureClient, params));
|
||||
}
|
||||
// The work has been forwarded to the IPDL thread, we are done.
|
||||
return;
|
||||
}
|
||||
|
||||
// Below this line, we are either in the IPDL thread or ther is no IPDL
|
||||
// thread anymore.
|
||||
|
||||
if (!ipdlMsgLoop) {
|
||||
// If we don't have a message loop we can't know for sure that we are in
|
||||
// the IPDL thread and use the ISurfaceAllocator.
|
||||
// This should ideally not happen outside of gtest, but some shutdown raciness
|
||||
// could put us in this situation.
|
||||
params.allocator = nullptr;
|
||||
}
|
||||
|
||||
if (!actor) {
|
||||
// We don't have an IPDL actor, probably because we destroyed the TextureClient
|
||||
// before sharing it with the compositor. It means the data cannot be owned by
|
||||
// the TextureHost since we never created the TextureHost.
|
||||
DestroyTextureData(params.data, params.allocator,
|
||||
true, // client-side deallocation
|
||||
false); // main-thread deallocation
|
||||
return;
|
||||
}
|
||||
|
||||
if (!actor->IPCOpen()) {
|
||||
// The actor is already deallocated which probably means there was a shutdown
|
||||
// race causing this function to be called concurrently which is bad!
|
||||
gfxCriticalError() << "Racy texture deallocation";
|
||||
return;
|
||||
}
|
||||
|
||||
if (params.syncDeallocation) {
|
||||
MOZ_PERFORMANCE_WARNING("gfx",
|
||||
"TextureClient/Host pair requires synchronous deallocation");
|
||||
actor->DestroySynchronously();
|
||||
DestroyTextureData(params.data, params.allocator, params.clientDeallocation,
|
||||
actor->mMainThreadOnly);
|
||||
} else {
|
||||
actor->mTextureData = params.data;
|
||||
actor->mOwnsTextureData = params.clientDeallocation;
|
||||
actor->Destroy();
|
||||
// DestroyTextureData will be called by TextureChild::ActorDestroy
|
||||
}
|
||||
}
|
||||
|
||||
void TextureClient::Destroy(bool aForceSync)
|
||||
{
|
||||
MOZ_ASSERT(!IsLocked());
|
||||
|
||||
RefPtr<TextureChild> actor = mActor;
|
||||
mActor = nullptr;
|
||||
|
||||
if (actor && !actor->mDestroyed.compareExchange(false, true)) {
|
||||
actor = nullptr;
|
||||
}
|
||||
|
||||
TextureData* data = mData;
|
||||
if (!mWorkaroundAnnoyingSharedSurfaceLifetimeIssues) {
|
||||
mData = nullptr;
|
||||
}
|
||||
|
||||
if (data || actor) {
|
||||
TextureDeallocParams params;
|
||||
params.actor = actor;
|
||||
params.allocator = mAllocator;
|
||||
params.clientDeallocation = !!(mFlags & TextureFlags::DEALLOCATE_CLIENT);
|
||||
if (mWorkaroundAnnoyingSharedSurfaceLifetimeIssues) {
|
||||
params.data = nullptr;
|
||||
} else {
|
||||
params.data = data;
|
||||
}
|
||||
// At the moment we always deallocate synchronously when deallocating on the
|
||||
// client side, but having asynchronous deallocate in some of the cases will
|
||||
// be a worthwhile optimization.
|
||||
params.syncDeallocation = !!(mFlags & TextureFlags::DEALLOCATE_CLIENT) || aForceSync;
|
||||
DeallocateTextureClient(params);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
TextureClient::Lock(OpenMode aMode)
|
||||
{
|
||||
MOZ_ASSERT(mValid);
|
||||
MOZ_ASSERT(IsValid());
|
||||
MOZ_ASSERT(!mIsLocked);
|
||||
if (mIsLocked) {
|
||||
return mOpenMode == aMode;
|
||||
}
|
||||
|
||||
if (mRemoveFromCompositableWaiter) {
|
||||
mRemoveFromCompositableWaiter->WaitComplete();
|
||||
mRemoveFromCompositableWaiter = nullptr;
|
||||
}
|
||||
|
||||
mIsLocked = mData->Lock(aMode, mReleaseFenceHandle.IsValid() ? &mReleaseFenceHandle : nullptr);
|
||||
mOpenMode = aMode;
|
||||
|
||||
@ -212,7 +360,7 @@ TextureClient::Lock(OpenMode aMode)
|
||||
void
|
||||
TextureClient::Unlock()
|
||||
{
|
||||
MOZ_ASSERT(mValid);
|
||||
MOZ_ASSERT(IsValid());
|
||||
MOZ_ASSERT(mIsLocked);
|
||||
if (!mIsLocked) {
|
||||
return;
|
||||
@ -241,44 +389,33 @@ TextureClient::Unlock()
|
||||
bool
|
||||
TextureClient::HasInternalBuffer() const
|
||||
{
|
||||
MOZ_ASSERT(mValid);
|
||||
MOZ_ASSERT(IsValid());
|
||||
return mData->HasInternalBuffer();
|
||||
}
|
||||
|
||||
gfx::IntSize
|
||||
TextureClient::GetSize() const
|
||||
{
|
||||
MOZ_ASSERT(mValid);
|
||||
MOZ_ASSERT(IsValid());
|
||||
return mData->GetSize();
|
||||
}
|
||||
|
||||
gfx::SurfaceFormat
|
||||
TextureClient::GetFormat() const
|
||||
{
|
||||
MOZ_ASSERT(mValid);
|
||||
MOZ_ASSERT(IsValid());
|
||||
return mData->GetFormat();
|
||||
}
|
||||
|
||||
TextureClient::~TextureClient()
|
||||
{
|
||||
if (ShouldDeallocateInDestructor()) {
|
||||
mData->Deallocate(mAllocator);
|
||||
} else {
|
||||
mData->Forget(mAllocator);
|
||||
}
|
||||
delete mData;
|
||||
}
|
||||
|
||||
void
|
||||
TextureClient::FinalizeOnIPDLThread()
|
||||
{
|
||||
mData->FinalizeOnIPDLThread(this);
|
||||
Destroy(false);
|
||||
}
|
||||
|
||||
void
|
||||
TextureClient::UpdateFromSurface(gfx::SourceSurface* aSurface)
|
||||
{
|
||||
MOZ_ASSERT(mValid);
|
||||
MOZ_ASSERT(IsValid());
|
||||
MOZ_ASSERT(mIsLocked);
|
||||
MOZ_ASSERT(aSurface);
|
||||
|
||||
@ -308,7 +445,7 @@ TextureClient::UpdateFromSurface(gfx::SourceSurface* aSurface)
|
||||
already_AddRefed<TextureClient>
|
||||
TextureClient::CreateSimilar(TextureFlags aFlags, TextureAllocationFlags aAllocFlags) const
|
||||
{
|
||||
MOZ_ASSERT(mValid);
|
||||
MOZ_ASSERT(IsValid());
|
||||
TextureData* data = mData->CreateSimilar(mAllocator, aFlags, aAllocFlags);
|
||||
if (!data) {
|
||||
return nullptr;
|
||||
@ -320,7 +457,7 @@ TextureClient::CreateSimilar(TextureFlags aFlags, TextureAllocationFlags aAllocF
|
||||
gfx::DrawTarget*
|
||||
TextureClient::BorrowDrawTarget()
|
||||
{
|
||||
MOZ_ASSERT(mValid);
|
||||
MOZ_ASSERT(IsValid());
|
||||
MOZ_ASSERT(mIsLocked);
|
||||
// TODO- We can't really assert that at the moment because there is code that Borrows
|
||||
// the DrawTarget, just to get a snapshot, which is legit in term of OpenMode
|
||||
@ -348,7 +485,7 @@ TextureClient::BorrowDrawTarget()
|
||||
bool
|
||||
TextureClient::BorrowMappedData(MappedTextureData& aMap)
|
||||
{
|
||||
MOZ_ASSERT(mValid);
|
||||
MOZ_ASSERT(IsValid());
|
||||
|
||||
// TODO - SharedRGBImage just accesses the buffer without properly locking
|
||||
// the texture. It's bad.
|
||||
@ -363,14 +500,14 @@ TextureClient::BorrowMappedData(MappedTextureData& aMap)
|
||||
bool
|
||||
TextureClient::BorrowMappedYCbCrData(MappedYCbCrTextureData& aMap)
|
||||
{
|
||||
MOZ_ASSERT(mValid);
|
||||
MOZ_ASSERT(IsValid());
|
||||
return mData->BorrowMappedYCbCrData(aMap);
|
||||
}
|
||||
|
||||
bool
|
||||
TextureClient::ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor)
|
||||
{
|
||||
MOZ_ASSERT(mValid);
|
||||
MOZ_ASSERT(IsValid());
|
||||
return mData->Serialize(aOutDescriptor);
|
||||
}
|
||||
|
||||
@ -382,10 +519,12 @@ TextureClient::WaitForBufferOwnership(bool aWaitReleaseFence)
|
||||
mRemoveFromCompositableWaiter = nullptr;
|
||||
}
|
||||
|
||||
#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION < 21
|
||||
if (aWaitReleaseFence && mReleaseFenceHandle.IsValid()) {
|
||||
mData->WaitForFence(&mReleaseFenceHandle);
|
||||
mReleaseFenceHandle = FenceHandle();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// static
|
||||
@ -409,12 +548,20 @@ TextureClient::DestroyIPDLActor(PTextureChild* actor)
|
||||
TextureClient*
|
||||
TextureClient::AsTextureClient(PTextureChild* actor)
|
||||
{
|
||||
return actor ? static_cast<TextureChild*>(actor)->mTextureClient : nullptr;
|
||||
if (!actor) {
|
||||
return nullptr;
|
||||
}
|
||||
TextureChild* tc = static_cast<TextureChild*>(actor);
|
||||
if (tc->mDestroyed) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return tc->mTextureClient;
|
||||
}
|
||||
|
||||
bool
|
||||
TextureClient::IsSharedWithCompositor() const {
|
||||
return mShared && mActor && mActor->IPCOpen();
|
||||
return mActor && mActor->IPCOpen();
|
||||
}
|
||||
|
||||
void
|
||||
@ -423,7 +570,7 @@ TextureClient::AddFlags(TextureFlags aFlags)
|
||||
MOZ_ASSERT(!IsSharedWithCompositor() ||
|
||||
((GetFlags() & TextureFlags::RECYCLE) && !IsAddedToCompositableClient()));
|
||||
mFlags |= aFlags;
|
||||
if (mValid && mActor && !mActor->mDestroyed && mActor->IPCOpen()) {
|
||||
if (IsValid() && mActor && !mActor->mDestroyed && mActor->IPCOpen()) {
|
||||
mActor->SendRecycleTexture(mFlags);
|
||||
}
|
||||
}
|
||||
@ -434,7 +581,7 @@ TextureClient::RemoveFlags(TextureFlags aFlags)
|
||||
MOZ_ASSERT(!IsSharedWithCompositor() ||
|
||||
((GetFlags() & TextureFlags::RECYCLE) && !IsAddedToCompositableClient()));
|
||||
mFlags &= ~aFlags;
|
||||
if (mValid && mActor && !mActor->mDestroyed && mActor->IPCOpen()) {
|
||||
if (IsValid() && mActor && !mActor->mDestroyed && mActor->IPCOpen()) {
|
||||
mActor->SendRecycleTexture(mFlags);
|
||||
}
|
||||
}
|
||||
@ -447,7 +594,7 @@ TextureClient::RecycleTexture(TextureFlags aFlags)
|
||||
mAddedToCompositableClient = false;
|
||||
if (mFlags != aFlags) {
|
||||
mFlags = aFlags;
|
||||
if (mValid && mActor && !mActor->mDestroyed && mActor->IPCOpen()) {
|
||||
if (IsValid() && mActor && !mActor->mDestroyed && mActor->IPCOpen()) {
|
||||
mActor->SendRecycleTexture(mFlags);
|
||||
}
|
||||
}
|
||||
@ -503,7 +650,7 @@ TextureClient::InitIPDLActor(CompositableForwarder* aForwarder)
|
||||
MOZ_ASSERT(mActor);
|
||||
mActor->mForwarder = aForwarder;
|
||||
mActor->mTextureClient = this;
|
||||
mShared = true;
|
||||
mActor->mMainThreadOnly = !!(mFlags & TextureFlags::DEALLOCATE_MAIN_THREAD);
|
||||
return mActor->IPCOpen();
|
||||
}
|
||||
|
||||
@ -548,7 +695,7 @@ TextureClient::CreateForDrawing(CompositableForwarder* aAllocator,
|
||||
LayersBackend parentBackend = aAllocator->GetCompositorBackendType();
|
||||
gfx::BackendType moz2DBackend = BackendTypeForBackendSelector(parentBackend, aSelector);
|
||||
|
||||
RefPtr<TextureClient> texture;
|
||||
TextureData* data = nullptr;
|
||||
|
||||
#if defined(XP_WIN)
|
||||
int32_t maxTextureSize = aAllocator->GetMaxTextureSize();
|
||||
@ -561,33 +708,23 @@ TextureClient::CreateForDrawing(CompositableForwarder* aAllocator,
|
||||
aSize.width <= maxTextureSize &&
|
||||
aSize.height <= maxTextureSize)
|
||||
{
|
||||
texture = CreateDXGITextureClient(aSize, aFormat, aTextureFlags, aAllocFlags, aAllocator);
|
||||
if (texture) {
|
||||
return texture.forget();
|
||||
}
|
||||
data = DXGITextureData::Create(aSize, aFormat, aAllocFlags);
|
||||
}
|
||||
if (parentBackend == LayersBackend::LAYERS_D3D9 &&
|
||||
moz2DBackend == gfx::BackendType::CAIRO &&
|
||||
aAllocator->IsSameProcess() &&
|
||||
aSize.width <= maxTextureSize &&
|
||||
aSize.height <= maxTextureSize &&
|
||||
NS_IsMainThread()) {
|
||||
if (gfxWindowsPlatform::GetPlatform()->GetD3D9Device()) {
|
||||
TextureData* data = D3D9TextureData::Create(aSize, aFormat, aAllocFlags);
|
||||
if (data) {
|
||||
return MakeAndAddRef<TextureClient>(data, aTextureFlags, aAllocator);
|
||||
}
|
||||
}
|
||||
NS_IsMainThread() &&
|
||||
gfxWindowsPlatform::GetPlatform()->GetD3D9Device()) {
|
||||
data = D3D9TextureData::Create(aSize, aFormat, aAllocFlags);
|
||||
}
|
||||
|
||||
if (!texture && aFormat == SurfaceFormat::B8G8R8X8 &&
|
||||
if (!data && aFormat == SurfaceFormat::B8G8R8X8 &&
|
||||
aAllocator->IsSameProcess() &&
|
||||
moz2DBackend == gfx::BackendType::CAIRO &&
|
||||
NS_IsMainThread()) {
|
||||
TextureData* data = DIBTextureData::Create(aSize, aFormat, aAllocator);
|
||||
if (data) {
|
||||
return MakeAndAddRef<TextureClient>(data, aTextureFlags, aAllocator);
|
||||
}
|
||||
data = DIBTextureData::Create(aSize, aFormat, aAllocator);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -595,37 +732,34 @@ TextureClient::CreateForDrawing(CompositableForwarder* aAllocator,
|
||||
gfxSurfaceType type =
|
||||
gfxPlatform::GetPlatform()->ScreenReferenceSurface()->GetType();
|
||||
|
||||
if (parentBackend == LayersBackend::LAYERS_BASIC &&
|
||||
if (!data && parentBackend == LayersBackend::LAYERS_BASIC &&
|
||||
moz2DBackend == gfx::BackendType::CAIRO &&
|
||||
type == gfxSurfaceType::Xlib)
|
||||
{
|
||||
texture = CreateX11TextureClient(aSize, aFormat, aTextureFlags, aAllocator);
|
||||
if (texture) {
|
||||
return texture.forget();
|
||||
}
|
||||
data = X11TextureData::Create(aSize, aFormat, aTextureFlags, aAllocator);
|
||||
}
|
||||
#ifdef GL_PROVIDER_GLX
|
||||
if (parentBackend == LayersBackend::LAYERS_OPENGL &&
|
||||
if (!data && parentBackend == LayersBackend::LAYERS_OPENGL &&
|
||||
type == gfxSurfaceType::Xlib &&
|
||||
aFormat != SurfaceFormat::A8 &&
|
||||
gl::sGLXLibrary.UseTextureFromPixmap())
|
||||
{
|
||||
texture = CreateX11TextureClient(aSize, aFormat, aTextureFlags, aAllocator);
|
||||
if (texture) {
|
||||
return texture.forget();
|
||||
}
|
||||
data = X11TextureData::Create(aSize, aFormat, aTextureFlags, aAllocator);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
texture = CreateGrallocTextureClientForDrawing(aSize, aFormat, moz2DBackend,
|
||||
aTextureFlags, aAllocator);
|
||||
if (texture) {
|
||||
return texture.forget();
|
||||
if (!data) {
|
||||
data = GrallocTextureData::CreateForDrawing(aSize, aFormat, moz2DBackend,
|
||||
aAllocator);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (data) {
|
||||
return MakeAndAddRef<TextureClient>(data, aTextureFlags, aAllocator);
|
||||
}
|
||||
|
||||
// Can't do any better than a buffer texture client.
|
||||
return TextureClient::CreateForRawBufferAccess(aAllocator, aFormat, aSize,
|
||||
moz2DBackend, aTextureFlags, aAllocFlags);
|
||||
@ -645,6 +779,10 @@ TextureClient::CreateForRawBufferAccess(ISurfaceAllocator* aAllocator,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (aAllocFlags & ALLOC_DISALLOW_BUFFERTEXTURECLIENT) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!gfx::Factory::AllowedSurfaceSize(aSize)) {
|
||||
return nullptr;
|
||||
}
|
||||
@ -717,39 +855,13 @@ TextureClient::TextureClient(TextureData* aData, TextureFlags aFlags, ISurfaceAl
|
||||
, mExpectedDtRefs(0)
|
||||
#endif
|
||||
, mIsLocked(false)
|
||||
, mShared(false)
|
||||
, mValid(true)
|
||||
, mAddedToCompositableClient(false)
|
||||
, mWorkaroundAnnoyingSharedSurfaceLifetimeIssues(false)
|
||||
#ifdef GFX_DEBUG_TRACK_CLIENTS_IN_POOL
|
||||
, mPoolTracker(nullptr)
|
||||
#endif
|
||||
{}
|
||||
|
||||
void
|
||||
TextureClient::KeepUntilFullDeallocation(UniquePtr<KeepAlive> aKeep, bool aMainThreadOnly)
|
||||
{
|
||||
MOZ_ASSERT(mActor);
|
||||
MOZ_ASSERT(!mActor->mKeep);
|
||||
mActor->mKeep = Move(aKeep);
|
||||
mActor->mMainThreadOnly = aMainThreadOnly;
|
||||
}
|
||||
|
||||
void TextureClient::ForceRemove(bool sync)
|
||||
{
|
||||
if (mActor && mActor->mDestroyed) {
|
||||
mActor = nullptr;
|
||||
}
|
||||
if (mValid && mActor) {
|
||||
FinalizeOnIPDLThread();
|
||||
if (mActor->CanSend()) {
|
||||
if (sync || GetFlags() & TextureFlags::DEALLOCATE_CLIENT) {
|
||||
mActor->DestroySynchronously();
|
||||
} else {
|
||||
mActor->Destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
MarkInvalid();
|
||||
mFlags |= mData->GetTextureFlags();
|
||||
}
|
||||
|
||||
bool TextureClient::CopyToTextureClient(TextureClient* aTarget,
|
||||
@ -782,45 +894,6 @@ bool TextureClient::CopyToTextureClient(TextureClient* aTarget,
|
||||
return true;
|
||||
}
|
||||
|
||||
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->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.
|
||||
|
||||
// this will call ForceRemove in the right thread, using a sync proxy if needed
|
||||
if (actor->GetForwarder()) {
|
||||
actor->GetForwarder()->RemoveTexture(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
TextureClient::ShouldDeallocateInDestructor() const
|
||||
{
|
||||
// If we're meant to be deallocated by the host,
|
||||
// but we haven't been shared yet or
|
||||
// TextureFlags::DEALLOCATE_CLIENT is set, then we should
|
||||
// deallocate on the client instead.
|
||||
return !mShared || (GetFlags() & TextureFlags::DEALLOCATE_CLIENT);
|
||||
}
|
||||
|
||||
void
|
||||
TextureClient::SetRemoveFromCompositableWaiter(AsyncTransactionWaiter* aWaiter) {
|
||||
mRemoveFromCompositableWaiter = aWaiter;
|
||||
|
@ -214,8 +214,7 @@ public:
|
||||
|
||||
virtual void SyncWithObject(SyncObject* aFence) {};
|
||||
|
||||
/// Needed until the destruction sequence of TextureClient is revamped.
|
||||
virtual void FinalizeOnIPDLThread(TextureClient*) {}
|
||||
virtual TextureFlags GetTextureFlags() const { return TextureFlags::NO_FLAGS; }
|
||||
};
|
||||
|
||||
/**
|
||||
@ -448,13 +447,11 @@ public:
|
||||
|
||||
bool IsSharedWithCompositor() const;
|
||||
|
||||
bool ShouldDeallocateInDestructor() const;
|
||||
|
||||
/**
|
||||
* If this method returns false users of TextureClient are not allowed
|
||||
* to access the shared data.
|
||||
*/
|
||||
bool IsValid() const { return mValid; }
|
||||
bool IsValid() const { return !!mData; }
|
||||
|
||||
/**
|
||||
* Called when TextureClient is added to CompositableClient.
|
||||
@ -467,16 +464,6 @@ public:
|
||||
*/
|
||||
bool IsAddedToCompositableClient() const { return mAddedToCompositableClient; }
|
||||
|
||||
/**
|
||||
* kee the passed object alive until the IPDL actor is destroyed. This can
|
||||
* help avoid race conditions in some cases.
|
||||
* It's a temporary hack to ensure that DXGI textures don't get destroyed
|
||||
* between serialization and deserialization.
|
||||
*
|
||||
* This must not be called off the texture's IPDL thread.
|
||||
*/
|
||||
void KeepUntilFullDeallocation(UniquePtr<KeepAlive> aKeep, bool aMainThreadOnly = false);
|
||||
|
||||
/**
|
||||
* Create and init the TextureChild/Parent IPDL actor pair.
|
||||
*
|
||||
@ -501,7 +488,7 @@ public:
|
||||
* If sync is true, the destruction will be synchronous regardless of the
|
||||
* texture's flags (bad for performance, use with care).
|
||||
*/
|
||||
void ForceRemove(bool sync = false);
|
||||
void Destroy(bool sync = false);
|
||||
|
||||
virtual void SetReleaseFenceHandle(const FenceHandle& aReleaseFenceHandle)
|
||||
{
|
||||
@ -532,6 +519,9 @@ public:
|
||||
|
||||
/**
|
||||
* This function waits until the buffer is no longer being used.
|
||||
*
|
||||
* XXX - Ideally we shouldn't need this method because Lock the right
|
||||
* thing already.
|
||||
*/
|
||||
virtual void WaitForBufferOwnership(bool aWaitReleaseFence = true);
|
||||
|
||||
@ -554,8 +544,6 @@ public:
|
||||
|
||||
void SyncWithObject(SyncObject* aFence) { mData->SyncWithObject(aFence); }
|
||||
|
||||
void MarkShared() { mShared = true; }
|
||||
|
||||
ISurfaceAllocator* GetAllocator() { return mAllocator; }
|
||||
|
||||
TextureClientRecycleAllocator* GetRecycleAllocator() { return mRecycleAllocator; }
|
||||
@ -575,23 +563,11 @@ private:
|
||||
* Here goes the shut-down code that uses virtual methods.
|
||||
* Must only be called by Release().
|
||||
*/
|
||||
B2G_ACL_EXPORT void Finalize();
|
||||
|
||||
/**
|
||||
* Called once during the destruction of the texture on the IPDL thread, if
|
||||
* the texture is shared on the compositor (otherwise it is not called at all).
|
||||
*/
|
||||
void FinalizeOnIPDLThread();
|
||||
B2G_ACL_EXPORT void Finalize() {}
|
||||
|
||||
friend class AtomicRefCountedWithFinalize<TextureClient>;
|
||||
friend class gl::SharedSurface_Gralloc;
|
||||
protected:
|
||||
/**
|
||||
* An invalid TextureClient cannot provide access to its shared data
|
||||
* anymore. This usually means it will soon be destroyed.
|
||||
*/
|
||||
void MarkInvalid() { mValid = false; }
|
||||
|
||||
/**
|
||||
* Should only be called *once* per texture, in TextureClient::InitIPDLActor.
|
||||
* Some texture implementations rely on the fact that the descriptor will be
|
||||
@ -620,9 +596,8 @@ protected:
|
||||
DebugOnly<uint32_t> mExpectedDtRefs;
|
||||
bool mIsLocked;
|
||||
|
||||
bool mShared;
|
||||
bool mValid;
|
||||
bool mAddedToCompositableClient;
|
||||
bool mWorkaroundAnnoyingSharedSurfaceLifetimeIssues;
|
||||
|
||||
RefPtr<TextureReadbackSink> mReadbackSink;
|
||||
|
||||
|
@ -52,7 +52,9 @@ SharedSurfaceTextureClient::SharedSurfaceTextureClient(SharedSurfaceTextureData*
|
||||
TextureFlags aFlags,
|
||||
ISurfaceAllocator* aAllocator)
|
||||
: TextureClient(aData, aFlags, aAllocator)
|
||||
{}
|
||||
{
|
||||
mWorkaroundAnnoyingSharedSurfaceLifetimeIssues = true;
|
||||
}
|
||||
|
||||
already_AddRefed<SharedSurfaceTextureClient>
|
||||
SharedSurfaceTextureClient::Create(UniquePtr<gl::SharedSurface> surf, gl::SurfaceFactory* factory,
|
||||
@ -127,5 +129,29 @@ SharedSurfaceTextureClient::GetAcquireFenceHandle() const
|
||||
return TextureClient::GetAcquireFenceHandle();
|
||||
}
|
||||
|
||||
SharedSurfaceTextureClient::~SharedSurfaceTextureClient()
|
||||
{
|
||||
// XXX - Things break when using the proper destruction handshake with
|
||||
// SharedSurfaceTextureData because the TextureData outlives its gl
|
||||
// context. Having a strong reference to the gl context creates a cycle.
|
||||
// This needs to be fixed in a better way, though, because deleting
|
||||
// the TextureData here can race with the compositor and cause flashing.
|
||||
TextureData* data = mData;
|
||||
mData = nullptr;
|
||||
|
||||
Destroy();
|
||||
|
||||
if (data) {
|
||||
// Destroy mData right away without doing the proper deallocation handshake,
|
||||
// because SharedSurface depends on things that may not outlive the texture's
|
||||
// destructor so we can't wait until we know the compositor isn't using the
|
||||
// texture anymore.
|
||||
// It goes without saying that this is really bad and we should fix the bugs
|
||||
// that block doing the right thing such as bug 1224199 sooner rather than
|
||||
// later.
|
||||
delete data;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
@ -66,6 +66,8 @@ public:
|
||||
TextureFlags aFlags,
|
||||
ISurfaceAllocator* aAllocator);
|
||||
|
||||
~SharedSurfaceTextureClient();
|
||||
|
||||
static already_AddRefed<SharedSurfaceTextureClient>
|
||||
Create(UniquePtr<gl::SharedSurface> surf, gl::SurfaceFactory* factory,
|
||||
ISurfaceAllocator* aAllocator, TextureFlags aFlags);
|
||||
|
@ -433,19 +433,6 @@ DXGITextureData::Create(IntSize aSize, SurfaceFormat aFormat, TextureAllocationF
|
||||
}
|
||||
}
|
||||
|
||||
already_AddRefed<TextureClient>
|
||||
CreateDXGITextureClient(IntSize aSize, SurfaceFormat aFormat,
|
||||
TextureFlags aTextureFlags, TextureAllocationFlags aAllocFlags,
|
||||
ISurfaceAllocator* aAllocator)
|
||||
{
|
||||
TextureData* data = DXGITextureData::Create(aSize, aFormat, aAllocFlags);
|
||||
if (!data) {
|
||||
return nullptr;
|
||||
}
|
||||
return MakeAndAddRef<TextureClient>(data, aTextureFlags, aAllocator);
|
||||
}
|
||||
|
||||
|
||||
DXGITextureData*
|
||||
D3D11TextureData::Create(IntSize aSize, SurfaceFormat aFormat, TextureAllocationFlags aFlags,
|
||||
ID3D11Device* aDevice)
|
||||
@ -654,26 +641,6 @@ DXGIYCbCrTextureData::Serialize(SurfaceDescriptor& aOutDescriptor)
|
||||
return true;
|
||||
}
|
||||
|
||||
class YCbCrKeepAliveD3D11 : public KeepAlive
|
||||
{
|
||||
public:
|
||||
YCbCrKeepAliveD3D11(RefPtr<IUnknown> aTextures[3])
|
||||
{
|
||||
mTextures[0] = aTextures[0];
|
||||
mTextures[1] = aTextures[1];
|
||||
mTextures[2] = aTextures[2];
|
||||
}
|
||||
|
||||
protected:
|
||||
RefPtr<IUnknown> mTextures[3];
|
||||
};
|
||||
|
||||
void
|
||||
DXGIYCbCrTextureData::FinalizeOnIPDLThread(TextureClient* aWrapper)
|
||||
{
|
||||
aWrapper->KeepUntilFullDeallocation(MakeUnique<YCbCrKeepAliveD3D11>(mHoldRefs));
|
||||
}
|
||||
|
||||
void
|
||||
DXGIYCbCrTextureData::Deallocate(ISurfaceAllocator*)
|
||||
{
|
||||
@ -812,18 +779,6 @@ D3D10TextureData::UpdateFromSurface(gfx::SourceSurface* aSurface)
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
D3D11TextureData::FinalizeOnIPDLThread(TextureClient* aWrapper)
|
||||
{
|
||||
aWrapper->KeepUntilFullDeallocation(MakeUnique<TKeepAlive<ID3D11Texture2D>>(mTexture));
|
||||
}
|
||||
|
||||
void
|
||||
D3D10TextureData::FinalizeOnIPDLThread(TextureClient* aWrapper)
|
||||
{
|
||||
aWrapper->KeepUntilFullDeallocation(MakeUnique<TKeepAlive<ID3D10Texture2D>>(mTexture));
|
||||
}
|
||||
|
||||
DXGITextureHostD3D11::DXGITextureHostD3D11(TextureFlags aFlags,
|
||||
const SurfaceDescriptorD3D10& aDescriptor)
|
||||
: TextureHost(aFlags)
|
||||
|
@ -55,11 +55,6 @@ protected:
|
||||
bool mHasSynchronization;
|
||||
};
|
||||
|
||||
already_AddRefed<TextureClient>
|
||||
CreateDXGITextureClient(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
|
||||
TextureFlags atextureFlags, TextureAllocationFlags aFlags,
|
||||
ISurfaceAllocator* aAllocator);
|
||||
|
||||
class D3D11TextureData : public DXGITextureData
|
||||
{
|
||||
public:
|
||||
@ -95,8 +90,6 @@ protected:
|
||||
gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
|
||||
bool aNeedsClear, bool aNeedsClearWhite);
|
||||
|
||||
virtual void FinalizeOnIPDLThread(TextureClient* aWrapper) override;
|
||||
|
||||
virtual void GetDXGIResource(IDXGIResource** aOutResource) override;
|
||||
|
||||
RefPtr<ID3D11Texture2D> mTexture;
|
||||
@ -141,8 +134,6 @@ protected:
|
||||
gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
|
||||
bool aNeedsClear, bool aNeedsClearWhite);
|
||||
|
||||
virtual void FinalizeOnIPDLThread(TextureClient*) override;
|
||||
|
||||
virtual void GetDXGIResource(IDXGIResource** aOutResource) override;
|
||||
|
||||
RefPtr<ID3D10Texture2D> mTexture;
|
||||
@ -201,9 +192,12 @@ public:
|
||||
|
||||
virtual bool UpdateFromSurface(gfx::SourceSurface*) override { return false; }
|
||||
|
||||
protected:
|
||||
virtual void FinalizeOnIPDLThread(TextureClient*) override;
|
||||
virtual TextureFlags GetTextureFlags() const override
|
||||
{
|
||||
return TextureFlags::DEALLOCATE_MAIN_THREAD;
|
||||
}
|
||||
|
||||
protected:
|
||||
RefPtr<IUnknown> mHoldRefs[3];
|
||||
HANDLE mHandles[3];
|
||||
gfx::IntSize mSize;
|
||||
@ -421,9 +415,9 @@ class SyncObjectD3D11 : public SyncObject
|
||||
{
|
||||
public:
|
||||
SyncObjectD3D11(SyncHandle aSyncHandle);
|
||||
virtual void FinalizeFrame();
|
||||
|
||||
virtual SyncType GetSyncType() { return SyncType::D3D11; }
|
||||
virtual void FinalizeFrame();
|
||||
|
||||
void RegisterTexture(ID3D11Texture2D* aTexture);
|
||||
void RegisterTexture(ID3D10Texture2D* aTexture);
|
||||
|
@ -487,14 +487,6 @@ D3D9TextureData::CreateSimilar(ISurfaceAllocator*, TextureFlags aFlags, TextureA
|
||||
return D3D9TextureData::Create(mSize, mFormat, aAllocFlags);
|
||||
}
|
||||
|
||||
void
|
||||
D3D9TextureData::FinalizeOnIPDLThread(TextureClient* aWrapper)
|
||||
{
|
||||
if (mTexture) {
|
||||
aWrapper->KeepUntilFullDeallocation(MakeUnique<TKeepAlive<IDirect3DTexture9>>(mTexture));
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
D3D9TextureData::Lock(OpenMode aMode, FenceHandle*)
|
||||
{
|
||||
|
@ -209,8 +209,6 @@ public:
|
||||
virtual void Deallocate(ISurfaceAllocator* aAllocator) {}
|
||||
|
||||
protected:
|
||||
virtual void FinalizeOnIPDLThread(TextureClient* aWrapper) override;
|
||||
|
||||
D3D9TextureData(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
|
||||
IDirect3DTexture9* aTexture);
|
||||
|
||||
|
@ -107,12 +107,6 @@ public:
|
||||
CompositableClient* aCompositable,
|
||||
TextureClient* aTexture) {}
|
||||
|
||||
/**
|
||||
* Tell the compositor side to delete the TextureHost corresponding to the
|
||||
* TextureClient passed in parameter.
|
||||
*/
|
||||
virtual void RemoveTexture(TextureClient* aTexture) = 0;
|
||||
|
||||
/**
|
||||
* Holds a reference to a TextureClient until after the next
|
||||
* compositor transaction, and then drops it.
|
||||
|
@ -198,7 +198,7 @@ static void ImageBridgeShutdownStep1(ReentrantMonitor *aBarrier, bool *aDone)
|
||||
for (int i = textures.Length() - 1; i >= 0; --i) {
|
||||
RefPtr<TextureClient> client = TextureClient::AsTextureClient(textures[i]);
|
||||
if (client) {
|
||||
client->ForceRemove();
|
||||
client->Destroy();
|
||||
}
|
||||
}
|
||||
sImageBridgeChildSingleton->SendWillStop();
|
||||
@ -766,7 +766,7 @@ bool InImageBridgeChildThread()
|
||||
|
||||
MessageLoop * ImageBridgeChild::GetMessageLoop() const
|
||||
{
|
||||
return sImageBridgeChildThread->message_loop();
|
||||
return sImageBridgeChildThread ? sImageBridgeChildThread->message_loop() : nullptr;
|
||||
}
|
||||
|
||||
void ImageBridgeChild::ConnectAsync(ImageBridgeParent* aParent)
|
||||
@ -1130,38 +1130,6 @@ ImageBridgeChild::RemoveTextureFromCompositableAsync(AsyncTransactionTracker* aA
|
||||
aAsyncTransactionTracker);
|
||||
}
|
||||
|
||||
static void RemoveTextureSync(TextureClient* aTexture, ReentrantMonitor* aBarrier, bool* aDone)
|
||||
{
|
||||
aTexture->ForceRemove();
|
||||
|
||||
ReentrantMonitorAutoEnter autoMon(*aBarrier);
|
||||
*aDone = true;
|
||||
aBarrier->NotifyAll();
|
||||
}
|
||||
|
||||
void ImageBridgeChild::RemoveTexture(TextureClient* aTexture)
|
||||
{
|
||||
if (InImageBridgeChildThread()) {
|
||||
MOZ_ASSERT(!mShuttingDown);
|
||||
aTexture->ForceRemove();
|
||||
return;
|
||||
}
|
||||
|
||||
ReentrantMonitor barrier("RemoveTexture Lock");
|
||||
ReentrantMonitorAutoEnter autoMon(barrier);
|
||||
bool done = false;
|
||||
|
||||
sImageBridgeChildSingleton->GetMessageLoop()->PostTask(
|
||||
FROM_HERE,
|
||||
NewRunnableFunction(&RemoveTextureSync, aTexture, &barrier, &done));
|
||||
|
||||
// should stop the thread until the ImageClient has been created on
|
||||
// the other thread
|
||||
while (!done) {
|
||||
barrier.Wait();
|
||||
}
|
||||
}
|
||||
|
||||
bool ImageBridgeChild::IsSameProcess() const
|
||||
{
|
||||
return OtherPid() == base::GetCurrentProcId();
|
||||
|
@ -259,8 +259,6 @@ public:
|
||||
CompositableClient* aCompositable,
|
||||
TextureClient* aTexture) override;
|
||||
|
||||
virtual void RemoveTexture(TextureClient* aTexture) override;
|
||||
|
||||
virtual void UseTiledLayerBuffer(CompositableClient* aCompositable,
|
||||
const SurfaceDescriptorTiles& aTileLayerDescriptor) override
|
||||
{
|
||||
|
@ -40,7 +40,7 @@ LayerTransactionChild::Destroy()
|
||||
for (auto iter = textures.ConstIter(); !iter.Done(); iter.Next()) {
|
||||
TextureClient* texture = TextureClient::AsTextureClient(iter.Get()->GetKey());
|
||||
if (texture) {
|
||||
texture->ForceRemove();
|
||||
texture->Destroy();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -470,38 +470,6 @@ ShadowLayerForwarder::InWorkerThread()
|
||||
return MessageLoop::current() && (GetMessageLoop()->id() == MessageLoop::current()->id());
|
||||
}
|
||||
|
||||
static void RemoveTextureWorker(TextureClient* aTexture, ReentrantMonitor* aBarrier, bool* aDone)
|
||||
{
|
||||
aTexture->ForceRemove();
|
||||
|
||||
ReentrantMonitorAutoEnter autoMon(*aBarrier);
|
||||
*aDone = true;
|
||||
aBarrier->NotifyAll();
|
||||
}
|
||||
|
||||
void
|
||||
ShadowLayerForwarder::RemoveTexture(TextureClient* aTexture)
|
||||
{
|
||||
MOZ_ASSERT(aTexture);
|
||||
if (InWorkerThread()) {
|
||||
aTexture->ForceRemove();
|
||||
return;
|
||||
}
|
||||
|
||||
ReentrantMonitor barrier("ShadowLayerForwarder::RemoveTexture Lock");
|
||||
ReentrantMonitorAutoEnter autoMon(barrier);
|
||||
bool done = false;
|
||||
|
||||
GetMessageLoop()->PostTask(
|
||||
FROM_HERE,
|
||||
NewRunnableFunction(&RemoveTextureWorker, aTexture, &barrier, &done));
|
||||
|
||||
// Wait until the TextureClient has been ForceRemoved on the worker thread
|
||||
while (!done) {
|
||||
barrier.Wait();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ShadowLayerForwarder::StorePluginWidgetConfigurations(const nsTArray<nsIWidget::Configuration>&
|
||||
aConfigurations)
|
||||
|
@ -221,8 +221,6 @@ public:
|
||||
CompositableClient* aCompositable,
|
||||
TextureClient* aTexture) override;
|
||||
|
||||
virtual void RemoveTexture(TextureClient* aTexture) override;
|
||||
|
||||
/**
|
||||
* Communicate to the compositor that aRegion in the texture identified by aLayer
|
||||
* and aIdentifier has been updated to aThebesBuffer.
|
||||
|
@ -118,7 +118,11 @@ GrallocTextureData::~GrallocTextureData()
|
||||
void
|
||||
GrallocTextureData::Deallocate(ISurfaceAllocator* aAllocator)
|
||||
{
|
||||
MOZ_ASSERT(aAllocator);
|
||||
if (aAllocator) {
|
||||
aAllocator->DeallocGrallocBuffer(&mGrallocHandle);
|
||||
}
|
||||
|
||||
mGrallocHandle = null_t();
|
||||
mGraphicBuffer = nullptr;
|
||||
}
|
||||
@ -126,7 +130,11 @@ GrallocTextureData::Deallocate(ISurfaceAllocator* aAllocator)
|
||||
void
|
||||
GrallocTextureData::Forget(ISurfaceAllocator* aAllocator)
|
||||
{
|
||||
MOZ_ASSERT(aAllocator);
|
||||
if (aAllocator) {
|
||||
aAllocator->DropGrallocBuffer(&mGrallocHandle);
|
||||
}
|
||||
|
||||
mGrallocHandle = null_t();
|
||||
mGraphicBuffer = nullptr;
|
||||
}
|
||||
@ -142,7 +150,7 @@ void
|
||||
GrallocTextureData::WaitForFence(FenceHandle* aFence)
|
||||
{
|
||||
#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION < 21 && ANDROID_VERSION >= 17
|
||||
if (aFence->IsValid()) {
|
||||
if (aFence && aFence->IsValid()) {
|
||||
RefPtr<FenceHandle::FdObj> fdObj = aFence->GetAndResetFdObj();
|
||||
android::sp<Fence> fence = new Fence(fdObj->GetAndResetFd());
|
||||
#if ANDROID_VERSION == 17
|
||||
@ -161,8 +169,6 @@ GrallocTextureData::Lock(OpenMode aMode, FenceHandle* aReleaseFence)
|
||||
{
|
||||
MOZ_ASSERT(!mMappedBuffer);
|
||||
|
||||
WaitForFence(aReleaseFence);
|
||||
|
||||
uint32_t usage = 0;
|
||||
if (aMode & OpenMode::OPEN_READ) {
|
||||
usage |= GRALLOC_USAGE_SW_READ_OFTEN;
|
||||
@ -170,20 +176,30 @@ GrallocTextureData::Lock(OpenMode aMode, FenceHandle* aReleaseFence)
|
||||
if (aMode & OpenMode::OPEN_WRITE) {
|
||||
usage |= GRALLOC_USAGE_SW_WRITE_OFTEN;
|
||||
}
|
||||
|
||||
void** mappedBufferPtr = reinterpret_cast<void**>(&mMappedBuffer);
|
||||
|
||||
int32_t rv = 0;
|
||||
#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 21
|
||||
if (aReleaseFence) {
|
||||
RefPtr<FenceHandle::FdObj> fdObj = aReleaseFence->GetAndResetFdObj();
|
||||
int32_t rv = mGraphicBuffer->lockAsync(usage,
|
||||
reinterpret_cast<void**>(&mMappedBuffer),
|
||||
rv = mGraphicBuffer->lockAsync(usage, mappedBufferPtr,
|
||||
fdObj->GetAndResetFd());
|
||||
} else {
|
||||
rv = mGraphicBuffer->lock(usage, mappedBufferPtr);
|
||||
}
|
||||
#else
|
||||
int32_t rv = mGraphicBuffer->lock(usage,
|
||||
reinterpret_cast<void**>(&mMappedBuffer));
|
||||
// older versions of android don't have lockAsync
|
||||
WaitForFence(aReleaseFence);
|
||||
rv = mGraphicBuffer->lock(usage, mappedBufferPtr);
|
||||
#endif
|
||||
|
||||
if (rv) {
|
||||
mMappedBuffer = nullptr;
|
||||
NS_WARNING("Couldn't lock graphic buffer");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -271,6 +287,9 @@ GrallocTextureData::Create(gfx::IntSize aSize, AndroidFormat aAndroidFormat,
|
||||
gfx::BackendType aMoz2dBackend, uint32_t aUsage,
|
||||
ISurfaceAllocator* aAllocator)
|
||||
{
|
||||
if (!aAllocator) {
|
||||
return nullptr;
|
||||
}
|
||||
int32_t maxSize = aAllocator->GetMaxTextureSize();
|
||||
if (aSize.width > maxSize || aSize.height > maxSize) {
|
||||
return nullptr;
|
||||
@ -346,23 +365,16 @@ GrallocTextureData::CreateForDrawing(gfx::IntSize aSize, gfx::SurfaceFormat aFor
|
||||
return data;
|
||||
}
|
||||
|
||||
already_AddRefed<TextureClient>
|
||||
CreateGrallocTextureClientForDrawing(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
|
||||
gfx::BackendType aMoz2dBackend,
|
||||
TextureFlags aFlags,
|
||||
ISurfaceAllocator* aAllocator)
|
||||
TextureFlags
|
||||
GrallocTextureData::GetTextureFlags() const
|
||||
{
|
||||
TextureData* data = GrallocTextureData::CreateForDrawing(aSize, aFormat, aMoz2dBackend,
|
||||
aAllocator);
|
||||
if (!data) {
|
||||
return nullptr;
|
||||
if (IsGrallocRBSwapped(mFormat)) {
|
||||
return TextureFlags::RB_SWAPPED;
|
||||
}
|
||||
if (IsGrallocRBSwapped(aFormat)) {
|
||||
aFlags |= TextureFlags::RB_SWAPPED;
|
||||
}
|
||||
return MakeAndAddRef<TextureClient>(data, aFlags, aAllocator);
|
||||
return TextureFlags::NO_FLAGS;
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
GrallocTextureData*
|
||||
GrallocTextureData::CreateForYCbCr(gfx::IntSize aYSize, gfx::IntSize aCbCrSize,
|
||||
|
@ -107,6 +107,8 @@ public:
|
||||
|
||||
~GrallocTextureData();
|
||||
|
||||
virtual TextureFlags GetTextureFlags() const override;
|
||||
|
||||
protected:
|
||||
GrallocTextureData(MaybeMagicGrallocBufferHandle aGrallocHandle,
|
||||
gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
|
||||
@ -128,10 +130,6 @@ protected:
|
||||
|
||||
gfx::SurfaceFormat SurfaceFormatForPixelFormat(android::PixelFormat aFormat);
|
||||
|
||||
already_AddRefed<TextureClient> CreateGrallocTextureClientForDrawing(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
|
||||
gfx::BackendType aMoz2dBackend, TextureFlags aFlags,
|
||||
ISurfaceAllocator* aAllocator);
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
||||
|
@ -18,14 +18,6 @@ MacIOSurfaceTextureData::MacIOSurfaceTextureData(MacIOSurface* aSurface)
|
||||
MacIOSurfaceTextureData::~MacIOSurfaceTextureData()
|
||||
{}
|
||||
|
||||
void
|
||||
MacIOSurfaceTextureData::FinalizeOnIPDLThread(TextureClient* aWrapper)
|
||||
{
|
||||
if (mSurface) {
|
||||
aWrapper->KeepUntilFullDeallocation(MakeUnique<TKeepAlive<MacIOSurface>>(mSurface));
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
MacIOSurfaceTextureData*
|
||||
MacIOSurfaceTextureData::Create(MacIOSurface* aSurface)
|
||||
|
@ -42,8 +42,6 @@ public:
|
||||
protected:
|
||||
explicit MacIOSurfaceTextureData(MacIOSurface* aSurface);
|
||||
|
||||
virtual void FinalizeOnIPDLThread(TextureClient* aWrapper) override;
|
||||
|
||||
RefPtr<MacIOSurface> mSurface;
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user