Bug 1280839 - Recycle SharedPlanarYCbCrImage r=nical

This commit is contained in:
Sotaro Ikeda 2016-06-29 19:12:31 -07:00
parent 43c4cb86a4
commit 774306bc97
12 changed files with 173 additions and 46 deletions

View File

@ -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
{

View File

@ -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;

View File

@ -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();

View File

@ -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();

View File

@ -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);

View File

@ -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;
}

View File

@ -230,6 +230,8 @@ public:
TextureClientRecycleAllocator* GetTextureClientRecycler();
bool HasTextureClientRecycler() { return !!mTextureClientRecycler; }
static void DumpTextureClient(std::stringstream& aStream,
TextureClient* aTexture,
TextureDumpMode aCompress);

View File

@ -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();
}
}

View File

@ -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;

View File

@ -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());
}
}

View File

@ -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

View File

@ -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;