Bug 1250500 - Avoid copying BufferTextureHost when possible. r=sotaro

This commit is contained in:
Nicolas Silva 2016-02-25 14:15:52 +01:00
Родитель 2b9dadff72
Коммит 9e20942d69
12 изменённых файлов: 139 добавлений и 9 удалений

Просмотреть файл

@ -6,10 +6,15 @@
#include "BufferTexture.h"
#include "mozilla/layers/ImageDataSerializer.h"
#include "mozilla/layers/ISurfaceAllocator.h"
#include "mozilla/layers/CompositableForwarder.h"
#include "mozilla/gfx/Logging.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/fallible.h"
#ifdef MOZ_WIDGET_GTK
#include "gfxPlatformGtk.h"
#endif
namespace mozilla {
namespace layers {
@ -83,6 +88,24 @@ protected:
mozilla::ipc::Shmem mShmem;
};
static bool UsingX11Compositor()
{
#ifdef MOZ_WIDGET_GTK
return gfxPlatformGtk::GetPlatform()->UseXRender();
#endif
return false;
}
static bool ComputeHasIntermediateBuffer(gfx::SurfaceFormat aFormat,
LayersBackend aLayersBackend)
{
return aLayersBackend != LayersBackend::LAYERS_BASIC
|| UsingX11Compositor()
|| aFormat == gfx::SurfaceFormat::UNKNOWN
|| aFormat == gfx::SurfaceFormat::YUV
|| aFormat == gfx::SurfaceFormat::NV12;
}
BufferTextureData*
BufferTextureData::Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
gfx::BackendType aMoz2DBackend, TextureFlags aFlags,
@ -90,9 +113,11 @@ BufferTextureData::Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
ISurfaceAllocator* aAllocator)
{
if (!aAllocator || aAllocator->IsSameProcess()) {
return MemoryTextureData::Create(aSize, aFormat, aMoz2DBackend, aFlags, aAllocFlags, aAllocator);
return MemoryTextureData::Create(aSize, aFormat, aMoz2DBackend, aFlags,
aAllocFlags, aAllocator);
} else {
return ShmemTextureData::Create(aSize, aFormat, aMoz2DBackend, aFlags, aAllocFlags, aAllocator);
return ShmemTextureData::Create(aSize, aFormat, aMoz2DBackend, aFlags,
aAllocFlags, aAllocator);
}
}
@ -179,6 +204,16 @@ BufferTextureData::GetFormat() const
return ImageDataSerializer::FormatFromBufferDescriptor(mDescriptor);
}
bool
BufferTextureData::HasInternalBuffer() const
{
if (mDescriptor.type() == BufferDescriptor::TYCbCrDescriptor) {
return true;
}
return mDescriptor.get_RGBDescriptor().hasInternalBuffer();
}
bool
BufferTextureData::SupportsMoz2D() const
{
@ -385,7 +420,7 @@ MemoryTextureData*
MemoryTextureData::Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
gfx::BackendType aMoz2DBackend, TextureFlags aFlags,
TextureAllocationFlags aAllocFlags,
ISurfaceAllocator*)
ISurfaceAllocator* aAllocator)
{
// Should have used CreateForYCbCr.
MOZ_ASSERT(aFormat != gfx::SurfaceFormat::YUV);
@ -405,9 +440,14 @@ MemoryTextureData::Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
return nullptr;
}
auto fwd = aAllocator ? aAllocator->AsCompositableForwarder() : nullptr;
bool hasInternalBuffer = fwd ? ComputeHasIntermediateBuffer(aFormat,
fwd->GetCompositorBackendType())
: true;
GfxMemoryImageReporter::DidAlloc(buf);
BufferDescriptor descriptor = RGBDescriptor(aSize, aFormat);
BufferDescriptor descriptor = RGBDescriptor(aSize, aFormat, hasInternalBuffer);
return new MemoryTextureData(descriptor, aMoz2DBackend, buf, bufSize);
}
@ -477,7 +517,12 @@ ShmemTextureData::Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
return nullptr;
}
BufferDescriptor descriptor = RGBDescriptor(aSize, aFormat);
auto fwd = aAllocator->AsCompositableForwarder();
bool hasInternalBuffer = fwd ? ComputeHasIntermediateBuffer(aFormat,
fwd->GetCompositorBackendType())
: true;
BufferDescriptor descriptor = RGBDescriptor(aSize, aFormat, hasInternalBuffer);
return new ShmemTextureData(descriptor, aMoz2DBackend, shm);

