Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/gfx/layers/ipc/CompositorBridgeParent.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 "mozilla/layers/CompositorBridgeParent.h"
8
9
#include <stdio.h>                      // for fprintf, stdout
10
#include <stdint.h>                     // for uint64_t
11
#include <map>                          // for _Rb_tree_iterator, etc
12
#include <utility>                      // for pair
13
14
#include "apz/src/APZCTreeManager.h"    // for APZCTreeManager
15
#include "LayerTransactionParent.h"     // for LayerTransactionParent
16
#include "RenderTrace.h"                // for RenderTraceLayers
17
#include "base/message_loop.h"          // for MessageLoop
18
#include "base/process.h"               // for ProcessId
19
#include "base/task.h"                  // for CancelableTask, etc
20
#include "base/thread.h"                // for Thread
21
#include "gfxContext.h"                 // for gfxContext
22
#include "gfxPlatform.h"                // for gfxPlatform
23
#include "TreeTraversal.h"              // for ForEachNode
24
#ifdef MOZ_WIDGET_GTK
25
#include "gfxPlatformGtk.h"             // for gfxPlatform
26
#endif
27
#include "gfxPrefs.h"                   // for gfxPrefs
28
#include "mozilla/AutoRestore.h"        // for AutoRestore
29
#include "mozilla/ClearOnShutdown.h"    // for ClearOnShutdown
30
#include "mozilla/DebugOnly.h"          // for DebugOnly
31
#include "mozilla/dom/ContentParent.h"
32
#include "mozilla/dom/TabParent.h"
33
#include "mozilla/gfx/2D.h"          // for DrawTarget
34
#include "mozilla/gfx/GPUChild.h"       // for GfxPrefValue
35
#include "mozilla/gfx/Point.h"          // for IntSize
36
#include "mozilla/gfx/Rect.h"          // for IntSize
37
#include "mozilla/gfx/gfxVars.h"        // for gfxVars
38
#include "VRManager.h"                  // for VRManager
39
#include "mozilla/ipc/Transport.h"      // for Transport
40
#include "mozilla/gfx/gfxVars.h"
41
#include "mozilla/gfx/GPUParent.h"
42
#include "mozilla/layers/AnimationHelper.h" // for CompositorAnimationStorage
43
#include "mozilla/layers/APZCTreeManagerParent.h"  // for APZCTreeManagerParent
44
#include "mozilla/layers/APZSampler.h"  // for APZSampler
45
#include "mozilla/layers/APZThreadUtils.h"  // for APZThreadUtils
46
#include "mozilla/layers/APZUpdater.h"  // for APZUpdater
47
#include "mozilla/layers/AsyncCompositionManager.h"
48
#include "mozilla/layers/BasicCompositor.h"  // for BasicCompositor
49
#include "mozilla/layers/Compositor.h"  // for Compositor
50
#include "mozilla/layers/CompositorManagerParent.h" // for CompositorManagerParent
51
#include "mozilla/layers/CompositorOGL.h"  // for CompositorOGL
52
#include "mozilla/layers/CompositorThread.h"
53
#include "mozilla/layers/CompositorTypes.h"
54
#include "mozilla/layers/CompositorVsyncScheduler.h"
55
#include "mozilla/layers/CrossProcessCompositorBridgeParent.h"
56
#include "mozilla/layers/FrameUniformityData.h"
57
#include "mozilla/layers/ImageBridgeParent.h"
58
#include "mozilla/layers/LayerManagerComposite.h"
59
#include "mozilla/layers/LayerManagerMLGPU.h"
60
#include "mozilla/layers/LayerTreeOwnerTracker.h"
61
#include "mozilla/layers/LayersTypes.h"
62
#include "mozilla/layers/PLayerTransactionParent.h"
63
#include "mozilla/layers/RemoteContentController.h"
64
#include "mozilla/layers/WebRenderBridgeParent.h"
65
#include "mozilla/layers/AsyncImagePipelineManager.h"
66
#include "mozilla/layout/RenderFrameParent.h"
67
#include "mozilla/webrender/WebRenderAPI.h"
68
#include "mozilla/media/MediaSystemResourceService.h" // for MediaSystemResourceService
69
#include "mozilla/mozalloc.h"           // for operator new, etc
70
#include "mozilla/Telemetry.h"
71
#ifdef MOZ_WIDGET_GTK
72
#include "basic/X11BasicCompositor.h" // for X11BasicCompositor
73
#endif
74
#include "nsCOMPtr.h"                   // for already_AddRefed
75
#include "nsDebug.h"                    // for NS_ASSERTION, etc
76
#include "nsISupportsImpl.h"            // for MOZ_COUNT_CTOR, etc
77
#include "nsIWidget.h"                  // for nsIWidget
78
#include "nsTArray.h"                   // for nsTArray
79
#include "nsThreadUtils.h"              // for NS_IsMainThread
80
#include "nsXULAppAPI.h"                // for XRE_GetIOMessageLoop
81
#ifdef XP_WIN
82
#include "mozilla/layers/CompositorD3D11.h"
83
#include "mozilla/widget/WinCompositorWidget.h"
84
#endif
85
#include "GeckoProfiler.h"
86
#include "mozilla/ipc/ProtocolTypes.h"
87
#include "mozilla/Unused.h"
88
#include "mozilla/Hal.h"
89
#include "mozilla/HalTypes.h"
90
#include "mozilla/StaticPtr.h"
91
#include "mozilla/Telemetry.h"
92
#ifdef MOZ_GECKO_PROFILER
93
# include "ProfilerMarkerPayload.h"
94
#endif
95
#include "mozilla/VsyncDispatcher.h"
96
#if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
97
# include "VsyncSource.h"
98
#endif
99
#include "mozilla/widget/CompositorWidget.h"
100
#ifdef MOZ_WIDGET_SUPPORTS_OOP_COMPOSITING
101
# include "mozilla/widget/CompositorWidgetParent.h"
102
#endif
103
#ifdef XP_WIN
104
# include "mozilla/gfx/DeviceManagerDx.h"
105
#endif
106
107
#include "LayerScope.h"
108
109
namespace mozilla {
110
111
namespace layers {
112
113
using namespace mozilla::ipc;
114
using namespace mozilla::gfx;
115
using namespace std;
116
117
using base::ProcessId;
118
using base::Thread;
119
120
121
/// Equivalent to asserting CompositorThreadHolder::IsInCompositorThread with the
122
/// addition that it doesn't assert if the compositor thread holder is already gone
123
/// during late shutdown.
124
static void AssertIsInCompositorThread()
125
0
{
126
0
  MOZ_RELEASE_ASSERT(!CompositorThread() ||
127
0
                     CompositorThreadHolder::IsInCompositorThread());
128
0
}
129
130
CompositorBridgeParentBase::CompositorBridgeParentBase(CompositorManagerParent* aManager)
131
  : mCanSend(true)
132
  , mCompositorManager(aManager)
133
0
{
134
0
}
135
136
CompositorBridgeParentBase::~CompositorBridgeParentBase()
137
0
{
138
0
}
139
140
ProcessId
141
CompositorBridgeParentBase::GetChildProcessId()
142
0
{
143
0
  return OtherPid();
144
0
}
145
146
void
147
CompositorBridgeParentBase::NotifyNotUsed(PTextureParent* aTexture, uint64_t aTransactionId)
148
0
{
149
0
  RefPtr<TextureHost> texture = TextureHost::AsTextureHost(aTexture);
150
0
  if (!texture) {
151
0
    return;
152
0
  }
153
0
154
0
  if (!(texture->GetFlags() & TextureFlags::RECYCLE)) {
155
0
    return;
156
0
  }
157
0
158
0
  uint64_t textureId = TextureHost::GetTextureSerial(aTexture);
159
0
  mPendingAsyncMessage.push_back(
160
0
    OpNotifyNotUsed(textureId, aTransactionId));
161
0
}
162
163
void
164
CompositorBridgeParentBase::SendAsyncMessage(const InfallibleTArray<AsyncParentMessageData>& aMessage)
165
0
{
166
0
  Unused << SendParentAsyncMessages(aMessage);
167
0
}
168
169
bool
170
CompositorBridgeParentBase::AllocShmem(size_t aSize,
171
                                   ipc::SharedMemory::SharedMemoryType aType,
172
                                   ipc::Shmem* aShmem)
173
0
{
174
0
  return PCompositorBridgeParent::AllocShmem(aSize, aType, aShmem);
175
0
}
176
177
bool
178
CompositorBridgeParentBase::AllocUnsafeShmem(size_t aSize,
179
                                         ipc::SharedMemory::SharedMemoryType aType,
180
                                         ipc::Shmem* aShmem)
181
0
{
182
0
  return PCompositorBridgeParent::AllocUnsafeShmem(aSize, aType, aShmem);
183
0
}
184
185
void
186
CompositorBridgeParentBase::DeallocShmem(ipc::Shmem& aShmem)
187
0
{
188
0
  PCompositorBridgeParent::DeallocShmem(aShmem);
189
0
}
190
191
static inline MessageLoop*
192
CompositorLoop()
193
0
{
194
0
  return CompositorThreadHolder::Loop();
195
0
}
196
197
base::ProcessId
198
CompositorBridgeParentBase::RemotePid()
199
0
{
200
0
  return OtherPid();
201
0
}
202
203
bool
204
CompositorBridgeParentBase::StartSharingMetrics(ipc::SharedMemoryBasic::Handle aHandle,
205
                                                CrossProcessMutexHandle aMutexHandle,
206
                                                LayersId aLayersId,
207
                                                uint32_t aApzcId)
208
0
{
209
0
  if (!CompositorThreadHolder::IsInCompositorThread()) {
210
0
    MOZ_ASSERT(CompositorLoop());
211
0
    CompositorLoop()->PostTask(
212
0
      NewRunnableMethod<ipc::SharedMemoryBasic::Handle,
213
0
                        CrossProcessMutexHandle,
214
0
                        LayersId,
215
0
                        uint32_t>(
216
0
        "layers::CompositorBridgeParent::StartSharingMetrics",
217
0
        this,
218
0
        &CompositorBridgeParentBase::StartSharingMetrics,
219
0
        aHandle, aMutexHandle, aLayersId, aApzcId));
220
0
    return true;
221
0
  }
222
0
223
0
  MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
224
0
  if (!mCanSend) {
225
0
    return false;
226
0
  }
227
0
  return PCompositorBridgeParent::SendSharedCompositorFrameMetrics(
228
0
    aHandle, aMutexHandle, aLayersId, aApzcId);
229
0
}
230
231
bool
232
CompositorBridgeParentBase::StopSharingMetrics(FrameMetrics::ViewID aScrollId,
233
                                               uint32_t aApzcId)
234
0
{
235
0
  if (!CompositorThreadHolder::IsInCompositorThread()) {
236
0
    MOZ_ASSERT(CompositorLoop());
237
0
    CompositorLoop()->PostTask(
238
0
      NewRunnableMethod<FrameMetrics::ViewID, uint32_t>(
239
0
        "layers::CompositorBridgeParent::StopSharingMetrics",
240
0
        this,
241
0
        &CompositorBridgeParentBase::StopSharingMetrics,
242
0
        aScrollId, aApzcId));
243
0
    return true;
244
0
  }
245
0
246
0
  MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
247
0
  if (!mCanSend) {
248
0
    return false;
249
0
  }
250
0
  return PCompositorBridgeParent::SendReleaseSharedCompositorFrameMetrics(
251
0
    aScrollId, aApzcId);
252
0
}
253
254
CompositorBridgeParent::LayerTreeState::LayerTreeState()
255
  : mApzcTreeManagerParent(nullptr)
256
  , mParent(nullptr)
257
  , mLayerManager(nullptr)
258
  , mCrossProcessParent(nullptr)
259
  , mLayerTree(nullptr)
260
  , mUpdatedPluginDataAvailable(false)
261
0
{
262
0
}
263
264
CompositorBridgeParent::LayerTreeState::~LayerTreeState()
265
0
{
266
0
  if (mController) {
267
0
    mController->Destroy();
268
0
  }
269
0
}
270
271
typedef map<LayersId, CompositorBridgeParent::LayerTreeState> LayerTreeMap;
272
LayerTreeMap sIndirectLayerTrees;
273
StaticAutoPtr<mozilla::Monitor> sIndirectLayerTreesLock;
274
275
static void EnsureLayerTreeMapReady()
276
0
{
277
0
  MOZ_ASSERT(NS_IsMainThread());
278
0
  if (!sIndirectLayerTreesLock) {
279
0
    sIndirectLayerTreesLock = new Monitor("IndirectLayerTree");
280
0
    mozilla::ClearOnShutdown(&sIndirectLayerTreesLock);
281
0
  }
282
0
}
283
284
template <typename Lambda>
285
inline void
286
CompositorBridgeParent::ForEachIndirectLayerTree(const Lambda& aCallback)
287
0
{
288
0
  sIndirectLayerTreesLock->AssertCurrentThreadOwns();
289
0
  for (auto it = sIndirectLayerTrees.begin(); it != sIndirectLayerTrees.end(); it++) {
290
0
    LayerTreeState* state = &it->second;
291
0
    if (state->mParent == this) {
292
0
      aCallback(state, it->first);
293
0
    }
294
0
  }
295
0
}
Unexecuted instantiation: Unified_cpp_gfx_layers8.cpp:void mozilla::layers::CompositorBridgeParent::ForEachIndirectLayerTree<mozilla::layers::CompositorBridgeParent::StopAndClearResources()::$_0>(mozilla::layers::CompositorBridgeParent::StopAndClearResources()::$_0 const&)
Unexecuted instantiation: Unified_cpp_gfx_layers8.cpp:void mozilla::layers::CompositorBridgeParent::ForEachIndirectLayerTree<mozilla::layers::CompositorBridgeParent::StopAndClearResources()::$_1>(mozilla::layers::CompositorBridgeParent::StopAndClearResources()::$_1 const&)
Unexecuted instantiation: Unified_cpp_gfx_layers8.cpp:void mozilla::layers::CompositorBridgeParent::ForEachIndirectLayerTree<mozilla::layers::CompositorBridgeParent::NotifyPipelineRendered(mozilla::wr::PipelineId const&, mozilla::wr::Epoch const&, mozilla::TimeStamp&, mozilla::TimeStamp&)::$_4>(mozilla::layers::CompositorBridgeParent::NotifyPipelineRendered(mozilla::wr::PipelineId const&, mozilla::wr::Epoch const&, mozilla::TimeStamp&, mozilla::TimeStamp&)::$_4 const&)
Unexecuted instantiation: Unified_cpp_gfx_layers8.cpp:void mozilla::layers::CompositorBridgeParent::ForEachIndirectLayerTree<mozilla::layers::CompositorBridgeParent::NotifyDidComposite(mozilla::layers::TransactionId, mozilla::TimeStamp&, mozilla::TimeStamp&)::$_5>(mozilla::layers::CompositorBridgeParent::NotifyDidComposite(mozilla::layers::TransactionId, mozilla::TimeStamp&, mozilla::TimeStamp&)::$_5 const&)
Unexecuted instantiation: Unified_cpp_gfx_layers8.cpp:void mozilla::layers::CompositorBridgeParent::ForEachIndirectLayerTree<mozilla::layers::CompositorBridgeParent::InvalidateRemoteLayers()::$_6>(mozilla::layers::CompositorBridgeParent::InvalidateRemoteLayers()::$_6 const&)
296
297
/**
298
  * A global map referencing each compositor by ID.
299
  *
300
  * This map is used by the ImageBridge protocol to trigger
301
  * compositions without having to keep references to the
302
  * compositor
303
  */
304
typedef map<uint64_t,CompositorBridgeParent*> CompositorMap;
305
static StaticAutoPtr<CompositorMap> sCompositorMap;
306
307
void
308
CompositorBridgeParent::Setup()
309
0
{
310
0
  EnsureLayerTreeMapReady();
311
0
312
0
  MOZ_ASSERT(!sCompositorMap);
313
0
  sCompositorMap = new CompositorMap;
314
0
}
315
316
void
317
CompositorBridgeParent::FinishShutdown()
318
0
{
319
0
  MOZ_ASSERT(NS_IsMainThread());
320
0
321
0
  if (sCompositorMap) {
322
0
    MOZ_ASSERT(sCompositorMap->empty());
323
0
    sCompositorMap = nullptr;
324
0
  }
325
0
326
0
  // TODO: this should be empty by now...
327
0
  sIndirectLayerTrees.clear();
328
0
}
329
330
#ifdef COMPOSITOR_PERFORMANCE_WARNING
331
static int32_t
332
CalculateCompositionFrameRate()
333
{
334
  // Used when layout.frame_rate is -1. Needs to be kept in sync with
335
  // DEFAULT_FRAME_RATE in nsRefreshDriver.cpp.
336
  // TODO: This should actually return the vsync rate.
337
  const int32_t defaultFrameRate = 60;
338
  int32_t compositionFrameRatePref = gfxPrefs::LayersCompositionFrameRate();
339
  if (compositionFrameRatePref < 0) {
340
    // Use the same frame rate for composition as for layout.
341
    int32_t layoutFrameRatePref = gfxPrefs::LayoutFrameRate();
342
    if (layoutFrameRatePref < 0) {
343
      // TODO: The main thread frame scheduling code consults the actual
344
      // monitor refresh rate in this case. We should do the same.
345
      return defaultFrameRate;
346
    }
347
    return layoutFrameRatePref;
348
  }
349
  return compositionFrameRatePref;
350
}
351
#endif
352
353
CompositorBridgeParent::CompositorBridgeParent(CompositorManagerParent* aManager,
354
                                               CSSToLayoutDeviceScale aScale,
355
                                               const TimeDuration& aVsyncRate,
356
                                               const CompositorOptions& aOptions,
357
                                               bool aUseExternalSurfaceSize,
358
                                               const gfx::IntSize& aSurfaceSize)
359
  : CompositorBridgeParentBase(aManager)
360
  , mWidget(nullptr)
361
  , mScale(aScale)
362
  , mVsyncRate(aVsyncRate)
363
  , mPendingTransaction{0}
364
  , mPaused(false)
365
  , mUseExternalSurfaceSize(aUseExternalSurfaceSize)
366
  , mEGLSurfaceSize(aSurfaceSize)
367
  , mOptions(aOptions)
368
  , mPauseCompositionMonitor("PauseCompositionMonitor")
369
  , mResumeCompositionMonitor("ResumeCompositionMonitor")
370
  , mCompositorBridgeID(0)
371
  , mRootLayerTreeID{0}
372
  , mOverrideComposeReadiness(false)
373
  , mForceCompositionTask(nullptr)
374
  , mCompositorScheduler(nullptr)
375
  , mAnimationStorage(nullptr)
376
  , mPaintTime(TimeDuration::Forever())
377
#if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
378
  , mLastPluginUpdateLayerTreeId{0}
379
  , mDeferPluginWindows(false)
380
  , mPluginWindowsHidden(false)
381
#endif
382
0
{
383
0
}
384
385
void
386
CompositorBridgeParent::InitSameProcess(widget::CompositorWidget* aWidget,
387
                                        const LayersId& aLayerTreeId)
388
0
{
389
0
  MOZ_ASSERT(XRE_IsParentProcess() || recordreplay::IsRecordingOrReplaying());
390
0
  MOZ_ASSERT(NS_IsMainThread());
391
0
392
0
  mWidget = aWidget;
393
0
  mRootLayerTreeID = aLayerTreeId;
394
0
395
0
  Initialize();
396
0
}
397
398
mozilla::ipc::IPCResult
399
CompositorBridgeParent::RecvInitialize(const LayersId& aRootLayerTreeId)
400
0
{
401
0
  MOZ_ASSERT(XRE_IsGPUProcess());
402
0
403
0
  mRootLayerTreeID = aRootLayerTreeId;
404
0
405
0
  Initialize();
406
0
  return IPC_OK();
407
0
}
408
409
void
410
CompositorBridgeParent::Initialize()
411
0
{
412
0
  MOZ_ASSERT(CompositorThread(),
413
0
             "The compositor thread must be Initialized before instanciating a CompositorBridgeParent.");
414
0
415
0
  if (mOptions.UseAPZ()) {
416
0
    MOZ_ASSERT(!mApzcTreeManager);
417
0
    MOZ_ASSERT(!mApzSampler);
418
0
    MOZ_ASSERT(!mApzUpdater);
419
0
    mApzcTreeManager = new APZCTreeManager(mRootLayerTreeID);
420
0
    mApzSampler = new APZSampler(mApzcTreeManager, mOptions.UseWebRender());
421
0
    mApzUpdater = new APZUpdater(mApzcTreeManager, mOptions.UseWebRender());
422
0
  }
423
0
424
0
  mPaused = mOptions.InitiallyPaused();
425
0
426
0
  mCompositorBridgeID = 0;
427
0
  // FIXME: This holds on the the fact that right now the only thing that
428
0
  // can destroy this instance is initialized on the compositor thread after
429
0
  // this task has been processed.
430
0
  MOZ_ASSERT(CompositorLoop());
431
0
  CompositorLoop()->PostTask(NewRunnableFunction("AddCompositorRunnable",
432
0
                                                 &AddCompositor,
433
0
                                                 this, &mCompositorBridgeID));
434
0
435
0
436
0
  { // scope lock
437
0
    MonitorAutoLock lock(*sIndirectLayerTreesLock);
438
0
    sIndirectLayerTrees[mRootLayerTreeID].mParent = this;
439
0
  }
440
0
441
0
  LayerScope::SetPixelScale(mScale.scale);
442
0
443
0
  if (!mOptions.UseWebRender()) {
444
0
    mCompositorScheduler = new CompositorVsyncScheduler(this, mWidget);
445
0
  }
446
0
}
447
448
LayersId
449
CompositorBridgeParent::RootLayerTreeId()
450
0
{
451
0
  MOZ_ASSERT(mRootLayerTreeID.IsValid());
452
0
  return mRootLayerTreeID;
453
0
}
454
455
CompositorBridgeParent::~CompositorBridgeParent()
456
0
{
457
0
  InfallibleTArray<PTextureParent*> textures;
458
0
  ManagedPTextureParent(textures);
459
0
  // We expect all textures to be destroyed by now.
460
0
  MOZ_DIAGNOSTIC_ASSERT(textures.Length() == 0);
461
0
  for (unsigned int i = 0; i < textures.Length(); ++i) {
462
0
    RefPtr<TextureHost> tex = TextureHost::AsTextureHost(textures[i]);
463
0
    tex->DeallocateDeviceData();
464
0
  }
465
0
}
466
467
void
468
CompositorBridgeParent::ForceIsFirstPaint()
469
0
{
470
0
  mCompositionManager->ForceIsFirstPaint();
471
0
}
472
473
void
474
CompositorBridgeParent::StopAndClearResources()
475
0
{
476
0
  if (mForceCompositionTask) {
477
0
    mForceCompositionTask->Cancel();
478
0
    mForceCompositionTask = nullptr;
479
0
  }
480
0
481
0
  mPaused = true;
482
0
483
0
  // We need to clear the APZ tree before we destroy the WebRender API below,
484
0
  // because in the case of async scene building that will shut down the updater
485
0
  // thread and we need to run the task before that happens.
486
0
  MOZ_ASSERT((mApzSampler != nullptr) == (mApzcTreeManager != nullptr));
487
0
  MOZ_ASSERT((mApzUpdater != nullptr) == (mApzcTreeManager != nullptr));
488
0
  if (mApzUpdater) {
489
0
    mApzSampler = nullptr;
490
0
    mApzUpdater->ClearTree(mRootLayerTreeID);
491
0
    mApzUpdater = nullptr;
492
0
    mApzcTreeManager = nullptr;
493
0
  }
494
0
495
0
  // Ensure that the layer manager is destroyed before CompositorBridgeChild.
496
0
  if (mLayerManager) {
497
0
    MonitorAutoLock lock(*sIndirectLayerTreesLock);
498
0
    ForEachIndirectLayerTree([this] (LayerTreeState* lts, LayersId) -> void {
499
0
      mLayerManager->ClearCachedResources(lts->mRoot);
500
0
      lts->mLayerManager = nullptr;
501
0
      lts->mParent = nullptr;
502
0
    });
503
0
    mLayerManager->Destroy();
504
0
    mLayerManager = nullptr;
505
0
    mCompositionManager = nullptr;
506
0
  }
507
0
508
0
  if (mWrBridge) {
509
0
    // Ensure we are not holding the sIndirectLayerTreesLock when destroying
510
0
    // the WebRenderBridgeParent instances because it may block on WR.
511
0
    std::vector<RefPtr<WebRenderBridgeParent>> indirectBridgeParents;
512
0
    { // scope lock
513
0
      MonitorAutoLock lock(*sIndirectLayerTreesLock);
514
0
      ForEachIndirectLayerTree([&] (LayerTreeState* lts, LayersId) -> void {
515
0
        if (lts->mWrBridge) {
516
0
          indirectBridgeParents.emplace_back(lts->mWrBridge.forget());
517
0
        }
518
0
        lts->mParent = nullptr;
519
0
      });
520
0
    }
521
0
    for (const RefPtr<WebRenderBridgeParent>& bridge : indirectBridgeParents) {
522
0
      bridge->Destroy();
523
0
    }
524
0
    indirectBridgeParents.clear();
525
0
526
0
    // Ensure we are not holding the sIndirectLayerTreesLock here because we
527
0
    // are going to block on WR threads in order to shut it down properly.
528
0
    mWrBridge->Destroy();
529
0
    mWrBridge = nullptr;
530
0
    if (mAsyncImageManager) {
531
0
      mAsyncImageManager->Destroy();
532
0
      // WebRenderAPI should be already destructed
533
0
      mAsyncImageManager = nullptr;
534
0
    }
535
0
  }
536
0
537
0
  if (mCompositor) {
538
0
    mCompositor->DetachWidget();
539
0
    mCompositor->Destroy();
540
0
    mCompositor = nullptr;
541
0
  }
542
0
543
0
  // This must be destroyed now since it accesses the widget.
544
0
  if (mCompositorScheduler) {
545
0
    mCompositorScheduler->Destroy();
546
0
    mCompositorScheduler = nullptr;
547
0
  }
548
0
549
0
  // After this point, it is no longer legal to access the widget.
550
0
  mWidget = nullptr;
551
0
552
0
  // Clear mAnimationStorage here to ensure that the compositor thread
553
0
  // still exists when we destroy it.
554
0
  mAnimationStorage = nullptr;
555
0
}
556
557
mozilla::ipc::IPCResult
558
CompositorBridgeParent::RecvWillClose()
559
0
{
560
0
  StopAndClearResources();
561
0
  // Once we get the WillClose message, the client side is going to go away
562
0
  // soon and we can't be guaranteed that sending messages will work.
563
0
  mCanSend = false;
564
0
  return IPC_OK();
565
0
}
566
567
void CompositorBridgeParent::DeferredDestroy()
568
0
{
569
0
  MOZ_ASSERT(!NS_IsMainThread());
570
0
  mSelfRef = nullptr;
571
0
}
572
573
mozilla::ipc::IPCResult
574
CompositorBridgeParent::RecvPause()
575
0
{
576
0
  PauseComposition();
577
0
  return IPC_OK();
578
0
}
579
580
mozilla::ipc::IPCResult
581
CompositorBridgeParent::RecvResume()
582
0
{
583
0
  ResumeComposition();
584
0
  return IPC_OK();
585
0
}
586
587
mozilla::ipc::IPCResult
588
CompositorBridgeParent::RecvMakeSnapshot(const SurfaceDescriptor& aInSnapshot,
589
                                         const gfx::IntRect& aRect)
590
0
{
591
0
  RefPtr<DrawTarget> target = GetDrawTargetForDescriptor(aInSnapshot, gfx::BackendType::CAIRO);
592
0
  MOZ_ASSERT(target);
593
0
  if (!target) {
594
0
    // We kill the content process rather than have it continue with an invalid
595
0
    // snapshot, that may be too harsh and we could decide to return some sort
596
0
    // of error to the child process and let it deal with it...
597
0
    return IPC_FAIL_NO_REASON(this);
598
0
  }
599
0
  ForceComposeToTarget(target, &aRect);
600
0
  return IPC_OK();
601
0
}
602
603
mozilla::ipc::IPCResult
604
CompositorBridgeParent::RecvWaitOnTransactionProcessed()
605
0
{
606
0
  return IPC_OK();
607
0
}
608
609
mozilla::ipc::IPCResult
610
CompositorBridgeParent::RecvFlushRendering()
611
0
{
612
0
  if (mWrBridge) {
613
0
    mWrBridge->FlushRendering();
614
0
    return IPC_OK();
615
0
  }
616
0
617
0
  if (mCompositorScheduler->NeedsComposite()) {
618
0
    CancelCurrentCompositeTask();
619
0
    ForceComposeToTarget(nullptr);
620
0
  }
621
0
  return IPC_OK();
622
0
}
623
624
mozilla::ipc::IPCResult
625
CompositorBridgeParent::RecvFlushRenderingAsync()
626
0
{
627
0
  if (mWrBridge) {
628
0
    mWrBridge->FlushRendering(false);
629
0
    return IPC_OK();
630
0
  }
631
0
632
0
  return RecvFlushRendering();
633
0
}
634
635
mozilla::ipc::IPCResult
636
CompositorBridgeParent::RecvForcePresent()
637
0
{
638
0
  if (mWrBridge) {
639
0
    mWrBridge->ScheduleGenerateFrame();
640
0
  }
641
0
  // During the shutdown sequence mLayerManager may be null
642
0
  if (mLayerManager) {
643
0
    mLayerManager->ForcePresent();
644
0
  }
645
0
  return IPC_OK();
646
0
}
647
648
mozilla::ipc::IPCResult
649
CompositorBridgeParent::RecvNotifyRegionInvalidated(const nsIntRegion& aRegion)
650
0
{
651
0
  if (mLayerManager) {
652
0
    mLayerManager->AddInvalidRegion(aRegion);
653
0
  }
654
0
  return IPC_OK();
655
0
}
656
657
void
658
CompositorBridgeParent::Invalidate()
659
0
{
660
0
  if (mLayerManager) {
661
0
    mLayerManager->InvalidateAll();
662
0
  }
663
0
}
664
665
mozilla::ipc::IPCResult
666
CompositorBridgeParent::RecvStartFrameTimeRecording(const int32_t& aBufferSize, uint32_t* aOutStartIndex)
667
0
{
668
0
  if (mLayerManager) {
669
0
    *aOutStartIndex = mLayerManager->StartFrameTimeRecording(aBufferSize);
670
0
  } else if (mWrBridge) {
671
0
    *aOutStartIndex = mWrBridge->StartFrameTimeRecording(aBufferSize);
672
0
  } else {
673
0
    *aOutStartIndex = 0;
674
0
  }
675
0
  return IPC_OK();
676
0
}
677
678
mozilla::ipc::IPCResult
679
CompositorBridgeParent::RecvStopFrameTimeRecording(const uint32_t& aStartIndex,
680
                                                   InfallibleTArray<float>* intervals)
681
0
{
682
0
  if (mLayerManager) {
683
0
    mLayerManager->StopFrameTimeRecording(aStartIndex, *intervals);
684
0
  } else if (mWrBridge) {
685
0
    mWrBridge->StopFrameTimeRecording(aStartIndex, *intervals);
686
0
  }
687
0
  return IPC_OK();
688
0
}
689
690
void
691
CompositorBridgeParent::ActorDestroy(ActorDestroyReason why)
692
0
{
693
0
  mCanSend = false;
694
0
695
0
  StopAndClearResources();
696
0
697
0
  RemoveCompositor(mCompositorBridgeID);
698
0
699
0
  mCompositionManager = nullptr;
700
0
701
0
  { // scope lock
702
0
    MonitorAutoLock lock(*sIndirectLayerTreesLock);
703
0
    sIndirectLayerTrees.erase(mRootLayerTreeID);
704
0
  }
705
0
706
0
  // There are chances that the ref count reaches zero on the main thread shortly
707
0
  // after this function returns while some ipdl code still needs to run on
708
0
  // this thread.
709
0
  // We must keep the compositor parent alive untill the code handling message
710
0
  // reception is finished on this thread.
711
0
  mSelfRef = this;
712
0
  MessageLoop::current()->PostTask(
713
0
    NewRunnableMethod("layers::CompositorBridgeParent::DeferredDestroy",
714
0
                      this,
715
0
                      &CompositorBridgeParent::DeferredDestroy));
716
0
}
717
718
void
719
CompositorBridgeParent::ScheduleRenderOnCompositorThread()
720
0
{
721
0
  MOZ_ASSERT(CompositorLoop());
722
0
  CompositorLoop()->PostTask(
723
0
    NewRunnableMethod("layers::CompositorBridgeParent::ScheduleComposition",
724
0
                      this,
725
0
                      &CompositorBridgeParent::ScheduleComposition));
726
0
}
727
728
void
729
CompositorBridgeParent::InvalidateOnCompositorThread()
730
0
{
731
0
  MOZ_ASSERT(CompositorLoop());
732
0
  CompositorLoop()->PostTask(
733
0
    NewRunnableMethod("layers::CompositorBridgeParent::Invalidate",
734
0
                      this,
735
0
                      &CompositorBridgeParent::Invalidate));
736
0
}
737
738
void
739
CompositorBridgeParent::PauseComposition()
740
0
{
741
0
  MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread(),
742
0
             "PauseComposition() can only be called on the compositor thread");
743
0
744
0
  MonitorAutoLock lock(mPauseCompositionMonitor);
745
0
746
0
  if (!mPaused) {
747
0
    mPaused = true;
748
0
749
0
    if (mCompositor) {
750
0
      mCompositor->Pause();
751
0
    } else if (mWrBridge) {
752
0
      mWrBridge->Pause();
753
0
    }
754
0
    TimeStamp now = TimeStamp::Now();
755
0
    DidComposite(now, now);
756
0
  }
757
0
758
0
  // if anyone's waiting to make sure that composition really got paused, tell them
759
0
  lock.NotifyAll();
760
0
}
761
762
void
763
CompositorBridgeParent::ResumeComposition()
764
0
{
765
0
  MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread(),
766
0
             "ResumeComposition() can only be called on the compositor thread");
767
0
768
0
  MonitorAutoLock lock(mResumeCompositionMonitor);
769
0
770
0
  bool resumed = mOptions.UseWebRender() ? mWrBridge->Resume() : mCompositor->Resume();
771
0
  if (!resumed) {
772
#ifdef MOZ_WIDGET_ANDROID
773
    // We can't get a surface. This could be because the activity changed between
774
    // the time resume was scheduled and now.
775
    __android_log_print(ANDROID_LOG_INFO, "CompositorBridgeParent", "Unable to renew compositor surface; remaining in paused state");
776
#endif
777
    lock.NotifyAll();
778
0
    return;
779
0
  }
780
0
781
0
  mPaused = false;
782
0
783
0
  Invalidate();
784
0
  mCompositorScheduler->ForceComposeToTarget(nullptr, nullptr);
785
0
786
0
  // if anyone's waiting to make sure that composition really got resumed, tell them
787
0
  lock.NotifyAll();
788
0
}
789
790
void
791
CompositorBridgeParent::ForceComposition()
792
0
{
793
0
  // Cancel the orientation changed state to force composition
794
0
  mForceCompositionTask = nullptr;
795
0
  ScheduleRenderOnCompositorThread();
796
0
}
797
798
void
799
CompositorBridgeParent::CancelCurrentCompositeTask()
800
0
{
801
0
  mCompositorScheduler->CancelCurrentCompositeTask();
802
0
}
803
804
void
805
CompositorBridgeParent::SetEGLSurfaceSize(int width, int height)
806
0
{
807
0
  NS_ASSERTION(mUseExternalSurfaceSize, "Compositor created without UseExternalSurfaceSize provided");
808
0
  mEGLSurfaceSize.SizeTo(width, height);
809
0
  if (mCompositor) {
810
0
    mCompositor->SetDestinationSurfaceSize(gfx::IntSize(mEGLSurfaceSize.width, mEGLSurfaceSize.height));
811
0
  }
812
0
}
813
814
void
815
CompositorBridgeParent::ResumeCompositionAndResize(int width, int height)
816
0
{
817
0
  SetEGLSurfaceSize(width, height);
818
0
  ResumeComposition();
819
0
}
820
821
/*
822
 * This will execute a pause synchronously, waiting to make sure that the compositor
823
 * really is paused.
824
 */
