already_AddRefed<TextureClient> TextureClientRecycleAllocator::CreateOrRecycle(ITextureClientAllocationHelper& aHelper) { // TextureAllocationFlags is actually used only by ContentClient. // This class does not handle ContentClient's TextureClient allocation. MOZ_ASSERT(aHelper.mAllocationFlags == TextureAllocationFlags::ALLOC_DEFAULT || aHelper.mAllocationFlags == TextureAllocationFlags::ALLOC_DISALLOW_BUFFERTEXTURECLIENT || 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(); textureHolder = nullptr; mSurfaceAllocator->GetMessageLoop()->PostTask(task.forget()); } else { textureHolder->GetTextureClient()->RecycleTexture(aHelper.mTextureFlags); } } } if (!textureHolder) { // Allocate new TextureClient RefPtr<TextureClient> texture = aHelper.Allocate(mSurfaceAllocator); if (!texture) { return nullptr; } textureHolder = new TextureClientHolder(texture); } { MutexAutoLock lock(mLock); MOZ_ASSERT(mInUseClients.find(textureHolder->GetTextureClient()) == mInUseClients.end()); // Register TextureClient mInUseClients[textureHolder->GetTextureClient()] = textureHolder; } RefPtr<TextureClient> client(textureHolder->GetTextureClient()); // Make sure the texture holds a reference to us, and ask it to call RecycleTextureClient when its // ref count drops to 1. client->SetRecycleAllocator(this); return client.forget(); }
already_AddRefed<TextureClient> TextureClientRecycleAllocator::CreateOrRecycle(ITextureClientAllocationHelper& aHelper) { 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 the texture's allocator is not open or a pooled TextureClient is // not compatible, release it. if (!textureHolder->GetTextureClient()->GetAllocator()->IPCOpen() || !aHelper.IsCompatible(textureHolder->GetTextureClient())) { // Release TextureClient. RefPtr<Runnable> task = new TextureClientReleaseTask(textureHolder->GetTextureClient()); textureHolder->ClearTextureClient(); textureHolder = nullptr; mSurfaceAllocator->GetTextureForwarder()->GetMessageLoop()->PostTask(task.forget()); } else { textureHolder->GetTextureClient()->RecycleTexture(aHelper.mTextureFlags); } } } if (!textureHolder) { // Allocate new TextureClient RefPtr<TextureClient> texture = aHelper.Allocate(mSurfaceAllocator); if (!texture) { return nullptr; } textureHolder = new TextureClientHolder(texture); } { MutexAutoLock lock(mLock); MOZ_ASSERT(mInUseClients.find(textureHolder->GetTextureClient()) == mInUseClients.end()); // Register TextureClient mInUseClients[textureHolder->GetTextureClient()] = textureHolder; } RefPtr<TextureClient> client(textureHolder->GetTextureClient()); // Make sure the texture holds a reference to us, and ask it to call RecycleTextureClient when its // ref count drops to 1. client->SetRecycleAllocator(this); return client.forget(); }