1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "ClientLayerManager.h"
8 #include "GeckoProfiler.h" // for AUTO_PROFILER_LABEL
9 #include "gfxEnv.h" // for gfxEnv
10 #include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
11 #include "mozilla/Hal.h"
12 #include "mozilla/StaticPrefs_apz.h"
13 #include "mozilla/StaticPrefs_gfx.h"
14 #include "mozilla/StaticPrefs_layers.h"
15 #include "mozilla/dom/BrowserChild.h" // for BrowserChild
16 #include "mozilla/hal_sandbox/PHal.h" // for ScreenConfiguration
17 #include "mozilla/layers/CompositableClient.h"
18 #include "mozilla/layers/CompositorBridgeChild.h" // for CompositorBridgeChild
19 #include "mozilla/layers/FrameUniformityData.h"
20 #include "mozilla/layers/ISurfaceAllocator.h"
21 #include "mozilla/layers/LayersMessages.h" // for EditReply, etc
22 #include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor
23 #include "mozilla/layers/LayerTransactionChild.h"
24 #include "mozilla/layers/PersistentBufferProvider.h"
25 #include "mozilla/layers/SyncObject.h"
26 #include "mozilla/PerfStats.h"
27 #include "ClientReadbackLayer.h" // for ClientReadbackLayer
28 #include "nsAString.h"
29 #include "nsDisplayList.h"
30 #include "nsIWidgetListener.h"
31 #include "nsTArray.h" // for AutoTArray
32 #include "nsXULAppAPI.h" // for XRE_GetProcessType, etc
33 #include "TiledLayerBuffer.h"
34 #include "FrameLayerBuilder.h" // for FrameLayerbuilder
35 #ifdef MOZ_WIDGET_ANDROID
36 # include "AndroidBridge.h"
37 # include "LayerMetricsWrapper.h"
40 # include "mozilla/gfx/DeviceManagerDx.h"
41 # include "gfxDWriteFonts.h"
47 using namespace mozilla::gfx
;
49 ClientLayerManager::ClientLayerManager(nsIWidget
* aWidget
)
52 mPaintedLayerCallback(nullptr),
53 mPaintedLayerCallbackData(nullptr),
54 mLatestTransactionId
{0},
55 mLastPaintTime(TimeDuration::Forever()),
56 mTargetRotation(ROTATION_0
),
57 mRepeatTransaction(false),
58 mIsRepeatTransaction(false),
59 mTransactionIncomplete(false),
60 mCompositorMightResample(false),
61 mNeedsComposite(false),
62 mQueuedAsyncPaints(false),
63 mNotifyingWidgetListener(false),
64 mPaintSequenceNumber(0),
65 mForwarder(new ShadowLayerForwarder(this)) {
66 MOZ_COUNT_CTOR(ClientLayerManager
);
67 mMemoryPressureObserver
= MemoryPressureObserver::Create(this);
70 ClientLayerManager::~ClientLayerManager() {
71 mMemoryPressureObserver
->Unregister();
72 ClearCachedResources();
73 // Stop receiveing AsyncParentMessage at Forwarder.
74 // After the call, the message is directly handled by LayerTransactionChild.
75 // Basically this function should be called in ShadowLayerForwarder's
76 // destructor. But when the destructor is triggered by
77 // CompositorBridgeChild::Destroy(), the destructor can not handle it
78 // correctly. See Bug 1000525.
79 mForwarder
->StopReceiveAsyncParentMessge();
82 MOZ_COUNT_DTOR(ClientLayerManager
);
85 bool ClientLayerManager::Initialize(
86 PCompositorBridgeChild
* aCBChild
, bool aShouldAccelerate
,
87 TextureFactoryIdentifier
* aTextureFactoryIdentifier
) {
88 MOZ_ASSERT(mForwarder
);
89 MOZ_ASSERT(aTextureFactoryIdentifier
);
91 nsTArray
<LayersBackend
> backendHints
;
92 gfxPlatform::GetPlatform()->GetCompositorBackends(aShouldAccelerate
,
94 if (backendHints
.IsEmpty()) {
95 gfxCriticalNote
<< "Failed to get backend hints.";
99 PLayerTransactionChild
* shadowManager
=
100 aCBChild
->SendPLayerTransactionConstructor(backendHints
, LayersId
{0});
102 TextureFactoryIdentifier textureFactoryIdentifier
;
103 shadowManager
->SendGetTextureFactoryIdentifier(&textureFactoryIdentifier
);
104 if (textureFactoryIdentifier
.mParentBackend
== LayersBackend::LAYERS_NONE
) {
105 gfxCriticalNote
<< "Failed to create an OMT compositor.";
109 mForwarder
->SetShadowManager(shadowManager
);
110 UpdateTextureFactoryIdentifier(textureFactoryIdentifier
);
111 *aTextureFactoryIdentifier
= textureFactoryIdentifier
;
115 void ClientLayerManager::Destroy() {
116 MOZ_DIAGNOSTIC_ASSERT(!mNotifyingWidgetListener
,
117 "Try to avoid destroying widgets and layer managers "
118 "during DidCompositeWindow, if you can");
120 // It's important to call ClearCachedResource before Destroy because the
121 // former will early-return if the later has already run.
122 ClearCachedResources();
123 LayerManager::Destroy();
125 if (mTransactionIdAllocator
) {
126 // Make sure to notify the refresh driver just in case it's waiting on a
127 // pending transaction. Do this at the top of the event loop so we don't
128 // cause a paint to occur during compositor shutdown.
129 RefPtr
<TransactionIdAllocator
> allocator
= mTransactionIdAllocator
;
130 TransactionId id
= mLatestTransactionId
;
132 RefPtr
<Runnable
> task
= NS_NewRunnableFunction(
133 "TransactionIdAllocator::NotifyTransactionCompleted",
134 [allocator
, id
]() -> void {
135 allocator
->NotifyTransactionCompleted(id
);
137 NS_DispatchToMainThread(task
.forget());
140 // Forget the widget pointer in case we outlive our owning widget.
144 int32_t ClientLayerManager::GetMaxTextureSize() const {
145 return mForwarder
->GetMaxTextureSize();
148 void ClientLayerManager::SetDefaultTargetConfiguration(
149 BufferMode aDoubleBuffering
, ScreenRotation aRotation
) {
150 mTargetRotation
= aRotation
;
153 void ClientLayerManager::SetRoot(Layer
* aLayer
) {
154 if (mRoot
!= aLayer
) {
155 // Have to hold the old root and its children in order to
156 // maintain the same view of the layer tree in this process as
157 // the parent sees. Otherwise layers can be destroyed
158 // mid-transaction and bad things can happen (v. bug 612573)
162 mForwarder
->SetRoot(Hold(aLayer
));
163 NS_ASSERTION(aLayer
, "Root can't be null");
164 NS_ASSERTION(aLayer
->Manager() == this, "Wrong manager");
165 NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
170 void ClientLayerManager::Mutated(Layer
* aLayer
) {
171 LayerManager::Mutated(aLayer
);
173 NS_ASSERTION(InConstruction() || InDrawing(), "wrong phase");
174 mForwarder
->Mutated(Hold(aLayer
));
177 void ClientLayerManager::MutatedSimple(Layer
* aLayer
) {
178 LayerManager::MutatedSimple(aLayer
);
180 NS_ASSERTION(InConstruction() || InDrawing(), "wrong phase");
181 mForwarder
->MutatedSimple(Hold(aLayer
));
184 already_AddRefed
<ReadbackLayer
> ClientLayerManager::CreateReadbackLayer() {
185 RefPtr
<ReadbackLayer
> layer
= new ClientReadbackLayer(this);
186 return layer
.forget();
189 bool ClientLayerManager::BeginTransactionWithTarget(gfxContext
* aTarget
,
190 const nsCString
& aURL
) {
191 #ifdef MOZ_DUMP_PAINTING
192 // When we are dump painting, we expect to be able to read the contents of
193 // compositable clients from previous paints inside this layer transaction
194 // before we flush async paints in EndTransactionInternal.
195 // So to work around this flush async paints now.
196 if (gfxEnv::DumpPaint()) {
201 MOZ_ASSERT(mForwarder
,
202 "ClientLayerManager::BeginTransaction without forwarder");
203 if (!mForwarder
->IPCOpen()) {
204 gfxCriticalNote
<< "ClientLayerManager::BeginTransaction with IPC channel "
205 "down. GPU process may have died.";
209 mInTransaction
= true;
210 mTransactionStart
= TimeStamp::Now();
213 #ifdef MOZ_LAYERS_HAVE_LOG
214 MOZ_LAYERS_LOG(("[----- BeginTransaction"));
218 NS_ASSERTION(!InTransaction(), "Nested transactions not allowed");
219 mPhase
= PHASE_CONSTRUCTION
;
221 MOZ_ASSERT(mKeepAlive
.IsEmpty(), "uncommitted txn?");
223 // If the last transaction was incomplete (a failed DoEmptyTransaction),
224 // don't signal a new transaction to ShadowLayerForwarder. Carry on adding
225 // to the previous transaction.
226 hal::ScreenOrientation orientation
;
227 if (dom::BrowserChild
* window
= mWidget
->GetOwningBrowserChild()) {
228 orientation
= window
->GetOrientation();
230 hal::ScreenConfiguration currentConfig
;
231 hal::GetCurrentScreenConfiguration(¤tConfig
);
232 orientation
= currentConfig
.orientation();
234 LayoutDeviceIntRect targetBounds
= mWidget
->GetNaturalBounds();
235 targetBounds
.MoveTo(0, 0);
236 mForwarder
->BeginTransaction(targetBounds
.ToUnknownRect(), mTargetRotation
,
239 // If we're drawing on behalf of a context with async pan/zoom
240 // enabled, then the entire buffer of painted layers might be
241 // composited (including resampling) asynchronously before we get
242 // a chance to repaint, so we have to ensure that it's all valid
245 // Desktop does not support async zoom yet, so we ignore this for those
247 #if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_UIKIT)
248 if (mWidget
&& mWidget
->GetOwningBrowserChild()) {
249 mCompositorMightResample
= AsyncPanZoomEnabled();
253 // If we have a non-default target, we need to let our shadow manager draw
254 // to it. This will happen at the end of the transaction.
255 if (aTarget
&& XRE_IsParentProcess()) {
256 mShadowTarget
= aTarget
;
260 "Content-process ClientLayerManager::BeginTransactionWithTarget not "
264 // If this is a new paint, increment the paint sequence number.
265 if (!mIsRepeatTransaction
) {
266 // Increment the paint sequence number even if test logging isn't
267 // enabled in this process; it may be enabled in the parent process,
268 // and the parent process expects unique sequence numbers.
269 ++mPaintSequenceNumber
;
270 if (StaticPrefs::apz_test_logging_enabled()) {
271 mApzTestData
.StartNewPaint(mPaintSequenceNumber
);
277 bool ClientLayerManager::BeginTransaction(const nsCString
& aURL
) {
278 return BeginTransactionWithTarget(nullptr, aURL
);
281 bool ClientLayerManager::EndTransactionInternal(
282 DrawPaintedLayerCallback aCallback
, void* aCallbackData
,
283 EndTransactionFlags
) {
284 // This just causes the compositor to check whether the GPU is done with its
285 // textures or not and unlock them if it is. This helps us avoid the case
286 // where we take a long time painting asynchronously, turn IPC back on at
287 // the end of that, and then have to wait for the compositor to to get into
288 // TiledLayerBufferComposite::UseTiles before getting a response.
290 mForwarder
->UpdateTextureLocks();
293 // Wait for any previous async paints to complete before starting to paint
294 // again. Do this outside the profiler and telemetry block so this doesn't
295 // count as time spent rasterizing.
297 PaintTelemetry::AutoRecord
record(
298 PaintTelemetry::Metric::FlushRasterization
);
302 PaintTelemetry::AutoRecord
record(PaintTelemetry::Metric::Rasterization
);
303 AUTO_PROFILER_TRACING_MARKER("Paint", "Rasterize", GRAPHICS
);
304 PerfStats::AutoMetricRecording
<PerfStats::Metric::Rasterizing
> autoRecording
;
306 Maybe
<TimeStamp
> startTime
;
307 if (StaticPrefs::layers_acceleration_draw_fps()) {
308 startTime
= Some(TimeStamp::Now());
311 AUTO_PROFILER_LABEL("ClientLayerManager::EndTransactionInternal", GRAPHICS
);
313 #ifdef MOZ_LAYERS_HAVE_LOG
314 MOZ_LAYERS_LOG((" ----- (beginning paint)"));
318 NS_ASSERTION(InConstruction(), "Should be in construction phase");
319 mPhase
= PHASE_DRAWING
;
321 ClientLayer
* root
= ClientLayer::ToClientLayer(GetRoot());
323 mTransactionIncomplete
= false;
324 mQueuedAsyncPaints
= false;
326 // Apply pending tree updates before recomputing effective
328 auto scrollIdsUpdated
= GetRoot()->ApplyPendingUpdatesToSubtree();
330 mPaintedLayerCallback
= aCallback
;
331 mPaintedLayerCallbackData
= aCallbackData
;
333 GetRoot()->ComputeEffectiveTransforms(Matrix4x4());
335 // Skip the painting if the device is in device-reset status.
336 if (!gfxPlatform::GetPlatform()->DidRenderingDeviceReset()) {
337 if (StaticPrefs::gfx_content_always_paint() && XRE_IsContentProcess()) {
338 TimeStamp start
= TimeStamp::Now();
340 mLastPaintTime
= TimeStamp::Now() - start
;
345 gfxCriticalNote
<< "LayerManager::EndTransaction skip RenderLayer().";
348 // Once we're sure we're not going to fall back to a full paint,
349 // notify the scroll frames which had pending updates.
350 if (!mTransactionIncomplete
) {
351 for (ScrollableLayerGuid::ViewID scrollId
: scrollIdsUpdated
) {
352 nsLayoutUtils::NotifyPaintSkipTransaction(scrollId
);
356 if (!mRepeatTransaction
&& !GetRoot()->GetInvalidRegion().IsEmpty()) {
357 GetRoot()->Mutated();
360 if (!mIsRepeatTransaction
) {
361 mAnimationReadyTime
= TimeStamp::Now();
362 GetRoot()->StartPendingAnimations(mAnimationReadyTime
);
365 mPaintedLayerCallback
= nullptr;
366 mPaintedLayerCallbackData
= nullptr;
368 // Go back to the construction phase if the transaction isn't complete.
369 // Layout will update the layer tree and call EndTransaction().
370 mPhase
= mTransactionIncomplete
? PHASE_CONSTRUCTION
: PHASE_NONE
;
372 NS_ASSERTION(!aCallback
|| !mTransactionIncomplete
,
373 "If callback is not null, transaction must be complete");
375 if (gfxPlatform::GetPlatform()->DidRenderingDeviceReset()) {
376 FrameLayerBuilder::InvalidateAllLayers(this);
380 PaintTiming
& pt
= mForwarder
->GetPaintTiming();
381 pt
.rasterMs() = (TimeStamp::Now() - startTime
.value()).ToMilliseconds();
384 return !mTransactionIncomplete
;
387 void ClientLayerManager::StorePluginWidgetConfigurations(
388 const nsTArray
<nsIWidget::Configuration
>& aConfigurations
) {
390 mForwarder
->StorePluginWidgetConfigurations(aConfigurations
);
394 void ClientLayerManager::EndTransaction(DrawPaintedLayerCallback aCallback
,
396 EndTransactionFlags aFlags
) {
397 if (!mForwarder
->IPCOpen()) {
398 mInTransaction
= false;
403 mWidget
->PrepareWindowEffects();
405 EndTransactionInternal(aCallback
, aCallbackData
, aFlags
);
406 if (XRE_IsContentProcess()) {
407 RegisterPayload({CompositionPayloadType::eContentPaint
, TimeStamp::Now()});
409 ForwardTransaction(!(aFlags
& END_NO_REMOTE_COMPOSITE
));
411 if (mRepeatTransaction
) {
412 mRepeatTransaction
= false;
413 mIsRepeatTransaction
= true;
415 // BeginTransaction will reset the transaction start time, but we
416 // would like to keep the original time for telemetry purposes.
417 TimeStamp transactionStart
= mTransactionStart
;
418 if (BeginTransaction(mURL
)) {
419 mTransactionStart
= transactionStart
;
420 ClientLayerManager::EndTransaction(aCallback
, aCallbackData
, aFlags
);
423 mIsRepeatTransaction
= false;
425 MakeSnapshotIfRequired();
428 mInTransaction
= false;
429 mTransactionStart
= TimeStamp();
432 bool ClientLayerManager::EndEmptyTransaction(EndTransactionFlags aFlags
) {
433 mInTransaction
= false;
435 if (!mRoot
|| !mForwarder
->IPCOpen()) {
439 if (!EndTransactionInternal(nullptr, nullptr, aFlags
)) {
440 // Return without calling ForwardTransaction. This leaves the
441 // ShadowLayerForwarder transaction open; the following
442 // EndTransaction will complete it.
443 if (PaintThread::Get() && mQueuedAsyncPaints
) {
444 PaintThread::Get()->QueueEndLayerTransaction(nullptr);
449 mWidget
->PrepareWindowEffects();
451 ForwardTransaction(!(aFlags
& END_NO_REMOTE_COMPOSITE
));
452 MakeSnapshotIfRequired();
456 CompositorBridgeChild
* ClientLayerManager::GetRemoteRenderer() {
461 return mWidget
->GetRemoteRenderer();
464 CompositorBridgeChild
* ClientLayerManager::GetCompositorBridgeChild() {
465 if (!XRE_IsParentProcess()) {
466 return CompositorBridgeChild::Get();
468 return GetRemoteRenderer();
471 void ClientLayerManager::FlushAsyncPaints() {
472 AUTO_PROFILER_LABEL_CATEGORY_PAIR(GRAPHICS_FlushingAsyncPaints
);
474 CompositorBridgeChild
* cbc
= GetCompositorBridgeChild();
476 cbc
->FlushAsyncPaints();
480 void ClientLayerManager::ScheduleComposite() {
481 mForwarder
->ScheduleComposite();
484 void ClientLayerManager::DidComposite(TransactionId aTransactionId
,
485 const TimeStamp
& aCompositeStart
,
486 const TimeStamp
& aCompositeEnd
) {
491 // Notifying the observers may tick the refresh driver which can cause
492 // a lot of different things to happen that may affect the lifetime of
493 // this layer manager. So let's make sure this object stays alive until
494 // the end of the method invocation.
495 RefPtr
<ClientLayerManager
> selfRef
= this;
497 // |aTransactionId| will be > 0 if the compositor is acknowledging a shadow
498 // layers transaction.
499 if (aTransactionId
.IsValid()) {
500 nsIWidgetListener
* listener
= mWidget
->GetWidgetListener();
502 mNotifyingWidgetListener
= true;
503 listener
->DidCompositeWindow(aTransactionId
, aCompositeStart
,
505 mNotifyingWidgetListener
= false;
507 // DidCompositeWindow might have called Destroy on us and nulled out
508 // mWidget, see bug 1510058. Re-check it here.
510 listener
= mWidget
->GetAttachedWidgetListener();
512 listener
->DidCompositeWindow(aTransactionId
, aCompositeStart
,
516 if (mTransactionIdAllocator
) {
517 mTransactionIdAllocator
->NotifyTransactionCompleted(aTransactionId
);
521 // These observers fire whether or not we were in a transaction.
522 for (size_t i
= 0; i
< mDidCompositeObservers
.Length(); i
++) {
523 mDidCompositeObservers
[i
]->DidComposite();
527 void ClientLayerManager::GetCompositorSideAPZTestData(
528 APZTestData
* aData
) const {
529 if (mForwarder
->HasShadowManager()) {
530 if (!mForwarder
->GetShadowManager()->SendGetAPZTestData(aData
)) {
531 NS_WARNING("Call to PLayerTransactionChild::SendGetAPZTestData() failed");
536 void ClientLayerManager::SetTransactionIdAllocator(
537 TransactionIdAllocator
* aAllocator
) {
538 // When changing the refresh driver, the previous refresh driver may never
539 // receive updates of pending transactions it's waiting for. So clear the
540 // waiting state before assigning another refresh driver.
541 if (mTransactionIdAllocator
&& (aAllocator
!= mTransactionIdAllocator
)) {
542 mTransactionIdAllocator
->ClearPendingTransactions();
544 // We should also reset the transaction id of the new allocator to previous
545 // allocator's last transaction id, so that completed transactions for
546 // previous allocator will be ignored and won't confuse the new allocator.
548 aAllocator
->ResetInitialTransactionId(
549 mTransactionIdAllocator
->LastTransactionId());
553 mTransactionIdAllocator
= aAllocator
;
556 float ClientLayerManager::RequestProperty(const nsAString
& aProperty
) {
557 if (mForwarder
->HasShadowManager()) {
559 if (!mForwarder
->GetShadowManager()->SendRequestProperty(
560 nsString(aProperty
), &value
)) {
561 NS_WARNING("Call to PLayerTransactionChild::SendGetAPZTestData() failed");
568 void ClientLayerManager::StartNewRepaintRequest(
569 SequenceNumber aSequenceNumber
) {
570 if (StaticPrefs::apz_test_logging_enabled()) {
571 mApzTestData
.StartNewRepaintRequest(aSequenceNumber
);
575 void ClientLayerManager::GetFrameUniformity(FrameUniformityData
* aOutData
) {
576 MOZ_ASSERT(XRE_IsParentProcess(),
577 "Frame Uniformity only supported in parent process");
579 if (HasShadowManager()) {
580 CompositorBridgeChild
* child
= GetRemoteRenderer();
581 child
->SendGetFrameUniformity(aOutData
);
585 return LayerManager::GetFrameUniformity(aOutData
);
588 void ClientLayerManager::MakeSnapshotIfRequired() {
589 if (!mShadowTarget
) {
593 if (CompositorBridgeChild
* remoteRenderer
= GetRemoteRenderer()) {
594 // The compositor doesn't draw to a different sized surface
595 // when there's a rotation. Instead we rotate the result
596 // when drawing into dt
597 LayoutDeviceIntRect outerBounds
= mWidget
->GetBounds();
599 IntRect bounds
= ToOutsideIntRect(mShadowTarget
->GetClipExtents());
600 if (mTargetRotation
) {
602 RotateRect(bounds
, outerBounds
.ToUnknownRect(), mTargetRotation
);
605 SurfaceDescriptor inSnapshot
;
606 if (!bounds
.IsEmpty() &&
607 mForwarder
->AllocSurfaceDescriptor(
608 bounds
.Size(), gfxContentType::COLOR_ALPHA
, &inSnapshot
)) {
609 // Make a copy of |inSnapshot| because the call to send it over IPC
610 // will call forget() on the Shmem inside, and zero it out.
611 SurfaceDescriptor outSnapshot
= inSnapshot
;
613 if (remoteRenderer
->SendMakeSnapshot(inSnapshot
, bounds
)) {
614 RefPtr
<DataSourceSurface
> surf
= GetSurfaceForDescriptor(outSnapshot
);
615 DrawTarget
* dt
= mShadowTarget
->GetDrawTarget();
617 Rect
dstRect(bounds
.X(), bounds
.Y(), bounds
.Width(), bounds
.Height());
618 Rect
srcRect(0, 0, bounds
.Width(), bounds
.Height());
620 gfx::Matrix rotate
= ComputeTransformForUnRotation(
621 outerBounds
.ToUnknownRect(), mTargetRotation
);
623 gfx::Matrix oldMatrix
= dt
->GetTransform();
624 dt
->SetTransform(rotate
* oldMatrix
);
625 dt
->DrawSurface(surf
, dstRect
, srcRect
, DrawSurfaceOptions(),
626 DrawOptions(1.0f
, CompositionOp::OP_OVER
));
627 dt
->SetTransform(oldMatrix
);
629 mForwarder
->DestroySurfaceDescriptor(&outSnapshot
);
633 mShadowTarget
= nullptr;
636 void ClientLayerManager::FlushRendering() {
638 if (CompositorBridgeChild
* remoteRenderer
= mWidget
->GetRemoteRenderer()) {
639 if (mWidget
->SynchronouslyRepaintOnResize() ||
640 StaticPrefs::layers_force_synchronous_resize()) {
641 remoteRenderer
->SendFlushRendering();
643 remoteRenderer
->SendFlushRenderingAsync();
649 void ClientLayerManager::WaitOnTransactionProcessed() {
650 CompositorBridgeChild
* remoteRenderer
= GetCompositorBridgeChild();
651 if (remoteRenderer
) {
652 remoteRenderer
->SendWaitOnTransactionProcessed();
655 void ClientLayerManager::UpdateTextureFactoryIdentifier(
656 const TextureFactoryIdentifier
& aNewIdentifier
) {
657 mForwarder
->IdentifyTextureHost(aNewIdentifier
);
660 void ClientLayerManager::SendInvalidRegion(const nsIntRegion
& aRegion
) {
662 if (CompositorBridgeChild
* remoteRenderer
= mWidget
->GetRemoteRenderer()) {
663 remoteRenderer
->SendNotifyRegionInvalidated(aRegion
);
668 uint32_t ClientLayerManager::StartFrameTimeRecording(int32_t aBufferSize
) {
669 CompositorBridgeChild
* renderer
= GetRemoteRenderer();
672 renderer
->SendStartFrameTimeRecording(aBufferSize
, &startIndex
);
678 void ClientLayerManager::StopFrameTimeRecording(
679 uint32_t aStartIndex
, nsTArray
<float>& aFrameIntervals
) {
680 CompositorBridgeChild
* renderer
= GetRemoteRenderer();
682 renderer
->SendStopFrameTimeRecording(aStartIndex
, &aFrameIntervals
);
686 void ClientLayerManager::ForwardTransaction(bool aScheduleComposite
) {
687 AUTO_PROFILER_TRACING_MARKER("Paint", "ForwardTransaction", GRAPHICS
);
688 TimeStamp start
= TimeStamp::Now();
690 GetCompositorBridgeChild()->EndCanvasTransaction();
692 // Skip the synchronization for buffer since we also skip the painting during
693 // device-reset status. With OMTP, we have to wait for async paints
694 // before we synchronize and it's done on the paint thread.
695 RefPtr
<SyncObjectClient
> syncObject
= nullptr;
696 if (!gfxPlatform::GetPlatform()->DidRenderingDeviceReset()) {
697 if (mForwarder
->GetSyncObject() &&
698 mForwarder
->GetSyncObject()->IsSyncObjectValid()) {
699 syncObject
= mForwarder
->GetSyncObject();
703 // If there were async paints queued, then we need to notify the paint thread
704 // that we finished queuing async paints so it can schedule a runnable after
705 // all async painting is finished to do a texture sync and unblock the main
706 // thread if it is waiting before doing a new layer transaction.
707 if (mQueuedAsyncPaints
) {
708 MOZ_ASSERT(PaintThread::Get());
709 PaintThread::Get()->QueueEndLayerTransaction(syncObject
);
710 } else if (syncObject
) {
711 syncObject
->Synchronize();
714 mPhase
= PHASE_FORWARD
;
716 mLatestTransactionId
=
717 mTransactionIdAllocator
->GetTransactionId(!mIsRepeatTransaction
);
718 TimeStamp refreshStart
= mTransactionIdAllocator
->GetTransactionStart();
720 refreshStart
= mTransactionStart
;
723 if (StaticPrefs::gfx_content_always_paint() && XRE_IsContentProcess()) {
724 mForwarder
->SendPaintTime(mLatestTransactionId
, mLastPaintTime
);
727 // forward this transaction's changeset to our LayerManagerComposite
729 bool ok
= mForwarder
->EndTransaction(
730 mRegionToClear
, mLatestTransactionId
, aScheduleComposite
,
731 mPaintSequenceNumber
, mIsRepeatTransaction
,
732 mTransactionIdAllocator
->GetVsyncId(),
733 mTransactionIdAllocator
->GetVsyncStart(), refreshStart
, mTransactionStart
,
734 mContainsSVG
, mURL
, &sent
, mPayload
);
738 // Our payload has now been dispatched.
740 mNeedsComposite
= false;
742 } else if (HasShadowManager()) {
743 NS_WARNING("failed to forward Layers transaction");
747 // Clear the transaction id so that it doesn't get returned
748 // unless we forwarded to somewhere that doesn't actually
749 // have a compositor.
750 mTransactionIdAllocator
->RevokeTransactionId(mLatestTransactionId
);
751 mLatestTransactionId
= mLatestTransactionId
.Prev();
756 // this may result in Layers being deleted, which results in
757 // PLayer::Send__delete__() and DeallocShmem()
760 BrowserChild
* window
= mWidget
? mWidget
->GetOwningBrowserChild() : nullptr;
762 TimeStamp end
= TimeStamp::Now();
763 window
->DidRequestComposite(start
, end
);
767 ShadowableLayer
* ClientLayerManager::Hold(Layer
* aLayer
) {
768 MOZ_ASSERT(HasShadowManager(), "top-level tree, no shadow tree to remote to");
770 ShadowableLayer
* shadowable
= ClientLayer::ToClientLayer(aLayer
);
771 MOZ_ASSERT(shadowable
, "trying to remote an unshadowable layer");
773 mKeepAlive
.AppendElement(aLayer
);
777 bool ClientLayerManager::IsCompositingCheap() {
778 // Whether compositing is cheap depends on the parent backend.
779 return mForwarder
->mShadowManager
&&
780 LayerManager::IsCompositingCheap(
781 mForwarder
->GetCompositorBackendType());
784 bool ClientLayerManager::AreComponentAlphaLayersEnabled() {
785 return GetCompositorBackendType() != LayersBackend::LAYERS_BASIC
&&
786 AsShadowForwarder()->SupportsComponentAlpha() &&
787 LayerManager::AreComponentAlphaLayersEnabled();
790 void ClientLayerManager::SetIsFirstPaint() { mForwarder
->SetIsFirstPaint(); }
792 void ClientLayerManager::SetFocusTarget(const FocusTarget
& aFocusTarget
) {
793 mForwarder
->SetFocusTarget(aFocusTarget
);
796 void ClientLayerManager::ClearCachedResources(Layer
* aSubtree
) {
798 // ClearCachedResource was already called by ClientLayerManager::Destroy
801 MOZ_ASSERT(!HasShadowManager() || !aSubtree
);
802 mForwarder
->ClearCachedResources();
804 ClearLayer(aSubtree
);
810 void ClientLayerManager::OnMemoryPressure(MemoryPressureReason aWhy
) {
812 HandleMemoryPressureLayer(mRoot
);
815 if (GetCompositorBridgeChild()) {
816 GetCompositorBridgeChild()->HandleMemoryPressure();
820 void ClientLayerManager::ClearLayer(Layer
* aLayer
) {
821 aLayer
->ClearCachedResources();
822 for (Layer
* child
= aLayer
->GetFirstChild(); child
;
823 child
= child
->GetNextSibling()) {
828 void ClientLayerManager::HandleMemoryPressureLayer(Layer
* aLayer
) {
829 ClientLayer::ToClientLayer(aLayer
)->HandleMemoryPressure();
830 for (Layer
* child
= aLayer
->GetFirstChild(); child
;
831 child
= child
->GetNextSibling()) {
832 HandleMemoryPressureLayer(child
);
836 void ClientLayerManager::GetBackendName(nsAString
& aName
) {
837 switch (mForwarder
->GetCompositorBackendType()) {
838 case LayersBackend::LAYERS_NONE
:
839 aName
.AssignLiteral("None");
841 case LayersBackend::LAYERS_BASIC
:
842 aName
.AssignLiteral("Basic");
844 case LayersBackend::LAYERS_OPENGL
:
845 aName
.AssignLiteral("OpenGL");
847 case LayersBackend::LAYERS_D3D11
: {
849 if (DeviceManagerDx::Get()->IsWARP()) {
850 aName
.AssignLiteral("Direct3D 11 WARP");
852 aName
.AssignLiteral("Direct3D 11");
858 MOZ_CRASH("Invalid backend");
862 bool ClientLayerManager::AsyncPanZoomEnabled() const {
863 return mWidget
&& mWidget
->AsyncPanZoomEnabled();
866 void ClientLayerManager::SetLayersObserverEpoch(LayersObserverEpoch aEpoch
) {
867 mForwarder
->SetLayersObserverEpoch(aEpoch
);
870 void ClientLayerManager::AddDidCompositeObserver(
871 DidCompositeObserver
* aObserver
) {
872 if (!mDidCompositeObservers
.Contains(aObserver
)) {
873 mDidCompositeObservers
.AppendElement(aObserver
);
877 void ClientLayerManager::RemoveDidCompositeObserver(
878 DidCompositeObserver
* aObserver
) {
879 mDidCompositeObservers
.RemoveElement(aObserver
);
882 already_AddRefed
<PersistentBufferProvider
>
883 ClientLayerManager::CreatePersistentBufferProvider(const gfx::IntSize
& aSize
,
884 gfx::SurfaceFormat aFormat
) {
885 // Don't use a shared buffer provider if compositing is considered "not cheap"
886 // because the canvas will most likely be flattened into a thebes layer
887 // instead of being sent to the compositor, in which case rendering into
888 // shared memory is wasteful.
889 if (IsCompositingCheap()) {
890 RefPtr
<PersistentBufferProvider
> provider
=
891 PersistentBufferProviderShared::Create(aSize
, aFormat
,
892 AsShadowForwarder());
894 return provider
.forget();
898 return LayerManager::CreatePersistentBufferProvider(aSize
, aFormat
);
901 ClientLayer::~ClientLayer() { MOZ_COUNT_DTOR(ClientLayer
); }
903 } // namespace layers
904 } // namespace mozilla