825
void
826
CompositorBridgeParent::SchedulePauseOnCompositorThread()
827
0
{
828
0
  MonitorAutoLock lock(mPauseCompositionMonitor);
829
0
830
0
  MOZ_ASSERT(CompositorLoop());
831
0
  CompositorLoop()->PostTask(
832
0
    NewRunnableMethod("layers::CompositorBridgeParent::PauseComposition",
833
0
                      this,
834
0
                      &CompositorBridgeParent::PauseComposition));
835
0
836
0
  // Wait until the pause has actually been processed by the compositor thread
837
0
  lock.Wait();
838
0
}
839
840
bool
841
CompositorBridgeParent::ScheduleResumeOnCompositorThread()
842
0
{
843
0
  MonitorAutoLock lock(mResumeCompositionMonitor);
844
0
845
0
  MOZ_ASSERT(CompositorLoop());
846
0
  CompositorLoop()->PostTask(
847
0
    NewRunnableMethod("layers::CompositorBridgeParent::ResumeComposition",
848
0
                      this,
849
0
                      &CompositorBridgeParent::ResumeComposition));
850
0
851
0
  // Wait until the resume has actually been processed by the compositor thread
852
0
  lock.Wait();
853
0
854
0
  return !mPaused;
855
0
}
856
857
bool
858
CompositorBridgeParent::ScheduleResumeOnCompositorThread(int width, int height)
859
0
{
860
0
  MonitorAutoLock lock(mResumeCompositionMonitor);
861
0
862
0
  MOZ_ASSERT(CompositorLoop());
863
0
  CompositorLoop()->PostTask(NewRunnableMethod<int, int>(
864
0
    "layers::CompositorBridgeParent::ResumeCompositionAndResize",
865
0
    this,
866
0
    &CompositorBridgeParent::ResumeCompositionAndResize,
867
0
    width,
868
0
    height));
869
0
870
0
  // Wait until the resume has actually been processed by the compositor thread
871
0
  lock.Wait();
872
0
873
0
  return !mPaused;
874
0
}
875
876
void
877
CompositorBridgeParent::ScheduleTask(already_AddRefed<CancelableRunnable> task, int time)
878
0
{
879
0
  if (time == 0) {
880
0
    MessageLoop::current()->PostTask(std::move(task));
881
0
  } else {
882
0
    MessageLoop::current()->PostDelayedTask(std::move(task), time);
883
0
  }
884
0
}
885
886
void
887
CompositorBridgeParent::UpdatePaintTime(LayerTransactionParent* aLayerTree,
888
                                        const TimeDuration& aPaintTime)