Просмотреть файл

@ -55,7 +55,7 @@ public:
virtual bool SupportsMoz2D() const override;
virtual bool HasInternalBuffer() const override { return true; }
virtual bool HasInternalBuffer() const override;
// use TextureClient's default implementation
virtual bool UpdateFromSurface(gfx::SourceSurface* aSurface) override;

Просмотреть файл

@ -112,6 +112,7 @@ namespace mozilla {
namespace gfx {
class Matrix;
class DrawTarget;
class DataSourceSurface;
} // namespace gfx
namespace layers {
@ -192,6 +193,10 @@ public:
}
virtual already_AddRefed<DataTextureSource> CreateDataTextureSource(TextureFlags aFlags = TextureFlags::NO_FLAGS) = 0;
virtual already_AddRefed<DataTextureSource>
CreateDataTextureSourceAround(gfx::DataSourceSurface* aSurface) { return nullptr; }
virtual bool Initialize() = 0;
virtual void Destroy() = 0;

Просмотреть файл

@ -36,6 +36,18 @@ class DataTextureSourceBasic : public DataTextureSource
public:
virtual const char* Name() const override { return "DataTextureSourceBasic"; }
explicit DataTextureSourceBasic(DataSourceSurface* aSurface)
: mSurface(aSurface)
, mWrappingExistingData(!!aSurface)
{}
virtual DataTextureSource* AsDataTextureSource() override
{
// If the texture wraps someone else's memory we'd rather not use it as
// a DataTextureSource per say (that is call Update on it).
return mWrappingExistingData ? nullptr : this;
}
virtual TextureSourceBasic* AsSourceBasic() override { return this; }
virtual gfx::SourceSurface* GetSurface(DrawTarget* aTarget) override { return mSurface; }
@ -54,6 +66,10 @@ public:
nsIntRegion* aDestRegion = nullptr,
gfx::IntPoint* aSrcOffset = nullptr) override
{
MOZ_ASSERT(!mWrappingExistingData);
if (mWrappingExistingData) {
return false;
}
mSurface = aSurface;
return true;
}
@ -66,6 +82,7 @@ public:
public:
RefPtr<gfx::DataSourceSurface> mSurface;
bool mWrappingExistingData;
};
BasicCompositor::BasicCompositor(nsIWidget *aWidget)
@ -182,7 +199,14 @@ BasicCompositor::CreateRenderTargetForWindow(const IntRect& aRect, SurfaceInitMo
already_AddRefed<DataTextureSource>
BasicCompositor::CreateDataTextureSource(TextureFlags aFlags)
{
RefPtr<DataTextureSource> result = new DataTextureSourceBasic();
RefPtr<DataTextureSource> result = new DataTextureSourceBasic(nullptr);
return result.forget();
}
already_AddRefed<DataTextureSource>
BasicCompositor::CreateDataTextureSourceAround(DataSourceSurface* aSurface)
{
RefPtr<DataTextureSource> result = new DataTextureSourceBasic(aSurface);
return result.forget();
}

Просмотреть файл

@ -70,6 +70,9 @@ public:
virtual already_AddRefed<DataTextureSource>
CreateDataTextureSource(TextureFlags aFlags = TextureFlags::NO_FLAGS) override;
virtual already_AddRefed<DataTextureSource>
CreateDataTextureSourceAround(gfx::DataSourceSurface* aSurface) override;
virtual bool SupportsEffect(EffectTypes aEffect) override;
virtual void SetRenderTarget(CompositingRenderTarget *aSource) override

Просмотреть файл

@ -52,6 +52,9 @@ public:
virtual already_AddRefed<DataTextureSource>
CreateDataTextureSource(TextureFlags aFlags = TextureFlags::NO_FLAGS) override;
virtual already_AddRefed<DataTextureSource>
CreateDataTextureSourceAround(gfx::DataSourceSurface* aSurface) override { return nullptr; }
virtual void EndFrame() override;
};

Просмотреть файл

