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