From 9bc4b1d4e681ed5c7eb0d89caba5b94d51d63a28 Mon Sep 17 00:00:00 2001 From: Nicolas Silva Date: Wed, 16 Dec 2015 19:50:58 +0100 Subject: [PATCH] Bug 1228952 - Move texture metadata out of the BufferTextureClient/Host's buffer. r=Sotaro --- gfx/2d/2D.h | 5 + gfx/2d/Factory.cpp | 6 + gfx/ipc/GfxMessageUtils.h | 12 +- gfx/layers/BufferTexture.cpp | 220 +++++++++------ gfx/layers/BufferTexture.h | 36 ++- gfx/layers/ImageDataSerializer.cpp | 217 ++++++++------- gfx/layers/ImageDataSerializer.h | 89 +++--- gfx/layers/YCbCrImageDataSerializer.cpp | 317 ---------------------- gfx/layers/YCbCrImageDataSerializer.h | 186 ------------- gfx/layers/basic/BasicCompositor.cpp | 1 - gfx/layers/client/TextureClient.cpp | 14 +- gfx/layers/client/TextureClient.h | 8 +- gfx/layers/composite/TextureHost.cpp | 141 +++++----- gfx/layers/composite/TextureHost.h | 13 +- gfx/layers/d3d11/TextureD3D11.cpp | 4 +- gfx/layers/d3d9/TextureD3D9.cpp | 6 +- gfx/layers/ipc/ISurfaceAllocator.cpp | 75 ++--- gfx/layers/ipc/LayersSurfaces.ipdlh | 39 ++- gfx/layers/ipc/ShadowLayers.cpp | 9 +- gfx/layers/ipc/SharedPlanarYCbCrImage.cpp | 50 ++-- gfx/layers/moz.build | 2 - gfx/layers/opengl/TextureHostOGL.cpp | 4 +- gfx/tests/gtest/TestTextures.cpp | 55 +--- 23 files changed, 509 insertions(+), 1000 deletions(-) delete mode 100644 gfx/layers/YCbCrImageDataSerializer.cpp delete mode 100644 gfx/layers/YCbCrImageDataSerializer.h diff --git a/gfx/2d/2D.h b/gfx/2d/2D.h index 2135a3b0982d..93acfacf8a9e 100644 --- a/gfx/2d/2D.h +++ b/gfx/2d/2D.h @@ -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. */ diff --git a/gfx/2d/Factory.cpp b/gfx/2d/Factory.cpp index f99b3a3d5e87..f2da085d34b0 100644 --- a/gfx/2d/Factory.cpp +++ b/gfx/2d/Factory.cpp @@ -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, diff --git a/gfx/ipc/GfxMessageUtils.h b/gfx/ipc/GfxMessageUtils.h index feac536f85be..9be762d23e8d 100644 --- a/gfx/ipc/GfxMessageUtils.h +++ b/gfx/ipc/GfxMessageUtils.h @@ -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 { 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::UNKNOWN> {}; +template <> +struct ParamTraits + : public ContiguousEnumSerializer< + mozilla::StereoMode, + mozilla::StereoMode::MONO, + mozilla::StereoMode::TOP_BOTTOM> +{}; + template <> struct ParamTraits { @@ -847,6 +856,7 @@ struct ParamTraits } }; + template <> struct ParamTraits { diff --git a/gfx/layers/BufferTexture.cpp b/gfx/layers/BufferTexture.cpp index 64c9f07ab29b..2702a74e3dcf 100644 --- a/gfx/layers/BufferTexture.cpp +++ b/gfx/layers/BufferTexture.cpp @@ -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()); @@ -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 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 surface = serializer.GetAsSurface(); + uint32_t stride = ImageDataSerializer::GetRGBStride(rgb); + RefPtr 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(mBuffer), - GetFormat()); + uintptr_t ptr = reinterpret_cast(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(); - - 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); } diff --git a/gfx/layers/BufferTexture.h b/gfx/layers/BufferTexture.h index 01996777c54a..c22424ca4826 100644 --- a/gfx/layers/BufferTexture.h +++ b/gfx/layers/BufferTexture.h @@ -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 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 mDrawTarget; - gfx::IntSize mSize; - gfx::SurfaceFormat mFormat; + BufferDescriptor mDescriptor; gfx::BackendType mMoz2DBackend; }; diff --git a/gfx/layers/ImageDataSerializer.cpp b/gfx/layers/ImageDataSerializer.cpp index 0ca952c69947..bdda54671570 100644 --- a/gfx/layers/ImageDataSerializer.cpp +++ b/gfx/layers/ImageDataSerializer.cpp @@ -4,70 +4,27 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "ImageDataSerializer.h" +#include // 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(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 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 -ImageDataSerializerBase::GetAsDrawTarget(gfx::BackendType aBackend) -{ - MOZ_ASSERT(IsValid()); - RefPtr 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 -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 +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 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 diff --git a/gfx/layers/ImageDataSerializer.h b/gfx/layers/ImageDataSerializer.h index ffbf5cfcebc9..85afa41975d0 100644 --- a/gfx/layers/ImageDataSerializer.h +++ b/gfx/layers/ImageDataSerializer.h @@ -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 GetAsSurface(); - already_AddRefed 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 +DataSourceSurfaceFromYCbCrDescriptor(uint8_t* aBuffer, const YCbCrDescriptor& aDescriptor); + +} // ImageDataSerializer } // namespace layers } // namespace mozilla diff --git a/gfx/layers/YCbCrImageDataSerializer.cpp b/gfx/layers/YCbCrImageDataSerializer.cpp deleted file mode 100644 index a04aa0a3a269..000000000000 --- a/gfx/layers/YCbCrImageDataSerializer.cpp +++ /dev/null @@ -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 // 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(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(info) + info->mYOffset; -} - -uint8_t* YCbCrImageDataDeserializerBase::GetCbData() -{ - YCbCrBufferInfo* info = GetYCbCrBufferInfo(mData, mDataSize); - return reinterpret_cast(info) + info->mCbOffset; -} - -uint8_t* YCbCrImageDataDeserializerBase::GetCrData() -{ - YCbCrBufferInfo* info = GetYCbCrBufferInfo(mData, mDataSize); - return reinterpret_cast(info) + info->mCrOffset; -} - -uint8_t* YCbCrImageDataDeserializerBase::GetData() -{ - YCbCrBufferInfo* info = GetYCbCrBufferInfo(mData, mDataSize); - return (reinterpret_cast(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 -YCbCrImageDataDeserializer::ToDataSourceSurface() -{ - RefPtr 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 diff --git a/gfx/layers/YCbCrImageDataSerializer.h b/gfx/layers/YCbCrImageDataSerializer.h deleted file mode 100644 index ec55a85c5d6e..000000000000 --- a/gfx/layers/YCbCrImageDataSerializer.h +++ /dev/null @@ -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 // for size_t -#include // 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()); - * 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()); - * 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 ToDataSourceSurface(); -}; - -} // namespace layers -} // namespace mozilla - -#endif diff --git a/gfx/layers/basic/BasicCompositor.cpp b/gfx/layers/basic/BasicCompositor.cpp index 3cec256efd88..f2fc53ac1fb3 100644 --- a/gfx/layers/basic/BasicCompositor.cpp +++ b/gfx/layers/basic/BasicCompositor.cpp @@ -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" diff --git a/gfx/layers/client/TextureClient.cpp b/gfx/layers/client/TextureClient.cpp index 81c3ef8f9c64..6bb29cb9e170 100644 --- a/gfx/layers/client/TextureClient.cpp +++ b/gfx/layers/client/TextureClient.cpp @@ -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::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; } diff --git a/gfx/layers/client/TextureClient.h b/gfx/layers/client/TextureClient.h index d710d3956080..691f21c231c9 100644 --- a/gfx/layers/client/TextureClient.h +++ b/gfx/layers/client/TextureClient.h @@ -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 - 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 diff --git a/gfx/layers/composite/TextureHost.cpp b/gfx/layers/composite/TextureHost.cpp index d82a0f9c19a2..5f520327cdd8 100644 --- a/gfx/layers/composite/TextureHost.cpp +++ b/gfx/layers/composite/TextureHost.cpp @@ -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 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(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(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 surf = yuvDeserializer.ToDataSourceSurface(); + RefPtr 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 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 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 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 surf = deserializer.GetAsSurface(); + RefPtr 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 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(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() diff --git a/gfx/layers/composite/TextureHost.h b/gfx/layers/composite/TextureHost.h index 22c9685ece21..dadde7d5531b 100644 --- a/gfx/layers/composite/TextureHost.h +++ b/gfx/layers/composite/TextureHost.h @@ -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 mCompositor; RefPtr 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: diff --git a/gfx/layers/d3d11/TextureD3D11.cpp b/gfx/layers/d3d11/TextureD3D11.cpp index 50ef9abde6ca..abde07ae723e 100644 --- a/gfx/layers/d3d11/TextureD3D11.cpp +++ b/gfx/layers/d3d11/TextureD3D11.cpp @@ -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 result; switch (aDesc.type()) { - case SurfaceDescriptor::TSurfaceDescriptorShmem: - case SurfaceDescriptor::TSurfaceDescriptorMemory: { + case SurfaceDescriptor::TSurfaceDescriptorBuffer: { result = CreateBackendIndependentTextureHost(aDesc, aDeallocator, aFlags); break; } diff --git a/gfx/layers/d3d9/TextureD3D9.cpp b/gfx/layers/d3d9/TextureD3D9.cpp index 82f69c516162..169d9d9c33e5 100644 --- a/gfx/layers/d3d9/TextureD3D9.cpp +++ b/gfx/layers/d3d9/TextureD3D9.cpp @@ -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 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); diff --git a/gfx/layers/ipc/ISurfaceAllocator.cpp b/gfx/layers/ipc/ISurfaceAllocator.cpp index c22726b41860..34003e1c66b9 100644 --- a/gfx/layers/ipc/ISurfaceAllocator.cpp +++ b/gfx/layers/ipc/ISurfaceAllocator.cpp @@ -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(); - return shmem.get(); + MOZ_RELEASE_ASSERT(aDescriptor.type() == SurfaceDescriptor::TSurfaceDescriptorBuffer); + + auto memOrShmem = aDescriptor.get_SurfaceDescriptorBuffer().data(); + if (memOrShmem.type() == MemoryOrShmem::TShmem) { + return memOrShmem.get_Shmem().get(); } else { - const SurfaceDescriptorMemory& image = aDescriptor.get_SurfaceDescriptorMemory(); - aSize = std::numeric_limits::max(); - return reinterpret_cast(image.data()); + return reinterpret_cast(memOrShmem.get_uintptr_t()); } } already_AddRefed 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 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(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!"); } diff --git a/gfx/layers/ipc/LayersSurfaces.ipdlh b/gfx/layers/ipc/LayersSurfaces.ipdlh index 4d0f5203359b..bef26df3fe9b 100644 --- a/gfx/layers/ipc/LayersSurfaces.ipdlh +++ b/gfx/layers/ipc/LayersSurfaces.ipdlh @@ -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; diff --git a/gfx/layers/ipc/ShadowLayers.cpp b/gfx/layers/ipc/ShadowLayers.cpp index d07e9dbf8183..6fd94ee82f42 100644 --- a/gfx/layers/ipc/ShadowLayers.cpp +++ b/gfx/layers/ipc/ShadowLayers.cpp @@ -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 diff --git a/gfx/layers/ipc/SharedPlanarYCbCrImage.cpp b/gfx/layers/ipc/SharedPlanarYCbCrImage.cpp index ec4859302fee..aa2c3bbe698e 100644 --- a/gfx/layers/ipc/SharedPlanarYCbCrImage.cpp +++ b/gfx/layers/ipc/SharedPlanarYCbCrImage.cpp @@ -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(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(); diff --git a/gfx/layers/moz.build b/gfx/layers/moz.build index 6918275ee0dd..93efe2d97044 100644 --- a/gfx/layers/moz.build +++ b/gfx/layers/moz.build @@ -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 += [ diff --git a/gfx/layers/opengl/TextureHostOGL.cpp b/gfx/layers/opengl/TextureHostOGL.cpp index f41113cc41af..d4006bb83133 100644 --- a/gfx/layers/opengl/TextureHostOGL.cpp +++ b/gfx/layers/opengl/TextureHostOGL.cpp @@ -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 result; switch (aDesc.type()) { - case SurfaceDescriptor::TSurfaceDescriptorShmem: - case SurfaceDescriptor::TSurfaceDescriptorMemory: { + case SurfaceDescriptor::TSurfaceDescriptorBuffer: { result = CreateBackendIndependentTextureHost(aDesc, aDeallocator, aFlags); break; diff --git a/gfx/tests/gtest/TestTextures.cpp b/gfx/tests/gtest/TestTextures.cpp index cf97cc6da314..c2cde0c452ff 100644 --- a/gfx/tests/gtest/TestTextures.cpp +++ b/gfx/tests/gtest/TestTextures.cpp @@ -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 = 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(); } }