Line data Source code
1 : /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 : * This Source Code Form is subject to the terms of the Mozilla Public
3 : * License, v. 2.0. If a copy of the MPL was not distributed with this
4 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 :
6 : #include "SharedPlanarYCbCrImage.h"
7 : #include <stddef.h> // for size_t
8 : #include <stdio.h> // for printf
9 : #include "gfx2DGlue.h" // for Moz2D transition helpers
10 : #include "ISurfaceAllocator.h" // for ISurfaceAllocator, etc
11 : #include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
12 : #include "mozilla/gfx/Types.h" // for SurfaceFormat::SurfaceFormat::YUV
13 : #include "mozilla/ipc/SharedMemory.h" // for SharedMemory, etc
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 0 : SharedPlanarYCbCrImage::SharedPlanarYCbCrImage(ImageClient* aCompositable)
31 0 : : mCompositable(aCompositable)
32 : {
33 0 : MOZ_COUNT_CTOR(SharedPlanarYCbCrImage);
34 0 : }
35 :
36 0 : SharedPlanarYCbCrImage::~SharedPlanarYCbCrImage() {
37 0 : MOZ_COUNT_DTOR(SharedPlanarYCbCrImage);
38 :
39 0 : if (mCompositable->GetAsyncHandle() && !InImageBridgeChildThread()) {
40 0 : if (mTextureClient) {
41 0 : ADDREF_MANUALLY(mTextureClient);
42 0 : ImageBridgeChild::DispatchReleaseTextureClient(mTextureClient);
43 0 : mTextureClient = nullptr;
44 : }
45 : }
46 0 : }
47 :
48 : size_t
49 0 : SharedPlanarYCbCrImage::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
50 : {
51 : // NB: Explicitly skipping mTextureClient, the memory is already reported
52 : // at time of allocation in GfxMemoryImageReporter.
53 : // Not owned:
54 : // - mCompositable
55 0 : return 0;
56 : }
57 :
58 : TextureClient*
59 0 : SharedPlanarYCbCrImage::GetTextureClient(KnowsCompositor* aForwarder)
60 : {
61 0 : return mTextureClient.get();
62 : }
63 :
64 : uint8_t*
65 0 : SharedPlanarYCbCrImage::GetBuffer()
66 : {
67 : // This should never be used
68 0 : MOZ_ASSERT(false);
69 : return nullptr;
70 : }
71 :
72 : already_AddRefed<gfx::SourceSurface>
73 0 : SharedPlanarYCbCrImage::GetAsSourceSurface()
74 : {
75 0 : if (!IsValid()) {
76 0 : NS_WARNING("Can't get as surface");
77 0 : return nullptr;
78 : }
79 0 : return PlanarYCbCrImage::GetAsSourceSurface();
80 : }
81 :
82 : bool
83 0 : SharedPlanarYCbCrImage::CopyData(const PlanarYCbCrData& aData)
84 : {
85 : // If mTextureClient has not already been allocated (through Allocate(aData))
86 : // allocate it. This code path is slower than the one used when Allocate has
87 : // been called since it will trigger a full copy.
88 0 : PlanarYCbCrData data = aData;
89 0 : if (!mTextureClient && !Allocate(data)) {
90 0 : return false;
91 : }
92 :
93 0 : TextureClientAutoLock autoLock(mTextureClient, OpenMode::OPEN_WRITE_ONLY);
94 0 : if (!autoLock.Succeeded()) {
95 0 : MOZ_ASSERT(false, "Failed to lock the texture.");
96 : return false;
97 : }
98 :
99 0 : if (!UpdateYCbCrTextureClient(mTextureClient, aData)) {
100 0 : MOZ_ASSERT(false, "Failed to copy YCbCr data into the TextureClient");
101 : return false;
102 : }
103 0 : mTextureClient->MarkImmutable();
104 0 : return true;
105 : }
106 :
107 : // needs to be overriden because the parent class sets mBuffer which we
108 : // do not want to happen.
109 : uint8_t*
110 0 : SharedPlanarYCbCrImage::AllocateAndGetNewBuffer(uint32_t aSize)
111 : {
112 0 : MOZ_ASSERT(!mTextureClient, "This image already has allocated data");
113 0 : size_t size = ImageDataSerializer::ComputeYCbCrBufferSize(aSize);
114 0 : if (!size) {
115 0 : return nullptr;
116 : }
117 :
118 : // XXX Add YUVColorSpace handling. Use YUVColorSpace::BT601 for now.
119 0 : mTextureClient = TextureClient::CreateForYCbCrWithBufferSize(mCompositable->GetForwarder(),
120 : size,
121 : YUVColorSpace::BT601,
122 0 : mCompositable->GetTextureFlags());
123 :
124 : // get new buffer _without_ setting mBuffer.
125 0 : if (!mTextureClient) {
126 0 : return nullptr;
127 : }
128 :
129 : // update buffer size
130 0 : mBufferSize = size;
131 :
132 0 : MappedYCbCrTextureData mapped;
133 0 : if (mTextureClient->BorrowMappedYCbCrData(mapped)) {
134 : // The caller expects a pointer to the beginning of the writable part of the
135 : // buffer which is where the y channel starts by default.
136 0 : return mapped.y.data;
137 : } else {
138 0 : MOZ_CRASH("GFX: Cannot borrow mapped YCbCr data");
139 : }
140 : }
141 :
142 : bool
143 0 : SharedPlanarYCbCrImage::AdoptData(const Data &aData)
144 : {
145 : // AdoptData is used to update YUV plane offsets without (re)allocating
146 : // memory previously allocated with AllocateAndGetNewBuffer().
147 :
148 0 : MOZ_ASSERT(mTextureClient, "This Image should have already allocated data");
149 0 : if (!mTextureClient) {
150 0 : return false;
151 : }
152 0 : mData = aData;
153 0 : mSize = aData.mPicSize;
154 0 : mOrigin = gfx::IntPoint(aData.mPicX, aData.mPicY);
155 :
156 0 : uint8_t *base = GetBuffer();
157 0 : uint32_t yOffset = aData.mYChannel - base;
158 0 : uint32_t cbOffset = aData.mCbChannel - base;
159 0 : uint32_t crOffset = aData.mCrChannel - base;
160 :
161 0 : auto fwd = mCompositable->GetForwarder();
162 0 : bool hasIntermediateBuffer = ComputeHasIntermediateBuffer(gfx::SurfaceFormat::YUV,
163 0 : fwd->GetCompositorBackendType());
164 :
165 0 : static_cast<BufferTextureData*>(mTextureClient->GetInternalData())->SetDesciptor(
166 0 : YCbCrDescriptor(aData.mYSize, aData.mCbCrSize, yOffset, cbOffset, crOffset,
167 : aData.mStereoMode, aData.mYUVColorSpace, hasIntermediateBuffer)
168 0 : );
169 :
170 0 : return true;
171 : }
172 :
173 : bool
174 0 : SharedPlanarYCbCrImage::IsValid() {
175 0 : return mTextureClient && mTextureClient->IsValid();
176 : }
177 :
178 : bool
179 0 : SharedPlanarYCbCrImage::Allocate(PlanarYCbCrData& aData)
180 : {
181 0 : MOZ_ASSERT(!mTextureClient,
182 : "This image already has allocated data");
183 : static const uint32_t MAX_POOLED_VIDEO_COUNT = 5;
184 :
185 0 : if (!mCompositable->HasTextureClientRecycler()) {
186 : // Initialize TextureClientRecycler
187 0 : mCompositable->GetTextureClientRecycler()->SetMaxPoolSize(MAX_POOLED_VIDEO_COUNT);
188 : }
189 :
190 : {
191 0 : YCbCrTextureClientAllocationHelper helper(aData, mCompositable->GetTextureFlags());
192 0 : mTextureClient = mCompositable->GetTextureClientRecycler()->CreateOrRecycle(helper);
193 : }
194 :
195 0 : if (!mTextureClient) {
196 0 : NS_WARNING("SharedPlanarYCbCrImage::Allocate failed.");
197 0 : return false;
198 : }
199 :
200 0 : MappedYCbCrTextureData mapped;
201 : // The locking here is sort of a lie. The SharedPlanarYCbCrImage just pulls
202 : // pointers out of the TextureClient and keeps them around, which works only
203 : // because the underlyin BufferTextureData is always mapped in memory even outside
204 : // of the lock/unlock interval. That's sad and new code should follow this example.
205 0 : if (!mTextureClient->Lock(OpenMode::OPEN_READ) || !mTextureClient->BorrowMappedYCbCrData(mapped)) {
206 0 : MOZ_CRASH("GFX: Cannot lock or borrow mapped YCbCr");
207 : }
208 :
209 0 : aData.mYChannel = mapped.y.data;
210 0 : aData.mCbChannel = mapped.cb.data;
211 0 : aData.mCrChannel = mapped.cr.data;
212 :
213 : // copy some of aData's values in mData (most of them)
214 0 : mData.mYChannel = aData.mYChannel;
215 0 : mData.mCbChannel = aData.mCbChannel;
216 0 : mData.mCrChannel = aData.mCrChannel;
217 0 : mData.mYSize = aData.mYSize;
218 0 : mData.mCbCrSize = aData.mCbCrSize;
219 0 : mData.mPicX = aData.mPicX;
220 0 : mData.mPicY = aData.mPicY;
221 0 : mData.mPicSize = aData.mPicSize;
222 0 : mData.mStereoMode = aData.mStereoMode;
223 0 : mData.mYUVColorSpace = aData.mYUVColorSpace;
224 : // those members are not always equal to aData's, due to potentially different
225 : // packing.
226 0 : mData.mYSkip = 0;
227 0 : mData.mCbSkip = 0;
228 0 : mData.mCrSkip = 0;
229 0 : mData.mYStride = mData.mYSize.width;
230 0 : mData.mCbCrStride = mData.mCbCrSize.width;
231 :
232 : // do not set mBuffer like in PlanarYCbCrImage because the later
233 : // will try to manage this memory without knowing it belongs to a
234 : // shmem.
235 0 : mBufferSize = ImageDataSerializer::ComputeYCbCrBufferSize(mData.mYSize, mData.mCbCrSize);
236 0 : mSize = mData.mPicSize;
237 0 : mOrigin = gfx::IntPoint(aData.mPicX, aData.mPicY);
238 :
239 0 : mTextureClient->Unlock();
240 :
241 0 : return mBufferSize > 0;
242 : }
243 :
244 : } // namespace layers
245 : } // namespace mozilla
|