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