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