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 "ShadowLayers.h"
8
9 #include <set> // for _Rb_tree_const_iterator, etc
10 #include <vector> // for vector
11
12 #include "ClientLayerManager.h" // for ClientLayerManager
13 #include "IPDLActor.h"
14 #include "ISurfaceAllocator.h" // for IsSurfaceDescriptorValid
15 #include "Layers.h" // for Layer
16 #include "RenderTrace.h" // for RenderTraceScope
17 #include "gfx2DGlue.h" // for Moz2D transition helpers
18 #include "gfxPlatform.h" // for gfxImageFormat, gfxPlatform
19 #include "ipc/IPCMessageUtils.h" // for gfxContentType, null_t
20 #include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
21 #include "mozilla/gfx/Point.h" // for IntSize
22 #include "mozilla/layers/CompositableClient.h" // for CompositableClient, etc
23 #include "mozilla/layers/CompositorBridgeChild.h"
24 #include "mozilla/layers/ContentClient.h"
25 #include "mozilla/layers/ImageBridgeChild.h"
26 #include "mozilla/layers/ImageDataSerializer.h"
27 #include "mozilla/layers/LayerTransactionChild.h"
28 #include "mozilla/layers/LayersMessages.h" // for Edit, etc
29 #include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor, etc
30 #include "mozilla/layers/LayersTypes.h" // for MOZ_LAYERS_LOG
31 #include "mozilla/layers/PTextureChild.h"
32 #include "mozilla/layers/SyncObject.h"
33 #ifdef XP_DARWIN
34 # include "mozilla/layers/TextureSync.h"
35 #endif
36 #include "ShadowLayerUtils.h"
37 #include "mozilla/ProfilerLabels.h"
38 #include "mozilla/ReentrantMonitor.h"
39 #include "mozilla/StaticPrefs_layers.h"
40 #include "mozilla/layers/TextureClient.h" // for TextureClient
41 #include "mozilla/mozalloc.h" // for operator new, etc
42 #include "nsIXULRuntime.h" // for BrowserTabsRemoteAutostart
43 #include "nsTArray.h" // for AutoTArray, nsTArray, etc
44 #include "nsTHashSet.h"
45 #include "nsXULAppAPI.h" // for XRE_GetProcessType, etc
46
47 namespace mozilla {
48 namespace ipc {
49 class Shmem;
50 } // namespace ipc
51
52 namespace layers {
53
54 using namespace mozilla::gfx;
55 using namespace mozilla::gl;
56 using namespace mozilla::ipc;
57
58 class ClientTiledLayerBuffer;
59
60 typedef nsTArray<SurfaceDescriptor> BufferArray;
61 typedef nsTArray<Edit> EditVector;
62 typedef nsTHashSet<ShadowableLayer*> ShadowableLayerSet;
63 typedef nsTArray<OpDestroy> OpDestroyVector;
64
65 class Transaction {
66 public:
Transaction()67 Transaction()
68 : mTargetRotation(ROTATION_0),
69 mTargetOrientation(hal::eScreenOrientation_None),
70 mOpen(false),
71 mRotationChanged(false) {}
72
Begin(const gfx::IntRect & aTargetBounds,ScreenRotation aRotation,hal::ScreenOrientation aOrientation)73 void Begin(const gfx::IntRect& aTargetBounds, ScreenRotation aRotation,
74 hal::ScreenOrientation aOrientation) {
75 mOpen = true;
76 mTargetBounds = aTargetBounds;
77 if (aRotation != mTargetRotation) {
78 // the first time this is called, mRotationChanged will be false if
79 // aRotation is 0, but we should be OK because for the first transaction
80 // we should only compose if it is non-empty. See the caller(s) of
81 // RotationChanged.
82 mRotationChanged = true;
83 }
84 mTargetRotation = aRotation;
85 mTargetOrientation = aOrientation;
86 }
AddEdit(const Edit & aEdit)87 void AddEdit(const Edit& aEdit) {
88 MOZ_ASSERT(!Finished(), "forgot BeginTransaction?");
89 mCset.AppendElement(aEdit);
90 }
AddEdit(const CompositableOperation & aEdit)91 void AddEdit(const CompositableOperation& aEdit) { AddEdit(Edit(aEdit)); }
92
AddNoSwapPaint(const CompositableOperation & aPaint)93 void AddNoSwapPaint(const CompositableOperation& aPaint) {
94 MOZ_ASSERT(!Finished(), "forgot BeginTransaction?");
95 mPaints.AppendElement(Edit(aPaint));
96 }
AddMutant(ShadowableLayer * aLayer)97 void AddMutant(ShadowableLayer* aLayer) {
98 MOZ_ASSERT(!Finished(), "forgot BeginTransaction?");
99 mMutants.Insert(aLayer);
100 }
AddSimpleMutant(ShadowableLayer * aLayer)101 void AddSimpleMutant(ShadowableLayer* aLayer) {
102 MOZ_ASSERT(!Finished(), "forgot BeginTransaction?");
103 mSimpleMutants.Insert(aLayer);
104 }
End()105 void End() {
106 mCset.Clear();
107 mPaints.Clear();
108 mMutants.Clear();
109 mSimpleMutants.Clear();
110 mDestroyedActors.Clear();
111 mOpen = false;
112 mRotationChanged = false;
113 }
114
Empty() const115 bool Empty() const {
116 return mCset.IsEmpty() && mPaints.IsEmpty() && mMutants.IsEmpty() &&
117 mSimpleMutants.IsEmpty() && mDestroyedActors.IsEmpty();
118 }
RotationChanged() const119 bool RotationChanged() const { return mRotationChanged; }
Finished() const120 bool Finished() const { return !mOpen && Empty(); }
121
Opened() const122 bool Opened() const { return mOpen; }
123
124 EditVector mCset;
125 nsTArray<CompositableOperation> mPaints;
126 OpDestroyVector mDestroyedActors;
127 ShadowableLayerSet mMutants;
128 ShadowableLayerSet mSimpleMutants;
129 gfx::IntRect mTargetBounds;
130 ScreenRotation mTargetRotation;
131 hal::ScreenOrientation mTargetOrientation;
132
133 private:
134 bool mOpen;
135 bool mRotationChanged;
136
137 // disabled
138 Transaction(const Transaction&);
139 Transaction& operator=(const Transaction&);
140 };
141 struct AutoTxnEnd final {
AutoTxnEndmozilla::layers::AutoTxnEnd142 explicit AutoTxnEnd(Transaction* aTxn) : mTxn(aTxn) {}
~AutoTxnEndmozilla::layers::AutoTxnEnd143 ~AutoTxnEnd() { mTxn->End(); }
144 Transaction* mTxn;
145 };
146
IdentifyTextureHost(const TextureFactoryIdentifier & aIdentifier)147 void KnowsCompositor::IdentifyTextureHost(
148 const TextureFactoryIdentifier& aIdentifier) {
149 auto lock = mData.Lock();
150 lock.ref().mTextureFactoryIdentifier = aIdentifier;
151
152 lock.ref().mSyncObject =
153 SyncObjectClient::CreateSyncObjectClientForContentDevice(
154 aIdentifier.mSyncHandle);
155 }
156
KnowsCompositor()157 KnowsCompositor::KnowsCompositor()
158 : mData("KnowsCompositorMutex"), mSerial(++sSerialCounter) {}
159
160 KnowsCompositor::~KnowsCompositor() = default;
161
KnowsCompositorMediaProxy(const TextureFactoryIdentifier & aIdentifier)162 KnowsCompositorMediaProxy::KnowsCompositorMediaProxy(
163 const TextureFactoryIdentifier& aIdentifier) {
164 auto lock = mData.Lock();
165 lock.ref().mTextureFactoryIdentifier = aIdentifier;
166 // overwrite mSerial's value set by the parent class because we use the same
167 // serial as the KnowsCompositor we are proxying.
168 mThreadSafeAllocator = ImageBridgeChild::GetSingleton();
169 lock.ref().mSyncObject = mThreadSafeAllocator->GetSyncObject();
170 }
171
172 KnowsCompositorMediaProxy::~KnowsCompositorMediaProxy() = default;
173
GetTextureForwarder()174 TextureForwarder* KnowsCompositorMediaProxy::GetTextureForwarder() {
175 return mThreadSafeAllocator->GetTextureForwarder();
176 }
177
GetLayersIPCActor()178 LayersIPCActor* KnowsCompositorMediaProxy::GetLayersIPCActor() {
179 return mThreadSafeAllocator->GetLayersIPCActor();
180 }
181
GetActiveResourceTracker()182 ActiveResourceTracker* KnowsCompositorMediaProxy::GetActiveResourceTracker() {
183 return mThreadSafeAllocator->GetActiveResourceTracker();
184 }
185
SyncWithCompositor()186 void KnowsCompositorMediaProxy::SyncWithCompositor() {
187 mThreadSafeAllocator->SyncWithCompositor();
188 }
189
GetForMedia()190 RefPtr<KnowsCompositor> ShadowLayerForwarder::GetForMedia() {
191 return MakeAndAddRef<KnowsCompositorMediaProxy>(
192 GetTextureFactoryIdentifier());
193 }
194
ShadowLayerForwarder(ClientLayerManager * aClientLayerManager)195 ShadowLayerForwarder::ShadowLayerForwarder(
196 ClientLayerManager* aClientLayerManager)
197 : mClientLayerManager(aClientLayerManager),
198 mThread(NS_GetCurrentThread()),
199 mDiagnosticTypes(DiagnosticTypes::NO_DIAGNOSTIC),
200 mIsFirstPaint(false),
201 mNextLayerHandle(1) {
202 mTxn = new Transaction();
203 mEventTarget = GetMainThreadSerialEventTarget();
204
205 MOZ_ASSERT(mEventTarget || !XRE_IsContentProcess());
206 mActiveResourceTracker = MakeUnique<ActiveResourceTracker>(
207 1000, "CompositableForwarder", mEventTarget);
208 }
209
210 template <typename T>
211 struct ReleaseOnMainThreadTask : public Runnable {
212 UniquePtr<T> mObj;
213
ReleaseOnMainThreadTaskmozilla::layers::ReleaseOnMainThreadTask214 explicit ReleaseOnMainThreadTask(UniquePtr<T>& aObj)
215 : Runnable("layers::ReleaseOnMainThreadTask"), mObj(std::move(aObj)) {}
216
Runmozilla::layers::ReleaseOnMainThreadTask217 NS_IMETHOD Run() override {
218 mObj = nullptr;
219 return NS_OK;
220 }
221 };
222
~ShadowLayerForwarder()223 ShadowLayerForwarder::~ShadowLayerForwarder() {
224 MOZ_ASSERT(mTxn->Finished(), "unfinished transaction?");
225 delete mTxn;
226 if (mShadowManager) {
227 mShadowManager->SetForwarder(nullptr);
228 if (NS_IsMainThread()) {
229 mShadowManager->Destroy();
230 } else {
231 if (mEventTarget) {
232 mEventTarget->Dispatch(
233 NewRunnableMethod("LayerTransactionChild::Destroy", mShadowManager,
234 &LayerTransactionChild::Destroy),
235 nsIEventTarget::DISPATCH_NORMAL);
236 } else {
237 NS_DispatchToMainThread(
238 NewRunnableMethod("layers::LayerTransactionChild::Destroy",
239 mShadowManager, &LayerTransactionChild::Destroy));
240 }
241 }
242 }
243
244 if (!NS_IsMainThread()) {
245 RefPtr<ReleaseOnMainThreadTask<ActiveResourceTracker>> event =
246 new ReleaseOnMainThreadTask<ActiveResourceTracker>(
247 mActiveResourceTracker);
248 if (mEventTarget) {
249 mEventTarget->Dispatch(event.forget(), nsIEventTarget::DISPATCH_NORMAL);
250 } else {
251 NS_DispatchToMainThread(event);
252 }
253 }
254 }
255
BeginTransaction(const gfx::IntRect & aTargetBounds,ScreenRotation aRotation,hal::ScreenOrientation aOrientation)256 void ShadowLayerForwarder::BeginTransaction(
257 const gfx::IntRect& aTargetBounds, ScreenRotation aRotation,
258 hal::ScreenOrientation aOrientation) {
259 MOZ_ASSERT(IPCOpen(), "no manager to forward to");
260 MOZ_ASSERT(mTxn->Finished(), "uncommitted txn?");
261 UpdateFwdTransactionId();
262 mTxn->Begin(aTargetBounds, aRotation, aOrientation);
263 }
264
Shadow(ShadowableLayer * aLayer)265 static const LayerHandle& Shadow(ShadowableLayer* aLayer) {
266 return aLayer->GetShadow();
267 }
268
269 template <typename OpCreateT>
CreatedLayer(Transaction * aTxn,ShadowableLayer * aLayer)270 static void CreatedLayer(Transaction* aTxn, ShadowableLayer* aLayer) {
271 aTxn->AddEdit(OpCreateT(Shadow(aLayer)));
272 }
273
CreatedPaintedLayer(ShadowableLayer * aThebes)274 void ShadowLayerForwarder::CreatedPaintedLayer(ShadowableLayer* aThebes) {
275 CreatedLayer<OpCreatePaintedLayer>(mTxn, aThebes);
276 }
CreatedContainerLayer(ShadowableLayer * aContainer)277 void ShadowLayerForwarder::CreatedContainerLayer(ShadowableLayer* aContainer) {
278 CreatedLayer<OpCreateContainerLayer>(mTxn, aContainer);
279 }
CreatedImageLayer(ShadowableLayer * aImage)280 void ShadowLayerForwarder::CreatedImageLayer(ShadowableLayer* aImage) {
281 CreatedLayer<OpCreateImageLayer>(mTxn, aImage);
282 }
CreatedColorLayer(ShadowableLayer * aColor)283 void ShadowLayerForwarder::CreatedColorLayer(ShadowableLayer* aColor) {
284 CreatedLayer<OpCreateColorLayer>(mTxn, aColor);
285 }
CreatedCanvasLayer(ShadowableLayer * aCanvas)286 void ShadowLayerForwarder::CreatedCanvasLayer(ShadowableLayer* aCanvas) {
287 CreatedLayer<OpCreateCanvasLayer>(mTxn, aCanvas);
288 }
CreatedRefLayer(ShadowableLayer * aRef)289 void ShadowLayerForwarder::CreatedRefLayer(ShadowableLayer* aRef) {
290 CreatedLayer<OpCreateRefLayer>(mTxn, aRef);
291 }
292
Mutated(ShadowableLayer * aMutant)293 void ShadowLayerForwarder::Mutated(ShadowableLayer* aMutant) {
294 mTxn->AddMutant(aMutant);
295 }
296
MutatedSimple(ShadowableLayer * aMutant)297 void ShadowLayerForwarder::MutatedSimple(ShadowableLayer* aMutant) {
298 mTxn->AddSimpleMutant(aMutant);
299 }
300
SetRoot(ShadowableLayer * aRoot)301 void ShadowLayerForwarder::SetRoot(ShadowableLayer* aRoot) {
302 mTxn->AddEdit(OpSetRoot(Shadow(aRoot)));
303 }
InsertAfter(ShadowableLayer * aContainer,ShadowableLayer * aChild,ShadowableLayer * aAfter)304 void ShadowLayerForwarder::InsertAfter(ShadowableLayer* aContainer,
305 ShadowableLayer* aChild,
306 ShadowableLayer* aAfter) {
307 if (!aChild->HasShadow()) {
308 return;
309 }
310
311 while (aAfter && !aAfter->HasShadow()) {
312 aAfter = aAfter->AsLayer()->GetPrevSibling()
313 ? aAfter->AsLayer()->GetPrevSibling()->AsShadowableLayer()
314 : nullptr;
315 }
316
317 if (aAfter) {
318 mTxn->AddEdit(
319 OpInsertAfter(Shadow(aContainer), Shadow(aChild), Shadow(aAfter)));
320 } else {
321 mTxn->AddEdit(OpPrependChild(Shadow(aContainer), Shadow(aChild)));
322 }
323 }
RemoveChild(ShadowableLayer * aContainer,ShadowableLayer * aChild)324 void ShadowLayerForwarder::RemoveChild(ShadowableLayer* aContainer,
325 ShadowableLayer* aChild) {
326 MOZ_LAYERS_LOG(("[LayersForwarder] OpRemoveChild container=%p child=%p\n",
327 aContainer->AsLayer(), aChild->AsLayer()));
328
329 if (!aChild->HasShadow()) {
330 return;
331 }
332
333 mTxn->AddEdit(OpRemoveChild(Shadow(aContainer), Shadow(aChild)));
334 }
RepositionChild(ShadowableLayer * aContainer,ShadowableLayer * aChild,ShadowableLayer * aAfter)335 void ShadowLayerForwarder::RepositionChild(ShadowableLayer* aContainer,
336 ShadowableLayer* aChild,
337 ShadowableLayer* aAfter) {
338 if (!aChild->HasShadow()) {
339 return;
340 }
341
342 while (aAfter && !aAfter->HasShadow()) {
343 aAfter = aAfter->AsLayer()->GetPrevSibling()
344 ? aAfter->AsLayer()->GetPrevSibling()->AsShadowableLayer()
345 : nullptr;
346 }
347
348 if (aAfter) {
349 MOZ_LAYERS_LOG(
350 ("[LayersForwarder] OpRepositionChild container=%p child=%p after=%p",
351 aContainer->AsLayer(), aChild->AsLayer(), aAfter->AsLayer()));
352 mTxn->AddEdit(
353 OpRepositionChild(Shadow(aContainer), Shadow(aChild), Shadow(aAfter)));
354 } else {
355 MOZ_LAYERS_LOG(("[LayersForwarder] OpRaiseToTopChild container=%p child=%p",
356 aContainer->AsLayer(), aChild->AsLayer()));
357 mTxn->AddEdit(OpRaiseToTopChild(Shadow(aContainer), Shadow(aChild)));
358 }
359 }
360
361 #ifdef DEBUG
CheckSurfaceDescriptor(const SurfaceDescriptor * aDescriptor) const362 void ShadowLayerForwarder::CheckSurfaceDescriptor(
363 const SurfaceDescriptor* aDescriptor) const {
364 if (!aDescriptor) {
365 return;
366 }
367
368 if (aDescriptor->type() == SurfaceDescriptor::TSurfaceDescriptorBuffer &&
369 aDescriptor->get_SurfaceDescriptorBuffer().data().type() ==
370 MemoryOrShmem::TShmem) {
371 const Shmem& shmem =
372 aDescriptor->get_SurfaceDescriptorBuffer().data().get_Shmem();
373 shmem.AssertInvariants();
374 MOZ_ASSERT(mShadowManager &&
375 mShadowManager->IsTrackingSharedMemory(shmem.mSegment));
376 }
377 }
378 #endif
379
UseTiledLayerBuffer(CompositableClient * aCompositable,const SurfaceDescriptorTiles & aTileLayerDescriptor)380 void ShadowLayerForwarder::UseTiledLayerBuffer(
381 CompositableClient* aCompositable,
382 const SurfaceDescriptorTiles& aTileLayerDescriptor) {
383 MOZ_ASSERT(aCompositable);
384
385 if (!aCompositable->IsConnected()) {
386 return;
387 }
388
389 mTxn->AddNoSwapPaint(
390 CompositableOperation(aCompositable->GetIPCHandle(),
391 OpUseTiledLayerBuffer(aTileLayerDescriptor)));
392 }
393
UpdateTextureRegion(CompositableClient * aCompositable,const ThebesBufferData & aThebesBufferData,const nsIntRegion & aUpdatedRegion)394 void ShadowLayerForwarder::UpdateTextureRegion(
395 CompositableClient* aCompositable,
396 const ThebesBufferData& aThebesBufferData,
397 const nsIntRegion& aUpdatedRegion) {
398 MOZ_ASSERT(aCompositable);
399
400 if (!aCompositable->IsConnected()) {
401 return;
402 }
403
404 mTxn->AddNoSwapPaint(CompositableOperation(
405 aCompositable->GetIPCHandle(),
406 OpPaintTextureRegion(aThebesBufferData, aUpdatedRegion)));
407 }
408
UseTextures(CompositableClient * aCompositable,const nsTArray<TimedTextureClient> & aTextures)409 void ShadowLayerForwarder::UseTextures(
410 CompositableClient* aCompositable,
411 const nsTArray<TimedTextureClient>& aTextures) {
412 MOZ_ASSERT(aCompositable);
413
414 if (!aCompositable->IsConnected()) {
415 return;
416 }
417
418 AutoTArray<TimedTexture, 4> textures;
419
420 for (auto& t : aTextures) {
421 MOZ_ASSERT(t.mTextureClient);
422 MOZ_ASSERT(t.mTextureClient->GetIPDLActor());
423 MOZ_RELEASE_ASSERT(t.mTextureClient->GetIPDLActor()->GetIPCChannel() ==
424 mShadowManager->GetIPCChannel());
425 bool readLocked = t.mTextureClient->OnForwardedToHost();
426 textures.AppendElement(
427 TimedTexture(nullptr, t.mTextureClient->GetIPDLActor(), t.mTimeStamp,
428 t.mPictureRect, t.mFrameID, t.mProducerID, readLocked));
429 mClientLayerManager->GetCompositorBridgeChild()
430 ->HoldUntilCompositableRefReleasedIfNecessary(t.mTextureClient);
431
432 auto fenceFd = t.mTextureClient->GetInternalData()->GetAcquireFence();
433 if (fenceFd.IsValid()) {
434 mTxn->AddEdit(CompositableOperation(
435 aCompositable->GetIPCHandle(),
436 OpDeliverAcquireFence(nullptr, t.mTextureClient->GetIPDLActor(),
437 fenceFd)));
438 }
439 }
440 mTxn->AddEdit(CompositableOperation(aCompositable->GetIPCHandle(),
441 OpUseTexture(textures)));
442 }
443
UseComponentAlphaTextures(CompositableClient * aCompositable,TextureClient * aTextureOnBlack,TextureClient * aTextureOnWhite)444 void ShadowLayerForwarder::UseComponentAlphaTextures(
445 CompositableClient* aCompositable, TextureClient* aTextureOnBlack,
446 TextureClient* aTextureOnWhite) {
447 MOZ_ASSERT(aCompositable);
448
449 if (!aCompositable->IsConnected()) {
450 return;
451 }
452
453 MOZ_ASSERT(aTextureOnWhite);
454 MOZ_ASSERT(aTextureOnBlack);
455 MOZ_ASSERT(aCompositable->GetIPCHandle());
456 MOZ_ASSERT(aTextureOnBlack->GetIPDLActor());
457 MOZ_ASSERT(aTextureOnWhite->GetIPDLActor());
458 MOZ_ASSERT(aTextureOnBlack->GetSize() == aTextureOnWhite->GetSize());
459 MOZ_RELEASE_ASSERT(aTextureOnWhite->GetIPDLActor()->GetIPCChannel() ==
460 mShadowManager->GetIPCChannel());
461 MOZ_RELEASE_ASSERT(aTextureOnBlack->GetIPDLActor()->GetIPCChannel() ==
462 mShadowManager->GetIPCChannel());
463
464 bool readLockedB = aTextureOnBlack->OnForwardedToHost();
465 bool readLockedW = aTextureOnWhite->OnForwardedToHost();
466
467 mClientLayerManager->GetCompositorBridgeChild()
468 ->HoldUntilCompositableRefReleasedIfNecessary(aTextureOnBlack);
469 mClientLayerManager->GetCompositorBridgeChild()
470 ->HoldUntilCompositableRefReleasedIfNecessary(aTextureOnWhite);
471
472 auto fenceFdB = aTextureOnBlack->GetInternalData()->GetAcquireFence();
473 if (fenceFdB.IsValid()) {
474 mTxn->AddEdit(CompositableOperation(
475 aCompositable->GetIPCHandle(),
476 OpDeliverAcquireFence(nullptr, aTextureOnBlack->GetIPDLActor(),
477 fenceFdB)));
478 }
479
480 auto fenceFdW = aTextureOnWhite->GetInternalData()->GetAcquireFence();
481 if (fenceFdW.IsValid()) {
482 mTxn->AddEdit(CompositableOperation(
483 aCompositable->GetIPCHandle(),
484 OpDeliverAcquireFence(nullptr, aTextureOnWhite->GetIPDLActor(),
485 fenceFdW)));
486 }
487
488 mTxn->AddEdit(CompositableOperation(
489 aCompositable->GetIPCHandle(),
490 OpUseComponentAlphaTextures(nullptr, aTextureOnBlack->GetIPDLActor(),
491 nullptr, aTextureOnWhite->GetIPDLActor(),
492 readLockedB, readLockedW)));
493 }
494
AddOpDestroy(Transaction * aTxn,const OpDestroy & op)495 static bool AddOpDestroy(Transaction* aTxn, const OpDestroy& op) {
496 if (!aTxn->Opened()) {
497 return false;
498 }
499
500 aTxn->mDestroyedActors.AppendElement(op);
501 return true;
502 }
503
DestroyInTransaction(PTextureChild * aTexture)504 bool ShadowLayerForwarder::DestroyInTransaction(PTextureChild* aTexture) {
505 return AddOpDestroy(mTxn, OpDestroy(aTexture));
506 }
507
DestroyInTransaction(const CompositableHandle & aHandle)508 bool ShadowLayerForwarder::DestroyInTransaction(
509 const CompositableHandle& aHandle) {
510 return AddOpDestroy(mTxn, OpDestroy(aHandle));
511 }
512
RemoveTextureFromCompositable(CompositableClient * aCompositable,TextureClient * aTexture)513 void ShadowLayerForwarder::RemoveTextureFromCompositable(
514 CompositableClient* aCompositable, TextureClient* aTexture) {
515 MOZ_ASSERT(aCompositable);
516 MOZ_ASSERT(aTexture);
517 MOZ_ASSERT(aTexture->GetIPDLActor());
518 MOZ_RELEASE_ASSERT(aTexture->GetIPDLActor()->GetIPCChannel() ==
519 mShadowManager->GetIPCChannel());
520 if (!aCompositable->IsConnected() || !aTexture->GetIPDLActor()) {
521 // We don't have an actor anymore, don't try to use it!
522 return;
523 }
524
525 mTxn->AddEdit(CompositableOperation(
526 aCompositable->GetIPCHandle(),
527 OpRemoveTexture(nullptr, aTexture->GetIPDLActor())));
528 }
529
InWorkerThread()530 bool ShadowLayerForwarder::InWorkerThread() {
531 return GetTextureForwarder()->GetThread()->IsOnCurrentThread();
532 }
533
SendPaintTime(TransactionId aId,TimeDuration aPaintTime)534 void ShadowLayerForwarder::SendPaintTime(TransactionId aId,
535 TimeDuration aPaintTime) {
536 if (!IPCOpen() || !mShadowManager->SendPaintTime(aId, aPaintTime)) {
537 NS_WARNING("Could not send paint times over IPC");
538 }
539 }
540
EndTransaction(const nsIntRegion & aRegionToClear,TransactionId aId,bool aScheduleComposite,uint32_t aPaintSequenceNumber,bool aIsRepeatTransaction,const mozilla::VsyncId & aVsyncId,const mozilla::TimeStamp & aVsyncStart,const mozilla::TimeStamp & aRefreshStart,const mozilla::TimeStamp & aTransactionStart,bool aContainsSVG,const nsCString & aURL,bool * aSent,const nsTArray<CompositionPayload> & aPayload)541 bool ShadowLayerForwarder::EndTransaction(
542 const nsIntRegion& aRegionToClear, TransactionId aId,
543 bool aScheduleComposite, uint32_t aPaintSequenceNumber,
544 bool aIsRepeatTransaction, const mozilla::VsyncId& aVsyncId,
545 const mozilla::TimeStamp& aVsyncStart,
546 const mozilla::TimeStamp& aRefreshStart,
547 const mozilla::TimeStamp& aTransactionStart, bool aContainsSVG,
548 const nsCString& aURL, bool* aSent,
549 const nsTArray<CompositionPayload>& aPayload) {
550 *aSent = false;
551
552 TransactionInfo info;
553
554 MOZ_ASSERT(IPCOpen(), "no manager to forward to");
555 if (!IPCOpen()) {
556 return false;
557 }
558
559 Maybe<TimeStamp> startTime;
560 if (StaticPrefs::layers_acceleration_draw_fps()) {
561 startTime = Some(TimeStamp::Now());
562 }
563
564 GetCompositorBridgeChild()->WillEndTransaction();
565
566 MOZ_ASSERT(aId.IsValid());
567
568 AUTO_PROFILER_LABEL("ShadowLayerForwarder::EndTransaction", GRAPHICS);
569
570 RenderTraceScope rendertrace("Foward Transaction", "000091");
571 MOZ_ASSERT(!mTxn->Finished(), "forgot BeginTransaction?");
572
573 DiagnosticTypes diagnostics =
574 gfxPlatform::GetPlatform()->GetLayerDiagnosticTypes();
575 if (mDiagnosticTypes != diagnostics) {
576 mDiagnosticTypes = diagnostics;
577 mTxn->AddEdit(OpSetDiagnosticTypes(diagnostics));
578 }
579
580 AutoTxnEnd _(mTxn);
581
582 if (mTxn->Empty() && !mTxn->RotationChanged()) {
583 MOZ_LAYERS_LOG(
584 ("[LayersForwarder] 0-length cset (?) and no rotation event, skipping "
585 "Update()"));
586 return true;
587 }
588
589 MOZ_LAYERS_LOG(("[LayersForwarder] destroying buffers..."));
590
591 MOZ_LAYERS_LOG(("[LayersForwarder] building transaction..."));
592
593 nsTArray<OpSetSimpleLayerAttributes> setSimpleAttrs;
594 for (ShadowableLayer* shadow : mTxn->mSimpleMutants) {
595 if (!shadow->HasShadow()) {
596 continue;
597 }
598
599 Layer* mutant = shadow->AsLayer();
600 setSimpleAttrs.AppendElement(OpSetSimpleLayerAttributes(
601 Shadow(shadow), mutant->GetSimpleAttributes()));
602 }
603
604 nsTArray<OpSetLayerAttributes> setAttrs;
605
606 // We purposely add attribute-change ops to the final changeset
607 // before we add paint ops. This allows layers to record the
608 // attribute changes before new pixels arrive, which can be useful
609 // for setting up back/front buffers.
610 RenderTraceScope rendertrace2("Foward Transaction", "000092");
611 for (ShadowableLayer* shadow : mTxn->mMutants) {
612 if (!shadow->HasShadow()) {
613 continue;
614 }
615 Layer* mutant = shadow->AsLayer();
616 MOZ_ASSERT(!!mutant, "unshadowable layer?");
617
618 OpSetLayerAttributes op;
619 op.layer() = Shadow(shadow);
620
621 LayerAttributes& attrs = op.attrs();
622 CommonLayerAttributes& common = attrs.common();
623 common.visibleRegion() = mutant->GetVisibleRegion();
624 common.eventRegions() = mutant->GetEventRegions();
625 common.useClipRect() = !!mutant->GetClipRect();
626 common.clipRect() =
627 (common.useClipRect() ? *mutant->GetClipRect() : ParentLayerIntRect());
628 if (Layer* maskLayer = mutant->GetMaskLayer()) {
629 common.maskLayer() = Shadow(maskLayer->AsShadowableLayer());
630 } else {
631 common.maskLayer() = LayerHandle();
632 }
633 common.compositorAnimations().id() = mutant->GetCompositorAnimationsId();
634 common.compositorAnimations().animations() =
635 mutant->GetAnimations().Clone();
636 common.invalidRegion() = mutant->GetInvalidRegion().GetRegion();
637 common.scrollMetadata() = mutant->GetAllScrollMetadata().Clone();
638 for (size_t i = 0; i < mutant->GetAncestorMaskLayerCount(); i++) {
639 auto layer =
640 Shadow(mutant->GetAncestorMaskLayerAt(i)->AsShadowableLayer());
641 common.ancestorMaskLayers().AppendElement(layer);
642 }
643 nsCString log;
644 mutant->GetDisplayListLog(log);
645 common.displayListLog() = log;
646
647 attrs.specific() = null_t();
648 mutant->FillSpecificAttributes(attrs.specific());
649
650 MOZ_LAYERS_LOG(("[LayersForwarder] OpSetLayerAttributes(%p)\n", mutant));
651
652 setAttrs.AppendElement(op);
653 }
654
655 if (mTxn->mCset.IsEmpty() && mTxn->mPaints.IsEmpty() && setAttrs.IsEmpty() &&
656 !mTxn->RotationChanged()) {
657 return true;
658 }
659
660 info.cset() = std::move(mTxn->mCset);
661 info.setSimpleAttrs() = std::move(setSimpleAttrs);
662 info.setAttrs() = std::move(setAttrs);
663 info.paints() = std::move(mTxn->mPaints);
664 info.toDestroy() = mTxn->mDestroyedActors.Clone();
665 info.fwdTransactionId() = GetFwdTransactionId();
666 info.id() = aId;
667 info.isFirstPaint() = mIsFirstPaint;
668 info.focusTarget() = mFocusTarget;
669 info.scheduleComposite() = aScheduleComposite;
670 info.paintSequenceNumber() = aPaintSequenceNumber;
671 info.isRepeatTransaction() = aIsRepeatTransaction;
672 info.vsyncId() = aVsyncId;
673 info.vsyncStart() = aVsyncStart;
674 info.refreshStart() = aRefreshStart;
675 info.transactionStart() = aTransactionStart;
676 info.url() = aURL;
677 info.containsSVG() = aContainsSVG;
678 #if defined(ENABLE_FRAME_LATENCY_LOG)
679 info.fwdTime() = TimeStamp::Now();
680 #endif
681 info.payload() = aPayload.Clone();
682
683 TargetConfig targetConfig(mTxn->mTargetBounds, mTxn->mTargetRotation,
684 mTxn->mTargetOrientation, aRegionToClear);
685 info.targetConfig() = targetConfig;
686
687 if (!GetTextureForwarder()->IsSameProcess()) {
688 MOZ_LAYERS_LOG(("[LayersForwarder] syncing before send..."));
689 PlatformSyncBeforeUpdate();
690 }
691
692 if (startTime) {
693 mPaintTiming.serializeMs() =
694 (TimeStamp::Now() - startTime.value()).ToMilliseconds();
695 startTime = Some(TimeStamp::Now());
696 }
697
698 // We delay at the last possible minute, to give the paint thread a chance to
699 // finish. If it does we don't have to delay messages at all.
700 GetCompositorBridgeChild()->PostponeMessagesIfAsyncPainting();
701
702 MOZ_LAYERS_LOG(("[LayersForwarder] sending transaction..."));
703 RenderTraceScope rendertrace3("Forward Transaction", "000093");
704 if (!mShadowManager->SendUpdate(info)) {
705 MOZ_LAYERS_LOG(("[LayersForwarder] WARNING: sending transaction failed!"));
706 return false;
707 }
708
709 if (startTime) {
710 mPaintTiming.sendMs() =
711 (TimeStamp::Now() - startTime.value()).ToMilliseconds();
712 mShadowManager->SendRecordPaintTimes(mPaintTiming);
713 }
714
715 *aSent = true;
716 mIsFirstPaint = false;
717 mFocusTarget = FocusTarget();
718 MOZ_LAYERS_LOG(("[LayersForwarder] ... done"));
719 return true;
720 }
721
FindCompositable(const CompositableHandle & aHandle)722 RefPtr<CompositableClient> ShadowLayerForwarder::FindCompositable(
723 const CompositableHandle& aHandle) {
724 CompositableClient* client = nullptr;
725 if (!mCompositables.Get(aHandle.Value(), &client)) {
726 return nullptr;
727 }
728 return client;
729 }
730
SetLayersObserverEpoch(LayersObserverEpoch aEpoch)731 void ShadowLayerForwarder::SetLayersObserverEpoch(LayersObserverEpoch aEpoch) {
732 if (!IPCOpen()) {
733 return;
734 }
735 Unused << mShadowManager->SendSetLayersObserverEpoch(aEpoch);
736 }
737
UpdateTextureLocks()738 void ShadowLayerForwarder::UpdateTextureLocks() {
739 #ifdef XP_DARWIN
740 if (!IPCOpen()) {
741 return;
742 }
743
744 auto compositorBridge = GetCompositorBridgeChild();
745 if (compositorBridge) {
746 auto pid = compositorBridge->OtherPid();
747 TextureSync::UpdateTextureLocks(pid);
748 }
749 #endif
750 }
751
SyncTextures(const nsTArray<uint64_t> & aSerials)752 void ShadowLayerForwarder::SyncTextures(const nsTArray<uint64_t>& aSerials) {
753 #ifdef XP_DARWIN
754 if (!IPCOpen()) {
755 return;
756 }
757
758 auto compositorBridge = GetCompositorBridgeChild();
759 if (compositorBridge) {
760 auto pid = compositorBridge->OtherPid();
761 TextureSync::WaitForTextures(pid, aSerials);
762 }
763 #endif
764 }
765
ReleaseLayer(const LayerHandle & aHandle)766 void ShadowLayerForwarder::ReleaseLayer(const LayerHandle& aHandle) {
767 if (!IPCOpen()) {
768 return;
769 }
770 Unused << mShadowManager->SendReleaseLayer(aHandle);
771 }
772
IPCOpen() const773 bool ShadowLayerForwarder::IPCOpen() const {
774 return HasShadowManager() && mShadowManager->IPCOpen();
775 }
776
777 /**
778 * We bail out when we have no shadow manager. That can happen when the
779 * layer manager is created by the preallocated process.
780 * See bug 914843 for details.
781 */
ConstructShadowFor(ShadowableLayer * aLayer)782 LayerHandle ShadowLayerForwarder::ConstructShadowFor(ShadowableLayer* aLayer) {
783 return LayerHandle(mNextLayerHandle++);
784 }
785
786 #if !defined(MOZ_HAVE_PLATFORM_SPECIFIC_LAYER_BUFFERS)
787
788 /*static*/
PlatformSyncBeforeUpdate()789 void ShadowLayerForwarder::PlatformSyncBeforeUpdate() {}
790
791 #endif // !defined(MOZ_HAVE_PLATFORM_SPECIFIC_LAYER_BUFFERS)
792
Connect(CompositableClient * aCompositable,ImageContainer * aImageContainer)793 void ShadowLayerForwarder::Connect(CompositableClient* aCompositable,
794 ImageContainer* aImageContainer) {
795 #ifdef GFX_COMPOSITOR_LOGGING
796 printf("ShadowLayerForwarder::Connect(Compositable)\n");
797 #endif
798 MOZ_ASSERT(aCompositable);
799 MOZ_ASSERT(mShadowManager);
800 if (!IPCOpen()) {
801 return;
802 }
803
804 static uint64_t sNextID = 1;
805 uint64_t id = sNextID++;
806
807 mCompositables.InsertOrUpdate(id, aCompositable);
808
809 CompositableHandle handle(id);
810 aCompositable->InitIPDL(handle);
811 mShadowManager->SendNewCompositable(handle, aCompositable->GetTextureInfo());
812 }
813
Attach(CompositableClient * aCompositable,ShadowableLayer * aLayer)814 void ShadowLayerForwarder::Attach(CompositableClient* aCompositable,
815 ShadowableLayer* aLayer) {
816 MOZ_ASSERT(aLayer);
817 MOZ_ASSERT(aCompositable);
818 mTxn->AddEdit(
819 OpAttachCompositable(Shadow(aLayer), aCompositable->GetIPCHandle()));
820 }
821
AttachAsyncCompositable(const CompositableHandle & aHandle,ShadowableLayer * aLayer)822 void ShadowLayerForwarder::AttachAsyncCompositable(
823 const CompositableHandle& aHandle, ShadowableLayer* aLayer) {
824 MOZ_ASSERT(aLayer);
825 MOZ_ASSERT(aHandle);
826 mTxn->AddEdit(OpAttachAsyncCompositable(Shadow(aLayer), aHandle));
827 }
828
SetShadowManager(PLayerTransactionChild * aShadowManager)829 void ShadowLayerForwarder::SetShadowManager(
830 PLayerTransactionChild* aShadowManager) {
831 mShadowManager = static_cast<LayerTransactionChild*>(aShadowManager);
832 mShadowManager->SetForwarder(this);
833 }
834
StopReceiveAsyncParentMessge()835 void ShadowLayerForwarder::StopReceiveAsyncParentMessge() {
836 if (!IPCOpen()) {
837 return;
838 }
839 mShadowManager->SetForwarder(nullptr);
840 }
841
ClearCachedResources()842 void ShadowLayerForwarder::ClearCachedResources() {
843 if (!IPCOpen()) {
844 return;
845 }
846 mShadowManager->SendClearCachedResources();
847 }
848
ScheduleComposite()849 void ShadowLayerForwarder::ScheduleComposite() {
850 if (!IPCOpen()) {
851 return;
852 }
853 mShadowManager->SendScheduleComposite();
854 }
855
IsSurfaceDescriptorValid(const SurfaceDescriptor & aSurface)856 bool IsSurfaceDescriptorValid(const SurfaceDescriptor& aSurface) {
857 return aSurface.type() != SurfaceDescriptor::T__None &&
858 aSurface.type() != SurfaceDescriptor::Tnull_t;
859 }
860
GetAddressFromDescriptor(const SurfaceDescriptor & aDescriptor)861 uint8_t* GetAddressFromDescriptor(const SurfaceDescriptor& aDescriptor) {
862 MOZ_ASSERT(IsSurfaceDescriptorValid(aDescriptor));
863 MOZ_RELEASE_ASSERT(
864 aDescriptor.type() == SurfaceDescriptor::TSurfaceDescriptorBuffer,
865 "GFX: surface descriptor is not the right type.");
866
867 auto memOrShmem = aDescriptor.get_SurfaceDescriptorBuffer().data();
868 if (memOrShmem.type() == MemoryOrShmem::TShmem) {
869 return memOrShmem.get_Shmem().get<uint8_t>();
870 } else {
871 return reinterpret_cast<uint8_t*>(memOrShmem.get_uintptr_t());
872 }
873 }
874
GetSurfaceForDescriptor(const SurfaceDescriptor & aDescriptor)875 already_AddRefed<gfx::DataSourceSurface> GetSurfaceForDescriptor(
876 const SurfaceDescriptor& aDescriptor) {
877 if (aDescriptor.type() != SurfaceDescriptor::TSurfaceDescriptorBuffer) {
878 return nullptr;
879 }
880 uint8_t* data = GetAddressFromDescriptor(aDescriptor);
881 auto rgb =
882 aDescriptor.get_SurfaceDescriptorBuffer().desc().get_RGBDescriptor();
883 uint32_t stride = ImageDataSerializer::GetRGBStride(rgb);
884 return gfx::Factory::CreateWrappingDataSourceSurface(data, stride, rgb.size(),
885 rgb.format());
886 }
887
GetDrawTargetForDescriptor(const SurfaceDescriptor & aDescriptor)888 already_AddRefed<gfx::DrawTarget> GetDrawTargetForDescriptor(
889 const SurfaceDescriptor& aDescriptor) {
890 uint8_t* data = GetAddressFromDescriptor(aDescriptor);
891 auto rgb =
892 aDescriptor.get_SurfaceDescriptorBuffer().desc().get_RGBDescriptor();
893 uint32_t stride = ImageDataSerializer::GetRGBStride(rgb);
894 return gfx::Factory::CreateDrawTargetForData(
895 gfx::BackendType::SKIA, data, rgb.size(), stride, rgb.format());
896 }
897
DestroySurfaceDescriptor(IShmemAllocator * aAllocator,SurfaceDescriptor * aSurface)898 void DestroySurfaceDescriptor(IShmemAllocator* aAllocator,
899 SurfaceDescriptor* aSurface) {
900 MOZ_ASSERT(aSurface);
901
902 SurfaceDescriptorBuffer& desc = aSurface->get_SurfaceDescriptorBuffer();
903 switch (desc.data().type()) {
904 case MemoryOrShmem::TShmem: {
905 aAllocator->DeallocShmem(desc.data().get_Shmem());
906 break;
907 }
908 case MemoryOrShmem::Tuintptr_t: {
909 uint8_t* ptr = (uint8_t*)desc.data().get_uintptr_t();
910 GfxMemoryImageReporter::WillFree(ptr);
911 delete[] ptr;
912 break;
913 }
914 default:
915 MOZ_CRASH("surface type not implemented!");
916 }
917 *aSurface = SurfaceDescriptor();
918 }
919
AllocSurfaceDescriptor(const gfx::IntSize & aSize,gfxContentType aContent,SurfaceDescriptor * aBuffer)920 bool ShadowLayerForwarder::AllocSurfaceDescriptor(const gfx::IntSize& aSize,
921 gfxContentType aContent,
922 SurfaceDescriptor* aBuffer) {
923 if (!IPCOpen()) {
924 return false;
925 }
926 return AllocSurfaceDescriptorWithCaps(aSize, aContent, DEFAULT_BUFFER_CAPS,
927 aBuffer);
928 }
929
AllocSurfaceDescriptorWithCaps(const gfx::IntSize & aSize,gfxContentType aContent,uint32_t aCaps,SurfaceDescriptor * aBuffer)930 bool ShadowLayerForwarder::AllocSurfaceDescriptorWithCaps(
931 const gfx::IntSize& aSize, gfxContentType aContent, uint32_t aCaps,
932 SurfaceDescriptor* aBuffer) {
933 if (!IPCOpen()) {
934 return false;
935 }
936 gfx::SurfaceFormat format =
937 gfxPlatform::GetPlatform()->Optimal2DFormatForContent(aContent);
938 size_t size = ImageDataSerializer::ComputeRGBBufferSize(aSize, format);
939 if (!size) {
940 return false;
941 }
942
943 MemoryOrShmem bufferDesc;
944 if (GetTextureForwarder()->IsSameProcess()) {
945 uint8_t* data = new (std::nothrow) uint8_t[size];
946 if (!data) {
947 return false;
948 }
949 GfxMemoryImageReporter::DidAlloc(data);
950 memset(data, 0, size);
951 bufferDesc = reinterpret_cast<uintptr_t>(data);
952 } else {
953 mozilla::ipc::Shmem shmem;
954 if (!GetTextureForwarder()->AllocUnsafeShmem(size, OptimalShmemType(),
955 &shmem)) {
956 return false;
957 }
958
959 bufferDesc = std::move(shmem);
960 }
961
962 // Use an intermediate buffer by default. Skipping the intermediate buffer is
963 // only possible in certain configurations so let's keep it simple here for
964 // now.
965 const bool hasIntermediateBuffer = true;
966 *aBuffer = SurfaceDescriptorBuffer(
967 RGBDescriptor(aSize, format, hasIntermediateBuffer), bufferDesc);
968
969 return true;
970 }
971
972 /* static */
IsShmem(SurfaceDescriptor * aSurface)973 bool ShadowLayerForwarder::IsShmem(SurfaceDescriptor* aSurface) {
974 return aSurface &&
975 (aSurface->type() == SurfaceDescriptor::TSurfaceDescriptorBuffer) &&
976 (aSurface->get_SurfaceDescriptorBuffer().data().type() ==
977 MemoryOrShmem::TShmem);
978 }
979
DestroySurfaceDescriptor(SurfaceDescriptor * aSurface)980 void ShadowLayerForwarder::DestroySurfaceDescriptor(
981 SurfaceDescriptor* aSurface) {
982 MOZ_ASSERT(aSurface);
983 MOZ_ASSERT(IPCOpen());
984 if (!IPCOpen() || !aSurface) {
985 return;
986 }
987
988 ::mozilla::layers::DestroySurfaceDescriptor(GetTextureForwarder(), aSurface);
989 }
990
UpdateFwdTransactionId()991 void ShadowLayerForwarder::UpdateFwdTransactionId() {
992 auto compositorBridge = GetCompositorBridgeChild();
993 if (compositorBridge) {
994 compositorBridge->UpdateFwdTransactionId();
995 }
996 }
997
GetFwdTransactionId()998 uint64_t ShadowLayerForwarder::GetFwdTransactionId() {
999 auto compositorBridge = GetCompositorBridgeChild();
1000 MOZ_DIAGNOSTIC_ASSERT(compositorBridge);
1001 return compositorBridge ? compositorBridge->GetFwdTransactionId() : 0;
1002 }
1003
GetCompositorBridgeChild()1004 CompositorBridgeChild* ShadowLayerForwarder::GetCompositorBridgeChild() {
1005 if (mCompositorBridgeChild) {
1006 return mCompositorBridgeChild;
1007 }
1008 if (!mShadowManager) {
1009 return nullptr;
1010 }
1011 mCompositorBridgeChild =
1012 static_cast<CompositorBridgeChild*>(mShadowManager->Manager());
1013 return mCompositorBridgeChild;
1014 }
1015
SyncWithCompositor()1016 void ShadowLayerForwarder::SyncWithCompositor() {
1017 auto compositorBridge = GetCompositorBridgeChild();
1018 if (compositorBridge && compositorBridge->IPCOpen()) {
1019 compositorBridge->SendSyncWithCompositor();
1020 }
1021 }
1022
ReleaseCompositable(const CompositableHandle & aHandle)1023 void ShadowLayerForwarder::ReleaseCompositable(
1024 const CompositableHandle& aHandle) {
1025 AssertInForwarderThread();
1026 if (!DestroyInTransaction(aHandle)) {
1027 if (!IPCOpen()) {
1028 return;
1029 }
1030 mShadowManager->SendReleaseCompositable(aHandle);
1031 }
1032 mCompositables.Remove(aHandle.Value());
1033 }
1034
SynchronouslyShutdown()1035 void ShadowLayerForwarder::SynchronouslyShutdown() {
1036 if (IPCOpen()) {
1037 mShadowManager->SendShutdownSync();
1038 mShadowManager->MarkDestroyed();
1039 }
1040 }
1041
~ShadowableLayer()1042 ShadowableLayer::~ShadowableLayer() {
1043 if (mShadow) {
1044 mForwarder->ReleaseLayer(GetShadow());
1045 }
1046 }
1047
1048 } // namespace layers
1049 } // namespace mozilla
1050