diff options
Diffstat (limited to 'gfx/layers/ipc/SharedPlanarYCbCrImage.cpp')
-rw-r--r-- | gfx/layers/ipc/SharedPlanarYCbCrImage.cpp | 246 |
1 files changed, 246 insertions, 0 deletions
diff --git a/gfx/layers/ipc/SharedPlanarYCbCrImage.cpp b/gfx/layers/ipc/SharedPlanarYCbCrImage.cpp new file mode 100644 index 000000000..6a1bbcac0 --- /dev/null +++ b/gfx/layers/ipc/SharedPlanarYCbCrImage.cpp @@ -0,0 +1,246 @@ +/* -*- 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 "SharedPlanarYCbCrImage.h" +#include <stddef.h> // for size_t +#include <stdio.h> // for printf +#include "gfx2DGlue.h" // for Moz2D transition helpers +#include "ISurfaceAllocator.h" // for ISurfaceAllocator, etc +#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc +#include "mozilla/gfx/Types.h" // for SurfaceFormat::SurfaceFormat::YUV +#include "mozilla/ipc/SharedMemory.h" // for SharedMemory, etc +#include "mozilla/layers/ImageClient.h" // for ImageClient +#include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor, etc +#include "mozilla/layers/TextureClient.h" +#include "mozilla/layers/TextureClientRecycleAllocator.h" +#include "mozilla/layers/BufferTexture.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 +#include "mozilla/ipc/Shmem.h" + +namespace mozilla { +namespace layers { + +using namespace mozilla::ipc; + +SharedPlanarYCbCrImage::SharedPlanarYCbCrImage(ImageClient* aCompositable) +: mCompositable(aCompositable) +{ + MOZ_COUNT_CTOR(SharedPlanarYCbCrImage); +} + +SharedPlanarYCbCrImage::~SharedPlanarYCbCrImage() { + MOZ_COUNT_DTOR(SharedPlanarYCbCrImage); + + if (mCompositable->GetAsyncID() != 0 && + !InImageBridgeChildThread()) { + if (mTextureClient) { + ADDREF_MANUALLY(mTextureClient); + ImageBridgeChild::DispatchReleaseTextureClient(mTextureClient); + mTextureClient = nullptr; + } + } +} + +size_t +SharedPlanarYCbCrImage::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const +{ + // NB: Explicitly skipping mTextureClient, the memory is already reported + // at time of allocation in GfxMemoryImageReporter. + // Not owned: + // - mCompositable + return 0; +} + +TextureClient* +SharedPlanarYCbCrImage::GetTextureClient(KnowsCompositor* aForwarder) +{ + return mTextureClient.get(); +} + +uint8_t* +SharedPlanarYCbCrImage::GetBuffer() +{ + // This should never be used + MOZ_ASSERT(false); + return nullptr; +} + +already_AddRefed<gfx::SourceSurface> +SharedPlanarYCbCrImage::GetAsSourceSurface() +{ + if (!IsValid()) { + NS_WARNING("Can't get as surface"); + return nullptr; + } + return PlanarYCbCrImage::GetAsSourceSurface(); +} + +bool +SharedPlanarYCbCrImage::CopyData(const PlanarYCbCrData& aData) +{ + // If mTextureClient has not already been allocated (through Allocate(aData)) + // allocate it. This code path is slower than the one used when Allocate has + // been called since it will trigger a full copy. + PlanarYCbCrData data = aData; + if (!mTextureClient && !Allocate(data)) { + return false; + } + + TextureClientAutoLock autoLock(mTextureClient, OpenMode::OPEN_WRITE_ONLY); + if (!autoLock.Succeeded()) { + MOZ_ASSERT(false, "Failed to lock the texture."); + return false; + } + + if (!UpdateYCbCrTextureClient(mTextureClient, aData)) { + MOZ_ASSERT(false, "Failed to copy YCbCr data into the TextureClient"); + return false; + } + mTextureClient->MarkImmutable(); + return true; +} + +// needs to be overriden because the parent class sets mBuffer which we +// do not want to happen. +uint8_t* +SharedPlanarYCbCrImage::AllocateAndGetNewBuffer(uint32_t aSize) +{ + MOZ_ASSERT(!mTextureClient, "This image already has allocated data"); + size_t size = ImageDataSerializer::ComputeYCbCrBufferSize(aSize); + if (!size) { + return nullptr; + } + + // XXX Add YUVColorSpace handling. Use YUVColorSpace::BT601 for now. + mTextureClient = TextureClient::CreateForYCbCrWithBufferSize(mCompositable->GetForwarder(), + size, + YUVColorSpace::BT601, + mCompositable->GetTextureFlags()); + + // get new buffer _without_ setting mBuffer. + if (!mTextureClient) { + return nullptr; + } + + // update buffer size + mBufferSize = size; + + MappedYCbCrTextureData mapped; + if (mTextureClient->BorrowMappedYCbCrData(mapped)) { + // The caller expects a pointer to the beginning of the writable part of the + // buffer which is where the y channel starts by default. + return mapped.y.data; + } else { + MOZ_CRASH("GFX: Cannot borrow mapped YCbCr data"); + } +} + +bool +SharedPlanarYCbCrImage::AdoptData(const Data &aData) +{ + // AdoptData 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; + 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()); + + static_cast<BufferTextureData*>(mTextureClient->GetInternalData())->SetDesciptor( + YCbCrDescriptor(aData.mYSize, aData.mCbCrSize, yOffset, cbOffset, crOffset, + aData.mStereoMode, aData.mYUVColorSpace, hasIntermediateBuffer) + ); + + return true; +} + +bool +SharedPlanarYCbCrImage::IsValid() { + return mTextureClient && mTextureClient->IsValid(); +} + +bool +SharedPlanarYCbCrImage::Allocate(PlanarYCbCrData& aData) +{ + MOZ_ASSERT(!mTextureClient, + "This image already has allocated data"); + static const uint32_t MAX_POOLED_VIDEO_COUNT = 5; + + if (!mCompositable->HasTextureClientRecycler()) { + // Initialize TextureClientRecycler + mCompositable->GetTextureClientRecycler()->SetMaxPoolSize(MAX_POOLED_VIDEO_COUNT); + } + + { + YCbCrTextureClientAllocationHelper helper(aData, mCompositable->GetTextureFlags()); + mTextureClient = mCompositable->GetTextureClientRecycler()->CreateOrRecycle(helper); + } + + if (!mTextureClient) { + NS_WARNING("SharedPlanarYCbCrImage::Allocate failed."); + return false; + } + + MappedYCbCrTextureData mapped; + // The locking here is sort of a lie. The SharedPlanarYCbCrImage just pulls + // pointers out of the TextureClient and keeps them around, which works only + // because the underlyin BufferTextureData is always mapped in memory even outside + // of the lock/unlock interval. That's sad and new code should follow this example. + if (!mTextureClient->Lock(OpenMode::OPEN_READ) || !mTextureClient->BorrowMappedYCbCrData(mapped)) { + MOZ_CRASH("GFX: Cannot lock or borrow mapped YCbCr"); + } + + aData.mYChannel = mapped.y.data; + aData.mCbChannel = mapped.cb.data; + aData.mCrChannel = mapped.cr.data; + + // copy some of aData's values in mData (most of them) + mData.mYChannel = aData.mYChannel; + mData.mCbChannel = aData.mCbChannel; + 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; + // 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; + + // 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); + mSize = mData.mPicSize; + mOrigin = gfx::IntPoint(aData.mPicX, aData.mPicY); + + mTextureClient->Unlock(); + + return mBufferSize > 0; +} + +} // namespace layers +} // namespace mozilla |