Bug 1690340 - Part 2: Use the new naming for the developer tools menu items. r=jdescottes
[gecko.git] / gfx / layers / ipc / ShadowLayers.cpp
blobb76601ae5d7aea85263f33782953cc3ec1f1174f
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/. */
7 #include "ShadowLayers.h"
9 #include <set> // for _Rb_tree_const_iterator, etc
10 #include <vector> // for vector
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 "nsXULAppAPI.h" // for XRE_GetProcessType, etc
46 namespace mozilla {
47 namespace ipc {
48 class Shmem;
49 } // namespace ipc
51 namespace layers {
53 using namespace mozilla::gfx;
54 using namespace mozilla::gl;
55 using namespace mozilla::ipc;
57 class ClientTiledLayerBuffer;
59 typedef nsTArray<SurfaceDescriptor> BufferArray;
60 typedef nsTArray<Edit> EditVector;
61 typedef nsTHashtable<nsPtrHashKey<ShadowableLayer>> ShadowableLayerSet;
62 typedef nsTArray<OpDestroy> OpDestroyVector;
64 class Transaction {
65 public:
66 Transaction()
67 : mTargetRotation(ROTATION_0),
68 mTargetOrientation(hal::eScreenOrientation_None),
69 mOpen(false),
70 mRotationChanged(false) {}
72 void Begin(const gfx::IntRect& aTargetBounds, ScreenRotation aRotation,
73 hal::ScreenOrientation aOrientation) {
74 mOpen = true;
75 mTargetBounds = aTargetBounds;
76 if (aRotation != mTargetRotation) {
77 // the first time this is called, mRotationChanged will be false if
78 // aRotation is 0, but we should be OK because for the first transaction
79 // we should only compose if it is non-empty. See the caller(s) of
80 // RotationChanged.
81 mRotationChanged = true;
83 mTargetRotation = aRotation;
84 mTargetOrientation = aOrientation;
86 void AddEdit(const Edit& aEdit) {
87 MOZ_ASSERT(!Finished(), "forgot BeginTransaction?");
88 mCset.AppendElement(aEdit);
90 void AddEdit(const CompositableOperation& aEdit) { AddEdit(Edit(aEdit)); }
92 void AddNoSwapPaint(const CompositableOperation& aPaint) {
93 MOZ_ASSERT(!Finished(), "forgot BeginTransaction?");
94 mPaints.AppendElement(Edit(aPaint));
96 void AddMutant(ShadowableLayer* aLayer) {
97 MOZ_ASSERT(!Finished(), "forgot BeginTransaction?");
98 mMutants.PutEntry(aLayer);
100 void AddSimpleMutant(ShadowableLayer* aLayer) {
101 MOZ_ASSERT(!Finished(), "forgot BeginTransaction?");
102 mSimpleMutants.PutEntry(aLayer);
104 void End() {
105 mCset.Clear();
106 mPaints.Clear();
107 mMutants.Clear();
108 mSimpleMutants.Clear();
109 mDestroyedActors.Clear();
110 mOpen = false;
111 mRotationChanged = false;
114 bool Empty() const {
115 return mCset.IsEmpty() && mPaints.IsEmpty() && mMutants.IsEmpty() &&
116 mSimpleMutants.IsEmpty() && mDestroyedActors.IsEmpty();
118 bool RotationChanged() const { return mRotationChanged; }
119 bool Finished() const { return !mOpen && Empty(); }
121 bool Opened() const { return mOpen; }
123 EditVector mCset;
124 nsTArray<CompositableOperation> mPaints;
125 OpDestroyVector mDestroyedActors;
126 ShadowableLayerSet mMutants;
127 ShadowableLayerSet mSimpleMutants;
128 gfx::IntRect mTargetBounds;
129 ScreenRotation mTargetRotation;
130 hal::ScreenOrientation mTargetOrientation;
132 private:
133 bool mOpen;
134 bool mRotationChanged;
136 // disabled
137 Transaction(const Transaction&);
138 Transaction& operator=(const Transaction&);
140 struct AutoTxnEnd final {
141 explicit AutoTxnEnd(Transaction* aTxn) : mTxn(aTxn) {}
142 ~AutoTxnEnd() { mTxn->End(); }
143 Transaction* mTxn;
146 void KnowsCompositor::IdentifyTextureHost(
147 const TextureFactoryIdentifier& aIdentifier) {
148 auto lock = mData.Lock();
149 lock.ref().mTextureFactoryIdentifier = aIdentifier;
151 lock.ref().mSyncObject =
152 SyncObjectClient::CreateSyncObjectClientForContentDevice(
153 aIdentifier.mSyncHandle);
156 KnowsCompositor::KnowsCompositor()
157 : mData("KnowsCompositorMutex"), mSerial(++sSerialCounter) {}
159 KnowsCompositor::~KnowsCompositor() = default;
161 KnowsCompositorMediaProxy::KnowsCompositorMediaProxy(
162 const TextureFactoryIdentifier& aIdentifier) {
163 auto lock = mData.Lock();
164 lock.ref().mTextureFactoryIdentifier = aIdentifier;
165 // overwrite mSerial's value set by the parent class because we use the same
166 // serial as the KnowsCompositor we are proxying.
167 mThreadSafeAllocator = ImageBridgeChild::GetSingleton();
168 lock.ref().mSyncObject = mThreadSafeAllocator->GetSyncObject();
171 KnowsCompositorMediaProxy::~KnowsCompositorMediaProxy() = default;
173 TextureForwarder* KnowsCompositorMediaProxy::GetTextureForwarder() {
174 return mThreadSafeAllocator->GetTextureForwarder();
177 LayersIPCActor* KnowsCompositorMediaProxy::GetLayersIPCActor() {
178 return mThreadSafeAllocator->GetLayersIPCActor();
181 ActiveResourceTracker* KnowsCompositorMediaProxy::GetActiveResourceTracker() {
182 return mThreadSafeAllocator->GetActiveResourceTracker();
185 void KnowsCompositorMediaProxy::SyncWithCompositor() {
186 mThreadSafeAllocator->SyncWithCompositor();
189 RefPtr<KnowsCompositor> ShadowLayerForwarder::GetForMedia() {
190 return MakeAndAddRef<KnowsCompositorMediaProxy>(
191 GetTextureFactoryIdentifier());
194 ShadowLayerForwarder::ShadowLayerForwarder(
195 ClientLayerManager* aClientLayerManager)
196 : mClientLayerManager(aClientLayerManager),
197 mThread(NS_GetCurrentThread()),
198 mDiagnosticTypes(DiagnosticTypes::NO_DIAGNOSTIC),
199 mIsFirstPaint(false),
200 mNextLayerHandle(1) {
201 mTxn = new Transaction();
202 mEventTarget = GetMainThreadSerialEventTarget();
204 MOZ_ASSERT(mEventTarget || !XRE_IsContentProcess());
205 mActiveResourceTracker = MakeUnique<ActiveResourceTracker>(
206 1000, "CompositableForwarder", mEventTarget);
209 template <typename T>
210 struct ReleaseOnMainThreadTask : public Runnable {
211 UniquePtr<T> mObj;
213 explicit ReleaseOnMainThreadTask(UniquePtr<T>& aObj)
214 : Runnable("layers::ReleaseOnMainThreadTask"), mObj(std::move(aObj)) {}
216 NS_IMETHOD Run() override {
217 mObj = nullptr;
218 return NS_OK;
222 ShadowLayerForwarder::~ShadowLayerForwarder() {
223 MOZ_ASSERT(mTxn->Finished(), "unfinished transaction?");
224 delete mTxn;
225 if (mShadowManager) {
226 mShadowManager->SetForwarder(nullptr);
227 if (NS_IsMainThread()) {
228 mShadowManager->Destroy();
229 } else {
230 if (mEventTarget) {
231 mEventTarget->Dispatch(
232 NewRunnableMethod("LayerTransactionChild::Destroy", mShadowManager,
233 &LayerTransactionChild::Destroy),
234 nsIEventTarget::DISPATCH_NORMAL);
235 } else {
236 NS_DispatchToMainThread(
237 NewRunnableMethod("layers::LayerTransactionChild::Destroy",
238 mShadowManager, &LayerTransactionChild::Destroy));
243 if (!NS_IsMainThread()) {
244 RefPtr<ReleaseOnMainThreadTask<ActiveResourceTracker>> event =
245 new ReleaseOnMainThreadTask<ActiveResourceTracker>(
246 mActiveResourceTracker);
247 if (mEventTarget) {
248 mEventTarget->Dispatch(event.forget(), nsIEventTarget::DISPATCH_NORMAL);
249 } else {
250 NS_DispatchToMainThread(event);
255 void ShadowLayerForwarder::BeginTransaction(
256 const gfx::IntRect& aTargetBounds, ScreenRotation aRotation,
257 hal::ScreenOrientation aOrientation) {
258 MOZ_ASSERT(IPCOpen(), "no manager to forward to");
259 MOZ_ASSERT(mTxn->Finished(), "uncommitted txn?");
260 UpdateFwdTransactionId();
261 mTxn->Begin(aTargetBounds, aRotation, aOrientation);
264 static const LayerHandle& Shadow(ShadowableLayer* aLayer) {
265 return aLayer->GetShadow();
268 template <typename OpCreateT>
269 static void CreatedLayer(Transaction* aTxn, ShadowableLayer* aLayer) {
270 aTxn->AddEdit(OpCreateT(Shadow(aLayer)));
273 void ShadowLayerForwarder::CreatedPaintedLayer(ShadowableLayer* aThebes) {
274 CreatedLayer<OpCreatePaintedLayer>(mTxn, aThebes);
276 void ShadowLayerForwarder::CreatedContainerLayer(ShadowableLayer* aContainer) {
277 CreatedLayer<OpCreateContainerLayer>(mTxn, aContainer);
279 void ShadowLayerForwarder::CreatedImageLayer(ShadowableLayer* aImage) {
280 CreatedLayer<OpCreateImageLayer>(mTxn, aImage);
282 void ShadowLayerForwarder::CreatedColorLayer(ShadowableLayer* aColor) {
283 CreatedLayer<OpCreateColorLayer>(mTxn, aColor);
285 void ShadowLayerForwarder::CreatedCanvasLayer(ShadowableLayer* aCanvas) {
286 CreatedLayer<OpCreateCanvasLayer>(mTxn, aCanvas);
288 void ShadowLayerForwarder::CreatedRefLayer(ShadowableLayer* aRef) {
289 CreatedLayer<OpCreateRefLayer>(mTxn, aRef);
292 void ShadowLayerForwarder::Mutated(ShadowableLayer* aMutant) {
293 mTxn->AddMutant(aMutant);
296 void ShadowLayerForwarder::MutatedSimple(ShadowableLayer* aMutant) {
297 mTxn->AddSimpleMutant(aMutant);
300 void ShadowLayerForwarder::SetRoot(ShadowableLayer* aRoot) {
301 mTxn->AddEdit(OpSetRoot(Shadow(aRoot)));
303 void ShadowLayerForwarder::InsertAfter(ShadowableLayer* aContainer,
304 ShadowableLayer* aChild,
305 ShadowableLayer* aAfter) {
306 if (!aChild->HasShadow()) {
307 return;
310 while (aAfter && !aAfter->HasShadow()) {
311 aAfter = aAfter->AsLayer()->GetPrevSibling()
312 ? aAfter->AsLayer()->GetPrevSibling()->AsShadowableLayer()
313 : nullptr;
316 if (aAfter) {
317 mTxn->AddEdit(
318 OpInsertAfter(Shadow(aContainer), Shadow(aChild), Shadow(aAfter)));
319 } else {
320 mTxn->AddEdit(OpPrependChild(Shadow(aContainer), Shadow(aChild)));
323 void ShadowLayerForwarder::RemoveChild(ShadowableLayer* aContainer,
324 ShadowableLayer* aChild) {
325 MOZ_LAYERS_LOG(("[LayersForwarder] OpRemoveChild container=%p child=%p\n",
326 aContainer->AsLayer(), aChild->AsLayer()));
328 if (!aChild->HasShadow()) {
329 return;
332 mTxn->AddEdit(OpRemoveChild(Shadow(aContainer), Shadow(aChild)));
334 void ShadowLayerForwarder::RepositionChild(ShadowableLayer* aContainer,
335 ShadowableLayer* aChild,
336 ShadowableLayer* aAfter) {
337 if (!aChild->HasShadow()) {
338 return;
341 while (aAfter && !aAfter->HasShadow()) {
342 aAfter = aAfter->AsLayer()->GetPrevSibling()
343 ? aAfter->AsLayer()->GetPrevSibling()->AsShadowableLayer()
344 : nullptr;
347 if (aAfter) {
348 MOZ_LAYERS_LOG(
349 ("[LayersForwarder] OpRepositionChild container=%p child=%p after=%p",
350 aContainer->AsLayer(), aChild->AsLayer(), aAfter->AsLayer()));
351 mTxn->AddEdit(
352 OpRepositionChild(Shadow(aContainer), Shadow(aChild), Shadow(aAfter)));
353 } else {
354 MOZ_LAYERS_LOG(("[LayersForwarder] OpRaiseToTopChild container=%p child=%p",
355 aContainer->AsLayer(), aChild->AsLayer()));
356 mTxn->AddEdit(OpRaiseToTopChild(Shadow(aContainer), Shadow(aChild)));
360 #ifdef DEBUG
361 void ShadowLayerForwarder::CheckSurfaceDescriptor(
362 const SurfaceDescriptor* aDescriptor) const {
363 if (!aDescriptor) {
364 return;
367 if (aDescriptor->type() == SurfaceDescriptor::TSurfaceDescriptorBuffer &&
368 aDescriptor->get_SurfaceDescriptorBuffer().data().type() ==
369 MemoryOrShmem::TShmem) {
370 const Shmem& shmem =
371 aDescriptor->get_SurfaceDescriptorBuffer().data().get_Shmem();
372 shmem.AssertInvariants();
373 MOZ_ASSERT(mShadowManager &&
374 mShadowManager->IsTrackingSharedMemory(shmem.mSegment));
377 #endif
379 void ShadowLayerForwarder::UseTiledLayerBuffer(
380 CompositableClient* aCompositable,
381 const SurfaceDescriptorTiles& aTileLayerDescriptor) {
382 MOZ_ASSERT(aCompositable);
384 if (!aCompositable->IsConnected()) {
385 return;
388 mTxn->AddNoSwapPaint(
389 CompositableOperation(aCompositable->GetIPCHandle(),
390 OpUseTiledLayerBuffer(aTileLayerDescriptor)));
393 void ShadowLayerForwarder::UpdateTextureRegion(
394 CompositableClient* aCompositable,
395 const ThebesBufferData& aThebesBufferData,
396 const nsIntRegion& aUpdatedRegion) {
397 MOZ_ASSERT(aCompositable);
399 if (!aCompositable->IsConnected()) {
400 return;
403 mTxn->AddNoSwapPaint(CompositableOperation(
404 aCompositable->GetIPCHandle(),
405 OpPaintTextureRegion(aThebesBufferData, aUpdatedRegion)));
408 void ShadowLayerForwarder::UseTextures(
409 CompositableClient* aCompositable,
410 const nsTArray<TimedTextureClient>& aTextures) {
411 MOZ_ASSERT(aCompositable);
413 if (!aCompositable->IsConnected()) {
414 return;
417 AutoTArray<TimedTexture, 4> textures;
419 for (auto& t : aTextures) {
420 MOZ_ASSERT(t.mTextureClient);
421 MOZ_ASSERT(t.mTextureClient->GetIPDLActor());
422 MOZ_RELEASE_ASSERT(t.mTextureClient->GetIPDLActor()->GetIPCChannel() ==
423 mShadowManager->GetIPCChannel());
424 bool readLocked = t.mTextureClient->OnForwardedToHost();
425 textures.AppendElement(
426 TimedTexture(nullptr, t.mTextureClient->GetIPDLActor(), t.mTimeStamp,
427 t.mPictureRect, t.mFrameID, t.mProducerID, readLocked));
428 mClientLayerManager->GetCompositorBridgeChild()
429 ->HoldUntilCompositableRefReleasedIfNecessary(t.mTextureClient);
431 auto fenceFd = t.mTextureClient->GetInternalData()->GetAcquireFence();
432 if (fenceFd.IsValid()) {
433 mTxn->AddEdit(CompositableOperation(
434 aCompositable->GetIPCHandle(),
435 OpDeliverAcquireFence(nullptr, t.mTextureClient->GetIPDLActor(),
436 fenceFd)));
439 mTxn->AddEdit(CompositableOperation(aCompositable->GetIPCHandle(),
440 OpUseTexture(textures)));
443 void ShadowLayerForwarder::UseComponentAlphaTextures(
444 CompositableClient* aCompositable, TextureClient* aTextureOnBlack,
445 TextureClient* aTextureOnWhite) {
446 MOZ_ASSERT(aCompositable);
448 if (!aCompositable->IsConnected()) {
449 return;
452 MOZ_ASSERT(aTextureOnWhite);
453 MOZ_ASSERT(aTextureOnBlack);
454 MOZ_ASSERT(aCompositable->GetIPCHandle());
455 MOZ_ASSERT(aTextureOnBlack->GetIPDLActor());
456 MOZ_ASSERT(aTextureOnWhite->GetIPDLActor());
457 MOZ_ASSERT(aTextureOnBlack->GetSize() == aTextureOnWhite->GetSize());
458 MOZ_RELEASE_ASSERT(aTextureOnWhite->GetIPDLActor()->GetIPCChannel() ==
459 mShadowManager->GetIPCChannel());
460 MOZ_RELEASE_ASSERT(aTextureOnBlack->GetIPDLActor()->GetIPCChannel() ==
461 mShadowManager->GetIPCChannel());
463 bool readLockedB = aTextureOnBlack->OnForwardedToHost();
464 bool readLockedW = aTextureOnWhite->OnForwardedToHost();
466 mClientLayerManager->GetCompositorBridgeChild()
467 ->HoldUntilCompositableRefReleasedIfNecessary(aTextureOnBlack);
468 mClientLayerManager->GetCompositorBridgeChild()
469 ->HoldUntilCompositableRefReleasedIfNecessary(aTextureOnWhite);
471 auto fenceFdB = aTextureOnBlack->GetInternalData()->GetAcquireFence();
472 if (fenceFdB.IsValid()) {
473 mTxn->AddEdit(CompositableOperation(
474 aCompositable->GetIPCHandle(),
475 OpDeliverAcquireFence(nullptr, aTextureOnBlack->GetIPDLActor(),
476 fenceFdB)));
479 auto fenceFdW = aTextureOnWhite->GetInternalData()->GetAcquireFence();
480 if (fenceFdW.IsValid()) {
481 mTxn->AddEdit(CompositableOperation(
482 aCompositable->GetIPCHandle(),
483 OpDeliverAcquireFence(nullptr, aTextureOnWhite->GetIPDLActor(),
484 fenceFdW)));
487 mTxn->AddEdit(CompositableOperation(
488 aCompositable->GetIPCHandle(),
489 OpUseComponentAlphaTextures(nullptr, aTextureOnBlack->GetIPDLActor(),
490 nullptr, aTextureOnWhite->GetIPDLActor(),
491 readLockedB, readLockedW)));
494 static bool AddOpDestroy(Transaction* aTxn, const OpDestroy& op) {
495 if (!aTxn->Opened()) {
496 return false;
499 aTxn->mDestroyedActors.AppendElement(op);
500 return true;
503 bool ShadowLayerForwarder::DestroyInTransaction(PTextureChild* aTexture) {
504 return AddOpDestroy(mTxn, OpDestroy(aTexture));
507 bool ShadowLayerForwarder::DestroyInTransaction(
508 const CompositableHandle& aHandle) {
509 return AddOpDestroy(mTxn, OpDestroy(aHandle));
512 void ShadowLayerForwarder::RemoveTextureFromCompositable(
513 CompositableClient* aCompositable, TextureClient* aTexture) {
514 MOZ_ASSERT(aCompositable);
515 MOZ_ASSERT(aTexture);
516 MOZ_ASSERT(aTexture->GetIPDLActor());
517 MOZ_RELEASE_ASSERT(aTexture->GetIPDLActor()->GetIPCChannel() ==
518 mShadowManager->GetIPCChannel());
519 if (!aCompositable->IsConnected() || !aTexture->GetIPDLActor()) {
520 // We don't have an actor anymore, don't try to use it!
521 return;
524 mTxn->AddEdit(CompositableOperation(
525 aCompositable->GetIPCHandle(),
526 OpRemoveTexture(nullptr, aTexture->GetIPDLActor())));
529 bool ShadowLayerForwarder::InWorkerThread() {
530 return GetTextureForwarder()->GetThread()->IsOnCurrentThread();
533 void ShadowLayerForwarder::StorePluginWidgetConfigurations(
534 const nsTArray<nsIWidget::Configuration>& aConfigurations) {
535 // Cache new plugin widget configs here until we call update, at which
536 // point this data will get shipped over to chrome.
537 mPluginWindowData.Clear();
538 for (uint32_t idx = 0; idx < aConfigurations.Length(); idx++) {
539 const nsIWidget::Configuration& configuration = aConfigurations[idx];
540 mPluginWindowData.AppendElement(
541 PluginWindowData(configuration.mWindowID, configuration.mClipRegion,
542 configuration.mBounds, configuration.mVisible));
546 void ShadowLayerForwarder::SendPaintTime(TransactionId aId,
547 TimeDuration aPaintTime) {
548 if (!IPCOpen() || !mShadowManager->SendPaintTime(aId, aPaintTime)) {
549 NS_WARNING("Could not send paint times over IPC");
553 bool ShadowLayerForwarder::EndTransaction(
554 const nsIntRegion& aRegionToClear, TransactionId aId,
555 bool aScheduleComposite, uint32_t aPaintSequenceNumber,
556 bool aIsRepeatTransaction, const mozilla::VsyncId& aVsyncId,
557 const mozilla::TimeStamp& aVsyncStart,
558 const mozilla::TimeStamp& aRefreshStart,
559 const mozilla::TimeStamp& aTransactionStart, bool aContainsSVG,
560 const nsCString& aURL, bool* aSent,
561 const nsTArray<CompositionPayload>& aPayload) {
562 *aSent = false;
564 TransactionInfo info;
566 MOZ_ASSERT(IPCOpen(), "no manager to forward to");
567 if (!IPCOpen()) {
568 return false;
571 Maybe<TimeStamp> startTime;
572 if (StaticPrefs::layers_acceleration_draw_fps()) {
573 startTime = Some(TimeStamp::Now());
576 GetCompositorBridgeChild()->WillEndTransaction();
578 MOZ_ASSERT(aId.IsValid());
580 AUTO_PROFILER_LABEL("ShadowLayerForwarder::EndTransaction", GRAPHICS);
582 RenderTraceScope rendertrace("Foward Transaction", "000091");
583 MOZ_ASSERT(!mTxn->Finished(), "forgot BeginTransaction?");
585 DiagnosticTypes diagnostics =
586 gfxPlatform::GetPlatform()->GetLayerDiagnosticTypes();
587 if (mDiagnosticTypes != diagnostics) {
588 mDiagnosticTypes = diagnostics;
589 mTxn->AddEdit(OpSetDiagnosticTypes(diagnostics));
592 AutoTxnEnd _(mTxn);
594 if (mTxn->Empty() && !mTxn->RotationChanged()) {
595 MOZ_LAYERS_LOG(
596 ("[LayersForwarder] 0-length cset (?) and no rotation event, skipping "
597 "Update()"));
598 return true;
601 if (!mTxn->mPaints.IsEmpty()) {
602 // With some platforms, telling the drawing backend that there will be no
603 // more drawing for this frame helps with preventing command queues from
604 // spanning across multiple frames.
605 gfxPlatform::GetPlatform()->FlushContentDrawing();
608 MOZ_LAYERS_LOG(("[LayersForwarder] destroying buffers..."));
610 MOZ_LAYERS_LOG(("[LayersForwarder] building transaction..."));
612 nsTArray<OpSetSimpleLayerAttributes> setSimpleAttrs;
613 for (ShadowableLayerSet::Iterator it(&mTxn->mSimpleMutants); !it.Done();
614 it.Next()) {
615 ShadowableLayer* shadow = it.Get()->GetKey();
616 if (!shadow->HasShadow()) {
617 continue;
620 Layer* mutant = shadow->AsLayer();
621 setSimpleAttrs.AppendElement(OpSetSimpleLayerAttributes(
622 Shadow(shadow), mutant->GetSimpleAttributes()));
625 nsTArray<OpSetLayerAttributes> setAttrs;
627 // We purposely add attribute-change ops to the final changeset
628 // before we add paint ops. This allows layers to record the
629 // attribute changes before new pixels arrive, which can be useful
630 // for setting up back/front buffers.
631 RenderTraceScope rendertrace2("Foward Transaction", "000092");
632 for (ShadowableLayerSet::Iterator it(&mTxn->mMutants); !it.Done();
633 it.Next()) {
634 ShadowableLayer* shadow = it.Get()->GetKey();
636 if (!shadow->HasShadow()) {
637 continue;
639 Layer* mutant = shadow->AsLayer();
640 MOZ_ASSERT(!!mutant, "unshadowable layer?");
642 OpSetLayerAttributes op;
643 op.layer() = Shadow(shadow);
645 LayerAttributes& attrs = op.attrs();
646 CommonLayerAttributes& common = attrs.common();
647 common.visibleRegion() = mutant->GetVisibleRegion();
648 common.eventRegions() = mutant->GetEventRegions();
649 common.useClipRect() = !!mutant->GetClipRect();
650 common.clipRect() =
651 (common.useClipRect() ? *mutant->GetClipRect() : ParentLayerIntRect());
652 if (Layer* maskLayer = mutant->GetMaskLayer()) {
653 common.maskLayer() = Shadow(maskLayer->AsShadowableLayer());
654 } else {
655 common.maskLayer() = LayerHandle();
657 common.compositorAnimations().id() = mutant->GetCompositorAnimationsId();
658 common.compositorAnimations().animations() =
659 mutant->GetAnimations().Clone();
660 common.invalidRegion() = mutant->GetInvalidRegion().GetRegion();
661 common.scrollMetadata() = mutant->GetAllScrollMetadata().Clone();
662 for (size_t i = 0; i < mutant->GetAncestorMaskLayerCount(); i++) {
663 auto layer =
664 Shadow(mutant->GetAncestorMaskLayerAt(i)->AsShadowableLayer());
665 common.ancestorMaskLayers().AppendElement(layer);
667 nsCString log;
668 mutant->GetDisplayListLog(log);
669 common.displayListLog() = log;
671 attrs.specific() = null_t();
672 mutant->FillSpecificAttributes(attrs.specific());
674 MOZ_LAYERS_LOG(("[LayersForwarder] OpSetLayerAttributes(%p)\n", mutant));
676 setAttrs.AppendElement(op);
679 if (mTxn->mCset.IsEmpty() && mTxn->mPaints.IsEmpty() && setAttrs.IsEmpty() &&
680 !mTxn->RotationChanged()) {
681 return true;
684 info.cset() = std::move(mTxn->mCset);
685 info.setSimpleAttrs() = std::move(setSimpleAttrs);
686 info.setAttrs() = std::move(setAttrs);
687 info.paints() = std::move(mTxn->mPaints);
688 info.toDestroy() = mTxn->mDestroyedActors.Clone();
689 info.fwdTransactionId() = GetFwdTransactionId();
690 info.id() = aId;
691 info.plugins() = mPluginWindowData.Clone();
692 info.isFirstPaint() = mIsFirstPaint;
693 info.focusTarget() = mFocusTarget;
694 info.scheduleComposite() = aScheduleComposite;
695 info.paintSequenceNumber() = aPaintSequenceNumber;
696 info.isRepeatTransaction() = aIsRepeatTransaction;
697 info.vsyncId() = aVsyncId;
698 info.vsyncStart() = aVsyncStart;
699 info.refreshStart() = aRefreshStart;
700 info.transactionStart() = aTransactionStart;
701 info.url() = aURL;
702 info.containsSVG() = aContainsSVG;
703 #if defined(ENABLE_FRAME_LATENCY_LOG)
704 info.fwdTime() = TimeStamp::Now();
705 #endif
706 info.payload() = aPayload.Clone();
708 TargetConfig targetConfig(mTxn->mTargetBounds, mTxn->mTargetRotation,
709 mTxn->mTargetOrientation, aRegionToClear);
710 info.targetConfig() = targetConfig;
712 if (!GetTextureForwarder()->IsSameProcess()) {
713 MOZ_LAYERS_LOG(("[LayersForwarder] syncing before send..."));
714 PlatformSyncBeforeUpdate();
717 if (startTime) {
718 mPaintTiming.serializeMs() =
719 (TimeStamp::Now() - startTime.value()).ToMilliseconds();
720 startTime = Some(TimeStamp::Now());
723 // We delay at the last possible minute, to give the paint thread a chance to
724 // finish. If it does we don't have to delay messages at all.
725 GetCompositorBridgeChild()->PostponeMessagesIfAsyncPainting();
727 MOZ_LAYERS_LOG(("[LayersForwarder] sending transaction..."));
728 RenderTraceScope rendertrace3("Forward Transaction", "000093");
729 if (!mShadowManager->SendUpdate(info)) {
730 MOZ_LAYERS_LOG(("[LayersForwarder] WARNING: sending transaction failed!"));
731 return false;
734 if (startTime) {
735 mPaintTiming.sendMs() =
736 (TimeStamp::Now() - startTime.value()).ToMilliseconds();
737 mShadowManager->SendRecordPaintTimes(mPaintTiming);
740 *aSent = true;
741 mIsFirstPaint = false;
742 mFocusTarget = FocusTarget();
743 MOZ_LAYERS_LOG(("[LayersForwarder] ... done"));
744 return true;
747 RefPtr<CompositableClient> ShadowLayerForwarder::FindCompositable(
748 const CompositableHandle& aHandle) {
749 CompositableClient* client = nullptr;
750 if (!mCompositables.Get(aHandle.Value(), &client)) {
751 return nullptr;
753 return client;
756 void ShadowLayerForwarder::SetLayersObserverEpoch(LayersObserverEpoch aEpoch) {
757 if (!IPCOpen()) {
758 return;
760 Unused << mShadowManager->SendSetLayersObserverEpoch(aEpoch);
763 void ShadowLayerForwarder::UpdateTextureLocks() {
764 #ifdef XP_DARWIN
765 if (!IPCOpen()) {
766 return;
769 auto compositorBridge = GetCompositorBridgeChild();
770 if (compositorBridge) {
771 auto pid = compositorBridge->OtherPid();
772 TextureSync::UpdateTextureLocks(pid);
774 #endif
777 void ShadowLayerForwarder::SyncTextures(const nsTArray<uint64_t>& aSerials) {
778 #ifdef XP_DARWIN
779 if (!IPCOpen()) {
780 return;
783 auto compositorBridge = GetCompositorBridgeChild();
784 if (compositorBridge) {
785 auto pid = compositorBridge->OtherPid();
786 TextureSync::WaitForTextures(pid, aSerials);
788 #endif
791 void ShadowLayerForwarder::ReleaseLayer(const LayerHandle& aHandle) {
792 if (!IPCOpen()) {
793 return;
795 Unused << mShadowManager->SendReleaseLayer(aHandle);
798 bool ShadowLayerForwarder::IPCOpen() const {
799 return HasShadowManager() && mShadowManager->IPCOpen();
803 * We bail out when we have no shadow manager. That can happen when the
804 * layer manager is created by the preallocated process.
805 * See bug 914843 for details.
807 LayerHandle ShadowLayerForwarder::ConstructShadowFor(ShadowableLayer* aLayer) {
808 return LayerHandle(mNextLayerHandle++);
811 #if !defined(MOZ_HAVE_PLATFORM_SPECIFIC_LAYER_BUFFERS)
813 /*static*/
814 void ShadowLayerForwarder::PlatformSyncBeforeUpdate() {}
816 #endif // !defined(MOZ_HAVE_PLATFORM_SPECIFIC_LAYER_BUFFERS)
818 void ShadowLayerForwarder::Connect(CompositableClient* aCompositable,
819 ImageContainer* aImageContainer) {
820 #ifdef GFX_COMPOSITOR_LOGGING
821 printf("ShadowLayerForwarder::Connect(Compositable)\n");
822 #endif
823 MOZ_ASSERT(aCompositable);
824 MOZ_ASSERT(mShadowManager);
825 if (!IPCOpen()) {
826 return;
829 static uint64_t sNextID = 1;
830 uint64_t id = sNextID++;
832 mCompositables.Put(id, aCompositable);
834 CompositableHandle handle(id);
835 aCompositable->InitIPDL(handle);
836 mShadowManager->SendNewCompositable(handle, aCompositable->GetTextureInfo());
839 void ShadowLayerForwarder::Attach(CompositableClient* aCompositable,
840 ShadowableLayer* aLayer) {
841 MOZ_ASSERT(aLayer);
842 MOZ_ASSERT(aCompositable);
843 mTxn->AddEdit(
844 OpAttachCompositable(Shadow(aLayer), aCompositable->GetIPCHandle()));
847 void ShadowLayerForwarder::AttachAsyncCompositable(
848 const CompositableHandle& aHandle, ShadowableLayer* aLayer) {
849 MOZ_ASSERT(aLayer);
850 MOZ_ASSERT(aHandle);
851 mTxn->AddEdit(OpAttachAsyncCompositable(Shadow(aLayer), aHandle));
854 void ShadowLayerForwarder::SetShadowManager(
855 PLayerTransactionChild* aShadowManager) {
856 mShadowManager = static_cast<LayerTransactionChild*>(aShadowManager);
857 mShadowManager->SetForwarder(this);
860 void ShadowLayerForwarder::StopReceiveAsyncParentMessge() {
861 if (!IPCOpen()) {
862 return;
864 mShadowManager->SetForwarder(nullptr);
867 void ShadowLayerForwarder::ClearCachedResources() {
868 if (!IPCOpen()) {
869 return;
871 mShadowManager->SendClearCachedResources();
874 void ShadowLayerForwarder::ScheduleComposite() {
875 if (!IPCOpen()) {
876 return;
878 mShadowManager->SendScheduleComposite();
881 bool IsSurfaceDescriptorValid(const SurfaceDescriptor& aSurface) {
882 return aSurface.type() != SurfaceDescriptor::T__None &&
883 aSurface.type() != SurfaceDescriptor::Tnull_t;
886 uint8_t* GetAddressFromDescriptor(const SurfaceDescriptor& aDescriptor) {
887 MOZ_ASSERT(IsSurfaceDescriptorValid(aDescriptor));
888 MOZ_RELEASE_ASSERT(
889 aDescriptor.type() == SurfaceDescriptor::TSurfaceDescriptorBuffer,
890 "GFX: surface descriptor is not the right type.");
892 auto memOrShmem = aDescriptor.get_SurfaceDescriptorBuffer().data();
893 if (memOrShmem.type() == MemoryOrShmem::TShmem) {
894 return memOrShmem.get_Shmem().get<uint8_t>();
895 } else {
896 return reinterpret_cast<uint8_t*>(memOrShmem.get_uintptr_t());
900 already_AddRefed<gfx::DataSourceSurface> GetSurfaceForDescriptor(
901 const SurfaceDescriptor& aDescriptor) {
902 if (aDescriptor.type() != SurfaceDescriptor::TSurfaceDescriptorBuffer) {
903 return nullptr;
905 uint8_t* data = GetAddressFromDescriptor(aDescriptor);
906 auto rgb =
907 aDescriptor.get_SurfaceDescriptorBuffer().desc().get_RGBDescriptor();
908 uint32_t stride = ImageDataSerializer::GetRGBStride(rgb);
909 return gfx::Factory::CreateWrappingDataSourceSurface(data, stride, rgb.size(),
910 rgb.format());
913 already_AddRefed<gfx::DrawTarget> GetDrawTargetForDescriptor(
914 const SurfaceDescriptor& aDescriptor) {
915 uint8_t* data = GetAddressFromDescriptor(aDescriptor);
916 auto rgb =
917 aDescriptor.get_SurfaceDescriptorBuffer().desc().get_RGBDescriptor();
918 uint32_t stride = ImageDataSerializer::GetRGBStride(rgb);
919 return gfx::Factory::CreateDrawTargetForData(
920 gfx::BackendType::SKIA, data, rgb.size(), stride, rgb.format());
923 void DestroySurfaceDescriptor(IShmemAllocator* aAllocator,
924 SurfaceDescriptor* aSurface) {
925 MOZ_ASSERT(aSurface);
927 SurfaceDescriptorBuffer& desc = aSurface->get_SurfaceDescriptorBuffer();
928 switch (desc.data().type()) {
929 case MemoryOrShmem::TShmem: {
930 aAllocator->DeallocShmem(desc.data().get_Shmem());
931 break;
933 case MemoryOrShmem::Tuintptr_t: {
934 uint8_t* ptr = (uint8_t*)desc.data().get_uintptr_t();
935 GfxMemoryImageReporter::WillFree(ptr);
936 delete[] ptr;
937 break;
939 default:
940 MOZ_CRASH("surface type not implemented!");
942 *aSurface = SurfaceDescriptor();
945 bool ShadowLayerForwarder::AllocSurfaceDescriptor(const gfx::IntSize& aSize,
946 gfxContentType aContent,
947 SurfaceDescriptor* aBuffer) {
948 if (!IPCOpen()) {
949 return false;
951 return AllocSurfaceDescriptorWithCaps(aSize, aContent, DEFAULT_BUFFER_CAPS,
952 aBuffer);
955 bool ShadowLayerForwarder::AllocSurfaceDescriptorWithCaps(
956 const gfx::IntSize& aSize, gfxContentType aContent, uint32_t aCaps,
957 SurfaceDescriptor* aBuffer) {
958 if (!IPCOpen()) {
959 return false;
961 gfx::SurfaceFormat format =
962 gfxPlatform::GetPlatform()->Optimal2DFormatForContent(aContent);
963 size_t size = ImageDataSerializer::ComputeRGBBufferSize(aSize, format);
964 if (!size) {
965 return false;
968 MemoryOrShmem bufferDesc;
969 if (GetTextureForwarder()->IsSameProcess()) {
970 uint8_t* data = new (std::nothrow) uint8_t[size];
971 if (!data) {
972 return false;
974 GfxMemoryImageReporter::DidAlloc(data);
975 memset(data, 0, size);
976 bufferDesc = reinterpret_cast<uintptr_t>(data);
977 } else {
978 mozilla::ipc::Shmem shmem;
979 if (!GetTextureForwarder()->AllocUnsafeShmem(size, OptimalShmemType(),
980 &shmem)) {
981 return false;
984 bufferDesc = std::move(shmem);
987 // Use an intermediate buffer by default. Skipping the intermediate buffer is
988 // only possible in certain configurations so let's keep it simple here for
989 // now.
990 const bool hasIntermediateBuffer = true;
991 *aBuffer = SurfaceDescriptorBuffer(
992 RGBDescriptor(aSize, format, hasIntermediateBuffer), bufferDesc);
994 return true;
997 /* static */
998 bool ShadowLayerForwarder::IsShmem(SurfaceDescriptor* aSurface) {
999 return aSurface &&
1000 (aSurface->type() == SurfaceDescriptor::TSurfaceDescriptorBuffer) &&
1001 (aSurface->get_SurfaceDescriptorBuffer().data().type() ==
1002 MemoryOrShmem::TShmem);
1005 void ShadowLayerForwarder::DestroySurfaceDescriptor(
1006 SurfaceDescriptor* aSurface) {
1007 MOZ_ASSERT(aSurface);
1008 MOZ_ASSERT(IPCOpen());
1009 if (!IPCOpen() || !aSurface) {
1010 return;
1013 ::mozilla::layers::DestroySurfaceDescriptor(GetTextureForwarder(), aSurface);
1016 void ShadowLayerForwarder::UpdateFwdTransactionId() {
1017 auto compositorBridge = GetCompositorBridgeChild();
1018 if (compositorBridge) {
1019 compositorBridge->UpdateFwdTransactionId();
1023 uint64_t ShadowLayerForwarder::GetFwdTransactionId() {
1024 auto compositorBridge = GetCompositorBridgeChild();
1025 MOZ_DIAGNOSTIC_ASSERT(compositorBridge);
1026 return compositorBridge ? compositorBridge->GetFwdTransactionId() : 0;
1029 CompositorBridgeChild* ShadowLayerForwarder::GetCompositorBridgeChild() {
1030 if (mCompositorBridgeChild) {
1031 return mCompositorBridgeChild;
1033 if (!mShadowManager) {
1034 return nullptr;
1036 mCompositorBridgeChild =
1037 static_cast<CompositorBridgeChild*>(mShadowManager->Manager());
1038 return mCompositorBridgeChild;
1041 void ShadowLayerForwarder::SyncWithCompositor() {
1042 auto compositorBridge = GetCompositorBridgeChild();
1043 if (compositorBridge && compositorBridge->IPCOpen()) {
1044 compositorBridge->SendSyncWithCompositor();
1048 void ShadowLayerForwarder::ReleaseCompositable(
1049 const CompositableHandle& aHandle) {
1050 AssertInForwarderThread();
1051 if (!DestroyInTransaction(aHandle)) {
1052 if (!IPCOpen()) {
1053 return;
1055 mShadowManager->SendReleaseCompositable(aHandle);
1057 mCompositables.Remove(aHandle.Value());
1060 void ShadowLayerForwarder::SynchronouslyShutdown() {
1061 if (IPCOpen()) {
1062 mShadowManager->SendShutdownSync();
1063 mShadowManager->MarkDestroyed();
1067 ShadowableLayer::~ShadowableLayer() {
1068 if (mShadow) {
1069 mForwarder->ReleaseLayer(GetShadow());
1073 } // namespace layers
1074 } // namespace mozilla