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