--- a/gfx/2d/Tools.h
+++ b/gfx/2d/Tools.h
@@ -87,30 +87,44 @@ Distance(Point aA, Point aB)
static inline int
BytesPerPixel(SurfaceFormat aFormat)
{
switch (aFormat) {
case SurfaceFormat::A8:
return 1;
case SurfaceFormat::R5G6B5_UINT16:
+ case SurfaceFormat::A16:
return 2;
case SurfaceFormat::R8G8B8:
case SurfaceFormat::B8G8R8:
return 3;
case SurfaceFormat::HSV:
case SurfaceFormat::Lab:
return 3 * sizeof(float);
case SurfaceFormat::Depth:
return sizeof(uint16_t);
default:
return 4;
}
}
+static inline SurfaceFormat
+SurfaceFormatForAlphaBitDepth(uint32_t aBitDepth)
+{
+ if (aBitDepth == 8) {
+ return SurfaceFormat::A8;
+ } else if (aBitDepth == 10 ||
+ aBitDepth == 12) {
+ return SurfaceFormat::A16;
+ }
+ MOZ_ASSERT_UNREACHABLE("Unsupported alpha bit depth");
+ return SurfaceFormat::UNKNOWN;
+}
+
static inline bool
IsOpaqueFormat(SurfaceFormat aFormat) {
switch (aFormat) {
case SurfaceFormat::B8G8R8X8:
case SurfaceFormat::R8G8B8X8:
case SurfaceFormat::X8R8G8B8:
case SurfaceFormat::YUV:
case SurfaceFormat::NV12:
--- a/gfx/2d/Types.h
+++ b/gfx/2d/Types.h
@@ -51,16 +51,17 @@ enum class SurfaceFormat : int8_t {
// The _UINT16 suffix here indicates that the name reflects the layout when
// viewed as a uint16_t value. In memory these values are stored using native
// endianness.
R5G6B5_UINT16, // 0bRRRRRGGGGGGBBBBB
// This one is a single-byte, so endianness isn't an issue.
A8,
+ A16,
R8G8,
// These ones are their own special cases.
YUV,
NV12,
YUV422,
HSV,
--- a/gfx/layers/BufferTexture.cpp
+++ b/gfx/layers/BufferTexture.cpp
@@ -154,67 +154,83 @@ BufferTextureData::CreateInternal(Layers
return new ShmemTextureData(aDesc, aMoz2DBackend, shm);
}
}
BufferTextureData*
BufferTextureData::CreateForYCbCrWithBufferSize(KnowsCompositor* aAllocator,
int32_t aBufferSize,
YUVColorSpace aYUVColorSpace,
+ uint32_t aBitDepth,
TextureFlags aTextureFlags)
{
if (aBufferSize == 0 || !gfx::Factory::CheckBufferSize(aBufferSize)) {
return nullptr;
}
bool hasIntermediateBuffer = aAllocator ? ComputeHasIntermediateBuffer(gfx::SurfaceFormat::YUV,
aAllocator->GetCompositorBackendType())
: true;
// 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.
- BufferDescriptor desc = YCbCrDescriptor(gfx::IntSize(), gfx::IntSize(),
+ BufferDescriptor desc = YCbCrDescriptor(gfx::IntSize(), 0, gfx::IntSize(), 0,
0, 0, 0, StereoMode::MONO,
aYUVColorSpace,
+ aBitDepth,
hasIntermediateBuffer);
return CreateInternal(aAllocator ? aAllocator->GetTextureForwarder() : nullptr,
desc, gfx::BackendType::NONE, aBufferSize, aTextureFlags);
}
BufferTextureData*
BufferTextureData::CreateForYCbCr(KnowsCompositor* aAllocator,
gfx::IntSize aYSize,
+ uint32_t aYStride,
gfx::IntSize aCbCrSize,
+ uint32_t aCbCrStride,
StereoMode aStereoMode,
YUVColorSpace aYUVColorSpace,
+ uint32_t aBitDepth,
TextureFlags aTextureFlags)
{
- uint32_t bufSize = ImageDataSerializer::ComputeYCbCrBufferSize(aYSize, aCbCrSize);
+ uint32_t bufSize = ImageDataSerializer::ComputeYCbCrBufferSize(
+ aYSize, aYStride, aCbCrSize, aCbCrStride);
if (bufSize == 0) {
return nullptr;
}
uint32_t yOffset;
uint32_t cbOffset;
uint32_t crOffset;
- ImageDataSerializer::ComputeYCbCrOffsets(aYSize.width, aYSize.height,
- aCbCrSize.width, aCbCrSize.height,
- yOffset, cbOffset, crOffset);
+ ImageDataSerializer::ComputeYCbCrOffsets(aYStride, aYSize.height,
+ aCbCrStride, aCbCrSize.height,
+ yOffset, cbOffset, crOffset);
- bool hasIntermediateBuffer = aAllocator ? ComputeHasIntermediateBuffer(gfx::SurfaceFormat::YUV,
- aAllocator->GetCompositorBackendType())
- : true;
+ bool hasIntermediateBuffer =
+ aAllocator
+ ? ComputeHasIntermediateBuffer(gfx::SurfaceFormat::YUV,
+ aAllocator->GetCompositorBackendType())
+ : true;
- YCbCrDescriptor descriptor = YCbCrDescriptor(aYSize, aCbCrSize, yOffset, cbOffset,
- crOffset, aStereoMode, aYUVColorSpace,
+ YCbCrDescriptor descriptor = YCbCrDescriptor(aYSize, aYStride,
+ aCbCrSize, aCbCrStride,
+ yOffset, cbOffset, crOffset,
+ aStereoMode,
+ aYUVColorSpace,
+ aBitDepth,
hasIntermediateBuffer);
- return CreateInternal(aAllocator ? aAllocator->GetTextureForwarder() : nullptr, descriptor,
- gfx::BackendType::NONE, bufSize, aTextureFlags);
+ return CreateInternal(aAllocator ? aAllocator->GetTextureForwarder()
+ : nullptr,
+ descriptor,
+ gfx::BackendType::NONE,
+ bufSize,
+ aTextureFlags);
}
void
BufferTextureData::FillInfo(TextureData::Info& aInfo) const
{
aInfo.size = GetSize();
aInfo.format = GetFormat();
aInfo.hasSynchronization = false;
@@ -249,16 +265,22 @@ BufferTextureData::GetCbCrSize() const
}
Maybe<YUVColorSpace>
BufferTextureData::GetYUVColorSpace() const
{
return ImageDataSerializer::YUVColorSpaceFromBufferDescriptor(mDescriptor);
}
+Maybe<uint32_t>
+BufferTextureData::GetBitDepth() const
+{
+ return ImageDataSerializer::BitDepthFromBufferDescriptor(mDescriptor);
+}
+
Maybe<StereoMode>
BufferTextureData::GetStereoMode() const
{
return ImageDataSerializer::StereoModeFromBufferDescriptor(mDescriptor);
}
gfx::SurfaceFormat
BufferTextureData::GetFormat() const
@@ -346,27 +368,27 @@ BufferTextureData::BorrowMappedYCbCrData
auto ySize = desc.ySize();
auto cbCrSize = desc.cbCrSize();
aMap.stereoMode = desc.stereoMode();
aMap.metadata = nullptr;
aMap.y.data = data + desc.yOffset();
aMap.y.size = ySize;
- aMap.y.stride = ySize.width;
+ aMap.y.stride = desc.yStride();
aMap.y.skip = 0;
aMap.cb.data = data + desc.cbOffset();
aMap.cb.size = cbCrSize;
- aMap.cb.stride = cbCrSize.width;
+ aMap.cb.stride = desc.cbCrStride();
aMap.cb.skip = 0;
aMap.cr.data = data + desc.crOffset();
aMap.cr.size = cbCrSize;
- aMap.cr.stride = cbCrSize.width;
+ aMap.cr.stride = desc.cbCrStride();
aMap.cr.skip = 0;
return true;
}
bool
BufferTextureData::UpdateFromSurface(gfx::SourceSurface* aSurface)
{
--- a/gfx/layers/BufferTexture.h
+++ b/gfx/layers/BufferTexture.h
@@ -25,27 +25,31 @@ public:
gfx::BackendType aMoz2DBackend,
LayersBackend aLayersBackend,
TextureFlags aFlags,
TextureAllocationFlags aAllocFlags,
LayersIPCChannel* aAllocator);
static BufferTextureData* CreateForYCbCr(KnowsCompositor* aAllocator,
gfx::IntSize aYSize,
+ uint32_t aYStride,
gfx::IntSize aCbCrSize,
+ uint32_t aCbCrStride,
StereoMode aStereoMode,
YUVColorSpace aYUVColorSpace,
+ uint32_t aBitDepth,
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(KnowsCompositor* aAllocator,
int32_t aSize,
YUVColorSpace aYUVColorSpace,
+ uint32_t aBitDepth,
TextureFlags aTextureFlags);
virtual bool Lock(OpenMode aMode) override { return true; }
virtual void Unlock() override {}
virtual void FillInfo(TextureData::Info& aInfo) const override;
@@ -62,16 +66,18 @@ public:
// Don't use this.
void SetDesciptor(const BufferDescriptor& aDesc);
Maybe<gfx::IntSize> GetCbCrSize() const;
Maybe<YUVColorSpace> GetYUVColorSpace() const;
+ Maybe<uint32_t> GetBitDepth() const;
+
Maybe<StereoMode> GetStereoMode() const;
protected:
gfx::IntSize GetSize() const;
gfx::SurfaceFormat GetFormat() const;
static BufferTextureData* CreateInternal(LayersIPCChannel* aAllocator,
--- a/gfx/layers/Effects.h
+++ b/gfx/layers/Effects.h
@@ -156,24 +156,26 @@ struct EffectRGB : public TexturedEffect
: TexturedEffect(EffectTypes::RGB, aTexture, aPremultiplied, aSamplingFilter)
{}
virtual const char* Name() { return "EffectRGB"; }
};
struct EffectYCbCr : public TexturedEffect
{
- EffectYCbCr(TextureSource *aSource, YUVColorSpace aYUVColorSpace, gfx::SamplingFilter aSamplingFilter)
+ EffectYCbCr(TextureSource *aSource, YUVColorSpace aYUVColorSpace, uint32_t aBitDepth, gfx::SamplingFilter aSamplingFilter)
: TexturedEffect(EffectTypes::YCBCR, aSource, false, aSamplingFilter)
, mYUVColorSpace(aYUVColorSpace)
+ , mBitDepth(aBitDepth)
{}
virtual const char* Name() { return "EffectYCbCr"; }
YUVColorSpace mYUVColorSpace;
+ uint32_t mBitDepth;
};
struct EffectNV12 : public TexturedEffect
{
EffectNV12(TextureSource *aSource, gfx::SamplingFilter aSamplingFilter)
: TexturedEffect(EffectTypes::NV12, aSource, false, aSamplingFilter)
{}
@@ -265,17 +267,18 @@ CreateTexturedEffect(TextureHost* aHost,
bool isAlphaPremultiplied)
{
MOZ_ASSERT(aHost);
MOZ_ASSERT(aSource);
RefPtr<TexturedEffect> result;
if (aHost->GetReadFormat() == gfx::SurfaceFormat::YUV) {
MOZ_ASSERT(aHost->GetYUVColorSpace() != YUVColorSpace::UNKNOWN);
- result = new EffectYCbCr(aSource, aHost->GetYUVColorSpace(), aSamplingFilter);
+ result = new EffectYCbCr(
+ aSource, aHost->GetYUVColorSpace(), aHost->GetBitDepth(), aSamplingFilter);
} else {
result = CreateTexturedEffect(aHost->GetReadFormat(),
aSource,
aSamplingFilter,
isAlphaPremultiplied);
}
return result.forget();
}
--- a/gfx/layers/ImageDataSerializer.cpp
+++ b/gfx/layers/ImageDataSerializer.cpp
@@ -66,28 +66,22 @@ ComputeYCbCrBufferSize(const gfx::IntSiz
{
MOZ_ASSERT(aYSize.height >= 0 && aYSize.width >= 0);
if (aYSize.height < 0 || aYSize.width < 0 || aCbCrSize.height < 0 || aCbCrSize.width < 0 ||
!gfx::Factory::AllowedSurfaceSize(IntSize(aYStride, aYSize.height)) ||
!gfx::Factory::AllowedSurfaceSize(IntSize(aCbCrStride, aCbCrSize.height))) {
return 0;
}
+
// Overflow checks are performed in AllowedSurfaceSize
return GetAlignedStride<4>(aYSize.height, aYStride) +
2 * GetAlignedStride<4>(aCbCrSize.height, aCbCrStride);
}
-// Minimum required shmem size in bytes
-uint32_t
-ComputeYCbCrBufferSize(const gfx::IntSize& aYSize, const gfx::IntSize& aCbCrSize)
-{
- return ComputeYCbCrBufferSize(aYSize, aYSize.width, aCbCrSize, aCbCrSize.width);
-}
-
uint32_t
ComputeYCbCrBufferSize(uint32_t aBufferSize)
{
return GetAlignedStride<4>(aBufferSize, 1);
}
void ComputeYCbCrOffsets(int32_t yStride, int32_t yHeight,
int32_t cbCrStride, int32_t cbCrHeight,
@@ -132,37 +126,47 @@ Maybe<gfx::IntSize> CbCrSizeFromBufferDe
return Some(aDescriptor.get_YCbCrDescriptor().cbCrSize());
default:
MOZ_CRASH("GFX: CbCrSizeFromBufferDescriptor");
}
}
Maybe<YUVColorSpace> YUVColorSpaceFromBufferDescriptor(const BufferDescriptor& aDescriptor)
{
-{
switch (aDescriptor.type()) {
case BufferDescriptor::TRGBDescriptor:
return Nothing();
case BufferDescriptor::TYCbCrDescriptor:
return Some(aDescriptor.get_YCbCrDescriptor().yUVColorSpace());
default:
- MOZ_CRASH("GFX: CbCrSizeFromBufferDescriptor");
+ MOZ_CRASH("GFX: YUVColorSpaceFromBufferDescriptor");
}
}
+
+Maybe<uint32_t> BitDepthFromBufferDescriptor(const BufferDescriptor& aDescriptor)
+{
+ switch (aDescriptor.type()) {
+ case BufferDescriptor::TRGBDescriptor:
+ return Nothing();
+ case BufferDescriptor::TYCbCrDescriptor:
+ return Some(aDescriptor.get_YCbCrDescriptor().bitDepth());
+ default:
+ MOZ_CRASH("GFX: BitDepthFromBufferDescriptor");
+ }
}
Maybe<StereoMode> StereoModeFromBufferDescriptor(const BufferDescriptor& aDescriptor)
{
switch (aDescriptor.type()) {
case BufferDescriptor::TRGBDescriptor:
return Nothing();
case BufferDescriptor::TYCbCrDescriptor:
return Some(aDescriptor.get_YCbCrDescriptor().stereoMode());
default:
- MOZ_CRASH("GFX: CbCrSizeFromBufferDescriptor");
+ MOZ_CRASH("GFX: StereoModeFromBufferDescriptor");
}
}
uint8_t* GetYChannel(uint8_t* aBuffer, const YCbCrDescriptor& aDescriptor)
{
return aBuffer + aDescriptor.yOffset();
}
@@ -175,19 +179,16 @@ uint8_t* GetCrChannel(uint8_t* aBuffer,
{
return aBuffer + aDescriptor.crOffset();
}
already_AddRefed<DataSourceSurface>
DataSourceSurfaceFromYCbCrDescriptor(uint8_t* aBuffer, const YCbCrDescriptor& aDescriptor, gfx::DataSourceSurface* aSurface)
{
gfx::IntSize ySize = aDescriptor.ySize();
- gfx::IntSize cbCrSize = aDescriptor.cbCrSize();
- int32_t yStride = ySize.width;
- int32_t cbCrStride = cbCrSize.width;
RefPtr<DataSourceSurface> result;
if (aSurface) {
MOZ_ASSERT(aSurface->GetSize() == ySize);
MOZ_ASSERT(aSurface->GetFormat() == gfx::SurfaceFormat::B8G8R8X8);
if (aSurface->GetSize() == ySize &&
aSurface->GetFormat() == gfx::SurfaceFormat::B8G8R8X8) {
result = aSurface;
@@ -204,24 +205,25 @@ DataSourceSurfaceFromYCbCrDescriptor(uin
DataSourceSurface::MappedSurface map;
if (NS_WARN_IF(!result->Map(DataSourceSurface::MapType::WRITE, &map))) {
return nullptr;
}
layers::PlanarYCbCrData ycbcrData;
ycbcrData.mYChannel = GetYChannel(aBuffer, aDescriptor);
- ycbcrData.mYStride = yStride;
+ ycbcrData.mYStride = aDescriptor.yStride();
ycbcrData.mYSize = ySize;
ycbcrData.mCbChannel = GetCbChannel(aBuffer, aDescriptor);
ycbcrData.mCrChannel = GetCrChannel(aBuffer, aDescriptor);
- ycbcrData.mCbCrStride = cbCrStride;
- ycbcrData.mCbCrSize = cbCrSize;
+ ycbcrData.mCbCrStride = aDescriptor.cbCrStride();
+ ycbcrData.mCbCrSize = aDescriptor.cbCrSize();
ycbcrData.mPicSize = ySize;
ycbcrData.mYUVColorSpace = aDescriptor.yUVColorSpace();
+ ycbcrData.mBitDepth = aDescriptor.bitDepth();
gfx::ConvertYCbCrToRGB(ycbcrData,
gfx::SurfaceFormat::B8G8R8X8,
ySize,
map.mData,
map.mStride);
result->Unmap();
@@ -232,30 +234,27 @@ void
ConvertAndScaleFromYCbCrDescriptor(uint8_t* aBuffer,
const YCbCrDescriptor& aDescriptor,
const gfx::SurfaceFormat& aDestFormat,
const gfx::IntSize& aDestSize,
unsigned char* aDestBuffer,
int32_t aStride)
{
MOZ_ASSERT(aBuffer);
- gfx::IntSize ySize = aDescriptor.ySize();
- gfx::IntSize cbCrSize = aDescriptor.cbCrSize();
- int32_t yStride = ySize.width;
- int32_t cbCrStride = cbCrSize.width;
layers::PlanarYCbCrData ycbcrData;
ycbcrData.mYChannel = GetYChannel(aBuffer, aDescriptor);
- ycbcrData.mYStride = yStride;
- ycbcrData.mYSize = ySize;
+ ycbcrData.mYStride = aDescriptor.yStride();;
+ ycbcrData.mYSize = aDescriptor.ySize();
ycbcrData.mCbChannel = GetCbChannel(aBuffer, aDescriptor);
ycbcrData.mCrChannel = GetCrChannel(aBuffer, aDescriptor);
- ycbcrData.mCbCrStride = cbCrStride;
- ycbcrData.mCbCrSize = cbCrSize;
- ycbcrData.mPicSize = ySize;
+ ycbcrData.mCbCrStride = aDescriptor.cbCrStride();
+ ycbcrData.mCbCrSize = aDescriptor.cbCrSize();
+ ycbcrData.mPicSize = aDescriptor.ySize();
ycbcrData.mYUVColorSpace = aDescriptor.yUVColorSpace();
+ ycbcrData.mBitDepth = aDescriptor.bitDepth();
gfx::ConvertYCbCrToRGB(ycbcrData, aDestFormat, aDestSize, aDestBuffer, aStride);
}
} // namespace ImageDataSerializer
} // namespace layers
} // namespace mozilla
--- a/gfx/layers/ImageDataSerializer.h
+++ b/gfx/layers/ImageDataSerializer.h
@@ -40,33 +40,32 @@ uint32_t ComputeRGBBufferSize(gfx::IntSi
///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);
-
uint32_t ComputeYCbCrBufferSize(uint32_t aBufferSize);
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);
Maybe<gfx::IntSize> CbCrSizeFromBufferDescriptor(const BufferDescriptor& aDescriptor);
Maybe<YUVColorSpace> YUVColorSpaceFromBufferDescriptor(const BufferDescriptor& aDescriptor);
+Maybe<uint32_t> BitDepthFromBufferDescriptor(const BufferDescriptor& aDescriptor);
+
Maybe<StereoMode> StereoModeFromBufferDescriptor(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);
--- a/gfx/layers/client/ImageClient.cpp
+++ b/gfx/layers/client/ImageClient.cpp
@@ -96,18 +96,21 @@ ImageClient::CreateTextureClientForImage
RefPtr<TextureClient> texture;
if (aImage->GetFormat() == ImageFormat::PLANAR_YCBCR) {
PlanarYCbCrImage* ycbcr = static_cast<PlanarYCbCrImage*>(aImage);
const PlanarYCbCrData* data = ycbcr->GetData();
if (!data) {
return nullptr;
}
texture = TextureClient::CreateForYCbCr(aForwarder,
- data->mYSize, data->mCbCrSize, data->mStereoMode,
+ data->mYSize, data->mYStride,
+ data->mCbCrSize, data->mCbCrStride,
+ data->mStereoMode,
data->mYUVColorSpace,
+ data->mBitDepth,
TextureFlags::DEFAULT);
if (!texture) {
return nullptr;
}
TextureClientAutoLock autoLock(texture, OpenMode::OPEN_WRITE_ONLY);
if (!autoLock.Succeeded()) {
return nullptr;
--- a/gfx/layers/client/TextureClient.cpp
+++ b/gfx/layers/client/TextureClient.cpp
@@ -1251,82 +1251,90 @@ TextureClient::CreateForRawBufferAccess(
return MakeAndAddRef<TextureClient>(texData, aTextureFlags, aAllocator);
}
// static
already_AddRefed<TextureClient>
TextureClient::CreateForYCbCr(KnowsCompositor* aAllocator,
gfx::IntSize aYSize,
+ uint32_t aYStride,
gfx::IntSize aCbCrSize,
+ uint32_t aCbCrStride,
StereoMode aStereoMode,
YUVColorSpace aYUVColorSpace,
+ uint32_t aBitDepth,
TextureFlags aTextureFlags)
{
if (!aAllocator || !aAllocator->GetLayersIPCActor()->IPCOpen()) {
return nullptr;
}
if (!gfx::Factory::AllowedSurfaceSize(aYSize)) {
return nullptr;
}
- TextureData* data = BufferTextureData::CreateForYCbCr(aAllocator, aYSize, aCbCrSize,
- aStereoMode, aYUVColorSpace,
- aTextureFlags);
+ TextureData* data =
+ BufferTextureData::CreateForYCbCr(aAllocator,
+ aYSize, aYStride,
+ aCbCrSize, aCbCrStride,
+ aStereoMode, aYUVColorSpace,
+ aBitDepth, aTextureFlags);
if (!data) {
return nullptr;
}
return MakeAndAddRef<TextureClient>(data, aTextureFlags,
aAllocator->GetTextureForwarder());
}
// static
already_AddRefed<TextureClient>
TextureClient::CreateForYCbCrWithBufferSize(KnowsCompositor* aAllocator,
size_t aSize,
YUVColorSpace aYUVColorSpace,
+ uint32_t aBitDepth,
TextureFlags aTextureFlags)
{
if (!aAllocator || !aAllocator->GetLayersIPCActor()->IPCOpen()) {
return nullptr;
}
- TextureData* data =
- BufferTextureData::CreateForYCbCrWithBufferSize(aAllocator, aSize, aYUVColorSpace,
- aTextureFlags);
+ TextureData* data = BufferTextureData::CreateForYCbCrWithBufferSize(
+ aAllocator, aSize, aYUVColorSpace, aBitDepth, aTextureFlags);
if (!data) {
return nullptr;
}
return MakeAndAddRef<TextureClient>(data, aTextureFlags,
aAllocator->GetTextureForwarder());
}
-TextureClient::TextureClient(TextureData* aData, TextureFlags aFlags, LayersIPCChannel* aAllocator)
-: AtomicRefCountedWithFinalize("TextureClient")
-, mAllocator(aAllocator)
-, mActor(nullptr)
-, mData(aData)
-, mFlags(aFlags)
-, mOpenMode(OpenMode::OPEN_NONE)
+TextureClient::TextureClient(TextureData* aData,
+ TextureFlags aFlags,
+ LayersIPCChannel* aAllocator)
+ : AtomicRefCountedWithFinalize("TextureClient")
+ , mAllocator(aAllocator)
+ , mActor(nullptr)
+ , mData(aData)
+ , mFlags(aFlags)
+ , mOpenMode(OpenMode::OPEN_NONE)
#ifdef DEBUG
-, mExpectedDtRefs(0)
+ , mExpectedDtRefs(0)
#endif
-, mIsLocked(false)
-, mIsReadLocked(false)
-, mUpdated(false)
-, mAddedToCompositableClient(false)
-, mWorkaroundAnnoyingSharedSurfaceLifetimeIssues(false)
-, mWorkaroundAnnoyingSharedSurfaceOwnershipIssues(false)
-, mFwdTransactionId(0)
-, mSerial(++sSerialCounter)
+ , mIsLocked(false)
+ , mIsReadLocked(false)
+ , mUpdated(false)
+ , mAddedToCompositableClient(false)
+ , mWorkaroundAnnoyingSharedSurfaceLifetimeIssues(false)
+ , mWorkaroundAnnoyingSharedSurfaceOwnershipIssues(false)
+ , mFwdTransactionId(0)
+ , mSerial(++sSerialCounter)
#ifdef GFX_DEBUG_TRACK_CLIENTS_IN_POOL
-, mPoolTracker(nullptr)
+ , mPoolTracker(nullptr)
#endif
{
mData->FillInfo(mInfo);
mFlags |= mData->GetTextureFlags();
}
bool TextureClient::CopyToTextureClient(TextureClient* aTarget,
const gfx::IntRect* aRect,
@@ -1752,24 +1760,28 @@ UpdateYCbCrTextureClient(TextureClient*
return false;
}
MappedYCbCrTextureData srcData;
srcData.y.data = aData.mYChannel;
srcData.y.size = aData.mYSize;
srcData.y.stride = aData.mYStride;
srcData.y.skip = aData.mYSkip;
+ MOZ_ASSERT(aData.mBitDepth == 8 || (aData.mBitDepth > 8 && aData.mBitDepth <= 16));
+ srcData.y.bytesPerPixel = (aData.mBitDepth > 8) ? 2 : 1;
srcData.cb.data = aData.mCbChannel;
srcData.cb.size = aData.mCbCrSize;
srcData.cb.stride = aData.mCbCrStride;
srcData.cb.skip = aData.mCbSkip;
+ srcData.cb.bytesPerPixel = (aData.mBitDepth > 8) ? 2 : 1;
srcData.cr.data = aData.mCrChannel;
srcData.cr.size = aData.mCbCrSize;
srcData.cr.stride = aData.mCbCrStride;
srcData.cr.skip = aData.mCrSkip;
+ srcData.cr.bytesPerPixel = (aData.mBitDepth > 8) ? 2 : 1;
srcData.metadata = nullptr;
if (!srcData.CopyInto(mapped)) {
NS_WARNING("Failed to copy image data!");
return false;
}
if (TextureRequiresLocking(aTexture->GetFlags())) {
@@ -1804,25 +1816,29 @@ MappedYCbCrChannelData::CopyInto(MappedY
return true;
}
for (int32_t i = 0; i < size.height; ++i) {
if (aDst.skip == 0 && skip == 0) {
// fast-ish path
memcpy(aDst.data + i * aDst.stride,
data + i * stride,
- size.width);
+ size.width * bytesPerPixel);
} else {
// slow path
uint8_t* src = data + i * stride;
uint8_t* dst = aDst.data + i * aDst.stride;
for (int32_t j = 0; j < size.width; ++j) {
- *dst = *src;
- src += 1 + skip;
- dst += 1 + aDst.skip;
+ for (uint32_t k = 0; k < bytesPerPixel; ++k) {
+ *dst = *src;
+ src += 1;
+ dst += 1;
+ }
+ src += skip;
+ dst += aDst.skip;
}
}
}
return true;
}
} // namespace layers
} // namespace mozilla
--- a/gfx/layers/client/TextureClient.h
+++ b/gfx/layers/client/TextureClient.h
@@ -134,16 +134,17 @@ struct MappedTextureData
};
struct MappedYCbCrChannelData
{
uint8_t* data;
gfx::IntSize size;
int32_t stride;
int32_t skip;
+ uint32_t bytesPerPixel;
bool CopyInto(MappedYCbCrChannelData& aDst);
};
struct MappedYCbCrTextureData {
MappedYCbCrChannelData y;
MappedYCbCrChannelData cb;
MappedYCbCrChannelData cr;
@@ -342,19 +343,22 @@ public:
BackendSelector aSelector,
TextureFlags aTextureFlags,
TextureAllocationFlags aAllocFlags);
// Creates and allocates a TextureClient supporting the YCbCr format.
static already_AddRefed<TextureClient>
CreateForYCbCr(KnowsCompositor* aAllocator,
gfx::IntSize aYSize,
+ uint32_t aYStride,
gfx::IntSize aCbCrSize,
+ uint32_t aCbCrStride,
StereoMode aStereoMode,
YUVColorSpace aYUVColorSpace,
+ uint32_t aBitDepth,
TextureFlags aTextureFlags);
// Creates and allocates a TextureClient (can be accessed through raw
// pointers).
static already_AddRefed<TextureClient>
CreateForRawBufferAccess(KnowsCompositor* aAllocator,
gfx::SurfaceFormat aFormat,
gfx::IntSize aSize,
@@ -364,16 +368,17 @@ public:
// Creates and allocates a TextureClient (can beaccessed through raw
// pointers) with a certain buffer size. It's unfortunate that we need this.
// providing format and sizes could let us do more optimization.
static already_AddRefed<TextureClient>
CreateForYCbCrWithBufferSize(KnowsCompositor* aAllocator,
size_t aSize,
YUVColorSpace aYUVColorSpace,
+ uint32_t aBitDepth,
TextureFlags aTextureFlags);
// Creates and allocates a TextureClient of the same type.
already_AddRefed<TextureClient>
CreateSimilar(LayersBackend aLayersBackend = LayersBackend::LAYERS_NONE,
TextureFlags aFlags = TextureFlags::DEFAULT,
TextureAllocationFlags aAllocFlags = ALLOC_DEFAULT) const;
--- a/gfx/layers/client/TextureClientRecycleAllocator.cpp
+++ b/gfx/layers/client/TextureClientRecycleAllocator.cpp
@@ -103,30 +103,34 @@ YCbCrTextureClientAllocationHelper::IsCo
BufferTextureData* bufferData = aTextureClient->GetInternalData()->AsBufferTextureData();
if (!bufferData ||
aTextureClient->GetSize() != mData.mYSize ||
bufferData->GetCbCrSize().isNothing() ||
bufferData->GetCbCrSize().ref() != mData.mCbCrSize ||
bufferData->GetYUVColorSpace().isNothing() ||
bufferData->GetYUVColorSpace().ref() != mData.mYUVColorSpace ||
+ bufferData->GetBitDepth().isNothing() ||
+ bufferData->GetBitDepth().ref() != mData.mBitDepth ||
bufferData->GetStereoMode().isNothing() ||
bufferData->GetStereoMode().ref() != mData.mStereoMode) {
return false;
}
return true;
}
already_AddRefed<TextureClient>
YCbCrTextureClientAllocationHelper::Allocate(KnowsCompositor* aAllocator)
{
return TextureClient::CreateForYCbCr(aAllocator,
- mData.mYSize, mData.mCbCrSize,
+ mData.mYSize, mData.mYStride,
+ mData.mCbCrSize, mData.mCbCrStride,
mData.mStereoMode,
mData.mYUVColorSpace,
+ mData.mBitDepth,
mTextureFlags);
}
TextureClientRecycleAllocator::TextureClientRecycleAllocator(KnowsCompositor* aAllocator)
: mSurfaceAllocator(aAllocator)
, mMaxPooledSize(kMaxPooledSized)
, mLock("TextureClientRecycleAllocatorImp.mLock")
, mIsDestroyed(false)
--- a/gfx/layers/composite/TextureHost.cpp
+++ b/gfx/layers/composite/TextureHost.cpp
@@ -441,17 +441,17 @@ TextureSource::~TextureSource()
}
const char*
TextureSource::Name() const
{
MOZ_CRASH("GFX: TextureSource without class name");
return "TextureSource";
}
-
+
BufferTextureHost::BufferTextureHost(const BufferDescriptor& aDesc,
TextureFlags aFlags)
: TextureHost(aFlags)
, mUpdateSerial(1)
, mLocked(false)
, mNeedsFullUpdate(false)
{
mDescriptor = aDesc;
@@ -875,16 +875,26 @@ BufferTextureHost::GetYUVColorSpace() co
{
if (mFormat == gfx::SurfaceFormat::YUV) {
const YCbCrDescriptor& desc = mDescriptor.get_YCbCrDescriptor();
return desc.yUVColorSpace();
}
return YUVColorSpace::UNKNOWN;
}
+uint32_t
+BufferTextureHost::GetBitDepth() const
+{
+ if (mFormat == gfx::SurfaceFormat::YUV) {
+ const YCbCrDescriptor& desc = mDescriptor.get_YCbCrDescriptor();
+ return desc.bitDepth();
+ }
+ return 8;
+}
+
bool
BufferTextureHost::UploadIfNeeded()
{
return MaybeUpload(!mNeedsFullUpdate ? &mMaybeUpdatedRegion : nullptr);
}
bool
BufferTextureHost::MaybeUpload(nsIntRegion *aRegion)
@@ -981,29 +991,29 @@ BufferTextureHost::Upload(nsIntRegion *a
MOZ_ASSERT(mFirstSource->GetNextSibling()->GetNextSibling());
srcY = mFirstSource;
srcU = mFirstSource->GetNextSibling()->AsDataTextureSource();
srcV = mFirstSource->GetNextSibling()->GetNextSibling()->AsDataTextureSource();
}
RefPtr<gfx::DataSourceSurface> tempY =
gfx::Factory::CreateWrappingDataSourceSurface(ImageDataSerializer::GetYChannel(buf, desc),
- desc.ySize().width,
+ desc.yStride(),
desc.ySize(),
- gfx::SurfaceFormat::A8);
+ SurfaceFormatForAlphaBitDepth(desc.bitDepth()));
RefPtr<gfx::DataSourceSurface> tempCb =
gfx::Factory::CreateWrappingDataSourceSurface(ImageDataSerializer::GetCbChannel(buf, desc),
- desc.cbCrSize().width,
+ desc.cbCrStride(),
desc.cbCrSize(),
- gfx::SurfaceFormat::A8);
+ SurfaceFormatForAlphaBitDepth(desc.bitDepth()));
RefPtr<gfx::DataSourceSurface> tempCr =
gfx::Factory::CreateWrappingDataSourceSurface(ImageDataSerializer::GetCrChannel(buf, desc),
- desc.cbCrSize().width,
+ desc.cbCrStride(),
desc.cbCrSize(),
- gfx::SurfaceFormat::A8);
+ SurfaceFormatForAlphaBitDepth(desc.bitDepth()));
// We don't support partial updates for Y U V textures
NS_ASSERTION(!aRegion, "Unsupported partial updates for YCbCr textures");
if (!tempY ||
!tempCb ||
!tempCr ||
!srcY->Update(tempY) ||
!srcU->Update(tempCb) ||
!srcV->Update(tempCr)) {
--- a/gfx/layers/composite/TextureHost.h
+++ b/gfx/layers/composite/TextureHost.h
@@ -434,16 +434,21 @@ public:
* Return the format used for reading the texture.
* Apple's YCBCR_422 is R8G8B8X8.
*/
virtual gfx::SurfaceFormat GetReadFormat() const { return GetFormat(); }
virtual YUVColorSpace GetYUVColorSpace() const { return YUVColorSpace::UNKNOWN; }
/**
+ * Return the bit depth of the image. Used with YUV textures.
+ */
+ virtual uint32_t GetBitDepth() const { return 8; }
+
+ /**
* Called during the transaction. The TextureSource may or may not be composited.
*
* Note that this is called outside of lock/unlock.
*/
virtual void PrepareTextureSource(CompositableTextureSourceRef& aTexture) {}
/**
* Called at composition time, just before compositing the TextureSource composited.
@@ -727,16 +732,18 @@ public:
*
* If the shared format is YCbCr and the compositor does not support it,
* GetFormat will be RGB32 (even though mFormat is SurfaceFormat::YUV).
*/
virtual gfx::SurfaceFormat GetFormat() const override;
virtual YUVColorSpace GetYUVColorSpace() const override;
+ virtual uint32_t GetBitDepth() const override;
+
virtual gfx::IntSize GetSize() const override { return mSize; }
virtual already_AddRefed<gfx::DataSourceSurface> GetAsSurface() override;
virtual bool HasIntermediateBuffer() const override { return mHasIntermediateBuffer; }
virtual BufferTextureHost* AsBufferTextureHost() override { return this; }
--- a/gfx/layers/ipc/LayersSurfaces.ipdlh
+++ b/gfx/layers/ipc/LayersSurfaces.ipdlh
@@ -95,22 +95,25 @@ struct SurfaceDescriptorGPUVideo {
struct RGBDescriptor {
IntSize size;
SurfaceFormat format;
bool hasIntermediateBuffer;
};
struct YCbCrDescriptor {
IntSize ySize;
+ uint32_t yStride;
IntSize cbCrSize;
+ uint32_t cbCrStride;
uint32_t yOffset;
uint32_t cbOffset;
uint32_t crOffset;
StereoMode stereoMode;
YUVColorSpace yUVColorSpace;
+ uint32_t bitDepth;
bool hasIntermediateBuffer;
};
union BufferDescriptor {
RGBDescriptor;
YCbCrDescriptor;
};
--- a/gfx/layers/ipc/SharedPlanarYCbCrImage.cpp
+++ b/gfx/layers/ipc/SharedPlanarYCbCrImage.cpp
@@ -108,23 +108,31 @@ SharedPlanarYCbCrImage::AdoptData(const
mOrigin = gfx::IntPoint(aData.mPicX, aData.mPicY);
uint8_t *base = GetBuffer();
uint32_t yOffset = aData.mYChannel - base;
uint32_t cbOffset = aData.mCbChannel - base;
uint32_t crOffset = aData.mCrChannel - base;
auto fwd = mCompositable->GetForwarder();
- bool hasIntermediateBuffer = ComputeHasIntermediateBuffer(gfx::SurfaceFormat::YUV,
- fwd->GetCompositorBackendType());
+ bool hasIntermediateBuffer = ComputeHasIntermediateBuffer(
+ gfx::SurfaceFormat::YUV, fwd->GetCompositorBackendType());
- static_cast<BufferTextureData*>(mTextureClient->GetInternalData())->SetDesciptor(
- YCbCrDescriptor(aData.mYSize, aData.mCbCrSize, yOffset, cbOffset, crOffset,
- aData.mStereoMode, aData.mYUVColorSpace, hasIntermediateBuffer)
- );
+ static_cast<BufferTextureData*>(mTextureClient->GetInternalData())
+ ->SetDesciptor(YCbCrDescriptor(aData.mYSize,
+ aData.mYStride,
+ aData.mCbCrSize,
+ aData.mCbCrStride,
+ yOffset,
+ cbOffset,
+ crOffset,
+ aData.mStereoMode,
+ aData.mYUVColorSpace,
+ aData.mBitDepth,
+ hasIntermediateBuffer));
return true;
}
bool
SharedPlanarYCbCrImage::IsValid() {
return mTextureClient && mTextureClient->IsValid();
}
@@ -170,28 +178,30 @@ SharedPlanarYCbCrImage::Allocate(PlanarY
mData.mCrChannel = aData.mCrChannel;
mData.mYSize = aData.mYSize;
mData.mCbCrSize = aData.mCbCrSize;
mData.mPicX = aData.mPicX;
mData.mPicY = aData.mPicY;
mData.mPicSize = aData.mPicSize;
mData.mStereoMode = aData.mStereoMode;
mData.mYUVColorSpace = aData.mYUVColorSpace;
+ mData.mBitDepth = aData.mBitDepth;
// those members are not always equal to aData's, due to potentially different
// packing.
mData.mYSkip = 0;
mData.mCbSkip = 0;
mData.mCrSkip = 0;
- mData.mYStride = mData.mYSize.width;
- mData.mCbCrStride = mData.mCbCrSize.width;
+ mData.mYStride = aData.mYStride;
+ mData.mCbCrStride = aData.mCbCrStride;
// do not set mBuffer like in PlanarYCbCrImage because the later
// will try to manage this memory without knowing it belongs to a
// shmem.
- mBufferSize = ImageDataSerializer::ComputeYCbCrBufferSize(mData.mYSize, mData.mCbCrSize);
+ mBufferSize = ImageDataSerializer::ComputeYCbCrBufferSize(
+ mData.mYSize, mData.mYStride, mData.mCbCrSize, mData.mCbCrStride);
mSize = mData.mPicSize;
mOrigin = gfx::IntPoint(aData.mPicX, aData.mPicY);
mTextureClient->Unlock();
return mBufferSize > 0;
}
--- a/gfx/tests/gtest/TestTextures.cpp
+++ b/gfx/tests/gtest/TestTextures.cpp
@@ -257,16 +257,17 @@ TEST(Layers, TextureYCbCrSerialization)
clientData.mCrChannel = crSurface->Data();
clientData.mYSize = ySurface->GetSize();
clientData.mPicSize = ySurface->GetSize();
clientData.mCbCrSize = cbSurface->GetSize();
clientData.mYStride = ySurface->Stride();
clientData.mCbCrStride = cbSurface->Stride();
clientData.mStereoMode = StereoMode::MONO;
clientData.mYUVColorSpace = YUVColorSpace::BT601;
+ clientData.mBitDepth = 8;
clientData.mYSkip = 0;
clientData.mCbSkip = 0;
clientData.mCrSkip = 0;
clientData.mCrSkip = 0;
clientData.mPicX = 0;
clientData.mPicX = 0;
uint32_t namespaceId = 1;
@@ -285,16 +286,16 @@ TEST(Layers, TextureYCbCrSerialization)
retry--;
}
// Skip this testing if IPDL connection is not ready
if (!retry && !imageBridge->IPCOpen()) {
return;
}
- RefPtr<TextureClient> client = TextureClient::CreateForYCbCr(imageBridge, clientData.mYSize, clientData.mCbCrSize,
+ RefPtr<TextureClient> client = TextureClient::CreateForYCbCr(imageBridge, clientData.mYSize, clientData.mYStride, clientData.mCbCrSize, clientData.mCbCrStride,
StereoMode::MONO, YUVColorSpace::BT601,
- TextureFlags::DEALLOCATE_CLIENT);
+ 8, TextureFlags::DEALLOCATE_CLIENT);
TestTextureClientYCbCr(client, clientData);
// XXX - Test more texture client types.
}
--- a/gfx/tests/gtest/TextureHelper.h
+++ b/gfx/tests/gtest/TextureHelper.h
@@ -57,19 +57,24 @@ CreateYCbCrTextureClientWithBackend(Laye
clientData.mCbSkip = 0;
clientData.mCrSkip = 0;
clientData.mCrSkip = 0;
clientData.mPicX = 0;
clientData.mPicX = 0;
// Create YCbCrTexture for basice backend.
if (aLayersBackend == LayersBackend::LAYERS_BASIC) {
- return TextureClient::CreateForYCbCr(nullptr, clientData.mYSize,
- clientData.mCbCrSize, StereoMode::MONO,
+ return TextureClient::CreateForYCbCr(nullptr,
+ clientData.mYSize,
+ clientData.mYStride,
+ clientData.mCbCrSize,
+ clientData.mCbCrStride,
+ StereoMode::MONO,
YUVColorSpace::BT601,
+ 8,
TextureFlags::DEALLOCATE_CLIENT);
}
#ifdef XP_WIN
RefPtr<ID3D11Device> device = DeviceManagerDx::Get()->GetContentDevice();
if (device && aLayersBackend == LayersBackend::LAYERS_D3D11) {
// Create YCbCrD3D11TextureData