Coverage Report

Created: 2018-09-25 14:53

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