mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 05:41:12 +00:00
Bug 1280839 - Recycle SharedPlanarYCbCrImage r=nical
This commit is contained in:
parent
43c4cb86a4
commit
774306bc97
@ -226,6 +226,18 @@ BufferTextureData::GetSize() const
|
||||
return ImageDataSerializer::SizeFromBufferDescriptor(mDescriptor);
|
||||
}
|
||||
|
||||
Maybe<gfx::IntSize>
|
||||
BufferTextureData::GetCbCrSize() const
|
||||
{
|
||||
return ImageDataSerializer::CbCrSizeFromBufferDescriptor(mDescriptor);
|
||||
}
|
||||
|
||||
Maybe<StereoMode>
|
||||
BufferTextureData::GetStereoMode() const
|
||||
{
|
||||
return ImageDataSerializer::StereoModeFromBufferDescriptor(mDescriptor);
|
||||
}
|
||||
|
||||
gfx::SurfaceFormat
|
||||
BufferTextureData::GetFormat() const
|
||||
{
|
||||
|
@ -52,9 +52,15 @@ public:
|
||||
// use TextureClient's default implementation
|
||||
virtual bool UpdateFromSurface(gfx::SourceSurface* aSurface) override;
|
||||
|
||||
virtual BufferTextureData* AsBufferTextureData() override { return this; }
|
||||
|
||||
// Don't use this.
|
||||
void SetDesciptor(const BufferDescriptor& aDesc);
|
||||
|
||||
Maybe<gfx::IntSize> GetCbCrSize() const;
|
||||
|
||||
Maybe<StereoMode> GetStereoMode() const;
|
||||
|
||||
protected:
|
||||
gfx::IntSize GetSize() const;
|
||||
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "mozilla/layers/LayersMessages.h"
|
||||
#include "mozilla/layers/SharedPlanarYCbCrImage.h"
|
||||
#include "mozilla/layers/SharedRGBImage.h"
|
||||
#include "mozilla/layers/TextureClientRecycleAllocator.h"
|
||||
#include "nsISupportsUtils.h" // for NS_IF_ADDREF
|
||||
#include "YCbCrUtils.h" // for YCbCr conversions
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
@ -356,6 +357,10 @@ ImageContainer::ClearCachedResources()
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
||||
if (mImageClient && mImageClient->AsImageClientSingle()) {
|
||||
if (!mImageClient->HasTextureClientRecycler()) {
|
||||
return;
|
||||
}
|
||||
mImageClient->GetTextureClientRecycler()->ShrinkToMinimumSize();
|
||||
return;
|
||||
}
|
||||
return mRecycleBin->ClearRecycledBuffers();
|
||||
|
@ -128,6 +128,30 @@ gfx::IntSize SizeFromBufferDescriptor(const BufferDescriptor& aDescriptor)
|
||||
}
|
||||
}
|
||||
|
||||
Maybe<gfx::IntSize> CbCrSizeFromBufferDescriptor(const BufferDescriptor& aDescriptor)
|
||||
{
|
||||
switch (aDescriptor.type()) {
|
||||
case BufferDescriptor::TRGBDescriptor:
|
||||
return Nothing();
|
||||
case BufferDescriptor::TYCbCrDescriptor:
|
||||
return Some(aDescriptor.get_YCbCrDescriptor().cbCrSize());
|
||||
default:
|
||||
MOZ_CRASH("GFX: CbCrSizeFromBufferDescriptor");
|
||||
}
|
||||
}
|
||||
|
||||
Maybe<StereoMode> StereoModeFromBufferDescriptor(const BufferDescriptor& aDescriptor)
|
||||
{
|
||||
switch (aDescriptor.type()) {
|
||||
case BufferDescriptor::TRGBDescriptor:
|
||||
return Nothing();
|
||||
case BufferDescriptor::TYCbCrDescriptor:
|
||||
return Some(aDescriptor.get_YCbCrDescriptor().stereoMode());
|
||||
default:
|
||||
MOZ_CRASH("GFX: CbCrSizeFromBufferDescriptor");
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t* GetYChannel(uint8_t* aBuffer, const YCbCrDescriptor& aDescriptor)
|
||||
{
|
||||
return aBuffer + aDescriptor.yOffset();
|
||||
|
@ -58,6 +58,10 @@ gfx::SurfaceFormat FormatFromBufferDescriptor(const BufferDescriptor& aDescripto
|
||||
|
||||
gfx::IntSize SizeFromBufferDescriptor(const BufferDescriptor& aDescriptor);
|
||||
|
||||
Maybe<gfx::IntSize> CbCrSizeFromBufferDescriptor(const BufferDescriptor& aDescriptor);
|
||||
|
||||
Maybe<StereoMode> StereoModeFromBufferDescriptor(const BufferDescriptor& aDescriptor);
|
||||
|
||||
uint8_t* GetYChannel(uint8_t* aBuffer, const YCbCrDescriptor& aDescriptor);
|
||||
|
||||
uint8_t* GetCbChannel(uint8_t* aBuffer, const YCbCrDescriptor& aDescriptor);
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include <stdint.h> // for uint64_t, uint32_t
|
||||
#include "gfxPlatform.h" // for gfxPlatform
|
||||
#include "mozilla/layers/CompositableForwarder.h"
|
||||
#include "mozilla/layers/ImageBridgeChild.h"
|
||||
#include "mozilla/layers/TextureClient.h" // for TextureClient, etc
|
||||
#include "mozilla/layers/TextureClientOGL.h"
|
||||
#include "mozilla/mozalloc.h" // for operator delete, etc
|
||||
@ -246,8 +247,40 @@ CompositableClient::GetTextureClientRecycler()
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
mTextureClientRecycler =
|
||||
new layers::TextureClientRecycleAllocator(mForwarder);
|
||||
if(!mForwarder->UsesImageBridge()) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
mTextureClientRecycler = new layers::TextureClientRecycleAllocator(mForwarder);
|
||||
return mTextureClientRecycler;
|
||||
}
|
||||
|
||||
// Handle a case that mForwarder is ImageBridge
|
||||
|
||||
if (InImageBridgeChildThread()) {
|
||||
mTextureClientRecycler = new layers::TextureClientRecycleAllocator(mForwarder);
|
||||
return mTextureClientRecycler;
|
||||
}
|
||||
|
||||
ReentrantMonitor barrier("CompositableClient::GetTextureClientRecycler");
|
||||
ReentrantMonitorAutoEnter mainThreadAutoMon(barrier);
|
||||
bool done = false;
|
||||
|
||||
RefPtr<Runnable> runnable =
|
||||
NS_NewRunnableFunction([&]() {
|
||||
if (!mTextureClientRecycler) {
|
||||
mTextureClientRecycler = new layers::TextureClientRecycleAllocator(mForwarder);
|
||||
}
|
||||
ReentrantMonitorAutoEnter childThreadAutoMon(barrier);
|
||||
done = true;
|
||||
barrier.NotifyAll();
|
||||
});
|
||||
|
||||
ImageBridgeChild::GetSingleton()->GetMessageLoop()->PostTask(runnable.forget());
|
||||
|
||||
// should stop the thread until done.
|
||||
while (!done) {
|
||||
barrier.Wait();
|
||||
}
|
||||
|
||||
return mTextureClientRecycler;
|
||||
}
|
||||
|
||||
|
@ -230,6 +230,8 @@ public:
|
||||
|
||||
TextureClientRecycleAllocator* GetTextureClientRecycler();
|
||||
|
||||
bool HasTextureClientRecycler() { return !!mTextureClientRecycler; }
|
||||
|
||||
static void DumpTextureClient(std::stringstream& aStream,
|
||||
TextureClient* aTexture,
|
||||
TextureDumpMode aCompress);
|
||||
|
@ -729,9 +729,6 @@ TextureClient::AddFlags(TextureFlags aFlags)
|
||||
MOZ_ASSERT(!IsSharedWithCompositor() ||
|
||||
((GetFlags() & TextureFlags::RECYCLE) && !IsAddedToCompositableClient()));
|
||||
mFlags |= aFlags;
|
||||
if (IsValid() && mActor && !mActor->mDestroyed && mActor->IPCOpen()) {
|
||||
mActor->SendRecycleTexture(mFlags);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -740,9 +737,6 @@ TextureClient::RemoveFlags(TextureFlags aFlags)
|
||||
MOZ_ASSERT(!IsSharedWithCompositor() ||
|
||||
((GetFlags() & TextureFlags::RECYCLE) && !IsAddedToCompositableClient()));
|
||||
mFlags &= ~aFlags;
|
||||
if (IsValid() && mActor && !mActor->mDestroyed && mActor->IPCOpen()) {
|
||||
mActor->SendRecycleTexture(mFlags);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -750,21 +744,11 @@ TextureClient::RecycleTexture(TextureFlags aFlags)
|
||||
{
|
||||
MOZ_ASSERT(GetFlags() & TextureFlags::RECYCLE);
|
||||
MOZ_ASSERT(!mIsLocked);
|
||||
if (mIsLocked) {
|
||||
return;
|
||||
}
|
||||
|
||||
LockActor();
|
||||
|
||||
mAddedToCompositableClient = false;
|
||||
if (mFlags != aFlags) {
|
||||
mFlags = aFlags;
|
||||
if (IsValid() && mActor && !mActor->mDestroyed && mActor->IPCOpen()) {
|
||||
mActor->SendRecycleTexture(mFlags);
|
||||
}
|
||||
}
|
||||
|
||||
UnlockActor();
|
||||
}
|
||||
|
||||
void
|
||||
@ -772,6 +756,15 @@ TextureClient::SetAddedToCompositableClient()
|
||||
{
|
||||
if (!mAddedToCompositableClient) {
|
||||
mAddedToCompositableClient = true;
|
||||
if(!(GetFlags() & TextureFlags::RECYCLE)) {
|
||||
return;
|
||||
}
|
||||
MOZ_ASSERT(!mIsLocked);
|
||||
LockActor();
|
||||
if (IsValid() && mActor && !mActor->mDestroyed && mActor->IPCOpen()) {
|
||||
mActor->SendRecycleTexture(mFlags);
|
||||
}
|
||||
UnlockActor();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -48,6 +48,7 @@ class SharedSurface_Gralloc;
|
||||
namespace layers {
|
||||
|
||||
class AsyncTransactionWaiter;
|
||||
class BufferTextureData;
|
||||
class CompositableForwarder;
|
||||
class GrallocTextureData;
|
||||
class ClientIPCAllocator;
|
||||
@ -299,6 +300,8 @@ public:
|
||||
#endif
|
||||
|
||||
virtual GrallocTextureData* AsGrallocTextureData() { return nullptr; }
|
||||
|
||||
virtual BufferTextureData* AsBufferTextureData() { return nullptr; }
|
||||
};
|
||||
|
||||
/**
|
||||
@ -515,7 +518,7 @@ public:
|
||||
|
||||
void RemoveFlags(TextureFlags aFlags);
|
||||
|
||||
// The TextureClient must not be locked when calling this method.
|
||||
// Must not be called when TextureClient is in use by CompositableClient.
|
||||
void RecycleTexture(TextureFlags aFlags);
|
||||
|
||||
/**
|
||||
@ -732,7 +735,9 @@ protected:
|
||||
// behalf of the compositor just before sending the notification.
|
||||
bool mUpdated;
|
||||
|
||||
// Used when TextureClient is recycled with TextureFlags::RECYCLE flag.
|
||||
bool mAddedToCompositableClient;
|
||||
|
||||
bool mWorkaroundAnnoyingSharedSurfaceLifetimeIssues;
|
||||
bool mWorkaroundAnnoyingSharedSurfaceOwnershipIssues;
|
||||
|
||||
|
@ -4,6 +4,8 @@
|
||||
* 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/CompositableForwarder.h"
|
||||
#include "TextureClientRecycleAllocator.h"
|
||||
@ -71,6 +73,43 @@ 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->GetStereoMode().isNothing() ||
|
||||
bufferData->GetStereoMode().ref() != mData.mStereoMode) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
already_AddRefed<TextureClient>
|
||||
YCbCrTextureClientAllocationHelper::Allocate(CompositableForwarder* aAllocator)
|
||||
{
|
||||
return TextureClient::CreateForYCbCr(aAllocator,
|
||||
mData.mYSize, mData.mCbCrSize,
|
||||
mData.mStereoMode,
|
||||
mTextureFlags);
|
||||
}
|
||||
|
||||
TextureClientRecycleAllocator::TextureClientRecycleAllocator(CompositableForwarder* aAllocator)
|
||||
: mSurfaceAllocator(aAllocator)
|
||||
, mMaxPooledSize(kMaxPooledSized)
|
||||
@ -93,25 +132,6 @@ TextureClientRecycleAllocator::SetMaxPoolSize(uint32_t aMax)
|
||||
mMaxPooledSize = aMax;
|
||||
}
|
||||
|
||||
class TextureClientRecycleTask : public Runnable
|
||||
{
|
||||
public:
|
||||
explicit TextureClientRecycleTask(TextureClient* aClient, TextureFlags aFlags)
|
||||
: mTextureClient(aClient)
|
||||
, mFlags(aFlags)
|
||||
{}
|
||||
|
||||
NS_IMETHOD Run() override
|
||||
{
|
||||
mTextureClient->RecycleTexture(mFlags);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
RefPtr<TextureClient> mTextureClient;
|
||||
TextureFlags mFlags;
|
||||
};
|
||||
|
||||
already_AddRefed<TextureClient>
|
||||
TextureClientRecycleAllocator::CreateOrRecycle(gfx::SurfaceFormat aFormat,
|
||||
gfx::IntSize aSize,
|
||||
@ -147,17 +167,16 @@ TextureClientRecycleAllocator::CreateOrRecycle(ITextureClientAllocationHelper& a
|
||||
if (!mPooledClients.empty()) {
|
||||
textureHolder = mPooledClients.top();
|
||||
mPooledClients.pop();
|
||||
RefPtr<Runnable> task;
|
||||
// If a pooled TextureClient is not compatible, release it.
|
||||
if (!aHelper.IsCompatible(textureHolder->GetTextureClient())) {
|
||||
// Release TextureClient.
|
||||
task = new TextureClientReleaseTask(textureHolder->GetTextureClient());
|
||||
RefPtr<Runnable> task = new TextureClientReleaseTask(textureHolder->GetTextureClient());
|
||||
textureHolder->ClearTextureClient();
|
||||
textureHolder = nullptr;
|
||||
mSurfaceAllocator->GetMessageLoop()->PostTask(task.forget());
|
||||
} else {
|
||||
task = new TextureClientRecycleTask(textureHolder->GetTextureClient(), aHelper.mTextureFlags);
|
||||
textureHolder->GetTextureClient()->RecycleTexture(aHelper.mTextureFlags);
|
||||
}
|
||||
mSurfaceAllocator->GetMessageLoop()->PostTask(task.forget());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -18,6 +18,7 @@ namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
class TextureClientHolder;
|
||||
struct PlanarYCbCrData;
|
||||
|
||||
class ITextureClientRecycleAllocator
|
||||
{
|
||||
@ -57,6 +58,21 @@ public:
|
||||
const TextureAllocationFlags mAllocationFlags;
|
||||
};
|
||||
|
||||
class YCbCrTextureClientAllocationHelper : public ITextureClientAllocationHelper
|
||||
{
|
||||
public:
|
||||
YCbCrTextureClientAllocationHelper(const PlanarYCbCrData& aData,
|
||||
TextureFlags aTextureFlags);
|
||||
|
||||
bool IsCompatible(TextureClient* aTextureClient) override;
|
||||
|
||||
already_AddRefed<TextureClient> Allocate(CompositableForwarder* aAllocator) override;
|
||||
|
||||
protected:
|
||||
const PlanarYCbCrData& mData;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* TextureClientRecycleAllocator provides TextureClients allocation and
|
||||
* recycling capabilities. It expects allocations of same sizes and
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "mozilla/layers/ImageClient.h" // for ImageClient
|
||||
#include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor, etc
|
||||
#include "mozilla/layers/TextureClient.h"
|
||||
#include "mozilla/layers/TextureClientRecycleAllocator.h"
|
||||
#include "mozilla/layers/BufferTexture.h"
|
||||
#include "mozilla/layers/ImageDataSerializer.h"
|
||||
#include "mozilla/layers/ImageBridgeChild.h" // for ImageBridgeChild
|
||||
@ -176,11 +177,18 @@ SharedPlanarYCbCrImage::Allocate(PlanarYCbCrData& aData)
|
||||
{
|
||||
MOZ_ASSERT(!mTextureClient,
|
||||
"This image already has allocated data");
|
||||
static const uint32_t MAX_POOLED_VIDEO_COUNT = 5;
|
||||
|
||||
if (!mCompositable->HasTextureClientRecycler()) {
|
||||
// Initialize TextureClientRecycler
|
||||
mCompositable->GetTextureClientRecycler()->SetMaxPoolSize(MAX_POOLED_VIDEO_COUNT);
|
||||
}
|
||||
|
||||
{
|
||||
YCbCrTextureClientAllocationHelper helper(aData, mCompositable->GetTextureFlags());
|
||||
mTextureClient = mCompositable->GetTextureClientRecycler()->CreateOrRecycle(helper);
|
||||
}
|
||||
|
||||
mTextureClient = TextureClient::CreateForYCbCr(mCompositable->GetForwarder(),
|
||||
aData.mYSize, aData.mCbCrSize,
|
||||
aData.mStereoMode,
|
||||
mCompositable->GetTextureFlags());
|
||||
if (!mTextureClient) {
|
||||
NS_WARNING("SharedPlanarYCbCrImage::Allocate failed.");
|
||||
return false;
|
||||
|
Loading…
Reference in New Issue
Block a user