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/ipc/SharedMemory.h" // for SharedMemory, etc
15 #include "mozilla/layers/ImageClient.h" // for ImageClient
16 #include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor, etc
17 #include "mozilla/layers/TextureClient.h"
18 #include "mozilla/layers/TextureClientRecycleAllocator.h"
19 #include "mozilla/layers/BufferTexture.h"
20 #include "mozilla/layers/ImageDataSerializer.h"
21 #include "mozilla/layers/ImageBridgeChild.h" // for ImageBridgeChild
22 #include "mozilla/mozalloc.h" // for operator delete
23 #include "nsISupportsImpl.h" // for Image::AddRef
24 #include "mozilla/ipc/Shmem.h"
25
26 namespace mozilla {
27 namespace layers {
28
29 using namespace mozilla::ipc;
30
SharedPlanarYCbCrImage(ImageClient * aCompositable)31 SharedPlanarYCbCrImage::SharedPlanarYCbCrImage(ImageClient* aCompositable)
32 : mCompositable(aCompositable) {
33 MOZ_COUNT_CTOR(SharedPlanarYCbCrImage);
34 }
35
SharedPlanarYCbCrImage(TextureClientRecycleAllocator * aRecycleAllocator)36 SharedPlanarYCbCrImage::SharedPlanarYCbCrImage(
37 TextureClientRecycleAllocator* aRecycleAllocator)
38 : mRecycleAllocator(aRecycleAllocator) {
39 MOZ_COUNT_CTOR(SharedPlanarYCbCrImage);
40 }
41
~SharedPlanarYCbCrImage()42 SharedPlanarYCbCrImage::~SharedPlanarYCbCrImage() {
43 MOZ_COUNT_DTOR(SharedPlanarYCbCrImage);
44 }
45
RecycleAllocator()46 TextureClientRecycleAllocator* SharedPlanarYCbCrImage::RecycleAllocator() {
47 static const uint32_t MAX_POOLED_VIDEO_COUNT = 5;
48
49 if (!mRecycleAllocator && mCompositable) {
50 if (!mCompositable->HasTextureClientRecycler()) {
51 // Initialize TextureClientRecycler
52 mCompositable->GetTextureClientRecycler()->SetMaxPoolSize(
53 MAX_POOLED_VIDEO_COUNT);
54 }
55 mRecycleAllocator = mCompositable->GetTextureClientRecycler();
56 }
57 return mRecycleAllocator;
58 }
59
SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const60 size_t SharedPlanarYCbCrImage::SizeOfExcludingThis(
61 MallocSizeOf aMallocSizeOf) const {
62 // NB: Explicitly skipping mTextureClient, the memory is already reported
63 // at time of allocation in GfxMemoryImageReporter.
64 // Not owned:
65 // - mCompositable
66 return 0;
67 }
68
GetTextureClient(KnowsCompositor * aKnowsCompositor)69 TextureClient* SharedPlanarYCbCrImage::GetTextureClient(
70 KnowsCompositor* aKnowsCompositor) {
71 return mTextureClient.get();
72 }
73
74 already_AddRefed<gfx::SourceSurface>
GetAsSourceSurface()75 SharedPlanarYCbCrImage::GetAsSourceSurface() {
76 if (!IsValid()) {
77 NS_WARNING("Can't get as surface");
78 return nullptr;
79 }
80 return PlanarYCbCrImage::GetAsSourceSurface();
81 }
82
CopyData(const PlanarYCbCrData & aData)83 bool SharedPlanarYCbCrImage::CopyData(const PlanarYCbCrData& aData) {
84 // If mTextureClient has not already been allocated (through Allocate(aData))
85 // allocate it. This code path is slower than the one used when Allocate has
86 // been called since it will trigger a full copy.
87 PlanarYCbCrData data = aData;
88 if (!mTextureClient && !Allocate(data)) {
89 return false;
90 }
91
92 TextureClientAutoLock autoLock(mTextureClient, OpenMode::OPEN_WRITE_ONLY);
93 if (!autoLock.Succeeded()) {
94 MOZ_ASSERT(false, "Failed to lock the texture.");
95 return false;
96 }
97
98 if (!UpdateYCbCrTextureClient(mTextureClient, aData)) {
99 MOZ_ASSERT(false, "Failed to copy YCbCr data into the TextureClient");
100 return false;
101 }
102 mTextureClient->MarkImmutable();
103 return true;
104 }
105
AdoptData(const Data & aData)106 bool SharedPlanarYCbCrImage::AdoptData(const Data& aData) {
107 MOZ_ASSERT(false, "This shouldn't be used.");
108 return false;
109 }
110
CreateEmptyBuffer(const Data & aData)111 bool SharedPlanarYCbCrImage::CreateEmptyBuffer(const Data& aData) {
112 auto data = aData;
113 return Allocate(data);
114 }
115
IsValid() const116 bool SharedPlanarYCbCrImage::IsValid() const {
117 return mTextureClient && mTextureClient->IsValid();
118 }
119
Allocate(PlanarYCbCrData & aData)120 bool SharedPlanarYCbCrImage::Allocate(PlanarYCbCrData& aData) {
121 MOZ_ASSERT(!mTextureClient, "This image already has allocated data");
122
123 TextureFlags flags =
124 mCompositable ? mCompositable->GetTextureFlags() : TextureFlags::DEFAULT;
125 {
126 YCbCrTextureClientAllocationHelper helper(aData, flags);
127 mTextureClient = RecycleAllocator()->CreateOrRecycle(helper);
128 }
129
130 if (!mTextureClient) {
131 NS_WARNING("SharedPlanarYCbCrImage::Allocate failed.");
132 return false;
133 }
134
135 MappedYCbCrTextureData mapped;
136 // The locking here is sort of a lie. The SharedPlanarYCbCrImage just pulls
137 // pointers out of the TextureClient and keeps them around, which works only
138 // because the underlyin BufferTextureData is always mapped in memory even
139 // outside of the lock/unlock interval. That's sad and new code should follow
140 // this example.
141 if (!mTextureClient->Lock(OpenMode::OPEN_READ) ||
142 !mTextureClient->BorrowMappedYCbCrData(mapped)) {
143 MOZ_CRASH("GFX: Cannot lock or borrow mapped YCbCr");
144 }
145
146 aData.mYChannel = mapped.y.data;
147 aData.mCbChannel = mapped.cb.data;
148 aData.mCrChannel = mapped.cr.data;
149
150 // copy some of aData's values in mData (most of them)
151 mData.mYChannel = aData.mYChannel;
152 mData.mCbChannel = aData.mCbChannel;
153 mData.mCrChannel = aData.mCrChannel;
154 mData.mYSize = aData.mYSize;
155 mData.mCbCrSize = aData.mCbCrSize;
156 mData.mPicX = aData.mPicX;
157 mData.mPicY = aData.mPicY;
158 mData.mPicSize = aData.mPicSize;
159 mData.mStereoMode = aData.mStereoMode;
160 mData.mYUVColorSpace = aData.mYUVColorSpace;
161 mData.mColorDepth = aData.mColorDepth;
162 // those members are not always equal to aData's, due to potentially different
163 // packing.
164 mData.mYSkip = 0;
165 mData.mCbSkip = 0;
166 mData.mCrSkip = 0;
167 mData.mYStride = aData.mYStride;
168 mData.mCbCrStride = aData.mCbCrStride;
169
170 // do not set mBuffer like in PlanarYCbCrImage because the later
171 // will try to manage this memory without knowing it belongs to a
172 // shmem.
173 mBufferSize = ImageDataSerializer::ComputeYCbCrBufferSize(
174 mData.mYSize, mData.mYStride, mData.mCbCrSize, mData.mCbCrStride);
175 mSize = mData.mPicSize;
176 mOrigin = gfx::IntPoint(aData.mPicX, aData.mPicY);
177
178 mTextureClient->Unlock();
179
180 return mBufferSize > 0;
181 }
182
183 } // namespace layers
184 } // namespace mozilla
185