Bug 1228952 - Move texture metadata out of the BufferTextureClient/Host's buffer. r=Sotaro

This commit is contained in:
Nicolas Silva 2015-12-16 19:50:58 +01:00
parent edb48de851
commit 6a9d93c630
23 changed files with 509 additions and 1000 deletions

View File

@ -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.
*/

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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 += [

View File

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

View File

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