SharedPlanarYCbCrImage.cpp (6849B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "SharedPlanarYCbCrImage.h" 8 #include <stddef.h> // for size_t 9 #include <stdio.h> // for printf 10 #include "gfx2DGlue.h" // for Moz2D transition helpers 11 #include "ISurfaceAllocator.h" // for ISurfaceAllocator, etc 12 #include "mozilla/Assertions.h" // for MOZ_ASSERT, etc 13 #include "mozilla/gfx/Types.h" // for SurfaceFormat::SurfaceFormat::YUV 14 #include "mozilla/layers/ImageClient.h" // for ImageClient 15 #include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor, etc 16 #include "mozilla/layers/TextureClient.h" 17 #include "mozilla/layers/TextureClientRecycleAllocator.h" 18 #include "mozilla/layers/BufferTexture.h" 19 #include "mozilla/layers/ImageDataSerializer.h" 20 #include "mozilla/layers/ImageBridgeChild.h" // for ImageBridgeChild 21 #include "mozilla/mozalloc.h" // for operator delete 22 #include "nsISupportsImpl.h" // for Image::AddRef 23 #include "mozilla/ipc/Shmem.h" 24 25 namespace mozilla { 26 namespace layers { 27 28 using namespace mozilla::ipc; 29 30 SharedPlanarYCbCrImage::SharedPlanarYCbCrImage(ImageClient* aCompositable) 31 : mCompositable(aCompositable) { 32 MOZ_COUNT_CTOR(SharedPlanarYCbCrImage); 33 } 34 35 SharedPlanarYCbCrImage::SharedPlanarYCbCrImage( 36 TextureClientRecycleAllocator* aRecycleAllocator) 37 : mRecycleAllocator(aRecycleAllocator) { 38 MOZ_COUNT_CTOR(SharedPlanarYCbCrImage); 39 } 40 41 SharedPlanarYCbCrImage::~SharedPlanarYCbCrImage() { 42 MOZ_COUNT_DTOR(SharedPlanarYCbCrImage); 43 } 44 45 TextureClientRecycleAllocator* SharedPlanarYCbCrImage::RecycleAllocator() { 46 static const uint32_t MAX_POOLED_VIDEO_COUNT = 5; 47 48 if (!mRecycleAllocator && mCompositable) { 49 if (!mCompositable->HasTextureClientRecycler()) { 50 // Initialize TextureClientRecycler 51 mCompositable->GetTextureClientRecycler()->SetMaxPoolSize( 52 MAX_POOLED_VIDEO_COUNT); 53 } 54 mRecycleAllocator = mCompositable->GetTextureClientRecycler(); 55 } 56 return mRecycleAllocator; 57 } 58 59 size_t SharedPlanarYCbCrImage::SizeOfExcludingThis( 60 MallocSizeOf aMallocSizeOf) const { 61 // NB: Explicitly skipping mTextureClient, the memory is already reported 62 // at time of allocation in GfxMemoryImageReporter. 63 // Not owned: 64 // - mCompositable 65 return 0; 66 } 67 68 TextureClient* SharedPlanarYCbCrImage::GetTextureClient( 69 KnowsCompositor* aKnowsCompositor) { 70 return mTextureClient.get(); 71 } 72 73 already_AddRefed<gfx::SourceSurface> 74 SharedPlanarYCbCrImage::GetAsSourceSurface() { 75 if (!IsValid()) { 76 NS_WARNING("Can't get as surface"); 77 return nullptr; 78 } 79 return PlanarYCbCrImage::GetAsSourceSurface(); 80 } 81 82 nsresult SharedPlanarYCbCrImage::CopyData(const PlanarYCbCrData& aData) { 83 // If mTextureClient has not already been allocated by CreateEmptyBuffer, 84 // allocate it. This code path is slower than the one used when 85 // CreateEmptyBuffer has been called since it will trigger a full copy. 86 if (!mTextureClient) { 87 nsresult r = 88 CreateEmptyBuffer(aData, aData.YDataSize(), aData.CbCrDataSize()); 89 if (NS_FAILED(r)) { 90 return r; 91 } 92 } 93 94 TextureClientAutoLock autoLock(mTextureClient, OpenMode::OPEN_WRITE_ONLY); 95 if (!autoLock.Succeeded()) { 96 MOZ_ASSERT(false, "Failed to lock the texture."); 97 return NS_ERROR_UNEXPECTED; 98 } 99 100 if (!UpdateYCbCrTextureClient(mTextureClient, aData)) { 101 MOZ_ASSERT(false, "Failed to copy YCbCr data into the TextureClient"); 102 return NS_ERROR_UNEXPECTED; 103 } 104 mTextureClient->MarkImmutable(); 105 return NS_OK; 106 } 107 108 nsresult SharedPlanarYCbCrImage::AdoptData(const Data& aData) { 109 MOZ_ASSERT(false, "This shouldn't be used."); 110 return NS_ERROR_NOT_IMPLEMENTED; 111 } 112 113 bool SharedPlanarYCbCrImage::IsValid() const { 114 return mTextureClient && mTextureClient->IsValid(); 115 } 116 117 nsresult SharedPlanarYCbCrImage::CreateEmptyBuffer( 118 const PlanarYCbCrData& aData, const gfx::IntSize& aYSize, 119 const gfx::IntSize& aCbCrSize) { 120 MOZ_ASSERT(!mTextureClient, "This image already has allocated data"); 121 122 TextureFlags flags = 123 mCompositable ? mCompositable->GetTextureFlags() : TextureFlags::DEFAULT; 124 { 125 YCbCrTextureClientAllocationHelper helper(aData, aYSize, aCbCrSize, flags); 126 Result<already_AddRefed<TextureClient>, nsresult> result = 127 RecycleAllocator()->CreateOrRecycle(helper); 128 if (result.isErr()) { 129 return Err(result.unwrapErr()); 130 } 131 mTextureClient = result.unwrap(); 132 } 133 134 if (!mTextureClient) { 135 NS_WARNING("SharedPlanarYCbCrImage::Allocate failed."); 136 // TODO: TextureClientRecycleAllocator::CreateOrRecycle may return NULL on 137 // non out-of-memory failures. 138 return NS_ERROR_OUT_OF_MEMORY; 139 } 140 141 MappedYCbCrTextureData mapped; 142 // The locking here is sort of a lie. The SharedPlanarYCbCrImage just pulls 143 // pointers out of the TextureClient and keeps them around, which works only 144 // because the underlyin BufferTextureData is always mapped in memory even 145 // outside of the lock/unlock interval. That's sad and new code should follow 146 // this example. 147 if (!mTextureClient->Lock(OpenMode::OPEN_READ) || 148 !mTextureClient->BorrowMappedYCbCrData(mapped)) { 149 MOZ_CRASH("GFX: Cannot lock or borrow mapped YCbCr"); 150 } 151 152 // copy some of aData's values in mData (most of them) 153 mData.mYChannel = mapped.y.data; 154 mData.mCbChannel = mapped.cb.data; 155 mData.mCrChannel = mapped.cr.data; 156 mData.mPictureRect = aData.mPictureRect; 157 mData.mStereoMode = aData.mStereoMode; 158 mData.mYUVColorSpace = aData.mYUVColorSpace; 159 mData.mColorDepth = aData.mColorDepth; 160 mData.mChromaSubsampling = aData.mChromaSubsampling; 161 // those members are not always equal to aData's, due to potentially different 162 // packing. 163 mData.mYSkip = 0; 164 mData.mCbSkip = 0; 165 mData.mCrSkip = 0; 166 mData.mYStride = aData.mYStride; 167 mData.mCbCrStride = aData.mCbCrStride; 168 169 // do not set mBuffer like in PlanarYCbCrImage because the later 170 // will try to manage this memory without knowing it belongs to a 171 // shmem. 172 mBufferSize = ImageDataSerializer::ComputeYCbCrBufferSize( 173 aYSize, mData.mYStride, aCbCrSize, mData.mCbCrStride); 174 mSize = mData.mPictureRect.Size(); 175 mOrigin = mData.mPictureRect.TopLeft(); 176 177 mTextureClient->Unlock(); 178 179 // ImageDataSerializer::ComputeYCbCrBufferSize may return zero when the size 180 // requested is out of the limit. 181 return mBufferSize > 0 ? NS_OK : NS_ERROR_INVALID_ARG; 182 } 183 184 void SharedPlanarYCbCrImage::SetIsDRM(bool aIsDRM) { 185 Image::SetIsDRM(aIsDRM); 186 if (mTextureClient) { 187 mTextureClient->AddFlags(TextureFlags::DRM_SOURCE); 188 } 189 } 190 191 } // namespace layers 192 } // namespace mozilla