889
0
{
890
0
  // We get a lot of paint timings for things with empty transactions.
891
0
  if (!mLayerManager || aPaintTime.ToMilliseconds() < 1.0) {
892
0
    return;
893
0
  }
894
0
895
0
  mLayerManager->SetPaintTime(aPaintTime);
896
0
}
897
898
void
899
CompositorBridgeParent::NotifyShadowTreeTransaction(LayersId aId, bool aIsFirstPaint,
900
    const FocusTarget& aFocusTarget,
901
    bool aScheduleComposite, uint32_t aPaintSequenceNumber,
902
    bool aIsRepeatTransaction, bool aHitTestUpdate)
903
0
{
904
0
  if (!aIsRepeatTransaction &&
905
0
      mLayerManager &&
906
0
      mLayerManager->GetRoot()) {
907
0
    // Process plugin data here to give time for them to update before the next
908
0
    // composition.
909
0
    bool pluginsUpdatedFlag = true;
910
0
    AutoResolveRefLayers resolve(mCompositionManager, this, nullptr,
911
0
                                 &pluginsUpdatedFlag);
912
0
913
0
#if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
914
0
    // If plugins haven't been updated, stop waiting.
915
0
    if (!pluginsUpdatedFlag) {
916
0
      mWaitForPluginsUntil = TimeStamp();
917
0
      mHaveBlockedForPlugins = false;
918
0
    }
919
0
#endif
920
0
921
0
    if (mApzUpdater) {
922
0
      mApzUpdater->UpdateFocusState(mRootLayerTreeID, aId, aFocusTarget);
923
0
      if (aHitTestUpdate) {
924
0
        mApzUpdater->UpdateHitTestingTree(mRootLayerTreeID,
925
0
            mLayerManager->GetRoot(), aIsFirstPaint, aId, aPaintSequenceNumber);
926
0
      }
927
0
    }
928
0
929
0
    mLayerManager->NotifyShadowTreeTransaction();
930
0
  }
931
0
  if (aScheduleComposite) {
932
0
    ScheduleComposition();
933
0
  }
934
0
}
935
936
void
937
CompositorBridgeParent::ScheduleComposition()
938
0
{
939
0
  MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
940
0
  if (mPaused) {
941
0
    return;
942
0
  }
943
0
944
0
  if (mWrBridge) {
945
0
    mWrBridge->ScheduleGenerateFrame();
946
0
  } else {
947
0
    mCompositorScheduler->ScheduleComposition();
948
0
  }
949
0
}
950
951
// Go down the composite layer tree, setting properties to match their
952
// content-side counterparts.
953
/* static */ void
954
CompositorBridgeParent::SetShadowProperties(Layer* aLayer)
955
0
{
956
0
  ForEachNode<ForwardIterator>(
957
0
      aLayer,
958
0
      [] (Layer *layer)
959
0
      {
960
0
        if (Layer* maskLayer = layer->GetMaskLayer()) {
961
0
          SetShadowProperties(maskLayer);
962
0
        }
963
0
        for (size_t i = 0; i < layer->GetAncestorMaskLayerCount(); i++) {
964
0
          SetShadowProperties(layer->GetAncestorMaskLayerAt(i));
965
0
        }
966
0
967
0
        // FIXME: Bug 717688 -- Do these updates in LayerTransactionParent::RecvUpdate.
968
0
        HostLayer* layerCompositor = layer->AsHostLayer();
969
0
        // Set the layerComposite's base transform to the layer's base transform.
970
0
        AnimationArray& animations = layer->GetAnimations();
971
0
        // If there is any animation, the animation value will override
972
0
        // non-animated value later, so we don't need to set the non-animated
973
0
        // value here.
974
0
        if (animations.IsEmpty()) {
975
0
          layerCompositor->SetShadowBaseTransform(layer->GetBaseTransform());
976
0
          layerCompositor->SetShadowTransformSetByAnimation(false);
977
0
          layerCompositor->SetShadowOpacity(layer->GetOpacity());
978
0
          layerCompositor->SetShadowOpacitySetByAnimation(false);
979
0
        }
980
0
        layerCompositor->SetShadowVisibleRegion(layer->GetVisibleRegion());
981
0
        layerCompositor->SetShadowClipRect(layer->GetClipRect());
982
0
      }
983
0
    );
984
0
}
985
986
void
987
CompositorBridgeParent::CompositeToTarget(DrawTarget* aTarget, const gfx::IntRect* aRect)
988
0
{
989
0
  AUTO_PROFILER_TRACING("Paint", "Composite");
990
0
  AUTO_PROFILER_LABEL("CompositorBridgeParent::CompositeToTarget", GRAPHICS);
991
0
992
0
  MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread(),
993
0
             "Composite can only be called on the compositor thread");
994
0
  TimeStamp start = TimeStamp::Now();
995
0
996
0
  if (!CanComposite()) {
997
0
    TimeStamp end = TimeStamp::Now();
998
0
    DidComposite(start, end);
999
0
    return;
1000
0
  }
1001
0
1002
0
#if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
1003
0
  if (!mWaitForPluginsUntil.IsNull() &&
1004
0
      mWaitForPluginsUntil > start) {
1005
0
    mHaveBlockedForPlugins = true;
1006
0
    ScheduleComposition();
1007
0
    return;
1008
0
  }
1009
0
#endif
1010
0
1011
0
  /*
1012
0
   * AutoResolveRefLayers handles two tasks related to Windows and Linux
1013
0
   * plugin window management:
1014
0
   * 1) calculating if we have remote content in the view. If we do not have
1015
0
   * remote content, all plugin windows for this CompositorBridgeParent (window)
1016
0
   * can be hidden since we do not support plugins in chrome when running
1017
0
   * under e10s.
1018
0
   * 2) Updating plugin position, size, and clip. We do this here while the
1019
0
   * remote layer tree is hooked up to to chrome layer tree. This is needed
1020
0
   * since plugin clipping can depend on chrome (for example, due to tab modal
1021
0
   * prompts). Updates in step 2 are applied via an async ipc message sent
1022
0
   * to the main thread.
1023
0
   */
1024
0
  bool hasRemoteContent = false;
1025
0
  bool updatePluginsFlag = true;
1026
0
  AutoResolveRefLayers resolve(mCompositionManager, this,
1027
0
                               &hasRemoteContent,
1028
0
                               &updatePluginsFlag);
