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 "CompositableTransactionParent.h"
8 #include "CompositableHost.h"        // for CompositableParent, etc
9 #include "CompositorBridgeParent.h"  // for CompositorBridgeParent
10 #include "mozilla/Assertions.h"      // for MOZ_ASSERT, etc
11 #include "mozilla/RefPtr.h"          // for RefPtr
12 #include "mozilla/layers/CompositorTypes.h"
13 #include "mozilla/layers/ImageBridgeParent.h"  // for ImageBridgeParent
14 #include "mozilla/layers/LayersSurfaces.h"     // for SurfaceDescriptor
15 #include "mozilla/layers/LayersTypes.h"        // for MOZ_LAYERS_LOG
16 #include "mozilla/layers/TextureHost.h"        // for TextureHost
17 #include "mozilla/mozalloc.h"                  // for operator delete
18 #include "mozilla/Unused.h"
19 #include "nsDebug.h"   // for NS_WARNING, NS_ASSERTION
20 #include "nsRegion.h"  // for nsIntRegion
21 
22 #ifdef MOZ_WIDGET_ANDROID
23 #  include "mozilla/layers/AndroidHardwareBuffer.h"
24 #endif
25 
26 namespace mozilla {
27 namespace layers {
28 
ReceiveCompositableUpdate(const CompositableOperation & aEdit)29 bool CompositableParentManager::ReceiveCompositableUpdate(
30     const CompositableOperation& aEdit) {
31   // Ignore all operations on compositables created on stale compositors. We
32   // return true because the child is unable to handle errors.
33   RefPtr<CompositableHost> compositable =
34       FindCompositable(aEdit.compositable());
35   if (!compositable) {
36     return false;
37   }
38   return ReceiveCompositableUpdate(aEdit.detail(), WrapNotNull(compositable));
39 }
40 
ReceiveCompositableUpdate(const CompositableOperationDetail & aDetail,NotNull<CompositableHost * > aCompositable)41 bool CompositableParentManager::ReceiveCompositableUpdate(
42     const CompositableOperationDetail& aDetail,
43     NotNull<CompositableHost*> aCompositable) {
44   switch (aDetail.type()) {
45     case CompositableOperationDetail::TOpRemoveTexture: {
46       const OpRemoveTexture& op = aDetail.get_OpRemoveTexture();
47 
48       RefPtr<TextureHost> tex = TextureHost::AsTextureHost(op.textureParent());
49 
50       MOZ_ASSERT(tex.get());
51       aCompositable->RemoveTextureHost(tex);
52       break;
53     }
54     case CompositableOperationDetail::TOpUseTexture: {
55       const OpUseTexture& op = aDetail.get_OpUseTexture();
56 
57       AutoTArray<CompositableHost::TimedTexture, 4> textures;
58       for (auto& timedTexture : op.textures()) {
59         CompositableHost::TimedTexture* t = textures.AppendElement();
60         t->mTexture = TextureHost::AsTextureHost(timedTexture.textureParent());
61         MOZ_ASSERT(t->mTexture);
62         t->mTimeStamp = timedTexture.timeStamp();
63         t->mPictureRect = timedTexture.picture();
64         t->mFrameID = timedTexture.frameID();
65         t->mProducerID = timedTexture.producerID();
66         if (timedTexture.readLocked()) {
67           t->mTexture->SetReadLocked();
68         }
69       }
70       if (textures.Length() > 0) {
71         aCompositable->UseTextureHost(textures);
72 
73         for (auto& timedTexture : op.textures()) {
74           RefPtr<TextureHost> texture =
75               TextureHost::AsTextureHost(timedTexture.textureParent());
76           if (texture) {
77             texture->SetLastFwdTransactionId(mFwdTransactionId);
78             // Make sure that each texture was handled by the compositable
79             // because the recycling logic depends on it.
80             MOZ_ASSERT(texture->NumCompositableRefs() > 0);
81           }
82         }
83       }
84       break;
85     }
86     case CompositableOperationDetail::TOpDeliverAcquireFence: {
87       const OpDeliverAcquireFence& op = aDetail.get_OpDeliverAcquireFence();
88       RefPtr<TextureHost> tex = TextureHost::AsTextureHost(op.textureParent());
89       MOZ_ASSERT(tex.get());
90       MOZ_ASSERT(tex->AsAndroidHardwareBufferTextureHost());
91 
92       auto fenceFd = op.fenceFd();
93       tex->SetAcquireFence(std::move(fenceFd));
94       break;
95     }
96     default: {
97       MOZ_ASSERT(false, "bad type");
98     }
99   }
100 
101   return true;
102 }
103 
DestroyActor(const OpDestroy & aOp)104 void CompositableParentManager::DestroyActor(const OpDestroy& aOp) {
105   switch (aOp.type()) {
106     case OpDestroy::TPTextureParent: {
107       auto actor = aOp.get_PTextureParent();
108       TextureHost::ReceivedDestroy(actor);
109       break;
110     }
111     case OpDestroy::TCompositableHandle: {
112       ReleaseCompositable(aOp.get_CompositableHandle());
113       break;
114     }
115     default: {
116       MOZ_ASSERT(false, "unsupported type");
117     }
118   }
119 }
120 
AddCompositable(const CompositableHandle & aHandle,const TextureInfo & aInfo)121 RefPtr<CompositableHost> CompositableParentManager::AddCompositable(
122     const CompositableHandle& aHandle, const TextureInfo& aInfo) {
123   if (mCompositables.find(aHandle.Value()) != mCompositables.end()) {
124     NS_ERROR("Client should not allocate duplicate handles");
125     return nullptr;
126   }
127   if (!aHandle) {
128     NS_ERROR("Client should not allocate 0 as a handle");
129     return nullptr;
130   }
131 
132   RefPtr<CompositableHost> host = CompositableHost::Create(aInfo);
133   if (!host) {
134     return nullptr;
135   }
136 
137   mCompositables[aHandle.Value()] = host;
138   return host;
139 }
140 
FindCompositable(const CompositableHandle & aHandle)141 RefPtr<CompositableHost> CompositableParentManager::FindCompositable(
142     const CompositableHandle& aHandle) {
143   auto iter = mCompositables.find(aHandle.Value());
144   if (iter == mCompositables.end()) {
145     return nullptr;
146   }
147 
148   return iter->second;
149 }
150 
ReleaseCompositable(const CompositableHandle & aHandle)151 void CompositableParentManager::ReleaseCompositable(
152     const CompositableHandle& aHandle) {
153   auto iter = mCompositables.find(aHandle.Value());
154   if (iter == mCompositables.end()) {
155     return;
156   }
157 
158   mCompositables.erase(iter);
159 }
160 
161 }  // namespace layers
162 }  // namespace mozilla
163