mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 13:21:05 +00:00
Bug 1228952 - Move texture metadata out of the BufferTextureClient/Host's buffer. r=Sotaro
This commit is contained in:
parent
537c84d51c
commit
9bc4b1d4e6
@ -1162,6 +1162,11 @@ public:
|
||||
int32_t limit = 0,
|
||||
int32_t allocLimit = 0);
|
||||
|
||||
/**
|
||||
* Make sure that the given buffer size doesn't exceed the allocation limit.
|
||||
*/
|
||||
static bool CheckBufferSize(int32_t bufSize);
|
||||
|
||||
/** Make sure the given dimension satisfies the CheckSurfaceSize and is
|
||||
* within 8k limit. The 8k value is chosen a bit randomly.
|
||||
*/
|
||||
|
@ -264,6 +264,12 @@ Factory::AllowedSurfaceSize(const IntSize &aSize)
|
||||
return CheckSurfaceSize(aSize);
|
||||
}
|
||||
|
||||
bool
|
||||
Factory::CheckBufferSize(int32_t bufSize)
|
||||
{
|
||||
return !sConfig || bufSize < sConfig->mMaxAllocSize;
|
||||
}
|
||||
|
||||
bool
|
||||
Factory::CheckSurfaceSize(const IntSize &sz,
|
||||
int32_t extentLimit,
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "mozilla/layers/AsyncDragMetrics.h"
|
||||
#include "mozilla/layers/LayersTypes.h"
|
||||
#include "mozilla/layers/CompositorTypes.h"
|
||||
#include "ImageTypes.h"
|
||||
#include "FrameMetrics.h"
|
||||
#include "FilterSupport.h"
|
||||
#include "mozilla/layers/GeckoContentController.h"
|
||||
@ -797,7 +798,7 @@ template<>
|
||||
struct ParamTraits<mozilla::layers::TextureInfo>
|
||||
{
|
||||
typedef mozilla::layers::TextureInfo paramType;
|
||||
|
||||
|
||||
static void Write(Message* aMsg, const paramType& aParam)
|
||||
{
|
||||
WriteParam(aMsg, aParam.mCompositableType);
|
||||
@ -827,6 +828,14 @@ struct ParamTraits<mozilla::gfx::SurfaceFormat>
|
||||
mozilla::gfx::SurfaceFormat::UNKNOWN>
|
||||
{};
|
||||
|
||||
template <>
|
||||
struct ParamTraits<mozilla::StereoMode>
|
||||
: public ContiguousEnumSerializer<
|
||||
mozilla::StereoMode,
|
||||
mozilla::StereoMode::MONO,
|
||||
mozilla::StereoMode::TOP_BOTTOM>
|
||||
{};
|
||||
|
||||
template <>
|
||||
struct ParamTraits<mozilla::layers::ScrollableLayerGuid>
|
||||
{
|
||||
@ -847,6 +856,7 @@ struct ParamTraits<mozilla::layers::ScrollableLayerGuid>
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <>
|
||||
struct ParamTraits<mozilla::layers::ZoomConstraints>
|
||||
{
|
||||
|
@ -30,10 +30,10 @@ public:
|
||||
|
||||
virtual void Deallocate(ISurfaceAllocator*) override;
|
||||
|
||||
MemoryTextureData(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
|
||||
MemoryTextureData(const BufferDescriptor& aDesc,
|
||||
gfx::BackendType aMoz2DBackend,
|
||||
uint8_t* aBuffer, size_t aBufferSize)
|
||||
: BufferTextureData(aSize, aFormat, aMoz2DBackend)
|
||||
: BufferTextureData(aDesc, aMoz2DBackend)
|
||||
, mBuffer(aBuffer)
|
||||
, mBufferSize(aBufferSize)
|
||||
{
|
||||
@ -67,9 +67,9 @@ public:
|
||||
|
||||
virtual void Deallocate(ISurfaceAllocator* aAllocator) override;
|
||||
|
||||
ShmemTextureData(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
|
||||
ShmemTextureData(const BufferDescriptor& aDesc,
|
||||
gfx::BackendType aMoz2DBackend, mozilla::ipc::Shmem aShmem)
|
||||
: BufferTextureData(aSize, aFormat, aMoz2DBackend)
|
||||
: BufferTextureData(aDesc, aMoz2DBackend)
|
||||
, mShmem(aShmem)
|
||||
{
|
||||
MOZ_ASSERT(mShmem.Size<uint8_t>());
|
||||
@ -97,43 +97,46 @@ BufferTextureData::Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
|
||||
}
|
||||
|
||||
BufferTextureData*
|
||||
BufferTextureData::CreateWithBufferSize(ISurfaceAllocator* aAllocator,
|
||||
gfx::SurfaceFormat aFormat,
|
||||
size_t aSize,
|
||||
TextureFlags aTextureFlags)
|
||||
BufferTextureData::CreateInternal(ISurfaceAllocator* aAllocator,
|
||||
const BufferDescriptor& aDesc,
|
||||
gfx::BackendType aMoz2DBackend,
|
||||
int32_t aBufferSize,
|
||||
TextureFlags aTextureFlags)
|
||||
{
|
||||
if (aSize == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
BufferTextureData* data;
|
||||
if (!aAllocator || aAllocator->IsSameProcess()) {
|
||||
uint8_t* buffer = new (fallible) uint8_t[aSize];
|
||||
uint8_t* buffer = new (fallible) uint8_t[aBufferSize];
|
||||
if (!buffer) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
data = new MemoryTextureData(gfx::IntSize(), aFormat, gfx::BackendType::NONE, buffer, aSize);
|
||||
return new MemoryTextureData(aDesc, aMoz2DBackend, buffer, aBufferSize);
|
||||
} else {
|
||||
ipc::Shmem shm;
|
||||
if (!aAllocator->AllocUnsafeShmem(aSize, OptimalShmemType(), &shm)) {
|
||||
if (!aAllocator->AllocUnsafeShmem(aBufferSize, OptimalShmemType(), &shm)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
data = new ShmemTextureData(gfx::IntSize(), aFormat, gfx::BackendType::NONE, shm);
|
||||
return new ShmemTextureData(aDesc, aMoz2DBackend, shm);
|
||||
}
|
||||
}
|
||||
|
||||
BufferTextureData*
|
||||
BufferTextureData::CreateForYCbCrWithBufferSize(ISurfaceAllocator* aAllocator,
|
||||
gfx::SurfaceFormat aFormat,
|
||||
int32_t aBufferSize,
|
||||
TextureFlags aTextureFlags)
|
||||
{
|
||||
if (aBufferSize == 0 || !gfx::Factory::CheckBufferSize(aBufferSize)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
BufferDescriptor desc = YCbCrDescriptor(gfx::IntSize(), gfx::IntSize(),
|
||||
0, 0, 0, StereoMode::MONO);
|
||||
|
||||
return data;
|
||||
return CreateInternal(aAllocator, desc, gfx::BackendType::NONE, aBufferSize,
|
||||
aTextureFlags);
|
||||
}
|
||||
|
||||
BufferTextureData*
|
||||
@ -143,24 +146,41 @@ BufferTextureData::CreateForYCbCr(ISurfaceAllocator* aAllocator,
|
||||
StereoMode aStereoMode,
|
||||
TextureFlags aTextureFlags)
|
||||
{
|
||||
size_t bufSize = YCbCrImageDataSerializer::ComputeMinBufferSize(aYSize, aCbCrSize);
|
||||
BufferTextureData* texture = CreateWithBufferSize(aAllocator, gfx::SurfaceFormat::YUV,
|
||||
bufSize, aTextureFlags);
|
||||
if (!texture) {
|
||||
uint32_t bufSize = ImageDataSerializer::ComputeYCbCrBufferSize(aYSize, aCbCrSize);
|
||||
if (bufSize == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
YCbCrImageDataSerializer serializer(texture->GetBuffer(), texture->GetBufferSize());
|
||||
serializer.InitializeBufferInfo(aYSize, aCbCrSize, aStereoMode);
|
||||
texture->mSize = aYSize;
|
||||
uint32_t yOffset;
|
||||
uint32_t cbOffset;
|
||||
uint32_t crOffset;
|
||||
ImageDataSerializer::ComputeYCbCrOffsets(aYSize.width, aYSize.height,
|
||||
aCbCrSize.width, aCbCrSize.height,
|
||||
yOffset, cbOffset, crOffset);
|
||||
|
||||
return texture;
|
||||
YCbCrDescriptor descriptor = YCbCrDescriptor(aYSize, aCbCrSize, yOffset, cbOffset,
|
||||
crOffset, aStereoMode);
|
||||
|
||||
return CreateInternal(aAllocator, descriptor, gfx::BackendType::NONE, bufSize,
|
||||
aTextureFlags);
|
||||
}
|
||||
|
||||
gfx::IntSize
|
||||
BufferTextureData::GetSize() const
|
||||
{
|
||||
return ImageDataSerializer::SizeFromBufferDescriptor(mDescriptor);
|
||||
}
|
||||
|
||||
gfx::SurfaceFormat
|
||||
BufferTextureData::GetFormat() const
|
||||
{
|
||||
return ImageDataSerializer::FormatFromBufferDescriptor(mDescriptor);
|
||||
}
|
||||
|
||||
bool
|
||||
BufferTextureData::SupportsMoz2D() const
|
||||
{
|
||||
switch (mFormat) {
|
||||
switch (GetFormat()) {
|
||||
case gfx::SurfaceFormat::YUV:
|
||||
case gfx::SurfaceFormat::NV12:
|
||||
case gfx::SurfaceFormat::UNKNOWN:
|
||||
@ -179,12 +199,17 @@ BufferTextureData::BorrowDrawTarget()
|
||||
return dt.forget();
|
||||
}
|
||||
|
||||
ImageDataSerializer serializer(GetBuffer(), GetBufferSize());
|
||||
if (!serializer.IsValid()) {
|
||||
if (mDescriptor.type() != BufferDescriptor::TRGBDescriptor) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
mDrawTarget = serializer.GetAsDrawTarget(mMoz2DBackend);
|
||||
const RGBDescriptor& rgb = mDescriptor.get_RGBDescriptor();
|
||||
|
||||
uint32_t stride = ImageDataSerializer::GetRGBStride(rgb);
|
||||
mDrawTarget = gfx::Factory::CreateDrawTargetForData(mMoz2DBackend,
|
||||
GetBuffer(), rgb.size(),
|
||||
stride, rgb.format());
|
||||
|
||||
if (mDrawTarget) {
|
||||
RefPtr<gfx::DrawTarget> dt = mDrawTarget;
|
||||
return dt.forget();
|
||||
@ -192,7 +217,12 @@ BufferTextureData::BorrowDrawTarget()
|
||||
|
||||
// TODO - should we warn? should we really fallback to cairo? perhaps
|
||||
// at least update mMoz2DBackend...
|
||||
mDrawTarget = serializer.GetAsDrawTarget(gfx::BackendType::CAIRO);
|
||||
if (mMoz2DBackend != gfx::BackendType::CAIRO) {
|
||||
mDrawTarget = gfx::Factory::CreateDrawTargetForData(gfx::BackendType::CAIRO,
|
||||
GetBuffer(), rgb.size(),
|
||||
stride, rgb.format());
|
||||
}
|
||||
|
||||
if (!mDrawTarget) {
|
||||
gfxCriticalNote << "BorrowDrawTarget failure, original backend " << (int)mMoz2DBackend;
|
||||
}
|
||||
@ -204,19 +234,16 @@ BufferTextureData::BorrowDrawTarget()
|
||||
bool
|
||||
BufferTextureData::BorrowMappedData(MappedTextureData& aData)
|
||||
{
|
||||
if (mFormat == gfx::SurfaceFormat::YUV) {
|
||||
if (GetFormat() == gfx::SurfaceFormat::YUV) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ImageDataDeserializer view(GetBuffer(), GetBufferSize());
|
||||
if (!view.IsValid()) {
|
||||
return false;
|
||||
}
|
||||
gfx::IntSize size = GetSize();
|
||||
|
||||
aData.data = view.GetData();
|
||||
aData.size = view.GetSize();
|
||||
aData.stride = view.GetStride();
|
||||
aData.format = mFormat;
|
||||
aData.data = GetBuffer();
|
||||
aData.size = size;
|
||||
aData.format = GetFormat();
|
||||
aData.stride = ImageDataSerializer::ComputeRGBStride(aData.format, size.width);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -224,31 +251,32 @@ BufferTextureData::BorrowMappedData(MappedTextureData& aData)
|
||||
bool
|
||||
BufferTextureData::BorrowMappedYCbCrData(MappedYCbCrTextureData& aMap)
|
||||
{
|
||||
if (mFormat != gfx::SurfaceFormat::YUV) {
|
||||
if (mDescriptor.type() != BufferDescriptor::TYCbCrDescriptor) {
|
||||
return false;
|
||||
}
|
||||
|
||||
YCbCrImageDataDeserializer view(GetBuffer(), GetBufferSize());
|
||||
if (!view.IsValid()) {
|
||||
return false;
|
||||
}
|
||||
const YCbCrDescriptor& desc = mDescriptor.get_YCbCrDescriptor();
|
||||
|
||||
aMap.stereoMode = view.GetStereoMode();
|
||||
aMap.metadata = GetBuffer();
|
||||
uint8_t* data = GetBuffer();
|
||||
auto ySize = desc.ySize();
|
||||
auto cbCrSize = desc.cbCrSize();
|
||||
|
||||
aMap.y.data = view.GetYData();
|
||||
aMap.y.size = view.GetYSize();
|
||||
aMap.y.stride = view.GetYStride();
|
||||
aMap.stereoMode = desc.stereoMode();
|
||||
aMap.metadata = nullptr;
|
||||
|
||||
aMap.y.data = data + desc.yOffset();
|
||||
aMap.y.size = ySize;
|
||||
aMap.y.stride = ySize.width;
|
||||
aMap.y.skip = 0;
|
||||
|
||||
aMap.cb.data = view.GetCbData();
|
||||
aMap.cb.size = view.GetCbCrSize();
|
||||
aMap.cb.stride = view.GetCbCrStride();
|
||||
aMap.cb.data = data + desc.cbOffset();
|
||||
aMap.cb.size = cbCrSize;
|
||||
aMap.cb.stride = cbCrSize.width;
|
||||
aMap.cb.skip = 0;
|
||||
|
||||
aMap.cr.data = view.GetCrData();
|
||||
aMap.cr.size = view.GetCbCrSize();
|
||||
aMap.cr.stride = view.GetCbCrStride();
|
||||
aMap.cr.data = data + desc.crOffset();
|
||||
aMap.cr.size = cbCrSize;
|
||||
aMap.cr.stride = cbCrSize.width;
|
||||
aMap.cr.skip = 0;
|
||||
|
||||
return true;
|
||||
@ -257,9 +285,15 @@ BufferTextureData::BorrowMappedYCbCrData(MappedYCbCrTextureData& aMap)
|
||||
bool
|
||||
BufferTextureData::UpdateFromSurface(gfx::SourceSurface* aSurface)
|
||||
{
|
||||
ImageDataSerializer serializer(GetBuffer(), GetBufferSize());
|
||||
if (mDescriptor.type() != BufferDescriptor::TRGBDescriptor) {
|
||||
return false;
|
||||
}
|
||||
const RGBDescriptor& rgb = mDescriptor.get_RGBDescriptor();
|
||||
|
||||
RefPtr<gfx::DataSourceSurface> surface = serializer.GetAsSurface();
|
||||
uint32_t stride = ImageDataSerializer::GetRGBStride(rgb);
|
||||
RefPtr<gfx::DataSourceSurface> surface =
|
||||
gfx::Factory::CreateWrappingDataSourceSurface(GetBuffer(), stride,
|
||||
rgb.size(), rgb.format());
|
||||
|
||||
if (!surface) {
|
||||
gfxCriticalError() << "Failed to get serializer as surface!";
|
||||
@ -304,6 +338,14 @@ BufferTextureData::UpdateFromSurface(gfx::SourceSurface* aSurface)
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
BufferTextureData::SetDesciptor(const BufferDescriptor& aDescriptor)
|
||||
{
|
||||
MOZ_ASSERT(mDescriptor.type() == BufferDescriptor::TYCbCrDescriptor);
|
||||
MOZ_ASSERT(mDescriptor.get_YCbCrDescriptor().ySize() == gfx::IntSize());
|
||||
mDescriptor = aDescriptor;
|
||||
}
|
||||
|
||||
bool
|
||||
MemoryTextureData::Serialize(SurfaceDescriptor& aOutDescriptor)
|
||||
{
|
||||
@ -312,14 +354,13 @@ MemoryTextureData::Serialize(SurfaceDescriptor& aOutDescriptor)
|
||||
return false;
|
||||
}
|
||||
|
||||
aOutDescriptor = SurfaceDescriptorMemory(reinterpret_cast<uintptr_t>(mBuffer),
|
||||
GetFormat());
|
||||
uintptr_t ptr = reinterpret_cast<uintptr_t>(mBuffer);
|
||||
aOutDescriptor = SurfaceDescriptorBuffer(mDescriptor, MemoryOrShmem(ptr));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool InitBuffer(uint8_t* buf, size_t bufSize,
|
||||
gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
|
||||
TextureAllocationFlags aAllocFlags)
|
||||
static bool InitBuffer(uint8_t* buf, size_t bufSize, TextureAllocationFlags aAllocFlags)
|
||||
{
|
||||
if (!buf) {
|
||||
gfxDebug() << "BufferTextureData: Failed to allocate " << bufSize << " bytes";
|
||||
@ -333,8 +374,6 @@ static bool InitBuffer(uint8_t* buf, size_t bufSize,
|
||||
memset(buf, 0xFF, bufSize);
|
||||
}
|
||||
|
||||
ImageDataSerializer serializer(buf, bufSize);
|
||||
serializer.InitializeBufferInfo(aSize, aFormat);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -344,24 +383,29 @@ MemoryTextureData::Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
|
||||
TextureAllocationFlags aAllocFlags,
|
||||
ISurfaceAllocator*)
|
||||
{
|
||||
// Should have used CreateForYCbCr.
|
||||
MOZ_ASSERT(aFormat != gfx::SurfaceFormat::YUV);
|
||||
|
||||
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);
|
||||
uint32_t bufSize = ImageDataSerializer::ComputeRGBBufferSize(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);
|
||||
if (!InitBuffer(buf, bufSize, aAllocFlags)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
GfxMemoryImageReporter::DidAlloc(buf);
|
||||
|
||||
BufferDescriptor descriptor = RGBDescriptor(aSize, aFormat);
|
||||
|
||||
return new MemoryTextureData(descriptor, aMoz2DBackend, buf, bufSize);
|
||||
}
|
||||
|
||||
void
|
||||
@ -378,7 +422,7 @@ MemoryTextureData::CreateSimilar(ISurfaceAllocator* aAllocator,
|
||||
TextureFlags aFlags,
|
||||
TextureAllocationFlags aAllocFlags) const
|
||||
{
|
||||
return MemoryTextureData::Create(mSize, mFormat, mMoz2DBackend,
|
||||
return MemoryTextureData::Create(GetSize(), GetFormat(), mMoz2DBackend,
|
||||
aFlags, aAllocFlags, aAllocator);
|
||||
}
|
||||
|
||||
@ -390,7 +434,7 @@ ShmemTextureData::Serialize(SurfaceDescriptor& aOutDescriptor)
|
||||
return false;
|
||||
}
|
||||
|
||||
aOutDescriptor = SurfaceDescriptorShmem(mShmem, GetFormat());
|
||||
aOutDescriptor = SurfaceDescriptorBuffer(mDescriptor, MemoryOrShmem(mShmem));
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -402,6 +446,9 @@ ShmemTextureData::Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
|
||||
ISurfaceAllocator* aAllocator)
|
||||
{
|
||||
MOZ_ASSERT(aAllocator);
|
||||
// Should have used CreateForYCbCr.
|
||||
MOZ_ASSERT(aFormat != gfx::SurfaceFormat::YUV);
|
||||
|
||||
if (!aAllocator) {
|
||||
return nullptr;
|
||||
}
|
||||
@ -411,7 +458,7 @@ ShmemTextureData::Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint32_t bufSize = ImageDataSerializer::ComputeMinBufferSize(aSize, aFormat);
|
||||
uint32_t bufSize = ImageDataSerializer::ComputeRGBBufferSize(aSize, aFormat);
|
||||
if (!bufSize) {
|
||||
return nullptr;
|
||||
}
|
||||
@ -422,11 +469,14 @@ ShmemTextureData::Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat,
|
||||
}
|
||||
|
||||
uint8_t* buf = shm.get<uint8_t>();
|
||||
|
||||
if (InitBuffer(buf, bufSize, aSize, aFormat, aAllocFlags)) {
|
||||
return new ShmemTextureData(aSize, aFormat, aMoz2DBackend, shm);
|
||||
if (!InitBuffer(buf, bufSize, aAllocFlags)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
BufferDescriptor descriptor = RGBDescriptor(aSize, aFormat);
|
||||
|
||||
return new ShmemTextureData(descriptor, aMoz2DBackend, shm);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -435,7 +485,7 @@ ShmemTextureData::CreateSimilar(ISurfaceAllocator* aAllocator,
|
||||
TextureFlags aFlags,
|
||||
TextureAllocationFlags aAllocFlags) const
|
||||
{
|
||||
return ShmemTextureData::Create(mSize, mFormat, mMoz2DBackend,
|
||||
return ShmemTextureData::Create(GetSize(), GetFormat(), mMoz2DBackend,
|
||||
aFlags, aAllocFlags, aAllocator);
|
||||
}
|
||||
|
||||
|
@ -6,8 +6,6 @@
|
||||
#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"
|
||||
@ -25,24 +23,27 @@ public:
|
||||
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);
|
||||
|
||||
// It is generally better to use CreateForYCbCr instead.
|
||||
// This creates a half-initialized texture since we don't know the sizes and
|
||||
// offsets in the buffer.
|
||||
static BufferTextureData* CreateForYCbCrWithBufferSize(ISurfaceAllocator* aAllocator,
|
||||
gfx::SurfaceFormat aFormat,
|
||||
int32_t aSize,
|
||||
TextureFlags aTextureFlags);
|
||||
|
||||
virtual bool Lock(OpenMode aMode, FenceHandle*) override { return true; }
|
||||
|
||||
virtual void Unlock() override {}
|
||||
|
||||
virtual gfx::IntSize GetSize() const override { return mSize; }
|
||||
virtual gfx::IntSize GetSize() const override;
|
||||
|
||||
virtual gfx::SurfaceFormat GetFormat() const override { return mFormat; }
|
||||
virtual gfx::SurfaceFormat GetFormat() const override;
|
||||
|
||||
virtual already_AddRefed<gfx::DrawTarget> BorrowDrawTarget() override;
|
||||
|
||||
@ -59,19 +60,26 @@ public:
|
||||
// use TextureClient's default implementation
|
||||
virtual bool UpdateFromSurface(gfx::SourceSurface* aSurface) override;
|
||||
|
||||
// Don't use this.
|
||||
void SetDesciptor(const BufferDescriptor& aDesc);
|
||||
|
||||
protected:
|
||||
static BufferTextureData* CreateInternal(ISurfaceAllocator* aAllocator,
|
||||
const BufferDescriptor& aDesc,
|
||||
gfx::BackendType aMoz2DBackend,
|
||||
int32_t aBufferSize,
|
||||
TextureFlags aTextureFlags);
|
||||
|
||||
virtual uint8_t* GetBuffer() = 0;
|
||||
virtual size_t GetBufferSize() = 0;
|
||||
|
||||
BufferTextureData(gfx::IntSize aSize, gfx::SurfaceFormat aFormat, gfx::BackendType aMoz2DBackend)
|
||||
: mSize(aSize)
|
||||
, mFormat(aFormat)
|
||||
BufferTextureData(const BufferDescriptor& aDescriptor, gfx::BackendType aMoz2DBackend)
|
||||
: mDescriptor(aDescriptor)
|
||||
, mMoz2DBackend(aMoz2DBackend)
|
||||
{}
|
||||
|
||||
RefPtr<gfx::DrawTarget> mDrawTarget;
|
||||
gfx::IntSize mSize;
|
||||
gfx::SurfaceFormat mFormat;
|
||||
BufferDescriptor mDescriptor;
|
||||
gfx::BackendType mMoz2DBackend;
|
||||
};
|
||||
|
||||
|
@ -4,70 +4,27 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "ImageDataSerializer.h"
|
||||
#include <string.h> // for memcpy
|
||||
#include "gfx2DGlue.h" // for SurfaceFormatToImageFormat
|
||||
#include "mozilla/gfx/Point.h" // for IntSize
|
||||
#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
|
||||
#include "mozilla/gfx/2D.h" // for DataSourceSurface, Factory
|
||||
#include "mozilla/gfx/Logging.h" // for gfxDebug
|
||||
#include "mozilla/gfx/Tools.h" // for GetAlignedStride, etc
|
||||
#include "mozilla/gfx/Types.h"
|
||||
#include "mozilla/mozalloc.h" // for operator delete, etc
|
||||
#include "yuv_convert.h" // for ConvertYCbCrToRGB32, etc
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
namespace ImageDataSerializer {
|
||||
|
||||
using namespace gfx;
|
||||
|
||||
// The Data is layed out as follows:
|
||||
//
|
||||
// +-------------------+ -++ --+ <-- ImageDataSerializerBase::mData pointer
|
||||
// | SurfaceBufferInfo | | |
|
||||
// +-------------------+ --+ | offset
|
||||
// | ... | |
|
||||
// +-------------------+ ------+
|
||||
// | |
|
||||
// | data |
|
||||
// | |
|
||||
// +-------------------+
|
||||
#define MOZ_ALIGN_WORD(x) (((x) + 3) & ~3)
|
||||
|
||||
// Structure written at the beginning of the data blob containing the image
|
||||
// (as shown in the figure above). It contains the necessary informations to
|
||||
// read the image in the blob.
|
||||
namespace {
|
||||
struct SurfaceBufferInfo
|
||||
{
|
||||
int32_t width;
|
||||
int32_t height;
|
||||
SurfaceFormat format;
|
||||
|
||||
static int32_t GetOffset()
|
||||
{
|
||||
return GetAlignedStride<16>(sizeof(SurfaceBufferInfo));
|
||||
}
|
||||
};
|
||||
} // namespace
|
||||
|
||||
static SurfaceBufferInfo*
|
||||
GetBufferInfo(uint8_t* aData, size_t aDataSize)
|
||||
{
|
||||
return aDataSize >= sizeof(SurfaceBufferInfo)
|
||||
? reinterpret_cast<SurfaceBufferInfo*>(aData)
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
ImageDataSerializer::InitializeBufferInfo(IntSize aSize,
|
||||
SurfaceFormat aFormat)
|
||||
{
|
||||
SurfaceBufferInfo* info = GetBufferInfo(mData, mDataSize);
|
||||
MOZ_ASSERT(info); // OK to assert here, this method is client-side-only
|
||||
info->width = aSize.width;
|
||||
info->height = aSize.height;
|
||||
info->format = aFormat;
|
||||
Validate();
|
||||
}
|
||||
|
||||
static inline int32_t
|
||||
ComputeStride(SurfaceFormat aFormat, int32_t aWidth)
|
||||
int32_t
|
||||
ComputeRGBStride(SurfaceFormat aFormat, int32_t aWidth)
|
||||
{
|
||||
CheckedInt<int32_t> size = BytesPerPixel(aFormat);
|
||||
size *= aWidth;
|
||||
@ -79,9 +36,14 @@ ComputeStride(SurfaceFormat aFormat, int32_t aWidth)
|
||||
return GetAlignedStride<4>(size.value());
|
||||
}
|
||||
|
||||
int32_t
|
||||
GetRGBStride(const RGBDescriptor& aDescriptor)
|
||||
{
|
||||
return ComputeRGBStride(aDescriptor.format(), aDescriptor.size().width);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
ImageDataSerializerBase::ComputeMinBufferSize(IntSize aSize,
|
||||
SurfaceFormat aFormat)
|
||||
ComputeRGBBufferSize(IntSize aSize, SurfaceFormat aFormat)
|
||||
{
|
||||
MOZ_ASSERT(aSize.height >= 0 && aSize.width >= 0);
|
||||
|
||||
@ -91,9 +53,8 @@ ImageDataSerializerBase::ComputeMinBufferSize(IntSize aSize,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t bufsize = GetAlignedStride<16>(ComputeStride(aFormat, aSize.width)
|
||||
* aSize.height)
|
||||
+ SurfaceBufferInfo::GetOffset();
|
||||
int32_t bufsize = GetAlignedStride<16>(ComputeRGBStride(aFormat, aSize.width)
|
||||
* aSize.height);
|
||||
|
||||
if (bufsize < 0) {
|
||||
// This should not be possible thanks to Factory::AllowedSurfaceSize
|
||||
@ -103,75 +64,121 @@ ImageDataSerializerBase::ComputeMinBufferSize(IntSize aSize,
|
||||
return bufsize;
|
||||
}
|
||||
|
||||
void
|
||||
ImageDataSerializerBase::Validate()
|
||||
{
|
||||
mIsValid = false;
|
||||
if (!mData) {
|
||||
return;
|
||||
}
|
||||
SurfaceBufferInfo* info = GetBufferInfo(mData, mDataSize);
|
||||
if (!info) {
|
||||
return;
|
||||
}
|
||||
size_t requiredSize =
|
||||
ComputeMinBufferSize(IntSize(info->width, info->height), info->format);
|
||||
|
||||
mIsValid = !!requiredSize && requiredSize <= mDataSize;
|
||||
|
||||
// Minimum required shmem size in bytes
|
||||
uint32_t
|
||||
ComputeYCbCrBufferSize(const gfx::IntSize& aYSize, int32_t aYStride,
|
||||
const gfx::IntSize& aCbCrSize, int32_t aCbCrStride)
|
||||
{
|
||||
MOZ_ASSERT(aYSize.height >= 0 && aYSize.width >= 0);
|
||||
|
||||
if (aYSize.height < 0 || aYSize.width < 0 || aCbCrSize.height < 0 || aCbCrSize.width < 0 ||
|
||||
aYSize.width > aYStride || aCbCrSize.width > aCbCrStride ||
|
||||
aCbCrStride > aYStride || aCbCrSize.height > aYSize.height ||
|
||||
!gfx::Factory::AllowedSurfaceSize(IntSize(aYStride, aYSize.height))) {
|
||||
return 0;
|
||||
}
|
||||
// Overflow checks are performed in AllowedSurfaceSize
|
||||
return MOZ_ALIGN_WORD(aYSize.height * aYStride)
|
||||
+ 2 * MOZ_ALIGN_WORD(aCbCrSize.height * aCbCrStride);
|
||||
}
|
||||
|
||||
uint8_t*
|
||||
ImageDataSerializerBase::GetData()
|
||||
// Minimum required shmem size in bytes
|
||||
uint32_t
|
||||
ComputeYCbCrBufferSize(const gfx::IntSize& aYSize, const gfx::IntSize& aCbCrSize)
|
||||
{
|
||||
MOZ_ASSERT(IsValid());
|
||||
return mData + SurfaceBufferInfo::GetOffset();
|
||||
return ComputeYCbCrBufferSize(aYSize, aYSize.width, aCbCrSize, aCbCrSize.width);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
ImageDataSerializerBase::GetStride() const
|
||||
ComputeYCbCrBufferSize(uint32_t aBufferSize)
|
||||
{
|
||||
MOZ_ASSERT(IsValid());
|
||||
SurfaceBufferInfo* info = GetBufferInfo(mData, mDataSize);
|
||||
return ComputeStride(GetFormat(), info->width);
|
||||
return MOZ_ALIGN_WORD(aBufferSize);
|
||||
}
|
||||
|
||||
IntSize
|
||||
ImageDataSerializerBase::GetSize() const
|
||||
void ComputeYCbCrOffsets(int32_t yStride, int32_t yHeight,
|
||||
int32_t cbCrStride, int32_t cbCrHeight,
|
||||
uint32_t& outYOffset, uint32_t& outCbOffset, uint32_t& outCrOffset)
|
||||
{
|
||||
MOZ_ASSERT(IsValid());
|
||||
SurfaceBufferInfo* info = GetBufferInfo(mData, mDataSize);
|
||||
return IntSize(info->width, info->height);
|
||||
outYOffset = 0;
|
||||
outCbOffset = outYOffset + MOZ_ALIGN_WORD(yStride * yHeight);
|
||||
outCrOffset = outCbOffset + MOZ_ALIGN_WORD(cbCrStride * cbCrHeight);
|
||||
}
|
||||
|
||||
SurfaceFormat
|
||||
ImageDataSerializerBase::GetFormat() const
|
||||
gfx::SurfaceFormat FormatFromBufferDescriptor(const BufferDescriptor& aDescriptor)
|
||||
{
|
||||
MOZ_ASSERT(IsValid());
|
||||
return GetBufferInfo(mData, mDataSize)->format;
|
||||
}
|
||||
|
||||
already_AddRefed<DrawTarget>
|
||||
ImageDataSerializerBase::GetAsDrawTarget(gfx::BackendType aBackend)
|
||||
{
|
||||
MOZ_ASSERT(IsValid());
|
||||
RefPtr<DrawTarget> dt = gfx::Factory::CreateDrawTargetForData(aBackend,
|
||||
GetData(), GetSize(),
|
||||
GetStride(), GetFormat());
|
||||
if (!dt) {
|
||||
gfxCriticalNote << "Failed GetAsDrawTarget " << IsValid() << ", " << hexa(size_t(mData)) << " + " << SurfaceBufferInfo::GetOffset() << ", " << GetSize() << ", " << GetStride() << ", " << (int)GetFormat();
|
||||
switch (aDescriptor.type()) {
|
||||
case BufferDescriptor::TRGBDescriptor:
|
||||
return aDescriptor.get_RGBDescriptor().format();
|
||||
case BufferDescriptor::TYCbCrDescriptor:
|
||||
return gfx::SurfaceFormat::YUV;
|
||||
default:
|
||||
MOZ_CRASH();
|
||||
}
|
||||
return dt.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<gfx::DataSourceSurface>
|
||||
ImageDataSerializerBase::GetAsSurface()
|
||||
gfx::IntSize SizeFromBufferDescriptor(const BufferDescriptor& aDescriptor)
|
||||
{
|
||||
MOZ_ASSERT(IsValid());
|
||||
return Factory::CreateWrappingDataSourceSurface(GetData(),
|
||||
GetStride(),
|
||||
GetSize(),
|
||||
GetFormat());
|
||||
switch (aDescriptor.type()) {
|
||||
case BufferDescriptor::TRGBDescriptor:
|
||||
return aDescriptor.get_RGBDescriptor().size();
|
||||
case BufferDescriptor::TYCbCrDescriptor:
|
||||
return aDescriptor.get_YCbCrDescriptor().ySize();
|
||||
default:
|
||||
MOZ_CRASH();
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t* GetYChannel(uint8_t* aBuffer, const YCbCrDescriptor& aDescriptor)
|
||||
{
|
||||
return aBuffer + aDescriptor.yOffset();
|
||||
}
|
||||
|
||||
uint8_t* GetCbChannel(uint8_t* aBuffer, const YCbCrDescriptor& aDescriptor)
|
||||
{
|
||||
return aBuffer + aDescriptor.cbOffset();
|
||||
}
|
||||
|
||||
uint8_t* GetCrChannel(uint8_t* aBuffer, const YCbCrDescriptor& aDescriptor)
|
||||
{
|
||||
return aBuffer + aDescriptor.crOffset();
|
||||
}
|
||||
|
||||
already_AddRefed<DataSourceSurface>
|
||||
DataSourceSurfaceFromYCbCrDescriptor(uint8_t* aBuffer, const YCbCrDescriptor& aDescriptor)
|
||||
{
|
||||
gfx::IntSize ySize = aDescriptor.ySize();
|
||||
gfx::IntSize cbCrSize = aDescriptor.cbCrSize();
|
||||
int32_t yStride = ySize.width;
|
||||
int32_t cbCrStride = cbCrSize.width;
|
||||
|
||||
RefPtr<DataSourceSurface> result =
|
||||
Factory::CreateDataSourceSurface(ySize, gfx::SurfaceFormat::B8G8R8X8);
|
||||
if (NS_WARN_IF(!result)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
DataSourceSurface::MappedSurface map;
|
||||
if (NS_WARN_IF(!result->Map(DataSourceSurface::MapType::WRITE, &map))) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
gfx::YUVType type = TypeFromSize(ySize.width, ySize.height,
|
||||
cbCrSize.width, cbCrSize.height);
|
||||
gfx::ConvertYCbCrToRGB32(GetYChannel(aBuffer, aDescriptor),
|
||||
GetCbChannel(aBuffer, aDescriptor),
|
||||
GetCrChannel(aBuffer, aDescriptor),
|
||||
map.mData,
|
||||
0, 0, //pic x and y
|
||||
ySize.width, ySize.height,
|
||||
yStride, cbCrStride,
|
||||
map.mStride, type);
|
||||
result->Unmap();
|
||||
return result.forget();
|
||||
}
|
||||
|
||||
|
||||
} // namespace ImageDataSerializer
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
@ -24,72 +24,49 @@ class DrawTarget;
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
class ImageDataSerializerBase
|
||||
{
|
||||
public:
|
||||
bool IsValid() const { return mIsValid; }
|
||||
namespace ImageDataSerializer {
|
||||
|
||||
uint8_t* GetData();
|
||||
uint32_t GetStride() const;
|
||||
gfx::IntSize GetSize() const;
|
||||
gfx::SurfaceFormat GetFormat() const;
|
||||
already_AddRefed<gfx::DataSourceSurface> GetAsSurface();
|
||||
already_AddRefed<gfx::DrawTarget> GetAsDrawTarget(gfx::BackendType aBackend);
|
||||
// RGB
|
||||
|
||||
static uint32_t ComputeMinBufferSize(gfx::IntSize aSize,
|
||||
gfx::SurfaceFormat aFormat);
|
||||
int32_t ComputeRGBStride(gfx::SurfaceFormat aFormat, int32_t aWidth);
|
||||
|
||||
size_t GetBufferSize() const { return mDataSize; }
|
||||
int32_t GetRGBStride(const RGBDescriptor& aDescriptor);
|
||||
|
||||
protected:
|
||||
uint32_t ComputeRGBBufferSize(gfx::IntSize aSize, gfx::SurfaceFormat aFormat);
|
||||
|
||||
ImageDataSerializerBase(uint8_t* aData, size_t aDataSize)
|
||||
: mData(aData)
|
||||
, mDataSize(aDataSize)
|
||||
, mIsValid(false)
|
||||
{}
|
||||
|
||||
void Validate();
|
||||
// YCbCr
|
||||
|
||||
uint8_t* mData;
|
||||
size_t mDataSize;
|
||||
bool mIsValid;
|
||||
};
|
||||
///This function is meant as a helper to know how much shared memory we need
|
||||
///to allocate in a shmem in order to place a shared YCbCr image blob of
|
||||
///given dimensions.
|
||||
uint32_t ComputeYCbCrBufferSize(const gfx::IntSize& aYSize,
|
||||
int32_t aYStride,
|
||||
const gfx::IntSize& aCbCrSize,
|
||||
int32_t aCbCrStride);
|
||||
uint32_t ComputeYCbCrBufferSize(const gfx::IntSize& aYSize,
|
||||
const gfx::IntSize& aCbCrSize);
|
||||
|
||||
/**
|
||||
* A facility to serialize an image into a buffer of memory.
|
||||
* This is intended for use with the IPC code, in order to copy image data
|
||||
* into shared memory.
|
||||
* Note that there is a separate serializer class for YCbCr images
|
||||
* (see YCbCrImageDataSerializer.h).
|
||||
*/
|
||||
class MOZ_STACK_CLASS ImageDataSerializer : public ImageDataSerializerBase
|
||||
{
|
||||
public:
|
||||
ImageDataSerializer(uint8_t* aData, size_t aDataSize)
|
||||
: ImageDataSerializerBase(aData, aDataSize)
|
||||
{
|
||||
// a serializer needs to be usable before correct buffer info has been written to it
|
||||
mIsValid = !!mData;
|
||||
}
|
||||
void InitializeBufferInfo(gfx::IntSize aSize,
|
||||
gfx::SurfaceFormat aFormat);
|
||||
};
|
||||
uint32_t ComputeYCbCrBufferSize(uint32_t aBufferSize);
|
||||
|
||||
/**
|
||||
* A facility to deserialize image data that has been serialized by an
|
||||
* ImageDataSerializer.
|
||||
*/
|
||||
class MOZ_STACK_CLASS ImageDataDeserializer : public ImageDataSerializerBase
|
||||
{
|
||||
public:
|
||||
ImageDataDeserializer(uint8_t* aData, size_t aDataSize)
|
||||
: ImageDataSerializerBase(aData, aDataSize)
|
||||
{
|
||||
Validate();
|
||||
}
|
||||
void ComputeYCbCrOffsets(int32_t yStride, int32_t yHeight,
|
||||
int32_t cbCrStride, int32_t cbCrHeight,
|
||||
uint32_t& outYOffset, uint32_t& outCbOffset, uint32_t& outCrOffset);
|
||||
|
||||
};
|
||||
gfx::SurfaceFormat FormatFromBufferDescriptor(const BufferDescriptor& aDescriptor);
|
||||
|
||||
gfx::IntSize SizeFromBufferDescriptor(const BufferDescriptor& aDescriptor);
|
||||
|
||||
uint8_t* GetYChannel(uint8_t* aBuffer, const YCbCrDescriptor& aDescriptor);
|
||||
|
||||
uint8_t* GetCbChannel(uint8_t* aBuffer, const YCbCrDescriptor& aDescriptor);
|
||||
|
||||
uint8_t* GetCrChannel(uint8_t* aBuffer, const YCbCrDescriptor& aDescriptor);
|
||||
|
||||
already_AddRefed<gfx::DataSourceSurface>
|
||||
DataSourceSurfaceFromYCbCrDescriptor(uint8_t* aBuffer, const YCbCrDescriptor& aDescriptor);
|
||||
|
||||
} // ImageDataSerializer
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
@ -1,317 +0,0 @@
|
||||
/* -*- 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 "mozilla/layers/YCbCrImageDataSerializer.h"
|
||||
#include <string.h> // for memcpy
|
||||
#include "mozilla/gfx/2D.h" // for DataSourceSurface, Factory
|
||||
#include "mozilla/gfx/BaseSize.h" // for BaseSize
|
||||
#include "mozilla/gfx/Logging.h" // for gfxDebug
|
||||
#include "mozilla/gfx/Types.h"
|
||||
#include "mozilla/mozalloc.h" // for operator delete
|
||||
#include "nsDebug.h" // for NS_WARN_IF
|
||||
#include "yuv_convert.h" // for ConvertYCbCrToRGB32, etc
|
||||
#include "nsDebug.h"
|
||||
|
||||
#define MOZ_ALIGN_WORD(x) (((x) + 3) & ~3)
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
using namespace gfx;
|
||||
|
||||
namespace layers {
|
||||
|
||||
// The Data is layed out as follows:
|
||||
//
|
||||
// +-----------------+ -++ --+ --+ <-- Beginning of the buffer
|
||||
// | YCbCrBufferInfo | | | |
|
||||
// +-----------------+ --+ | |
|
||||
// | data | | | YCbCrBufferInfo->[mY/mCb/mCr]Offset
|
||||
// +-----------------+ ------+ |
|
||||
// | data | |
|
||||
// +-----------------+ ----------+
|
||||
// | data |
|
||||
// +-----------------+
|
||||
//
|
||||
// There can be padding between the blocks above to keep word alignment.
|
||||
|
||||
// Structure written at the beginning og the data blob containing the image
|
||||
// (as shown in the figure above). It contains the necessary informations to
|
||||
// read the image in the blob.
|
||||
struct YCbCrBufferInfo
|
||||
{
|
||||
uint32_t mYOffset;
|
||||
uint32_t mCbOffset;
|
||||
uint32_t mCrOffset;
|
||||
uint32_t mYStride;
|
||||
uint32_t mYWidth;
|
||||
uint32_t mYHeight;
|
||||
uint32_t mCbCrStride;
|
||||
uint32_t mCbCrWidth;
|
||||
uint32_t mCbCrHeight;
|
||||
StereoMode mStereoMode;
|
||||
};
|
||||
|
||||
static YCbCrBufferInfo* GetYCbCrBufferInfo(uint8_t* aData, size_t aDataSize)
|
||||
{
|
||||
return aDataSize >= sizeof(YCbCrBufferInfo)
|
||||
? reinterpret_cast<YCbCrBufferInfo*>(aData)
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
void YCbCrImageDataDeserializerBase::Validate()
|
||||
{
|
||||
mIsValid = false;
|
||||
if (!mData) {
|
||||
return;
|
||||
}
|
||||
YCbCrBufferInfo* info = GetYCbCrBufferInfo(mData, mDataSize);
|
||||
if (!info) {
|
||||
return;
|
||||
}
|
||||
size_t requiredSize = ComputeMinBufferSize(
|
||||
IntSize(info->mYWidth, info->mYHeight),
|
||||
info->mYStride,
|
||||
IntSize(info->mCbCrWidth, info->mCbCrHeight),
|
||||
info->mCbCrStride);
|
||||
mIsValid = requiredSize <= mDataSize;
|
||||
|
||||
}
|
||||
|
||||
uint8_t* YCbCrImageDataDeserializerBase::GetYData()
|
||||
{
|
||||
YCbCrBufferInfo* info = GetYCbCrBufferInfo(mData, mDataSize);
|
||||
return reinterpret_cast<uint8_t*>(info) + info->mYOffset;
|
||||
}
|
||||
|
||||
uint8_t* YCbCrImageDataDeserializerBase::GetCbData()
|
||||
{
|
||||
YCbCrBufferInfo* info = GetYCbCrBufferInfo(mData, mDataSize);
|
||||
return reinterpret_cast<uint8_t*>(info) + info->mCbOffset;
|
||||
}
|
||||
|
||||
uint8_t* YCbCrImageDataDeserializerBase::GetCrData()
|
||||
{
|
||||
YCbCrBufferInfo* info = GetYCbCrBufferInfo(mData, mDataSize);
|
||||
return reinterpret_cast<uint8_t*>(info) + info->mCrOffset;
|
||||
}
|
||||
|
||||
uint8_t* YCbCrImageDataDeserializerBase::GetData()
|
||||
{
|
||||
YCbCrBufferInfo* info = GetYCbCrBufferInfo(mData, mDataSize);
|
||||
return (reinterpret_cast<uint8_t*>(info)) + MOZ_ALIGN_WORD(sizeof(YCbCrBufferInfo));
|
||||
}
|
||||
|
||||
uint32_t YCbCrImageDataDeserializerBase::GetYStride()
|
||||
{
|
||||
YCbCrBufferInfo* info = GetYCbCrBufferInfo(mData, mDataSize);
|
||||
return info->mYStride;
|
||||
}
|
||||
|
||||
uint32_t YCbCrImageDataDeserializerBase::GetCbCrStride()
|
||||
{
|
||||
YCbCrBufferInfo* info = GetYCbCrBufferInfo(mData, mDataSize);
|
||||
return info->mCbCrStride;
|
||||
}
|
||||
|
||||
gfx::IntSize YCbCrImageDataDeserializerBase::GetYSize()
|
||||
{
|
||||
YCbCrBufferInfo* info = GetYCbCrBufferInfo(mData, mDataSize);
|
||||
return gfx::IntSize(info->mYWidth, info->mYHeight);
|
||||
}
|
||||
|
||||
gfx::IntSize YCbCrImageDataDeserializerBase::GetCbCrSize()
|
||||
{
|
||||
YCbCrBufferInfo* info = GetYCbCrBufferInfo(mData, mDataSize);
|
||||
return gfx::IntSize(info->mCbCrWidth, info->mCbCrHeight);
|
||||
}
|
||||
|
||||
StereoMode YCbCrImageDataDeserializerBase::GetStereoMode()
|
||||
{
|
||||
YCbCrBufferInfo* info = GetYCbCrBufferInfo(mData, mDataSize);
|
||||
return info->mStereoMode;
|
||||
}
|
||||
|
||||
// Offset in bytes
|
||||
static size_t ComputeOffset(uint32_t aHeight, uint32_t aStride)
|
||||
{
|
||||
return MOZ_ALIGN_WORD(aHeight * aStride);
|
||||
}
|
||||
|
||||
// Minimum required shmem size in bytes
|
||||
size_t
|
||||
YCbCrImageDataDeserializerBase::ComputeMinBufferSize(const gfx::IntSize& aYSize,
|
||||
uint32_t aYStride,
|
||||
const gfx::IntSize& aCbCrSize,
|
||||
uint32_t aCbCrStride)
|
||||
{
|
||||
MOZ_ASSERT(aYSize.height >= 0 && aYSize.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 (aYSize != IntSize() &&
|
||||
(!gfx::Factory::AllowedSurfaceSize(aYSize) ||
|
||||
aCbCrSize.width > aYSize.width ||
|
||||
aCbCrSize.height > aYSize.height)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ComputeOffset(aYSize.height, aYStride)
|
||||
+ 2 * ComputeOffset(aCbCrSize.height, aCbCrStride)
|
||||
+ MOZ_ALIGN_WORD(sizeof(YCbCrBufferInfo));
|
||||
}
|
||||
|
||||
// Minimum required shmem size in bytes
|
||||
size_t
|
||||
YCbCrImageDataDeserializerBase::ComputeMinBufferSize(const gfx::IntSize& aYSize,
|
||||
const gfx::IntSize& aCbCrSize)
|
||||
{
|
||||
return ComputeMinBufferSize(aYSize, aYSize.width, aCbCrSize, aCbCrSize.width);
|
||||
}
|
||||
|
||||
// Offset in bytes
|
||||
static size_t ComputeOffset(uint32_t aSize)
|
||||
{
|
||||
return MOZ_ALIGN_WORD(aSize);
|
||||
}
|
||||
|
||||
// Minimum required shmem size in bytes
|
||||
size_t
|
||||
YCbCrImageDataDeserializerBase::ComputeMinBufferSize(uint32_t aSize)
|
||||
{
|
||||
return ComputeOffset(aSize) + MOZ_ALIGN_WORD(sizeof(YCbCrBufferInfo));
|
||||
}
|
||||
|
||||
void
|
||||
YCbCrImageDataSerializer::InitializeBufferInfo(uint32_t aYOffset,
|
||||
uint32_t aCbOffset,
|
||||
uint32_t aCrOffset,
|
||||
uint32_t aYStride,
|
||||
uint32_t aCbCrStride,
|
||||
const gfx::IntSize& aYSize,
|
||||
const gfx::IntSize& aCbCrSize,
|
||||
StereoMode aStereoMode)
|
||||
{
|
||||
YCbCrBufferInfo* info = GetYCbCrBufferInfo(mData, mDataSize);
|
||||
MOZ_ASSERT(info); // OK to assert here, this method is client-side-only
|
||||
uint32_t info_size = MOZ_ALIGN_WORD(sizeof(YCbCrBufferInfo));
|
||||
info->mYOffset = info_size + aYOffset;
|
||||
info->mCbOffset = info_size + aCbOffset;
|
||||
info->mCrOffset = info_size + aCrOffset;
|
||||
info->mYStride = aYStride;
|
||||
info->mYWidth = aYSize.width;
|
||||
info->mYHeight = aYSize.height;
|
||||
info->mCbCrStride = aCbCrStride;
|
||||
info->mCbCrWidth = aCbCrSize.width;
|
||||
info->mCbCrHeight = aCbCrSize.height;
|
||||
info->mStereoMode = aStereoMode;
|
||||
Validate();
|
||||
}
|
||||
|
||||
void
|
||||
YCbCrImageDataSerializer::InitializeBufferInfo(uint32_t aYStride,
|
||||
uint32_t aCbCrStride,
|
||||
const gfx::IntSize& aYSize,
|
||||
const gfx::IntSize& aCbCrSize,
|
||||
StereoMode aStereoMode)
|
||||
{
|
||||
uint32_t yOffset = 0;
|
||||
uint32_t cbOffset = yOffset + MOZ_ALIGN_WORD(aYStride * aYSize.height);
|
||||
uint32_t crOffset = cbOffset + MOZ_ALIGN_WORD(aCbCrStride * aCbCrSize.height);
|
||||
return InitializeBufferInfo(yOffset, cbOffset, crOffset,
|
||||
aYStride, aCbCrStride, aYSize, aCbCrSize, aStereoMode);
|
||||
}
|
||||
|
||||
void
|
||||
YCbCrImageDataSerializer::InitializeBufferInfo(const gfx::IntSize& aYSize,
|
||||
const gfx::IntSize& aCbCrSize,
|
||||
StereoMode aStereoMode)
|
||||
{
|
||||
return InitializeBufferInfo(aYSize.width, aCbCrSize.width, aYSize, aCbCrSize, aStereoMode);
|
||||
}
|
||||
|
||||
static void CopyLineWithSkip(const uint8_t* src, uint8_t* dst, uint32_t len, uint32_t skip) {
|
||||
for (uint32_t i = 0; i < len; ++i) {
|
||||
*dst = *src;
|
||||
src += 1 + skip;
|
||||
++dst;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
YCbCrImageDataSerializer::CopyData(const uint8_t* aYData,
|
||||
const uint8_t* aCbData, const uint8_t* aCrData,
|
||||
gfx::IntSize aYSize, uint32_t aYStride,
|
||||
gfx::IntSize aCbCrSize, uint32_t aCbCrStride,
|
||||
uint32_t aYSkip, uint32_t aCbCrSkip)
|
||||
{
|
||||
if (!IsValid() || GetYSize() != aYSize || GetCbCrSize() != aCbCrSize) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < aYSize.height; ++i) {
|
||||
if (aYSkip == 0) {
|
||||
// fast path
|
||||
memcpy(GetYData() + i * GetYStride(),
|
||||
aYData + i * aYStride,
|
||||
aYSize.width);
|
||||
} else {
|
||||
// slower path
|
||||
CopyLineWithSkip(aYData + i * aYStride,
|
||||
GetYData() + i * GetYStride(),
|
||||
aYSize.width, aYSkip);
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < aCbCrSize.height; ++i) {
|
||||
if (aCbCrSkip == 0) {
|
||||
// fast path
|
||||
memcpy(GetCbData() + i * GetCbCrStride(),
|
||||
aCbData + i * aCbCrStride,
|
||||
aCbCrSize.width);
|
||||
memcpy(GetCrData() + i * GetCbCrStride(),
|
||||
aCrData + i * aCbCrStride,
|
||||
aCbCrSize.width);
|
||||
} else {
|
||||
// slower path
|
||||
CopyLineWithSkip(aCbData + i * aCbCrStride,
|
||||
GetCbData() + i * GetCbCrStride(),
|
||||
aCbCrSize.width, aCbCrSkip);
|
||||
CopyLineWithSkip(aCrData + i * aCbCrStride,
|
||||
GetCrData() + i * GetCbCrStride(),
|
||||
aCbCrSize.width, aCbCrSkip);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
already_AddRefed<DataSourceSurface>
|
||||
YCbCrImageDataDeserializer::ToDataSourceSurface()
|
||||
{
|
||||
RefPtr<DataSourceSurface> result =
|
||||
Factory::CreateDataSourceSurface(GetYSize(), gfx::SurfaceFormat::B8G8R8X8);
|
||||
if (NS_WARN_IF(!result)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
DataSourceSurface::MappedSurface map;
|
||||
if (NS_WARN_IF(!result->Map(DataSourceSurface::MapType::WRITE, &map))) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
gfx::YUVType type = TypeFromSize(GetYSize().width, GetYSize().height,
|
||||
GetCbCrSize().width, GetCbCrSize().height);
|
||||
gfx::ConvertYCbCrToRGB32(GetYData(), GetCbData(), GetCrData(),
|
||||
map.mData,
|
||||
0, 0, //pic x and y
|
||||
GetYSize().width, GetYSize().height,
|
||||
GetYStride(), GetCbCrStride(),
|
||||
map.mStride, type);
|
||||
result->Unmap();
|
||||
return result.forget();
|
||||
}
|
||||
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
@ -1,186 +0,0 @@
|
||||
/* -*- 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_BLOBYCBCRSURFACE_H
|
||||
#define MOZILLA_LAYERS_BLOBYCBCRSURFACE_H
|
||||
|
||||
#include <stddef.h> // for size_t
|
||||
#include <stdint.h> // for uint8_t, uint32_t
|
||||
#include "ImageTypes.h" // for StereoMode
|
||||
#include "mozilla/Attributes.h" // for MOZ_STACK_CLASS
|
||||
#include "mozilla/RefPtr.h" // for already_AddRefed
|
||||
#include "mozilla/gfx/Point.h" // for IntSize
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
class DataSourceSurface;
|
||||
} // namespace gfx
|
||||
|
||||
namespace layers {
|
||||
|
||||
class Image;
|
||||
|
||||
/**
|
||||
* Convenience class to share code between YCbCrImageDataSerializer
|
||||
* and YCbCrImageDataDeserializer.
|
||||
* Do not use it.
|
||||
*/
|
||||
class YCbCrImageDataDeserializerBase
|
||||
{
|
||||
public:
|
||||
bool IsValid() const { return mIsValid; }
|
||||
|
||||
/**
|
||||
* Returns the Y channel data pointer.
|
||||
*/
|
||||
uint8_t* GetYData();
|
||||
/**
|
||||
* Returns the Cb channel data pointer.
|
||||
*/
|
||||
uint8_t* GetCbData();
|
||||
/**
|
||||
* Returns the Cr channel data pointer.
|
||||
*/
|
||||
uint8_t* GetCrData();
|
||||
|
||||
/**
|
||||
* Returns the Y channel stride.
|
||||
*/
|
||||
uint32_t GetYStride();
|
||||
/**
|
||||
* Returns the stride of the Cb and Cr channels.
|
||||
*/
|
||||
uint32_t GetCbCrStride();
|
||||
|
||||
/**
|
||||
* Returns the dimensions of the Y Channel.
|
||||
*/
|
||||
gfx::IntSize GetYSize();
|
||||
|
||||
/**
|
||||
* Returns the dimensions of the Cb and Cr Channel.
|
||||
*/
|
||||
gfx::IntSize GetCbCrSize();
|
||||
|
||||
/**
|
||||
* Stereo mode for the image.
|
||||
*/
|
||||
StereoMode GetStereoMode();
|
||||
|
||||
/**
|
||||
* Return a pointer to the begining of the data buffer.
|
||||
*/
|
||||
uint8_t* GetData();
|
||||
|
||||
/**
|
||||
* This function is meant as a helper to know how much shared memory we need
|
||||
* to allocate in a shmem in order to place a shared YCbCr image blob of
|
||||
* given dimensions.
|
||||
*/
|
||||
static size_t ComputeMinBufferSize(const gfx::IntSize& aYSize,
|
||||
uint32_t aYStride,
|
||||
const gfx::IntSize& aCbCrSize,
|
||||
uint32_t aCbCrStride);
|
||||
static size_t ComputeMinBufferSize(const gfx::IntSize& aYSize,
|
||||
const gfx::IntSize& aCbCrSize);
|
||||
static size_t ComputeMinBufferSize(uint32_t aSize);
|
||||
|
||||
protected:
|
||||
YCbCrImageDataDeserializerBase(uint8_t* aData, size_t aDataSize)
|
||||
: mData (aData)
|
||||
, mDataSize(aDataSize)
|
||||
, mIsValid(false)
|
||||
{}
|
||||
|
||||
void Validate();
|
||||
|
||||
uint8_t* mData;
|
||||
size_t mDataSize;
|
||||
bool mIsValid;
|
||||
};
|
||||
|
||||
/**
|
||||
* A view on a YCbCr image stored with its metadata in a blob of memory.
|
||||
* It is only meant as a convenience to access the image data, and does not own
|
||||
* the data. The instance can live on the stack and used as follows:
|
||||
*
|
||||
* const YCbCrImage& yuv = sharedImage.get_YCbCrImage();
|
||||
* YCbCrImageDataDeserializer deserializer(yuv.data().get<uint8_t>());
|
||||
* if (!deserializer.IsValid()) {
|
||||
* // handle error
|
||||
* }
|
||||
* size = deserializer.GetYSize(); // work with the data, etc...
|
||||
*/
|
||||
class MOZ_STACK_CLASS YCbCrImageDataSerializer : public YCbCrImageDataDeserializerBase
|
||||
{
|
||||
public:
|
||||
YCbCrImageDataSerializer(uint8_t* aData, size_t aDataSize)
|
||||
: YCbCrImageDataDeserializerBase(aData, aDataSize)
|
||||
{
|
||||
// a serializer needs to be usable before correct buffer info has been written to it
|
||||
mIsValid = !!mData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the image informations in the buffer for given dimensions.
|
||||
* The provided pointer should point to the beginning of the (chunk of)
|
||||
* buffer on which we want to store the image.
|
||||
*/
|
||||
void InitializeBufferInfo(uint32_t aYOffset,
|
||||
uint32_t aCbOffset,
|
||||
uint32_t aCrOffset,
|
||||
uint32_t aYStride,
|
||||
uint32_t aCbCrStride,
|
||||
const gfx::IntSize& aYSize,
|
||||
const gfx::IntSize& aCbCrSize,
|
||||
StereoMode aStereoMode);
|
||||
void InitializeBufferInfo(uint32_t aYStride,
|
||||
uint32_t aCbCrStride,
|
||||
const gfx::IntSize& aYSize,
|
||||
const gfx::IntSize& aCbCrSize,
|
||||
StereoMode aStereoMode);
|
||||
void InitializeBufferInfo(const gfx::IntSize& aYSize,
|
||||
const gfx::IntSize& aCbCrSize,
|
||||
StereoMode aStereoMode);
|
||||
bool CopyData(const uint8_t* aYData,
|
||||
const uint8_t* aCbData, const uint8_t* aCrData,
|
||||
gfx::IntSize aYSize, uint32_t aYStride,
|
||||
gfx::IntSize aCbCrSize, uint32_t aCbCrStride,
|
||||
uint32_t aYSkip, uint32_t aCbCrSkip);
|
||||
};
|
||||
|
||||
/**
|
||||
* A view on a YCbCr image stored with its metadata in a blob of memory.
|
||||
* It is only meant as a convenience to access the image data, and does not own
|
||||
* the data. The instance can live on the stack and used as follows:
|
||||
*
|
||||
* const YCbCrImage& yuv = sharedImage.get_YCbCrImage();
|
||||
* YCbCrImageDataDeserializer deserializer(yuv.data().get<uint8_t>());
|
||||
* if (!deserializer.IsValid()) {
|
||||
* // handle error
|
||||
* }
|
||||
* size = deserializer.GetYSize(); // work with the data, etc...
|
||||
*/
|
||||
class MOZ_STACK_CLASS YCbCrImageDataDeserializer : public YCbCrImageDataDeserializerBase
|
||||
{
|
||||
public:
|
||||
YCbCrImageDataDeserializer(uint8_t* aData, size_t aDataSize)
|
||||
: YCbCrImageDataDeserializerBase(aData, aDataSize)
|
||||
{
|
||||
Validate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the YCbCr data into RGB and return a DataSourceSurface.
|
||||
* This is a costly operation, so use it only when YCbCr compositing is
|
||||
* not supported.
|
||||
*/
|
||||
already_AddRefed<gfx::DataSourceSurface> ToDataSourceSurface();
|
||||
};
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
@ -7,7 +7,6 @@
|
||||
#include "BasicLayersImpl.h" // for FillRectWithMask
|
||||
#include "TextureHostBasic.h"
|
||||
#include "mozilla/layers/Effects.h"
|
||||
#include "mozilla/layers/YCbCrImageDataSerializer.h"
|
||||
#include "nsIWidget.h"
|
||||
#include "gfx2DGlue.h"
|
||||
#include "mozilla/gfx/2D.h"
|
||||
|
@ -15,7 +15,6 @@
|
||||
#include "mozilla/layers/ISurfaceAllocator.h"
|
||||
#include "mozilla/layers/ImageDataSerializer.h"
|
||||
#include "mozilla/layers/TextureClientRecycleAllocator.h"
|
||||
#include "mozilla/layers/YCbCrImageDataSerializer.h"
|
||||
#include "nsDebug.h" // for NS_ASSERTION, NS_WARNING, etc
|
||||
#include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, etc
|
||||
#include "ImageContainer.h" // for PlanarYCbCrData, etc
|
||||
@ -838,10 +837,10 @@ TextureClient::CreateForYCbCr(ISurfaceAllocator* aAllocator,
|
||||
|
||||
// static
|
||||
already_AddRefed<TextureClient>
|
||||
TextureClient::CreateWithBufferSize(ISurfaceAllocator* aAllocator,
|
||||
gfx::SurfaceFormat aFormat,
|
||||
size_t aSize,
|
||||
TextureFlags aTextureFlags)
|
||||
TextureClient::CreateForYCbCrWithBufferSize(ISurfaceAllocator* aAllocator,
|
||||
gfx::SurfaceFormat aFormat,
|
||||
size_t aSize,
|
||||
TextureFlags aTextureFlags)
|
||||
{
|
||||
// also test the validity of aAllocator
|
||||
MOZ_ASSERT(aAllocator && aAllocator->IPCOpen());
|
||||
@ -849,8 +848,9 @@ TextureClient::CreateWithBufferSize(ISurfaceAllocator* aAllocator,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
TextureData* data = BufferTextureData::CreateWithBufferSize(aAllocator, aFormat, aSize,
|
||||
aTextureFlags);
|
||||
TextureData* data =
|
||||
BufferTextureData::CreateForYCbCrWithBufferSize(aAllocator, aFormat, aSize,
|
||||
aTextureFlags);
|
||||
if (!data) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -297,10 +297,10 @@ public:
|
||||
// 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<TextureClient>
|
||||
CreateWithBufferSize(ISurfaceAllocator* aAllocator,
|
||||
gfx::SurfaceFormat aFormat,
|
||||
size_t aSize,
|
||||
TextureFlags aTextureFlags);
|
||||
CreateForYCbCrWithBufferSize(ISurfaceAllocator* aAllocator,
|
||||
gfx::SurfaceFormat aFormat,
|
||||
size_t aSize,
|
||||
TextureFlags aTextureFlags);
|
||||
|
||||
// Creates and allocates a TextureClient of the same type.
|
||||
already_AddRefed<TextureClient>
|
||||
|
@ -13,10 +13,9 @@
|
||||
#include "mozilla/layers/CompositableTransactionParent.h" // for CompositableParentManager
|
||||
#include "mozilla/layers/Compositor.h" // for Compositor
|
||||
#include "mozilla/layers/ISurfaceAllocator.h" // for ISurfaceAllocator
|
||||
#include "mozilla/layers/ImageDataSerializer.h"
|
||||
#include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor, etc
|
||||
#include "mozilla/layers/TextureHostOGL.h" // for TextureHostOGL
|
||||
#include "mozilla/layers/YCbCrImageDataSerializer.h"
|
||||
#include "mozilla/layers/ImageDataSerializer.h"
|
||||
#include "nsAString.h"
|
||||
#include "mozilla/RefPtr.h" // for nsRefPtr
|
||||
#include "nsPrintfCString.h" // for nsPrintfCString
|
||||
@ -95,7 +94,8 @@ TextureHost::CreateIPDLActor(CompositableParentManager* aManager,
|
||||
LayersBackend aLayersBackend,
|
||||
TextureFlags aFlags)
|
||||
{
|
||||
if (aSharedData.type() == SurfaceDescriptor::TSurfaceDescriptorMemory &&
|
||||
if (aSharedData.type() == SurfaceDescriptor::TSurfaceDescriptorBuffer &&
|
||||
aSharedData.get_SurfaceDescriptorBuffer().data().type() == MemoryOrShmem::Tuintptr_t &&
|
||||
!aManager->IsSameProcess())
|
||||
{
|
||||
NS_ERROR("A client process is trying to peek at our address space using a MemoryTexture!");
|
||||
@ -202,8 +202,7 @@ TextureHost::Create(const SurfaceDescriptor& aDesc,
|
||||
TextureFlags aFlags)
|
||||
{
|
||||
switch (aDesc.type()) {
|
||||
case SurfaceDescriptor::TSurfaceDescriptorShmem:
|
||||
case SurfaceDescriptor::TSurfaceDescriptorMemory:
|
||||
case SurfaceDescriptor::TSurfaceDescriptorBuffer:
|
||||
case SurfaceDescriptor::TSurfaceDescriptorDIB:
|
||||
case SurfaceDescriptor::TSurfaceDescriptorFileMapping:
|
||||
return CreateBackendIndependentTextureHost(aDesc, aDeallocator, aFlags);
|
||||
@ -252,19 +251,26 @@ CreateBackendIndependentTextureHost(const SurfaceDescriptor& aDesc,
|
||||
{
|
||||
RefPtr<TextureHost> result;
|
||||
switch (aDesc.type()) {
|
||||
case SurfaceDescriptor::TSurfaceDescriptorShmem: {
|
||||
const SurfaceDescriptorShmem& descriptor = aDesc.get_SurfaceDescriptorShmem();
|
||||
result = new ShmemTextureHost(descriptor.data(),
|
||||
descriptor.format(),
|
||||
aDeallocator,
|
||||
aFlags);
|
||||
break;
|
||||
}
|
||||
case SurfaceDescriptor::TSurfaceDescriptorMemory: {
|
||||
const SurfaceDescriptorMemory& descriptor = aDesc.get_SurfaceDescriptorMemory();
|
||||
result = new MemoryTextureHost(reinterpret_cast<uint8_t*>(descriptor.data()),
|
||||
descriptor.format(),
|
||||
aFlags);
|
||||
case SurfaceDescriptor::TSurfaceDescriptorBuffer: {
|
||||
const SurfaceDescriptorBuffer& bufferDesc = aDesc.get_SurfaceDescriptorBuffer();
|
||||
const MemoryOrShmem& data = bufferDesc.data();
|
||||
switch (data.type()) {
|
||||
case MemoryOrShmem::TShmem: {
|
||||
result = new ShmemTextureHost(data.get_Shmem(),
|
||||
bufferDesc.desc(),
|
||||
aDeallocator,
|
||||
aFlags);
|
||||
break;
|
||||
}
|
||||
case MemoryOrShmem::Tuintptr_t: {
|
||||
result = new MemoryTextureHost(reinterpret_cast<uint8_t*>(data.get_uintptr_t()),
|
||||
bufferDesc.desc(),
|
||||
aFlags);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
MOZ_CRASH();
|
||||
}
|
||||
break;
|
||||
}
|
||||
#ifdef XP_WIN
|
||||
@ -368,15 +374,30 @@ TextureSource::~TextureSource()
|
||||
MOZ_COUNT_DTOR(TextureSource);
|
||||
}
|
||||
|
||||
BufferTextureHost::BufferTextureHost(gfx::SurfaceFormat aFormat,
|
||||
BufferTextureHost::BufferTextureHost(const BufferDescriptor& aDesc,
|
||||
TextureFlags aFlags)
|
||||
: TextureHost(aFlags)
|
||||
, mCompositor(nullptr)
|
||||
, mFormat(aFormat)
|
||||
, mUpdateSerial(1)
|
||||
, mLocked(false)
|
||||
, mNeedsFullUpdate(false)
|
||||
{
|
||||
mDescriptor = aDesc;
|
||||
switch (mDescriptor.type()) {
|
||||
case BufferDescriptor::TYCbCrDescriptor: {
|
||||
const YCbCrDescriptor& ycbcr = mDescriptor.get_YCbCrDescriptor();
|
||||
mSize = ycbcr.ySize();
|
||||
mFormat = gfx::SurfaceFormat::YUV;
|
||||
break;
|
||||
}
|
||||
case BufferDescriptor::TRGBDescriptor: {
|
||||
const RGBDescriptor& rgb = mDescriptor.get_RGBDescriptor();
|
||||
mSize = rgb.size();
|
||||
mFormat = rgb.format();
|
||||
break;
|
||||
}
|
||||
default: MOZ_CRASH();
|
||||
}
|
||||
if (aFlags & TextureFlags::COMPONENT_ALPHA) {
|
||||
// One texture of a component alpha texture pair will start out all white.
|
||||
// This hack allows us to easily make sure that white will be uploaded.
|
||||
@ -385,22 +406,6 @@ BufferTextureHost::BufferTextureHost(gfx::SurfaceFormat aFormat,
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
BufferTextureHost::InitSize()
|
||||
{
|
||||
if (mFormat == gfx::SurfaceFormat::YUV) {
|
||||
YCbCrImageDataDeserializer yuvDeserializer(GetBuffer(), GetBufferSize());
|
||||
if (yuvDeserializer.IsValid()) {
|
||||
mSize = yuvDeserializer.GetYSize();
|
||||
}
|
||||
} else if (mFormat != gfx::SurfaceFormat::UNKNOWN) {
|
||||
ImageDataDeserializer deserializer(GetBuffer(), GetBufferSize());
|
||||
if (deserializer.IsValid()) {
|
||||
mSize = deserializer.GetSize();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BufferTextureHost::~BufferTextureHost()
|
||||
{}
|
||||
|
||||
@ -512,7 +517,8 @@ BufferTextureHost::MaybeUpload(nsIntRegion *aRegion)
|
||||
bool
|
||||
BufferTextureHost::Upload(nsIntRegion *aRegion)
|
||||
{
|
||||
if (!GetBuffer()) {
|
||||
uint8_t* buf = GetBuffer();
|
||||
if (!buf) {
|
||||
// We don't have a buffer; a possible cause is that the IPDL actor
|
||||
// is already dead. This inevitably happens as IPDL actors can die
|
||||
// at any time, so we want to silently return in this case.
|
||||
@ -527,11 +533,11 @@ BufferTextureHost::Upload(nsIntRegion *aRegion)
|
||||
NS_WARNING("BufferTextureHost: unsupported format!");
|
||||
return false;
|
||||
} else if (mFormat == gfx::SurfaceFormat::YUV) {
|
||||
YCbCrImageDataDeserializer yuvDeserializer(GetBuffer(), GetBufferSize());
|
||||
MOZ_ASSERT(yuvDeserializer.IsValid());
|
||||
const YCbCrDescriptor& desc = mDescriptor.get_YCbCrDescriptor();
|
||||
|
||||
if (!mCompositor->SupportsEffect(EffectTypes::YCBCR)) {
|
||||
RefPtr<gfx::DataSourceSurface> surf = yuvDeserializer.ToDataSourceSurface();
|
||||
RefPtr<gfx::DataSourceSurface> surf =
|
||||
ImageDataSerializer::DataSourceSurfaceFromYCbCrDescriptor(buf, mDescriptor.get_YCbCrDescriptor());
|
||||
if (NS_WARN_IF(!surf)) {
|
||||
return false;
|
||||
}
|
||||
@ -565,21 +571,20 @@ BufferTextureHost::Upload(nsIntRegion *aRegion)
|
||||
srcV = mFirstSource->GetNextSibling()->GetNextSibling()->AsDataTextureSource();
|
||||
}
|
||||
|
||||
|
||||
RefPtr<gfx::DataSourceSurface> tempY =
|
||||
gfx::Factory::CreateWrappingDataSourceSurface(yuvDeserializer.GetYData(),
|
||||
yuvDeserializer.GetYStride(),
|
||||
yuvDeserializer.GetYSize(),
|
||||
gfx::Factory::CreateWrappingDataSourceSurface(ImageDataSerializer::GetYChannel(buf, desc),
|
||||
desc.ySize().width,
|
||||
desc.ySize(),
|
||||
gfx::SurfaceFormat::A8);
|
||||
RefPtr<gfx::DataSourceSurface> tempCb =
|
||||
gfx::Factory::CreateWrappingDataSourceSurface(yuvDeserializer.GetCbData(),
|
||||
yuvDeserializer.GetCbCrStride(),
|
||||
yuvDeserializer.GetCbCrSize(),
|
||||
gfx::Factory::CreateWrappingDataSourceSurface(ImageDataSerializer::GetCbChannel(buf, desc),
|
||||
desc.cbCrSize().width,
|
||||
desc.cbCrSize(),
|
||||
gfx::SurfaceFormat::A8);
|
||||
RefPtr<gfx::DataSourceSurface> tempCr =
|
||||
gfx::Factory::CreateWrappingDataSourceSurface(yuvDeserializer.GetCrData(),
|
||||
yuvDeserializer.GetCbCrStride(),
|
||||
yuvDeserializer.GetCbCrSize(),
|
||||
gfx::Factory::CreateWrappingDataSourceSurface(ImageDataSerializer::GetCrChannel(buf, desc),
|
||||
desc.cbCrSize().width,
|
||||
desc.cbCrSize(),
|
||||
gfx::SurfaceFormat::A8);
|
||||
// We don't support partial updates for Y U V textures
|
||||
NS_ASSERTION(!aRegion, "Unsupported partial updates for YCbCr textures");
|
||||
@ -602,13 +607,10 @@ BufferTextureHost::Upload(nsIntRegion *aRegion)
|
||||
regionToUpdate = nullptr;
|
||||
}
|
||||
}
|
||||
ImageDataDeserializer deserializer(GetBuffer(), GetBufferSize());
|
||||
if (!deserializer.IsValid()) {
|
||||
NS_ERROR("Failed to deserialize image!");
|
||||
return false;
|
||||
}
|
||||
|
||||
RefPtr<gfx::DataSourceSurface> surf = deserializer.GetAsSurface();
|
||||
RefPtr<gfx::DataSourceSurface> surf =
|
||||
gfx::Factory::CreateWrappingDataSourceSurface(GetBuffer(),
|
||||
ImageDataSerializer::ComputeRGBStride(mFormat, mSize.width), mSize, mFormat);
|
||||
if (!surf) {
|
||||
return false;
|
||||
}
|
||||
@ -630,35 +632,29 @@ BufferTextureHost::GetAsSurface()
|
||||
NS_WARNING("BufferTextureHost: unsupported format!");
|
||||
return nullptr;
|
||||
} else if (mFormat == gfx::SurfaceFormat::YUV) {
|
||||
YCbCrImageDataDeserializer yuvDeserializer(GetBuffer(), GetBufferSize());
|
||||
if (!yuvDeserializer.IsValid()) {
|
||||
return nullptr;
|
||||
}
|
||||
result = yuvDeserializer.ToDataSourceSurface();
|
||||
result = ImageDataSerializer::DataSourceSurfaceFromYCbCrDescriptor(
|
||||
GetBuffer(), mDescriptor.get_YCbCrDescriptor());
|
||||
if (NS_WARN_IF(!result)) {
|
||||
return nullptr;
|
||||
}
|
||||
} else {
|
||||
ImageDataDeserializer deserializer(GetBuffer(), GetBufferSize());
|
||||
if (!deserializer.IsValid()) {
|
||||
NS_ERROR("Failed to deserialize image!");
|
||||
return nullptr;
|
||||
}
|
||||
result = deserializer.GetAsSurface();
|
||||
RefPtr<gfx::DataSourceSurface> surf =
|
||||
gfx::Factory::CreateWrappingDataSourceSurface(GetBuffer(),
|
||||
ImageDataSerializer::GetRGBStride(mDescriptor.get_RGBDescriptor()),
|
||||
mSize, mFormat);
|
||||
}
|
||||
return result.forget();
|
||||
}
|
||||
|
||||
ShmemTextureHost::ShmemTextureHost(const ipc::Shmem& aShmem,
|
||||
gfx::SurfaceFormat aFormat,
|
||||
const BufferDescriptor& aDesc,
|
||||
ISurfaceAllocator* aDeallocator,
|
||||
TextureFlags aFlags)
|
||||
: BufferTextureHost(aFormat, aFlags)
|
||||
: BufferTextureHost(aDesc, aFlags)
|
||||
, mShmem(MakeUnique<ipc::Shmem>(aShmem))
|
||||
, mDeallocator(aDeallocator)
|
||||
{
|
||||
MOZ_COUNT_CTOR(ShmemTextureHost);
|
||||
InitSize();
|
||||
}
|
||||
|
||||
ShmemTextureHost::~ShmemTextureHost()
|
||||
@ -705,13 +701,12 @@ size_t ShmemTextureHost::GetBufferSize()
|
||||
}
|
||||
|
||||
MemoryTextureHost::MemoryTextureHost(uint8_t* aBuffer,
|
||||
gfx::SurfaceFormat aFormat,
|
||||
const BufferDescriptor& aDesc,
|
||||
TextureFlags aFlags)
|
||||
: BufferTextureHost(aFormat, aFlags)
|
||||
: BufferTextureHost(aDesc, aFlags)
|
||||
, mBuffer(aBuffer)
|
||||
{
|
||||
MOZ_COUNT_CTOR(MemoryTextureHost);
|
||||
InitSize();
|
||||
}
|
||||
|
||||
MemoryTextureHost::~MemoryTextureHost()
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "mozilla/layers/CompositorTypes.h" // for TextureFlags, etc
|
||||
#include "mozilla/layers/FenceUtils.h" // for FenceHandle
|
||||
#include "mozilla/layers/LayersTypes.h" // for LayerRenderState, etc
|
||||
#include "mozilla/layers/LayersSurfaces.h"
|
||||
#include "mozilla/mozalloc.h" // for operator delete
|
||||
#include "mozilla/UniquePtr.h" // for UniquePtr
|
||||
#include "nsCOMPtr.h" // for already_AddRefed
|
||||
@ -37,6 +38,7 @@ class Shmem;
|
||||
|
||||
namespace layers {
|
||||
|
||||
class BufferDescriptor;
|
||||
class Compositor;
|
||||
class CompositableParentManager;
|
||||
class SurfaceDescriptor;
|
||||
@ -567,8 +569,7 @@ protected:
|
||||
class BufferTextureHost : public TextureHost
|
||||
{
|
||||
public:
|
||||
BufferTextureHost(gfx::SurfaceFormat aFormat,
|
||||
TextureFlags aFlags);
|
||||
BufferTextureHost(const BufferDescriptor& aDescriptor, TextureFlags aFlags);
|
||||
|
||||
~BufferTextureHost();
|
||||
|
||||
@ -605,15 +606,13 @@ protected:
|
||||
bool Upload(nsIntRegion *aRegion = nullptr);
|
||||
bool MaybeUpload(nsIntRegion *aRegion = nullptr);
|
||||
|
||||
void InitSize();
|
||||
|
||||
virtual void UpdatedInternal(const nsIntRegion* aRegion = nullptr) override;
|
||||
|
||||
BufferDescriptor mDescriptor;
|
||||
RefPtr<Compositor> mCompositor;
|
||||
RefPtr<DataTextureSource> mFirstSource;
|
||||
nsIntRegion mMaybeUpdatedRegion;
|
||||
gfx::IntSize mSize;
|
||||
// format of the data that is shared with the content process.
|
||||
gfx::SurfaceFormat mFormat;
|
||||
uint32_t mUpdateSerial;
|
||||
bool mLocked;
|
||||
@ -629,7 +628,7 @@ class ShmemTextureHost : public BufferTextureHost
|
||||
{
|
||||
public:
|
||||
ShmemTextureHost(const mozilla::ipc::Shmem& aShmem,
|
||||
gfx::SurfaceFormat aFormat,
|
||||
const BufferDescriptor& aDesc,
|
||||
ISurfaceAllocator* aDeallocator,
|
||||
TextureFlags aFlags);
|
||||
|
||||
@ -664,7 +663,7 @@ class MemoryTextureHost : public BufferTextureHost
|
||||
{
|
||||
public:
|
||||
MemoryTextureHost(uint8_t* aBuffer,
|
||||
gfx::SurfaceFormat aFormat,
|
||||
const BufferDescriptor& aDesc,
|
||||
TextureFlags aFlags);
|
||||
|
||||
protected:
|
||||
|
@ -7,7 +7,6 @@
|
||||
#include "CompositorD3D11.h"
|
||||
#include "gfxContext.h"
|
||||
#include "Effects.h"
|
||||
#include "mozilla/layers/YCbCrImageDataSerializer.h"
|
||||
#include "gfxWindowsPlatform.h"
|
||||
#include "gfx2DGlue.h"
|
||||
#include "gfxPrefs.h"
|
||||
@ -665,8 +664,7 @@ CreateTextureHostD3D11(const SurfaceDescriptor& aDesc,
|
||||
{
|
||||
RefPtr<TextureHost> result;
|
||||
switch (aDesc.type()) {
|
||||
case SurfaceDescriptor::TSurfaceDescriptorShmem:
|
||||
case SurfaceDescriptor::TSurfaceDescriptorMemory: {
|
||||
case SurfaceDescriptor::TSurfaceDescriptorBuffer: {
|
||||
result = CreateBackendIndependentTextureHost(aDesc, aDeallocator, aFlags);
|
||||
break;
|
||||
}
|
||||
|
@ -8,7 +8,6 @@
|
||||
#include "gfxContext.h"
|
||||
#include "gfxImageSurface.h"
|
||||
#include "Effects.h"
|
||||
#include "mozilla/layers/YCbCrImageDataSerializer.h"
|
||||
#include "gfxWindowsPlatform.h"
|
||||
#include "gfx2DGlue.h"
|
||||
#include "gfxUtils.h"
|
||||
@ -53,8 +52,7 @@ CreateTextureHostD3D9(const SurfaceDescriptor& aDesc,
|
||||
{
|
||||
RefPtr<TextureHost> result;
|
||||
switch (aDesc.type()) {
|
||||
case SurfaceDescriptor::TSurfaceDescriptorShmem:
|
||||
case SurfaceDescriptor::TSurfaceDescriptorMemory: {
|
||||
case SurfaceDescriptor::TSurfaceDescriptorBuffer: {
|
||||
result = CreateBackendIndependentTextureHost(aDesc, aDeallocator, aFlags);
|
||||
break;
|
||||
}
|
||||
@ -192,7 +190,7 @@ TextureSourceD3D9::InitTextures(DeviceManagerD3D9* aDeviceManager,
|
||||
}
|
||||
|
||||
tmpTexture->GetSurfaceLevel(0, getter_AddRefs(aSurface));
|
||||
|
||||
|
||||
HRESULT hr = aSurface->LockRect(&aLockedRect, nullptr, 0);
|
||||
if (FAILED(hr) || !aLockedRect.pBits) {
|
||||
gfxCriticalError() << "Failed to lock rect initialize texture in D3D9 " << hexa(hr);
|
||||
|
@ -60,38 +60,38 @@ ISurfaceAllocator::Finalize()
|
||||
}
|
||||
|
||||
static inline uint8_t*
|
||||
GetAddressFromDescriptor(const SurfaceDescriptor& aDescriptor, size_t& aSize)
|
||||
GetAddressFromDescriptor(const SurfaceDescriptor& aDescriptor)
|
||||
{
|
||||
MOZ_ASSERT(IsSurfaceDescriptorValid(aDescriptor));
|
||||
MOZ_ASSERT(aDescriptor.type() == SurfaceDescriptor::TSurfaceDescriptorShmem ||
|
||||
aDescriptor.type() == SurfaceDescriptor::TSurfaceDescriptorMemory);
|
||||
if (aDescriptor.type() == SurfaceDescriptor::TSurfaceDescriptorShmem) {
|
||||
Shmem shmem(aDescriptor.get_SurfaceDescriptorShmem().data());
|
||||
aSize = shmem.Size<uint8_t>();
|
||||
return shmem.get<uint8_t>();
|
||||
MOZ_RELEASE_ASSERT(aDescriptor.type() == SurfaceDescriptor::TSurfaceDescriptorBuffer);
|
||||
|
||||
auto memOrShmem = aDescriptor.get_SurfaceDescriptorBuffer().data();
|
||||
if (memOrShmem.type() == MemoryOrShmem::TShmem) {
|
||||
return memOrShmem.get_Shmem().get<uint8_t>();
|
||||
} else {
|
||||
const SurfaceDescriptorMemory& image = aDescriptor.get_SurfaceDescriptorMemory();
|
||||
aSize = std::numeric_limits<size_t>::max();
|
||||
return reinterpret_cast<uint8_t*>(image.data());
|
||||
return reinterpret_cast<uint8_t*>(memOrShmem.get_uintptr_t());
|
||||
}
|
||||
}
|
||||
|
||||
already_AddRefed<gfx::DrawTarget>
|
||||
GetDrawTargetForDescriptor(const SurfaceDescriptor& aDescriptor, gfx::BackendType aBackend)
|
||||
{
|
||||
size_t size;
|
||||
uint8_t* data = GetAddressFromDescriptor(aDescriptor, size);
|
||||
ImageDataDeserializer image(data, size);
|
||||
return image.GetAsDrawTarget(aBackend);
|
||||
uint8_t* data = GetAddressFromDescriptor(aDescriptor);
|
||||
auto rgb = aDescriptor.get_SurfaceDescriptorBuffer().desc().get_RGBDescriptor();
|
||||
uint32_t stride = ImageDataSerializer::GetRGBStride(rgb);
|
||||
return gfx::Factory::CreateDrawTargetForData(gfx::BackendType::CAIRO,
|
||||
data, rgb.size(),
|
||||
stride, rgb.format());
|
||||
}
|
||||
|
||||
already_AddRefed<gfx::DataSourceSurface>
|
||||
GetSurfaceForDescriptor(const SurfaceDescriptor& aDescriptor)
|
||||
{
|
||||
size_t size;
|
||||
uint8_t* data = GetAddressFromDescriptor(aDescriptor, size);
|
||||
ImageDataDeserializer image(data, size);
|
||||
return image.GetAsSurface();
|
||||
uint8_t* data = GetAddressFromDescriptor(aDescriptor);
|
||||
auto rgb = aDescriptor.get_SurfaceDescriptorBuffer().desc().get_RGBDescriptor();
|
||||
uint32_t stride = ImageDataSerializer::GetRGBStride(rgb);
|
||||
return gfx::Factory::CreateWrappingDataSourceSurface(data, stride, rgb.size(),
|
||||
rgb.format());
|
||||
}
|
||||
|
||||
bool
|
||||
@ -116,12 +116,14 @@ ISurfaceAllocator::AllocSurfaceDescriptorWithCaps(const gfx::IntSize& aSize,
|
||||
}
|
||||
gfx::SurfaceFormat format =
|
||||
gfxPlatform::GetPlatform()->Optimal2DFormatForContent(aContent);
|
||||
size_t size = ImageDataSerializer::ComputeMinBufferSize(aSize, format);
|
||||
size_t size = ImageDataSerializer::ComputeRGBBufferSize(aSize, format);
|
||||
if (!size) {
|
||||
return false;
|
||||
}
|
||||
|
||||
MemoryOrShmem bufferDesc;
|
||||
if (IsSameProcess()) {
|
||||
uint8_t *data = new (std::nothrow) uint8_t[size];
|
||||
uint8_t* data = new (std::nothrow) uint8_t[size];
|
||||
if (!data) {
|
||||
return false;
|
||||
}
|
||||
@ -133,7 +135,7 @@ ISurfaceAllocator::AllocSurfaceDescriptorWithCaps(const gfx::IntSize& aSize,
|
||||
memset(data, 0, size);
|
||||
}
|
||||
#endif
|
||||
*aBuffer = SurfaceDescriptorMemory((uintptr_t)data, format);
|
||||
bufferDesc = reinterpret_cast<uintptr_t>(data);
|
||||
} else {
|
||||
|
||||
mozilla::ipc::SharedMemory::SharedMemoryType shmemType = OptimalShmemType();
|
||||
@ -142,19 +144,19 @@ ISurfaceAllocator::AllocSurfaceDescriptorWithCaps(const gfx::IntSize& aSize,
|
||||
return false;
|
||||
}
|
||||
|
||||
*aBuffer = SurfaceDescriptorShmem(shmem, format);
|
||||
bufferDesc = shmem;
|
||||
}
|
||||
|
||||
uint8_t* data = GetAddressFromDescriptor(*aBuffer, size);
|
||||
ImageDataSerializer serializer(data, size);
|
||||
serializer.InitializeBufferInfo(aSize, format);
|
||||
|
||||
*aBuffer = SurfaceDescriptorBuffer(RGBDescriptor(aSize, format), bufferDesc);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
ISurfaceAllocator::IsShmem(SurfaceDescriptor* aSurface)
|
||||
{
|
||||
return aSurface && (aSurface->type() == SurfaceDescriptor::TSurfaceDescriptorShmem);
|
||||
return aSurface && (aSurface->type() == SurfaceDescriptor::TSurfaceDescriptorBuffer)
|
||||
&& (aSurface->get_SurfaceDescriptorBuffer().data().type() == MemoryOrShmem::TShmem);
|
||||
}
|
||||
|
||||
void
|
||||
@ -172,17 +174,18 @@ ISurfaceAllocator::DestroySharedSurface(SurfaceDescriptor* aSurface)
|
||||
if (!IPCOpen()) {
|
||||
return;
|
||||
}
|
||||
switch (aSurface->type()) {
|
||||
case SurfaceDescriptor::TSurfaceDescriptorShmem:
|
||||
DeallocShmem(aSurface->get_SurfaceDescriptorShmem().data());
|
||||
SurfaceDescriptorBuffer& desc = aSurface->get_SurfaceDescriptorBuffer();
|
||||
switch (desc.data().type()) {
|
||||
case MemoryOrShmem::TShmem: {
|
||||
DeallocShmem(desc.data().get_Shmem());
|
||||
break;
|
||||
case SurfaceDescriptor::TSurfaceDescriptorMemory:
|
||||
GfxMemoryImageReporter::WillFree((uint8_t*)aSurface->get_SurfaceDescriptorMemory().data());
|
||||
delete [] (uint8_t*)aSurface->get_SurfaceDescriptorMemory().data();
|
||||
break;
|
||||
case SurfaceDescriptor::Tnull_t:
|
||||
case SurfaceDescriptor::T__None:
|
||||
}
|
||||
case MemoryOrShmem::Tuintptr_t: {
|
||||
uint8_t* ptr = (uint8_t*)desc.data().get_uintptr_t();
|
||||
GfxMemoryImageReporter::WillFree(ptr);
|
||||
delete [] ptr;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
NS_RUNTIMEABORT("surface type not implemented!");
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ using nsIntRegion from "nsRegion.h";
|
||||
using struct mozilla::layers::MagicGrallocBufferHandle from "gfxipc/ShadowLayerUtils.h";
|
||||
using struct mozilla::layers::GrallocBufferRef from "gfxipc/ShadowLayerUtils.h";
|
||||
using struct mozilla::layers::SurfaceDescriptorX11 from "gfxipc/ShadowLayerUtils.h";
|
||||
using mozilla::StereoMode from "ImageTypes.h";
|
||||
using struct mozilla::null_t from "ipc/IPCMessageUtils.h";
|
||||
using mozilla::WindowsHandle from "ipc/IPCMessageUtils.h";
|
||||
using mozilla::gfx::SurfaceFormat from "mozilla/gfx/Types.h";
|
||||
@ -95,25 +96,37 @@ struct SurfaceDescriptorGralloc {
|
||||
bool isOpaque;
|
||||
};
|
||||
|
||||
/**
|
||||
* Used for shmem-backed YCbCr and (flavors of) RGBA textures
|
||||
*/
|
||||
struct SurfaceDescriptorShmem {
|
||||
Shmem data;
|
||||
struct RGBDescriptor {
|
||||
IntSize size;
|
||||
SurfaceFormat format;
|
||||
};
|
||||
|
||||
/**
|
||||
* Used for "raw memory"-backed YCbCr and (flavors of) RGBA textures
|
||||
*/
|
||||
struct SurfaceDescriptorMemory {
|
||||
uintptr_t data;
|
||||
SurfaceFormat format;
|
||||
struct YCbCrDescriptor {
|
||||
IntSize ySize;
|
||||
IntSize cbCrSize;
|
||||
uint32_t yOffset;
|
||||
uint32_t cbOffset;
|
||||
uint32_t crOffset;
|
||||
StereoMode stereoMode;
|
||||
};
|
||||
|
||||
union BufferDescriptor {
|
||||
RGBDescriptor;
|
||||
YCbCrDescriptor;
|
||||
};
|
||||
|
||||
union MemoryOrShmem {
|
||||
uintptr_t;
|
||||
Shmem;
|
||||
};
|
||||
|
||||
struct SurfaceDescriptorBuffer {
|
||||
BufferDescriptor desc;
|
||||
MemoryOrShmem data;
|
||||
};
|
||||
|
||||
union SurfaceDescriptor {
|
||||
SurfaceDescriptorShmem;
|
||||
SurfaceDescriptorMemory;
|
||||
SurfaceDescriptorBuffer;
|
||||
SurfaceDescriptorD3D9;
|
||||
SurfaceDescriptorDIB;
|
||||
SurfaceDescriptorD3D10;
|
||||
|
@ -319,11 +319,12 @@ ShadowLayerForwarder::CheckSurfaceDescriptor(const SurfaceDescriptor* aDescripto
|
||||
return;
|
||||
}
|
||||
|
||||
if (aDescriptor->type() == SurfaceDescriptor::TSurfaceDescriptorShmem) {
|
||||
const SurfaceDescriptorShmem& shmem = aDescriptor->get_SurfaceDescriptorShmem();
|
||||
shmem.data().AssertInvariants();
|
||||
if (aDescriptor->type() == SurfaceDescriptor::TSurfaceDescriptorBuffer &&
|
||||
aDescriptor->get_SurfaceDescriptorBuffer().data().type() == MemoryOrShmem::TShmem) {
|
||||
const Shmem& shmem = aDescriptor->get_SurfaceDescriptorBuffer().data().get_Shmem();
|
||||
shmem.AssertInvariants();
|
||||
MOZ_ASSERT(mShadowManager &&
|
||||
mShadowManager->IsTrackingSharedMemory(shmem.data().mSegment));
|
||||
mShadowManager->IsTrackingSharedMemory(shmem.mSegment));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -15,7 +15,7 @@
|
||||
#include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor, etc
|
||||
#include "mozilla/layers/TextureClient.h"
|
||||
#include "mozilla/layers/BufferTexture.h"
|
||||
#include "mozilla/layers/YCbCrImageDataSerializer.h"
|
||||
#include "mozilla/layers/ImageDataSerializer.h"
|
||||
#include "mozilla/layers/ImageBridgeChild.h" // for ImageBridgeChild
|
||||
#include "mozilla/mozalloc.h" // for operator delete
|
||||
#include "nsISupportsImpl.h" // for Image::AddRef
|
||||
@ -112,14 +112,14 @@ uint8_t*
|
||||
SharedPlanarYCbCrImage::AllocateAndGetNewBuffer(uint32_t aSize)
|
||||
{
|
||||
MOZ_ASSERT(!mTextureClient, "This image already has allocated data");
|
||||
size_t size = YCbCrImageDataSerializer::ComputeMinBufferSize(aSize);
|
||||
size_t size = ImageDataSerializer::ComputeYCbCrBufferSize(aSize);
|
||||
if (!size) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
mTextureClient = TextureClient::CreateWithBufferSize(mCompositable->GetForwarder(),
|
||||
gfx::SurfaceFormat::YUV, size,
|
||||
mCompositable->GetTextureFlags());
|
||||
mTextureClient = TextureClient::CreateForYCbCrWithBufferSize(mCompositable->GetForwarder(),
|
||||
gfx::SurfaceFormat::YUV, size,
|
||||
mCompositable->GetTextureFlags());
|
||||
|
||||
// get new buffer _without_ setting mBuffer.
|
||||
if (!mTextureClient) {
|
||||
@ -132,11 +132,7 @@ SharedPlanarYCbCrImage::AllocateAndGetNewBuffer(uint32_t aSize)
|
||||
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.
|
||||
// buffer which is where the y channel starts by default.
|
||||
return mapped.y.data;
|
||||
} else {
|
||||
MOZ_CRASH();
|
||||
@ -146,35 +142,26 @@ SharedPlanarYCbCrImage::AllocateAndGetNewBuffer(uint32_t aSize)
|
||||
bool
|
||||
SharedPlanarYCbCrImage::SetDataNoCopy(const Data &aData)
|
||||
{
|
||||
// SetDataNoCopy is used to update YUV plane offsets without (re)allocating
|
||||
// memory previously allocated with AllocateAndGetNewBuffer().
|
||||
|
||||
MOZ_ASSERT(mTextureClient, "This Image should have already allocated data");
|
||||
if (!mTextureClient) {
|
||||
return false;
|
||||
}
|
||||
mData = aData;
|
||||
mSize = aData.mPicSize;
|
||||
/* SetDataNoCopy is used to update YUV plane offsets without (re)allocating
|
||||
* memory previously allocated with AllocateAndGetNewBuffer().
|
||||
* serializer.GetData() returns the address of the memory previously allocated
|
||||
* with AllocateAndGetNewBuffer(), that we subtract from the Y, Cb, Cr
|
||||
* channels to compute 0-based offsets to pass to InitializeBufferInfo.
|
||||
*/
|
||||
MappedYCbCrTextureData mapped;
|
||||
if(!mTextureClient->BorrowMappedYCbCrData(mapped)) {
|
||||
MOZ_CRASH();
|
||||
}
|
||||
YCbCrImageDataSerializer serializer(mapped.metadata, mBufferSize);
|
||||
uint8_t *base = serializer.GetData();
|
||||
|
||||
uint8_t *base = GetBuffer();
|
||||
uint32_t yOffset = aData.mYChannel - base;
|
||||
uint32_t cbOffset = aData.mCbChannel - base;
|
||||
uint32_t crOffset = aData.mCrChannel - base;
|
||||
serializer.InitializeBufferInfo(yOffset,
|
||||
cbOffset,
|
||||
crOffset,
|
||||
aData.mYStride,
|
||||
aData.mCbCrStride,
|
||||
aData.mYSize,
|
||||
aData.mCbCrSize,
|
||||
aData.mStereoMode);
|
||||
|
||||
static_cast<BufferTextureData*>(mTextureClient->GetInternalData())->SetDesciptor(
|
||||
YCbCrDescriptor(aData.mYSize, aData.mCbCrSize, yOffset, cbOffset, crOffset,
|
||||
aData.mStereoMode)
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -232,8 +219,7 @@ SharedPlanarYCbCrImage::Allocate(PlanarYCbCrData& aData)
|
||||
// do not set mBuffer like in PlanarYCbCrImage because the later
|
||||
// will try to manage this memory without knowing it belongs to a
|
||||
// shmem.
|
||||
mBufferSize = YCbCrImageDataSerializer::ComputeMinBufferSize(mData.mYSize,
|
||||
mData.mCbCrSize);
|
||||
mBufferSize = ImageDataSerializer::ComputeYCbCrBufferSize(mData.mYSize, mData.mCbCrSize);
|
||||
mSize = mData.mPicSize;
|
||||
|
||||
mTextureClient->Unlock();
|
||||
|
@ -180,7 +180,6 @@ EXPORTS.mozilla.layers += [
|
||||
'RenderTrace.h',
|
||||
'TextureWrapperImage.h',
|
||||
'TransactionIdAllocator.h',
|
||||
'YCbCrImageDataSerializer.h',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_X11']:
|
||||
@ -352,7 +351,6 @@ UNIFIED_SOURCES += [
|
||||
'RenderTrace.cpp',
|
||||
'RotatedBuffer.cpp',
|
||||
'TextureWrapperImage.cpp',
|
||||
'YCbCrImageDataSerializer.cpp',
|
||||
]
|
||||
|
||||
SOURCES += [
|
||||
|
@ -16,7 +16,6 @@
|
||||
#include "mozilla/gfx/BaseSize.h" // for BaseSize
|
||||
#include "mozilla/gfx/Logging.h" // for gfxCriticalError
|
||||
#include "mozilla/layers/ISurfaceAllocator.h"
|
||||
#include "mozilla/layers/YCbCrImageDataSerializer.h"
|
||||
#include "mozilla/layers/GrallocTextureHost.h"
|
||||
#include "nsRegion.h" // for nsIntRegion
|
||||
#include "AndroidSurfaceTexture.h"
|
||||
@ -52,8 +51,7 @@ CreateTextureHostOGL(const SurfaceDescriptor& aDesc,
|
||||
{
|
||||
RefPtr<TextureHost> result;
|
||||
switch (aDesc.type()) {
|
||||
case SurfaceDescriptor::TSurfaceDescriptorShmem:
|
||||
case SurfaceDescriptor::TSurfaceDescriptorMemory: {
|
||||
case SurfaceDescriptor::TSurfaceDescriptorBuffer: {
|
||||
result = CreateBackendIndependentTextureHost(aDesc,
|
||||
aDeallocator, aFlags);
|
||||
break;
|
||||
|
@ -16,7 +16,7 @@
|
||||
#include "gfxImageSurface.h"
|
||||
#include "gfxTypes.h"
|
||||
#include "ImageContainer.h"
|
||||
#include "mozilla/layers/YCbCrImageDataSerializer.h"
|
||||
#include "mozilla/layers/ImageDataSerializer.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::gfx;
|
||||
@ -119,31 +119,6 @@ void AssertSurfacesEqual(SourceSurface* surface1,
|
||||
dataSurface2->Unmap();
|
||||
}
|
||||
|
||||
// Same as above, for YCbCr surfaces
|
||||
void AssertYCbCrSurfacesEqual(PlanarYCbCrData* surface1,
|
||||
PlanarYCbCrData* surface2)
|
||||
{
|
||||
ASSERT_EQ(surface1->mYSize, surface2->mYSize);
|
||||
ASSERT_EQ(surface1->mCbCrSize, surface2->mCbCrSize);
|
||||
ASSERT_EQ(surface1->mStereoMode, surface2->mStereoMode);
|
||||
ASSERT_EQ(surface1->mPicSize, surface2->mPicSize);
|
||||
|
||||
for (int y = 0; y < surface1->mYSize.height; ++y) {
|
||||
for (int x = 0; x < surface1->mYSize.width; ++x) {
|
||||
ASSERT_EQ(surface1->mYChannel[y*surface1->mYStride + x*(1+surface1->mYSkip)],
|
||||
surface2->mYChannel[y*surface2->mYStride + x*(1+surface2->mYSkip)]);
|
||||
}
|
||||
}
|
||||
for (int y = 0; y < surface1->mCbCrSize.height; ++y) {
|
||||
for (int x = 0; x < surface1->mCbCrSize.width; ++x) {
|
||||
ASSERT_EQ(surface1->mCbChannel[y*surface1->mCbCrStride + x*(1+surface1->mCbSkip)],
|
||||
surface2->mCbChannel[y*surface2->mCbCrStride + x*(1+surface2->mCbSkip)]);
|
||||
ASSERT_EQ(surface1->mCrChannel[y*surface1->mCbCrStride + x*(1+surface1->mCrSkip)],
|
||||
surface2->mCrChannel[y*surface2->mCbCrStride + x*(1+surface2->mCrSkip)]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Run the test for a texture client and a surface
|
||||
void TestTextureClientSurface(TextureClient* texture, gfxImageSurface* surface) {
|
||||
|
||||
@ -206,7 +181,13 @@ void TestTextureClientYCbCr(TextureClient* client, PlanarYCbCrData& ycbcrData) {
|
||||
SurfaceDescriptor descriptor;
|
||||
ASSERT_TRUE(client->ToSurfaceDescriptor(descriptor));
|
||||
|
||||
ASSERT_NE(descriptor.type(), SurfaceDescriptor::Tnull_t);
|
||||
ASSERT_EQ(descriptor.type(), SurfaceDescriptor::TSurfaceDescriptorBuffer);
|
||||
auto bufferDesc = descriptor.get_SurfaceDescriptorBuffer();
|
||||
ASSERT_EQ(bufferDesc.desc().type(), BufferDescriptor::TYCbCrDescriptor);
|
||||
auto ycbcrDesc = bufferDesc.desc().get_YCbCrDescriptor();
|
||||
ASSERT_EQ(ycbcrDesc.ySize(), ycbcrData.mYSize);
|
||||
ASSERT_EQ(ycbcrDesc.cbCrSize(), ycbcrData.mCbCrSize);
|
||||
ASSERT_EQ(ycbcrDesc.stereoMode(), ycbcrData.mStereoMode);
|
||||
|
||||
// host deserialization
|
||||
RefPtr<TextureHost> textureHost = CreateBackendIndependentTextureHost(descriptor, nullptr,
|
||||
@ -222,26 +203,6 @@ void TestTextureClientYCbCr(TextureClient* client, PlanarYCbCrData& ycbcrData) {
|
||||
if (host->Lock()) {
|
||||
// This will work iff the compositor is not BasicCompositor
|
||||
ASSERT_EQ(host->GetFormat(), mozilla::gfx::SurfaceFormat::YUV);
|
||||
|
||||
YCbCrImageDataDeserializer yuvDeserializer(host->GetBuffer(), host->GetBufferSize());
|
||||
ASSERT_TRUE(yuvDeserializer.IsValid());
|
||||
PlanarYCbCrData data;
|
||||
data.mYChannel = yuvDeserializer.GetYData();
|
||||
data.mCbChannel = yuvDeserializer.GetCbData();
|
||||
data.mCrChannel = yuvDeserializer.GetCrData();
|
||||
data.mYStride = yuvDeserializer.GetYStride();
|
||||
data.mCbCrStride = yuvDeserializer.GetCbCrStride();
|
||||
data.mStereoMode = yuvDeserializer.GetStereoMode();
|
||||
data.mYSize = yuvDeserializer.GetYSize();
|
||||
data.mCbCrSize = yuvDeserializer.GetCbCrSize();
|
||||
data.mYSkip = 0;
|
||||
data.mCbSkip = 0;
|
||||
data.mCrSkip = 0;
|
||||
data.mPicSize = data.mYSize;
|
||||
data.mPicX = 0;
|
||||
data.mPicY = 0;
|
||||
|
||||
AssertYCbCrSurfacesEqual(&ycbcrData, &data);
|
||||
host->Unlock();
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user