1029
0
1030
0
#if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
1031
0
  // We do not support plugins in local content. When switching tabs
1032
0
  // to local pages, hide every plugin associated with the window.
1033
0
  if (!hasRemoteContent && gfxVars::BrowserTabsRemoteAutostart() &&
1034
0
      mCachedPluginData.Length()) {
1035
0
    Unused << SendHideAllPlugins(GetWidget()->GetWidgetKey());
1036
0
    mCachedPluginData.Clear();
1037
0
  }
1038
0
#endif
1039
0
1040
0
  if (aTarget) {
1041
0
    mLayerManager->BeginTransactionWithDrawTarget(aTarget, *aRect);
1042
0
  } else {
1043
0
    mLayerManager->BeginTransaction();
1044
0
  }
1045
0
1046
0
  SetShadowProperties(mLayerManager->GetRoot());
1047
0
1048
0
  if (mForceCompositionTask && !mOverrideComposeReadiness) {
1049
0
    if (mCompositionManager->ReadyForCompose()) {
1050
0
      mForceCompositionTask->Cancel();
1051
0
      mForceCompositionTask = nullptr;
1052
0
    } else {
1053
0
      return;
1054
0
    }
1055
0
  }
1056
0
1057
0
  mCompositionManager->ComputeRotation();
1058
0
1059
0
  TimeStamp time = mTestTime.valueOr(mCompositorScheduler->GetLastComposeTime());
1060
0
  bool requestNextFrame = mCompositionManager->TransformShadowTree(time, mVsyncRate);
1061
0
1062
0
  // Don't eagerly schedule new compositions here when recording or replaying.
1063
0
  // Recording/replaying processes schedule composites at the top of the main
1064
0
  // thread's event loop rather than via PVsync, which can cause the composites
1065
0
  // scheduled here to pile up without any drawing actually happening.
1066
0
  if (requestNextFrame && !recordreplay::IsRecordingOrReplaying()) {
1067
0
    ScheduleComposition();
1068
0
#if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
1069
0
    // If we have visible windowed plugins then we need to wait for content (and
1070
0
    // then the plugins) to have been updated by the active animation.
1071
0
    if (!mPluginWindowsHidden && mCachedPluginData.Length()) {
1072
0
      mWaitForPluginsUntil = mCompositorScheduler->GetLastComposeTime() + (mVsyncRate * 2);
1073
0
    }
1074
0
#endif
1075
0
  }
1076
0
1077
0
  RenderTraceLayers(mLayerManager->GetRoot(), "0000");
1078
0
1079
#ifdef MOZ_DUMP_PAINTING
1080
  if (gfxPrefs::DumpHostLayers()) {
1081
    printf_stderr("Painting --- compositing layer tree:\n");
1082
    mLayerManager->Dump(/* aSorted = */ true);
1083
  }
1084
#endif
1085
  mLayerManager->SetDebugOverlayWantsNextFrame(false);
1086
0
  mLayerManager->EndTransaction(time);
1087
0
1088
0
  if (!aTarget) {
1089
0
    TimeStamp end = TimeStamp::Now();
1090
0
    DidComposite(start, end);
1091
0
  }
1092
0
1093
0
  // We're not really taking advantage of the stored composite-again-time here.
1094
0
  // We might be able to skip the next few composites altogether. However,
1095
0
  // that's a bit complex to implement and we'll get most of the advantage
1096
0
  // by skipping compositing when we detect there's nothing invalid. This is why
1097
0
  // we do "composite until" rather than "composite again at".
1098
0
  //
1099
0
  // TODO(bug 1328602) Figure out what we should do here with the render thread.
1100
0
  if (!mLayerManager->GetCompositeUntilTime().IsNull() ||
1101
0
      mLayerManager->DebugOverlayWantsNextFrame())
1102
0
  {
1103
0
      ScheduleComposition();
1104
0
  }
1105
0
1106
#ifdef COMPOSITOR_PERFORMANCE_WARNING
1107
  TimeDuration executionTime = TimeStamp::Now() - mCompositorScheduler->GetLastComposeTime();
1108
  TimeDuration frameBudget = TimeDuration::FromMilliseconds(15);
1109
  int32_t frameRate = CalculateCompositionFrameRate();
1110
  if (frameRate > 0) {
1111
    frameBudget = TimeDuration::FromSeconds(1.0 / frameRate);
1112
  }
1113
  if (executionTime > frameBudget) {
1114
    printf_stderr("Compositor: Composite execution took %4.1f ms\n",
1115
                  executionTime.ToMilliseconds());
1116
  }
1117
#endif
1118
1119
0
  // 0 -> Full-tilt composite
1120
0
  if (gfxPrefs::LayersCompositionFrameRate() == 0 ||
1121
0
      mLayerManager->AlwaysScheduleComposite())
1122
0
  {
1123
0
    // Special full-tilt composite mode for performance testing
1124
0
    ScheduleComposition();
1125
0
  }
1126
0
1127
0
  // TODO(bug 1328602) Need an equivalent that works with the rende thread.
1128
0
  mLayerManager->SetCompositionTime(TimeStamp());
1129
0
1130
0
  mozilla::Telemetry::AccumulateTimeDelta(mozilla::Telemetry::COMPOSITE_TIME, start);
1131
0
}
1132
1133
mozilla::ipc::IPCResult
1134
CompositorBridgeParent::RecvRemotePluginsReady()
1135
0
{
1136
0
#if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
1137
0
  mWaitForPluginsUntil = TimeStamp();
1138
0
  if (mHaveBlockedForPlugins) {
1139
0
    mHaveBlockedForPlugins = false;
1140
0
    ForceComposeToTarget(nullptr);
1141
0
  } else {
1142
0
    ScheduleComposition();
1143
0
  }
1144
0
  return IPC_OK();
1145
#else
1146
  MOZ_ASSERT_UNREACHABLE("CompositorBridgeParent::RecvRemotePluginsReady calls "
1147
                         "unexpected on this platform.");
1148
  return IPC_FAIL_NO_REASON(this);
1149
#endif
1150
}
1151
1152
void
1153
CompositorBridgeParent::ForceComposeToTarget(DrawTarget* aTarget, const gfx::IntRect* aRect)
1154
0
{
1155
0
  AUTO_PROFILER_LABEL("CompositorBridgeParent::ForceComposeToTarget", GRAPHICS);
1156
0
1157
0
  AutoRestore<bool> override(mOverrideComposeReadiness);
1158
0
  mOverrideComposeReadiness = true;
1159
0
  mCompositorScheduler->ForceComposeToTarget(aTarget, aRect);
1160
0
}
1161
1162
PAPZCTreeManagerParent*
1163
CompositorBridgeParent::AllocPAPZCTreeManagerParent(const LayersId& aLayersId)
1164
0
{
1165
0
  // This should only ever get called in the GPU process.
1166
0
  MOZ_ASSERT(XRE_IsGPUProcess());
1167
0
  // We should only ever get this if APZ is enabled in this compositor.
1168
0
  MOZ_ASSERT(mOptions.UseAPZ());
1169
0
  // The mApzcTreeManager and mApzUpdater should have been created via RecvInitialize()
1170
0
  MOZ_ASSERT(mApzcTreeManager);
1171
0
  MOZ_ASSERT(mApzUpdater);
1172
0
  // The main process should pass in 0 because we assume mRootLayerTreeID
1173
0
  MOZ_ASSERT(!aLayersId.IsValid());
1174
0
1175
0
  MonitorAutoLock lock(*sIndirectLayerTreesLock);
1176
0
  CompositorBridgeParent::LayerTreeState& state = sIndirectLayerTrees[mRootLayerTreeID];
1177
0
  MOZ_ASSERT(state.mParent.get() == this);
1178
0
  MOZ_ASSERT(!state.mApzcTreeManagerParent);
1179
0
  state.mApzcTreeManagerParent = new APZCTreeManagerParent(mRootLayerTreeID, mApzcTreeManager, mApzUpdater);
1180
0
1181
0
  return state.mApzcTreeManagerParent;
1182
0
}
1183
1184
bool
1185
CompositorBridgeParent::DeallocPAPZCTreeManagerParent(PAPZCTreeManagerParent* aActor)
1186
0
{
1187
0
  delete aActor;
1188
0
  return true;
1189
0
}
1190
1191
void
1192
CompositorBridgeParent::AllocateAPZCTreeManagerParent(const MonitorAutoLock& aProofOfLayerTreeStateLock,
1193
                                                      const LayersId& aLayersId,
1194
                                                      LayerTreeState& aState)
1195
0
{
1196
0
  MOZ_ASSERT(aState.mParent == this);
1197
0
  MOZ_ASSERT(mApzcTreeManager);
1198
0
  MOZ_ASSERT(mApzUpdater);
1199
0
  MOZ_ASSERT(!aState.mApzcTreeManagerParent);
1200
0
  aState.mApzcTreeManagerParent = new APZCTreeManagerParent(aLayersId, mApzcTreeManager, mApzUpdater);
1201
0
}
1202
1203
PAPZParent*
1204
CompositorBridgeParent::AllocPAPZParent(const LayersId& aLayersId)
1205
0
{
1206
0
  // The main process should pass in 0 because we assume mRootLayerTreeID
1207
0
  MOZ_ASSERT(!aLayersId.IsValid());
1208
0
1209
0
  RemoteContentController* controller = new RemoteContentController();
1210
0
1211
0
  // Increment the controller's refcount before we return it. This will keep the
1212
0
  // controller alive until it is released by IPDL in DeallocPAPZParent.
1213
0
  controller->AddRef();
1214
0
1215
0
  MonitorAutoLock lock(*sIndirectLayerTreesLock);
1216
0
  CompositorBridgeParent::LayerTreeState& state = sIndirectLayerTrees[mRootLayerTreeID];
1217
0
  MOZ_ASSERT(!state.mController);
1218
0
  state.mController = controller;
1219
0
1220
0
  return controller;
1221
0
}
1222
1223
bool
1224
CompositorBridgeParent::DeallocPAPZParent(PAPZParent* aActor)
1225
0
{
1226
0
  RemoteContentController* controller = static_cast<RemoteContentController*>(aActor);
1227
0
  controller->Release();
1228
0
  return true;
1229
0
}
1230
1231
#if defined(MOZ_WIDGET_ANDROID)
1232
AndroidDynamicToolbarAnimator*
1233
CompositorBridgeParent::GetAndroidDynamicToolbarAnimator()
1234
{
1235
  return mApzcTreeManager ? mApzcTreeManager->GetAndroidDynamicToolbarAnimator() : nullptr;
1236
}
1237
#endif
1238
1239
RefPtr<APZSampler>
1240
CompositorBridgeParent::GetAPZSampler()
1241
0
{
1242
0
  return mApzSampler;
1243
0
}
1244
1245
RefPtr<APZUpdater>
1246
CompositorBridgeParent::GetAPZUpdater()
1247
0
{
1248
0
  return mApzUpdater;
1249
0
}
1250
1251
CompositorBridgeParent*
1252
CompositorBridgeParent::GetCompositorBridgeParentFromLayersId(const LayersId& aLayersId)
1253
0
{
1254
0
  MonitorAutoLock lock(*sIndirectLayerTreesLock);
1255
0
  return sIndirectLayerTrees[aLayersId].mParent;
1256
0
}
1257
1258
/*static*/ RefPtr<CompositorBridgeParent>
1259
CompositorBridgeParent::GetCompositorBridgeParentFromWindowId(const wr::WindowId& aWindowId)
1260
0
{
1261
0
  MonitorAutoLock lock(*sIndirectLayerTreesLock);
1262
0
  for (auto it = sIndirectLayerTrees.begin(); it != sIndirectLayerTrees.end(); it++) {
1263
0
    LayerTreeState* state = &it->second;
1264
0
    if (!state->mWrBridge) {
1265
0
      continue;
1266
0
    }
1267
0
    // state->mWrBridge might be a root WebRenderBridgeParent or one of a content
1268
0
    // process, but in either case the state->mParent will be the same. So we
1269
0
    // don't need to distinguish between the two.
1270
0
    if (RefPtr<wr::WebRenderAPI> api = state->mWrBridge->GetWebRenderAPI()) {
1271
0
      if (api->GetId() == aWindowId) {
1272
0
        return state->mParent;
1273
0
      }
1274
0
    }
1275
0
  }
1276
0
  return nullptr;
1277
0
}
1278
1279
bool
1280
CompositorBridgeParent::CanComposite()
1281
0
{
1282
0
  return mLayerManager &&
1283
0
         mLayerManager->GetRoot() &&
1284
0
         !mPaused;
1285
0
}
1286
1287
void
1288
CompositorBridgeParent::ScheduleRotationOnCompositorThread(const TargetConfig& aTargetConfig,
1289
                                                     bool aIsFirstPaint)
1290
0
{
1291
0
  MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
1292
0
1293
0
  if (!aIsFirstPaint &&
1294
0
      !mCompositionManager->IsFirstPaint() &&
1295
0
      mCompositionManager->RequiresReorientation(aTargetConfig.orientation())) {
1296
0
    if (mForceCompositionTask != nullptr) {
1297
0
      mForceCompositionTask->Cancel();
1298
0
    }
1299
0
    RefPtr<CancelableRunnable> task = NewCancelableRunnableMethod(
1300
0
      "layers::CompositorBridgeParent::ForceComposition",
1301
0
      this,
1302
0
      &CompositorBridgeParent::ForceComposition);
1303
0
    mForceCompositionTask = task;
1304
0
    ScheduleTask(task.forget(), gfxPrefs::OrientationSyncMillis());
1305
0
  }
1306
0
}
1307
1308
void
1309
CompositorBridgeParent::ShadowLayersUpdated(LayerTransactionParent* aLayerTree,
1310
                                            const TransactionInfo& aInfo,
1311
                                            bool aHitTestUpdate)
