Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 : * vim: sw=2 ts=8 et :
3 : */
4 : /* This Source Code Form is subject to the terms of the Mozilla Public
5 : * License, v. 2.0. If a copy of the MPL was not distributed with this
6 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 :
8 : #include "CompositableTransactionParent.h"
9 : #include "CompositableHost.h" // for CompositableParent, etc
10 : #include "CompositorBridgeParent.h" // for CompositorBridgeParent
11 : #include "GLContext.h" // for GLContext
12 : #include "Layers.h" // for Layer
13 : #include "RenderTrace.h" // for RenderTraceInvalidateEnd, etc
14 : #include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
15 : #include "mozilla/RefPtr.h" // for RefPtr
16 : #include "mozilla/layers/CompositorTypes.h"
17 : #include "mozilla/layers/ContentHost.h" // for ContentHostBase
18 : #include "mozilla/layers/ImageBridgeParent.h" // for ImageBridgeParent
19 : #include "mozilla/layers/LayerManagerComposite.h"
20 : #include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor
21 : #include "mozilla/layers/LayersTypes.h" // for MOZ_LAYERS_LOG
22 : #include "mozilla/layers/TextureHost.h" // for TextureHost
23 : #include "mozilla/layers/TextureHostOGL.h" // for TextureHostOGL
24 : #include "mozilla/layers/TiledContentHost.h"
25 : #include "mozilla/layers/PaintedLayerComposite.h"
26 : #include "mozilla/mozalloc.h" // for operator delete
27 : #include "mozilla/Unused.h"
28 : #include "nsDebug.h" // for NS_WARNING, NS_ASSERTION
29 : #include "nsRegion.h" // for nsIntRegion
30 :
31 : namespace mozilla {
32 : namespace layers {
33 :
34 : class ClientTiledLayerBuffer;
35 : class Compositor;
36 :
37 : // This function can in some cases fail and return false without it being a bug.
38 : // This can theoretically happen if the ImageBridge sends frames before
39 : // we created the layer tree. Since we can't enforce that the layer
40 : // tree is already created before ImageBridge operates, there isn't much
41 : // we can do about it, but in practice it is very rare.
42 : // Typically when a tab with a video is dragged from a window to another,
43 : // there can be a short time when the video is still sending frames
44 : // asynchonously while the layer tree is not reconstructed. It's not a
45 : // big deal.
46 : // Note that Layers transactions do not need to call this because they always
47 : // schedule the composition, in LayerManagerComposite::EndTransaction.
48 : static bool
49 0 : ScheduleComposition(CompositableHost* aCompositable)
50 : {
51 0 : uint64_t id = aCompositable->GetCompositorBridgeID();
52 0 : if (!id) {
53 0 : return false;
54 : }
55 0 : CompositorBridgeParent* cp = CompositorBridgeParent::GetCompositorBridgeParent(id);
56 0 : if (!cp) {
57 0 : return false;
58 : }
59 0 : cp->ScheduleComposition();
60 0 : return true;
61 : }
62 :
63 : bool
64 66 : CompositableParentManager::ReceiveCompositableUpdate(const CompositableOperation& aEdit)
65 : {
66 : // Ignore all operations on compositables created on stale compositors. We
67 : // return true because the child is unable to handle errors.
68 132 : RefPtr<CompositableHost> compositable = FindCompositable(aEdit.compositable());
69 66 : if (!compositable) {
70 0 : return false;
71 : }
72 66 : if (TextureSourceProvider* provider = compositable->GetTextureSourceProvider()) {
73 66 : if (!provider->IsValid()) {
74 0 : return false;
75 : }
76 : }
77 :
78 66 : switch (aEdit.detail().type()) {
79 : case CompositableOperationDetail::TOpPaintTextureRegion: {
80 33 : MOZ_LAYERS_LOG(("[ParentSide] Paint PaintedLayer"));
81 :
82 33 : const OpPaintTextureRegion& op = aEdit.detail().get_OpPaintTextureRegion();
83 33 : Layer* layer = compositable->GetLayer();
84 33 : if (!layer || layer->GetType() != Layer::TYPE_PAINTED) {
85 0 : return false;
86 : }
87 33 : PaintedLayerComposite* thebes = static_cast<PaintedLayerComposite*>(layer);
88 :
89 33 : const ThebesBufferData& bufferData = op.bufferData();
90 :
91 33 : RenderTraceInvalidateStart(thebes, "FF00FF", op.updatedRegion().GetBounds());
92 :
93 66 : if (!compositable->UpdateThebes(bufferData,
94 : op.updatedRegion(),
95 33 : thebes->GetValidRegion()))
96 : {
97 0 : return false;
98 : }
99 :
100 33 : RenderTraceInvalidateEnd(thebes, "FF00FF");
101 33 : break;
102 : }
103 : case CompositableOperationDetail::TOpUseTiledLayerBuffer: {
104 0 : MOZ_LAYERS_LOG(("[ParentSide] Paint TiledLayerBuffer"));
105 0 : const OpUseTiledLayerBuffer& op = aEdit.detail().get_OpUseTiledLayerBuffer();
106 0 : TiledContentHost* tiledHost = compositable->AsTiledContentHost();
107 :
108 0 : NS_ASSERTION(tiledHost, "The compositable is not tiled");
109 :
110 0 : const SurfaceDescriptorTiles& tileDesc = op.tileLayerDescriptor();
111 :
112 0 : bool success = tiledHost->UseTiledLayerBuffer(this, tileDesc);
113 :
114 0 : const InfallibleTArray<TileDescriptor>& tileDescriptors = tileDesc.tiles();
115 0 : for (size_t i = 0; i < tileDescriptors.Length(); i++) {
116 0 : const TileDescriptor& tileDesc = tileDescriptors[i];
117 0 : if (tileDesc.type() != TileDescriptor::TTexturedTileDescriptor) {
118 0 : continue;
119 : }
120 0 : const TexturedTileDescriptor& texturedDesc = tileDesc.get_TexturedTileDescriptor();
121 0 : RefPtr<TextureHost> texture = TextureHost::AsTextureHost(texturedDesc.textureParent());
122 0 : if (texture) {
123 0 : texture->SetLastFwdTransactionId(mFwdTransactionId);
124 : // Make sure that each texture was handled by the compositable
125 : // because the recycling logic depends on it.
126 0 : MOZ_ASSERT(texture->NumCompositableRefs() > 0);
127 : }
128 0 : if (texturedDesc.textureOnWhite().type() == MaybeTexture::TPTextureParent) {
129 0 : texture = TextureHost::AsTextureHost(texturedDesc.textureOnWhite().get_PTextureParent());
130 0 : if (texture) {
131 0 : texture->SetLastFwdTransactionId(mFwdTransactionId);
132 : // Make sure that each texture was handled by the compositable
133 : // because the recycling logic depends on it.
134 0 : MOZ_ASSERT(texture->NumCompositableRefs() > 0);
135 : }
136 : }
137 : }
138 0 : if (!success) {
139 0 : return false;
140 : }
141 0 : break;
142 : }
143 : case CompositableOperationDetail::TOpRemoveTexture: {
144 0 : const OpRemoveTexture& op = aEdit.detail().get_OpRemoveTexture();
145 :
146 0 : RefPtr<TextureHost> tex = TextureHost::AsTextureHost(op.textureParent());
147 :
148 0 : MOZ_ASSERT(tex.get());
149 0 : compositable->RemoveTextureHost(tex);
150 0 : break;
151 : }
152 : case CompositableOperationDetail::TOpUseTexture: {
153 33 : const OpUseTexture& op = aEdit.detail().get_OpUseTexture();
154 :
155 66 : AutoTArray<CompositableHost::TimedTexture,4> textures;
156 66 : for (auto& timedTexture : op.textures()) {
157 33 : CompositableHost::TimedTexture* t = textures.AppendElement();
158 : t->mTexture =
159 33 : TextureHost::AsTextureHost(timedTexture.textureParent());
160 33 : MOZ_ASSERT(t->mTexture);
161 33 : t->mTimeStamp = timedTexture.timeStamp();
162 33 : t->mPictureRect = timedTexture.picture();
163 33 : t->mFrameID = timedTexture.frameID();
164 33 : t->mProducerID = timedTexture.producerID();
165 33 : t->mTexture->SetReadLock(FindReadLock(timedTexture.sharedLock()));
166 : }
167 33 : if (textures.Length() > 0) {
168 33 : compositable->UseTextureHost(textures);
169 :
170 66 : for (auto& timedTexture : op.textures()) {
171 66 : RefPtr<TextureHost> texture = TextureHost::AsTextureHost(timedTexture.textureParent());
172 33 : if (texture) {
173 33 : texture->SetLastFwdTransactionId(mFwdTransactionId);
174 : // Make sure that each texture was handled by the compositable
175 : // because the recycling logic depends on it.
176 33 : MOZ_ASSERT(texture->NumCompositableRefs() > 0);
177 : }
178 : }
179 : }
180 :
181 33 : if (UsesImageBridge() && compositable->GetLayer()) {
182 0 : ScheduleComposition(compositable);
183 : }
184 33 : break;
185 : }
186 : case CompositableOperationDetail::TOpUseComponentAlphaTextures: {
187 0 : const OpUseComponentAlphaTextures& op = aEdit.detail().get_OpUseComponentAlphaTextures();
188 0 : RefPtr<TextureHost> texOnBlack = TextureHost::AsTextureHost(op.textureOnBlackParent());
189 0 : RefPtr<TextureHost> texOnWhite = TextureHost::AsTextureHost(op.textureOnWhiteParent());
190 0 : texOnBlack->SetReadLock(FindReadLock(op.sharedLockBlack()));
191 0 : texOnWhite->SetReadLock(FindReadLock(op.sharedLockWhite()));
192 :
193 0 : MOZ_ASSERT(texOnBlack && texOnWhite);
194 0 : compositable->UseComponentAlphaTextures(texOnBlack, texOnWhite);
195 :
196 0 : if (texOnBlack) {
197 0 : texOnBlack->SetLastFwdTransactionId(mFwdTransactionId);
198 : // Make sure that each texture was handled by the compositable
199 : // because the recycling logic depends on it.
200 0 : MOZ_ASSERT(texOnBlack->NumCompositableRefs() > 0);
201 : }
202 :
203 0 : if (texOnWhite) {
204 0 : texOnWhite->SetLastFwdTransactionId(mFwdTransactionId);
205 : // Make sure that each texture was handled by the compositable
206 : // because the recycling logic depends on it.
207 0 : MOZ_ASSERT(texOnWhite->NumCompositableRefs() > 0);
208 : }
209 :
210 0 : if (UsesImageBridge()) {
211 0 : ScheduleComposition(compositable);
212 : }
213 0 : break;
214 : }
215 : default: {
216 0 : MOZ_ASSERT(false, "bad type");
217 : }
218 : }
219 :
220 66 : return true;
221 : }
222 :
223 : void
224 2 : CompositableParentManager::DestroyActor(const OpDestroy& aOp)
225 : {
226 2 : switch (aOp.type()) {
227 : case OpDestroy::TPTextureParent: {
228 2 : auto actor = aOp.get_PTextureParent();
229 2 : TextureHost::ReceivedDestroy(actor);
230 2 : break;
231 : }
232 : case OpDestroy::TCompositableHandle: {
233 0 : ReleaseCompositable(aOp.get_CompositableHandle());
234 0 : break;
235 : }
236 : default: {
237 0 : MOZ_ASSERT(false, "unsupported type");
238 : }
239 : }
240 2 : }
241 :
242 : RefPtr<CompositableHost>
243 22 : CompositableParentManager::AddCompositable(const CompositableHandle& aHandle,
244 : const TextureInfo& aInfo)
245 : {
246 22 : if (mCompositables.find(aHandle.Value()) != mCompositables.end()) {
247 0 : NS_ERROR("Client should not allocate duplicate handles");
248 0 : return nullptr;
249 : }
250 22 : if (!aHandle) {
251 0 : NS_ERROR("Client should not allocate 0 as a handle");
252 0 : return nullptr;
253 : }
254 :
255 44 : RefPtr<CompositableHost> host = CompositableHost::Create(aInfo);
256 22 : if (!host) {
257 0 : return nullptr;
258 : }
259 :
260 22 : mCompositables[aHandle.Value()] = host;
261 22 : return host;
262 : }
263 :
264 : RefPtr<CompositableHost>
265 88 : CompositableParentManager::FindCompositable(const CompositableHandle& aHandle)
266 : {
267 88 : auto iter = mCompositables.find(aHandle.Value());
268 88 : if (iter == mCompositables.end()) {
269 0 : return nullptr;
270 : }
271 88 : return iter->second;
272 : }
273 :
274 : void
275 19 : CompositableParentManager::ReleaseCompositable(const CompositableHandle& aHandle)
276 : {
277 19 : auto iter = mCompositables.find(aHandle.Value());
278 19 : if (iter == mCompositables.end()) {
279 0 : return;
280 : }
281 :
282 38 : RefPtr<CompositableHost> host = iter->second;
283 19 : mCompositables.erase(iter);
284 :
285 19 : host->Detach(nullptr, CompositableHost::FORCE_DETACH);
286 : }
287 :
288 : bool
289 24 : CompositableParentManager::AddReadLocks(ReadLockArray&& aReadLocks)
290 : {
291 57 : for (ReadLockInit& r : aReadLocks) {
292 33 : if (mReadLocks.find(r.handle().Value()) != mReadLocks.end()) {
293 0 : NS_ERROR("Duplicate read lock handle!");
294 0 : return false;
295 : }
296 33 : mReadLocks[r.handle().Value()] = TextureReadLock::Deserialize(r.sharedLock(), this);
297 : }
298 24 : return true;
299 : }
300 :
301 : TextureReadLock*
302 33 : CompositableParentManager::FindReadLock(const ReadLockHandle& aHandle)
303 : {
304 33 : auto iter = mReadLocks.find(aHandle.Value());
305 33 : if (iter == mReadLocks.end()) {
306 0 : return nullptr;
307 : }
308 33 : return iter->second.get();
309 : }
310 :
311 : } // namespace layers
312 : } // namespace mozilla
313 :
|