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 "LayerTransactionParent.h"
8 #include <vector>                           // for vector
9 #include "CompositableHost.h"               // for CompositableParent, Get, etc
10 #include "ImageLayers.h"                    // for ImageLayer
11 #include "Layers.h"                         // for Layer, ContainerLayer, etc
12 #include "CompositableTransactionParent.h"  // for EditReplyVector
13 #include "CompositorBridgeParent.h"
14 #include "mozilla/gfx/BasePoint3D.h"         // for BasePoint3D
15 #include "mozilla/layers/AnimationHelper.h"  // for GetAnimatedPropValue
16 #include "mozilla/layers/CanvasLayerComposite.h"
17 #include "mozilla/layers/ColorLayerComposite.h"
18 #include "mozilla/layers/Compositor.h"                  // for Compositor
19 #include "mozilla/layers/CompositorAnimationStorage.h"  // for CompositorAnimationStorage
20 #include "mozilla/layers/ContainerLayerComposite.h"
21 #include "mozilla/layers/ImageBridgeParent.h"  // for ImageBridgeParent
22 #include "mozilla/layers/ImageLayerComposite.h"
23 #include "mozilla/layers/LayerManagerComposite.h"
24 #include "mozilla/layers/LayersMessages.h"  // for EditReply, etc
25 #include "mozilla/layers/LayersTypes.h"     // for MOZ_LAYERS_LOG
26 #include "mozilla/layers/TextureHostOGL.h"  // for TextureHostOGL
27 #include "mozilla/layers/PaintedLayerComposite.h"
28 #include "mozilla/mozalloc.h"  // for operator delete, etc
29 #include "mozilla/PerfStats.h"
30 #include "mozilla/StaticPrefs_layers.h"
31 #include "mozilla/StaticPrefs_layout.h"
32 #include "mozilla/Telemetry.h"
33 #include "mozilla/Unused.h"
34 #include "nsCoord.h"          // for NSAppUnitsToFloatPixels
35 #include "nsISupportsImpl.h"  // for Layer::Release, etc
36 #include "nsLayoutUtils.h"    // for nsLayoutUtils
37 #include "nsMathUtils.h"      // for NS_round
38 #include "nsPoint.h"          // for nsPoint
39 #include "nsTArray.h"         // for nsTArray, nsTArray_Impl, etc
40 #include "TreeTraversal.h"    // for ForEachNode
41 #include "mozilla/ProfilerLabels.h"
42 #include "mozilla/ProfilerMarkers.h"
43 #include "mozilla/layers/TextureHost.h"
44 #include "mozilla/layers/AsyncCompositionManager.h"
45 
46 using mozilla::Telemetry::LABELS_CONTENT_FRAME_TIME_REASON;
47 
48 namespace mozilla {
49 namespace layers {
50 
51 //--------------------------------------------------
52 // LayerTransactionParent
LayerTransactionParent(HostLayerManager * aManager,CompositorBridgeParentBase * aBridge,CompositorAnimationStorage * aAnimStorage,LayersId aId,TimeDuration aVsyncRate)53 LayerTransactionParent::LayerTransactionParent(
54     HostLayerManager* aManager, CompositorBridgeParentBase* aBridge,
55     CompositorAnimationStorage* aAnimStorage, LayersId aId,
56     TimeDuration aVsyncRate)
57     : mLayerManager(aManager),
58       mCompositorBridge(aBridge),
59       mAnimStorage(aAnimStorage),
60       mId(aId),
61       mChildEpoch{0},
62       mParentEpoch{0},
63       mVsyncRate(aVsyncRate),
64       mDestroyed(false),
65       mIPCOpen(false),
66       mUpdateHitTestingTree(false) {
67   MOZ_ASSERT(mId.IsValid());
68 }
69 
70 LayerTransactionParent::~LayerTransactionParent() = default;
71 
SetLayerManager(HostLayerManager * aLayerManager,CompositorAnimationStorage * aAnimStorage)72 void LayerTransactionParent::SetLayerManager(
73     HostLayerManager* aLayerManager, CompositorAnimationStorage* aAnimStorage) {
74   if (mDestroyed) {
75     return;
76   }
77   mLayerManager = aLayerManager;
78   for (const auto& layer : mLayerMap.Values()) {
79     if (mAnimStorage && layer->GetCompositorAnimationsId()) {
80       mAnimStorage->ClearById(layer->GetCompositorAnimationsId());
81     }
82     layer->AsHostLayer()->SetLayerManager(aLayerManager);
83   }
84   mAnimStorage = aAnimStorage;
85 }
86 
RecvShutdown()87 mozilla::ipc::IPCResult LayerTransactionParent::RecvShutdown() {
88   Destroy();
89   IProtocol* mgr = Manager();
90   if (!Send__delete__(this)) {
91     return IPC_FAIL_NO_REASON(mgr);
92   }
93   return IPC_OK();
94 }
95 
RecvShutdownSync()96 mozilla::ipc::IPCResult LayerTransactionParent::RecvShutdownSync() {
97   return RecvShutdown();
98 }
99 
Destroy()100 void LayerTransactionParent::Destroy() {
101   if (mDestroyed) {
102     return;
103   }
104   mDestroyed = true;
105   if (mAnimStorage) {
106     for (const auto& layer : mLayerMap.Values()) {
107       if (layer->GetCompositorAnimationsId()) {
108         mAnimStorage->ClearById(layer->GetCompositorAnimationsId());
109       }
110       layer->Disconnect();
111     }
112   }
113   mCompositables.clear();
114   mAnimStorage = nullptr;
115 }
116 
117 class MOZ_STACK_CLASS AutoLayerTransactionParentAsyncMessageSender final {
118  public:
AutoLayerTransactionParentAsyncMessageSender(LayerTransactionParent * aLayerTransaction,const nsTArray<OpDestroy> * aDestroyActors=nullptr)119   explicit AutoLayerTransactionParentAsyncMessageSender(
120       LayerTransactionParent* aLayerTransaction,
121       const nsTArray<OpDestroy>* aDestroyActors = nullptr)
122       : mLayerTransaction(aLayerTransaction), mActorsToDestroy(aDestroyActors) {
123     mLayerTransaction->SetAboutToSendAsyncMessages();
124   }
125 
~AutoLayerTransactionParentAsyncMessageSender()126   ~AutoLayerTransactionParentAsyncMessageSender() {
127     mLayerTransaction->SendPendingAsyncMessages();
128     if (mActorsToDestroy) {
129       // Destroy the actors after sending the async messages because the latter
130       // may contain references to some actors.
131       for (const auto& op : *mActorsToDestroy) {
132         mLayerTransaction->DestroyActor(op);
133       }
134     }
135   }
136 
137  private:
138   LayerTransactionParent* mLayerTransaction;
139   const nsTArray<OpDestroy>* mActorsToDestroy;
140 };
141 
RecvPaintTime(const TransactionId & aTransactionId,const TimeDuration & aPaintTime)142 mozilla::ipc::IPCResult LayerTransactionParent::RecvPaintTime(
143     const TransactionId& aTransactionId, const TimeDuration& aPaintTime) {
144   mCompositorBridge->UpdatePaintTime(this, aPaintTime);
145   return IPC_OK();
146 }
147 
RecvUpdate(const TransactionInfo & aInfo)148 mozilla::ipc::IPCResult LayerTransactionParent::RecvUpdate(
149     const TransactionInfo& aInfo) {
150   AUTO_PROFILER_TRACING_MARKER("Paint", "LayerTransaction", GRAPHICS);
151   AUTO_PROFILER_LABEL("LayerTransactionParent::RecvUpdate", GRAPHICS);
152   PerfStats::AutoMetricRecording<PerfStats::Metric::LayerTransactions>
153       autoRecording;
154 
155   TimeStamp updateStart = TimeStamp::Now();
156 
157   MOZ_LAYERS_LOG(
158       ("[ParentSide] received txn with %zu edits", aInfo.cset().Length()));
159 
160   UpdateFwdTransactionId(aInfo.fwdTransactionId());
161 
162   if (mDestroyed || !mLayerManager || mLayerManager->IsDestroyed()) {
163     for (const auto& op : aInfo.toDestroy()) {
164       DestroyActor(op);
165     }
166     return IPC_OK();
167   }
168 
169   // This ensures that destroy operations are always processed. It is not safe
170   // to early-return from RecvUpdate without doing so.
171   AutoLayerTransactionParentAsyncMessageSender autoAsyncMessageSender(
172       this, &aInfo.toDestroy());
173 
174   {
175     AutoResolveRefLayers resolve(
176         mCompositorBridge->GetCompositionManager(this));
177     nsCString none;
178     mLayerManager->BeginTransaction(none);
179   }
180 
181   // Not all edits require an update to the hit testing tree.
182   mUpdateHitTestingTree = false;
183 
184   for (EditArray::index_type i = 0; i < aInfo.cset().Length(); ++i) {
185     const Edit& edit = const_cast<Edit&>(aInfo.cset()[i]);
186 
187     switch (edit.type()) {
188       // Create* ops
189       case Edit::TOpCreatePaintedLayer: {
190         MOZ_LAYERS_LOG(("[ParentSide] CreatePaintedLayer"));
191 
192         RefPtr<PaintedLayer> layer = mLayerManager->CreatePaintedLayer();
193         if (!BindLayer(layer, edit.get_OpCreatePaintedLayer())) {
194           return IPC_FAIL_NO_REASON(this);
195         }
196 
197         UpdateHitTestingTree(layer, "CreatePaintedLayer");
198         break;
199       }
200       case Edit::TOpCreateContainerLayer: {
201         MOZ_LAYERS_LOG(("[ParentSide] CreateContainerLayer"));
202 
203         RefPtr<ContainerLayer> layer = mLayerManager->CreateContainerLayer();
204         if (!BindLayer(layer, edit.get_OpCreateContainerLayer())) {
205           return IPC_FAIL_NO_REASON(this);
206         }
207 
208         UpdateHitTestingTree(layer, "CreateContainerLayer");
209         break;
210       }
211       case Edit::TOpCreateImageLayer: {
212         MOZ_LAYERS_LOG(("[ParentSide] CreateImageLayer"));
213 
214         RefPtr<ImageLayer> layer = mLayerManager->CreateImageLayer();
215         if (!BindLayer(layer, edit.get_OpCreateImageLayer())) {
216           return IPC_FAIL_NO_REASON(this);
217         }
218 
219         UpdateHitTestingTree(layer, "CreateImageLayer");
220         break;
221       }
222       case Edit::TOpCreateColorLayer: {
223         MOZ_LAYERS_LOG(("[ParentSide] CreateColorLayer"));
224 
225         RefPtr<ColorLayer> layer = mLayerManager->CreateColorLayer();
226         if (!BindLayer(layer, edit.get_OpCreateColorLayer())) {
227           return IPC_FAIL_NO_REASON(this);
228         }
229 
230         UpdateHitTestingTree(layer, "CreateColorLayer");
231         break;
232       }
233       case Edit::TOpCreateCanvasLayer: {
234         MOZ_LAYERS_LOG(("[ParentSide] CreateCanvasLayer"));
235 
236         RefPtr<CanvasLayer> layer = mLayerManager->CreateCanvasLayer();
237         if (!BindLayer(layer, edit.get_OpCreateCanvasLayer())) {
238           return IPC_FAIL_NO_REASON(this);
239         }
240 
241         UpdateHitTestingTree(layer, "CreateCanvasLayer");
242         break;
243       }
244       case Edit::TOpCreateRefLayer: {
245         MOZ_LAYERS_LOG(("[ParentSide] CreateRefLayer"));
246 
247         RefPtr<RefLayer> layer = mLayerManager->CreateRefLayer();
248         if (!BindLayer(layer, edit.get_OpCreateRefLayer())) {
249           return IPC_FAIL_NO_REASON(this);
250         }
251 
252         UpdateHitTestingTree(layer, "CreateRefLayer");
253         break;
254       }
255       case Edit::TOpSetDiagnosticTypes: {
256         mLayerManager->SetDiagnosticTypes(
257             edit.get_OpSetDiagnosticTypes().diagnostics());
258         break;
259       }
260       // Tree ops
261       case Edit::TOpSetRoot: {
262         MOZ_LAYERS_LOG(("[ParentSide] SetRoot"));
263 
264         Layer* newRoot = AsLayer(edit.get_OpSetRoot().root());
265         if (!newRoot) {
266           return IPC_FAIL_NO_REASON(this);
267         }
268         if (newRoot->GetParent()) {
269           // newRoot is not a root!
270           return IPC_FAIL_NO_REASON(this);
271         }
272         mRoot = newRoot;
273 
274         UpdateHitTestingTree(mRoot, "SetRoot");
275         break;
276       }
277       case Edit::TOpInsertAfter: {
278         MOZ_LAYERS_LOG(("[ParentSide] InsertAfter"));
279 
280         const OpInsertAfter& oia = edit.get_OpInsertAfter();
281         Layer* child = AsLayer(oia.childLayer());
282         Layer* layer = AsLayer(oia.container());
283         Layer* after = AsLayer(oia.after());
284         if (!child || !layer || !after) {
285           return IPC_FAIL_NO_REASON(this);
286         }
287         ContainerLayer* container = layer->AsContainerLayer();
288         if (!container || !container->InsertAfter(child, after)) {
289           return IPC_FAIL_NO_REASON(this);
290         }
291 
292         UpdateHitTestingTree(layer, "InsertAfter");
293         break;
294       }
295       case Edit::TOpPrependChild: {
296         MOZ_LAYERS_LOG(("[ParentSide] PrependChild"));
297 
298         const OpPrependChild& oac = edit.get_OpPrependChild();
299         Layer* child = AsLayer(oac.childLayer());
300         Layer* layer = AsLayer(oac.container());
301         if (!child || !layer) {
302           return IPC_FAIL_NO_REASON(this);
303         }
304         ContainerLayer* container = layer->AsContainerLayer();
305         if (!container || !container->InsertAfter(child, nullptr)) {
306           return IPC_FAIL_NO_REASON(this);
307         }
308 
309         UpdateHitTestingTree(layer, "PrependChild");
310         break;
311       }
312       case Edit::TOpRemoveChild: {
313         MOZ_LAYERS_LOG(("[ParentSide] RemoveChild"));
314 
315         const OpRemoveChild& orc = edit.get_OpRemoveChild();
316         Layer* childLayer = AsLayer(orc.childLayer());
317         Layer* layer = AsLayer(orc.container());
318         if (!childLayer || !layer) {
319           return IPC_FAIL_NO_REASON(this);
320         }
321         ContainerLayer* container = layer->AsContainerLayer();
322         if (!container || !container->RemoveChild(childLayer)) {
323           return IPC_FAIL_NO_REASON(this);
324         }
325 
326         UpdateHitTestingTree(layer, "RemoveChild");
327         break;
328       }
329       case Edit::TOpRepositionChild: {
330         MOZ_LAYERS_LOG(("[ParentSide] RepositionChild"));
331 
332         const OpRepositionChild& orc = edit.get_OpRepositionChild();
333         Layer* child = AsLayer(orc.childLayer());
334         Layer* after = AsLayer(orc.after());
335         Layer* layer = AsLayer(orc.container());
336         if (!child || !layer || !after) {
337           return IPC_FAIL_NO_REASON(this);
338         }
339         ContainerLayer* container = layer->AsContainerLayer();
340         if (!container || !container->RepositionChild(child, after)) {
341           return IPC_FAIL_NO_REASON(this);
342         }
343 
344         UpdateHitTestingTree(layer, "RepositionChild");
345         break;
346       }
347       case Edit::TOpRaiseToTopChild: {
348         MOZ_LAYERS_LOG(("[ParentSide] RaiseToTopChild"));
349 
350         const OpRaiseToTopChild& rtc = edit.get_OpRaiseToTopChild();
351         Layer* child = AsLayer(rtc.childLayer());
352         if (!child) {
353           return IPC_FAIL_NO_REASON(this);
354         }
355         Layer* layer = AsLayer(rtc.container());
356         if (!layer) {
357           return IPC_FAIL_NO_REASON(this);
358         }
359         ContainerLayer* container = layer->AsContainerLayer();
360         if (!container || !container->RepositionChild(child, nullptr)) {
361           return IPC_FAIL_NO_REASON(this);
362         }
363 
364         UpdateHitTestingTree(layer, "RaiseToTopChild");
365         break;
366       }
367       case Edit::TCompositableOperation: {
368         if (!ReceiveCompositableUpdate(edit.get_CompositableOperation())) {
369           return IPC_FAIL_NO_REASON(this);
370         }
371         break;
372       }
373       case Edit::TOpAttachCompositable: {
374         const OpAttachCompositable& op = edit.get_OpAttachCompositable();
375         RefPtr<CompositableHost> host = FindCompositable(op.compositable());
376         if (!Attach(AsLayer(op.layer()), host, false)) {
377           return IPC_FAIL_NO_REASON(this);
378         }
379         host->SetCompositorBridgeID(mLayerManager->GetCompositorBridgeID());
380         break;
381       }
382       case Edit::TOpAttachAsyncCompositable: {
383         const OpAttachAsyncCompositable& op =
384             edit.get_OpAttachAsyncCompositable();
385         RefPtr<ImageBridgeParent> imageBridge =
386             ImageBridgeParent::GetInstance(OtherPid());
387         if (!imageBridge) {
388           return IPC_FAIL_NO_REASON(this);
389         }
390         RefPtr<CompositableHost> host = imageBridge->FindCompositable(
391             op.compositable(), /* aAllowDisablingWebRender */ true);
392         if (!host) {
393           // This normally should not happen, but can after a GPU process crash.
394           // Media may not have had time to update the ImageContainer associated
395           // with a video frame, and we may try to attach a stale
396           // CompositableHandle. Rather than break the whole transaction, we
397           // just continue.
398           gfxCriticalNote << "CompositableHost " << op.compositable().Value()
399                           << " not found";
400           continue;
401         }
402         if (!Attach(AsLayer(op.layer()), host, true)) {
403           return IPC_FAIL_NO_REASON(this);
404         }
405         host->SetCompositorBridgeID(mLayerManager->GetCompositorBridgeID());
406         break;
407       }
408       default:
409         MOZ_CRASH("not reached");
410     }
411   }
412 
413   // Process simple attribute updates.
414   for (const auto& op : aInfo.setSimpleAttrs()) {
415     MOZ_LAYERS_LOG(("[ParentSide] SetSimpleLayerAttributes"));
416     Layer* layer = AsLayer(op.layer());
417     if (!layer) {
418       return IPC_FAIL_NO_REASON(this);
419     }
420     const SimpleLayerAttributes& attrs = op.attrs();
421     const SimpleLayerAttributes& orig = layer->GetSimpleAttributes();
422     if (!attrs.HitTestingInfoIsEqual(orig)) {
423       UpdateHitTestingTree(layer, "scrolling info changed");
424     }
425     layer->SetSimpleAttributes(op.attrs());
426   }
427 
428   // Process attribute updates.
429   for (const auto& op : aInfo.setAttrs()) {
430     MOZ_LAYERS_LOG(("[ParentSide] SetLayerAttributes"));
431     if (!SetLayerAttributes(op)) {
432       return IPC_FAIL_NO_REASON(this);
433     }
434   }
435 
436   // Process paints separately, after all normal edits.
437   for (const auto& op : aInfo.paints()) {
438     if (!ReceiveCompositableUpdate(op)) {
439       return IPC_FAIL_NO_REASON(this);
440     }
441   }
442 
443   mCompositorBridge->ShadowLayersUpdated(this, aInfo, mUpdateHitTestingTree);
444 
445   {
446     AutoResolveRefLayers resolve(
447         mCompositorBridge->GetCompositionManager(this));
448     mLayerManager->EndTransaction(TimeStamp(),
449                                   LayerManager::END_NO_IMMEDIATE_REDRAW);
450   }
451 
452   if (!IsSameProcess()) {
453     // Ensure that any pending operations involving back and front
454     // buffers have completed, so that neither process stomps on the
455     // other's buffer contents.
456     LayerManagerComposite::PlatformSyncBeforeReplyUpdate();
457   }
458 
459 #ifdef COMPOSITOR_PERFORMANCE_WARNING
460   int compositeTime =
461       (int)(mozilla::TimeStamp::Now() - updateStart).ToMilliseconds();
462   if (compositeTime > 15) {
463     printf_stderr("Compositor: Layers update took %i ms (blocking gecko).\n",
464                   compositeTime);
465   }
466 #endif
467 
468   // Enable visual warning for long transaction when draw FPS option is enabled
469   bool drawFps = StaticPrefs::layers_acceleration_draw_fps();
470   if (drawFps) {
471     uint32_t visualWarningTrigger =
472         StaticPrefs::layers_transaction_warning_ms();
473     // The default theshold is 200ms to trigger, hit red when it take 4 times
474     // longer
475     TimeDuration latency = TimeStamp::Now() - aInfo.transactionStart();
476     if (latency > TimeDuration::FromMilliseconds(visualWarningTrigger)) {
477       float severity =
478           (latency - TimeDuration::FromMilliseconds(visualWarningTrigger))
479               .ToMilliseconds() /
480           (4 * visualWarningTrigger);
481       if (severity > 1.f) {
482         severity = 1.f;
483       }
484       mLayerManager->VisualFrameWarning(severity);
485       printf_stderr(
486           "LayerTransactionParent::RecvUpdate transaction from process %d took "
487           "%f ms",
488           OtherPid(), latency.ToMilliseconds());
489     }
490 
491     mLayerManager->RecordUpdateTime(
492         (TimeStamp::Now() - updateStart).ToMilliseconds());
493   }
494 
495   return IPC_OK();
496 }
497 
SetLayerAttributes(const OpSetLayerAttributes & aOp)498 bool LayerTransactionParent::SetLayerAttributes(
499     const OpSetLayerAttributes& aOp) {
500   Layer* layer = AsLayer(aOp.layer());
501   if (!layer) {
502     return false;
503   }
504 
505   const LayerAttributes& attrs = aOp.attrs();
506   const CommonLayerAttributes& common = attrs.common();
507   if (common.visibleRegion() != layer->GetVisibleRegion()) {
508     UpdateHitTestingTree(layer, "visible region changed");
509     layer->SetVisibleRegion(common.visibleRegion());
510   }
511   if (common.eventRegions() != layer->GetEventRegions()) {
512     UpdateHitTestingTree(layer, "event regions changed");
513     layer->SetEventRegions(common.eventRegions());
514   }
515   Maybe<ParentLayerIntRect> clipRect =
516       common.useClipRect() ? Some(common.clipRect()) : Nothing();
517   if (clipRect != layer->GetClipRect()) {
518     UpdateHitTestingTree(layer, "clip rect changed");
519     layer->SetClipRect(clipRect);
520   }
521   if (LayerHandle maskLayer = common.maskLayer()) {
522     layer->SetMaskLayer(AsLayer(maskLayer));
523   } else {
524     layer->SetMaskLayer(nullptr);
525   }
526   layer->SetCompositorAnimations(mId, common.compositorAnimations());
527   // Clean up the Animations by id in the CompositorAnimationStorage
528   // if there are no active animations on the layer
529   if (mAnimStorage && layer->GetCompositorAnimationsId() &&
530       layer->GetPropertyAnimationGroups().IsEmpty()) {
531     mAnimStorage->ClearById(layer->GetCompositorAnimationsId());
532   }
533   if (common.scrollMetadata() != layer->GetAllScrollMetadata()) {
534     UpdateHitTestingTree(layer, "scroll metadata changed");
535     layer->SetScrollMetadata(common.scrollMetadata());
536   }
537   layer->SetDisplayListLog(common.displayListLog().get());
538 
539   // The updated invalid region is added to the existing one, since we can
540   // update multiple times before the next composite.
541   layer->AddInvalidRegion(common.invalidRegion());
542 
543   nsTArray<RefPtr<Layer>> maskLayers;
544   for (size_t i = 0; i < common.ancestorMaskLayers().Length(); i++) {
545     Layer* maskLayer = AsLayer(common.ancestorMaskLayers().ElementAt(i));
546     if (!maskLayer) {
547       return false;
548     }
549     maskLayers.AppendElement(maskLayer);
550   }
551   layer->SetAncestorMaskLayers(maskLayers);
552 
553   typedef SpecificLayerAttributes Specific;
554   const SpecificLayerAttributes& specific = attrs.specific();
555   switch (specific.type()) {
556     case Specific::Tnull_t:
557       break;
558 
559     case Specific::TPaintedLayerAttributes: {
560       MOZ_LAYERS_LOG(("[ParentSide]   painted layer"));
561 
562       PaintedLayer* paintedLayer = layer->AsPaintedLayer();
563       if (!paintedLayer) {
564         return false;
565       }
566       const PaintedLayerAttributes& attrs =
567           specific.get_PaintedLayerAttributes();
568 
569       paintedLayer->SetValidRegion(attrs.validRegion());
570       break;
571     }
572     case Specific::TContainerLayerAttributes: {
573       MOZ_LAYERS_LOG(("[ParentSide]   container layer"));
574 
575       ContainerLayer* containerLayer = layer->AsContainerLayer();
576       if (!containerLayer) {
577         return false;
578       }
579       const ContainerLayerAttributes& attrs =
580           specific.get_ContainerLayerAttributes();
581       containerLayer->SetPreScale(attrs.preXScale(), attrs.preYScale());
582       containerLayer->SetInheritedScale(attrs.inheritedXScale(),
583                                         attrs.inheritedYScale());
584       containerLayer->SetScaleToResolution(attrs.presShellResolution());
585       break;
586     }
587     case Specific::TColorLayerAttributes: {
588       MOZ_LAYERS_LOG(("[ParentSide]   color layer"));
589 
590       ColorLayer* colorLayer = layer->AsColorLayer();
591       if (!colorLayer) {
592         return false;
593       }
594       colorLayer->SetColor(specific.get_ColorLayerAttributes().color().value());
595       colorLayer->SetBounds(specific.get_ColorLayerAttributes().bounds());
596       break;
597     }
598     case Specific::TCanvasLayerAttributes: {
599       MOZ_LAYERS_LOG(("[ParentSide]   canvas layer"));
600 
601       CanvasLayer* canvasLayer = layer->AsCanvasLayer();
602       if (!canvasLayer) {
603         return false;
604       }
605       canvasLayer->SetSamplingFilter(
606           specific.get_CanvasLayerAttributes().samplingFilter());
607       canvasLayer->SetBounds(specific.get_CanvasLayerAttributes().bounds());
608       break;
609     }
610     case Specific::TRefLayerAttributes: {
611       MOZ_LAYERS_LOG(("[ParentSide]   ref layer"));
612 
613       RefLayer* refLayer = layer->AsRefLayer();
614       if (!refLayer) {
615         return false;
616       }
617       refLayer->SetReferentId(specific.get_RefLayerAttributes().id());
618       refLayer->SetEventRegionsOverride(
619           specific.get_RefLayerAttributes().eventRegionsOverride());
620       refLayer->SetRemoteDocumentSize(
621           specific.get_RefLayerAttributes().remoteDocumentSize());
622       UpdateHitTestingTree(layer, "ref layer attributes changed");
623       break;
624     }
625     case Specific::TImageLayerAttributes: {
626       MOZ_LAYERS_LOG(("[ParentSide]   image layer"));
627 
628       ImageLayer* imageLayer = layer->AsImageLayer();
629       if (!imageLayer) {
630         return false;
631       }
632       const ImageLayerAttributes& attrs = specific.get_ImageLayerAttributes();
633       imageLayer->SetSamplingFilter(attrs.samplingFilter());
634       imageLayer->SetScaleToSize(attrs.scaleToSize(), attrs.scaleMode());
635       break;
636     }
637     default:
638       MOZ_CRASH("not reached");
639   }
640 
641   return true;
642 }
643 
RecvSetLayersObserverEpoch(const LayersObserverEpoch & aChildEpoch)644 mozilla::ipc::IPCResult LayerTransactionParent::RecvSetLayersObserverEpoch(
645     const LayersObserverEpoch& aChildEpoch) {
646   mChildEpoch = aChildEpoch;
647   return IPC_OK();
648 }
649 
ShouldParentObserveEpoch()650 bool LayerTransactionParent::ShouldParentObserveEpoch() {
651   if (mParentEpoch == mChildEpoch) {
652     return false;
653   }
654 
655   mParentEpoch = mChildEpoch;
656   return true;
657 }
658 
RecvSetTestSampleTime(const TimeStamp & aTime)659 mozilla::ipc::IPCResult LayerTransactionParent::RecvSetTestSampleTime(
660     const TimeStamp& aTime) {
661   if (!mCompositorBridge->SetTestSampleTime(GetId(), aTime)) {
662     return IPC_FAIL_NO_REASON(this);
663   }
664   return IPC_OK();
665 }
666 
RecvLeaveTestMode()667 mozilla::ipc::IPCResult LayerTransactionParent::RecvLeaveTestMode() {
668   if (mDestroyed) {
669     return IPC_FAIL_NO_REASON(this);
670   }
671 
672   mCompositorBridge->LeaveTestMode(GetId());
673   return IPC_OK();
674 }
675 
RecvGetAnimationValue(const uint64_t & aCompositorAnimationsId,OMTAValue * aValue)676 mozilla::ipc::IPCResult LayerTransactionParent::RecvGetAnimationValue(
677     const uint64_t& aCompositorAnimationsId, OMTAValue* aValue) {
678   if (mDestroyed || !mLayerManager || mLayerManager->IsDestroyed()) {
679     return IPC_FAIL_NO_REASON(this);
680   }
681 
682   // Make sure we apply the latest animation style or else we can end up with
683   // a race between when we temporarily clear the animation transform (in
684   // CompositorBridgeParent::SetShadowProperties) and when animation
685   // recalculates the value.
686   mCompositorBridge->ApplyAsyncProperties(
687       this, CompositorBridgeParentBase::TransformsToSkip::APZ);
688 
689   if (!mAnimStorage) {
690     return IPC_FAIL_NO_REASON(this);
691   }
692 
693   *aValue = mAnimStorage->GetOMTAValue(aCompositorAnimationsId);
694   return IPC_OK();
695 }
696 
RecvGetTransform(const LayerHandle & aLayerHandle,Maybe<Matrix4x4> * aTransform)697 mozilla::ipc::IPCResult LayerTransactionParent::RecvGetTransform(
698     const LayerHandle& aLayerHandle, Maybe<Matrix4x4>* aTransform) {
699   if (mDestroyed || !mLayerManager || mLayerManager->IsDestroyed()) {
700     return IPC_FAIL_NO_REASON(this);
701   }
702 
703   Layer* layer = AsLayer(aLayerHandle);
704   if (!layer) {
705     return IPC_FAIL_NO_REASON(this);
706   }
707 
708   mCompositorBridge->ApplyAsyncProperties(
709       this, CompositorBridgeParentBase::TransformsToSkip::NoneOfThem);
710 
711   Matrix4x4 transform = layer->AsHostLayer()->GetShadowBaseTransform();
712   // Undo the scale transform applied by FrameTransformToTransformInDevice in
713   // AsyncCompositionManager.cpp.
714   if (ContainerLayer* c = layer->AsContainerLayer()) {
715     transform.PostScale(1.0f / c->GetInheritedXScale(),
716                         1.0f / c->GetInheritedYScale(), 1.0f);
717   }
718   float scale = 1;
719   Point3D scaledOrigin;
720   if (layer->GetTransformData()) {
721     const TransformData& data = *layer->GetTransformData();
722     scale = data.appUnitsPerDevPixel();
723     scaledOrigin = Point3D(
724         NS_round(NSAppUnitsToFloatPixels(data.origin().x, scale)),
725         NS_round(NSAppUnitsToFloatPixels(data.origin().y, scale)), 0.0f);
726   }
727 
728   // If our parent isn't a perspective layer, then the offset into reference
729   // frame coordinates will have been applied to us. Add an inverse translation
730   // to cancel it out.
731   if (!layer->GetParent() || !layer->GetParent()->GetTransformIsPerspective()) {
732     transform.PostTranslate(-scaledOrigin.x, -scaledOrigin.y, -scaledOrigin.z);
733   }
734 
735   *aTransform = Some(transform);
736 
737   return IPC_OK();
738 }
739 
RecvSetAsyncScrollOffset(const ScrollableLayerGuid::ViewID & aScrollID,const float & aX,const float & aY)740 mozilla::ipc::IPCResult LayerTransactionParent::RecvSetAsyncScrollOffset(
741     const ScrollableLayerGuid::ViewID& aScrollID, const float& aX,
742     const float& aY) {
743   if (mDestroyed || !mLayerManager || mLayerManager->IsDestroyed()) {
744     return IPC_FAIL_NO_REASON(this);
745   }
746 
747   mCompositorBridge->SetTestAsyncScrollOffset(GetId(), aScrollID,
748                                               CSSPoint(aX, aY));
749   return IPC_OK();
750 }
751 
RecvSetAsyncZoom(const ScrollableLayerGuid::ViewID & aScrollID,const float & aValue)752 mozilla::ipc::IPCResult LayerTransactionParent::RecvSetAsyncZoom(
753     const ScrollableLayerGuid::ViewID& aScrollID, const float& aValue) {
754   if (mDestroyed || !mLayerManager || mLayerManager->IsDestroyed()) {
755     return IPC_FAIL_NO_REASON(this);
756   }
757 
758   mCompositorBridge->SetTestAsyncZoom(GetId(), aScrollID,
759                                       LayerToParentLayerScale(aValue));
760   return IPC_OK();
761 }
762 
RecvFlushApzRepaints()763 mozilla::ipc::IPCResult LayerTransactionParent::RecvFlushApzRepaints() {
764   mCompositorBridge->FlushApzRepaints(GetId());
765   return IPC_OK();
766 }
767 
RecvGetAPZTestData(APZTestData * aOutData)768 mozilla::ipc::IPCResult LayerTransactionParent::RecvGetAPZTestData(
769     APZTestData* aOutData) {
770   mCompositorBridge->GetAPZTestData(GetId(), aOutData);
771   return IPC_OK();
772 }
773 
RecvGetFrameUniformity(FrameUniformityData * aOutData)774 mozilla::ipc::IPCResult LayerTransactionParent::RecvGetFrameUniformity(
775     FrameUniformityData* aOutData) {
776   mCompositorBridge->GetFrameUniformity(GetId(), aOutData);
777   return IPC_OK();
778 }
779 
RecvRequestProperty(const nsString & aProperty,float * aValue)780 mozilla::ipc::IPCResult LayerTransactionParent::RecvRequestProperty(
781     const nsString& aProperty, float* aValue) {
782   *aValue = -1;
783   return IPC_OK();
784 }
785 
RecvSetConfirmedTargetAPZC(const uint64_t & aBlockId,nsTArray<ScrollableLayerGuid> && aTargets)786 mozilla::ipc::IPCResult LayerTransactionParent::RecvSetConfirmedTargetAPZC(
787     const uint64_t& aBlockId, nsTArray<ScrollableLayerGuid>&& aTargets) {
788   for (size_t i = 0; i < aTargets.Length(); i++) {
789     // Guard against bad data from hijacked child processes
790     if (aTargets[i].mLayersId != GetId()) {
791       NS_ERROR(
792           "Unexpected layers id in RecvSetConfirmedTargetAPZC; dropping "
793           "message...");
794       return IPC_FAIL(this, "Bad layers id");
795     }
796   }
797   mCompositorBridge->SetConfirmedTargetAPZC(GetId(), aBlockId,
798                                             std::move(aTargets));
799   return IPC_OK();
800 }
801 
Attach(Layer * aLayer,CompositableHost * aCompositable,bool aIsAsync)802 bool LayerTransactionParent::Attach(Layer* aLayer,
803                                     CompositableHost* aCompositable,
804                                     bool aIsAsync) {
805   if (!aCompositable || !aLayer) {
806     return false;
807   }
808 
809   HostLayer* layer = aLayer->AsHostLayer();
810   if (!layer) {
811     return false;
812   }
813 
814   TextureSourceProvider* provider =
815       static_cast<HostLayerManager*>(aLayer->Manager())
816           ->GetTextureSourceProvider();
817 
818   MOZ_ASSERT(!aCompositable->AsWebRenderImageHost());
819   if (aCompositable->AsWebRenderImageHost()) {
820     gfxCriticalNote << "Use WebRenderImageHost at LayerTransactionParent.";
821   }
822   if (!layer->SetCompositableHost(aCompositable)) {
823     // not all layer types accept a compositable, see bug 967824
824     return false;
825   }
826   aCompositable->Attach(aLayer, provider,
827                         aIsAsync ? CompositableHost::ALLOW_REATTACH |
828                                        CompositableHost::KEEP_ATTACHED
829                                  : CompositableHost::NO_FLAGS);
830   return true;
831 }
832 
RecvClearCachedResources()833 mozilla::ipc::IPCResult LayerTransactionParent::RecvClearCachedResources() {
834   if (mRoot) {
835     // NB: |mRoot| here is the *child* context's root.  In this parent
836     // context, it's just a subtree root.  We need to scope the clear
837     // of resources to exactly that subtree, so we specify it here.
838     mLayerManager->ClearCachedResources(mRoot);
839   }
840   mCompositorBridge->NotifyClearCachedResources(this);
841   return IPC_OK();
842 }
843 
RecvScheduleComposite()844 mozilla::ipc::IPCResult LayerTransactionParent::RecvScheduleComposite() {
845   mCompositorBridge->ScheduleComposite(this);
846   return IPC_OK();
847 }
848 
ActorDestroy(ActorDestroyReason why)849 void LayerTransactionParent::ActorDestroy(ActorDestroyReason why) { Destroy(); }
850 
AllocShmem(size_t aSize,ipc::SharedMemory::SharedMemoryType aType,ipc::Shmem * aShmem)851 bool LayerTransactionParent::AllocShmem(
852     size_t aSize, ipc::SharedMemory::SharedMemoryType aType,
853     ipc::Shmem* aShmem) {
854   if (!mIPCOpen || mDestroyed) {
855     return false;
856   }
857   return PLayerTransactionParent::AllocShmem(aSize, aType, aShmem);
858 }
859 
AllocUnsafeShmem(size_t aSize,ipc::SharedMemory::SharedMemoryType aType,ipc::Shmem * aShmem)860 bool LayerTransactionParent::AllocUnsafeShmem(
861     size_t aSize, ipc::SharedMemory::SharedMemoryType aType,
862     ipc::Shmem* aShmem) {
863   if (!mIPCOpen || mDestroyed) {
864     return false;
865   }
866 
867   return PLayerTransactionParent::AllocUnsafeShmem(aSize, aType, aShmem);
868 }
869 
DeallocShmem(ipc::Shmem & aShmem)870 bool LayerTransactionParent::DeallocShmem(ipc::Shmem& aShmem) {
871   if (!mIPCOpen || mDestroyed) {
872     return false;
873   }
874   return PLayerTransactionParent::DeallocShmem(aShmem);
875 }
876 
IsSameProcess() const877 bool LayerTransactionParent::IsSameProcess() const {
878   return OtherPid() == base::GetCurrentProcId();
879 }
880 
SetPendingTransactionId(TransactionId aId,const VsyncId & aVsyncId,const TimeStamp & aVsyncStartTime,const TimeStamp & aRefreshStartTime,const TimeStamp & aTxnStartTime,const TimeStamp & aTxnEndTime,bool aContainsSVG,const nsCString & aURL,const TimeStamp & aFwdTime)881 void LayerTransactionParent::SetPendingTransactionId(
882     TransactionId aId, const VsyncId& aVsyncId,
883     const TimeStamp& aVsyncStartTime, const TimeStamp& aRefreshStartTime,
884     const TimeStamp& aTxnStartTime, const TimeStamp& aTxnEndTime,
885     bool aContainsSVG, const nsCString& aURL, const TimeStamp& aFwdTime) {
886   mPendingTransactions.AppendElement(PendingTransaction{
887       aId, aVsyncId, aVsyncStartTime, aRefreshStartTime, aTxnStartTime,
888       aTxnEndTime, aFwdTime, aURL, aContainsSVG});
889 }
890 
FlushPendingTransactions(const VsyncId & aCompositeId,TimeStamp & aCompositeEnd,nsTArray<TransactionId> & aOutTransactions)891 void LayerTransactionParent::FlushPendingTransactions(
892     const VsyncId& aCompositeId, TimeStamp& aCompositeEnd,
893     nsTArray<TransactionId>& aOutTransactions) {
894   for (auto& transaction : mPendingTransactions) {
895     aOutTransactions.AppendElement(transaction.mId);
896     if (mId.IsValid() && transaction.mId.IsValid() && !mVsyncRate.IsZero()) {
897       RecordContentFrameTime(
898           transaction.mTxnVsyncId, transaction.mVsyncStartTime,
899           transaction.mTxnStartTime, aCompositeId, aCompositeEnd,
900           transaction.mTxnEndTime - transaction.mTxnStartTime, mVsyncRate,
901           transaction.mContainsSVG, false);
902     }
903 
904 #if defined(ENABLE_FRAME_LATENCY_LOG)
905     if (transaction.mId.IsValid()) {
906       if (transaction.mRefreshStartTime) {
907         int32_t latencyMs = lround(
908             (aCompositeEnd - transaction.mRefreshStartTime).ToMilliseconds());
909         printf_stderr(
910             "From transaction start to end of generate frame latencyMs %d this "
911             "%p\n",
912             latencyMs, this);
913       }
914       if (transaction.mFwdTime) {
915         int32_t latencyMs =
916             lround((aCompositeEnd - transaction.mFwdTime).ToMilliseconds());
917         printf_stderr(
918             "From forwarding transaction to end of generate frame latencyMs %d "
919             "this %p\n",
920             latencyMs, this);
921       }
922     }
923 #endif
924   }
925 
926   mPendingTransactions.Clear();
927 }
928 
SendAsyncMessage(const nsTArray<AsyncParentMessageData> & aMessage)929 void LayerTransactionParent::SendAsyncMessage(
930     const nsTArray<AsyncParentMessageData>& aMessage) {
931   MOZ_ASSERT_UNREACHABLE("unexpected to be called");
932 }
933 
SendPendingAsyncMessages()934 void LayerTransactionParent::SendPendingAsyncMessages() {
935   mCompositorBridge->SendPendingAsyncMessages();
936 }
937 
SetAboutToSendAsyncMessages()938 void LayerTransactionParent::SetAboutToSendAsyncMessages() {
939   mCompositorBridge->SetAboutToSendAsyncMessages();
940 }
941 
NotifyNotUsed(PTextureParent * aTexture,uint64_t aTransactionId)942 void LayerTransactionParent::NotifyNotUsed(PTextureParent* aTexture,
943                                            uint64_t aTransactionId) {
944   MOZ_ASSERT_UNREACHABLE("unexpected to be called");
945 }
946 
BindLayerToHandle(RefPtr<Layer> aLayer,const LayerHandle & aHandle)947 bool LayerTransactionParent::BindLayerToHandle(RefPtr<Layer> aLayer,
948                                                const LayerHandle& aHandle) {
949   if (!aHandle || !aLayer) {
950     return false;
951   }
952   return mLayerMap.WithEntryHandle(aHandle.Value(), [&](auto&& entry) {
953     if (entry) {
954       return false;
955     }
956     entry.Insert(std::move(aLayer));
957     return true;
958   });
959 }
960 
AsLayer(const LayerHandle & aHandle)961 Layer* LayerTransactionParent::AsLayer(const LayerHandle& aHandle) {
962   if (!aHandle) {
963     return nullptr;
964   }
965   return mLayerMap.GetWeak(aHandle.Value());
966 }
967 
RecvNewCompositable(const CompositableHandle & aHandle,const TextureInfo & aInfo)968 mozilla::ipc::IPCResult LayerTransactionParent::RecvNewCompositable(
969     const CompositableHandle& aHandle, const TextureInfo& aInfo) {
970   if (!AddCompositable(aHandle, aInfo, /* aUseWebRender */ false)) {
971     return IPC_FAIL_NO_REASON(this);
972   }
973   return IPC_OK();
974 }
975 
RecvReleaseLayer(const LayerHandle & aHandle)976 mozilla::ipc::IPCResult LayerTransactionParent::RecvReleaseLayer(
977     const LayerHandle& aHandle) {
978   RefPtr<Layer> layer;
979   if (!aHandle || !mLayerMap.Remove(aHandle.Value(), getter_AddRefs(layer))) {
980     return IPC_FAIL_NO_REASON(this);
981   }
982   if (mAnimStorage && layer->GetCompositorAnimationsId()) {
983     mAnimStorage->ClearById(layer->GetCompositorAnimationsId());
984     layer->ClearCompositorAnimations();
985   }
986   layer->Disconnect();
987   return IPC_OK();
988 }
989 
RecvReleaseCompositable(const CompositableHandle & aHandle)990 mozilla::ipc::IPCResult LayerTransactionParent::RecvReleaseCompositable(
991     const CompositableHandle& aHandle) {
992   ReleaseCompositable(aHandle);
993   return IPC_OK();
994 }
995 
RecvRecordPaintTimes(const PaintTiming & aTiming)996 mozilla::ipc::IPCResult LayerTransactionParent::RecvRecordPaintTimes(
997     const PaintTiming& aTiming) {
998   // Currently we only add paint timings for remote layers. In the future
999   // we could be smarter and use paint timings from the UI process, either
1000   // as a separate overlay or if no remote layers are attached.
1001   if (mLayerManager && mCompositorBridge->IsRemote()) {
1002     mLayerManager->RecordPaintTimes(aTiming);
1003   }
1004   return IPC_OK();
1005 }
1006 
RecvGetTextureFactoryIdentifier(TextureFactoryIdentifier * aIdentifier)1007 mozilla::ipc::IPCResult LayerTransactionParent::RecvGetTextureFactoryIdentifier(
1008     TextureFactoryIdentifier* aIdentifier) {
1009   if (mDestroyed || !mLayerManager || mLayerManager->IsDestroyed()) {
1010     // Default constructor sets mParentBackend to LAYERS_NONE.
1011     return IPC_OK();
1012   }
1013 
1014   *aIdentifier = mLayerManager->GetTextureFactoryIdentifier();
1015   return IPC_OK();
1016 }
1017 
1018 }  // namespace layers
1019 }  // namespace mozilla
1020