1312
0
{
1313
0
  const TargetConfig& targetConfig = aInfo.targetConfig();
1314
0
1315
0
  ScheduleRotationOnCompositorThread(targetConfig, aInfo.isFirstPaint());
1316
0
1317
0
  // Instruct the LayerManager to update its render bounds now. Since all the orientation
1318
0
  // change, dimension change would be done at the stage, update the size here is free of
1319
0
  // race condition.
1320
0
  mLayerManager->UpdateRenderBounds(targetConfig.naturalBounds());
1321
0
  mLayerManager->SetRegionToClear(targetConfig.clearRegion());
1322
0
  if (mLayerManager->GetCompositor()) {
1323
0
    mLayerManager->GetCompositor()->SetScreenRotation(targetConfig.rotation());
1324
0
  }
1325
0
1326
0
  mCompositionManager->Updated(aInfo.isFirstPaint(), targetConfig);
1327
0
  Layer* root = aLayerTree->GetRoot();
1328
0
  mLayerManager->SetRoot(root);
1329
0
1330
0
  if (mApzUpdater && !aInfo.isRepeatTransaction()) {
1331
0
    mApzUpdater->UpdateFocusState(mRootLayerTreeID,
1332
0
                                  mRootLayerTreeID,
1333
0
                                  aInfo.focusTarget());
1334
0
1335
0
    if (aHitTestUpdate) {
1336
0
      AutoResolveRefLayers resolve(mCompositionManager);
1337
0
1338
0
      mApzUpdater->UpdateHitTestingTree(
1339
0
        mRootLayerTreeID, root, aInfo.isFirstPaint(),
1340
0
        mRootLayerTreeID, aInfo.paintSequenceNumber());
1341
0
    }
1342
0
  }
1343
0
1344
0
  // The transaction ID might get reset to 1 if the page gets reloaded, see
1345
0
  // https://bugzilla.mozilla.org/show_bug.cgi?id=1145295#c41
1346
0
  // Otherwise, it should be continually increasing.
1347
0
  MOZ_ASSERT(aInfo.id() == TransactionId{1} || aInfo.id() > mPendingTransaction);
1348
0
  mPendingTransaction = aInfo.id();
1349
0
  mRefreshStartTime = aInfo.refreshStart();
1350
0
  mTxnStartTime = aInfo.transactionStart();
1351
0
  mFwdTime = aInfo.fwdTime();
1352
0
1353
0
  if (root) {
1354
0
    SetShadowProperties(root);
1355
0
  }
1356
0
  if (aInfo.scheduleComposite()) {
1357
0
    ScheduleComposition();
1358
0
    if (mPaused) {
1359
0
      TimeStamp now = TimeStamp::Now();
1360
0
      DidComposite(now, now);
1361
0
    }
1362
0
  }
1363
0
  mLayerManager->NotifyShadowTreeTransaction();
1364
0
}
1365
1366
void
1367
CompositorBridgeParent::ScheduleComposite(LayerTransactionParent* aLayerTree)
1368
0
{
1369
0
  ScheduleComposition();
1370
0
}
1371
1372
bool
1373
CompositorBridgeParent::SetTestSampleTime(const LayersId& aId,
1374
                                          const TimeStamp& aTime)
1375
0
{
1376
0
  MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
1377
0
1378
0
  if (aTime.IsNull()) {
1379
0
    return false;
1380
0
  }
1381
0
1382
0
  mTestTime = Some(aTime);
1383
0
1384
0
  if (mWrBridge) {
1385
0
    mWrBridge->FlushRendering();
1386
0
    return true;
1387
0
  }
1388
0
1389
0
  bool testComposite = mCompositionManager &&
1390
0
                       mCompositorScheduler->NeedsComposite();
1391
0
1392
0
  // Update but only if we were already scheduled to animate
1393
0
  if (testComposite) {
1394
0
    AutoResolveRefLayers resolve(mCompositionManager);
1395
0
    bool requestNextFrame = mCompositionManager->TransformShadowTree(aTime, mVsyncRate);
1396
0
    if (!requestNextFrame) {
1397
0
      CancelCurrentCompositeTask();
1398
0
      // Pretend we composited in case someone is wating for this event.
1399
0
      TimeStamp now = TimeStamp::Now();
1400
0
      DidComposite(now, now);
1401
0
    }
1402
0
  }
1403
0
1404
0
  return true;
1405
0
}
1406
1407
void
1408
CompositorBridgeParent::LeaveTestMode(const LayersId& aId)
1409
0
{
1410
0
  mTestTime = Nothing();
1411
0
}
1412
1413
void
1414
CompositorBridgeParent::ApplyAsyncProperties(LayerTransactionParent* aLayerTree,
1415
                                             TransformsToSkip aSkip)
1416
0
{
1417
0
  // NOTE: This should only be used for testing. For example, when mTestTime is
1418
0
  // non-empty, or when called from test-only methods like
1419
0
  // LayerTransactionParent::RecvGetAnimationTransform.
1420
0
1421
0
  // Synchronously update the layer tree
1422
0
  if (aLayerTree->GetRoot()) {
1423
0
    AutoResolveRefLayers resolve(mCompositionManager);
1424
0
    SetShadowProperties(mLayerManager->GetRoot());
1425
0
1426
0
    TimeStamp time = mTestTime.valueOr(mCompositorScheduler->GetLastComposeTime());
1427
0
    bool requestNextFrame =
1428
0
      mCompositionManager->TransformShadowTree(time, mVsyncRate, aSkip);
1429
0
    if (!requestNextFrame) {
1430
0
      CancelCurrentCompositeTask();
1431
0
      // Pretend we composited in case someone is waiting for this event.
1432
0
      TimeStamp now = TimeStamp::Now();
1433
0
      DidComposite(now, now);
1434
0
    }
1435
0
  }
1436
0
}
1437
1438
CompositorAnimationStorage*
1439
CompositorBridgeParent::GetAnimationStorage()
1440
0
{
1441
0
  if (!mAnimationStorage) {
1442
0
    mAnimationStorage = new CompositorAnimationStorage();
1443
0
  }
1444
0
  return mAnimationStorage;
1445
0
}
1446
1447
mozilla::ipc::IPCResult
1448
CompositorBridgeParent::RecvGetFrameUniformity(FrameUniformityData* aOutData)
1449
0
{
1450
0
  mCompositionManager->GetFrameUniformity(aOutData);
1451
0
  return IPC_OK();
1452
0
}
1453
1454
void
1455
CompositorBridgeParent::SetTestAsyncScrollOffset(
1456
    const LayersId& aLayersId,
1457
    const FrameMetrics::ViewID& aScrollId,
1458
    const CSSPoint& aPoint)
1459
0
{
1460
0
  if (mApzUpdater) {
1461
0
    MOZ_ASSERT(aLayersId.IsValid());
1462
0
    mApzUpdater->SetTestAsyncScrollOffset(aLayersId, aScrollId, aPoint);
1463
0
  }
1464
0
}
1465
1466
void
1467
CompositorBridgeParent::SetTestAsyncZoom(
1468
    const LayersId& aLayersId,
1469
    const FrameMetrics::ViewID& aScrollId,
1470
    const LayerToParentLayerScale& aZoom)
1471
0
{
1472
0
  if (mApzUpdater) {
1473
0
    MOZ_ASSERT(aLayersId.IsValid());
1474
0
    mApzUpdater->SetTestAsyncZoom(aLayersId, aScrollId, aZoom);
1475
0
  }
1476
0
}
1477
1478
void
1479
CompositorBridgeParent::FlushApzRepaints(const LayersId& aLayersId)
1480
0
{
1481
0
  MOZ_ASSERT(mApzcTreeManager);
1482
0
  MOZ_ASSERT(mApzUpdater);
1483
0
  MOZ_ASSERT(aLayersId.IsValid());
1484
0
  RefPtr<CompositorBridgeParent> self = this;
1485
0
  mApzUpdater->RunOnControllerThread(aLayersId, NS_NewRunnableFunction(
1486
0
    "layers::CompositorBridgeParent::FlushApzRepaints",
1487
0
    [=]() { self->mApzcTreeManager->FlushApzRepaints(aLayersId); }));
1488
0
}
1489
1490
void
1491
CompositorBridgeParent::GetAPZTestData(const LayersId& aLayersId,
1492
                                       APZTestData* aOutData)
1493
0
{
1494
0
  if (mApzUpdater) {
1495
0
    MOZ_ASSERT(aLayersId.IsValid());
1496
0
    mApzUpdater->GetAPZTestData(aLayersId, aOutData);
1497
0
  }
1498
0
}
1499
1500
void
1501
CompositorBridgeParent::SetConfirmedTargetAPZC(const LayersId& aLayersId,
1502
                                               const uint64_t& aInputBlockId,
1503
                                               const nsTArray<ScrollableLayerGuid>& aTargets)
1504
0
{
1505
0
  if (!mApzcTreeManager || !mApzUpdater) {
1506
0
    return;
1507
0
  }
1508
0
  // Need to specifically bind this since it's overloaded.
1509
0
  void (APZCTreeManager::*setTargetApzcFunc)
1510
0
        (uint64_t, const nsTArray<ScrollableLayerGuid>&) =
1511
0
        &APZCTreeManager::SetTargetAPZC;
1512
0
  RefPtr<Runnable> task =
1513
0
    NewRunnableMethod<uint64_t,
1514
0
                      StoreCopyPassByConstLRef<nsTArray<ScrollableLayerGuid>>>(
1515
0
      "layers::CompositorBridgeParent::SetConfirmedTargetAPZC",
1516
0
      mApzcTreeManager.get(),
1517
0
      setTargetApzcFunc,
1518
0
      aInputBlockId,
1519
0
      aTargets);
1520
0
  mApzUpdater->RunOnControllerThread(aLayersId, task.forget());
1521
0
}
1522
1523
void
1524
CompositorBridgeParent::InitializeLayerManager(const nsTArray<LayersBackend>& aBackendHints)
1525
0
{
1526
0
  NS_ASSERTION(!mLayerManager, "Already initialised mLayerManager");
1527
0
  NS_ASSERTION(!mCompositor,   "Already initialised mCompositor");
1528
0
1529
0
  if (!InitializeAdvancedLayers(aBackendHints, nullptr)) {
1530
0
    mCompositor = NewCompositor(aBackendHints);
1531
0
    if (!mCompositor) {
1532
0
      return;
1533
0
    }
1534
0
    mLayerManager = new LayerManagerComposite(mCompositor);
1535
0
  }
1536
0
  mLayerManager->SetCompositorBridgeID(mCompositorBridgeID);
1537
0
1538
0
  MonitorAutoLock lock(*sIndirectLayerTreesLock);
1539
0
  sIndirectLayerTrees[mRootLayerTreeID].mLayerManager = mLayerManager;
1540
0
}
1541
1542
bool
1543
CompositorBridgeParent::InitializeAdvancedLayers(const nsTArray<LayersBackend>& aBackendHints,
1544
                                                 TextureFactoryIdentifier* aOutIdentifier)
1545
0
{
1546
#ifdef XP_WIN
1547
  if (!mOptions.UseAdvancedLayers()) {
1548
    return false;
1549
  }
1550
1551
  // Currently LayerManagerMLGPU hardcodes a D3D11 device, so we reject using
1552
  // AL if LAYERS_D3D11 isn't in the backend hints.
1553
  if (!aBackendHints.Contains(LayersBackend::LAYERS_D3D11)) {
1554
    return false;
1555
  }
1556
1557
  RefPtr<LayerManagerMLGPU> manager = new LayerManagerMLGPU(mWidget);
1558
  if (!manager->Initialize()) {
1559
    return false;
1560
  }
1561
1562
  if (aOutIdentifier) {
1563
    *aOutIdentifier = manager->GetTextureFactoryIdentifier();
1564
  }
1565
  mLayerManager = manager;
1566
  return true;
1567
#else
1568
  return false;
1569
0
#endif
1570
0
}
1571
1572
RefPtr<Compositor>
1573
CompositorBridgeParent::NewCompositor(const nsTArray<LayersBackend>& aBackendHints)
1574
0
{
1575
0
  for (size_t i = 0; i < aBackendHints.Length(); ++i) {
1576
0
    RefPtr<Compositor> compositor;
1577
0
    if (aBackendHints[i] == LayersBackend::LAYERS_OPENGL) {
1578
0
      compositor = new CompositorOGL(this,
1579
0
                                     mWidget,
1580
0
                                     mEGLSurfaceSize.width,
1581
0
                                     mEGLSurfaceSize.height,
1582
0
                                     mUseExternalSurfaceSize);
1583
0
    } else if (aBackendHints[i] == LayersBackend::LAYERS_BASIC) {
1584
0
#ifdef MOZ_WIDGET_GTK
1585
0
      if (gfxVars::UseXRender()) {
1586
0
        compositor = new X11BasicCompositor(this, mWidget);
1587
0
      } else
1588
0
#endif
1589
0
      {
1590
0
        compositor = new BasicCompositor(this, mWidget);
1591
0
      }
1592
#ifdef XP_WIN
1593
    } else if (aBackendHints[i] == LayersBackend::LAYERS_D3D11) {
1594
      compositor = new CompositorD3D11(this, mWidget);
1595
#endif
1596
    }
1597
0
    nsCString failureReason;
1598
0
1599
0
    // Some software GPU emulation implementations will happily try to create
1600
0
    // unreasonably big surfaces and then fail in awful ways.
1601
0
    // Let's at least limit this to the default max texture size we use for content,
1602
0
    // anything larger than that will fail to render on the content side anyway.
1603
0
    // We can revisit this value and make it even tighter if need be.
1604
0
    const int max_fb_size = 32767;
1605
0
    const LayoutDeviceIntSize size = mWidget->GetClientSize();
1606
0
    if (size.width > max_fb_size || size.height > max_fb_size) {
1607
0
      failureReason = "FEATURE_FAILURE_MAX_FRAMEBUFFER_SIZE";
1608
0
      return nullptr;
1609
0
    }
1610
0
1611
0
    MOZ_ASSERT(!gfxVars::UseWebRender() || aBackendHints[i] == LayersBackend::LAYERS_BASIC);
1612
0
    if (compositor && compositor->Initialize(&failureReason)) {
1613
0
      if (failureReason.IsEmpty()){
1614
0
        failureReason = "SUCCESS";
1615
0
      }
1616
0
1617
0
      // should only report success here
1618
0
      if (aBackendHints[i] == LayersBackend::LAYERS_OPENGL){
1619
0
        Telemetry::Accumulate(Telemetry::OPENGL_COMPOSITING_FAILURE_ID, failureReason);
1620
0
      }
1621
#ifdef XP_WIN
1622
      else if (aBackendHints[i] == LayersBackend::LAYERS_D3D11){
1623
        Telemetry::Accumulate(Telemetry::D3D11_COMPOSITING_FAILURE_ID, failureReason);
1624
      }
1625
#endif
1626
1627
0
      return compositor;
1628
0
    }
1629
0
1630
0
    // report any failure reasons here
1631
0
    if (aBackendHints[i] == LayersBackend::LAYERS_OPENGL){
1632
0
      gfxCriticalNote << "[OPENGL] Failed to init compositor with reason: "
1633
0
                      << failureReason.get();
1634
0
      Telemetry::Accumulate(Telemetry::OPENGL_COMPOSITING_FAILURE_ID, failureReason);
1635
0
    }
1636
#ifdef XP_WIN
1637
    else if (aBackendHints[i] == LayersBackend::LAYERS_D3D11){
1638
      gfxCriticalNote << "[D3D11] Failed to init compositor with reason: "
1639
                      << failureReason.get();
1640
      Telemetry::Accumulate(Telemetry::D3D11_COMPOSITING_FAILURE_ID, failureReason);
1641
    }
1642
#endif
1643
  }
1644
0
1645
0
  return nullptr;
1646
0
}
1647
1648
PLayerTransactionParent*
1649
CompositorBridgeParent::AllocPLayerTransactionParent(const nsTArray<LayersBackend>& aBackendHints,
1650
                                                     const LayersId& aId)
1651
0
{
1652
0
  MOZ_ASSERT(!aId.IsValid());
1653
0
1654
0
  InitializeLayerManager(aBackendHints);
1655
0
1656
0
  if (!mLayerManager) {
1657
0
    NS_WARNING("Failed to initialise Compositor");
1658
0
    LayerTransactionParent* p = new LayerTransactionParent(/* aManager */ nullptr, this, /* aAnimStorage */ nullptr, mRootLayerTreeID, mVsyncRate);
1659
0
    p->AddIPDLReference();
1660
0
    return p;
1661
0
  }
1662
0
1663
0
  mCompositionManager = new AsyncCompositionManager(this, mLayerManager);
1664
0
1665
0
  LayerTransactionParent* p = new LayerTransactionParent(mLayerManager, this, GetAnimationStorage(), mRootLayerTreeID, mVsyncRate);
1666
0
  p->AddIPDLReference();
1667
0
  return p;
1668
0
}
1669
1670
bool
1671
CompositorBridgeParent::DeallocPLayerTransactionParent(PLayerTransactionParent* actor)
1672
0
{
1673
0
  static_cast<LayerTransactionParent*>(actor)->ReleaseIPDLReference();
1674
0
  return true;
1675
0
}
1676
1677
CompositorBridgeParent* CompositorBridgeParent::GetCompositorBridgeParent(uint64_t id)
1678
0
{
1679
0
  AssertIsInCompositorThread();
1680
0
  CompositorMap::iterator it = sCompositorMap->find(id);
1681
0
  return it != sCompositorMap->end() ? it->second : nullptr;
1682
0
}
1683
1684
void CompositorBridgeParent::AddCompositor(CompositorBridgeParent* compositor, uint64_t* outID)
1685
0
{
1686
0
  AssertIsInCompositorThread();
1687
0
1688
0
  static uint64_t sNextID = 1;
1689
0
1690
0
  ++sNextID;
1691
0
  (*sCompositorMap)[sNextID] = compositor;
1692
0
  *outID = sNextID;
1693
0
}
1694
1695
CompositorBridgeParent* CompositorBridgeParent::RemoveCompositor(uint64_t id)
1696
0
{
1697
0
  AssertIsInCompositorThread();
1698
0
1699
0
  CompositorMap::iterator it = sCompositorMap->find(id);
1700
0
  if (it == sCompositorMap->end()) {
1701
0
    return nullptr;
1702
0
  }
1703
0
  CompositorBridgeParent *retval = it->second;
1704
0
  sCompositorMap->erase(it);
1705
0
  return retval;
1706
0
}
1707
1708
void
1709
CompositorBridgeParent::NotifyVsync(const TimeStamp& aTimeStamp, const LayersId& aLayersId)
1710
0
{
1711
0
  MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_GPU);
1712
0
  MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
1713
0
1714
0
  MonitorAutoLock lock(*sIndirectLayerTreesLock);
1715
0
  auto it = sIndirectLayerTrees.find(aLayersId);
1716
0
  if (it == sIndirectLayerTrees.end())
1717
0
    return;
1718
0
1719
0
  CompositorBridgeParent* cbp = it->second.mParent;
1720
0
  if (!cbp || !cbp->mWidget)
1721
0
    return;
1722
0
1723
0
  RefPtr<VsyncObserver> obs = cbp->mWidget->GetVsyncObserver();
1724
0
  if (!obs)
1725
0
    return;
1726
0
1727
0
  obs->NotifyVsync(aTimeStamp);
1728
0
}
1729
1730
mozilla::ipc::IPCResult
1731
CompositorBridgeParent::RecvNotifyChildCreated(const LayersId& child,
1732
                                               CompositorOptions* aOptions)
1733
0
{
1734
0
  MonitorAutoLock lock(*sIndirectLayerTreesLock);
1735
0
  NotifyChildCreated(child);
1736
0
  *aOptions = mOptions;
1737
0
  return IPC_OK();
1738
0
}
1739
1740
mozilla::ipc::IPCResult
1741
CompositorBridgeParent::RecvNotifyChildRecreated(const LayersId& aChild,
1742
                                                 CompositorOptions* aOptions)
1743
0
{
1744
0
  MonitorAutoLock lock(*sIndirectLayerTreesLock);
1745
0
1746
0
  if (sIndirectLayerTrees.find(aChild) != sIndirectLayerTrees.end()) {
1747
0
    NS_WARNING("Invalid to register the same layer tree twice");
1748
0
    return IPC_FAIL_NO_REASON(this);
1749
0
  }
1750
0
1751
0
  NotifyChildCreated(aChild);
1752
0
  *aOptions = mOptions;
1753
0
  return IPC_OK();
1754
0
}
1755
1756
void
1757
CompositorBridgeParent::NotifyChildCreated(LayersId aChild)
1758
0
{
1759
0
  sIndirectLayerTreesLock->AssertCurrentThreadOwns();
1760
0
  sIndirectLayerTrees[aChild].mParent = this;
1761
0
  sIndirectLayerTrees[aChild].mLayerManager = mLayerManager;
1762
0
}
1763
1764
mozilla::ipc::IPCResult
1765
CompositorBridgeParent::RecvMapAndNotifyChildCreated(const LayersId& aChild,
1766
                                                     const base::ProcessId& aOwnerPid,
1767
                                                     CompositorOptions* aOptions)
1768
0
{
1769
0
  // We only use this message when the remote compositor is in the GPU process.
1770
0
  // It is harmless to call it, though.
1771
0
  MOZ_ASSERT(XRE_IsGPUProcess());
1772
0
1773
0
  LayerTreeOwnerTracker::Get()->Map(aChild, aOwnerPid);
1774
0
1775
0
  MonitorAutoLock lock(*sIndirectLayerTreesLock);
1776
0
  NotifyChildCreated(aChild);
1777
0
  *aOptions = mOptions;
1778
0
  return IPC_OK();
1779
0
}
1780
1781
mozilla::ipc::IPCResult
1782
CompositorBridgeParent::RecvAdoptChild(const LayersId& child)
1783
0
{
1784
0
  RefPtr<APZUpdater> oldApzUpdater;
1785
0
  APZCTreeManagerParent* parent;
1786
0
  bool scheduleComposition = false;
1787
0
  RefPtr<CrossProcessCompositorBridgeParent> cpcp;
1788
0
  RefPtr<WebRenderBridgeParent> childWrBridge;
1789
0
1790
0
  { // scope lock
1791
0
    MonitorAutoLock lock(*sIndirectLayerTreesLock);
1792
0
    // If child is already belong to this CompositorBridgeParent,
1793
0
    // no need to handle adopting child.
1794
0
    if (sIndirectLayerTrees[child].mParent == this) {
1795
0
      return IPC_OK();
1796
0
    }
1797
0
1798
0
    if (sIndirectLayerTrees[child].mParent) {
1799
0
      // We currently don't support adopting children from one compositor to
1800
0
      // another if the two compositors don't have the same options.
1801
0
      MOZ_ASSERT(sIndirectLayerTrees[child].mParent->mOptions == mOptions);
1802
0
      oldApzUpdater = sIndirectLayerTrees[child].mParent->mApzUpdater;
1803
0
    }
1804
0
    NotifyChildCreated(child);
1805
0
    if (sIndirectLayerTrees[child].mLayerTree) {
1806
0
      sIndirectLayerTrees[child].mLayerTree->SetLayerManager(mLayerManager, GetAnimationStorage());
1807
0
      // Trigger composition to handle a case that mLayerTree was not composited yet
1808
0
      // by previous CompositorBridgeParent, since nsRefreshDriver might wait composition complete.
1809
0
      scheduleComposition = true;
1810
0
    }
1811
0
    if (mWrBridge) {
1812
0
      childWrBridge = sIndirectLayerTrees[child].mWrBridge;
1813
0
      cpcp = sIndirectLayerTrees[child].mCrossProcessParent;
1814
0
    }
1815
0
    parent = sIndirectLayerTrees[child].mApzcTreeManagerParent;
1816
0
  }
1817
0
1818
0
  if (scheduleComposition) {
1819
0
    ScheduleComposition();
1820
0
  }
1821
0
1822
0
  if (childWrBridge) {
1823
0
    MOZ_ASSERT(mWrBridge);
1824
0
    RefPtr<wr::WebRenderAPI> api = mWrBridge->GetWebRenderAPI();
1825
0
    api = api->Clone();
1826
0
    wr::Epoch newEpoch = childWrBridge->UpdateWebRender(mWrBridge->CompositorScheduler(),
1827
0
                                   api,
1828
0
                                   mWrBridge->AsyncImageManager(),
1829
0
                                   GetAnimationStorage(),
1830
0
                                   mWrBridge->GetTextureFactoryIdentifier());
1831
0
    // Pretend we composited, since parent CompositorBridgeParent was replaced.
1832
0
    TimeStamp now = TimeStamp::Now();
1833
0
    NotifyPipelineRendered(childWrBridge->PipelineId(), newEpoch, now, now);
1834
0
  }
1835
0
1836
0
  if (oldApzUpdater) {
1837
0
    // We don't support moving a child from an APZ-enabled compositor to a
1838
0
    // APZ-disabled compositor. The mOptions assertion above should already
1839
0
    // ensure this, since APZ-ness is one of the things in mOptions. Note
1840
0
    // however it is possible for mApzUpdater to be non-null here with
1841
0
    // oldApzUpdater null, because the child may not have been previously
1842
0
    // composited.
1843
0
    MOZ_ASSERT(mApzUpdater);
1844
0
  }
1845
0
  if (mApzUpdater) {
1846
0
    if (parent) {
1847
0
      MOZ_ASSERT(mApzcTreeManager);
1848
0
      parent->ChildAdopted(mApzcTreeManager, mApzUpdater);
1849
0
    }
1850
0
    mApzUpdater->NotifyLayerTreeAdopted(child, oldApzUpdater);
1851
0
  }
1852
0
  return IPC_OK();
1853
0
}
1854
1855
PWebRenderBridgeParent*
1856
CompositorBridgeParent::AllocPWebRenderBridgeParent(const wr::PipelineId& aPipelineId,
1857
                                                    const LayoutDeviceIntSize& aSize,
1858
                                                    TextureFactoryIdentifier* aTextureFactoryIdentifier,
1859
                                                    wr::IdNamespace* aIdNamespace)
1860
0
{
1861
#ifndef MOZ_BUILD_WEBRENDER
1862
  // Extra guard since this in the parent process and we don't want a malicious
1863
  // child process invoking this codepath before it's ready
1864
  MOZ_RELEASE_ASSERT(false);
1865
#endif
1866
0
  MOZ_ASSERT(wr::AsLayersId(aPipelineId) == mRootLayerTreeID);
1867
0
  MOZ_ASSERT(!mWrBridge);
1868
0
  MOZ_ASSERT(!mCompositor);
1869
0
  MOZ_ASSERT(!mCompositorScheduler);
1870
0
  MOZ_ASSERT(mWidget);
1871
0
1872
0
  RefPtr<widget::CompositorWidget> widget = mWidget;
1873
0
  wr::WrWindowId windowId = wr::NewWindowId();
1874
0
  if (mApzUpdater) {
1875
0
    // If APZ is enabled, we need to register the APZ updater with the window id
1876
0
    // before the updater thread is created in WebRenderAPI::Create, so
1877
0
    // that the callback from the updater thread can find the right APZUpdater.
1878
0
    mApzUpdater->SetWebRenderWindowId(windowId);
1879
0
  }
1880
0
  if (mApzSampler) {
1881
0
    // Same as for mApzUpdater, but for the sampler thread.
1882
0
    mApzSampler->SetWebRenderWindowId(windowId);
1883
0
  }
1884
0
  RefPtr<wr::WebRenderAPI> api = wr::WebRenderAPI::Create(this, std::move(widget), windowId, aSize);
1885
0
  if (!api) {
1886
0
    mWrBridge = WebRenderBridgeParent::CreateDestroyed(aPipelineId);
1887
0
    mWrBridge.get()->AddRef(); // IPDL reference
1888
0
    *aIdNamespace = mWrBridge->GetIdNamespace();
1889
0
    *aTextureFactoryIdentifier = TextureFactoryIdentifier(LayersBackend::LAYERS_NONE);
1890
0
    return mWrBridge;
1891
0
  }
1892
0
  mAsyncImageManager = new AsyncImagePipelineManager(api->Clone());
1893
0
  RefPtr<AsyncImagePipelineManager> asyncMgr = mAsyncImageManager;
1894
0
  wr::TransactionBuilder txn;
1895
0
  txn.SetRootPipeline(aPipelineId);
1896
0
  api->SendTransaction(txn);
1897
0
  RefPtr<CompositorAnimationStorage> animStorage = GetAnimationStorage();
1898
0
  mWrBridge = new WebRenderBridgeParent(this, aPipelineId, mWidget, nullptr, std::move(api), std::move(asyncMgr), std::move(animStorage), mVsyncRate);
1899
0
  mWrBridge.get()->AddRef(); // IPDL reference
1900
0
1901
0
  *aIdNamespace = mWrBridge->GetIdNamespace();
1902
0
  mCompositorScheduler = mWrBridge->CompositorScheduler();
1903
0
  MOZ_ASSERT(mCompositorScheduler);
1904
0
  { // scope lock
1905
0
    MonitorAutoLock lock(*sIndirectLayerTreesLock);
1906
0
    MOZ_ASSERT(sIndirectLayerTrees[mRootLayerTreeID].mWrBridge == nullptr);
1907
0
    sIndirectLayerTrees[mRootLayerTreeID].mWrBridge = mWrBridge;
1908
0
  }
1909
0
  *aTextureFactoryIdentifier = mWrBridge->GetTextureFactoryIdentifier();
1910
0
  return mWrBridge;
1911
0
}
1912
1913
bool
1914
CompositorBridgeParent::DeallocPWebRenderBridgeParent(PWebRenderBridgeParent* aActor)
1915
0
{
1916
#ifndef MOZ_BUILD_WEBRENDER
1917
  // Extra guard since this in the parent process and we don't want a malicious
1918
  // child process invoking this codepath before it's ready
1919
  MOZ_RELEASE_ASSERT(false);
1920
#endif
1921
  WebRenderBridgeParent* parent = static_cast<WebRenderBridgeParent*>(aActor);
1922
0
  {
1923
0
    MonitorAutoLock lock(*sIndirectLayerTreesLock);
1924
0
    auto it = sIndirectLayerTrees.find(wr::AsLayersId(parent->PipelineId()));
1925
0
    if (it != sIndirectLayerTrees.end()) {
1926
0
      it->second.mWrBridge = nullptr;
1927
0
    }
1928
0
  }
1929
0
  parent->Release(); // IPDL reference
1930
0
  return true;
1931
0
}
1932
1933
void
1934
CompositorBridgeParent::NotifyMemoryPressure()
1935
0
{
1936
0
  if (mWrBridge) {
1937
0
    RefPtr<wr::WebRenderAPI> api = mWrBridge->GetWebRenderAPI();
1938
0
    if (api) {
1939
0
      api->NotifyMemoryPressure();
1940
0
    }
1941
0
  }
1942
0
}
1943
1944
void
1945
CompositorBridgeParent::AccumulateMemoryReport(wr::MemoryReport* aReport)
1946
0
{
1947
0
  if (mWrBridge) {
1948
0
    RefPtr<wr::WebRenderAPI> api = mWrBridge->GetWebRenderAPI();
1949
0
    if (api) {
1950
0
      api->AccumulateMemoryReport(aReport);
1951
0
    }
1952
0
  }
1953
0
}
1954
1955
RefPtr<WebRenderBridgeParent>
1956
CompositorBridgeParent::GetWebRenderBridgeParent() const
1957
0
{
1958
0
  return mWrBridge;
1959
0
}
1960
1961
Maybe<TimeStamp>
1962
CompositorBridgeParent::GetTestingTimeStamp() const
1963
0
{
1964
0
  return mTestTime;
1965
0
}
1966
1967
void
1968
EraseLayerState(LayersId aId)
1969
0
{
1970
0
  RefPtr<APZUpdater> apz;
1971
0
1972
0
  { // scope lock
1973
0
    MonitorAutoLock lock(*sIndirectLayerTreesLock);
1974
0
    auto iter = sIndirectLayerTrees.find(aId);
1975
0
    if (iter != sIndirectLayerTrees.end()) {
1976
0
      CompositorBridgeParent* parent = iter->second.mParent;
1977
0
      if (parent) {
1978
0
        apz = parent->GetAPZUpdater();
1979
0
      }
1980
0
      sIndirectLayerTrees.erase(iter);
1981
0
    }
1982
0
  }
1983
0
1984
0
  if (apz) {
1985
0
    apz->NotifyLayerTreeRemoved(aId);
1986
0
  }
1987
0
}
1988
1989
/*static*/ void
1990
CompositorBridgeParent::DeallocateLayerTreeId(LayersId aId)
1991
0
{
1992
0
  MOZ_ASSERT(NS_IsMainThread());
1993
0
  // Here main thread notifies compositor to remove an element from
1994
0
  // sIndirectLayerTrees. This removed element might be queried soon.
1995
0
  // Checking the elements of sIndirectLayerTrees exist or not before using.
1996
0
  if (!CompositorLoop()) {
1997
0
    gfxCriticalError() << "Attempting to post to a invalid Compositor Loop";
1998
0
    return;
1999
0
  }
2000
0
  CompositorLoop()->PostTask(NewRunnableFunction("EraseLayerStateRunnable",
2001
0
                                                 &EraseLayerState, aId));
2002
0
}
2003
2004
static void
2005
UpdateControllerForLayersId(LayersId aLayersId,
2006
                            GeckoContentController* aController)
