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