зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1200595 - Buffer TextureData implementation. r=mattwoodrow
This commit is contained in:
Родитель
62fdc49f48
Коммит
71d9215e93
|
@ -11,6 +11,7 @@
|
|||
#include "GLReadTexImageHelper.h"
|
||||
#include "GLScreenBuffer.h"
|
||||
#include "mozilla/dom/HTMLCanvasElement.h"
|
||||
#include "mozilla/layers/BufferTexture.h"
|
||||
#include "mozilla/layers/CanvasClient.h"
|
||||
#include "mozilla/layers/TextureClient.h"
|
||||
#include "mozilla/layers/TextureClientSharedSurface.h"
|
||||
|
@ -147,8 +148,8 @@ void
|
|||
AsyncCanvasRenderer::CopyFromTextureClient(TextureClient* aTextureClient)
|
||||
{
|
||||
MutexAutoLock lock(mMutex);
|
||||
RefPtr<BufferTextureClient> buffer = static_cast<BufferTextureClient*>(aTextureClient);
|
||||
if (!buffer->Lock(layers::OpenMode::OPEN_READ)) {
|
||||
TextureClientAutoLock texLock(aTextureClient, layers::OpenMode::OPEN_READ);
|
||||
if (texLock.Succeeded()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -165,16 +166,20 @@ AsyncCanvasRenderer::CopyFromTextureClient(TextureClient* aTextureClient)
|
|||
mSurfaceForBasic = gfx::Factory::CreateDataSourceSurfaceWithStride(size, format, stride);
|
||||
}
|
||||
|
||||
const uint8_t* lockedBytes = buffer->GetLockedData();
|
||||
gfx::DataSourceSurface::ScopedMap map(mSurfaceForBasic,
|
||||
gfx::DataSourceSurface::MapType::WRITE);
|
||||
if (!map.IsMapped()) {
|
||||
buffer->Unlock();
|
||||
MappedTextureData mapped;
|
||||
if (!aTextureClient->BorrowMappedData(mapped)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const uint8_t* lockedBytes = mapped.data;
|
||||
gfx::DataSourceSurface::ScopedMap map(mSurfaceForBasic,
|
||||
gfx::DataSourceSurface::MapType::WRITE);
|
||||
if (!map.IsMapped()) {
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(map.GetStride() == mapped.stride);
|
||||
memcpy(map.GetData(), lockedBytes, map.GetStride() * mSurfaceForBasic->GetSize().height);
|
||||
buffer->Unlock();
|
||||
|
||||
if (mSurfaceForBasic->GetFormat() == gfx::SurfaceFormat::R8G8B8A8 ||
|
||||
mSurfaceForBasic->GetFormat() == gfx::SurfaceFormat::R8G8B8X8) {
|
||||
|
|
|
@ -0,0 +1,449 @@
|
|||
/* -*- 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 "BufferTexture.h"
|
||||
#include "mozilla/layers/ImageDataSerializer.h"
|
||||
#include "mozilla/layers/ISurfaceAllocator.h"
|
||||
#include "mozilla/gfx/Logging.h"
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include "mozilla/fallible.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
class MemoryTextureData : public BufferTextureData
|
||||
{
|
||||
public:
|
||||
static MemoryTextureData* Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
|
||||
gfx::BackendType aMoz2DBackend,TextureFlags aFlags,
|
||||
TextureAllocationFlags aAllocFlags,
|
||||
ISurfaceAllocator* aAllocator);
|
||||
|
||||
virtual TextureData*
|
||||
CreateSimilar(ISurfaceAllocator* aAllocator,
|
||||
TextureFlags aFlags = TextureFlags::DEFAULT,
|
||||
TextureAllocationFlags aAllocFlags = ALLOC_DEFAULT) const override;
|
||||
|
||||
virtual bool Serialize(SurfaceDescriptor& aOutDescriptor) override;
|
||||
|
||||
virtual void Deallocate(ISurfaceAllocator*) override;
|
||||
|
||||
MemoryTextureData(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
|
||||
gfx::BackendType aMoz2DBackend,
|
||||
uint8_t* aBuffer, size_t aBufferSize)
|
||||
: BufferTextureData(aSize, aFormat, aMoz2DBackend)
|
||||
, mBuffer(aBuffer)
|
||||
, mBufferSize(aBufferSize)
|
||||
{
|
||||
MOZ_ASSERT(aBuffer);
|
||||
MOZ_ASSERT(aBufferSize);
|
||||
}
|
||||
|
||||
virtual uint8_t* GetBuffer() override { return mBuffer; }
|
||||
|
||||
virtual size_t GetBufferSize() override { return mBufferSize; }
|
||||
|
||||
protected:
|
||||
uint8_t* mBuffer;
|
||||
size_t mBufferSize;
|
||||
};
|
||||
|
||||
class ShmemTextureData : public BufferTextureData
|
||||
{
|
||||
public:
|
||||
static ShmemTextureData* Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
|
||||
gfx::BackendType aMoz2DBackend, TextureFlags aFlags,
|
||||
TextureAllocationFlags aAllocFlags,
|
||||
ISurfaceAllocator* aAllocator);
|
||||
|
||||
virtual TextureData*
|
||||
CreateSimilar(ISurfaceAllocator* aAllocator,
|
||||
TextureFlags aFlags = TextureFlags::DEFAULT,
|
||||
TextureAllocationFlags aAllocFlags = ALLOC_DEFAULT) const override;
|
||||
|
||||
virtual bool Serialize(SurfaceDescriptor& aOutDescriptor) override;
|
||||
|
||||
virtual void Deallocate(ISurfaceAllocator* aAllocator) override;
|
||||
|
||||
ShmemTextureData(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
|
||||
gfx::BackendType aMoz2DBackend, mozilla::ipc::Shmem aShmem)
|
||||
: BufferTextureData(aSize, aFormat, aMoz2DBackend)
|
||||
, mShmem(aShmem)
|
||||
{
|
||||
MOZ_ASSERT(mShmem.Size<uint8_t>());
|
||||
}
|
||||
|
||||
virtual uint8_t* GetBuffer() override { return mShmem.get<uint8_t>(); }
|
||||
|
||||
virtual size_t GetBufferSize() override { return mShmem.Size<uint8_t>(); }
|
||||
|
||||
protected:
|
||||
mozilla::ipc::Shmem mShmem;
|
||||
};
|
||||
|
||||
BufferTextureData*
|
||||
BufferTextureData::Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
|
||||
gfx::BackendType aMoz2DBackend, TextureFlags aFlags,
|
||||
TextureAllocationFlags aAllocFlags,
|
||||
ISurfaceAllocator* aAllocator)
|
||||
{
|
||||
if (!aAllocator || aAllocator->IsSameProcess()) {
|
||||
return MemoryTextureData::Create(aSize, aFormat, aMoz2DBackend, aFlags, aAllocFlags, aAllocator);
|
||||
} else {
|
||||
return ShmemTextureData::Create(aSize, aFormat, aMoz2DBackend, aFlags, aAllocFlags, aAllocator);
|
||||
}
|
||||
}
|
||||
|
||||
BufferTextureData*
|
||||
BufferTextureData::CreateWithBufferSize(ISurfaceAllocator* aAllocator,
|
||||
gfx::SurfaceFormat aFormat,
|
||||
size_t aSize,
|
||||
TextureFlags aTextureFlags)
|
||||
{
|
||||
if (aSize == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
BufferTextureData* data;
|
||||
if (!aAllocator || aAllocator->IsSameProcess()) {
|
||||
uint8_t* buffer = new (fallible) uint8_t[aSize];
|
||||
if (!buffer) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
data = new MemoryTextureData(gfx::IntSize(), aFormat, gfx::BackendType::NONE, buffer, aSize);
|
||||
} else {
|
||||
ipc::Shmem shm;
|
||||
if (!aAllocator->AllocUnsafeShmem(aSize, OptimalShmemType(), &shm)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
data = new ShmemTextureData(gfx::IntSize(), aFormat, gfx::BackendType::NONE, shm);
|
||||
}
|
||||
|
||||
// Initialize the metadata with something, even if it will have to be rewritten
|
||||
// afterwards since we don't know the dimensions of the texture at this point.
|
||||
if (aFormat == gfx::SurfaceFormat::YUV) {
|
||||
YCbCrImageDataSerializer serializer(data->GetBuffer(), data->GetBufferSize());
|
||||
serializer.InitializeBufferInfo(gfx::IntSize(0,0), gfx::IntSize(0,0), StereoMode::MONO);
|
||||
} else {
|
||||
ImageDataSerializer serializer(data->GetBuffer(), data->GetBufferSize());
|
||||
serializer.InitializeBufferInfo(gfx::IntSize(0, 0), aFormat);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
BufferTextureData*
|
||||
BufferTextureData::CreateForYCbCr(ISurfaceAllocator* aAllocator,
|
||||
gfx::IntSize aYSize,
|
||||
gfx::IntSize aCbCrSize,
|
||||
StereoMode aStereoMode,
|
||||
TextureFlags aTextureFlags)
|
||||
{
|
||||
size_t bufSize = YCbCrImageDataSerializer::ComputeMinBufferSize(aYSize, aCbCrSize);
|
||||
BufferTextureData* texture = CreateWithBufferSize(aAllocator, gfx::SurfaceFormat::YUV,
|
||||
bufSize, aTextureFlags);
|
||||
if (!texture) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
YCbCrImageDataSerializer serializer(texture->GetBuffer(), texture->GetBufferSize());
|
||||
serializer.InitializeBufferInfo(aYSize, aCbCrSize, aStereoMode);
|
||||
texture->mSize = aYSize;
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
bool
|
||||
BufferTextureData::SupportsMoz2D() const
|
||||
{
|
||||
switch (mFormat) {
|
||||
case gfx::SurfaceFormat::YUV:
|
||||
case gfx::SurfaceFormat::NV12:
|
||||
case gfx::SurfaceFormat::UNKNOWN:
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
already_AddRefed<gfx::DrawTarget>
|
||||
BufferTextureData::BorrowDrawTarget()
|
||||
{
|
||||
if (mDrawTarget) {
|
||||
mDrawTarget->SetTransform(gfx::Matrix());
|
||||
RefPtr<gfx::DrawTarget> dt = mDrawTarget;
|
||||
return dt.forget();
|
||||
}
|
||||
|
||||
ImageDataSerializer serializer(GetBuffer(), GetBufferSize());
|
||||
if (!serializer.IsValid()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
mDrawTarget = serializer.GetAsDrawTarget(mMoz2DBackend);
|
||||
if (mDrawTarget) {
|
||||
RefPtr<gfx::DrawTarget> dt = mDrawTarget;
|
||||
return dt.forget();
|
||||
}
|
||||
|
||||
// TODO - should we warn? should we really fallback to cairo? perhaps
|
||||
// at least update mMoz2DBackend...
|
||||
mDrawTarget = serializer.GetAsDrawTarget(gfx::BackendType::CAIRO);
|
||||
if (!mDrawTarget) {
|
||||
gfxCriticalNote << "BorrowDrawTarget failure, original backend " << (int)mMoz2DBackend;
|
||||
}
|
||||
|
||||
RefPtr<gfx::DrawTarget> dt = mDrawTarget;
|
||||
return dt.forget();
|
||||
}
|
||||
|
||||
bool
|
||||
BufferTextureData::BorrowMappedData(MappedTextureData& aData)
|
||||
{
|
||||
if (mFormat == gfx::SurfaceFormat::YUV) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ImageDataDeserializer view(GetBuffer(), GetBufferSize());
|
||||
if (!view.IsValid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
aData.data = view.GetData();
|
||||
aData.size = view.GetSize();
|
||||
aData.stride = view.GetStride();
|
||||
aData.format = mFormat;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BufferTextureData::BorrowMappedYCbCrData(MappedYCbCrTextureData& aMap)
|
||||
{
|
||||
if (mFormat != gfx::SurfaceFormat::YUV) {
|
||||
return false;
|
||||
}
|
||||
|
||||
YCbCrImageDataDeserializer view(GetBuffer(), GetBufferSize());
|
||||
if (!view.IsValid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
aMap.stereoMode = view.GetStereoMode();
|
||||
aMap.metadata = GetBuffer();
|
||||
|
||||
aMap.y.data = view.GetYData();
|
||||
aMap.y.size = view.GetYSize();
|
||||
aMap.y.stride = view.GetYStride();
|
||||
aMap.y.skip = 0;
|
||||
|
||||
aMap.cb.data = view.GetCbData();
|
||||
aMap.cb.size = view.GetCbCrSize();
|
||||
aMap.cb.stride = view.GetCbCrStride();
|
||||
aMap.cb.skip = 0;
|
||||
|
||||
aMap.cr.data = view.GetCrData();
|
||||
aMap.cr.size = view.GetCbCrSize();
|
||||
aMap.cr.stride = view.GetCbCrStride();
|
||||
aMap.cr.skip = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BufferTextureData::UpdateFromSurface(gfx::SourceSurface* aSurface)
|
||||
{
|
||||
ImageDataSerializer serializer(GetBuffer(), GetBufferSize());
|
||||
|
||||
RefPtr<gfx::DataSourceSurface> surface = serializer.GetAsSurface();
|
||||
|
||||
if (!surface) {
|
||||
gfxCriticalError() << "Failed to get serializer as surface!";
|
||||
return false;
|
||||
}
|
||||
|
||||
RefPtr<gfx::DataSourceSurface> srcSurf = aSurface->GetDataSurface();
|
||||
|
||||
if (!srcSurf) {
|
||||
gfxCriticalError() << "Failed to GetDataSurface in UpdateFromSurface.";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (surface->GetSize() != srcSurf->GetSize() || surface->GetFormat() != srcSurf->GetFormat()) {
|
||||
gfxCriticalError() << "Attempt to update texture client from a surface with a different size or format! This: " << surface->GetSize() << " " << surface->GetFormat() << " Other: " << aSurface->GetSize() << " " << aSurface->GetFormat();
|
||||
return false;
|
||||
}
|
||||
|
||||
gfx::DataSourceSurface::MappedSurface sourceMap;
|
||||
gfx::DataSourceSurface::MappedSurface destMap;
|
||||
if (!srcSurf->Map(gfx::DataSourceSurface::READ, &sourceMap)) {
|
||||
gfxCriticalError() << "Failed to map source surface for UpdateFromSurface.";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!surface->Map(gfx::DataSourceSurface::WRITE, &destMap)) {
|
||||
srcSurf->Unmap();
|
||||
gfxCriticalError() << "Failed to map destination surface for UpdateFromSurface.";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
for (int y = 0; y < srcSurf->GetSize().height; y++) {
|
||||
memcpy(destMap.mData + destMap.mStride * y,
|
||||
sourceMap.mData + sourceMap.mStride * y,
|
||||
srcSurf->GetSize().width * BytesPerPixel(srcSurf->GetFormat()));
|
||||
}
|
||||
|
||||
srcSurf->Unmap();
|
||||
surface->Unmap();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
MemoryTextureData::Serialize(SurfaceDescriptor& aOutDescriptor)
|
||||
{
|
||||
MOZ_ASSERT(GetFormat() != gfx::SurfaceFormat::UNKNOWN);
|
||||
if (GetFormat() == gfx::SurfaceFormat::UNKNOWN) {
|
||||
return false;
|
||||
}
|
||||
|
||||
aOutDescriptor = SurfaceDescriptorMemory(reinterpret_cast<uintptr_t>(mBuffer),
|
||||
GetFormat());
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool InitBuffer(uint8_t* buf, size_t bufSize,
|
||||
gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
|
||||
TextureAllocationFlags aAllocFlags)
|
||||
{
|
||||
if (!buf) {
|
||||
gfxDebug() << "BufferTextureData: Failed to allocate " << bufSize << " bytes";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (aAllocFlags & ALLOC_CLEAR_BUFFER) {
|
||||
memset(buf, 0, bufSize);
|
||||
}
|
||||
if (aAllocFlags & ALLOC_CLEAR_BUFFER_WHITE) {
|
||||
memset(buf, 0xFF, bufSize);
|
||||
}
|
||||
|
||||
ImageDataSerializer serializer(buf, bufSize);
|
||||
serializer.InitializeBufferInfo(aSize, aFormat);
|
||||
return true;
|
||||
}
|
||||
|
||||
MemoryTextureData*
|
||||
MemoryTextureData::Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
|
||||
gfx::BackendType aMoz2DBackend, TextureFlags aFlags,
|
||||
TextureAllocationFlags aAllocFlags,
|
||||
ISurfaceAllocator*)
|
||||
{
|
||||
if (aSize.width <= 0 || aSize.height <= 0) {
|
||||
gfxDebug() << "Asking for buffer of invalid size " << aSize.width << "x" << aSize.height;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint32_t bufSize = ImageDataSerializer::ComputeMinBufferSize(aSize, aFormat);
|
||||
if (!bufSize) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint8_t* buf = new (fallible) uint8_t[bufSize];
|
||||
|
||||
if (InitBuffer(buf, bufSize, aSize, aFormat, aAllocFlags)) {
|
||||
GfxMemoryImageReporter::DidAlloc(buf);
|
||||
return new MemoryTextureData(aSize, aFormat, aMoz2DBackend, buf, bufSize);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
MemoryTextureData::Deallocate(ISurfaceAllocator*)
|
||||
{
|
||||
MOZ_ASSERT(mBuffer);
|
||||
GfxMemoryImageReporter::WillFree(mBuffer);
|
||||
delete [] mBuffer;
|
||||
mBuffer = nullptr;
|
||||
}
|
||||
|
||||
TextureData*
|
||||
MemoryTextureData::CreateSimilar(ISurfaceAllocator* aAllocator,
|
||||
TextureFlags aFlags,
|
||||
TextureAllocationFlags aAllocFlags) const
|
||||
{
|
||||
return MemoryTextureData::Create(mSize, mFormat, mMoz2DBackend,
|
||||
aFlags, aAllocFlags, aAllocator);
|
||||
}
|
||||
|
||||
bool
|
||||
ShmemTextureData::Serialize(SurfaceDescriptor& aOutDescriptor)
|
||||
{
|
||||
MOZ_ASSERT(GetFormat() != gfx::SurfaceFormat::UNKNOWN);
|
||||
if (GetFormat() == gfx::SurfaceFormat::UNKNOWN) {
|
||||
return false;
|
||||
}
|
||||
|
||||
aOutDescriptor = SurfaceDescriptorShmem(mShmem, GetFormat());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
ShmemTextureData*
|
||||
ShmemTextureData::Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
|
||||
gfx::BackendType aMoz2DBackend, TextureFlags aFlags,
|
||||
TextureAllocationFlags aAllocFlags,
|
||||
ISurfaceAllocator* aAllocator)
|
||||
{
|
||||
MOZ_ASSERT(aAllocator);
|
||||
if (!aAllocator) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (aSize.width <= 0 || aSize.height <= 0) {
|
||||
gfxDebug() << "Asking for buffer of invalid size " << aSize.width << "x" << aSize.height;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint32_t bufSize = ImageDataSerializer::ComputeMinBufferSize(aSize, aFormat);
|
||||
if (!bufSize) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
mozilla::ipc::Shmem shm;
|
||||
if (!aAllocator->AllocUnsafeShmem(bufSize, OptimalShmemType(), &shm)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint8_t* buf = shm.get<uint8_t>();
|
||||
|
||||
if (InitBuffer(buf, bufSize, aSize, aFormat, aAllocFlags)) {
|
||||
return new ShmemTextureData(aSize, aFormat, aMoz2DBackend, shm);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
TextureData*
|
||||
ShmemTextureData::CreateSimilar(ISurfaceAllocator* aAllocator,
|
||||
TextureFlags aFlags,
|
||||
TextureAllocationFlags aAllocFlags) const
|
||||
{
|
||||
return ShmemTextureData::Create(mSize, mFormat, mMoz2DBackend,
|
||||
aFlags, aAllocFlags, aAllocator);
|
||||
}
|
||||
|
||||
void
|
||||
ShmemTextureData::Deallocate(ISurfaceAllocator* aAllocator)
|
||||
{
|
||||
aAllocator->DeallocShmem(mShmem);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
|
@ -0,0 +1,81 @@
|
|||
/* -*- 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/. */
|
||||
|
||||
#ifndef MOZILLA_LAYERS_BUFFERETEXTURE
|
||||
#define MOZILLA_LAYERS_BUFFERETEXTURE
|
||||
|
||||
#include "mozilla/layers/ImageDataSerializer.h"
|
||||
#include "mozilla/layers/YCbCrImageDataSerializer.h"
|
||||
#include "mozilla/layers/TextureClient.h"
|
||||
#include "mozilla/ipc/SharedMemory.h"
|
||||
#include "mozilla/gfx/Types.h"
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
class BufferTextureData : public TextureData
|
||||
{
|
||||
public:
|
||||
static BufferTextureData* Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
|
||||
gfx::BackendType aMoz2DBackend,TextureFlags aFlags,
|
||||
TextureAllocationFlags aAllocFlags,
|
||||
ISurfaceAllocator* aAllocator);
|
||||
|
||||
static BufferTextureData* CreateWithBufferSize(ISurfaceAllocator* aAllocator,
|
||||
gfx::SurfaceFormat aFormat,
|
||||
size_t aSize,
|
||||
TextureFlags aTextureFlags);
|
||||
|
||||
static BufferTextureData* CreateForYCbCr(ISurfaceAllocator* aAllocator,
|
||||
gfx::IntSize aYSize,
|
||||
gfx::IntSize aCbCrSize,
|
||||
StereoMode aStereoMode,
|
||||
TextureFlags aTextureFlags);
|
||||
|
||||
virtual bool Lock(OpenMode aMode) override { return true; }
|
||||
|
||||
virtual void Unlock() override {}
|
||||
|
||||
virtual gfx::IntSize GetSize() const override { return mSize; }
|
||||
|
||||
virtual gfx::SurfaceFormat GetFormat() const override { return mFormat; }
|
||||
|
||||
virtual already_AddRefed<gfx::DrawTarget> BorrowDrawTarget() override;
|
||||
|
||||
virtual bool CanExposeMappedData() const override { return true; }
|
||||
|
||||
virtual bool BorrowMappedData(MappedTextureData& aMap) override;
|
||||
|
||||
virtual bool BorrowMappedYCbCrData(MappedYCbCrTextureData& aMap) override;
|
||||
|
||||
virtual bool SupportsMoz2D() const override;
|
||||
|
||||
virtual bool HasInternalBuffer() const override { return true; }
|
||||
|
||||
// use ClientTexture's default implementation
|
||||
virtual bool UpdateFromSurface(gfx::SourceSurface* aSurface) override;
|
||||
|
||||
protected:
|
||||
virtual uint8_t* GetBuffer() = 0;
|
||||
virtual size_t GetBufferSize() = 0;
|
||||
|
||||
BufferTextureData(gfx::IntSize aSize, gfx::SurfaceFormat aFormat, gfx::BackendType aMoz2DBackend)
|
||||
: mSize(aSize)
|
||||
, mFormat(aFormat)
|
||||
, mMoz2DBackend(aMoz2DBackend)
|
||||
{}
|
||||
|
||||
RefPtr<gfx::DrawTarget> mDrawTarget;
|
||||
gfx::IntSize mSize;
|
||||
gfx::SurfaceFormat mFormat;
|
||||
gfx::BackendType mMoz2DBackend;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
#endif
|
|
@ -39,6 +39,8 @@ public:
|
|||
static uint32_t ComputeMinBufferSize(gfx::IntSize aSize,
|
||||
gfx::SurfaceFormat aFormat);
|
||||
|
||||
size_t GetBufferSize() const { return mDataSize; }
|
||||
|
||||
protected:
|
||||
|
||||
ImageDataSerializerBase(uint8_t* aData, size_t aDataSize)
|
||||
|
|
|
@ -75,7 +75,7 @@ void YCbCrImageDataDeserializerBase::Validate()
|
|||
info->mYStride,
|
||||
IntSize(info->mCbCrWidth, info->mCbCrHeight),
|
||||
info->mCbCrStride);
|
||||
mIsValid = requiredSize && requiredSize <= mDataSize;
|
||||
mIsValid = requiredSize <= mDataSize;
|
||||
|
||||
}
|
||||
|
||||
|
@ -147,14 +147,15 @@ YCbCrImageDataDeserializerBase::ComputeMinBufferSize(const gfx::IntSize& aYSize,
|
|||
uint32_t aCbCrStride)
|
||||
{
|
||||
MOZ_ASSERT(aYSize.height >= 0 && aYSize.width >= 0);
|
||||
if (aYSize.height <= 0 || aYSize.width <= 0 || aCbCrSize.height <= 0 || aCbCrSize.width <= 0) {
|
||||
if (aYSize.height < 0 || aYSize.width < 0 || aCbCrSize.height < 0 || aCbCrSize.width < 0) {
|
||||
gfxDebug() << "Non-positive YCbCr buffer size request " << aYSize.height << "x" << aYSize.width << ", " << aCbCrSize.height << "x" << aCbCrSize.width;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!gfx::Factory::AllowedSurfaceSize(aYSize) ||
|
||||
aCbCrSize.width > aYSize.width ||
|
||||
aCbCrSize.height > aYSize.height) {
|
||||
if (aYSize != IntSize() &&
|
||||
(!gfx::Factory::AllowedSurfaceSize(aYSize) ||
|
||||
aCbCrSize.width > aYSize.width ||
|
||||
aCbCrSize.height > aYSize.height)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "gfxPlatform.h" // for gfxPlatform
|
||||
#include "GLReadTexImageHelper.h"
|
||||
#include "mozilla/gfx/BaseSize.h" // for BaseSize
|
||||
#include "mozilla/layers/BufferTexture.h"
|
||||
#include "mozilla/layers/AsyncCanvasRenderer.h"
|
||||
#include "mozilla/layers/CompositableForwarder.h"
|
||||
#include "mozilla/layers/CompositorChild.h" // for CompositorChild
|
||||
|
@ -200,21 +201,21 @@ public:
|
|||
}
|
||||
|
||||
protected:
|
||||
already_AddRefed<BufferTextureClient> Create(gfx::SurfaceFormat format) {
|
||||
already_AddRefed<TextureClient> Create(gfx::SurfaceFormat format) {
|
||||
return TextureClient::CreateForRawBufferAccess(mAllocator, format,
|
||||
mSize, mBackendType,
|
||||
mBaseTexFlags);
|
||||
}
|
||||
|
||||
public:
|
||||
already_AddRefed<BufferTextureClient> CreateB8G8R8AX8() {
|
||||
already_AddRefed<TextureClient> CreateB8G8R8AX8() {
|
||||
gfx::SurfaceFormat format = mHasAlpha ? gfx::SurfaceFormat::B8G8R8A8
|
||||
: gfx::SurfaceFormat::B8G8R8X8;
|
||||
return Create(format);
|
||||
}
|
||||
|
||||
already_AddRefed<BufferTextureClient> CreateR8G8B8AX8() {
|
||||
RefPtr<BufferTextureClient> ret;
|
||||
already_AddRefed<TextureClient> CreateR8G8B8AX8() {
|
||||
RefPtr<TextureClient> ret;
|
||||
|
||||
bool areRGBAFormatsBroken = mLayersBackend == LayersBackend::LAYERS_BASIC;
|
||||
if (!areRGBAFormatsBroken) {
|
||||
|
@ -242,7 +243,7 @@ TexClientFromReadback(SharedSurface* src, ISurfaceAllocator* allocator,
|
|||
TexClientFactory factory(allocator, src->mHasAlpha, src->mSize, backendType,
|
||||
baseFlags, layersBackend);
|
||||
|
||||
RefPtr<BufferTextureClient> texClient;
|
||||
RefPtr<TextureClient> texClient;
|
||||
|
||||
{
|
||||
gl::ScopedReadbackFB autoReadback(src);
|
||||
|
@ -288,16 +289,18 @@ TexClientFromReadback(SharedSurface* src, ISurfaceAllocator* allocator,
|
|||
DebugOnly<bool> succeeded = autoLock.Succeeded();
|
||||
MOZ_ASSERT(succeeded, "texture should have locked");
|
||||
|
||||
uint8_t* lockedBytes = texClient->GetLockedData();
|
||||
MappedTextureData mapped;
|
||||
texClient->BorrowMappedData(mapped);
|
||||
|
||||
// ReadPixels from the current FB into lockedBits.
|
||||
// ReadPixels from the current FB into mapped.data.
|
||||
auto width = src->mSize.width;
|
||||
auto height = src->mSize.height;
|
||||
|
||||
{
|
||||
ScopedPackAlignment autoAlign(gl, 4);
|
||||
|
||||
gl->raw_fReadPixels(0, 0, width, height, readFormat, readType, lockedBytes);
|
||||
MOZ_ASSERT(mapped.stride/4 == mapped.size.width);
|
||||
gl->raw_fReadPixels(0, 0, width, height, readFormat, readType, mapped.data);
|
||||
}
|
||||
|
||||
// RB_SWAPPED doesn't work with D3D11. (bug 1051010)
|
||||
|
@ -310,7 +313,7 @@ TexClientFromReadback(SharedSurface* src, ISurfaceAllocator* allocator,
|
|||
layersNeedsManualSwap)
|
||||
{
|
||||
size_t pixels = width * height;
|
||||
uint8_t* itr = lockedBytes;
|
||||
uint8_t* itr = mapped.data;
|
||||
for (size_t i = 0; i < pixels; i++) {
|
||||
SwapRB_R8G8B8A8(itr);
|
||||
itr += 4;
|
||||
|
|
|
@ -198,7 +198,7 @@ CompositableClient::GetAsyncID() const
|
|||
return 0; // zero is always an invalid async ID
|
||||
}
|
||||
|
||||
already_AddRefed<BufferTextureClient>
|
||||
already_AddRefed<TextureClient>
|
||||
CompositableClient::CreateBufferTextureClient(gfx::SurfaceFormat aFormat,
|
||||
gfx::IntSize aSize,
|
||||
gfx::BackendType aMoz2DBackend,
|
||||
|
|
|
@ -23,7 +23,6 @@ namespace mozilla {
|
|||
namespace layers {
|
||||
|
||||
class CompositableClient;
|
||||
class BufferTextureClient;
|
||||
class ImageBridgeChild;
|
||||
class ImageContainer;
|
||||
class CompositableForwarder;
|
||||
|
@ -136,7 +135,7 @@ public:
|
|||
|
||||
LayersBackend GetCompositorBackendType() const;
|
||||
|
||||
already_AddRefed<BufferTextureClient>
|
||||
already_AddRefed<TextureClient>
|
||||
CreateBufferTextureClient(gfx::SurfaceFormat aFormat,
|
||||
gfx::IntSize aSize,
|
||||
gfx::BackendType aMoz2dBackend = gfx::BackendType::NONE,
|
||||
|
|
|
@ -192,7 +192,7 @@ ImageClientSingle::UpdateImage(ImageContainer* aContainer, uint32_t aContentFlag
|
|||
return false;
|
||||
}
|
||||
|
||||
bool status = texture->AsTextureClientYCbCr()->UpdateYCbCr(*data);
|
||||
bool status = UpdateYCbCrTextureClient(texture, *data);
|
||||
MOZ_ASSERT(status);
|
||||
if (!status) {
|
||||
return false;
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "LayersLogging.h" // for AppendToString
|
||||
#include "gfxUtils.h" // for gfxUtils::GetAsLZ4Base64Str
|
||||
#include "IPDLActor.h"
|
||||
#include "BufferTexture.h"
|
||||
|
||||
#ifdef XP_WIN
|
||||
#include "mozilla/layers/TextureD3D9.h"
|
||||
|
@ -192,6 +193,16 @@ TextureChild::ActorDestroy(ActorDestroyReason why)
|
|||
mKeep = nullptr;
|
||||
}
|
||||
|
||||
ClientTexture::ClientTexture(TextureData* aData, TextureFlags aFlags, ISurfaceAllocator* aAllocator)
|
||||
: TextureClient(aAllocator, aFlags)
|
||||
, mData(aData)
|
||||
, mOpenMode(OpenMode::OPEN_NONE)
|
||||
#ifdef DEBUG
|
||||
, mExpectedDtRefs(0)
|
||||
#endif
|
||||
, mIsLocked(false)
|
||||
{}
|
||||
|
||||
bool
|
||||
ClientTexture::Lock(OpenMode aMode)
|
||||
{
|
||||
|
@ -217,7 +228,7 @@ ClientTexture::Unlock()
|
|||
}
|
||||
|
||||
if (mBorrowedDrawTarget) {
|
||||
MOZ_ASSERT(mBorrowedDrawTarget->refCount() == 1);
|
||||
MOZ_ASSERT(mBorrowedDrawTarget->refCount() <= mExpectedDtRefs);
|
||||
if (mOpenMode & OpenMode::OPEN_WRITE) {
|
||||
mBorrowedDrawTarget->Flush();
|
||||
if (mReadbackSink) {
|
||||
|
@ -270,24 +281,28 @@ ClientTexture::UpdateFromSurface(gfx::SourceSurface* aSurface)
|
|||
{
|
||||
MOZ_ASSERT(mValid);
|
||||
MOZ_ASSERT(mIsLocked);
|
||||
MOZ_ASSERT(aSurface);
|
||||
|
||||
// XXX - It would be better to first try the DrawTarget approach and fallback
|
||||
// to the backend-specific implementation because the latter will usually do
|
||||
// an expensive read-back + cpu-side copy if the texture is on the gpu.
|
||||
// There is a bug with the DrawTarget approach, though specific to reading back
|
||||
// from WebGL (where R and B channel end up inverted) to figure out first.
|
||||
if (mData->UpdateFromSurface(aSurface)) {
|
||||
return;
|
||||
}
|
||||
if (CanExposeDrawTarget() && NS_IsMainThread()) {
|
||||
RefPtr<DrawTarget> dt = BorrowDrawTarget();
|
||||
|
||||
MOZ_ASSERT(dt);
|
||||
if (!dt) {
|
||||
if (dt) {
|
||||
dt->CopySurface(aSurface,
|
||||
gfx::IntRect(gfx::IntPoint(0, 0), aSurface->GetSize()),
|
||||
gfx::IntPoint(0, 0));
|
||||
return;
|
||||
}
|
||||
|
||||
dt->CopySurface(aSurface,
|
||||
gfx::IntRect(gfx::IntPoint(0, 0), aSurface->GetSize()),
|
||||
gfx::IntPoint(0, 0));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mData->UpdateFromSurface(aSurface)) {
|
||||
NS_WARNING("ClientTexture::UpdateFromSurface failed");
|
||||
}
|
||||
NS_WARNING("ClientTexture::UpdateFromSurface failed");
|
||||
}
|
||||
|
||||
|
||||
|
@ -319,11 +334,36 @@ ClientTexture::BorrowDrawTarget()
|
|||
|
||||
if (!mBorrowedDrawTarget) {
|
||||
mBorrowedDrawTarget = mData->BorrowDrawTarget();
|
||||
#ifdef DEBUG
|
||||
mExpectedDtRefs = mBorrowedDrawTarget ? mBorrowedDrawTarget->refCount() : 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
return mBorrowedDrawTarget;
|
||||
}
|
||||
|
||||
bool
|
||||
ClientTexture::BorrowMappedData(MappedTextureData& aMap)
|
||||
{
|
||||
MOZ_ASSERT(mValid);
|
||||
|
||||
// TODO - SharedRGBImage just accesses the buffer without properly locking
|
||||
// the texture. It's bad.
|
||||
//MOZ_ASSERT(mIsLocked);
|
||||
//if (!mIsLocked) {
|
||||
// return nullptr;
|
||||
//}
|
||||
|
||||
return mData->BorrowMappedData(aMap);
|
||||
}
|
||||
|
||||
bool
|
||||
ClientTexture::BorrowMappedYCbCrData(MappedYCbCrTextureData& aMap)
|
||||
{
|
||||
MOZ_ASSERT(mValid);
|
||||
return mData->BorrowMappedYCbCrData(aMap);
|
||||
}
|
||||
|
||||
bool
|
||||
ClientTexture::ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor)
|
||||
{
|
||||
|
@ -480,25 +520,6 @@ DisableGralloc(SurfaceFormat aFormat, const gfx::IntSize& aSizeHint)
|
|||
}
|
||||
#endif
|
||||
|
||||
static
|
||||
already_AddRefed<BufferTextureClient>
|
||||
CreateBufferTextureClient(ISurfaceAllocator* aAllocator,
|
||||
SurfaceFormat aFormat,
|
||||
TextureFlags aTextureFlags,
|
||||
gfx::BackendType aMoz2DBackend)
|
||||
{
|
||||
if (aAllocator->IsSameProcess()) {
|
||||
RefPtr<BufferTextureClient> result = new MemoryTextureClient(aAllocator, aFormat,
|
||||
aMoz2DBackend,
|
||||
aTextureFlags);
|
||||
return result.forget();
|
||||
}
|
||||
RefPtr<BufferTextureClient> result = new ShmemTextureClient(aAllocator, aFormat,
|
||||
aMoz2DBackend,
|
||||
aTextureFlags);
|
||||
return result.forget();
|
||||
}
|
||||
|
||||
static inline gfx::BackendType
|
||||
BackendTypeForBackendSelector(LayersBackend aLayersBackend, BackendSelector aSelector)
|
||||
{
|
||||
|
@ -625,17 +646,12 @@ TextureClient::CreateForDrawing(CompositableForwarder* aAllocator,
|
|||
}
|
||||
|
||||
// Can't do any better than a buffer texture client.
|
||||
texture = CreateBufferTextureClient(aAllocator, aFormat, aTextureFlags, moz2DBackend);
|
||||
|
||||
if (!texture->AllocateForSurface(aSize, aAllocFlags)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return texture.forget();
|
||||
return TextureClient::CreateForRawBufferAccess(aAllocator, aFormat, aSize,
|
||||
moz2DBackend, aTextureFlags, aAllocFlags);
|
||||
}
|
||||
|
||||
// static
|
||||
already_AddRefed<BufferTextureClient>
|
||||
already_AddRefed<TextureClient>
|
||||
TextureClient::CreateForRawBufferAccess(ISurfaceAllocator* aAllocator,
|
||||
gfx::SurfaceFormat aFormat,
|
||||
gfx::IntSize aSize,
|
||||
|
@ -652,27 +668,27 @@ TextureClient::CreateForRawBufferAccess(ISurfaceAllocator* aAllocator,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<BufferTextureClient> texture =
|
||||
CreateBufferTextureClient(aAllocator, aFormat,
|
||||
aTextureFlags, aMoz2DBackend);
|
||||
if (texture) {
|
||||
if (!texture->AllocateForSurface(aSize, aAllocFlags)) {
|
||||
return nullptr;
|
||||
}
|
||||
TextureData* texData = BufferTextureData::Create(aSize, aFormat, aMoz2DBackend,
|
||||
aTextureFlags, aAllocFlags,
|
||||
aAllocator);
|
||||
if (!texData) {
|
||||
return nullptr;
|
||||
}
|
||||
return texture.forget();
|
||||
|
||||
return MakeAndAddRef<ClientTexture>(texData, aTextureFlags, aAllocator);
|
||||
}
|
||||
|
||||
// static
|
||||
already_AddRefed<BufferTextureClient>
|
||||
already_AddRefed<TextureClient>
|
||||
TextureClient::CreateForYCbCr(ISurfaceAllocator* aAllocator,
|
||||
gfx::IntSize aYSize,
|
||||
gfx::IntSize aCbCrSize,
|
||||
StereoMode aStereoMode,
|
||||
TextureFlags aTextureFlags)
|
||||
{
|
||||
MOZ_ASSERT(aAllocator->IPCOpen());
|
||||
if (!aAllocator || !aAllocator->IPCOpen()) {
|
||||
// The only reason we allow aAllocator to be null is for gtests
|
||||
MOZ_ASSERT(!aAllocator || aAllocator->IPCOpen());
|
||||
if (aAllocator && !aAllocator->IPCOpen()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -680,52 +696,34 @@ TextureClient::CreateForYCbCr(ISurfaceAllocator* aAllocator,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<BufferTextureClient> texture;
|
||||
if (aAllocator->IsSameProcess()) {
|
||||
texture = new MemoryTextureClient(aAllocator, gfx::SurfaceFormat::YUV,
|
||||
gfx::BackendType::NONE,
|
||||
aTextureFlags);
|
||||
} else {
|
||||
texture = new ShmemTextureClient(aAllocator, gfx::SurfaceFormat::YUV,
|
||||
gfx::BackendType::NONE,
|
||||
aTextureFlags);
|
||||
}
|
||||
|
||||
if (!texture->AllocateForYCbCr(aYSize, aCbCrSize, aStereoMode)) {
|
||||
TextureData* data = BufferTextureData::CreateForYCbCr(aAllocator, aYSize, aCbCrSize,
|
||||
aStereoMode, aTextureFlags);
|
||||
if (!data) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return texture.forget();
|
||||
return MakeAndAddRef<ClientTexture>(data, aTextureFlags, aAllocator);
|
||||
}
|
||||
|
||||
// static
|
||||
already_AddRefed<BufferTextureClient>
|
||||
already_AddRefed<TextureClient>
|
||||
TextureClient::CreateWithBufferSize(ISurfaceAllocator* aAllocator,
|
||||
gfx::SurfaceFormat aFormat,
|
||||
size_t aSize,
|
||||
TextureFlags aTextureFlags)
|
||||
gfx::SurfaceFormat aFormat,
|
||||
size_t aSize,
|
||||
TextureFlags aTextureFlags)
|
||||
{
|
||||
MOZ_ASSERT(aAllocator->IPCOpen());
|
||||
if (!aAllocator || !aAllocator->IPCOpen()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<BufferTextureClient> texture;
|
||||
if (aAllocator->IsSameProcess()) {
|
||||
texture = new MemoryTextureClient(aAllocator, gfx::SurfaceFormat::YUV,
|
||||
gfx::BackendType::NONE,
|
||||
aTextureFlags);
|
||||
} else {
|
||||
texture = new ShmemTextureClient(aAllocator, gfx::SurfaceFormat::YUV,
|
||||
gfx::BackendType::NONE,
|
||||
aTextureFlags);
|
||||
}
|
||||
|
||||
if (!texture->Allocate(aSize)) {
|
||||
TextureData* data = BufferTextureData::CreateWithBufferSize(aAllocator, aFormat, aSize,
|
||||
aTextureFlags);
|
||||
if (!data) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return texture.forget();
|
||||
return MakeAndAddRef<ClientTexture>(data, aTextureFlags, aAllocator);
|
||||
}
|
||||
|
||||
TextureClient::TextureClient(ISurfaceAllocator* aAllocator, TextureFlags aFlags)
|
||||
|
@ -867,344 +865,51 @@ TextureClient::PrintInfo(std::stringstream& aStream, const char* aPrefix)
|
|||
}
|
||||
#endif
|
||||
}
|
||||
bool
|
||||
ShmemTextureClient::ToSurfaceDescriptor(SurfaceDescriptor& aDescriptor)
|
||||
{
|
||||
MOZ_ASSERT(IsValid());
|
||||
if (!IsAllocated() || GetFormat() == gfx::SurfaceFormat::UNKNOWN) {
|
||||
return false;
|
||||
}
|
||||
|
||||
aDescriptor = SurfaceDescriptorShmem(mShmem, GetFormat());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ShmemTextureClient::Allocate(uint32_t aSize)
|
||||
UpdateYCbCrTextureClient(TextureClient* aTexture, const PlanarYCbCrData& aData)
|
||||
{
|
||||
MOZ_ASSERT(mValid);
|
||||
if (aSize > 0) {
|
||||
SharedMemory::SharedMemoryType memType = OptimalShmemType();
|
||||
mAllocated = GetAllocator()->AllocUnsafeShmem(aSize, memType, &mShmem);
|
||||
}
|
||||
return mAllocated;
|
||||
}
|
||||
|
||||
uint8_t*
|
||||
ShmemTextureClient::GetBuffer() const
|
||||
{
|
||||
MOZ_ASSERT(IsValid());
|
||||
if (mAllocated) {
|
||||
return mShmem.get<uint8_t>();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
size_t
|
||||
ShmemTextureClient::GetBufferSize() const
|
||||
{
|
||||
MOZ_ASSERT(IsValid());
|
||||
return mShmem.Size<uint8_t>();
|
||||
}
|
||||
|
||||
ShmemTextureClient::ShmemTextureClient(ISurfaceAllocator* aAllocator,
|
||||
gfx::SurfaceFormat aFormat,
|
||||
gfx::BackendType aMoz2DBackend,
|
||||
TextureFlags aFlags)
|
||||
: BufferTextureClient(aAllocator, aFormat, aMoz2DBackend, aFlags)
|
||||
, mAllocated(false)
|
||||
{
|
||||
MOZ_COUNT_CTOR(ShmemTextureClient);
|
||||
}
|
||||
|
||||
ShmemTextureClient::~ShmemTextureClient()
|
||||
{
|
||||
MOZ_COUNT_DTOR(ShmemTextureClient);
|
||||
if (ShouldDeallocateInDestructor()) {
|
||||
// if the buffer has never been shared we must deallocate it or ir would
|
||||
// leak.
|
||||
GetAllocator()->DeallocShmem(mShmem);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
MemoryTextureClient::ToSurfaceDescriptor(SurfaceDescriptor& aDescriptor)
|
||||
{
|
||||
MOZ_ASSERT(IsValid());
|
||||
if (!IsAllocated() || GetFormat() == gfx::SurfaceFormat::UNKNOWN) {
|
||||
return false;
|
||||
}
|
||||
aDescriptor = SurfaceDescriptorMemory(reinterpret_cast<uintptr_t>(mBuffer),
|
||||
GetFormat());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
MemoryTextureClient::Allocate(uint32_t aSize)
|
||||
{
|
||||
MOZ_ASSERT(!mBuffer);
|
||||
mBuffer = new (fallible) uint8_t[aSize];
|
||||
if (!mBuffer) {
|
||||
NS_WARNING("Failed to allocate buffer");
|
||||
return false;
|
||||
}
|
||||
GfxMemoryImageReporter::DidAlloc(mBuffer);
|
||||
mBufSize = aSize;
|
||||
return true;
|
||||
}
|
||||
|
||||
MemoryTextureClient::MemoryTextureClient(ISurfaceAllocator* aAllocator,
|
||||
gfx::SurfaceFormat aFormat,
|
||||
gfx::BackendType aMoz2DBackend,
|
||||
TextureFlags aFlags)
|
||||
: BufferTextureClient(aAllocator, aFormat, aMoz2DBackend, aFlags)
|
||||
, mBuffer(nullptr)
|
||||
, mBufSize(0)
|
||||
{
|
||||
MOZ_COUNT_CTOR(MemoryTextureClient);
|
||||
}
|
||||
|
||||
MemoryTextureClient::~MemoryTextureClient()
|
||||
{
|
||||
MOZ_COUNT_DTOR(MemoryTextureClient);
|
||||
if (mBuffer && ShouldDeallocateInDestructor()) {
|
||||
// if the buffer has never been shared we must deallocate it or it would
|
||||
// leak.
|
||||
GfxMemoryImageReporter::WillFree(mBuffer);
|
||||
delete [] mBuffer;
|
||||
}
|
||||
}
|
||||
|
||||
BufferTextureClient::BufferTextureClient(ISurfaceAllocator* aAllocator,
|
||||
gfx::SurfaceFormat aFormat,
|
||||
gfx::BackendType aMoz2DBackend,
|
||||
TextureFlags aFlags)
|
||||
: TextureClient(aAllocator, aFlags)
|
||||
, mFormat(aFormat)
|
||||
, mBackend(aMoz2DBackend)
|
||||
, mOpenMode(OpenMode::OPEN_NONE)
|
||||
, mLocked(false)
|
||||
{}
|
||||
|
||||
BufferTextureClient::~BufferTextureClient()
|
||||
{}
|
||||
|
||||
already_AddRefed<TextureClient>
|
||||
BufferTextureClient::CreateSimilar(TextureFlags aFlags,
|
||||
TextureAllocationFlags aAllocFlags) const
|
||||
{
|
||||
// This may return null
|
||||
RefPtr<BufferTextureClient> newBufferTex = TextureClient::CreateForRawBufferAccess(
|
||||
mAllocator, mFormat, mSize, mBackend, mFlags | aFlags, aAllocFlags
|
||||
);
|
||||
|
||||
return newBufferTex.forget();
|
||||
}
|
||||
|
||||
bool
|
||||
BufferTextureClient::AllocateForSurface(gfx::IntSize aSize, TextureAllocationFlags aFlags)
|
||||
{
|
||||
MOZ_ASSERT(IsValid());
|
||||
MOZ_ASSERT(mFormat != gfx::SurfaceFormat::YUV, "This textureClient cannot use YCbCr data");
|
||||
MOZ_ASSERT(aSize.width > 0 && aSize.height > 0);
|
||||
|
||||
if (aSize.width <= 0 || aSize.height <= 0) {
|
||||
gfxDebug() << "Asking for buffer of invalid size " << aSize.width << "x" << aSize.height;
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t bufSize = ImageDataSerializer::ComputeMinBufferSize(aSize, mFormat);
|
||||
if (!bufSize || !Allocate(bufSize)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (aFlags & ALLOC_CLEAR_BUFFER) {
|
||||
memset(GetBuffer(), 0, bufSize);
|
||||
}
|
||||
if (aFlags & ALLOC_CLEAR_BUFFER_WHITE) {
|
||||
memset(GetBuffer(), 0xFF, bufSize);
|
||||
}
|
||||
|
||||
ImageDataSerializer serializer(GetBuffer(), GetBufferSize());
|
||||
serializer.InitializeBufferInfo(aSize, mFormat);
|
||||
mSize = aSize;
|
||||
return true;
|
||||
}
|
||||
|
||||
gfx::DrawTarget*
|
||||
BufferTextureClient::BorrowDrawTarget()
|
||||
{
|
||||
MOZ_ASSERT(IsValid());
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(mLocked, "BorrowDrawTarget should be called on locked textures only");
|
||||
if (!mLocked) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (mDrawTarget) {
|
||||
mDrawTarget->SetTransform(Matrix());
|
||||
return mDrawTarget;
|
||||
}
|
||||
|
||||
ImageDataSerializer serializer(GetBuffer(), GetBufferSize());
|
||||
if (!serializer.IsValid()) {
|
||||
gfxCriticalNote << "Invalid serializer " << IsValid() << ", " << IsLocked() << ", " << GetBufferSize();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
mDrawTarget = serializer.GetAsDrawTarget(mBackend);
|
||||
if (mDrawTarget) {
|
||||
return mDrawTarget;
|
||||
}
|
||||
|
||||
mDrawTarget = serializer.GetAsDrawTarget(BackendType::CAIRO);
|
||||
if (!mDrawTarget) {
|
||||
gfxCriticalNote << "BorrowDrawTarget failure, original backend " << (int)mBackend;
|
||||
}
|
||||
|
||||
return mDrawTarget;
|
||||
}
|
||||
|
||||
void
|
||||
BufferTextureClient::UpdateFromSurface(gfx::SourceSurface* aSurface)
|
||||
{
|
||||
ImageDataSerializer serializer(GetBuffer(), GetBufferSize());
|
||||
|
||||
RefPtr<DataSourceSurface> surface = serializer.GetAsSurface();
|
||||
|
||||
if (!surface) {
|
||||
gfxCriticalError() << "Failed to get serializer as surface!";
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<DataSourceSurface> srcSurf = aSurface->GetDataSurface();
|
||||
|
||||
if (!srcSurf) {
|
||||
gfxCriticalError() << "Failed to GetDataSurface in UpdateFromSurface.";
|
||||
return;
|
||||
}
|
||||
|
||||
if (surface->GetSize() != srcSurf->GetSize() || surface->GetFormat() != srcSurf->GetFormat()) {
|
||||
gfxCriticalError() << "Attempt to update texture client from a surface with a different size or format! This: " << surface->GetSize() << " " << surface->GetFormat() << " Other: " << aSurface->GetSize() << " " << aSurface->GetFormat();
|
||||
return;
|
||||
}
|
||||
|
||||
DataSourceSurface::MappedSurface sourceMap;
|
||||
DataSourceSurface::MappedSurface destMap;
|
||||
if (!srcSurf->Map(DataSourceSurface::READ, &sourceMap)) {
|
||||
gfxCriticalError() << "Failed to map source surface for UpdateFromSurface.";
|
||||
return;
|
||||
}
|
||||
|
||||
if (!surface->Map(DataSourceSurface::WRITE, &destMap)) {
|
||||
srcSurf->Unmap();
|
||||
gfxCriticalError() << "Failed to map destination surface for UpdateFromSurface.";
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
for (int y = 0; y < srcSurf->GetSize().height; y++) {
|
||||
memcpy(destMap.mData + destMap.mStride * y,
|
||||
sourceMap.mData + sourceMap.mStride * y,
|
||||
srcSurf->GetSize().width * BytesPerPixel(srcSurf->GetFormat()));
|
||||
}
|
||||
|
||||
srcSurf->Unmap();
|
||||
surface->Unmap();
|
||||
}
|
||||
|
||||
bool
|
||||
BufferTextureClient::Lock(OpenMode aMode)
|
||||
{
|
||||
MOZ_ASSERT(!mLocked, "The TextureClient is already Locked!");
|
||||
mOpenMode = aMode;
|
||||
mLocked = IsValid() && IsAllocated();;
|
||||
return mLocked;
|
||||
}
|
||||
|
||||
void
|
||||
BufferTextureClient::Unlock()
|
||||
{
|
||||
MOZ_ASSERT(mLocked, "The TextureClient is already Unlocked!");
|
||||
mLocked = false;
|
||||
if (!mDrawTarget) {
|
||||
return;
|
||||
}
|
||||
|
||||
// see the comment on TextureClient::BorrowDrawTarget.
|
||||
// This DrawTarget is internal to the TextureClient and is only exposed to the
|
||||
// outside world between Lock() and Unlock(). This assertion checks that no outside
|
||||
// reference remains by the time Unlock() is called.
|
||||
MOZ_ASSERT(mDrawTarget->refCount() == 1);
|
||||
|
||||
if (mReadbackSink) {
|
||||
RefPtr<SourceSurface> snapshot = mDrawTarget->Snapshot();
|
||||
RefPtr<DataSourceSurface> dataSurf = snapshot->GetDataSurface();
|
||||
mReadbackSink->ProcessReadback(dataSurf);
|
||||
}
|
||||
|
||||
mDrawTarget->Flush();
|
||||
}
|
||||
|
||||
bool
|
||||
BufferTextureClient::UpdateYCbCr(const PlanarYCbCrData& aData)
|
||||
{
|
||||
MOZ_ASSERT(mLocked);
|
||||
MOZ_ASSERT(mFormat == gfx::SurfaceFormat::YUV, "This textureClient can only use YCbCr data");
|
||||
MOZ_ASSERT(!IsImmutable());
|
||||
MOZ_ASSERT(IsValid());
|
||||
MOZ_ASSERT(aTexture);
|
||||
MOZ_ASSERT(aTexture->IsLocked());
|
||||
MOZ_ASSERT(aTexture->GetFormat() == gfx::SurfaceFormat::YUV, "This textureClient can only use YCbCr data");
|
||||
MOZ_ASSERT(!aTexture->IsImmutable());
|
||||
MOZ_ASSERT(aTexture->IsValid());
|
||||
MOZ_ASSERT(aData.mCbSkip == aData.mCrSkip);
|
||||
|
||||
YCbCrImageDataSerializer serializer(GetBuffer(), GetBufferSize());
|
||||
MOZ_ASSERT(serializer.IsValid());
|
||||
if (!serializer.CopyData(aData.mYChannel, aData.mCbChannel, aData.mCrChannel,
|
||||
aData.mYSize, aData.mYStride,
|
||||
aData.mCbCrSize, aData.mCbCrStride,
|
||||
aData.mYSkip, aData.mCbSkip)) {
|
||||
MappedYCbCrTextureData mapped;
|
||||
if (!aTexture->BorrowMappedYCbCrData(mapped)) {
|
||||
NS_WARNING("Failed to extract YCbCr info!");
|
||||
return false;
|
||||
}
|
||||
|
||||
MappedYCbCrTextureData srcData;
|
||||
srcData.y.data = aData.mYChannel;
|
||||
srcData.y.size = aData.mYSize;
|
||||
srcData.y.stride = aData.mYStride;
|
||||
srcData.y.skip = aData.mYSkip;
|
||||
srcData.cb.data = aData.mCbChannel;
|
||||
srcData.cb.size = aData.mCbCrSize;
|
||||
srcData.cb.stride = aData.mCbCrStride;
|
||||
srcData.cb.skip = aData.mCbSkip;
|
||||
srcData.cr.data = aData.mCrChannel;
|
||||
srcData.cr.size = aData.mCbCrSize;
|
||||
srcData.cr.stride = aData.mCbCrStride;
|
||||
srcData.cr.skip = aData.mCrSkip;
|
||||
srcData.metadata = nullptr;
|
||||
|
||||
if (!srcData.CopyInto(mapped)) {
|
||||
NS_WARNING("Failed to copy image data!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (TextureRequiresLocking(mFlags)) {
|
||||
if (TextureRequiresLocking(aTexture->GetFlags())) {
|
||||
// We don't have support for proper locking yet, so we'll
|
||||
// have to be immutable instead.
|
||||
MarkImmutable();
|
||||
aTexture->MarkImmutable();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BufferTextureClient::AllocateForYCbCr(gfx::IntSize aYSize,
|
||||
gfx::IntSize aCbCrSize,
|
||||
StereoMode aStereoMode)
|
||||
{
|
||||
MOZ_ASSERT(IsValid());
|
||||
|
||||
size_t bufSize = YCbCrImageDataSerializer::ComputeMinBufferSize(aYSize,
|
||||
aCbCrSize);
|
||||
if (!bufSize || !Allocate(bufSize)) {
|
||||
return false;
|
||||
}
|
||||
YCbCrImageDataSerializer serializer(GetBuffer(), GetBufferSize());
|
||||
serializer.InitializeBufferInfo(aYSize,
|
||||
aCbCrSize,
|
||||
aStereoMode);
|
||||
mSize = aYSize;
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8_t*
|
||||
BufferTextureClient::GetLockedData() const
|
||||
{
|
||||
MOZ_ASSERT(IsLocked());
|
||||
|
||||
ImageDataSerializer serializer(GetBuffer(), GetBufferSize());
|
||||
MOZ_ASSERT(serializer.IsValid());
|
||||
|
||||
return serializer.GetData();
|
||||
}
|
||||
|
||||
already_AddRefed<SyncObject>
|
||||
SyncObject::CreateSyncObject(SyncHandle aHandle)
|
||||
{
|
||||
|
@ -1220,5 +925,40 @@ SyncObject::CreateSyncObject(SyncHandle aHandle)
|
|||
#endif
|
||||
}
|
||||
|
||||
bool
|
||||
MappedYCbCrChannelData::CopyInto(MappedYCbCrChannelData& aDst)
|
||||
{
|
||||
if (!data || !aDst.data || size != aDst.size) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (stride == aDst.stride) {
|
||||
// fast path!
|
||||
// We assume that the padding in the destination is there for alignment
|
||||
// purposes and doesn't contain useful data.
|
||||
memcpy(aDst.data, data, stride * size.height);
|
||||
return true;
|
||||
}
|
||||
|
||||
for (int32_t i = 0; i < size.height; ++i) {
|
||||
if (aDst.skip == 0 && skip == 0) {
|
||||
// fast-ish path
|
||||
memcpy(aDst.data + i * aDst.stride,
|
||||
data + i * stride,
|
||||
size.width);
|
||||
} else {
|
||||
// slow path
|
||||
uint8_t* src = data + i * stride;
|
||||
uint8_t* dst = aDst.data + i * aDst.stride;
|
||||
for (int32_t j = 0; j < size.width; ++j) {
|
||||
*dst = *src;
|
||||
src += 1 + skip;
|
||||
dst += 1 + aDst.skip;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -49,7 +49,8 @@ struct PlanarYCbCrData;
|
|||
class Image;
|
||||
class PTextureChild;
|
||||
class TextureChild;
|
||||
class BufferTextureClient;
|
||||
struct RawTextureBuffer;
|
||||
class RawYCbCrTextureBuffer;
|
||||
class TextureClient;
|
||||
class TextureClientRecycleAllocator;
|
||||
#ifdef GFX_DEBUG_TRACK_CLIENTS_IN_POOL
|
||||
|
@ -95,31 +96,6 @@ protected:
|
|||
SyncObject() { }
|
||||
};
|
||||
|
||||
/**
|
||||
* Interface for TextureClients that can be updated using YCbCr data.
|
||||
*/
|
||||
class TextureClientYCbCr
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Copy aData into this texture client.
|
||||
*
|
||||
* This must never be called on a TextureClient that is not sucessfully locked.
|
||||
*/
|
||||
virtual bool UpdateYCbCr(const PlanarYCbCrData& aData) = 0;
|
||||
|
||||
/**
|
||||
* Allocates for a given surface size, taking into account the pixel format
|
||||
* which is part of the state of the TextureClient.
|
||||
*
|
||||
* Does not clear the surface, since we consider that the surface
|
||||
* be painted entirely with opaque content.
|
||||
*/
|
||||
virtual bool AllocateForYCbCr(gfx::IntSize aYSize,
|
||||
gfx::IntSize aCbCrSize,
|
||||
StereoMode aStereoMode) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* This class may be used to asynchronously receive an update when the content
|
||||
* drawn to this texture client is available for reading in CPU memory. This
|
||||
|
@ -147,6 +123,43 @@ enum class BackendSelector
|
|||
Canvas
|
||||
};
|
||||
|
||||
/// Temporary object providing direct access to a Texture's memory.
|
||||
///
|
||||
/// see TextureClient::CanExposeMappedData() and TextureClient::BorrowMappedData().
|
||||
struct MappedTextureData
|
||||
{
|
||||
uint8_t* data;
|
||||
gfx::IntSize size;
|
||||
int32_t stride;
|
||||
gfx::SurfaceFormat format;
|
||||
};
|
||||
|
||||
struct MappedYCbCrChannelData
|
||||
{
|
||||
uint8_t* data;
|
||||
gfx::IntSize size;
|
||||
int32_t stride;
|
||||
int32_t skip;
|
||||
|
||||
bool CopyInto(MappedYCbCrChannelData& aDst);
|
||||
};
|
||||
|
||||
struct MappedYCbCrTextureData {
|
||||
MappedYCbCrChannelData y;
|
||||
MappedYCbCrChannelData cb;
|
||||
MappedYCbCrChannelData cr;
|
||||
// Sad but because of how SharedPlanarYCbCrData is used we have to expose this for now.
|
||||
uint8_t* metadata;
|
||||
StereoMode stereoMode;
|
||||
|
||||
bool CopyInto(MappedYCbCrTextureData& aDst)
|
||||
{
|
||||
return y.CopyInto(aDst.y)
|
||||
&& cb.CopyInto(aDst.cb)
|
||||
&& cr.CopyInto(aDst.cr);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* TextureClient is a thin abstraction over texture data that need to be shared
|
||||
* between the content process and the compositor process. It is the
|
||||
|
@ -187,17 +200,17 @@ public:
|
|||
TextureFlags aTextureFlags,
|
||||
TextureAllocationFlags flags = ALLOC_DEFAULT);
|
||||
|
||||
// Creates and allocates a BufferTextureClient supporting the YCbCr format.
|
||||
static already_AddRefed<BufferTextureClient>
|
||||
// Creates and allocates a TextureClient supporting the YCbCr format.
|
||||
static already_AddRefed<TextureClient>
|
||||
CreateForYCbCr(ISurfaceAllocator* aAllocator,
|
||||
gfx::IntSize aYSize,
|
||||
gfx::IntSize aCbCrSize,
|
||||
StereoMode aStereoMode,
|
||||
TextureFlags aTextureFlags);
|
||||
|
||||
// Creates and allocates a BufferTextureClient (can beaccessed through raw
|
||||
// Creates and allocates a TextureClient (can be accessed through raw
|
||||
// pointers).
|
||||
static already_AddRefed<BufferTextureClient>
|
||||
static already_AddRefed<TextureClient>
|
||||
CreateForRawBufferAccess(ISurfaceAllocator* aAllocator,
|
||||
gfx::SurfaceFormat aFormat,
|
||||
gfx::IntSize aSize,
|
||||
|
@ -205,10 +218,10 @@ public:
|
|||
TextureFlags aTextureFlags,
|
||||
TextureAllocationFlags flags = ALLOC_DEFAULT);
|
||||
|
||||
// Creates and allocates a BufferTextureClient (can beaccessed through raw
|
||||
// Creates and allocates a TextureClient (can beaccessed through raw
|
||||
// pointers) with a certain buffer size. It's unfortunate that we need this.
|
||||
// providing format and sizes could let us do more optimization.
|
||||
static already_AddRefed<BufferTextureClient>
|
||||
static already_AddRefed<TextureClient>
|
||||
CreateWithBufferSize(ISurfaceAllocator* aAllocator,
|
||||
gfx::SurfaceFormat aFormat,
|
||||
size_t aSize,
|
||||
|
@ -234,7 +247,6 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
virtual TextureClientYCbCr* AsTextureClientYCbCr() { return nullptr; }
|
||||
virtual GrallocTextureClientOGL* AsGrallocTextureClientOGL() { return nullptr; }
|
||||
|
||||
/**
|
||||
|
@ -251,6 +263,8 @@ public:
|
|||
|
||||
virtual bool CanExposeDrawTarget() const { return false; }
|
||||
|
||||
virtual bool CanExposeMappedData() const { return false; }
|
||||
|
||||
/**
|
||||
* Returns a DrawTarget to draw into the TextureClient.
|
||||
* This function should never be called when not on the main thread!
|
||||
|
@ -279,6 +293,13 @@ public:
|
|||
*/
|
||||
virtual gfx::DrawTarget* BorrowDrawTarget() { return nullptr; }
|
||||
|
||||
/**
|
||||
* Similar to BorrowDrawTarget but provides direct access to the texture's bits
|
||||
* instead of a DrawTarget.
|
||||
*/
|
||||
virtual bool BorrowMappedData(MappedTextureData&) { return false; }
|
||||
virtual bool BorrowMappedYCbCrData(MappedYCbCrTextureData&) { return false; }
|
||||
|
||||
/**
|
||||
* This function can be used to update the contents of the TextureClient
|
||||
* off the main thread.
|
||||
|
@ -585,12 +606,18 @@ public:
|
|||
|
||||
virtual bool SupportsMoz2D() const { return false; }
|
||||
|
||||
virtual bool CanExposeMappedData() const { return false; }
|
||||
|
||||
virtual bool HasInternalBuffer() const = 0;
|
||||
|
||||
virtual bool HasSynchronization() const { return false; }
|
||||
|
||||
virtual already_AddRefed<gfx::DrawTarget> BorrowDrawTarget() { return nullptr; }
|
||||
|
||||
virtual bool BorrowMappedData(MappedTextureData&) { return false; }
|
||||
|
||||
virtual bool BorrowMappedYCbCrData(MappedYCbCrTextureData&) { return false; }
|
||||
|
||||
virtual void Deallocate(ISurfaceAllocator* aAllocator) = 0;
|
||||
|
||||
virtual bool Serialize(SurfaceDescriptor& aDescriptor) = 0;
|
||||
|
@ -607,17 +634,14 @@ public:
|
|||
/// are based on TextureData.
|
||||
class ClientTexture : public TextureClient {
|
||||
public:
|
||||
ClientTexture(TextureData* aData, TextureFlags aFlags, ISurfaceAllocator* aAllocator)
|
||||
: TextureClient(aAllocator, aFlags)
|
||||
, mData(aData)
|
||||
, mOpenMode(OpenMode::OPEN_NONE)
|
||||
, mIsLocked(false)
|
||||
{}
|
||||
ClientTexture(TextureData* aData, TextureFlags aFlags, ISurfaceAllocator* aAllocator);
|
||||
|
||||
~ClientTexture();
|
||||
|
||||
virtual bool CanExposeDrawTarget() const override { return mData->SupportsMoz2D(); }
|
||||
|
||||
virtual bool CanExposeMappedData() const override { return mData->CanExposeMappedData(); }
|
||||
|
||||
virtual bool HasInternalBuffer() const override;
|
||||
|
||||
virtual bool HasSynchronization() const { return mData->HasSynchronization(); }
|
||||
|
@ -634,6 +658,10 @@ public:
|
|||
|
||||
virtual gfx::DrawTarget* BorrowDrawTarget() override;
|
||||
|
||||
virtual bool BorrowMappedData(MappedTextureData&) override;
|
||||
|
||||
virtual bool BorrowMappedYCbCrData(MappedYCbCrTextureData&) override;
|
||||
|
||||
virtual bool ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor) override;
|
||||
|
||||
virtual already_AddRefed<TextureClient>
|
||||
|
@ -651,6 +679,7 @@ protected:
|
|||
RefPtr<TextureReadbackSink> mReadbackSink;
|
||||
|
||||
OpenMode mOpenMode;
|
||||
DebugOnly<uint32_t> mExpectedDtRefs;
|
||||
bool mIsLocked;
|
||||
};
|
||||
|
||||
|
@ -673,143 +702,6 @@ private:
|
|||
RefPtr<TextureClient> mTextureClient;
|
||||
};
|
||||
|
||||
/**
|
||||
* TextureClient that wraps a random access buffer such as a Shmem or raw memory.
|
||||
* This class must be inherited to implement the memory allocation and access bits.
|
||||
* (see ShmemTextureClient and MemoryTextureClient)
|
||||
*/
|
||||
class BufferTextureClient : public TextureClient
|
||||
, public TextureClientYCbCr
|
||||
{
|
||||
public:
|
||||
BufferTextureClient(ISurfaceAllocator* aAllocator, gfx::SurfaceFormat aFormat,
|
||||
gfx::BackendType aBackend, TextureFlags aFlags);
|
||||
|
||||
virtual ~BufferTextureClient();
|
||||
|
||||
virtual bool IsAllocated() const override = 0;
|
||||
|
||||
virtual uint8_t* GetBuffer() const = 0;
|
||||
|
||||
virtual gfx::IntSize GetSize() const override { return mSize; }
|
||||
|
||||
virtual bool Lock(OpenMode aMode) override;
|
||||
|
||||
virtual void Unlock() override;
|
||||
|
||||
virtual bool IsLocked() const override { return mLocked; }
|
||||
|
||||
uint8_t* GetLockedData() const;
|
||||
|
||||
virtual bool CanExposeDrawTarget() const override { return true; }
|
||||
|
||||
virtual gfx::DrawTarget* BorrowDrawTarget() override;
|
||||
|
||||
virtual void UpdateFromSurface(gfx::SourceSurface* aSurface) override;
|
||||
|
||||
virtual bool AllocateForSurface(gfx::IntSize aSize,
|
||||
TextureAllocationFlags aFlags = ALLOC_DEFAULT) override;
|
||||
|
||||
// TextureClientYCbCr
|
||||
|
||||
virtual TextureClientYCbCr* AsTextureClientYCbCr() override { return this; }
|
||||
|
||||
virtual bool UpdateYCbCr(const PlanarYCbCrData& aData) override;
|
||||
|
||||
virtual bool AllocateForYCbCr(gfx::IntSize aYSize,
|
||||
gfx::IntSize aCbCrSize,
|
||||
StereoMode aStereoMode) override;
|
||||
|
||||
virtual gfx::SurfaceFormat GetFormat() const override { return mFormat; }
|
||||
|
||||
// XXX - Bug 908196 - Make Allocate(uint32_t) and GetBufferSize() protected.
|
||||
// these two methods should only be called by methods of BufferTextureClient
|
||||
// that are overridden in GrallocTextureClient (which does not implement the
|
||||
// two methods below)
|
||||
virtual bool Allocate(uint32_t aSize) = 0;
|
||||
|
||||
virtual size_t GetBufferSize() const = 0;
|
||||
|
||||
virtual bool HasInternalBuffer() const override { return true; }
|
||||
|
||||
virtual already_AddRefed<TextureClient>
|
||||
CreateSimilar(TextureFlags aFlags = TextureFlags::DEFAULT,
|
||||
TextureAllocationFlags aAllocFlags = ALLOC_DEFAULT) const override;
|
||||
|
||||
protected:
|
||||
RefPtr<gfx::DrawTarget> mDrawTarget;
|
||||
gfx::SurfaceFormat mFormat;
|
||||
gfx::IntSize mSize;
|
||||
gfx::BackendType mBackend;
|
||||
OpenMode mOpenMode;
|
||||
bool mLocked;
|
||||
};
|
||||
|
||||
/**
|
||||
* TextureClient that wraps shared memory.
|
||||
* the corresponding texture on the host side is ShmemTextureHost.
|
||||
*/
|
||||
class ShmemTextureClient : public BufferTextureClient
|
||||
{
|
||||
public:
|
||||
ShmemTextureClient(ISurfaceAllocator* aAllocator, gfx::SurfaceFormat aFormat,
|
||||
gfx::BackendType aBackend, TextureFlags aFlags);
|
||||
|
||||
protected:
|
||||
~ShmemTextureClient();
|
||||
|
||||
public:
|
||||
virtual bool ToSurfaceDescriptor(SurfaceDescriptor& aDescriptor) override;
|
||||
|
||||
virtual bool Allocate(uint32_t aSize) override;
|
||||
|
||||
virtual uint8_t* GetBuffer() const override;
|
||||
|
||||
virtual size_t GetBufferSize() const override;
|
||||
|
||||
virtual bool IsAllocated() const override { return mAllocated; }
|
||||
|
||||
virtual bool HasInternalBuffer() const override { return true; }
|
||||
|
||||
mozilla::ipc::Shmem& GetShmem() { return mShmem; }
|
||||
|
||||
protected:
|
||||
mozilla::ipc::Shmem mShmem;
|
||||
bool mAllocated;
|
||||
};
|
||||
|
||||
/**
|
||||
* TextureClient that wraps raw memory.
|
||||
* The corresponding texture on the host side is MemoryTextureHost.
|
||||
* Can obviously not be used in a cross process setup.
|
||||
*/
|
||||
class MemoryTextureClient : public BufferTextureClient
|
||||
{
|
||||
public:
|
||||
MemoryTextureClient(ISurfaceAllocator* aAllocator, gfx::SurfaceFormat aFormat,
|
||||
gfx::BackendType aBackend, TextureFlags aFlags);
|
||||
|
||||
protected:
|
||||
~MemoryTextureClient();
|
||||
|
||||
public:
|
||||
virtual bool ToSurfaceDescriptor(SurfaceDescriptor& aDescriptor) override;
|
||||
|
||||
virtual bool Allocate(uint32_t aSize) override;
|
||||
|
||||
virtual uint8_t* GetBuffer() const override { return mBuffer; }
|
||||
|
||||
virtual size_t GetBufferSize() const override { return mBufSize; }
|
||||
|
||||
virtual bool IsAllocated() const override { return mBuffer != nullptr; }
|
||||
|
||||
virtual bool HasInternalBuffer() const override { return true; }
|
||||
|
||||
protected:
|
||||
uint8_t* mBuffer;
|
||||
size_t mBufSize;
|
||||
};
|
||||
|
||||
// Automatically lock and unlock a texture. Since texture locking is fallible,
|
||||
// Succeeded() must be checked on the guard object before proceeding.
|
||||
class MOZ_RAII TextureClientAutoLock
|
||||
|
@ -860,6 +752,9 @@ protected:
|
|||
RefPtr<T> mData;
|
||||
};
|
||||
|
||||
/// Convenience function to set the content of ycbcr texture.
|
||||
bool UpdateYCbCrTextureClient(TextureClient* aTexture, const PlanarYCbCrData& aData);
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
||||
|
|
|
@ -13,7 +13,8 @@
|
|||
#include "mozilla/ipc/SharedMemory.h" // for SharedMemory, etc
|
||||
#include "mozilla/layers/ImageClient.h" // for ImageClient
|
||||
#include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor, etc
|
||||
#include "mozilla/layers/TextureClient.h" // for BufferTextureClient, etc
|
||||
#include "mozilla/layers/TextureClient.h"
|
||||
#include "mozilla/layers/BufferTexture.h"
|
||||
#include "mozilla/layers/YCbCrImageDataSerializer.h"
|
||||
#include "mozilla/layers/ImageBridgeChild.h" // for ImageBridgeChild
|
||||
#include "mozilla/mozalloc.h" // for operator delete
|
||||
|
@ -65,7 +66,9 @@ SharedPlanarYCbCrImage::GetTextureClient(CompositableClient* aClient)
|
|||
uint8_t*
|
||||
SharedPlanarYCbCrImage::GetBuffer()
|
||||
{
|
||||
return mTextureClient ? mTextureClient->GetBuffer() : nullptr;
|
||||
// This should never be used
|
||||
MOZ_ASSERT(false);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
already_AddRefed<gfx::SourceSurface>
|
||||
|
@ -89,15 +92,13 @@ SharedPlanarYCbCrImage::SetData(const PlanarYCbCrData& aData)
|
|||
return false;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mTextureClient->AsTextureClientYCbCr());
|
||||
|
||||
TextureClientAutoLock autoLock(mTextureClient, OpenMode::OPEN_WRITE_ONLY);
|
||||
if (!autoLock.Succeeded()) {
|
||||
MOZ_ASSERT(false, "Failed to lock the texture.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!mTextureClient->AsTextureClientYCbCr()->UpdateYCbCr(aData)) {
|
||||
if (!UpdateYCbCrTextureClient(mTextureClient, aData)) {
|
||||
MOZ_ASSERT(false, "Failed to copy YCbCr data into the TextureClient");
|
||||
return false;
|
||||
}
|
||||
|
@ -128,8 +129,18 @@ SharedPlanarYCbCrImage::AllocateAndGetNewBuffer(uint32_t aSize)
|
|||
// update buffer size
|
||||
mBufferSize = size;
|
||||
|
||||
YCbCrImageDataSerializer serializer(mTextureClient->GetBuffer(), mTextureClient->GetBufferSize());
|
||||
return serializer.GetData();
|
||||
MappedYCbCrTextureData mapped;
|
||||
if (mTextureClient->BorrowMappedYCbCrData(mapped)) {
|
||||
// The caller expects a pointer to the beginning of the writable part of the
|
||||
// buffer (after the metadata) which is where the y channel starts by default.
|
||||
// The caller might choose to write the y channel at a different offset and
|
||||
// if it does so, it will also update the metadata.
|
||||
// Anyway, we return the y channel here but the intent is to obtain the start of
|
||||
// the writable part of the buffer.
|
||||
return mapped.y.data;
|
||||
} else {
|
||||
MOZ_CRASH();
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -147,7 +158,11 @@ SharedPlanarYCbCrImage::SetDataNoCopy(const Data &aData)
|
|||
* with AllocateAndGetNewBuffer(), that we subtract from the Y, Cb, Cr
|
||||
* channels to compute 0-based offsets to pass to InitializeBufferInfo.
|
||||
*/
|
||||
YCbCrImageDataSerializer serializer(mTextureClient->GetBuffer(), mTextureClient->GetBufferSize());
|
||||
MappedYCbCrTextureData mapped;
|
||||
if(!mTextureClient->BorrowMappedYCbCrData(mapped)) {
|
||||
MOZ_CRASH();
|
||||
}
|
||||
YCbCrImageDataSerializer serializer(mapped.metadata, mBufferSize);
|
||||
uint8_t *base = serializer.GetData();
|
||||
uint32_t yOffset = aData.mYChannel - base;
|
||||
uint32_t cbOffset = aData.mCbChannel - base;
|
||||
|
@ -183,15 +198,18 @@ SharedPlanarYCbCrImage::Allocate(PlanarYCbCrData& aData)
|
|||
return false;
|
||||
}
|
||||
|
||||
YCbCrImageDataSerializer serializer(mTextureClient->GetBuffer(), mTextureClient->GetBufferSize());
|
||||
serializer.InitializeBufferInfo(aData.mYSize,
|
||||
aData.mCbCrSize,
|
||||
aData.mStereoMode);
|
||||
MOZ_ASSERT(serializer.IsValid());
|
||||
MappedYCbCrTextureData mapped;
|
||||
// The locking here is sort of a lie. The SharedPlanarYCbCrImage just pulls
|
||||
// pointers out of the TextureClient and keeps them around, which works only
|
||||
// because the underlyin BufferTextureData is always mapped in memory even outside
|
||||
// of the lock/unlock interval. That's sad and new code should follow this example.
|
||||
if (!mTextureClient->Lock(OpenMode::OPEN_READ) || !mTextureClient->BorrowMappedYCbCrData(mapped)) {
|
||||
MOZ_CRASH();
|
||||
}
|
||||
|
||||
aData.mYChannel = serializer.GetYData();
|
||||
aData.mCbChannel = serializer.GetCbData();
|
||||
aData.mCrChannel = serializer.GetCrData();
|
||||
aData.mYChannel = mapped.y.data;
|
||||
aData.mCbChannel = mapped.cb.data;
|
||||
aData.mCrChannel = mapped.cr.data;
|
||||
|
||||
// copy some of aData's values in mData (most of them)
|
||||
mData.mYChannel = aData.mYChannel;
|
||||
|
@ -218,6 +236,8 @@ SharedPlanarYCbCrImage::Allocate(PlanarYCbCrData& aData)
|
|||
mData.mCbCrSize);
|
||||
mSize = mData.mPicSize;
|
||||
|
||||
mTextureClient->Unlock();
|
||||
|
||||
return mBufferSize > 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
class BufferTextureClient;
|
||||
class ImageClient;
|
||||
class TextureClient;
|
||||
|
||||
|
@ -51,7 +50,7 @@ public:
|
|||
virtual size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const override;
|
||||
|
||||
private:
|
||||
RefPtr<BufferTextureClient> mTextureClient;
|
||||
RefPtr<TextureClient> mTextureClient;
|
||||
RefPtr<ImageClient> mCompositable;
|
||||
};
|
||||
|
||||
|
|
|
@ -8,9 +8,9 @@
|
|||
#include "gfx2DGlue.h" // for ImageFormatToSurfaceFormat, etc
|
||||
#include "gfxPlatform.h" // for gfxPlatform, gfxImageFormat
|
||||
#include "mozilla/gfx/Point.h" // for IntSIze
|
||||
#include "mozilla/layers/BufferTexture.h"
|
||||
#include "mozilla/layers/ISurfaceAllocator.h" // for ISurfaceAllocator, etc
|
||||
#include "mozilla/layers/ImageClient.h" // for ImageClient
|
||||
#include "mozilla/layers/ImageDataSerializer.h" // for ImageDataSerializer
|
||||
#include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor, etc
|
||||
#include "mozilla/layers/TextureClient.h" // for BufferTextureClient, etc
|
||||
#include "mozilla/layers/ImageBridgeChild.h" // for ImageBridgeChild
|
||||
|
@ -87,12 +87,11 @@ SharedRGBImage::Allocate(gfx::IntSize aSize, gfx::SurfaceFormat aFormat)
|
|||
uint8_t*
|
||||
SharedRGBImage::GetBuffer()
|
||||
{
|
||||
if (!mTextureClient) {
|
||||
return nullptr;
|
||||
MappedTextureData mapped;
|
||||
if (mTextureClient && mTextureClient->BorrowMappedData(mapped)) {
|
||||
return mapped.data;
|
||||
}
|
||||
|
||||
ImageDataSerializer serializer(mTextureClient->GetBuffer(), mTextureClient->GetBufferSize());
|
||||
return serializer.GetData();
|
||||
return 0;
|
||||
}
|
||||
|
||||
gfx::IntSize
|
||||
|
@ -101,13 +100,6 @@ SharedRGBImage::GetSize()
|
|||
return mSize;
|
||||
}
|
||||
|
||||
size_t
|
||||
SharedRGBImage::GetBufferSize()
|
||||
{
|
||||
return mTextureClient ? mTextureClient->GetBufferSize()
|
||||
: 0;
|
||||
}
|
||||
|
||||
TextureClient*
|
||||
SharedRGBImage::GetTextureClient(CompositableClient* aClient)
|
||||
{
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
class BufferTextureClient;
|
||||
class ImageClient;
|
||||
class TextureClient;
|
||||
|
||||
|
@ -45,15 +44,13 @@ public:
|
|||
|
||||
gfx::IntSize GetSize() override;
|
||||
|
||||
size_t GetBufferSize();
|
||||
|
||||
already_AddRefed<gfx::SourceSurface> GetAsSourceSurface() override;
|
||||
|
||||
bool Allocate(gfx::IntSize aSize, gfx::SurfaceFormat aFormat);
|
||||
private:
|
||||
gfx::IntSize mSize;
|
||||
RefPtr<ImageClient> mCompositable;
|
||||
RefPtr<BufferTextureClient> mTextureClient;
|
||||
RefPtr<TextureClient> mTextureClient;
|
||||
};
|
||||
|
||||
} // namespace layers
|
||||
|
|
|
@ -116,6 +116,7 @@ EXPORTS.mozilla.layers += [
|
|||
'basic/BasicCompositor.h',
|
||||
'basic/MacIOSurfaceTextureHostBasic.h',
|
||||
'basic/TextureHostBasic.h',
|
||||
'BufferTexture.h',
|
||||
'client/CanvasClient.h',
|
||||
'client/CompositableClient.h',
|
||||
'client/ContentClient.h',
|
||||
|
@ -270,6 +271,7 @@ UNIFIED_SOURCES += [
|
|||
'basic/BasicLayersImpl.cpp',
|
||||
'basic/BasicPaintedLayer.cpp',
|
||||
'basic/TextureHostBasic.cpp',
|
||||
'BufferTexture.cpp',
|
||||
'BufferUnrotate.cpp',
|
||||
'client/CanvasClient.cpp',
|
||||
'client/ClientCanvasLayer.cpp',
|
||||
|
|
|
@ -112,6 +112,7 @@ GrallocTextureClientOGL::WaitForBufferOwnership(bool aWaitReleaseFence)
|
|||
bool
|
||||
GrallocTextureClientOGL::Lock(OpenMode aMode)
|
||||
{
|
||||
MOZ_ASSERT(!mIsLocked);
|
||||
MOZ_ASSERT(IsValid());
|
||||
if (!IsValid() || !IsAllocated()) {
|
||||
return false;
|
||||
|
@ -148,13 +149,15 @@ GrallocTextureClientOGL::Lock(OpenMode aMode)
|
|||
NS_WARNING("Couldn't lock graphic buffer");
|
||||
return false;
|
||||
}
|
||||
return BufferTextureClient::Lock(aMode);
|
||||
mIsLocked = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
GrallocTextureClientOGL::Unlock()
|
||||
{
|
||||
BufferTextureClient::Unlock();
|
||||
MOZ_ASSERT(mIsLocked);
|
||||
mIsLocked = false;
|
||||
mDrawTarget = nullptr;
|
||||
if (mMappedBuffer) {
|
||||
mMappedBuffer = nullptr;
|
||||
|
@ -162,14 +165,6 @@ GrallocTextureClientOGL::Unlock()
|
|||
}
|
||||
}
|
||||
|
||||
uint8_t*
|
||||
GrallocTextureClientOGL::GetBuffer() const
|
||||
{
|
||||
MOZ_ASSERT(IsValid());
|
||||
NS_WARN_IF_FALSE(mMappedBuffer, "Trying to get a gralloc buffer without getting the lock?");
|
||||
return mMappedBuffer;
|
||||
}
|
||||
|
||||
static gfx::SurfaceFormat
|
||||
SurfaceFormatForPixelFormat(android::PixelFormat aFormat)
|
||||
{
|
||||
|
@ -379,22 +374,6 @@ GrallocTextureClientOGL::IsAllocated() const
|
|||
return !!mGraphicBuffer.get();
|
||||
}
|
||||
|
||||
bool
|
||||
GrallocTextureClientOGL::Allocate(uint32_t aSize)
|
||||
{
|
||||
// see Bug 908196
|
||||
MOZ_CRASH("This method should never be called.");
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t
|
||||
GrallocTextureClientOGL::GetBufferSize() const
|
||||
{
|
||||
// see Bug 908196
|
||||
MOZ_CRASH("This method should never be called.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*static*/ already_AddRefed<TextureClient>
|
||||
GrallocTextureClientOGL::FromSharedSurface(gl::SharedSurface* abstractSurf,
|
||||
TextureFlags flags)
|
||||
|
|
|
@ -38,7 +38,7 @@ namespace layers {
|
|||
*
|
||||
* This is only used in Firefox OS
|
||||
*/
|
||||
class GrallocTextureClientOGL : public BufferTextureClient
|
||||
class GrallocTextureClientOGL : public TextureClient
|
||||
{
|
||||
public:
|
||||
GrallocTextureClientOGL(ISurfaceAllocator* aAllocator,
|
||||
|
@ -82,8 +82,6 @@ public:
|
|||
return mGraphicBuffer->getPixelFormat();
|
||||
}
|
||||
|
||||
virtual uint8_t* GetBuffer() const override;
|
||||
|
||||
virtual gfx::DrawTarget* BorrowDrawTarget() override;
|
||||
|
||||
virtual void UpdateFromSurface(gfx::SourceSurface* aSurface) override;
|
||||
|
@ -93,7 +91,7 @@ public:
|
|||
|
||||
virtual bool AllocateForYCbCr(gfx::IntSize aYSize,
|
||||
gfx::IntSize aCbCrSize,
|
||||
StereoMode aStereoMode) override;
|
||||
StereoMode aStereoMode);
|
||||
|
||||
bool AllocateForGLRendering(gfx::IntSize aSize);
|
||||
|
||||
|
@ -101,10 +99,6 @@ public:
|
|||
|
||||
void SetIsOpaque(bool aIsOpaque) { mIsOpaque = aIsOpaque; }
|
||||
|
||||
virtual bool Allocate(uint32_t aSize) override;
|
||||
|
||||
virtual size_t GetBufferSize() const override;
|
||||
|
||||
/**
|
||||
* Hold android::MediaBuffer.
|
||||
* MediaBuffer needs to be add refed to keep MediaBuffer alive
|
||||
|
@ -128,6 +122,11 @@ public:
|
|||
TextureFlags flags);
|
||||
|
||||
protected:
|
||||
gfx::SurfaceFormat mFormat;
|
||||
gfx::IntSize mSize;
|
||||
gfx::BackendType mBackend;
|
||||
OpenMode mOpenMode;
|
||||
|
||||
/**
|
||||
* Unfortunately, until bug 879681 is fixed we need to use a GrallocBufferActor.
|
||||
*/
|
||||
|
@ -148,6 +147,7 @@ protected:
|
|||
android::MediaBuffer* mMediaBuffer;
|
||||
|
||||
bool mIsOpaque;
|
||||
bool mLocked;
|
||||
};
|
||||
|
||||
} // namespace layers
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "mozilla/gfx/Tools.h"
|
||||
#include "mozilla/layers/TextureClient.h"
|
||||
#include "mozilla/layers/TextureHost.h"
|
||||
#include "mozilla/layers/BufferTexture.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "gfx2DGlue.h"
|
||||
#include "gfxImageSurface.h"
|
||||
|
@ -148,8 +149,6 @@ void TestTextureClientSurface(TextureClient* texture, gfxImageSurface* surface)
|
|||
|
||||
// client allocation
|
||||
ASSERT_TRUE(texture->CanExposeDrawTarget());
|
||||
texture->AllocateForSurface(surface->GetSize());
|
||||
ASSERT_TRUE(texture->IsAllocated());
|
||||
|
||||
ASSERT_TRUE(texture->Lock(OpenMode::OPEN_READ_WRITE));
|
||||
// client painting
|
||||
|
@ -199,18 +198,8 @@ void TestTextureClientSurface(TextureClient* texture, gfxImageSurface* surface)
|
|||
|
||||
// Same as above, for YCbCr surfaces
|
||||
void TestTextureClientYCbCr(TextureClient* client, PlanarYCbCrData& ycbcrData) {
|
||||
|
||||
// client allocation
|
||||
ASSERT_TRUE(client->AsTextureClientYCbCr() != nullptr);
|
||||
TextureClientYCbCr* texture = client->AsTextureClientYCbCr();
|
||||
texture->AllocateForYCbCr(ycbcrData.mYSize,
|
||||
ycbcrData.mCbCrSize,
|
||||
ycbcrData.mStereoMode);
|
||||
ASSERT_TRUE(client->IsAllocated());
|
||||
|
||||
ASSERT_TRUE(client->Lock(OpenMode::OPEN_READ_WRITE));
|
||||
// client painting
|
||||
texture->UpdateYCbCr(ycbcrData);
|
||||
client->Lock(OpenMode::OPEN_READ_WRITE);
|
||||
UpdateYCbCrTextureClient(client, ycbcrData);
|
||||
client->Unlock();
|
||||
|
||||
// client serialization
|
||||
|
@ -273,11 +262,15 @@ TEST(Layers, TextureSerialization) {
|
|||
SetupSurface(surface.get());
|
||||
AssertSurfacesEqual(surface, surface);
|
||||
|
||||
RefPtr<TextureClient> client
|
||||
= new MemoryTextureClient(nullptr,
|
||||
mozilla::gfx::ImageFormatToSurfaceFormat(surface->Format()),
|
||||
gfx::BackendType::CAIRO,
|
||||
TextureFlags::DEALLOCATE_CLIENT);
|
||||
auto texData = BufferTextureData::Create(surface->GetSize(),
|
||||
gfx::ImageFormatToSurfaceFormat(surface->Format()),
|
||||
gfx::BackendType::CAIRO, TextureFlags::DEALLOCATE_CLIENT, ALLOC_DEFAULT, nullptr
|
||||
);
|
||||
ASSERT_TRUE(!!texData);
|
||||
|
||||
RefPtr<TextureClient> client = new ClientTexture(
|
||||
texData, TextureFlags::DEALLOCATE_CLIENT, nullptr
|
||||
);
|
||||
|
||||
TestTextureClientSurface(client, surface);
|
||||
|
||||
|
@ -310,11 +303,8 @@ TEST(Layers, TextureYCbCrSerialization) {
|
|||
clientData.mPicX = 0;
|
||||
clientData.mPicX = 0;
|
||||
|
||||
RefPtr<TextureClient> client
|
||||
= new MemoryTextureClient(nullptr,
|
||||
mozilla::gfx::SurfaceFormat::YUV,
|
||||
gfx::BackendType::CAIRO,
|
||||
TextureFlags::DEALLOCATE_CLIENT);
|
||||
RefPtr<TextureClient> client = TextureClient::CreateForYCbCr(nullptr, clientData.mYSize, clientData.mCbCrSize,
|
||||
StereoMode::MONO, TextureFlags::DEALLOCATE_CLIENT);
|
||||
|
||||
TestTextureClientYCbCr(client, clientData);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче