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