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(¤tConfig);
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