Bug 1200595 - Buffer TextureData implementation. r=mattwoodrow

This commit is contained in:
Nicolas Silva 2015-10-15 17:53:33 +02:00
Родитель 62fdc49f48
Коммит 71d9215e93
19 изменённых файлов: 851 добавлений и 697 удалений

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

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