2007
0
{
2008
0
  // Adopt ref given to us by SetControllerForLayerTree()
2009
0
  MonitorAutoLock lock(*sIndirectLayerTreesLock);
2010
0
  sIndirectLayerTrees[aLayersId].mController =
2011
0
    already_AddRefed<GeckoContentController>(aController);
2012
0
}
2013
2014
ScopedLayerTreeRegistration::ScopedLayerTreeRegistration(APZCTreeManager* aApzctm,
2015
                                                         LayersId aLayersId,
2016
                                                         Layer* aRoot,
2017
                                                         GeckoContentController* aController)
2018
    : mLayersId(aLayersId)
2019
0
{
2020
0
  EnsureLayerTreeMapReady();
2021
0
  MonitorAutoLock lock(*sIndirectLayerTreesLock);
2022
0
  sIndirectLayerTrees[aLayersId].mRoot = aRoot;
2023
0
  sIndirectLayerTrees[aLayersId].mController = aController;
2024
0
}
2025
2026
ScopedLayerTreeRegistration::~ScopedLayerTreeRegistration()
2027
0
{
2028
0
  MonitorAutoLock lock(*sIndirectLayerTreesLock);
2029
0
  sIndirectLayerTrees.erase(mLayersId);
2030
0
}
2031
2032
/*static*/ void
2033
CompositorBridgeParent::SetControllerForLayerTree(LayersId aLayersId,
2034
                                                  GeckoContentController* aController)
2035
0
{
2036
0
  // This ref is adopted by UpdateControllerForLayersId().
2037
0
  aController->AddRef();
2038
0
  CompositorLoop()->PostTask(NewRunnableFunction("UpdateControllerForLayersIdRunnable",
2039
0
                                                 &UpdateControllerForLayersId,
2040
0
                                                 aLayersId,
2041
0
                                                 aController));
2042
0
}
2043
2044
/*static*/ already_AddRefed<IAPZCTreeManager>
2045
CompositorBridgeParent::GetAPZCTreeManager(LayersId aLayersId)
2046
0
{
2047
0
  EnsureLayerTreeMapReady();
2048
0
  MonitorAutoLock lock(*sIndirectLayerTreesLock);
2049
0
  LayerTreeMap::iterator cit = sIndirectLayerTrees.find(aLayersId);
2050
0
  if (sIndirectLayerTrees.end() == cit) {
2051
0
    return nullptr;
2052
0
  }
2053
0
  LayerTreeState* lts = &cit->second;
2054
0
2055
0
  RefPtr<IAPZCTreeManager> apzctm = lts->mParent
2056
0
                                   ? lts->mParent->mApzcTreeManager.get()
2057
0
                                   : nullptr;
2058
0
  return apzctm.forget();
2059
0
}
2060
2061
#if defined(MOZ_GECKO_PROFILER)
2062
static void
2063
InsertVsyncProfilerMarker(TimeStamp aVsyncTimestamp)
2064
0
{
2065
0
  MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
2066
0
  profiler_add_marker(
2067
0
    "VsyncTimestamp",
2068
0
    MakeUnique<VsyncMarkerPayload>(aVsyncTimestamp));
2069
0
}
2070
#endif
2071
2072
/*static */ void
2073
CompositorBridgeParent::PostInsertVsyncProfilerMarker(TimeStamp aVsyncTimestamp)
2074
0
{
2075
0
#if defined(MOZ_GECKO_PROFILER)
2076
0
  // Called in the vsync thread
2077
0
  if (profiler_is_active() && CompositorThreadHolder::IsActive()) {
2078
0
    CompositorLoop()->PostTask(
2079
0
      NewRunnableFunction("InsertVsyncProfilerMarkerRunnable", InsertVsyncProfilerMarker,
2080
0
                          aVsyncTimestamp));
2081
0
  }
2082
0
#endif
2083
0
}
2084
2085
widget::PCompositorWidgetParent*
2086
CompositorBridgeParent::AllocPCompositorWidgetParent(const CompositorWidgetInitData& aInitData)
2087
0
{
2088
0
#if defined(MOZ_WIDGET_SUPPORTS_OOP_COMPOSITING)
2089
0
  if (mWidget) {
2090
0
    // Should not create two widgets on the same compositor.
2091
0
    return nullptr;
2092
0
  }
2093
0
2094
0
  widget::CompositorWidgetParent* widget =
2095
0
    new widget::CompositorWidgetParent(aInitData, mOptions);
2096
0
  widget->AddRef();
2097
0
2098
#ifdef XP_WIN
2099
  if (mOptions.UseWebRender() && DeviceManagerDx::Get()->CanUseDComp()) {
2100
    widget->AsWindows()->EnsureCompositorWindow();
2101
  }
2102
#endif
2103
2104
0
  // Sending the constructor acts as initialization as well.
2105
0
  mWidget = widget;
2106
0
  return widget;
2107
#else
2108
  return nullptr;
2109
#endif
2110
}
2111
2112
bool
2113
CompositorBridgeParent::DeallocPCompositorWidgetParent(PCompositorWidgetParent* aActor)
2114
0
{
2115
0
#if defined(MOZ_WIDGET_SUPPORTS_OOP_COMPOSITING)
2116
0
  static_cast<widget::CompositorWidgetParent*>(aActor)->Release();
2117
0
  return true;
2118
#else
2119
  return false;
2120
#endif
2121
}
2122
2123
bool
2124
CompositorBridgeParent::IsPendingComposite()
2125
0
{
2126
0
  MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
2127
0
  if (!mCompositor) {
2128
0
    return false;
2129
0
  }
2130
0
  return mCompositor->IsPendingComposite();
2131
0
}
2132
2133
void
2134
CompositorBridgeParent::FinishPendingComposite()
2135
0
{
2136
0
  MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
2137
0
  if (!mCompositor) {
2138
0
    return;
2139
0
  }
2140
0
  return mCompositor->FinishPendingComposite();
2141
0
}
2142
2143
CompositorController*
2144
CompositorBridgeParent::LayerTreeState::GetCompositorController() const
2145
0
{
2146
0
  return mParent;
2147
0
}
2148
2149
MetricsSharingController*
2150
CompositorBridgeParent::LayerTreeState::CrossProcessSharingController() const
2151
0
{
2152
0
  return mCrossProcessParent;
2153
0
}
2154
2155
MetricsSharingController*
2156
CompositorBridgeParent::LayerTreeState::InProcessSharingController() const
2157
0
{
2158
0
  return mParent;
2159
0
}
2160
2161
void
2162
CompositorBridgeParent::DidComposite(LayersId aId, TimeStamp& aCompositeStart, TimeStamp& aCompositeEnd)
2163
0
{
2164
0
  MOZ_ASSERT(aId == mRootLayerTreeID);
2165
0
  DidComposite(aCompositeStart, aCompositeEnd);
2166
0
}
2167
2168
void
2169
CompositorBridgeParent::DidComposite(TimeStamp& aCompositeStart,
2170
                                     TimeStamp& aCompositeEnd)
2171
0
{
2172
0
  if (mWrBridge) {
2173
0
    MOZ_ASSERT(false); // This should never get called for a WR compositor
2174
0
  } else {
2175
0
    NotifyDidComposite(mPendingTransaction, aCompositeStart, aCompositeEnd);
2176
#if defined(ENABLE_FRAME_LATENCY_LOG)
2177
    if (mPendingTransaction.IsValid()) {
2178
      if (mRefreshStartTime) {
2179
        int32_t latencyMs = lround((aCompositeEnd - mRefreshStartTime).ToMilliseconds());
2180
        printf_stderr("From transaction start to end of generate frame latencyMs %d this %p\n", latencyMs, this);
2181
      }
2182
      if (mFwdTime) {
2183
        int32_t latencyMs = lround((aCompositeEnd - mFwdTime).ToMilliseconds());
2184
        printf_stderr("From forwarding transaction to end of generate frame latencyMs %d this %p\n", latencyMs, this);
2185
      }
2186
    }
2187
    mRefreshStartTime = TimeStamp();
2188
    mTxnStartTime = TimeStamp();
2189
    mFwdTime = TimeStamp();
2190
#endif
2191
    mPendingTransaction = TransactionId{0};
2192
0
  }
2193
0
}
2194
2195
void
2196
CompositorBridgeParent::NotifyPipelineRendered(const wr::PipelineId& aPipelineId,
2197
                                               const wr::Epoch& aEpoch,
2198
                                               TimeStamp& aCompositeStart,
2199
                                               TimeStamp& aCompositeEnd)
2200
0
{
2201
0
  if (!mWrBridge) {
2202
0
    return;
2203
0
  }
2204
0
2205
0
  if (mWrBridge->PipelineId() == aPipelineId) {
2206
0
    mWrBridge->RemoveEpochDataPriorTo(aEpoch);
2207
0
2208
0
    if (!mPaused) {
2209
0
      TransactionId transactionId = mWrBridge->FlushTransactionIdsForEpoch(aEpoch, aCompositeEnd);
2210
0
      Unused << SendDidComposite(LayersId{0}, transactionId, aCompositeStart, aCompositeEnd);
2211
0
2212
0
      nsTArray<ImageCompositeNotificationInfo> notifications;
2213
0
      mWrBridge->ExtractImageCompositeNotifications(&notifications);
2214
0
      if (!notifications.IsEmpty()) {
2215
0
        Unused << ImageBridgeParent::NotifyImageComposites(notifications);
2216
0
      }
2217
0
    }
2218
0
    return;
2219
0
  }
2220
0
2221
0
  MonitorAutoLock lock(*sIndirectLayerTreesLock);
2222
0
  ForEachIndirectLayerTree([&] (LayerTreeState* lts, const LayersId& aLayersId) -> void {
2223
0
    if (lts->mCrossProcessParent &&
2224
0
        lts->mWrBridge &&
2225
0
        lts->mWrBridge->PipelineId() == aPipelineId) {
2226
0
2227
0
      lts->mWrBridge->RemoveEpochDataPriorTo(aEpoch);
2228
0
2229
0
      if (!mPaused) {
2230
0
        CrossProcessCompositorBridgeParent* cpcp = lts->mCrossProcessParent;
2231
0
        TransactionId transactionId = lts->mWrBridge->FlushTransactionIdsForEpoch(aEpoch, aCompositeEnd);
2232
0
        Unused << cpcp->SendDidComposite(aLayersId, transactionId, aCompositeStart, aCompositeEnd);
2233
0
      }
2234
0
    }
2235
0
  });
2236
0
}
2237
2238
RefPtr<AsyncImagePipelineManager>
2239
CompositorBridgeParent::GetAsyncImagePipelineManager() const
2240
0
{
2241
0
  return mAsyncImageManager;
2242
0
}
2243
2244
void
2245
CompositorBridgeParent::NotifyDidComposite(TransactionId aTransactionId, TimeStamp& aCompositeStart, TimeStamp& aCompositeEnd)
2246
0
{
2247
0
  MOZ_ASSERT(!mWrBridge); // We should be going through NotifyPipelineRendered instead
2248
0
2249
0
  Unused << SendDidComposite(LayersId{0}, aTransactionId, aCompositeStart, aCompositeEnd);
2250
0
2251
0
  if (mLayerManager) {
2252
0
    nsTArray<ImageCompositeNotificationInfo> notifications;
2253
0
    mLayerManager->ExtractImageCompositeNotifications(&notifications);
2254
0
    if (!notifications.IsEmpty()) {
2255
0
      Unused << ImageBridgeParent::NotifyImageComposites(notifications);
2256
0
    }
2257
0
  }
2258
0
2259
0
  MonitorAutoLock lock(*sIndirectLayerTreesLock);
2260
0
  ForEachIndirectLayerTree([&] (LayerTreeState* lts, const LayersId& aLayersId) -> void {
2261
0
    if (lts->mCrossProcessParent && lts->mParent == this) {
2262
0
      CrossProcessCompositorBridgeParent* cpcp = lts->mCrossProcessParent;
2263
0
      cpcp->DidCompositeLocked(aLayersId, aCompositeStart, aCompositeEnd);
2264
0
    }
2265
0
  });
2266
0
}
2267
2268
void
2269
CompositorBridgeParent::InvalidateRemoteLayers()
2270
0
{
2271
0
  MOZ_ASSERT(CompositorLoop() == MessageLoop::current());
2272
0
2273
0
  Unused << PCompositorBridgeParent::SendInvalidateLayers(LayersId{0});
2274
0
2275
0
  MonitorAutoLock lock(*sIndirectLayerTreesLock);
2276
0
  ForEachIndirectLayerTree([] (LayerTreeState* lts, const LayersId& aLayersId) -> void {
2277
0
    if (lts->mCrossProcessParent) {
2278
0
      CrossProcessCompositorBridgeParent* cpcp = lts->mCrossProcessParent;
2279
0
      Unused << cpcp->SendInvalidateLayers(aLayersId);
2280
0
    }
2281
0
  });
2282
0
}
2283
2284
void
2285
UpdateIndirectTree(LayersId aId, Layer* aRoot, const TargetConfig& aTargetConfig)
2286
0
{
2287
0
  MonitorAutoLock lock(*sIndirectLayerTreesLock);
2288
0
  sIndirectLayerTrees[aId].mRoot = aRoot;
2289
0
  sIndirectLayerTrees[aId].mTargetConfig = aTargetConfig;
2290
0
}
2291
2292
/* static */ CompositorBridgeParent::LayerTreeState*
2293
CompositorBridgeParent::GetIndirectShadowTree(LayersId aId)
2294
0
{
2295
0
  // Only the compositor thread should use this method variant
2296
0
  MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
2297
0
2298
0
  MonitorAutoLock lock(*sIndirectLayerTreesLock);
2299
0
  LayerTreeMap::iterator cit = sIndirectLayerTrees.find(aId);
2300
0
  if (sIndirectLayerTrees.end() == cit) {
2301
0
    return nullptr;
2302
0
  }
2303
0
  return &cit->second;
2304
0
}
2305
2306
/* static */ bool
2307
CompositorBridgeParent::CallWithIndirectShadowTree(LayersId aId,
2308
                                                   const std::function<void(CompositorBridgeParent::LayerTreeState&)>& aFunc)
