mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-06 07:48:38 +09:00
import FIREFOX_52_6_0esr_RELEASE from mozilla-esr52 hg repo
This commit is contained in:
commit
dcd9973243
150858 changed files with 23884658 additions and 0 deletions
279
gfx/layers/client/TextureClientRecycleAllocator.cpp
Normal file
279
gfx/layers/client/TextureClientRecycleAllocator.cpp
Normal file
|
|
@ -0,0 +1,279 @@
|
|||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "gfxPlatform.h"
|
||||
#include "ImageContainer.h"
|
||||
#include "mozilla/layers/BufferTexture.h"
|
||||
#include "mozilla/layers/ISurfaceAllocator.h"
|
||||
#include "mozilla/layers/TextureForwarder.h"
|
||||
#include "TextureClientRecycleAllocator.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
// Used to keep TextureClient's reference count stable as not to disrupt recycling.
|
||||
class TextureClientHolder
|
||||
{
|
||||
~TextureClientHolder() {}
|
||||
public:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TextureClientHolder)
|
||||
|
||||
explicit TextureClientHolder(TextureClient* aClient)
|
||||
: mTextureClient(aClient)
|
||||
, mWillRecycle(true)
|
||||
{}
|
||||
|
||||
TextureClient* GetTextureClient()
|
||||
{
|
||||
return mTextureClient;
|
||||
}
|
||||
|
||||
bool WillRecycle()
|
||||
{
|
||||
return mWillRecycle;
|
||||
}
|
||||
|
||||
void ClearWillRecycle()
|
||||
{
|
||||
mWillRecycle = false;
|
||||
}
|
||||
|
||||
void ClearTextureClient() { mTextureClient = nullptr; }
|
||||
protected:
|
||||
RefPtr<TextureClient> mTextureClient;
|
||||
bool mWillRecycle;
|
||||
};
|
||||
|
||||
class DefaultTextureClientAllocationHelper : public ITextureClientAllocationHelper
|
||||
{
|
||||
public:
|
||||
DefaultTextureClientAllocationHelper(TextureClientRecycleAllocator* aAllocator,
|
||||
gfx::SurfaceFormat aFormat,
|
||||
gfx::IntSize aSize,
|
||||
BackendSelector aSelector,
|
||||
TextureFlags aTextureFlags,
|
||||
TextureAllocationFlags aAllocationFlags)
|
||||
: ITextureClientAllocationHelper(aFormat,
|
||||
aSize,
|
||||
aSelector,
|
||||
aTextureFlags,
|
||||
aAllocationFlags)
|
||||
, mAllocator(aAllocator)
|
||||
{}
|
||||
|
||||
bool IsCompatible(TextureClient* aTextureClient) override
|
||||
{
|
||||
if (aTextureClient->GetFormat() != mFormat ||
|
||||
aTextureClient->GetSize() != mSize) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
already_AddRefed<TextureClient> Allocate(KnowsCompositor* aAllocator) override
|
||||
{
|
||||
return mAllocator->Allocate(mFormat,
|
||||
mSize,
|
||||
mSelector,
|
||||
mTextureFlags,
|
||||
mAllocationFlags);
|
||||
}
|
||||
|
||||
protected:
|
||||
TextureClientRecycleAllocator* mAllocator;
|
||||
};
|
||||
|
||||
YCbCrTextureClientAllocationHelper::YCbCrTextureClientAllocationHelper(const PlanarYCbCrData& aData,
|
||||
TextureFlags aTextureFlags)
|
||||
: ITextureClientAllocationHelper(gfx::SurfaceFormat::YUV,
|
||||
aData.mYSize,
|
||||
BackendSelector::Content,
|
||||
aTextureFlags,
|
||||
ALLOC_DEFAULT)
|
||||
, mData(aData)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
YCbCrTextureClientAllocationHelper::IsCompatible(TextureClient* aTextureClient)
|
||||
{
|
||||
MOZ_ASSERT(aTextureClient->GetFormat() == gfx::SurfaceFormat::YUV);
|
||||
|
||||
BufferTextureData* bufferData = aTextureClient->GetInternalData()->AsBufferTextureData();
|
||||
if (!bufferData ||
|
||||
aTextureClient->GetSize() != mData.mYSize ||
|
||||
bufferData->GetCbCrSize().isNothing() ||
|
||||
bufferData->GetCbCrSize().ref() != mData.mCbCrSize ||
|
||||
bufferData->GetYUVColorSpace().isNothing() ||
|
||||
bufferData->GetYUVColorSpace().ref() != mData.mYUVColorSpace ||
|
||||
bufferData->GetStereoMode().isNothing() ||
|
||||
bufferData->GetStereoMode().ref() != mData.mStereoMode) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
already_AddRefed<TextureClient>
|
||||
YCbCrTextureClientAllocationHelper::Allocate(KnowsCompositor* aAllocator)
|
||||
{
|
||||
return TextureClient::CreateForYCbCr(aAllocator,
|
||||
mData.mYSize, mData.mCbCrSize,
|
||||
mData.mStereoMode,
|
||||
mData.mYUVColorSpace,
|
||||
mTextureFlags);
|
||||
}
|
||||
|
||||
TextureClientRecycleAllocator::TextureClientRecycleAllocator(KnowsCompositor* aAllocator)
|
||||
: mSurfaceAllocator(aAllocator)
|
||||
, mMaxPooledSize(kMaxPooledSized)
|
||||
, mLock("TextureClientRecycleAllocatorImp.mLock")
|
||||
, mIsDestroyed(false)
|
||||
{
|
||||
}
|
||||
|
||||
TextureClientRecycleAllocator::~TextureClientRecycleAllocator()
|
||||
{
|
||||
MutexAutoLock lock(mLock);
|
||||
while (!mPooledClients.empty()) {
|
||||
mPooledClients.pop();
|
||||
}
|
||||
MOZ_ASSERT(mInUseClients.empty());
|
||||
}
|
||||
|
||||
void
|
||||
TextureClientRecycleAllocator::SetMaxPoolSize(uint32_t aMax)
|
||||
{
|
||||
mMaxPooledSize = aMax;
|
||||
}
|
||||
|
||||
already_AddRefed<TextureClient>
|
||||
TextureClientRecycleAllocator::CreateOrRecycle(gfx::SurfaceFormat aFormat,
|
||||
gfx::IntSize aSize,
|
||||
BackendSelector aSelector,
|
||||
TextureFlags aTextureFlags,
|
||||
TextureAllocationFlags aAllocFlags)
|
||||
{
|
||||
MOZ_ASSERT(!(aTextureFlags & TextureFlags::RECYCLE));
|
||||
DefaultTextureClientAllocationHelper helper(this,
|
||||
aFormat,
|
||||
aSize,
|
||||
aSelector,
|
||||
aTextureFlags,
|
||||
aAllocFlags);
|
||||
return CreateOrRecycle(helper);
|
||||
}
|
||||
|
||||
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 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->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();
|
||||
}
|
||||
|
||||
already_AddRefed<TextureClient>
|
||||
TextureClientRecycleAllocator::Allocate(gfx::SurfaceFormat aFormat,
|
||||
gfx::IntSize aSize,
|
||||
BackendSelector aSelector,
|
||||
TextureFlags aTextureFlags,
|
||||
TextureAllocationFlags aAllocFlags)
|
||||
{
|
||||
return TextureClient::CreateForDrawing(mSurfaceAllocator, aFormat, aSize,
|
||||
aSelector, aTextureFlags, aAllocFlags);
|
||||
}
|
||||
|
||||
void
|
||||
TextureClientRecycleAllocator::ShrinkToMinimumSize()
|
||||
{
|
||||
MutexAutoLock lock(mLock);
|
||||
while (!mPooledClients.empty()) {
|
||||
mPooledClients.pop();
|
||||
}
|
||||
// We can not clear using TextureClients safely.
|
||||
// Just clear WillRecycle here.
|
||||
std::map<TextureClient*, RefPtr<TextureClientHolder> >::iterator it;
|
||||
for (it = mInUseClients.begin(); it != mInUseClients.end(); it++) {
|
||||
RefPtr<TextureClientHolder> holder = it->second;
|
||||
holder->ClearWillRecycle();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TextureClientRecycleAllocator::Destroy()
|
||||
{
|
||||
MutexAutoLock lock(mLock);
|
||||
while (!mPooledClients.empty()) {
|
||||
mPooledClients.pop();
|
||||
}
|
||||
mIsDestroyed = true;
|
||||
}
|
||||
|
||||
void
|
||||
TextureClientRecycleAllocator::RecycleTextureClient(TextureClient* aClient)
|
||||
{
|
||||
// Clearing the recycle allocator drops a reference, so make sure we stay alive
|
||||
// for the duration of this function.
|
||||
RefPtr<TextureClientRecycleAllocator> kungFuDeathGrip(this);
|
||||
aClient->SetRecycleAllocator(nullptr);
|
||||
|
||||
RefPtr<TextureClientHolder> textureHolder;
|
||||
{
|
||||
MutexAutoLock lock(mLock);
|
||||
if (mInUseClients.find(aClient) != mInUseClients.end()) {
|
||||
textureHolder = mInUseClients[aClient]; // Keep reference count of TextureClientHolder within lock.
|
||||
if (textureHolder->WillRecycle() &&
|
||||
!mIsDestroyed && mPooledClients.size() < mMaxPooledSize) {
|
||||
mPooledClients.push(textureHolder);
|
||||
}
|
||||
mInUseClients.erase(aClient);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
Loading…
Add table
Add a link
Reference in a new issue