@ -395,12 +395,14 @@ BufferTextureHost::BufferTextureHost(const BufferDescriptor& aDesc,
const YCbCrDescriptor& ycbcr = mDescriptor.get_YCbCrDescriptor();
mSize = ycbcr.ySize();
mFormat = gfx::SurfaceFormat::YUV;
mHasInternalBuffer = true;
break;
}
case BufferDescriptor::TRGBDescriptor: {
const RGBDescriptor& rgb = mDescriptor.get_RGBDescriptor();
mSize = rgb.size();
mFormat = rgb.format();
mHasInternalBuffer = rgb.hasInternalBuffer();
break;
}
default: MOZ_CRASH();
@ -491,9 +493,42 @@ BufferTextureHost::Unlock()
mLocked = false;
}
bool
BufferTextureHost::EnsureWrappingTextureSource()
{
MOZ_ASSERT(!mHasInternalBuffer);
MOZ_ASSERT(mFormat != gfx::SurfaceFormat::YUV);
if (mFirstSource) {
return true;
}
if (!mCompositor) {
return false;
}
RefPtr<gfx::DataSourceSurface> surf =
gfx::Factory::CreateWrappingDataSourceSurface(GetBuffer(),
ImageDataSerializer::ComputeRGBStride(mFormat, mSize.width), mSize, mFormat);
if (!surf) {
return false;
}
mFirstSource = mCompositor->CreateDataTextureSourceAround(surf);
mFirstSource->SetUpdateSerial(mUpdateSerial);
mFirstSource->SetOwner(this);
return true;
}
void
BufferTextureHost::PrepareTextureSource(CompositableTextureSourceRef& aTexture)
{
if (!mHasInternalBuffer) {
EnsureWrappingTextureSource();
}
if (mFirstSource && mFirstSource->IsOwnedBy(this)) {
// We are already attached to a TextureSource, nothing to do except tell
// the compositable to use it.
@ -594,6 +629,10 @@ BufferTextureHost::Upload(nsIntRegion *aRegion)
// attached to a layer.
return false;
}
if (!mHasInternalBuffer && EnsureWrappingTextureSource()) {
return true;
}
if (mFormat == gfx::SurfaceFormat::UNKNOWN) {
NS_WARNING("BufferTextureHost: unsupported format!");
return false;

Просмотреть файл

@ -630,11 +630,12 @@ public:
virtual already_AddRefed<gfx::DataSourceSurface> GetAsSurface() override;
virtual bool HasInternalBuffer() const override { return true; }
virtual bool HasInternalBuffer() const override { return mHasInternalBuffer; }
protected:
bool Upload(nsIntRegion *aRegion = nullptr);
bool MaybeUpload(nsIntRegion *aRegion = nullptr);
bool EnsureWrappingTextureSource();
virtual void UpdatedInternal(const nsIntRegion* aRegion = nullptr) override;
@ -647,6 +648,7 @@ protected:
uint32_t mUpdateSerial;
bool mLocked;
bool mNeedsFullUpdate;
bool mHasInternalBuffer;
};
/**

Просмотреть файл

@ -172,6 +172,8 @@ public:
SyncObject* GetSyncObject() { return mSyncObject; }
virtual CompositableForwarder* AsCompositableForwarder() override { return this; }
protected:
TextureFactoryIdentifier mTextureFactoryIdentifier;
nsTArray<RefPtr<TextureClient> > mTexturesToRemove;

Просмотреть файл

@ -147,7 +147,11 @@ ISurfaceAllocator::AllocSurfaceDescriptorWithCaps(const gfx::IntSize& aSize,
bufferDesc = shmem;
}
*aBuffer = SurfaceDescriptorBuffer(RGBDescriptor(aSize, format), bufferDesc);
// Use an intermediate buffer by default. Skipping the intermediate buffer is
// only possible in certain configurations so let's keep it simple here for now.
const bool hasIntermediateBuffer = true;
*aBuffer = SurfaceDescriptorBuffer(RGBDescriptor(aSize, format, hasIntermediateBuffer),
bufferDesc);
return true;
}

Просмотреть файл

@ -41,6 +41,7 @@ class DataSourceSurface;
namespace layers {
class MaybeMagicGrallocBufferHandle;
class CompositableForwarder;
enum BufferCapabilities {
DEFAULT_BUFFER_CAPS = 0,
@ -160,6 +161,7 @@ public:
// Returns true if aSurface wraps a Shmem.
static bool IsShmem(SurfaceDescriptor* aSurface);
virtual CompositableForwarder* AsCompositableForwarder() { return nullptr; }
protected:
virtual bool IsOnCompositorSide() const = 0;

Просмотреть файл

@ -101,6 +101,7 @@ struct SurfaceDescriptorGralloc {
struct RGBDescriptor {
IntSize size;
SurfaceFormat format;
bool hasInternalBuffer;
};
struct YCbCrDescriptor {