1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #include "ClientLayerManager.h"
8 #include "GeckoProfiler.h"       // for AUTO_PROFILER_LABEL
9 #include "gfxPrefs.h"            // for gfxPrefs::LayersTile...
10 #include "mozilla/Assertions.h"  // for MOZ_ASSERT, etc
11 #include "mozilla/Hal.h"
12 #include "mozilla/dom/ScreenOrientation.h"  // for ScreenOrientation
13 #include "mozilla/dom/TabChild.h"           // for TabChild
14 #include "mozilla/dom/TabGroup.h"           // for TabGroup
15 #include "mozilla/hal_sandbox/PHal.h"       // for ScreenConfiguration
16 #include "mozilla/layers/CompositableClient.h"
17 #include "mozilla/layers/CompositorBridgeChild.h"  // for CompositorBridgeChild
18 #include "mozilla/layers/FrameUniformityData.h"
19 #include "mozilla/layers/ISurfaceAllocator.h"
20 #include "mozilla/layers/LayersMessages.h"  // for EditReply, etc
21 #include "mozilla/layers/LayersSurfaces.h"  // for SurfaceDescriptor
22 #include "mozilla/layers/LayerTransactionChild.h"
23 #include "mozilla/layers/PersistentBufferProvider.h"
24 #include "mozilla/layers/SyncObject.h"
25 #include "ClientReadbackLayer.h"  // for ClientReadbackLayer
26 #include "nsAString.h"
27 #include "nsDisplayList.h"
28 #include "nsIWidgetListener.h"
29 #include "nsTArray.h"     // for AutoTArray
30 #include "nsXULAppAPI.h"  // for XRE_GetProcessType, etc
31 #include "TiledLayerBuffer.h"
32 #include "FrameLayerBuilder.h"  // for FrameLayerbuilder
33 #ifdef MOZ_WIDGET_ANDROID
34 #include "AndroidBridge.h"
35 #include "LayerMetricsWrapper.h"
36 #endif
37 #ifdef XP_WIN
38 #include "mozilla/gfx/DeviceManagerDx.h"
39 #include "gfxDWriteFonts.h"
40 #endif
41 
42 namespace mozilla {
43 namespace layers {
44 
45 using namespace mozilla::gfx;
46 
Destroy()47 void ClientLayerManager::MemoryPressureObserver::Destroy() {
48   UnregisterMemoryPressureEvent();
49   mClientLayerManager = nullptr;
50 }
51 
52 NS_IMETHODIMP
Observe(nsISupports * aSubject,const char * aTopic,const char16_t * aSomeData)53 ClientLayerManager::MemoryPressureObserver::Observe(nsISupports* aSubject,
54                                                     const char* aTopic,
55                                                     const char16_t* aSomeData) {
56   if (!mClientLayerManager || strcmp(aTopic, "memory-pressure")) {
57     return NS_OK;
58   }
59 
60   mClientLayerManager->HandleMemoryPressure();
61   return NS_OK;
62 }
63 
RegisterMemoryPressureEvent()64 void ClientLayerManager::MemoryPressureObserver::RegisterMemoryPressureEvent() {
65   nsCOMPtr<nsIObserverService> observerService =
66       mozilla::services::GetObserverService();
67 
68   MOZ_ASSERT(observerService);
69 
70   if (observerService) {
71     observerService->AddObserver(this, "memory-pressure", false);
72   }
73 }
74 
75 void ClientLayerManager::MemoryPressureObserver::
UnregisterMemoryPressureEvent()76     UnregisterMemoryPressureEvent() {
77   nsCOMPtr<nsIObserverService> observerService =
78       mozilla::services::GetObserverService();
79 
80   if (observerService) {
81     observerService->RemoveObserver(this, "memory-pressure");
82   }
83 }
84 
NS_IMPL_ISUPPORTS(ClientLayerManager::MemoryPressureObserver,nsIObserver)85 NS_IMPL_ISUPPORTS(ClientLayerManager::MemoryPressureObserver, nsIObserver)
86 
87 ClientLayerManager::ClientLayerManager(nsIWidget* aWidget)
88     : mPhase(PHASE_NONE),
89       mWidget(aWidget),
90       mLatestTransactionId(0),
91       mLastPaintTime(TimeDuration::Forever()),
92       mTargetRotation(ROTATION_0),
93       mRepeatTransaction(false),
94       mIsRepeatTransaction(false),
95       mTransactionIncomplete(false),
96       mCompositorMightResample(false),
97       mNeedsComposite(false),
98       mQueuedAsyncPaints(false),
99       mPaintSequenceNumber(0),
100       mForwarder(new ShadowLayerForwarder(this)) {
101   MOZ_COUNT_CTOR(ClientLayerManager);
102   mMemoryPressureObserver = new MemoryPressureObserver(this);
103 }
104 
~ClientLayerManager()105 ClientLayerManager::~ClientLayerManager() {
106   mMemoryPressureObserver->Destroy();
107   ClearCachedResources();
108   // Stop receiveing AsyncParentMessage at Forwarder.
109   // After the call, the message is directly handled by LayerTransactionChild.
110   // Basically this function should be called in ShadowLayerForwarder's
111   // destructor. But when the destructor is triggered by
112   // CompositorBridgeChild::Destroy(), the destructor can not handle it
113   // correctly. See Bug 1000525.
114   mForwarder->StopReceiveAsyncParentMessge();
115   mRoot = nullptr;
116 
117   MOZ_COUNT_DTOR(ClientLayerManager);
118 }
119 
Destroy()120 void ClientLayerManager::Destroy() {
121   // It's important to call ClearCachedResource before Destroy because the
122   // former will early-return if the later has already run.
123   ClearCachedResources();
124   LayerManager::Destroy();
125 
126   if (mTransactionIdAllocator) {
127     // Make sure to notify the refresh driver just in case it's waiting on a
128     // pending transaction. Do this at the top of the event loop so we don't
129     // cause a paint to occur during compositor shutdown.
130     RefPtr<TransactionIdAllocator> allocator = mTransactionIdAllocator;
131     uint64_t id = mLatestTransactionId;
132 
133     RefPtr<Runnable> task = NS_NewRunnableFunction(
134         "TransactionIdAllocator::NotifyTransactionCompleted",
135         [allocator, id]() -> void {
136           allocator->NotifyTransactionCompleted(id);
137         });
138     NS_DispatchToMainThread(task.forget());
139   }
140 
141   // Forget the widget pointer in case we outlive our owning widget.
142   mWidget = nullptr;
143 }
144 
GetTabGroup()145 TabGroup* ClientLayerManager::GetTabGroup() {
146   if (mWidget) {
147     if (TabChild* tabChild = mWidget->GetOwningTabChild()) {
148       return tabChild->TabGroup();
149     }
150   }
151   return nullptr;
152 }
153 
GetMaxTextureSize() const154 int32_t ClientLayerManager::GetMaxTextureSize() const {
155   return mForwarder->GetMaxTextureSize();
156 }
157 
SetDefaultTargetConfiguration(BufferMode aDoubleBuffering,ScreenRotation aRotation)158 void ClientLayerManager::SetDefaultTargetConfiguration(
159     BufferMode aDoubleBuffering, ScreenRotation aRotation) {
160   mTargetRotation = aRotation;
161 }
162 
SetRoot(Layer * aLayer)163 void ClientLayerManager::SetRoot(Layer* aLayer) {
164   if (mRoot != aLayer) {
165     // Have to hold the old root and its children in order to
166     // maintain the same view of the layer tree in this process as
167     // the parent sees.  Otherwise layers can be destroyed
168     // mid-transaction and bad things can happen (v. bug 612573)
169     if (mRoot) {
170       Hold(mRoot);
171     }
172     mForwarder->SetRoot(Hold(aLayer));
173     NS_ASSERTION(aLayer, "Root can't be null");
174     NS_ASSERTION(aLayer->Manager() == this, "Wrong manager");
175     NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
176     mRoot = aLayer;
177   }
178 }
179 
Mutated(Layer * aLayer)180 void ClientLayerManager::Mutated(Layer* aLayer) {
181   LayerManager::Mutated(aLayer);
182 
183   NS_ASSERTION(InConstruction() || InDrawing(), "wrong phase");
184   mForwarder->Mutated(Hold(aLayer));
185 }
186 
MutatedSimple(Layer * aLayer)187 void ClientLayerManager::MutatedSimple(Layer* aLayer) {
188   LayerManager::MutatedSimple(aLayer);
189 
190   NS_ASSERTION(InConstruction() || InDrawing(), "wrong phase");
191   mForwarder->MutatedSimple(Hold(aLayer));
192 }
193 
CreateReadbackLayer()194 already_AddRefed<ReadbackLayer> ClientLayerManager::CreateReadbackLayer() {
195   RefPtr<ReadbackLayer> layer = new ClientReadbackLayer(this);
196   return layer.forget();
197 }
198 
BeginTransactionWithTarget(gfxContext * aTarget)199 bool ClientLayerManager::BeginTransactionWithTarget(gfxContext* aTarget) {
200   // Wait for any previous async paints to complete before starting to paint
201   // again.
202   FlushAsyncPaints();
203 
204   MOZ_ASSERT(mForwarder,
205              "ClientLayerManager::BeginTransaction without forwarder");
206   if (!mForwarder->IPCOpen()) {
207     gfxCriticalNote << "ClientLayerManager::BeginTransaction with IPC channel "
208                        "down. GPU process may have died.";
209     return false;
210   }
211 
212   mInTransaction = true;
213   mTransactionStart = TimeStamp::Now();
214 
215 #ifdef MOZ_LAYERS_HAVE_LOG
216   MOZ_LAYERS_LOG(("[----- BeginTransaction"));
217   Log();
218 #endif
219 
220   NS_ASSERTION(!InTransaction(), "Nested transactions not allowed");
221   mPhase = PHASE_CONSTRUCTION;
222 
223   MOZ_ASSERT(mKeepAlive.IsEmpty(), "uncommitted txn?");
224 
225   // If the last transaction was incomplete (a failed DoEmptyTransaction),
226   // don't signal a new transaction to ShadowLayerForwarder. Carry on adding
227   // to the previous transaction.
228   dom::ScreenOrientationInternal orientation;
229   if (dom::TabChild* window = mWidget->GetOwningTabChild()) {
230     orientation = window->GetOrientation();
231   } else {
232     hal::ScreenConfiguration currentConfig;
233     hal::GetCurrentScreenConfiguration(&currentConfig);
234     orientation = currentConfig.orientation();
235   }
236   LayoutDeviceIntRect targetBounds = mWidget->GetNaturalBounds();
237   targetBounds.MoveTo(0, 0);
238   mForwarder->BeginTransaction(targetBounds.ToUnknownRect(), mTargetRotation,
239                                orientation);
240 
241   // If we're drawing on behalf of a context with async pan/zoom
242   // enabled, then the entire buffer of painted layers might be
243   // composited (including resampling) asynchronously before we get
244   // a chance to repaint, so we have to ensure that it's all valid
245   // and not rotated.
246   //
247   // Desktop does not support async zoom yet, so we ignore this for those
248   // platforms.
249 #if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_UIKIT)
250   if (mWidget && mWidget->GetOwningTabChild()) {
251     mCompositorMightResample = AsyncPanZoomEnabled();
252   }
253 #endif
254 
255   // If we have a non-default target, we need to let our shadow manager draw
256   // to it. This will happen at the end of the transaction.
257   if (aTarget && XRE_IsParentProcess()) {
258     mShadowTarget = aTarget;
259   } else {
260     NS_ASSERTION(!aTarget,
261                  "Content-process "
262                  "ClientLayerManager::BeginTransactionWithTarget not "
263                  "supported");
264   }
265 
266   // If this is a new paint, increment the paint sequence number.
267   if (!mIsRepeatTransaction) {
268     // Increment the paint sequence number even if test logging isn't
269     // enabled in this process; it may be enabled in the parent process,
270     // and the parent process expects unique sequence numbers.
271     ++mPaintSequenceNumber;
272     if (gfxPrefs::APZTestLoggingEnabled()) {
273       mApzTestData.StartNewPaint(mPaintSequenceNumber);
274     }
275   }
276   return true;
277 }
278 
BeginTransaction()279 bool ClientLayerManager::BeginTransaction() {
280   return BeginTransactionWithTarget(nullptr);
281 }
282 
EndTransactionInternal(DrawPaintedLayerCallback aCallback,void * aCallbackData,EndTransactionFlags)283 bool ClientLayerManager::EndTransactionInternal(
284     DrawPaintedLayerCallback aCallback, void* aCallbackData,
285     EndTransactionFlags) {
286   PaintTelemetry::AutoRecord record(PaintTelemetry::Metric::Rasterization);
287   AUTO_PROFILER_TRACING("Paint", "Rasterize");
288 
289   Maybe<TimeStamp> startTime;
290   if (gfxPrefs::LayersDrawFPS()) {
291     startTime = Some(TimeStamp::Now());
292   }
293 
294 #ifdef WIN32
295   if (aCallbackData) {
296     // Content processes don't get OnPaint called. So update here whenever we
297     // may do Thebes drawing.
298     gfxDWriteFont::UpdateClearTypeUsage();
299   }
300 #endif
301 
302   AUTO_PROFILER_LABEL("ClientLayerManager::EndTransactionInternal", GRAPHICS);
303 
304 #ifdef MOZ_LAYERS_HAVE_LOG
305   MOZ_LAYERS_LOG(("  ----- (beginning paint)"));
306   Log();
307 #endif
308 
309   NS_ASSERTION(InConstruction(), "Should be in construction phase");
310   mPhase = PHASE_DRAWING;
311 
312   ClientLayer* root = ClientLayer::ToClientLayer(GetRoot());
313 
314   mTransactionIncomplete = false;
315   mQueuedAsyncPaints = false;
316 
317   // Apply pending tree updates before recomputing effective
318   // properties.
319   GetRoot()->ApplyPendingUpdatesToSubtree();
320 
321   mPaintedLayerCallback = aCallback;
322   mPaintedLayerCallbackData = aCallbackData;
323 
324   GetRoot()->ComputeEffectiveTransforms(Matrix4x4());
325 
326   // Skip the painting if the device is in device-reset status.
327   if (!gfxPlatform::GetPlatform()->DidRenderingDeviceReset()) {
328     if (gfxPrefs::AlwaysPaint() && XRE_IsContentProcess()) {
329       TimeStamp start = TimeStamp::Now();
330       root->RenderLayer();
331       mLastPaintTime = TimeStamp::Now() - start;
332     } else {
333       root->RenderLayer();
334     }
335   } else {
336     gfxCriticalNote << "LayerManager::EndTransaction skip RenderLayer().";
337   }
338 
339   if (!mRepeatTransaction && !GetRoot()->GetInvalidRegion().IsEmpty()) {
340     GetRoot()->Mutated();
341   }
342 
343   if (!mIsRepeatTransaction) {
344     mAnimationReadyTime = TimeStamp::Now();
345     GetRoot()->StartPendingAnimations(mAnimationReadyTime);
346   }
347 
348   mPaintedLayerCallback = nullptr;
349   mPaintedLayerCallbackData = nullptr;
350 
351   // Go back to the construction phase if the transaction isn't complete.
352   // Layout will update the layer tree and call EndTransaction().
353   mPhase = mTransactionIncomplete ? PHASE_CONSTRUCTION : PHASE_NONE;
354 
355   NS_ASSERTION(!aCallback || !mTransactionIncomplete,
356                "If callback is not null, transaction must be complete");
357 
358   if (gfxPlatform::GetPlatform()->DidRenderingDeviceReset()) {
359     FrameLayerBuilder::InvalidateAllLayers(this);
360   }
361 
362   if (startTime) {
363     PaintTiming& pt = mForwarder->GetPaintTiming();
364     pt.rasterMs() = (TimeStamp::Now() - startTime.value()).ToMilliseconds();
365   }
366 
367   return !mTransactionIncomplete;
368 }
369 
StorePluginWidgetConfigurations(const nsTArray<nsIWidget::Configuration> & aConfigurations)370 void ClientLayerManager::StorePluginWidgetConfigurations(
371     const nsTArray<nsIWidget::Configuration>& aConfigurations) {
372   if (mForwarder) {
373     mForwarder->StorePluginWidgetConfigurations(aConfigurations);
374   }
375 }
376 
EndTransaction(DrawPaintedLayerCallback aCallback,void * aCallbackData,EndTransactionFlags aFlags)377 void ClientLayerManager::EndTransaction(DrawPaintedLayerCallback aCallback,
378                                         void* aCallbackData,
379                                         EndTransactionFlags aFlags) {
380   if (!mForwarder->IPCOpen()) {
381     mInTransaction = false;
382     return;
383   }
384 
385   if (mTransactionIncomplete) {
386     // If the previous transaction was incomplete then we may have buffer
387     // operations running on the paint thread that haven't finished yet
388     FlushAsyncPaints();
389   }
390 
391   if (mWidget) {
392     mWidget->PrepareWindowEffects();
393   }
394   EndTransactionInternal(aCallback, aCallbackData, aFlags);
395   ForwardTransaction(!(aFlags & END_NO_REMOTE_COMPOSITE));
396 
397   if (mRepeatTransaction) {
398     mRepeatTransaction = false;
399     mIsRepeatTransaction = true;
400     if (BeginTransaction()) {
401       ClientLayerManager::EndTransaction(aCallback, aCallbackData, aFlags);
402     }
403     mIsRepeatTransaction = false;
404   } else {
405     MakeSnapshotIfRequired();
406   }
407 
408   mInTransaction = false;
409   mTransactionStart = TimeStamp();
410 }
411 
EndEmptyTransaction(EndTransactionFlags aFlags)412 bool ClientLayerManager::EndEmptyTransaction(EndTransactionFlags aFlags) {
413   mInTransaction = false;
414 
415   if (!mRoot || !mForwarder->IPCOpen()) {
416     return false;
417   }
418 
419   if (mTransactionIncomplete) {
420     // If the previous transaction was incomplete then we may have buffer
421     // operations running on the paint thread that haven't finished yet
422     FlushAsyncPaints();
423   }
424 
425   if (!EndTransactionInternal(nullptr, nullptr, aFlags)) {
426     // Return without calling ForwardTransaction. This leaves the
427     // ShadowLayerForwarder transaction open; the following
428     // EndTransaction will complete it.
429     if (PaintThread::Get() && mQueuedAsyncPaints) {
430       PaintThread::Get()->EndLayerTransaction(nullptr);
431     }
432     return false;
433   }
434   if (mWidget) {
435     mWidget->PrepareWindowEffects();
436   }
437   ForwardTransaction(!(aFlags & END_NO_REMOTE_COMPOSITE));
438   MakeSnapshotIfRequired();
439   return true;
440 }
441 
GetRemoteRenderer()442 CompositorBridgeChild* ClientLayerManager::GetRemoteRenderer() {
443   if (!mWidget) {
444     return nullptr;
445   }
446 
447   return mWidget->GetRemoteRenderer();
448 }
449 
GetCompositorBridgeChild()450 CompositorBridgeChild* ClientLayerManager::GetCompositorBridgeChild() {
451   if (!XRE_IsParentProcess()) {
452     return CompositorBridgeChild::Get();
453   }
454   return GetRemoteRenderer();
455 }
456 
FlushAsyncPaints()457 void ClientLayerManager::FlushAsyncPaints() {
458   CompositorBridgeChild* cbc = GetCompositorBridgeChild();
459   if (cbc) {
460     cbc->FlushAsyncPaints();
461   }
462 }
463 
ScheduleComposite()464 void ClientLayerManager::ScheduleComposite() {
465   mForwarder->ScheduleComposite();
466 }
467 
DidComposite(uint64_t aTransactionId,const TimeStamp & aCompositeStart,const TimeStamp & aCompositeEnd)468 void ClientLayerManager::DidComposite(uint64_t aTransactionId,
469                                       const TimeStamp& aCompositeStart,
470                                       const TimeStamp& aCompositeEnd) {
471   MOZ_ASSERT(mWidget);
472 
473   // Notifying the observers may tick the refresh driver which can cause
474   // a lot of different things to happen that may affect the lifetime of
475   // this layer manager. So let's make sure this object stays alive until
476   // the end of the method invocation.
477   RefPtr<ClientLayerManager> selfRef = this;
478 
479   // |aTransactionId| will be > 0 if the compositor is acknowledging a shadow
480   // layers transaction.
481   if (aTransactionId) {
482     nsIWidgetListener* listener = mWidget->GetWidgetListener();
483     if (listener) {
484       listener->DidCompositeWindow(aTransactionId, aCompositeStart,
485                                    aCompositeEnd);
486     }
487     listener = mWidget->GetAttachedWidgetListener();
488     if (listener) {
489       listener->DidCompositeWindow(aTransactionId, aCompositeStart,
490                                    aCompositeEnd);
491     }
492     if (mTransactionIdAllocator) {
493       mTransactionIdAllocator->NotifyTransactionCompleted(aTransactionId);
494     }
495   }
496 
497   // These observers fire whether or not we were in a transaction.
498   for (size_t i = 0; i < mDidCompositeObservers.Length(); i++) {
499     mDidCompositeObservers[i]->DidComposite();
500   }
501 }
502 
GetCompositorSideAPZTestData(APZTestData * aData) const503 void ClientLayerManager::GetCompositorSideAPZTestData(
504     APZTestData* aData) const {
505   if (mForwarder->HasShadowManager()) {
506     if (!mForwarder->GetShadowManager()->SendGetAPZTestData(aData)) {
507       NS_WARNING("Call to PLayerTransactionChild::SendGetAPZTestData() failed");
508     }
509   }
510 }
511 
SetTransactionIdAllocator(TransactionIdAllocator * aAllocator)512 void ClientLayerManager::SetTransactionIdAllocator(
513     TransactionIdAllocator* aAllocator) {
514   // When changing the refresh driver, the previous refresh driver may never
515   // receive updates of pending transactions it's waiting for. So clear the
516   // waiting state before assigning another refresh driver.
517   if (mTransactionIdAllocator && (aAllocator != mTransactionIdAllocator)) {
518     mTransactionIdAllocator->ClearPendingTransactions();
519 
520     // We should also reset the transaction id of the new allocator to previous
521     // allocator's last transaction id, so that completed transactions for
522     // previous allocator will be ignored and won't confuse the new allocator.
523     if (aAllocator) {
524       aAllocator->ResetInitialTransactionId(
525           mTransactionIdAllocator->LastTransactionId());
526     }
527   }
528 
529   mTransactionIdAllocator = aAllocator;
530 }
531 
RequestProperty(const nsAString & aProperty)532 float ClientLayerManager::RequestProperty(const nsAString& aProperty) {
533   if (mForwarder->HasShadowManager()) {
534     float value;
535     if (!mForwarder->GetShadowManager()->SendRequestProperty(
536             nsString(aProperty), &value)) {
537       NS_WARNING("Call to PLayerTransactionChild::SendGetAPZTestData() failed");
538     }
539     return value;
540   }
541   return -1;
542 }
543 
StartNewRepaintRequest(SequenceNumber aSequenceNumber)544 void ClientLayerManager::StartNewRepaintRequest(
545     SequenceNumber aSequenceNumber) {
546   if (gfxPrefs::APZTestLoggingEnabled()) {
547     mApzTestData.StartNewRepaintRequest(aSequenceNumber);
548   }
549 }
550 
GetFrameUniformity(FrameUniformityData * aOutData)551 void ClientLayerManager::GetFrameUniformity(FrameUniformityData* aOutData) {
552   MOZ_ASSERT(XRE_IsParentProcess(),
553              "Frame Uniformity only supported in parent process");
554 
555   if (HasShadowManager()) {
556     CompositorBridgeChild* child = GetRemoteRenderer();
557     child->SendGetFrameUniformity(aOutData);
558     return;
559   }
560 
561   return LayerManager::GetFrameUniformity(aOutData);
562 }
563 
MakeSnapshotIfRequired()564 void ClientLayerManager::MakeSnapshotIfRequired() {
565   if (!mShadowTarget) {
566     return;
567   }
568   if (mWidget) {
569     if (CompositorBridgeChild* remoteRenderer = GetRemoteRenderer()) {
570       // The compositor doesn't draw to a different sized surface
571       // when there's a rotation. Instead we rotate the result
572       // when drawing into dt
573       LayoutDeviceIntRect outerBounds = mWidget->GetBounds();
574 
575       IntRect bounds = ToOutsideIntRect(mShadowTarget->GetClipExtents());
576       if (mTargetRotation) {
577         bounds =
578             RotateRect(bounds, outerBounds.ToUnknownRect(), mTargetRotation);
579       }
580 
581       SurfaceDescriptor inSnapshot;
582       if (!bounds.IsEmpty() &&
583           mForwarder->AllocSurfaceDescriptor(
584               bounds.Size(), gfxContentType::COLOR_ALPHA, &inSnapshot)) {
585         // Make a copy of |inSnapshot| because the call to send it over IPC
586         // will call forget() on the Shmem inside, and zero it out.
587         SurfaceDescriptor outSnapshot = inSnapshot;
588 
589         if (remoteRenderer->SendMakeSnapshot(inSnapshot, bounds)) {
590           RefPtr<DataSourceSurface> surf = GetSurfaceForDescriptor(outSnapshot);
591           DrawTarget* dt = mShadowTarget->GetDrawTarget();
592 
593           Rect dstRect(bounds.X(), bounds.Y(), bounds.Width(), bounds.Height());
594           Rect srcRect(0, 0, bounds.Width(), bounds.Height());
595 
596           gfx::Matrix rotate = ComputeTransformForUnRotation(
597               outerBounds.ToUnknownRect(), mTargetRotation);
598 
599           gfx::Matrix oldMatrix = dt->GetTransform();
600           dt->SetTransform(rotate * oldMatrix);
601           dt->DrawSurface(surf, dstRect, srcRect, DrawSurfaceOptions(),
602                           DrawOptions(1.0f, CompositionOp::OP_OVER));
603           dt->SetTransform(oldMatrix);
604         }
605         mForwarder->DestroySurfaceDescriptor(&outSnapshot);
606       }
607     }
608   }
609   mShadowTarget = nullptr;
610 }
611 
FlushRendering()612 void ClientLayerManager::FlushRendering() {
613   if (mWidget) {
614     if (CompositorBridgeChild* remoteRenderer = mWidget->GetRemoteRenderer()) {
615       if (mWidget->SynchronouslyRepaintOnResize() ||
616           gfxPrefs::LayersForceSynchronousResize()) {
617         remoteRenderer->SendFlushRendering();
618       } else {
619         remoteRenderer->SendFlushRenderingAsync();
620       }
621     }
622   }
623 }
624 
WaitOnTransactionProcessed()625 void ClientLayerManager::WaitOnTransactionProcessed() {
626   CompositorBridgeChild* remoteRenderer = GetCompositorBridgeChild();
627   if (remoteRenderer) {
628     remoteRenderer->SendWaitOnTransactionProcessed();
629   }
630 }
UpdateTextureFactoryIdentifier(const TextureFactoryIdentifier & aNewIdentifier)631 void ClientLayerManager::UpdateTextureFactoryIdentifier(
632     const TextureFactoryIdentifier& aNewIdentifier) {
633   mForwarder->IdentifyTextureHost(aNewIdentifier);
634 }
635 
SendInvalidRegion(const nsIntRegion & aRegion)636 void ClientLayerManager::SendInvalidRegion(const nsIntRegion& aRegion) {
637   if (mWidget) {
638     if (CompositorBridgeChild* remoteRenderer = mWidget->GetRemoteRenderer()) {
639       remoteRenderer->SendNotifyRegionInvalidated(aRegion);
640     }
641   }
642 }
643 
StartFrameTimeRecording(int32_t aBufferSize)644 uint32_t ClientLayerManager::StartFrameTimeRecording(int32_t aBufferSize) {
645   CompositorBridgeChild* renderer = GetRemoteRenderer();
646   if (renderer) {
647     uint32_t startIndex;
648     renderer->SendStartFrameTimeRecording(aBufferSize, &startIndex);
649     return startIndex;
650   }
651   return -1;
652 }
653 
StopFrameTimeRecording(uint32_t aStartIndex,nsTArray<float> & aFrameIntervals)654 void ClientLayerManager::StopFrameTimeRecording(
655     uint32_t aStartIndex, nsTArray<float>& aFrameIntervals) {
656   CompositorBridgeChild* renderer = GetRemoteRenderer();
657   if (renderer) {
658     renderer->SendStopFrameTimeRecording(aStartIndex, &aFrameIntervals);
659   }
660 }
661 
ForwardTransaction(bool aScheduleComposite)662 void ClientLayerManager::ForwardTransaction(bool aScheduleComposite) {
663   AUTO_PROFILER_TRACING("Paint", "ForwardTransaction");
664   TimeStamp start = TimeStamp::Now();
665 
666   // Skip the synchronization for buffer since we also skip the painting during
667   // device-reset status. With OMTP, we have to wait for async paints
668   // before we synchronize and it's done on the paint thread.
669   RefPtr<SyncObjectClient> syncObject = nullptr;
670   if (!gfxPlatform::GetPlatform()->DidRenderingDeviceReset()) {
671     if (mForwarder->GetSyncObject() &&
672         mForwarder->GetSyncObject()->IsSyncObjectValid()) {
673       syncObject = mForwarder->GetSyncObject();
674     }
675   }
676 
677   // If there were async paints queued, then we need to notify the paint thread
678   // that we finished queuing async paints so it can schedule a runnable after
679   // all async painting is finished to do a texture sync and unblock the main
680   // thread if it is waiting before doing a new layer transaction.
681   if (mQueuedAsyncPaints) {
682     MOZ_ASSERT(PaintThread::Get());
683     PaintThread::Get()->EndLayerTransaction(syncObject);
684   } else if (syncObject) {
685     syncObject->Synchronize();
686   }
687 
688   mPhase = PHASE_FORWARD;
689 
690   mLatestTransactionId =
691       mTransactionIdAllocator->GetTransactionId(!mIsRepeatTransaction);
692   TimeStamp transactionStart;
693   if (!mTransactionIdAllocator->GetTransactionStart().IsNull()) {
694     transactionStart = mTransactionIdAllocator->GetTransactionStart();
695   } else {
696     transactionStart = mTransactionStart;
697   }
698 
699   if (gfxPrefs::AlwaysPaint() && XRE_IsContentProcess()) {
700     mForwarder->SendPaintTime(mLatestTransactionId, mLastPaintTime);
701   }
702 
703   // forward this transaction's changeset to our LayerManagerComposite
704   bool sent = false;
705   bool ok = mForwarder->EndTransaction(
706       mRegionToClear, mLatestTransactionId, aScheduleComposite,
707       mPaintSequenceNumber, mIsRepeatTransaction, transactionStart, &sent);
708   if (ok) {
709     if (sent) {
710       mNeedsComposite = false;
711     }
712   } else if (HasShadowManager()) {
713     NS_WARNING("failed to forward Layers transaction");
714   }
715 
716   if (!sent) {
717     // Clear the transaction id so that it doesn't get returned
718     // unless we forwarded to somewhere that doesn't actually
719     // have a compositor.
720     mTransactionIdAllocator->RevokeTransactionId(mLatestTransactionId);
721   }
722 
723   mPhase = PHASE_NONE;
724 
725   // this may result in Layers being deleted, which results in
726   // PLayer::Send__delete__() and DeallocShmem()
727   mKeepAlive.Clear();
728 
729   TabChild* window = mWidget ? mWidget->GetOwningTabChild() : nullptr;
730   if (window) {
731     TimeStamp end = TimeStamp::Now();
732     window->DidRequestComposite(start, end);
733   }
734 }
735 
Hold(Layer * aLayer)736 ShadowableLayer* ClientLayerManager::Hold(Layer* aLayer) {
737   MOZ_ASSERT(HasShadowManager(), "top-level tree, no shadow tree to remote to");
738 
739   ShadowableLayer* shadowable = ClientLayer::ToClientLayer(aLayer);
740   MOZ_ASSERT(shadowable, "trying to remote an unshadowable layer");
741 
742   mKeepAlive.AppendElement(aLayer);
743   return shadowable;
744 }
745 
IsCompositingCheap()746 bool ClientLayerManager::IsCompositingCheap() {
747   // Whether compositing is cheap depends on the parent backend.
748   return mForwarder->mShadowManager &&
749          LayerManager::IsCompositingCheap(
750              mForwarder->GetCompositorBackendType());
751 }
752 
AreComponentAlphaLayersEnabled()753 bool ClientLayerManager::AreComponentAlphaLayersEnabled() {
754   return GetCompositorBackendType() != LayersBackend::LAYERS_BASIC &&
755          AsShadowForwarder()->SupportsComponentAlpha() &&
756          LayerManager::AreComponentAlphaLayersEnabled();
757 }
758 
SetIsFirstPaint()759 void ClientLayerManager::SetIsFirstPaint() { mForwarder->SetIsFirstPaint(); }
760 
SetFocusTarget(const FocusTarget & aFocusTarget)761 void ClientLayerManager::SetFocusTarget(const FocusTarget& aFocusTarget) {
762   mForwarder->SetFocusTarget(aFocusTarget);
763 }
764 
ClearCachedResources(Layer * aSubtree)765 void ClientLayerManager::ClearCachedResources(Layer* aSubtree) {
766   if (mDestroyed) {
767     // ClearCachedResource was already called by ClientLayerManager::Destroy
768     return;
769   }
770   MOZ_ASSERT(!HasShadowManager() || !aSubtree);
771   mForwarder->ClearCachedResources();
772   if (aSubtree) {
773     ClearLayer(aSubtree);
774   } else if (mRoot) {
775     ClearLayer(mRoot);
776   }
777 }
778 
HandleMemoryPressure()779 void ClientLayerManager::HandleMemoryPressure() {
780   if (mRoot) {
781     HandleMemoryPressureLayer(mRoot);
782   }
783 
784   if (GetCompositorBridgeChild()) {
785     GetCompositorBridgeChild()->HandleMemoryPressure();
786   }
787 }
788 
ClearLayer(Layer * aLayer)789 void ClientLayerManager::ClearLayer(Layer* aLayer) {
790   aLayer->ClearCachedResources();
791   for (Layer* child = aLayer->GetFirstChild(); child;
792        child = child->GetNextSibling()) {
793     ClearLayer(child);
794   }
795 }
796 
HandleMemoryPressureLayer(Layer * aLayer)797 void ClientLayerManager::HandleMemoryPressureLayer(Layer* aLayer) {
798   ClientLayer::ToClientLayer(aLayer)->HandleMemoryPressure();
799   for (Layer* child = aLayer->GetFirstChild(); child;
800        child = child->GetNextSibling()) {
801     HandleMemoryPressureLayer(child);
802   }
803 }
804 
GetBackendName(nsAString & aName)805 void ClientLayerManager::GetBackendName(nsAString& aName) {
806   switch (mForwarder->GetCompositorBackendType()) {
807     case LayersBackend::LAYERS_NONE:
808       aName.AssignLiteral("None");
809       return;
810     case LayersBackend::LAYERS_BASIC:
811       aName.AssignLiteral("Basic");
812       return;
813     case LayersBackend::LAYERS_OPENGL:
814       aName.AssignLiteral("OpenGL");
815       return;
816     case LayersBackend::LAYERS_D3D11: {
817 #ifdef XP_WIN
818       if (DeviceManagerDx::Get()->IsWARP()) {
819         aName.AssignLiteral("Direct3D 11 WARP");
820       } else {
821         aName.AssignLiteral("Direct3D 11");
822       }
823 #endif
824       return;
825     }
826     default:
827       MOZ_CRASH("Invalid backend");
828   }
829 }
830 
AsyncPanZoomEnabled() const831 bool ClientLayerManager::AsyncPanZoomEnabled() const {
832   return mWidget && mWidget->AsyncPanZoomEnabled();
833 }
834 
SetLayerObserverEpoch(uint64_t aLayerObserverEpoch)835 void ClientLayerManager::SetLayerObserverEpoch(uint64_t aLayerObserverEpoch) {
836   mForwarder->SetLayerObserverEpoch(aLayerObserverEpoch);
837 }
838 
AddDidCompositeObserver(DidCompositeObserver * aObserver)839 void ClientLayerManager::AddDidCompositeObserver(
840     DidCompositeObserver* aObserver) {
841   if (!mDidCompositeObservers.Contains(aObserver)) {
842     mDidCompositeObservers.AppendElement(aObserver);
843   }
844 }
845 
RemoveDidCompositeObserver(DidCompositeObserver * aObserver)846 void ClientLayerManager::RemoveDidCompositeObserver(
847     DidCompositeObserver* aObserver) {
848   mDidCompositeObservers.RemoveElement(aObserver);
849 }
850 
851 already_AddRefed<PersistentBufferProvider>
CreatePersistentBufferProvider(const gfx::IntSize & aSize,gfx::SurfaceFormat aFormat)852 ClientLayerManager::CreatePersistentBufferProvider(const gfx::IntSize& aSize,
853                                                    gfx::SurfaceFormat aFormat) {
854   // Don't use a shared buffer provider if compositing is considered "not cheap"
855   // because the canvas will most likely be flattened into a thebes layer
856   // instead of being sent to the compositor, in which case rendering into
857   // shared memory is wasteful.
858   if (IsCompositingCheap() &&
859       gfxPrefs::PersistentBufferProviderSharedEnabled()) {
860     RefPtr<PersistentBufferProvider> provider =
861         PersistentBufferProviderShared::Create(aSize, aFormat,
862                                                AsShadowForwarder());
863     if (provider) {
864       return provider.forget();
865     }
866   }
867 
868   return LayerManager::CreatePersistentBufferProvider(aSize, aFormat);
869 }
870 
~ClientLayer()871 ClientLayer::~ClientLayer() { MOZ_COUNT_DTOR(ClientLayer); }
872 
873 }  // namespace layers
874 }  // namespace mozilla
875