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