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