2309
0
{
2310
0
  // Note that this does not make things universally threadsafe just because the
2311
0
  // sIndirectLayerTreesLock mutex is held. This is because the compositor
2312
0
  // thread can mutate the LayerTreeState outside the lock. It does however
2313
0
  // ensure that the *storage* for the LayerTreeState remains stable, since we
2314
0
  // should always hold the lock when adding/removing entries to the map.
2315
0
  MonitorAutoLock lock(*sIndirectLayerTreesLock);
2316
0
  LayerTreeMap::iterator cit = sIndirectLayerTrees.find(aId);
2317
0
  if (sIndirectLayerTrees.end() == cit) {
2318
0
    return false;
2319
0
  }
2320
0
  aFunc(cit->second);
2321
0
  return true;
2322
0
}
2323
2324
static CompositorBridgeParent::LayerTreeState*
2325
GetStateForRoot(LayersId aContentLayersId, const MonitorAutoLock& aProofOfLock)
2326
0
{
2327
0
  CompositorBridgeParent::LayerTreeState* state = nullptr;
2328
0
  LayerTreeMap::iterator itr = sIndirectLayerTrees.find(aContentLayersId);
2329
0
  if (sIndirectLayerTrees.end() != itr) {
2330
0
    state = &itr->second;
2331
0
  }
2332
0
2333
0
  // |state| is the state for the content process, but we want the APZCTMParent
2334
0
  // for the parent process owning that content process. So we have to jump to
2335
0
  // the LayerTreeState for the root layer tree id for that layer tree, and use
2336
0
  // the mApzcTreeManagerParent from that. This should also work with nested
2337
0
  // content processes, because RootLayerTreeId() will bypass any intermediate
2338
0
  // processes' ids and go straight to the root.
2339
0
  if (state) {
2340
0
    LayersId rootLayersId = state->mParent->RootLayerTreeId();
2341
0
    itr = sIndirectLayerTrees.find(rootLayersId);
2342
0
    state = (sIndirectLayerTrees.end() != itr) ? &itr->second : nullptr;
2343
0
  }
2344
0
2345
0
  return state;
2346
0
}
2347
2348
/* static */ APZCTreeManagerParent*
2349
CompositorBridgeParent::GetApzcTreeManagerParentForRoot(LayersId aContentLayersId)
2350
0
{
2351
0
  MonitorAutoLock lock(*sIndirectLayerTreesLock);
2352
0
  CompositorBridgeParent::LayerTreeState* state =
2353
0
      GetStateForRoot(aContentLayersId, lock);
2354
0
  return state ? state->mApzcTreeManagerParent : nullptr;
2355
0
}
2356
2357
/* static */ GeckoContentController*
2358
CompositorBridgeParent::GetGeckoContentControllerForRoot(LayersId aContentLayersId)
2359
0
{
2360
0
  MonitorAutoLock lock(*sIndirectLayerTreesLock);
2361
0
  CompositorBridgeParent::LayerTreeState* state =
2362
0
      GetStateForRoot(aContentLayersId, lock);
2363
0
  return state ? state->mController.get() : nullptr;
2364
0
}
2365
2366
PTextureParent*
2367
CompositorBridgeParent::AllocPTextureParent(const SurfaceDescriptor& aSharedData,
2368
                                            const ReadLockDescriptor& aReadLock,
2369
                                            const LayersBackend& aLayersBackend,
2370
                                            const TextureFlags& aFlags,
2371
                                            const LayersId& aId,
2372
                                            const uint64_t& aSerial,
2373
                                            const wr::MaybeExternalImageId& aExternalImageId)
2374
0
{
2375
0
  return TextureHost::CreateIPDLActor(this, aSharedData, aReadLock, aLayersBackend, aFlags, aSerial, aExternalImageId);
2376
0
}
2377
2378
bool
2379
CompositorBridgeParent::DeallocPTextureParent(PTextureParent* actor)
2380
0
{
2381
0
  return TextureHost::DestroyIPDLActor(actor);
2382
0
}
2383
2384
bool
2385
CompositorBridgeParent::IsSameProcess() const
2386
0
{
2387
0
  return OtherPid() == base::GetCurrentProcId();
2388
0
}
2389
2390
void
2391
CompositorBridgeParent::NotifyWebRenderError(wr::WebRenderError aError)
2392
0
{
2393
0
  MOZ_ASSERT(CompositorLoop() == MessageLoop::current());
2394
0
  Unused << SendNotifyWebRenderError(aError);
2395
0
}
2396
2397
void
2398
CompositorBridgeParent::NotifyWebRenderContextPurge()
2399
0
{
2400
0
  MOZ_ASSERT(CompositorLoop() == MessageLoop::current());
2401
0
  RefPtr<wr::WebRenderAPI> api = mWrBridge->GetWebRenderAPI();
2402
0
  api->ClearAllCaches();
2403
0
}
2404
2405
#if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
2406
//#define PLUGINS_LOG(...) printf_stderr("CP [%s]: ", __FUNCTION__);
2407
//                         printf_stderr(__VA_ARGS__);
2408
//                         printf_stderr("\n");
2409
#define PLUGINS_LOG(...)
2410
2411
bool
2412
CompositorBridgeParent::UpdatePluginWindowState(LayersId aId)
2413
0
{
2414
0
  MonitorAutoLock lock(*sIndirectLayerTreesLock);
2415
0
  CompositorBridgeParent::LayerTreeState& lts = sIndirectLayerTrees[aId];
2416
0
  if (!lts.mParent) {
2417
0
    PLUGINS_LOG("[%" PRIu64 "] layer tree compositor parent pointer is null", aId);
2418
0
    return false;
2419
0
  }
2420
0
2421
0
  // Check if this layer tree has received any shadow layer updates
2422
0
  if (!lts.mUpdatedPluginDataAvailable) {
2423
0
    PLUGINS_LOG("[%" PRIu64 "] no plugin data", aId);
2424
0
    return false;
2425
0
  }
2426
0
2427
0
  // pluginMetricsChanged tracks whether we need to send plugin update
2428
0
  // data to the main thread. If we do we'll have to block composition,
2429
0
  // which we want to avoid if at all possible.
2430
0
  bool pluginMetricsChanged = false;
2431
0
2432
0
  // Same layer tree checks
2433
0
  if (mLastPluginUpdateLayerTreeId == aId) {
2434
0
    // no plugin data and nothing has changed, bail.
2435
0
    if (!mCachedPluginData.Length() && !lts.mPluginData.Length()) {
2436
0
      PLUGINS_LOG("[%" PRIu64 "] no data, no changes", aId);
2437
0
      return false;
2438
0
    }
2439
0
2440
0
    if (mCachedPluginData.Length() == lts.mPluginData.Length()) {
2441
0
      // check for plugin data changes
2442
0
      for (uint32_t idx = 0; idx < lts.mPluginData.Length(); idx++) {
2443
0
        if (!(mCachedPluginData[idx] == lts.mPluginData[idx])) {
2444
0
          pluginMetricsChanged = true;
2445
0
          break;
2446
0
        }
2447
0
      }
2448
0
    } else {
2449
0
      // array lengths don't match, need to update
2450
0
      pluginMetricsChanged = true;
2451
0
    }
2452
0
  } else {
2453
0
    // exchanging layer trees, we need to update
2454
0
    pluginMetricsChanged = true;
2455
0
  }
2456
0
2457
0
  // Check if plugin windows are currently hidden due to scrolling
2458
0
  if (mDeferPluginWindows) {
2459
0
    PLUGINS_LOG("[%" PRIu64 "] suppressing", aId);
2460
0
    return false;
2461
0
  }
2462
0
2463
0
  // If the plugin windows were hidden but now are not, we need to force
2464
0
  // update the metrics to make sure they are visible again.
2465
0
  if (mPluginWindowsHidden) {
2466
0
    PLUGINS_LOG("[%" PRIu64 "] re-showing", aId);
2467
0
    mPluginWindowsHidden = false;
2468
0
    pluginMetricsChanged = true;
2469
0
  }
2470
0
2471
0
  if (!lts.mPluginData.Length()) {
2472
0
    // Don't hide plugins if the previous remote layer tree didn't contain any.
2473
0
    if (!mCachedPluginData.Length()) {
2474
0
      PLUGINS_LOG("[%" PRIu64 "] nothing to hide", aId);
2475
0
      return false;
2476
0
    }
2477
0
2478
0
    uintptr_t parentWidget = GetWidget()->GetWidgetKey();
2479
0
2480
0
    // We will pass through here in cases where the previous shadow layer
2481
0
    // tree contained visible plugins and the new tree does not. All we need
2482
0
    // to do here is hide the plugins for the old tree, so don't waste time
2483
0
    // calculating clipping.
2484
0
    mPluginsLayerOffset = nsIntPoint(0,0);
2485
0
    mPluginsLayerVisibleRegion.SetEmpty();
2486
0
    Unused << lts.mParent->SendHideAllPlugins(parentWidget);
2487
0
    lts.mUpdatedPluginDataAvailable = false;
2488
0
    PLUGINS_LOG("[%" PRIu64 "] hide all", aId);
2489
0
  } else {
2490
0
    // Retrieve the offset and visible region of the layer that hosts
2491
0
    // the plugins, CompositorBridgeChild needs these in calculating proper
2492
0
    // plugin clipping.
2493
0
    LayerTransactionParent* layerTree = lts.mLayerTree;
2494
0
    Layer* contentRoot = layerTree->GetRoot();
2495
0
    if (contentRoot) {
2496
0
      nsIntPoint offset;
2497
0
      nsIntRegion visibleRegion;
2498
0
      if (contentRoot->GetVisibleRegionRelativeToRootLayer(visibleRegion,
2499
0
                                                            &offset)) {
2500
0
        // Check to see if these values have changed, if so we need to
2501
0
        // update plugin window position within the window.
2502
0
        if (!pluginMetricsChanged &&
2503
0
            mPluginsLayerVisibleRegion == visibleRegion &&
2504
0
            mPluginsLayerOffset == offset) {
2505
0
          PLUGINS_LOG("[%" PRIu64 "] no change", aId);
2506
0
          return false;
2507
0
        }
2508
0
        mPluginsLayerOffset = offset;
2509
0
        mPluginsLayerVisibleRegion = visibleRegion;
2510
0
        Unused << lts.mParent->SendUpdatePluginConfigurations(
2511
0
          LayoutDeviceIntPoint::FromUnknownPoint(offset),
2512
0
          LayoutDeviceIntRegion::FromUnknownRegion(visibleRegion),
2513
0
          lts.mPluginData);
2514
0
        lts.mUpdatedPluginDataAvailable = false;
2515
0
        PLUGINS_LOG("[%" PRIu64 "] updated", aId);
2516
0
      } else {
2517
0
        PLUGINS_LOG("[%" PRIu64 "] no visibility data", aId);
2518
0
        return false;
2519
0
      }
2520
0
    } else {
2521
0
      PLUGINS_LOG("[%" PRIu64 "] no content root", aId);
2522
0
      return false;
2523
0
    }
2524
0
  }
2525
0
2526
0
  mLastPluginUpdateLayerTreeId = aId;
2527
0
  mCachedPluginData = lts.mPluginData;
2528
0
  return true;
2529
0
}
2530
2531
void
2532
CompositorBridgeParent::ScheduleShowAllPluginWindows()
2533
0
{
2534
0
  MOZ_ASSERT(CompositorLoop());
2535
0
  CompositorLoop()->PostTask(
2536
0
    NewRunnableMethod("layers::CompositorBridgeParent::ShowAllPluginWindows",
2537
0
                      this,
2538
0
                      &CompositorBridgeParent::ShowAllPluginWindows));
2539
0
}
2540
2541
void
2542
CompositorBridgeParent::ShowAllPluginWindows()
2543
0
{
2544
0
  MOZ_ASSERT(!NS_IsMainThread());
2545
0
  mDeferPluginWindows = false;
2546
0
  ScheduleComposition();
2547
0
}
2548
2549
void
2550
CompositorBridgeParent::ScheduleHideAllPluginWindows()
2551
0
{
2552
0
  MOZ_ASSERT(CompositorLoop());
2553
0
  CompositorLoop()->PostTask(
2554
0
    NewRunnableMethod("layers::CompositorBridgeParent::HideAllPluginWindows",
2555
0
                      this,
2556
0
                      &CompositorBridgeParent::HideAllPluginWindows));
2557
0
}
2558
2559
void
2560
CompositorBridgeParent::HideAllPluginWindows()
2561
0
{
2562
0
  MOZ_ASSERT(!NS_IsMainThread());
2563
0
  // No plugins in the cache implies no plugins to manage
2564
0
  // in this content.
2565
0
  if (!mCachedPluginData.Length() || mDeferPluginWindows) {
2566
0
    return;
2567
0
  }
2568
0
2569
0
  uintptr_t parentWidget = GetWidget()->GetWidgetKey();
2570
0
2571
0
  mDeferPluginWindows = true;
2572
0
  mPluginWindowsHidden = true;
2573
0
2574
#if defined(XP_WIN)
2575
  // We will get an async reply that this has happened and then send hide.
2576
  mWaitForPluginsUntil = TimeStamp::Now() + mVsyncRate;
2577
  Unused << SendCaptureAllPlugins(parentWidget);
2578
#else
2579
  Unused << SendHideAllPlugins(parentWidget);
2580
0
  ScheduleComposition();
2581
0
#endif
2582
0
}
2583
#endif // #if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
2584
2585
mozilla::ipc::IPCResult
2586
CompositorBridgeParent::RecvAllPluginsCaptured()
2587
0
{
2588
#if defined(XP_WIN)
2589
  mWaitForPluginsUntil = TimeStamp();
2590
  mHaveBlockedForPlugins = false;
2591
  ForceComposeToTarget(nullptr);
2592
  Unused << SendHideAllPlugins(GetWidget()->GetWidgetKey());
2593
  return IPC_OK();
2594
#else
2595
0
  MOZ_ASSERT_UNREACHABLE(
2596
0
    "CompositorBridgeParent::RecvAllPluginsCaptured calls unexpected.");
2597
0
  return IPC_FAIL_NO_REASON(this);
2598
0
#endif
2599
0
}
2600
2601
} // namespace layers
2602
} // namespace mozilla