diff --git a/gfx/2d/Tools.h b/gfx/2d/Tools.h index 041e92303a88..520a56bacb48 100644 --- a/gfx/2d/Tools.h +++ b/gfx/2d/Tools.h @@ -92,6 +92,7 @@ BytesPerPixel(SurfaceFormat aFormat) case SurfaceFormat::A8: return 1; case SurfaceFormat::R5G6B5_UINT16: + case SurfaceFormat::A16: return 2; case SurfaceFormat::R8G8B8: case SurfaceFormat::B8G8R8: @@ -106,6 +107,19 @@ BytesPerPixel(SurfaceFormat aFormat) } } +static inline SurfaceFormat +SurfaceFormatForAlphaDepth(uint32_t aDepth) +{ + if (aDepth == 8) { + return SurfaceFormat::A8; + } else if (aDepth == 10 || + aDepth == 12) { + return SurfaceFormat::A16; + } + MOZ_ASSERT_UNREACHABLE("Unsupported alpha depth"); + return SurfaceFormat::UNKNOWN; +} + static inline bool IsOpaqueFormat(SurfaceFormat aFormat) { switch (aFormat) { diff --git a/gfx/2d/Types.h b/gfx/2d/Types.h index fd106bfa8087..0810ff963840 100644 --- a/gfx/2d/Types.h +++ b/gfx/2d/Types.h @@ -56,6 +56,7 @@ enum class SurfaceFormat : int8_t { // This one is a single-byte, so endianness isn't an issue. A8, + A16, R8G8, diff --git a/gfx/layers/BufferTexture.cpp b/gfx/layers/BufferTexture.cpp index 04cb1d0bf79f..4b5ca38aa311 100644 --- a/gfx/layers/BufferTexture.cpp +++ b/gfx/layers/BufferTexture.cpp @@ -159,6 +159,7 @@ BufferTextureData* BufferTextureData::CreateForYCbCrWithBufferSize(KnowsCompositor* aAllocator, int32_t aBufferSize, YUVColorSpace aYUVColorSpace, + uint32_t aDepth, TextureFlags aTextureFlags) { if (aBufferSize == 0 || !gfx::Factory::CheckBufferSize(aBufferSize)) { @@ -171,9 +172,10 @@ BufferTextureData::CreateForYCbCrWithBufferSize(KnowsCompositor* aAllocator, // 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, + aDepth, hasIntermediateBuffer); return CreateInternal(aAllocator ? aAllocator->GetTextureForwarder() : nullptr, @@ -183,12 +185,16 @@ BufferTextureData::CreateForYCbCrWithBufferSize(KnowsCompositor* aAllocator, BufferTextureData* BufferTextureData::CreateForYCbCr(KnowsCompositor* aAllocator, gfx::IntSize aYSize, + uint32_t aYStride, gfx::IntSize aCbCrSize, + uint32_t aCbCrStride, StereoMode aStereoMode, YUVColorSpace aYUVColorSpace, + uint32_t aDepth, TextureFlags aTextureFlags) { - uint32_t bufSize = ImageDataSerializer::ComputeYCbCrBufferSize(aYSize, aCbCrSize); + uint32_t bufSize = ImageDataSerializer::ComputeYCbCrBufferSize( + aYSize, aYStride, aCbCrSize, aCbCrStride); if (bufSize == 0) { return nullptr; } @@ -196,20 +202,30 @@ BufferTextureData::CreateForYCbCr(KnowsCompositor* aAllocator, 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, + aDepth, 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 @@ -254,6 +270,12 @@ BufferTextureData::GetYUVColorSpace() const return ImageDataSerializer::YUVColorSpaceFromBufferDescriptor(mDescriptor); } +Maybe +BufferTextureData::GetDepth() const +{ + return ImageDataSerializer::DepthFromBufferDescriptor(mDescriptor); +} + Maybe BufferTextureData::GetStereoMode() const { @@ -351,17 +373,17 @@ BufferTextureData::BorrowMappedYCbCrData(MappedYCbCrTextureData& aMap) 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; diff --git a/gfx/layers/BufferTexture.h b/gfx/layers/BufferTexture.h index 2999d1d944be..dd78aa8b351a 100644 --- a/gfx/layers/BufferTexture.h +++ b/gfx/layers/BufferTexture.h @@ -30,9 +30,12 @@ public: static BufferTextureData* CreateForYCbCr(KnowsCompositor* aAllocator, gfx::IntSize aYSize, + uint32_t aYStride, gfx::IntSize aCbCrSize, + uint32_t aCbCrStride, StereoMode aStereoMode, YUVColorSpace aYUVColorSpace, + uint32_t aDepth, TextureFlags aTextureFlags); // It is generally better to use CreateForYCbCr instead. @@ -41,6 +44,7 @@ public: static BufferTextureData* CreateForYCbCrWithBufferSize(KnowsCompositor* aAllocator, int32_t aSize, YUVColorSpace aYUVColorSpace, + uint32_t aDepth, TextureFlags aTextureFlags); virtual bool Lock(OpenMode aMode) override { return true; } @@ -67,6 +71,8 @@ public: Maybe GetYUVColorSpace() const; + Maybe GetDepth() const; + Maybe GetStereoMode() const; protected: diff --git a/gfx/layers/Effects.h b/gfx/layers/Effects.h index d4d459c76b20..f6f7f094fe07 100644 --- a/gfx/layers/Effects.h +++ b/gfx/layers/Effects.h @@ -161,14 +161,16 @@ struct EffectRGB : public TexturedEffect struct EffectYCbCr : public TexturedEffect { - EffectYCbCr(TextureSource *aSource, YUVColorSpace aYUVColorSpace, gfx::SamplingFilter aSamplingFilter) + EffectYCbCr(TextureSource *aSource, YUVColorSpace aYUVColorSpace, uint32_t aDepth, gfx::SamplingFilter aSamplingFilter) : TexturedEffect(EffectTypes::YCBCR, aSource, false, aSamplingFilter) , mYUVColorSpace(aYUVColorSpace) + , mDepth(aDepth) {} virtual const char* Name() { return "EffectYCbCr"; } YUVColorSpace mYUVColorSpace; + uint32_t mDepth; }; struct EffectNV12 : public TexturedEffect @@ -270,7 +272,8 @@ CreateTexturedEffect(TextureHost* aHost, RefPtr 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->GetDepth(), aSamplingFilter); } else { result = CreateTexturedEffect(aHost->GetReadFormat(), aSource, diff --git a/gfx/layers/ImageDataSerializer.cpp b/gfx/layers/ImageDataSerializer.cpp index 08ed83bd9957..8e6c3a4cbe1f 100644 --- a/gfx/layers/ImageDataSerializer.cpp +++ b/gfx/layers/ImageDataSerializer.cpp @@ -71,18 +71,12 @@ ComputeYCbCrBufferSize(const gfx::IntSize& aYSize, int32_t aYStride, !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) { @@ -136,7 +130,6 @@ Maybe CbCrSizeFromBufferDescriptor(const BufferDescriptor& aDescri } Maybe YUVColorSpaceFromBufferDescriptor(const BufferDescriptor& aDescriptor) -{ { switch (aDescriptor.type()) { case BufferDescriptor::TRGBDescriptor: @@ -144,9 +137,20 @@ Maybe YUVColorSpaceFromBufferDescriptor(const BufferDescriptor& a case BufferDescriptor::TYCbCrDescriptor: return Some(aDescriptor.get_YCbCrDescriptor().yUVColorSpace()); default: - MOZ_CRASH("GFX: CbCrSizeFromBufferDescriptor"); + MOZ_CRASH("GFX: YUVColorSpaceFromBufferDescriptor"); } } + +Maybe DepthFromBufferDescriptor(const BufferDescriptor& aDescriptor) +{ + switch (aDescriptor.type()) { + case BufferDescriptor::TRGBDescriptor: + return Nothing(); + case BufferDescriptor::TYCbCrDescriptor: + return Some(aDescriptor.get_YCbCrDescriptor().depth()); + default: + MOZ_CRASH("GFX: DepthFromBufferDescriptor"); + } } Maybe StereoModeFromBufferDescriptor(const BufferDescriptor& aDescriptor) @@ -157,7 +161,7 @@ Maybe StereoModeFromBufferDescriptor(const BufferDescriptor& aDescri case BufferDescriptor::TYCbCrDescriptor: return Some(aDescriptor.get_YCbCrDescriptor().stereoMode()); default: - MOZ_CRASH("GFX: CbCrSizeFromBufferDescriptor"); + MOZ_CRASH("GFX: StereoModeFromBufferDescriptor"); } } @@ -180,9 +184,6 @@ already_AddRefed 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 result; if (aSurface) { @@ -209,14 +210,15 @@ DataSourceSurfaceFromYCbCrDescriptor(uint8_t* aBuffer, const YCbCrDescriptor& aD 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.mDepth = aDescriptor.depth(); gfx::ConvertYCbCrToRGB(ycbcrData, gfx::SurfaceFormat::B8G8R8X8, @@ -237,21 +239,18 @@ ConvertAndScaleFromYCbCrDescriptor(uint8_t* aBuffer, 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.mDepth = aDescriptor.depth(); gfx::ConvertYCbCrToRGB(ycbcrData, aDestFormat, aDestSize, aDestBuffer, aStride); } diff --git a/gfx/layers/ImageDataSerializer.h b/gfx/layers/ImageDataSerializer.h index 53a589d21d95..f1d306729dba 100644 --- a/gfx/layers/ImageDataSerializer.h +++ b/gfx/layers/ImageDataSerializer.h @@ -45,9 +45,6 @@ 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, @@ -62,6 +59,8 @@ Maybe CbCrSizeFromBufferDescriptor(const BufferDescriptor& aDescri Maybe YUVColorSpaceFromBufferDescriptor(const BufferDescriptor& aDescriptor); +Maybe DepthFromBufferDescriptor(const BufferDescriptor& aDescriptor); + Maybe StereoModeFromBufferDescriptor(const BufferDescriptor& aDescriptor); uint8_t* GetYChannel(uint8_t* aBuffer, const YCbCrDescriptor& aDescriptor); diff --git a/gfx/layers/client/ImageClient.cpp b/gfx/layers/client/ImageClient.cpp index cc9dd207e7e8..bcec7e7803fc 100644 --- a/gfx/layers/client/ImageClient.cpp +++ b/gfx/layers/client/ImageClient.cpp @@ -101,8 +101,11 @@ ImageClient::CreateTextureClientForImage(Image* aImage, KnowsCompositor* aForwar 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->mDepth, TextureFlags::DEFAULT); if (!texture) { return nullptr; diff --git a/gfx/layers/client/TextureClient.cpp b/gfx/layers/client/TextureClient.cpp index fd11ce9736f0..03c3b961bea3 100644 --- a/gfx/layers/client/TextureClient.cpp +++ b/gfx/layers/client/TextureClient.cpp @@ -1256,9 +1256,12 @@ TextureClient::CreateForRawBufferAccess(LayersIPCChannel* aAllocator, already_AddRefed TextureClient::CreateForYCbCr(KnowsCompositor* aAllocator, gfx::IntSize aYSize, + uint32_t aYStride, gfx::IntSize aCbCrSize, + uint32_t aCbCrStride, StereoMode aStereoMode, YUVColorSpace aYUVColorSpace, + uint32_t aDepth, TextureFlags aTextureFlags) { if (!aAllocator || !aAllocator->GetLayersIPCActor()->IPCOpen()) { @@ -1269,9 +1272,12 @@ TextureClient::CreateForYCbCr(KnowsCompositor* aAllocator, return nullptr; } - TextureData* data = BufferTextureData::CreateForYCbCr(aAllocator, aYSize, aCbCrSize, - aStereoMode, aYUVColorSpace, - aTextureFlags); + TextureData* data = + BufferTextureData::CreateForYCbCr(aAllocator, + aYSize, aYStride, + aCbCrSize, aCbCrStride, + aStereoMode, aYUVColorSpace, + aDepth, aTextureFlags); if (!data) { return nullptr; } @@ -1285,15 +1291,15 @@ already_AddRefed TextureClient::CreateForYCbCrWithBufferSize(KnowsCompositor* aAllocator, size_t aSize, YUVColorSpace aYUVColorSpace, + uint32_t aDepth, TextureFlags aTextureFlags) { if (!aAllocator || !aAllocator->GetLayersIPCActor()->IPCOpen()) { return nullptr; } - TextureData* data = - BufferTextureData::CreateForYCbCrWithBufferSize(aAllocator, aSize, aYUVColorSpace, - aTextureFlags); + TextureData* data = BufferTextureData::CreateForYCbCrWithBufferSize( + aAllocator, aSize, aYUVColorSpace, aDepth, aTextureFlags); if (!data) { return nullptr; } @@ -1302,26 +1308,28 @@ TextureClient::CreateForYCbCrWithBufferSize(KnowsCompositor* aAllocator, 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); @@ -1757,14 +1765,18 @@ UpdateYCbCrTextureClient(TextureClient* aTexture, const PlanarYCbCrData& aData) srcData.y.size = aData.mYSize; srcData.y.stride = aData.mYStride; srcData.y.skip = aData.mYSkip; + MOZ_ASSERT(aData.mDepth == 8 || (aData.mDepth > 8 && aData.mDepth <= 16)); + srcData.y.bytesPerPixel = (aData.mDepth > 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.mDepth > 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.mDepth > 8) ? 2 : 1; srcData.metadata = nullptr; if (!srcData.CopyInto(mapped)) { @@ -1809,15 +1821,19 @@ MappedYCbCrChannelData::CopyInto(MappedYCbCrChannelData& aDst) // 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; } } } diff --git a/gfx/layers/client/TextureClient.h b/gfx/layers/client/TextureClient.h index df816bbf126c..605bcd5d70a7 100644 --- a/gfx/layers/client/TextureClient.h +++ b/gfx/layers/client/TextureClient.h @@ -139,6 +139,7 @@ struct MappedYCbCrChannelData gfx::IntSize size; int32_t stride; int32_t skip; + uint32_t bytesPerPixel; bool CopyInto(MappedYCbCrChannelData& aDst); }; @@ -347,9 +348,12 @@ public: static already_AddRefed CreateForYCbCr(KnowsCompositor* aAllocator, gfx::IntSize aYSize, + uint32_t aYStride, gfx::IntSize aCbCrSize, + uint32_t aCbCrStride, StereoMode aStereoMode, YUVColorSpace aYUVColorSpace, + uint32_t aDepth, TextureFlags aTextureFlags); // Creates and allocates a TextureClient (can be accessed through raw @@ -369,6 +373,7 @@ public: CreateForYCbCrWithBufferSize(KnowsCompositor* aAllocator, size_t aSize, YUVColorSpace aYUVColorSpace, + uint32_t aDepth, TextureFlags aTextureFlags); // Creates and allocates a TextureClient of the same type. diff --git a/gfx/layers/client/TextureClientRecycleAllocator.cpp b/gfx/layers/client/TextureClientRecycleAllocator.cpp index fcfc0e99578a..2c06fa189005 100644 --- a/gfx/layers/client/TextureClientRecycleAllocator.cpp +++ b/gfx/layers/client/TextureClientRecycleAllocator.cpp @@ -108,6 +108,8 @@ YCbCrTextureClientAllocationHelper::IsCompatible(TextureClient* aTextureClient) bufferData->GetCbCrSize().ref() != mData.mCbCrSize || bufferData->GetYUVColorSpace().isNothing() || bufferData->GetYUVColorSpace().ref() != mData.mYUVColorSpace || + bufferData->GetDepth().isNothing() || + bufferData->GetDepth().ref() != mData.mDepth || bufferData->GetStereoMode().isNothing() || bufferData->GetStereoMode().ref() != mData.mStereoMode) { return false; @@ -119,9 +121,11 @@ already_AddRefed 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.mDepth, mTextureFlags); } diff --git a/gfx/layers/composite/TextureHost.cpp b/gfx/layers/composite/TextureHost.cpp index bb429a364e96..efd311cd4288 100644 --- a/gfx/layers/composite/TextureHost.cpp +++ b/gfx/layers/composite/TextureHost.cpp @@ -446,7 +446,7 @@ TextureSource::Name() const MOZ_CRASH("GFX: TextureSource without class name"); return "TextureSource"; } - + BufferTextureHost::BufferTextureHost(const BufferDescriptor& aDesc, TextureFlags aFlags) : TextureHost(aFlags) @@ -880,6 +880,16 @@ BufferTextureHost::GetYUVColorSpace() const return YUVColorSpace::UNKNOWN; } +uint32_t +BufferTextureHost::GetDepth() const +{ + if (mFormat == gfx::SurfaceFormat::YUV) { + const YCbCrDescriptor& desc = mDescriptor.get_YCbCrDescriptor(); + return desc.depth(); + } + return 8; +} + bool BufferTextureHost::UploadIfNeeded() { @@ -986,19 +996,19 @@ BufferTextureHost::Upload(nsIntRegion *aRegion) RefPtr tempY = gfx::Factory::CreateWrappingDataSourceSurface(ImageDataSerializer::GetYChannel(buf, desc), - desc.ySize().width, + desc.yStride(), desc.ySize(), - gfx::SurfaceFormat::A8); + SurfaceFormatForAlphaDepth(desc.depth())); RefPtr tempCb = gfx::Factory::CreateWrappingDataSourceSurface(ImageDataSerializer::GetCbChannel(buf, desc), - desc.cbCrSize().width, + desc.cbCrStride(), desc.cbCrSize(), - gfx::SurfaceFormat::A8); + SurfaceFormatForAlphaDepth(desc.depth())); RefPtr tempCr = gfx::Factory::CreateWrappingDataSourceSurface(ImageDataSerializer::GetCrChannel(buf, desc), - desc.cbCrSize().width, + desc.cbCrStride(), desc.cbCrSize(), - gfx::SurfaceFormat::A8); + SurfaceFormatForAlphaDepth(desc.depth())); // We don't support partial updates for Y U V textures NS_ASSERTION(!aRegion, "Unsupported partial updates for YCbCr textures"); if (!tempY || diff --git a/gfx/layers/composite/TextureHost.h b/gfx/layers/composite/TextureHost.h index 8e808903a7d0..a3d6bc00b971 100644 --- a/gfx/layers/composite/TextureHost.h +++ b/gfx/layers/composite/TextureHost.h @@ -438,6 +438,11 @@ public: virtual YUVColorSpace GetYUVColorSpace() const { return YUVColorSpace::UNKNOWN; } + /** + * Return the bit depth of the image. Used with YUV textures. + */ + virtual uint32_t GetDepth() const { return 8; } + /** * Called during the transaction. The TextureSource may or may not be composited. * @@ -732,6 +737,8 @@ public: virtual YUVColorSpace GetYUVColorSpace() const override; + virtual uint32_t GetDepth() const override; + virtual gfx::IntSize GetSize() const override { return mSize; } virtual already_AddRefed GetAsSurface() override; diff --git a/gfx/layers/ipc/LayersSurfaces.ipdlh b/gfx/layers/ipc/LayersSurfaces.ipdlh index e4d296b32f88..f1f84e6cc1c0 100644 --- a/gfx/layers/ipc/LayersSurfaces.ipdlh +++ b/gfx/layers/ipc/LayersSurfaces.ipdlh @@ -100,12 +100,15 @@ struct RGBDescriptor { 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 depth; bool hasIntermediateBuffer; }; diff --git a/gfx/layers/ipc/SharedPlanarYCbCrImage.cpp b/gfx/layers/ipc/SharedPlanarYCbCrImage.cpp index 1688a86046d4..8a82c8964a66 100644 --- a/gfx/layers/ipc/SharedPlanarYCbCrImage.cpp +++ b/gfx/layers/ipc/SharedPlanarYCbCrImage.cpp @@ -113,13 +113,21 @@ SharedPlanarYCbCrImage::AdoptData(const Data& aData) 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(mTextureClient->GetInternalData())->SetDesciptor( - YCbCrDescriptor(aData.mYSize, aData.mCbCrSize, yOffset, cbOffset, crOffset, - aData.mStereoMode, aData.mYUVColorSpace, hasIntermediateBuffer) - ); + static_cast(mTextureClient->GetInternalData()) + ->SetDesciptor(YCbCrDescriptor(aData.mYSize, + aData.mYStride, + aData.mCbCrSize, + aData.mCbCrStride, + yOffset, + cbOffset, + crOffset, + aData.mStereoMode, + aData.mYUVColorSpace, + aData.mDepth, + hasIntermediateBuffer)); return true; } @@ -175,18 +183,20 @@ SharedPlanarYCbCrImage::Allocate(PlanarYCbCrData& aData) mData.mPicSize = aData.mPicSize; mData.mStereoMode = aData.mStereoMode; mData.mYUVColorSpace = aData.mYUVColorSpace; + mData.mDepth = aData.mDepth; // 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); diff --git a/gfx/tests/gtest/TestTextures.cpp b/gfx/tests/gtest/TestTextures.cpp index 5c6820a1e180..06c43d4bae9f 100644 --- a/gfx/tests/gtest/TestTextures.cpp +++ b/gfx/tests/gtest/TestTextures.cpp @@ -262,6 +262,7 @@ TEST(Layers, TextureYCbCrSerialization) { clientData.mCbCrStride = cbSurface->Stride(); clientData.mStereoMode = StereoMode::MONO; clientData.mYUVColorSpace = YUVColorSpace::BT601; + clientData.mDepth = 8; clientData.mYSkip = 0; clientData.mCbSkip = 0; clientData.mCrSkip = 0; @@ -290,9 +291,9 @@ TEST(Layers, TextureYCbCrSerialization) { return; } - RefPtr client = TextureClient::CreateForYCbCr(imageBridge, clientData.mYSize, clientData.mCbCrSize, + RefPtr 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); diff --git a/gfx/tests/gtest/TextureHelper.h b/gfx/tests/gtest/TextureHelper.h index eea7ac66132b..144a237b17d4 100644 --- a/gfx/tests/gtest/TextureHelper.h +++ b/gfx/tests/gtest/TextureHelper.h @@ -62,9 +62,14 @@ CreateYCbCrTextureClientWithBackend(LayersBackend aLayersBackend) // 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); }