tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

CompositorBridgeParent.cpp (68881B)


      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 <utility>   // for pair
     12 
     13 #include "apz/src/APZCTreeManager.h"  // for APZCTreeManager
     14 #include "base/process.h"             // for ProcessId
     15 #include "gfxContext.h"               // for gfxContext
     16 #include "gfxPlatform.h"              // for gfxPlatform
     17 #include "TreeTraversal.h"            // for ForEachNode
     18 #ifdef MOZ_WIDGET_GTK
     19 #  include "gfxPlatformGtk.h"  // for gfxPlatform
     20 #endif
     21 #include "mozilla/AutoRestore.h"      // for AutoRestore
     22 #include "mozilla/ClearOnShutdown.h"  // for ClearOnShutdown
     23 #include "mozilla/DebugOnly.h"        // for DebugOnly
     24 #include "mozilla/StaticPrefs_gfx.h"
     25 #include "mozilla/StaticPrefs_layers.h"
     26 #include "mozilla/StaticPrefs_layout.h"
     27 #include "mozilla/dom/BrowserParent.h"
     28 #include "mozilla/gfx/2D.h"       // for DrawTarget
     29 #include "mozilla/gfx/Point.h"    // for IntSize
     30 #include "mozilla/gfx/Rect.h"     // for IntSize
     31 #include "mozilla/gfx/gfxVars.h"  // for gfxVars
     32 #include "mozilla/gfx/GPUParent.h"
     33 #include "mozilla/gfx/GPUProcessManager.h"
     34 #include "mozilla/layers/APZCTreeManagerParent.h"  // for APZCTreeManagerParent
     35 #include "mozilla/layers/APZSampler.h"             // for APZSampler
     36 #include "mozilla/layers/APZThreadUtils.h"         // for APZThreadUtils
     37 #include "mozilla/layers/APZUpdater.h"             // for APZUpdater
     38 #include "mozilla/layers/CompositionRecorder.h"    // for CompositionRecorder
     39 #include "mozilla/layers/Compositor.h"             // for Compositor
     40 #include "mozilla/layers/CompositorAnimationStorage.h"  // for CompositorAnimationStorage
     41 #include "mozilla/layers/CompositorManagerParent.h"  // for CompositorManagerParent
     42 #include "mozilla/layers/CompositorOGL.h"            // for CompositorOGL
     43 #include "mozilla/layers/CompositorThread.h"
     44 #include "mozilla/layers/CompositorTypes.h"
     45 #include "mozilla/layers/CompositorVsyncScheduler.h"
     46 #include "mozilla/layers/ContentCompositorBridgeParent.h"
     47 #include "mozilla/layers/FrameUniformityData.h"
     48 #include "mozilla/layers/GeckoContentController.h"
     49 #include "mozilla/layers/ImageBridgeParent.h"
     50 #include "mozilla/layers/LayerTreeOwnerTracker.h"
     51 #include "mozilla/layers/LayersTypes.h"
     52 #include "mozilla/layers/OMTASampler.h"
     53 #include "mozilla/layers/RemoteContentController.h"
     54 #include "mozilla/layers/UiCompositorControllerParent.h"
     55 #include "mozilla/layers/WebRenderBridgeParent.h"
     56 #include "mozilla/layers/AsyncImagePipelineManager.h"
     57 #include "mozilla/webrender/WebRenderAPI.h"
     58 #include "mozilla/webrender/RenderThread.h"
     59 #include "mozilla/media/MediaSystemResourceService.h"  // for MediaSystemResourceService
     60 #include "mozilla/mozalloc.h"                          // for operator new, etc
     61 #include "mozilla/ProfilerLabels.h"
     62 #include "mozilla/ProfilerMarkers.h"
     63 #include "mozilla/glean/GfxMetrics.h"
     64 #include "nsCOMPtr.h"         // for already_AddRefed
     65 #include "nsDebug.h"          // for NS_ASSERTION, etc
     66 #include "nsISupportsImpl.h"  // for MOZ_COUNT_CTOR, etc
     67 #include "nsIWidget.h"        // for nsIWidget
     68 #include "nsTArray.h"         // for nsTArray
     69 #include "nsThreadUtils.h"    // for NS_IsMainThread
     70 #ifdef XP_WIN
     71 #  include "mozilla/layers/CompositorD3D11.h"
     72 #  include "mozilla/widget/WinCompositorWidget.h"
     73 #endif
     74 #include "mozilla/ipc/ProtocolTypes.h"
     75 #include "mozilla/Hal.h"
     76 #include "mozilla/HalTypes.h"
     77 #include "mozilla/StaticPtr.h"
     78 #include "mozilla/VsyncDispatcher.h"
     79 #if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
     80 #  include "VsyncSource.h"
     81 #endif
     82 #include "mozilla/widget/CompositorWidget.h"
     83 #ifdef MOZ_WIDGET_SUPPORTS_OOP_COMPOSITING
     84 #  include "mozilla/widget/CompositorWidgetParent.h"
     85 #endif
     86 #ifdef XP_WIN
     87 #  include "mozilla/gfx/DeviceManagerDx.h"
     88 #endif
     89 
     90 namespace mozilla {
     91 
     92 namespace layers {
     93 
     94 using namespace mozilla::ipc;
     95 using namespace mozilla::gfx;
     96 
     97 using base::ProcessId;
     98 
     99 /* static*/
    100 StaticMonitor CompositorBridgeParent::sIndirectLayerTreesLock;
    101 
    102 /* static */
    103 MOZ_RUNINIT CompositorBridgeParent::LayerTreeMap
    104    CompositorBridgeParent::sIndirectLayerTrees MOZ_GUARDED_BY(
    105        CompositorBridgeParent::sIndirectLayerTreesLock);
    106 
    107 CompositorBridgeParentBase::CompositorBridgeParentBase(
    108    CompositorManagerParent* aManager)
    109    : mCanSend(true), mCompositorManager(aManager) {}
    110 
    111 CompositorBridgeParentBase::~CompositorBridgeParentBase() = default;
    112 
    113 ProcessId CompositorBridgeParentBase::GetChildProcessId() { return OtherPid(); }
    114 
    115 dom::ContentParentId CompositorBridgeParentBase::GetContentId() {
    116  return mCompositorManager->GetContentId();
    117 }
    118 
    119 void CompositorBridgeParentBase::NotifyNotUsed(PTextureParent* aTexture,
    120                                               uint64_t aTransactionId) {
    121  RefPtr<TextureHost> texture = TextureHost::AsTextureHost(aTexture);
    122  if (!texture) {
    123    return;
    124  }
    125 
    126  if (!(texture->GetFlags() & TextureFlags::RECYCLE) &&
    127      !(texture->GetFlags() & TextureFlags::WAIT_HOST_USAGE_END)) {
    128    return;
    129  }
    130 
    131  uint64_t textureId = TextureHost::GetTextureSerial(aTexture);
    132  mPendingAsyncMessage.push_back(OpNotifyNotUsed(textureId, aTransactionId));
    133 }
    134 
    135 void CompositorBridgeParentBase::SendAsyncMessage(
    136    const nsTArray<AsyncParentMessageData>& aMessage) {
    137  (void)SendParentAsyncMessages(aMessage);
    138 }
    139 
    140 bool CompositorBridgeParentBase::AllocShmem(size_t aSize, ipc::Shmem* aShmem) {
    141  return PCompositorBridgeParent::AllocShmem(aSize, aShmem);
    142 }
    143 
    144 bool CompositorBridgeParentBase::AllocUnsafeShmem(size_t aSize,
    145                                                  ipc::Shmem* aShmem) {
    146  return PCompositorBridgeParent::AllocUnsafeShmem(aSize, aShmem);
    147 }
    148 
    149 bool CompositorBridgeParentBase::DeallocShmem(ipc::Shmem& aShmem) {
    150  return PCompositorBridgeParent::DeallocShmem(aShmem);
    151 }
    152 
    153 CompositorBridgeParent::LayerTreeState::LayerTreeState()
    154    : mApzcTreeManagerParent(nullptr),
    155      mApzInputBridgeParent(nullptr),
    156      mParent(nullptr),
    157      mContentCompositorBridgeParent(nullptr) {}
    158 
    159 CompositorBridgeParent::LayerTreeState::~LayerTreeState() {
    160  if (mController) {
    161    mController->Destroy();
    162  }
    163 }
    164 
    165 template <typename Lambda>
    166 inline void CompositorBridgeParent::ForEachIndirectLayerTree(
    167    const Lambda& aCallback) {
    168  sIndirectLayerTreesLock.AssertCurrentThreadOwns();
    169  for (auto it = sIndirectLayerTrees.begin(); it != sIndirectLayerTrees.end();
    170       it++) {
    171    LayerTreeState* state = &it->second;
    172    if (state->mParent == this) {
    173      aCallback(state, it->first);
    174    }
    175  }
    176 }
    177 
    178 /*static*/ template <typename Lambda>
    179 inline void CompositorBridgeParent::ForEachWebRenderBridgeParent(
    180    const Lambda& aCallback) {
    181  sIndirectLayerTreesLock.AssertCurrentThreadOwns();
    182  for (auto& it : sIndirectLayerTrees) {
    183    LayerTreeState* state = &it.second;
    184    if (state->mWrBridge) {
    185      aCallback(state->mWrBridge);
    186    }
    187  }
    188 }
    189 
    190 void CompositorBridgeParent::FinishShutdown() {
    191  MOZ_ASSERT(NS_IsMainThread());
    192 
    193  // TODO: this should be empty by now...
    194  StaticMonitorAutoLock lock(sIndirectLayerTreesLock);
    195  sIndirectLayerTrees.clear();
    196 }
    197 
    198 CompositorBridgeParent::CompositorBridgeParent(
    199    CompositorManagerParent* aManager, CSSToLayoutDeviceScale aScale,
    200    const TimeDuration& aVsyncRate, const CompositorOptions& aOptions,
    201    bool aUseExternalSurfaceSize, const gfx::IntSize& aSurfaceSize,
    202    uint64_t aInnerWindowId)
    203    : CompositorBridgeParentBase(aManager),
    204      mWidget(nullptr),
    205      mScale(aScale),
    206      mVsyncRate(aVsyncRate),
    207      mPaused(false),
    208      mHaveCompositionRecorder(false),
    209      mIsForcedFirstPaint(false),
    210      mUseExternalSurfaceSize(aUseExternalSurfaceSize),
    211      mEGLSurfaceSize(aSurfaceSize),
    212      mOptions(aOptions),
    213      mRootLayerTreeID{0},
    214      mInnerWindowId(aInnerWindowId),
    215      mCompositorScheduler(nullptr),
    216      mAnimationStorage(nullptr) {}
    217 
    218 void CompositorBridgeParent::InitSameProcess(widget::CompositorWidget* aWidget,
    219                                             const LayersId& aLayerTreeId) {
    220  MOZ_ASSERT(XRE_IsParentProcess());
    221  MOZ_ASSERT(NS_IsMainThread());
    222 
    223  mWidget = aWidget;
    224  mRootLayerTreeID = aLayerTreeId;
    225 #if defined(XP_WIN)
    226  // when run in headless mode, no WinCompositorWidget is created
    227  if (widget::WinCompositorWidget* windows = mWidget->AsWindows()) {
    228    windows->SetRootLayerTreeID(mRootLayerTreeID);
    229  }
    230 #endif
    231 
    232  Initialize();
    233 }
    234 
    235 bool CompositorBridgeParent::IsPaused() {
    236  MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
    237  return mPaused;
    238 }
    239 
    240 mozilla::ipc::IPCResult CompositorBridgeParent::RecvInitialize(
    241    const LayersId& aRootLayerTreeId) {
    242  MOZ_ASSERT(XRE_IsGPUProcess());
    243 
    244  mRootLayerTreeID = aRootLayerTreeId;
    245 #ifdef XP_WIN
    246  // headless mode is probably always same-process; but just in case...
    247  if (widget::WinCompositorWidget* windows = mWidget->AsWindows()) {
    248    windows->SetRootLayerTreeID(mRootLayerTreeID);
    249  }
    250 #endif
    251 
    252  Initialize();
    253  return IPC_OK();
    254 }
    255 
    256 void CompositorBridgeParent::Initialize() {
    257  MOZ_ASSERT(CompositorThread(),
    258             "The compositor thread must be Initialized before instanciating a "
    259             "CompositorBridgeParent.");
    260 
    261  if (mOptions.UseAPZ()) {
    262    MOZ_ASSERT(!mApzcTreeManager);
    263    MOZ_ASSERT(!mApzSampler);
    264    MOZ_ASSERT(!mApzUpdater);
    265    mApzcTreeManager = APZCTreeManager::Create(mRootLayerTreeID);
    266    mApzSampler = new APZSampler(mApzcTreeManager, true);
    267    mApzUpdater = new APZUpdater(mApzcTreeManager, true);
    268  }
    269 
    270  CompositorAnimationStorage* animationStorage = GetAnimationStorage();
    271  mOMTASampler = new OMTASampler(animationStorage, mRootLayerTreeID);
    272 
    273  mPaused = mOptions.InitiallyPaused();
    274 
    275  {  // scope lock
    276    StaticMonitorAutoLock lock(sIndirectLayerTreesLock);
    277    sIndirectLayerTrees[mRootLayerTreeID].mParent = this;
    278  }
    279 }
    280 
    281 LayersId CompositorBridgeParent::RootLayerTreeId() {
    282  MOZ_ASSERT(mRootLayerTreeID.IsValid());
    283  return mRootLayerTreeID;
    284 }
    285 
    286 CompositorBridgeParent::~CompositorBridgeParent() {
    287  MOZ_DIAGNOSTIC_ASSERT(
    288      !mCanSend,
    289      "ActorDestroy or RecvWillClose should have been called first.");
    290  MOZ_DIAGNOSTIC_ASSERT(mRefCnt == 0,
    291                        "ActorDealloc should have been called first.");
    292  nsTArray<PTextureParent*> textures;
    293  ManagedPTextureParent(textures);
    294  // We expect all textures to be destroyed by now.
    295  MOZ_DIAGNOSTIC_ASSERT(textures.Length() == 0);
    296  for (unsigned int i = 0; i < textures.Length(); ++i) {
    297    RefPtr<TextureHost> tex = TextureHost::AsTextureHost(textures[i]);
    298    tex->DeallocateDeviceData();
    299  }
    300  // Check if WebRender/Compositor was shutdown.
    301  if (mWrBridge) {
    302    gfxCriticalNote << "CompositorBridgeParent destroyed without shutdown";
    303  }
    304 }
    305 
    306 void CompositorBridgeParent::ForceIsFirstPaint() {
    307  if (mWrBridge) {
    308    mIsForcedFirstPaint = true;
    309  }
    310 }
    311 
    312 void CompositorBridgeParent::StopAndClearResources() {
    313  MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
    314  mPaused = true;
    315 
    316  // We need to clear the APZ tree before we destroy the WebRender API below,
    317  // because in the case of async scene building that will shut down the updater
    318  // thread and we need to run the task before that happens.
    319  MOZ_ASSERT((mApzSampler != nullptr) == (mApzcTreeManager != nullptr));
    320  MOZ_ASSERT((mApzUpdater != nullptr) == (mApzcTreeManager != nullptr));
    321  if (mApzUpdater) {
    322    mApzSampler->Destroy();
    323    mApzSampler = nullptr;
    324    mApzUpdater->ClearTree(mRootLayerTreeID);
    325    mApzUpdater = nullptr;
    326    mApzcTreeManager = nullptr;
    327  }
    328 
    329  if (mWrBridge) {
    330    // Ensure we are not holding the sIndirectLayerTreesLock when destroying
    331    // the WebRenderBridgeParent instances because it may block on WR.
    332    std::vector<RefPtr<WebRenderBridgeParent>> indirectBridgeParents;
    333    {  // scope lock
    334      StaticMonitorAutoLock lock(sIndirectLayerTreesLock);
    335      ForEachIndirectLayerTree([&](LayerTreeState* lts, LayersId) -> void {
    336        if (lts->mWrBridge) {
    337          indirectBridgeParents.emplace_back(lts->mWrBridge.forget());
    338        }
    339        lts->mParent = nullptr;
    340      });
    341    }
    342    for (const RefPtr<WebRenderBridgeParent>& bridge : indirectBridgeParents) {
    343      bridge->Destroy();
    344    }
    345    indirectBridgeParents.clear();
    346 
    347    RefPtr<wr::WebRenderAPI> api = mWrBridge->GetWebRenderAPI();
    348    // Ensure we are not holding the sIndirectLayerTreesLock here because we
    349    // are going to block on WR threads in order to shut it down properly.
    350    mWrBridge->Destroy();
    351    mWrBridge = nullptr;
    352 
    353    if (api) {
    354      // Make extra sure we are done cleaning WebRender up before continuing.
    355      // After that we wont have a way to talk to a lot of the webrender parts.
    356      api->FlushSceneBuilder();
    357      api = nullptr;
    358    }
    359 
    360    if (mAsyncImageManager) {
    361      mAsyncImageManager->Destroy();
    362      // WebRenderAPI should be already destructed
    363      mAsyncImageManager = nullptr;
    364    }
    365  }
    366 
    367  // This must be destroyed now since it accesses the widget.
    368  if (mCompositorScheduler) {
    369    mCompositorScheduler->Destroy();
    370    mCompositorScheduler = nullptr;
    371  }
    372 
    373  if (mOMTASampler) {
    374    mOMTASampler->Destroy();
    375    mOMTASampler = nullptr;
    376  }
    377 
    378  // After this point, it is no longer legal to access the widget.
    379  mWidget = nullptr;
    380 
    381  // Clear mAnimationStorage here to ensure that the compositor thread
    382  // still exists when we destroy it.
    383  mAnimationStorage = nullptr;
    384 }
    385 
    386 mozilla::ipc::IPCResult CompositorBridgeParent::RecvWillClose() {
    387  StopAndClearResources();
    388  // Once we get the WillClose message, the client side is going to go away
    389  // soon and we can't be guaranteed that sending messages will work.
    390  mCanSend = false;
    391  return IPC_OK();
    392 }
    393 
    394 void CompositorBridgeParent::DeferredDestroy() {
    395  MOZ_ASSERT(!NS_IsMainThread());
    396  mSelfRef = nullptr;
    397 }
    398 
    399 mozilla::ipc::IPCResult CompositorBridgeParent::RecvPause() {
    400  PauseComposition();
    401  return IPC_OK();
    402 }
    403 
    404 mozilla::ipc::IPCResult CompositorBridgeParent::RecvRequestFxrOutput() {
    405 #ifdef XP_WIN
    406  // Continue forwarding the request to the Widget + SwapChain
    407  mWidget->AsWindows()->RequestFxrOutput();
    408 #endif
    409 
    410  return IPC_OK();
    411 }
    412 
    413 mozilla::ipc::IPCResult CompositorBridgeParent::RecvResume() {
    414  ResumeComposition();
    415  return IPC_OK();
    416 }
    417 
    418 mozilla::ipc::IPCResult CompositorBridgeParent::RecvResumeAsync() {
    419  ResumeComposition();
    420  return IPC_OK();
    421 }
    422 
    423 mozilla::ipc::IPCResult
    424 CompositorBridgeParent::RecvWaitOnTransactionProcessed() {
    425  return IPC_OK();
    426 }
    427 
    428 mozilla::ipc::IPCResult CompositorBridgeParent::RecvFlushRendering(
    429    const wr::RenderReasons& aReasons) {
    430  if (mWrBridge) {
    431    mWrBridge->FlushRendering(aReasons, /* aBlocking */ true);
    432    return IPC_OK();
    433  }
    434  return IPC_OK();
    435 }
    436 
    437 mozilla::ipc::IPCResult CompositorBridgeParent::RecvNotifyMemoryPressure() {
    438  NotifyMemoryPressure();
    439  return IPC_OK();
    440 }
    441 
    442 mozilla::ipc::IPCResult CompositorBridgeParent::RecvFlushRenderingAsync(
    443    const wr::RenderReasons& aReasons) {
    444  if (mWrBridge) {
    445    mWrBridge->FlushRendering(aReasons, /* aBlocking */ false);
    446    return IPC_OK();
    447  }
    448  return IPC_OK();
    449 }
    450 
    451 mozilla::ipc::IPCResult CompositorBridgeParent::RecvForcePresent(
    452    const wr::RenderReasons& aReasons) {
    453  if (mWrBridge) {
    454    mWrBridge->ScheduleForcedGenerateFrame(aReasons);
    455  }
    456  return IPC_OK();
    457 }
    458 
    459 mozilla::ipc::IPCResult CompositorBridgeParent::RecvStartFrameTimeRecording(
    460    const int32_t& aBufferSize, uint32_t* aOutStartIndex) {
    461  if (mWrBridge) {
    462    *aOutStartIndex = mWrBridge->StartFrameTimeRecording(aBufferSize);
    463  } else {
    464    *aOutStartIndex = 0;
    465  }
    466  return IPC_OK();
    467 }
    468 
    469 mozilla::ipc::IPCResult CompositorBridgeParent::RecvStopFrameTimeRecording(
    470    const uint32_t& aStartIndex, nsTArray<float>* intervals) {
    471  if (mWrBridge) {
    472    mWrBridge->StopFrameTimeRecording(aStartIndex, *intervals);
    473  }
    474  return IPC_OK();
    475 }
    476 
    477 void CompositorBridgeParent::ActorDestroy(ActorDestroyReason why) {
    478  mCanSend = false;
    479 
    480  StopAndClearResources();
    481 
    482  {  // scope lock
    483    StaticMonitorAutoLock lock(sIndirectLayerTreesLock);
    484    sIndirectLayerTrees.erase(mRootLayerTreeID);
    485  }
    486 
    487  // There are chances that the ref count reaches zero on the main thread
    488  // shortly after this function returns while some ipdl code still needs to run
    489  // on this thread. We must keep the compositor parent alive untill the code
    490  // handling message reception is finished on this thread.
    491  mSelfRef = this;
    492  NS_GetCurrentThread()->Dispatch(
    493      NewRunnableMethod("layers::CompositorBridgeParent::DeferredDestroy", this,
    494                        &CompositorBridgeParent::DeferredDestroy));
    495 }
    496 
    497 void CompositorBridgeParent::ScheduleRenderOnCompositorThread(
    498    wr::RenderReasons aReasons) {
    499  MOZ_ASSERT(CompositorThread());
    500  CompositorThread()->Dispatch(NewRunnableMethod<wr::RenderReasons>(
    501      "layers::CompositorBridgeParent::ScheduleComposition", this,
    502      &CompositorBridgeParent::ScheduleComposition, aReasons));
    503 }
    504 
    505 void CompositorBridgeParent::PauseComposition() {
    506  MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread(),
    507             "PauseComposition() can only be called on the compositor thread");
    508 
    509  if (!mPaused) {
    510    mPaused = true;
    511 
    512    TimeStamp now = TimeStamp::Now();
    513    if (mWrBridge) {
    514      mWrBridge->Pause();
    515      NotifyPipelineRendered(mWrBridge->PipelineId(),
    516                             mWrBridge->GetCurrentEpoch(), VsyncId(), now, now,
    517                             now);
    518    }
    519  }
    520 }
    521 
    522 bool CompositorBridgeParent::ResumeComposition() {
    523  MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread(),
    524             "ResumeComposition() can only be called on the compositor thread");
    525 
    526  bool resumed = mWidget->OnResumeComposition();
    527  resumed = resumed && mWrBridge->Resume();
    528 
    529  if (!resumed) {
    530 #ifdef MOZ_WIDGET_ANDROID
    531    // We can't get a surface. This could be because the activity changed
    532    // between the time resume was scheduled and now.
    533    __android_log_print(
    534        ANDROID_LOG_INFO, "CompositorBridgeParent",
    535        "Unable to renew compositor surface; remaining in paused state");
    536 #endif
    537    return false;
    538  }
    539 
    540  MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
    541  mPaused = false;
    542 
    543  mCompositorScheduler->ForceComposeToTarget(wr::RenderReasons::WIDGET, nullptr,
    544                                             nullptr);
    545  return true;
    546 }
    547 
    548 void CompositorBridgeParent::SetEGLSurfaceRect(int x, int y, int width,
    549                                               int height) {
    550  NS_ASSERTION(mUseExternalSurfaceSize,
    551               "Compositor created without UseExternalSurfaceSize provided");
    552  mEGLSurfaceSize.SizeTo(width, height);
    553 }
    554 
    555 bool CompositorBridgeParent::ResumeCompositionAndResize(int x, int y, int width,
    556                                                        int height) {
    557  SetEGLSurfaceRect(x, y, width, height);
    558  return ResumeComposition();
    559 }
    560 
    561 void CompositorBridgeParent::ScheduleComposition(wr::RenderReasons aReasons) {
    562  MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
    563  if (mPaused) {
    564    return;
    565  }
    566 
    567  if (mWrBridge) {
    568    mWrBridge->ScheduleGenerateFrame(aReasons);
    569  }
    570 }
    571 
    572 PAPZCTreeManagerParent* CompositorBridgeParent::AllocPAPZCTreeManagerParent(
    573    const LayersId& aLayersId) {
    574  // This should only ever get called in the GPU process.
    575  MOZ_ASSERT(XRE_IsGPUProcess());
    576  // We should only ever get this if APZ is enabled in this compositor.
    577  MOZ_ASSERT(mOptions.UseAPZ());
    578  // The mApzcTreeManager and mApzUpdater should have been created via
    579  // RecvInitialize()
    580  MOZ_ASSERT(mApzcTreeManager);
    581  MOZ_ASSERT(mApzUpdater);
    582  // The main process should pass in 0 because we assume mRootLayerTreeID
    583  MOZ_ASSERT(!aLayersId.IsValid());
    584 
    585  StaticMonitorAutoLock lock(sIndirectLayerTreesLock);
    586  CompositorBridgeParent::LayerTreeState& state =
    587      sIndirectLayerTrees[mRootLayerTreeID];
    588  MOZ_ASSERT(state.mParent.get() == this);
    589  MOZ_ASSERT(!state.mApzcTreeManagerParent);
    590  state.mApzcTreeManagerParent = new APZCTreeManagerParent(
    591      mRootLayerTreeID, mApzcTreeManager, mApzUpdater);
    592 
    593  return state.mApzcTreeManagerParent;
    594 }
    595 
    596 bool CompositorBridgeParent::DeallocPAPZCTreeManagerParent(
    597    PAPZCTreeManagerParent* aActor) {
    598  delete aActor;
    599  return true;
    600 }
    601 
    602 void CompositorBridgeParent::SetAPZInputBridgeParent(
    603    const LayersId& aLayersId, APZInputBridgeParent* aInputBridgeParent) {
    604  MOZ_RELEASE_ASSERT(XRE_IsGPUProcess());
    605  MOZ_ASSERT(NS_IsMainThread());
    606  StaticMonitorAutoLock lock(CompositorBridgeParent::sIndirectLayerTreesLock);
    607  CompositorBridgeParent::LayerTreeState& state =
    608      CompositorBridgeParent::sIndirectLayerTrees[aLayersId];
    609  MOZ_ASSERT(!state.mApzInputBridgeParent);
    610  state.mApzInputBridgeParent = aInputBridgeParent;
    611 }
    612 
    613 void CompositorBridgeParent::AllocateAPZCTreeManagerParent(
    614    const StaticMonitorAutoLock& aProofOfLayerTreeStateLock,
    615    const LayersId& aLayersId, LayerTreeState& aState) {
    616  MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
    617  MOZ_ASSERT(aState.mParent == this);
    618  MOZ_ASSERT(mApzcTreeManager);
    619  MOZ_ASSERT(mApzUpdater);
    620  MOZ_ASSERT(!aState.mApzcTreeManagerParent);
    621  aState.mApzcTreeManagerParent =
    622      new APZCTreeManagerParent(aLayersId, mApzcTreeManager, mApzUpdater);
    623 }
    624 
    625 PAPZParent* CompositorBridgeParent::AllocPAPZParent(const LayersId& aLayersId) {
    626  // This is the CompositorBridgeParent for a window, and so should only be
    627  // creating a PAPZ instance if it lives in the GPU process. Instances that
    628  // live in the UI process should going through SetControllerForLayerTree.
    629  MOZ_RELEASE_ASSERT(XRE_IsGPUProcess());
    630 
    631  // We should only ever get this if APZ is enabled on this compositor.
    632  MOZ_RELEASE_ASSERT(mOptions.UseAPZ());
    633 
    634  // The main process should pass in 0 because we assume mRootLayerTreeID
    635  MOZ_RELEASE_ASSERT(!aLayersId.IsValid());
    636 
    637  RemoteContentController* controller = new RemoteContentController();
    638 
    639  // Increment the controller's refcount before we return it. This will keep the
    640  // controller alive until it is released by IPDL in DeallocPAPZParent.
    641  controller->AddRef();
    642 
    643  StaticMonitorAutoLock lock(sIndirectLayerTreesLock);
    644  CompositorBridgeParent::LayerTreeState& state =
    645      sIndirectLayerTrees[mRootLayerTreeID];
    646  MOZ_RELEASE_ASSERT(!state.mController);
    647  state.mController = controller;
    648 
    649  return controller;
    650 }
    651 
    652 bool CompositorBridgeParent::DeallocPAPZParent(PAPZParent* aActor) {
    653  RemoteContentController* controller =
    654      static_cast<RemoteContentController*>(aActor);
    655  controller->Release();
    656  return true;
    657 }
    658 
    659 RefPtr<APZSampler> CompositorBridgeParent::GetAPZSampler() const {
    660  return mApzSampler;
    661 }
    662 
    663 RefPtr<APZUpdater> CompositorBridgeParent::GetAPZUpdater() const {
    664  return mApzUpdater;
    665 }
    666 
    667 RefPtr<OMTASampler> CompositorBridgeParent::GetOMTASampler() const {
    668  return mOMTASampler;
    669 }
    670 
    671 mozilla::ipc::IPCResult CompositorBridgeParent::RecvDynamicToolbarOffsetChanged(
    672    const int32_t& aOffset) {
    673  SetFixedLayerMargins(0, aOffset);
    674  return IPC_OK();
    675 }
    676 
    677 CompositorBridgeParent*
    678 CompositorBridgeParent::GetCompositorBridgeParentFromLayersId(
    679    const LayersId& aLayersId) {
    680  StaticMonitorAutoLock lock(sIndirectLayerTreesLock);
    681  return sIndirectLayerTrees[aLayersId].mParent;
    682 }
    683 
    684 /*static*/
    685 RefPtr<CompositorBridgeParent>
    686 CompositorBridgeParent::GetCompositorBridgeParentFromWindowId(
    687    const wr::WindowId& aWindowId) {
    688  StaticMonitorAutoLock lock(sIndirectLayerTreesLock);
    689  for (auto it = sIndirectLayerTrees.begin(); it != sIndirectLayerTrees.end();
    690       it++) {
    691    LayerTreeState* state = &it->second;
    692    if (!state->mWrBridge) {
    693      continue;
    694    }
    695    // state->mWrBridge might be a root WebRenderBridgeParent or one of a
    696    // content process, but in either case the state->mParent will be the same.
    697    // So we don't need to distinguish between the two.
    698    if (RefPtr<wr::WebRenderAPI> api = state->mWrBridge->GetWebRenderAPI()) {
    699      if (api->GetId() == aWindowId) {
    700        return state->mParent;
    701      }
    702    }
    703  }
    704  return nullptr;
    705 }
    706 
    707 bool CompositorBridgeParent::SetTestSampleTime(const LayersId& aId,
    708                                               const TimeStamp& aTime) {
    709  MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
    710 
    711  if (aTime.IsNull()) {
    712    return false;
    713  }
    714 
    715  mTestTime = Some(aTime);
    716  if (mApzcTreeManager) {
    717    mApzcTreeManager->SetTestSampleTime(mTestTime);
    718  }
    719 
    720  if (mWrBridge) {
    721    mWrBridge->FlushRendering(wr::RenderReasons::TESTING, /* aBlocking */ true);
    722    return true;
    723  }
    724 
    725  return true;
    726 }
    727 
    728 void CompositorBridgeParent::LeaveTestMode(const LayersId& aId) {
    729  mTestTime = Nothing();
    730  if (mApzcTreeManager) {
    731    mApzcTreeManager->SetTestSampleTime(mTestTime);
    732  }
    733 }
    734 
    735 CompositorAnimationStorage* CompositorBridgeParent::GetAnimationStorage() {
    736  if (!mAnimationStorage) {
    737    mAnimationStorage = new CompositorAnimationStorage(this);
    738  }
    739  return mAnimationStorage;
    740 }
    741 
    742 void CompositorBridgeParent::NotifyJankedAnimations(
    743    const JankedAnimations& aJankedAnimations) {
    744  MOZ_ASSERT(!aJankedAnimations.empty());
    745 
    746  if (StaticPrefs::layout_animation_prerender_partial_jank()) {
    747    return;
    748  }
    749 
    750  for (const auto& entry : aJankedAnimations) {
    751    const LayersId& layersId = entry.first;
    752    const nsTArray<uint64_t>& animations = entry.second;
    753    if (layersId == mRootLayerTreeID) {
    754      if (mWrBridge) {
    755        (void)SendNotifyJankedAnimations(LayersId{0}, animations);
    756      }
    757      // It unlikely happens multiple processes have janked animations at same
    758      // time, so it should be fine with enumerating sIndirectLayerTrees every
    759      // time.
    760    } else if (const LayerTreeState* state = GetIndirectShadowTree(layersId)) {
    761      if (ContentCompositorBridgeParent* cpcp =
    762              state->mContentCompositorBridgeParent) {
    763        (void)cpcp->SendNotifyJankedAnimations(layersId, animations);
    764      }
    765    }
    766  }
    767 }
    768 
    769 void CompositorBridgeParent::SetTestAsyncScrollOffset(
    770    const LayersId& aLayersId, const ScrollableLayerGuid::ViewID& aScrollId,
    771    const CSSPoint& aPoint) {
    772  if (mApzUpdater) {
    773    MOZ_ASSERT(aLayersId.IsValid());
    774    mApzUpdater->SetTestAsyncScrollOffset(aLayersId, aScrollId, aPoint);
    775  }
    776 }
    777 
    778 void CompositorBridgeParent::SetTestAsyncZoom(
    779    const LayersId& aLayersId, const ScrollableLayerGuid::ViewID& aScrollId,
    780    const LayerToParentLayerScale& aZoom) {
    781  if (mApzUpdater) {
    782    MOZ_ASSERT(aLayersId.IsValid());
    783    mApzUpdater->SetTestAsyncZoom(aLayersId, aScrollId, aZoom);
    784  }
    785 }
    786 
    787 void CompositorBridgeParent::FlushApzRepaints(const LayersId& aLayersId) {
    788  MOZ_ASSERT(mApzUpdater);
    789  MOZ_ASSERT(aLayersId.IsValid());
    790  mApzUpdater->RunOnControllerThread(
    791      aLayersId, NS_NewRunnableFunction(
    792                     "layers::CompositorBridgeParent::FlushApzRepaints",
    793                     [=]() { APZCTreeManager::FlushApzRepaints(aLayersId); }));
    794 }
    795 
    796 void CompositorBridgeParent::GetAPZTestData(const LayersId& aLayersId,
    797                                            APZTestData* aOutData) {
    798  if (mApzUpdater) {
    799    MOZ_ASSERT(aLayersId.IsValid());
    800    mApzUpdater->GetAPZTestData(aLayersId, aOutData);
    801  }
    802 }
    803 
    804 void CompositorBridgeParent::GetFrameUniformity(const LayersId& aLayersId,
    805                                                FrameUniformityData* aOutData) {
    806 }
    807 
    808 void CompositorBridgeParent::SetConfirmedTargetAPZC(
    809    const LayersId& aLayersId, const uint64_t& aInputBlockId,
    810    nsTArray<ScrollableLayerGuid>&& aTargets) {
    811  if (!mApzcTreeManager || !mApzUpdater) {
    812    return;
    813  }
    814  // Need to specifically bind this since it's overloaded.
    815  void (APZCTreeManager::*setTargetApzcFunc)(
    816      uint64_t, const nsTArray<ScrollableLayerGuid>&) =
    817      &APZCTreeManager::SetTargetAPZC;
    818  RefPtr<Runnable> task =
    819      NewRunnableMethod<uint64_t,
    820                        StoreCopyPassByRRef<nsTArray<ScrollableLayerGuid>>>(
    821          "layers::CompositorBridgeParent::SetConfirmedTargetAPZC",
    822          mApzcTreeManager.get(), setTargetApzcFunc, aInputBlockId,
    823          std::move(aTargets));
    824  mApzUpdater->RunOnUpdaterThread(aLayersId, task.forget());
    825 }
    826 
    827 void CompositorBridgeParent::SetFixedLayerMargins(ScreenIntCoord aTop,
    828                                                  ScreenIntCoord aBottom) {
    829  if (mApzcTreeManager) {
    830    mApzcTreeManager->SetFixedLayerMargins(aTop, aBottom);
    831  }
    832 
    833  ScheduleComposition(wr::RenderReasons::RESIZE);
    834 }
    835 
    836 void CompositorBridgeParent::EndWheelTransaction(
    837    const LayersId& aLayersId,
    838    PWebRenderBridgeParent::EndWheelTransactionResolver&& aResolve) {
    839  if (mApzcTreeManager) {
    840    mApzcTreeManager->EndWheelTransaction(std::move(aResolve));
    841  }
    842 }
    843 
    844 void CompositorBridgeParent::NotifyVsync(const VsyncEvent& aVsync,
    845                                         const LayersId& aLayersId) {
    846  MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_GPU);
    847  MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
    848 
    849  StaticMonitorAutoLock lock(sIndirectLayerTreesLock);
    850  auto it = sIndirectLayerTrees.find(aLayersId);
    851  if (it == sIndirectLayerTrees.end()) return;
    852 
    853  CompositorBridgeParent* cbp = it->second.mParent;
    854  if (!cbp || !cbp->mWidget) return;
    855 
    856  RefPtr<VsyncObserver> obs = cbp->mWidget->GetVsyncObserver();
    857  if (!obs) return;
    858 
    859  obs->NotifyVsync(aVsync);
    860 }
    861 
    862 /* static */
    863 void CompositorBridgeParent::ScheduleForcedComposition(
    864    const LayersId& aLayersId, wr::RenderReasons aReasons) {
    865  MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_GPU);
    866  MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
    867 
    868  StaticMonitorAutoLock lock(sIndirectLayerTreesLock);
    869  auto it = sIndirectLayerTrees.find(aLayersId);
    870  if (it == sIndirectLayerTrees.end()) {
    871    return;
    872  }
    873 
    874  CompositorBridgeParent* cbp = it->second.mParent;
    875  if (!cbp || !cbp->mWidget) {
    876    return;
    877  }
    878 
    879  if (cbp->mWrBridge) {
    880    cbp->mWrBridge->ScheduleForcedGenerateFrame(aReasons);
    881  }
    882 }
    883 
    884 mozilla::ipc::IPCResult CompositorBridgeParent::RecvNotifyChildCreated(
    885    const LayersId& child, CompositorOptions* aOptions) {
    886  StaticMonitorAutoLock lock(sIndirectLayerTreesLock);
    887  NotifyChildCreated(child);
    888  *aOptions = mOptions;
    889  return IPC_OK();
    890 }
    891 
    892 mozilla::ipc::IPCResult CompositorBridgeParent::RecvNotifyChildRecreated(
    893    const LayersId& aChild, CompositorOptions* aOptions) {
    894  StaticMonitorAutoLock lock(sIndirectLayerTreesLock);
    895 
    896  if (sIndirectLayerTrees.find(aChild) != sIndirectLayerTrees.end()) {
    897    NS_WARNING("Invalid to register the same layer tree twice");
    898    return IPC_FAIL_NO_REASON(this);
    899  }
    900 
    901  NotifyChildCreated(aChild);
    902  *aOptions = mOptions;
    903  return IPC_OK();
    904 }
    905 
    906 void CompositorBridgeParent::NotifyChildCreated(LayersId aChild) {
    907  sIndirectLayerTreesLock.AssertCurrentThreadOwns();
    908  sIndirectLayerTrees[aChild].mParent = this;
    909 }
    910 
    911 mozilla::ipc::IPCResult CompositorBridgeParent::RecvMapAndNotifyChildCreated(
    912    const LayersId& aChild, const base::ProcessId& aOwnerPid,
    913    CompositorOptions* aOptions) {
    914  // We only use this message when the remote compositor is in the GPU process.
    915  // It is harmless to call it, though.
    916  MOZ_ASSERT(XRE_IsGPUProcess());
    917 
    918  LayerTreeOwnerTracker::Get()->Map(aChild, aOwnerPid);
    919 
    920  StaticMonitorAutoLock lock(sIndirectLayerTreesLock);
    921  NotifyChildCreated(aChild);
    922  *aOptions = mOptions;
    923  return IPC_OK();
    924 }
    925 
    926 enum class CompositorOptionsChangeKind {
    927  eSupported,
    928  eBestEffort,
    929  eUnsupported
    930 };
    931 
    932 static CompositorOptionsChangeKind ClassifyCompositorOptionsChange(
    933    const CompositorOptions& aOld, const CompositorOptions& aNew) {
    934  if (aOld == aNew) {
    935    return CompositorOptionsChangeKind::eSupported;
    936  }
    937  if (aOld.EqualsIgnoringApzEnablement(aNew)) {
    938    return CompositorOptionsChangeKind::eBestEffort;
    939  }
    940  return CompositorOptionsChangeKind::eUnsupported;
    941 }
    942 
    943 mozilla::ipc::IPCResult CompositorBridgeParent::RecvAdoptChild(
    944    const LayersId& child) {
    945  RefPtr<APZUpdater> oldApzUpdater;
    946  APZCTreeManagerParent* parent;
    947  bool apzEnablementChanged = false;
    948  RefPtr<WebRenderBridgeParent> childWrBridge;
    949 
    950  // Before adopting the child, save the old compositor's root content
    951  // controller. We may need this to clear old layer transforms associated
    952  // with the child.
    953  // This is outside the lock because GetGeckoContentControllerForRoot()
    954  // does its own locking.
    955  RefPtr<GeckoContentController> oldRootController =
    956      GetGeckoContentControllerForRoot(child);
    957 
    958  {  // scope lock
    959    StaticMonitorAutoLock lock(sIndirectLayerTreesLock);
    960    // If child is already belong to this CompositorBridgeParent,
    961    // no need to handle adopting child.
    962    if (sIndirectLayerTrees[child].mParent == this) {
    963      return IPC_OK();
    964    }
    965 
    966    if (sIndirectLayerTrees[child].mParent) {
    967      switch (ClassifyCompositorOptionsChange(
    968          sIndirectLayerTrees[child].mParent->mOptions, mOptions)) {
    969        case CompositorOptionsChangeKind::eUnsupported: {
    970          MOZ_ASSERT(false,
    971                     "Moving tab between windows whose compositor options"
    972                     "differ in unsupported ways. Things may break in "
    973                     "unexpected ways");
    974          break;
    975        }
    976        case CompositorOptionsChangeKind::eBestEffort: {
    977          NS_WARNING(
    978              "Moving tab between windows with different APZ enablement. "
    979              "This is supported on a best-effort basis, but some things may "
    980              "break.");
    981          apzEnablementChanged = true;
    982          break;
    983        }
    984        case CompositorOptionsChangeKind::eSupported: {
    985          // The common case, no action required.
    986          break;
    987        }
    988      }
    989      oldApzUpdater = sIndirectLayerTrees[child].mParent->mApzUpdater;
    990    }
    991    if (mWrBridge) {
    992      childWrBridge = sIndirectLayerTrees[child].mWrBridge;
    993    }
    994    parent = sIndirectLayerTrees[child].mApzcTreeManagerParent;
    995  }
    996 
    997  if (childWrBridge) {
    998    MOZ_ASSERT(mWrBridge);
    999    RefPtr<wr::WebRenderAPI> api = mWrBridge->GetWebRenderAPI();
   1000    api = api->Clone();
   1001    wr::Epoch newEpoch = childWrBridge->UpdateWebRender(
   1002        mWrBridge->CompositorScheduler(), std::move(api),
   1003        mWrBridge->AsyncImageManager(),
   1004        mWrBridge->GetTextureFactoryIdentifier());
   1005    // Pretend we composited, since parent CompositorBridgeParent was replaced.
   1006    TimeStamp now = TimeStamp::Now();
   1007    NotifyPipelineRendered(childWrBridge->PipelineId(), newEpoch, VsyncId(),
   1008                           now, now, now);
   1009  }
   1010 
   1011  {
   1012    StaticMonitorAutoLock lock(sIndirectLayerTreesLock);
   1013    // Update sIndirectLayerTrees[child].mParent after
   1014    // WebRenderBridgeParent::UpdateWebRender().
   1015    NotifyChildCreated(child);
   1016  }
   1017 
   1018  if (oldApzUpdater) {
   1019    // If we are moving a child from an APZ-enabled window to an APZ-disabled
   1020    // window (which can happen if e.g. a WebExtension moves a tab into a
   1021    // popup window), try to handle it gracefully by clearing the old layer
   1022    // transforms associated with the child. (Since the new compositor is
   1023    // APZ-disabled, there will be nothing to update the transforms going
   1024    // forward.)
   1025    if (!mApzUpdater && oldRootController) {
   1026      // Tell the old APZCTreeManager not to send any more layer transforms
   1027      // for this layers ids.
   1028      oldApzUpdater->MarkAsDetached(child);
   1029 
   1030      // Clear the current transforms.
   1031      nsTArray<MatrixMessage> clear;
   1032      clear.AppendElement(MatrixMessage(Nothing(), ScreenRect(), child));
   1033      oldRootController->NotifyLayerTransforms(std::move(clear));
   1034    }
   1035  }
   1036  if (mApzUpdater) {
   1037    if (parent) {
   1038      MOZ_ASSERT(mApzcTreeManager);
   1039      parent->ChildAdopted(mApzcTreeManager, mApzUpdater);
   1040    }
   1041    mApzUpdater->NotifyLayerTreeAdopted(child, oldApzUpdater);
   1042  }
   1043  if (apzEnablementChanged) {
   1044    (void)SendCompositorOptionsChanged(child, mOptions);
   1045  }
   1046  return IPC_OK();
   1047 }
   1048 
   1049 PWebRenderBridgeParent* CompositorBridgeParent::AllocPWebRenderBridgeParent(
   1050    const wr::PipelineId& aPipelineId, const LayoutDeviceIntSize& aSize,
   1051    const WindowKind& aWindowKind) {
   1052  MOZ_ASSERT(wr::AsLayersId(aPipelineId) == mRootLayerTreeID);
   1053  MOZ_ASSERT(!mWrBridge);
   1054  MOZ_ASSERT(!mCompositorScheduler);
   1055  MOZ_ASSERT(mWidget);
   1056 
   1057 #ifdef XP_WIN
   1058  if (mWidget && mWidget->AsWindows()) {
   1059    const auto options = mWidget->GetCompositorOptions();
   1060    if (!options.UseSoftwareWebRender() &&
   1061        (DeviceManagerDx::Get()->CanUseDComp() ||
   1062         gfxVars::UseWebRenderFlipSequentialWin())) {
   1063      mWidget->AsWindows()->EnsureCompositorWindow();
   1064    } else if (options.UseSoftwareWebRender() &&
   1065               mWidget->AsWindows()->GetCompositorHwnd()) {
   1066      mWidget->AsWindows()->DestroyCompositorWindow();
   1067    }
   1068  }
   1069 #endif
   1070 
   1071  RefPtr<widget::CompositorWidget> widget = mWidget;
   1072  wr::WrWindowId windowId = wr::NewWindowId();
   1073  if (mApzUpdater) {
   1074    // If APZ is enabled, we need to register the APZ updater with the window id
   1075    // before the updater thread is created in WebRenderAPI::Create, so
   1076    // that the callback from the updater thread can find the right APZUpdater.
   1077    mApzUpdater->SetWebRenderWindowId(windowId);
   1078  }
   1079  if (mApzSampler) {
   1080    // Same as for mApzUpdater, but for the sampler thread.
   1081    mApzSampler->SetWebRenderWindowId(windowId);
   1082  }
   1083  if (mOMTASampler) {
   1084    // Same, but for the OMTA sampler.
   1085    mOMTASampler->SetWebRenderWindowId(windowId);
   1086  }
   1087 
   1088  nsCString error("FEATURE_FAILURE_WEBRENDER_INITIALIZE_UNSPECIFIED");
   1089  RefPtr<wr::WebRenderAPI> api = wr::WebRenderAPI::Create(
   1090      this, std::move(widget), windowId, aSize, aWindowKind, error);
   1091  if (!api) {
   1092    mWrBridge =
   1093        WebRenderBridgeParent::CreateDestroyed(aPipelineId, std::move(error));
   1094    mWrBridge.get()->AddRef();  // IPDL reference
   1095    return mWrBridge;
   1096  }
   1097 
   1098 #ifdef MOZ_WIDGET_ANDROID
   1099  // On Android, WebRenderAPI::Resume() call is triggered from Java side. But
   1100  // Java side does not know about fallback to RenderCompositorOGLSWGL. In this
   1101  // fallback case, RenderCompositor::Resume() needs to be called from gfx code.
   1102  MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
   1103  if (!mPaused && mWidget->GetCompositorOptions().UseSoftwareWebRender() &&
   1104      mWidget->GetCompositorOptions().AllowSoftwareWebRenderOGL()) {
   1105    api->Resume();
   1106  }
   1107 #endif
   1108 
   1109  wr::TransactionBuilder txn(api);
   1110  txn.SetRootPipeline(aPipelineId);
   1111  api->SendTransaction(txn);
   1112 
   1113  bool useCompositorWnd = false;
   1114 #ifdef XP_WIN
   1115  // Headless mode uses HeadlessWidget.
   1116  if (mWidget->AsWindows()) {
   1117    useCompositorWnd = !!mWidget->AsWindows()->GetCompositorHwnd();
   1118  }
   1119 #endif
   1120  mAsyncImageManager =
   1121      new AsyncImagePipelineManager(api->Clone(), useCompositorWnd);
   1122  RefPtr<AsyncImagePipelineManager> asyncMgr = mAsyncImageManager;
   1123  mWrBridge = new WebRenderBridgeParent(this, aPipelineId, mWidget, nullptr,
   1124                                        std::move(api), std::move(asyncMgr),
   1125                                        mVsyncRate);
   1126  mWrBridge.get()->AddRef();  // IPDL reference
   1127 
   1128  mAsyncImageManager->SetTextureFactoryIdentifier(
   1129      mWrBridge->GetTextureFactoryIdentifier());
   1130 
   1131  mCompositorScheduler = mWrBridge->CompositorScheduler();
   1132  MOZ_ASSERT(mCompositorScheduler);
   1133  {  // scope lock
   1134    StaticMonitorAutoLock lock(sIndirectLayerTreesLock);
   1135    MOZ_ASSERT(sIndirectLayerTrees[mRootLayerTreeID].mWrBridge == nullptr);
   1136    sIndirectLayerTrees[mRootLayerTreeID].mWrBridge = mWrBridge;
   1137  }
   1138  return mWrBridge;
   1139 }
   1140 
   1141 bool CompositorBridgeParent::DeallocPWebRenderBridgeParent(
   1142    PWebRenderBridgeParent* aActor) {
   1143  WebRenderBridgeParent* parent = static_cast<WebRenderBridgeParent*>(aActor);
   1144  {
   1145    StaticMonitorAutoLock lock(sIndirectLayerTreesLock);
   1146    auto it = sIndirectLayerTrees.find(wr::AsLayersId(parent->PipelineId()));
   1147    if (it != sIndirectLayerTrees.end()) {
   1148      it->second.mWrBridge = nullptr;
   1149    }
   1150  }
   1151  parent->Release();  // IPDL reference
   1152  return true;
   1153 }
   1154 
   1155 void CompositorBridgeParent::NotifyMemoryPressure() {
   1156  if (mWrBridge) {
   1157    RefPtr<wr::WebRenderAPI> api = mWrBridge->GetWebRenderAPI();
   1158    if (api) {
   1159      api->NotifyMemoryPressure();
   1160    }
   1161  }
   1162 }
   1163 
   1164 void CompositorBridgeParent::AccumulateMemoryReport(wr::MemoryReport* aReport) {
   1165  if (mWrBridge) {
   1166    RefPtr<wr::WebRenderAPI> api = mWrBridge->GetWebRenderAPI();
   1167    if (api) {
   1168      api->AccumulateMemoryReport(aReport);
   1169    }
   1170  }
   1171 }
   1172 
   1173 /*static*/
   1174 void CompositorBridgeParent::InitializeStatics() {
   1175  gfxVars::SetForceSubpixelAAWherePossibleListener(&UpdateQualitySettings);
   1176  gfxVars::SetWebRenderDebugFlagsListener(&UpdateDebugFlags);
   1177  gfxVars::SetWebRenderBoolParametersListener(&UpdateWebRenderBoolParameters);
   1178  gfxVars::SetWebRenderBatchingLookbackListener(&UpdateWebRenderParameters);
   1179  gfxVars::SetWebRenderBlobTileSizeListener(&UpdateWebRenderParameters);
   1180  gfxVars::SetWebRenderSlowCpuFrameThresholdListener(
   1181      &UpdateWebRenderParameters);
   1182  gfxVars::SetWebRenderBatchedUploadThresholdListener(
   1183      &UpdateWebRenderParameters);
   1184 
   1185  gfxVars::SetWebRenderProfilerUIListener(&UpdateWebRenderProfilerUI);
   1186 }
   1187 
   1188 /*static*/
   1189 void CompositorBridgeParent::UpdateQualitySettings() {
   1190  if (!CompositorThreadHolder::IsInCompositorThread()) {
   1191    if (CompositorThread()) {
   1192      CompositorThread()->Dispatch(
   1193          NewRunnableFunction("CompositorBridgeParent::UpdateQualitySettings",
   1194                              &CompositorBridgeParent::UpdateQualitySettings));
   1195    }
   1196 
   1197    // If there is no compositor thread, e.g. due to shutdown, then we can
   1198    // safefully just ignore this request.
   1199    return;
   1200  }
   1201 
   1202  StaticMonitorAutoLock lock(sIndirectLayerTreesLock);
   1203  ForEachWebRenderBridgeParent([&](WebRenderBridgeParent* wrBridge) -> void {
   1204    if (!wrBridge->IsRootWebRenderBridgeParent()) {
   1205      return;
   1206    }
   1207    wrBridge->UpdateQualitySettings();
   1208  });
   1209 }
   1210 
   1211 /*static*/
   1212 void CompositorBridgeParent::UpdateDebugFlags() {
   1213  if (!CompositorThreadHolder::IsInCompositorThread()) {
   1214    if (CompositorThread()) {
   1215      CompositorThread()->Dispatch(
   1216          NewRunnableFunction("CompositorBridgeParent::UpdateDebugFlags",
   1217                              &CompositorBridgeParent::UpdateDebugFlags));
   1218    }
   1219 
   1220    // If there is no compositor thread, e.g. due to shutdown, then we can
   1221    // safefully just ignore this request.
   1222    return;
   1223  }
   1224 
   1225  StaticMonitorAutoLock lock(sIndirectLayerTreesLock);
   1226  ForEachWebRenderBridgeParent([&](WebRenderBridgeParent* wrBridge) -> void {
   1227    if (!wrBridge->IsRootWebRenderBridgeParent()) {
   1228      return;
   1229    }
   1230    wrBridge->UpdateDebugFlags();
   1231  });
   1232 }
   1233 
   1234 /*static*/
   1235 void CompositorBridgeParent::UpdateWebRenderBoolParameters() {
   1236  if (!CompositorThreadHolder::IsInCompositorThread()) {
   1237    if (CompositorThread()) {
   1238      CompositorThread()->Dispatch(NewRunnableFunction(
   1239          "CompositorBridgeParent::UpdateWebRenderBoolParameters",
   1240          &CompositorBridgeParent::UpdateWebRenderBoolParameters));
   1241    }
   1242 
   1243    return;
   1244  }
   1245 
   1246  StaticMonitorAutoLock lock(sIndirectLayerTreesLock);
   1247  ForEachWebRenderBridgeParent([&](WebRenderBridgeParent* wrBridge) -> void {
   1248    if (!wrBridge->IsRootWebRenderBridgeParent()) {
   1249      return;
   1250    }
   1251    wrBridge->UpdateBoolParameters();
   1252  });
   1253 }
   1254 
   1255 /*static*/
   1256 void CompositorBridgeParent::UpdateWebRenderParameters() {
   1257  if (!CompositorThreadHolder::IsInCompositorThread()) {
   1258    if (CompositorThread()) {
   1259      CompositorThread()->Dispatch(NewRunnableFunction(
   1260          "CompositorBridgeParent::UpdateWebRenderParameters",
   1261          &CompositorBridgeParent::UpdateWebRenderParameters));
   1262    }
   1263 
   1264    return;
   1265  }
   1266 
   1267  StaticMonitorAutoLock lock(sIndirectLayerTreesLock);
   1268  ForEachWebRenderBridgeParent([&](WebRenderBridgeParent* wrBridge) -> void {
   1269    if (!wrBridge->IsRootWebRenderBridgeParent()) {
   1270      return;
   1271    }
   1272    wrBridge->UpdateParameters();
   1273  });
   1274 }
   1275 
   1276 /*static*/
   1277 void CompositorBridgeParent::UpdateWebRenderProfilerUI() {
   1278  StaticMonitorAutoLock lock(sIndirectLayerTreesLock);
   1279  ForEachWebRenderBridgeParent([&](WebRenderBridgeParent* wrBridge) -> void {
   1280    if (!wrBridge->IsRootWebRenderBridgeParent()) {
   1281      return;
   1282    }
   1283    wrBridge->UpdateProfilerUI();
   1284  });
   1285 }
   1286 
   1287 RefPtr<WebRenderBridgeParent> CompositorBridgeParent::GetWebRenderBridgeParent()
   1288    const {
   1289  return mWrBridge;
   1290 }
   1291 
   1292 Maybe<TimeStamp> CompositorBridgeParent::GetTestingTimeStamp() const {
   1293  return mTestTime;
   1294 }
   1295 
   1296 void EraseLayerState(LayersId aId) {
   1297  RefPtr<APZUpdater> apz;
   1298  RefPtr<WebRenderBridgeParent> wrBridge;
   1299 
   1300  {  // scope lock
   1301    StaticMonitorAutoLock lock(CompositorBridgeParent::sIndirectLayerTreesLock);
   1302    auto iter = CompositorBridgeParent::sIndirectLayerTrees.find(aId);
   1303    if (iter != CompositorBridgeParent::sIndirectLayerTrees.end()) {
   1304      CompositorBridgeParent* parent = iter->second.mParent;
   1305      if (parent) {
   1306        apz = parent->GetAPZUpdater();
   1307      }
   1308      wrBridge = iter->second.mWrBridge;
   1309      CompositorBridgeParent::sIndirectLayerTrees.erase(iter);
   1310    }
   1311  }
   1312 
   1313  if (apz) {
   1314    apz->NotifyLayerTreeRemoved(aId);
   1315  }
   1316 
   1317  if (wrBridge) {
   1318    wrBridge->Destroy();
   1319  }
   1320 }
   1321 
   1322 /*static*/
   1323 void CompositorBridgeParent::DeallocateLayerTreeId(LayersId aId) {
   1324  MOZ_ASSERT(NS_IsMainThread());
   1325  // Here main thread notifies compositor to remove an element from
   1326  // sIndirectLayerTrees. This removed element might be queried soon.
   1327  // Checking the elements of sIndirectLayerTrees exist or not before using.
   1328  if (!CompositorThread()) {
   1329    gfxCriticalError() << "Attempting to post to an invalid Compositor Thread";
   1330    return;
   1331  }
   1332  CompositorThread()->Dispatch(
   1333      NewRunnableFunction("EraseLayerStateRunnable", &EraseLayerState, aId));
   1334 }
   1335 
   1336 static void UpdateControllerForLayersId(LayersId aLayersId,
   1337                                        GeckoContentController* aController) {
   1338  // Adopt ref given to us by SetControllerForLayerTree()
   1339  StaticMonitorAutoLock lock(CompositorBridgeParent::sIndirectLayerTreesLock);
   1340  CompositorBridgeParent::sIndirectLayerTrees[aLayersId].mController =
   1341      already_AddRefed<GeckoContentController>(aController);
   1342 }
   1343 
   1344 ScopedLayerTreeRegistration::ScopedLayerTreeRegistration(
   1345    LayersId aLayersId, GeckoContentController* aController)
   1346    : mLayersId(aLayersId) {
   1347  StaticMonitorAutoLock lock(CompositorBridgeParent::sIndirectLayerTreesLock);
   1348  CompositorBridgeParent::sIndirectLayerTrees[aLayersId].mController =
   1349      aController;
   1350 }
   1351 
   1352 ScopedLayerTreeRegistration::~ScopedLayerTreeRegistration() {
   1353  StaticMonitorAutoLock lock(CompositorBridgeParent::sIndirectLayerTreesLock);
   1354  CompositorBridgeParent::sIndirectLayerTrees.erase(mLayersId);
   1355 }
   1356 
   1357 /*static*/
   1358 void CompositorBridgeParent::SetControllerForLayerTree(
   1359    LayersId aLayersId, GeckoContentController* aController) {
   1360  // This ref is adopted by UpdateControllerForLayersId().
   1361  aController->AddRef();
   1362  CompositorThread()->Dispatch(NewRunnableFunction(
   1363      "UpdateControllerForLayersIdRunnable", &UpdateControllerForLayersId,
   1364      aLayersId, aController));
   1365 }
   1366 
   1367 /*static*/
   1368 already_AddRefed<IAPZCTreeManager> CompositorBridgeParent::GetAPZCTreeManager(
   1369    LayersId aLayersId) {
   1370  StaticMonitorAutoLock lock(sIndirectLayerTreesLock);
   1371  LayerTreeMap::iterator cit = sIndirectLayerTrees.find(aLayersId);
   1372  if (sIndirectLayerTrees.end() == cit) {
   1373    return nullptr;
   1374  }
   1375  LayerTreeState* lts = &cit->second;
   1376 
   1377  RefPtr<IAPZCTreeManager> apzctm =
   1378      lts->mParent ? lts->mParent->mApzcTreeManager.get() : nullptr;
   1379  return apzctm.forget();
   1380 }
   1381 
   1382 static void InsertVsyncProfilerMarker(TimeStamp aVsyncTimestamp) {
   1383  MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
   1384  if (profiler_thread_is_being_profiled_for_markers()) {
   1385    // Tracks when a vsync occurs according to the HardwareComposer.
   1386    struct VsyncMarker {
   1387      static constexpr mozilla::Span<const char> MarkerTypeName() {
   1388        return mozilla::MakeStringSpan("VsyncTimestamp");
   1389      }
   1390      static void StreamJSONMarkerData(
   1391          baseprofiler::SpliceableJSONWriter& aWriter) {}
   1392      static MarkerSchema MarkerTypeDisplay() {
   1393        using MS = MarkerSchema;
   1394        MS schema{MS::Location::MarkerChart, MS::Location::MarkerTable};
   1395        // Nothing outside the defaults.
   1396        return schema;
   1397      }
   1398    };
   1399    profiler_add_marker("VsyncTimestamp", geckoprofiler::category::GRAPHICS,
   1400                        MarkerTiming::InstantAt(aVsyncTimestamp),
   1401                        VsyncMarker{});
   1402  }
   1403 }
   1404 
   1405 /*static */
   1406 void CompositorBridgeParent::PostInsertVsyncProfilerMarker(
   1407    TimeStamp aVsyncTimestamp) {
   1408  // Called in the vsync thread
   1409  if (profiler_is_active() && CompositorThreadHolder::IsActive()) {
   1410    CompositorThread()->Dispatch(
   1411        NewRunnableFunction("InsertVsyncProfilerMarkerRunnable",
   1412                            InsertVsyncProfilerMarker, aVsyncTimestamp));
   1413  }
   1414 }
   1415 
   1416 already_AddRefed<widget::PCompositorWidgetParent>
   1417 CompositorBridgeParent::AllocPCompositorWidgetParent(
   1418    const CompositorWidgetInitData& aInitData) {
   1419 #if defined(MOZ_WIDGET_SUPPORTS_OOP_COMPOSITING)
   1420  if (mWidget) {
   1421    // Should not create two widgets on the same compositor.
   1422    return nullptr;
   1423  }
   1424 
   1425  RefPtr<widget::CompositorWidgetParent> widget =
   1426      new widget::CompositorWidgetParent(aInitData, mOptions);
   1427 
   1428  // Sending the constructor acts as initialization as well.
   1429  mWidget = widget;
   1430  return widget.forget();
   1431 #else
   1432  return nullptr;
   1433 #endif
   1434 }
   1435 
   1436 #ifdef XP_MACOSX
   1437 mozilla::ipc::IPCResult
   1438 CompositorBridgeParent::RecvPCompositorWidgetConstructor(
   1439    PCompositorWidgetParent* actor, CompositorWidgetInitData&& aInitData) {
   1440  // macOS CocoaCompositorWidget (a superclass of the platform-specific
   1441  // CompositorWidgetParent) requires an extra step to pass aInitData
   1442  // with move semantics, because IPDL can't generate move semantics
   1443  // in the constructor. The macOS-specific aInitData contains an
   1444  // Endpoint, so it *must* use move semantics.
   1445  auto* widget = static_cast<widget::CompositorWidgetParent*>(actor);
   1446  widget->Init(std::move(aInitData));
   1447  return IPC_OK();
   1448 }
   1449 #endif
   1450 
   1451 CompositorController*
   1452 CompositorBridgeParent::LayerTreeState::GetCompositorController() const {
   1453  return mParent;
   1454 }
   1455 
   1456 void CompositorBridgeParent::ScheduleFrameAfterSceneBuild(
   1457    RefPtr<const wr::WebRenderPipelineInfo> aInfo) {
   1458  MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
   1459  if (mPaused) {
   1460    return;
   1461  }
   1462 
   1463  if (mWrBridge) {
   1464    mWrBridge->ScheduleFrameAfterSceneBuild(aInfo);
   1465  }
   1466 }
   1467 
   1468 void CompositorBridgeParent::NotifyDidRender(const VsyncId& aCompositeStartId,
   1469                                             TimeStamp& aCompositeStart,
   1470                                             TimeStamp& aRenderStart,
   1471                                             TimeStamp& aCompositeEnd,
   1472                                             wr::RendererStats* aStats) {
   1473  if (!mWrBridge) {
   1474    return;
   1475  }
   1476 
   1477  MOZ_RELEASE_ASSERT(mWrBridge->IsRootWebRenderBridgeParent());
   1478 
   1479  RefPtr<UiCompositorControllerParent> uiController =
   1480      UiCompositorControllerParent::GetFromRootLayerTreeId(mRootLayerTreeID);
   1481 
   1482  if (uiController && mIsForcedFirstPaint) {
   1483    uiController->NotifyFirstPaint();
   1484    mIsForcedFirstPaint = false;
   1485  }
   1486 
   1487  nsTArray<CompositionPayload> payload =
   1488      mWrBridge->TakePendingScrollPayload(aCompositeStartId);
   1489  if (!payload.IsEmpty()) {
   1490    RecordCompositionPayloadsPresented(aCompositeEnd, payload);
   1491  }
   1492 
   1493  nsTArray<ImageCompositeNotificationInfo> notifications;
   1494  mWrBridge->ExtractImageCompositeNotifications(&notifications);
   1495  if (!notifications.IsEmpty()) {
   1496    (void)ImageBridgeParent::NotifyImageComposites(notifications);
   1497  }
   1498 }
   1499 
   1500 bool CompositorBridgeParent::sStable = false;
   1501 uint32_t CompositorBridgeParent::sFramesComposited = 0;
   1502 
   1503 /* static */ void CompositorBridgeParent::ResetStable() {
   1504  if (!CompositorThreadHolder::IsInCompositorThread()) {
   1505    if (CompositorThread()) {
   1506      CompositorThread()->Dispatch(
   1507          NewRunnableFunction("CompositorBridgeParent::ResetStable",
   1508                              &CompositorBridgeParent::ResetStable));
   1509    }
   1510 
   1511    // If there is no compositor thread, e.g. due to shutdown, then we can
   1512    // safefully just ignore this request.
   1513    return;
   1514  }
   1515 
   1516  sStable = false;
   1517  sFramesComposited = 0;
   1518 }
   1519 
   1520 void CompositorBridgeParent::MaybeDeclareStable() {
   1521  MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
   1522 
   1523  if (sStable) {
   1524    return;
   1525  }
   1526 
   1527  // Once we render as many frames as the threshold, we declare this instance of
   1528  // the GPU process 'stable'. This causes the parent process to always respawn
   1529  // the GPU process if it crashes.
   1530  if (++sFramesComposited >=
   1531      StaticPrefs::layers_gpu_process_stable_frame_threshold()) {
   1532    sStable = true;
   1533 
   1534    NS_DispatchToMainThread(NS_NewRunnableFunction(
   1535        "CompositorBridgeParent::MaybeDeclareStable", []() -> void {
   1536          if (XRE_IsParentProcess()) {
   1537            GPUProcessManager* gpm = GPUProcessManager::Get();
   1538            if (gpm) {
   1539              gpm->OnProcessDeclaredStable();
   1540            }
   1541          } else {
   1542            gfx::GPUParent* gpu = gfx::GPUParent::GetSingleton();
   1543            if (gpu && gpu->CanSend()) {
   1544              (void)gpu->SendDeclareStable();
   1545            }
   1546          }
   1547        }));
   1548  }
   1549 }
   1550 
   1551 void CompositorBridgeParent::NotifyPipelineRendered(
   1552    const wr::PipelineId& aPipelineId, const wr::Epoch& aEpoch,
   1553    const VsyncId& aCompositeStartId, TimeStamp& aCompositeStart,
   1554    TimeStamp& aRenderStart, TimeStamp& aCompositeEnd,
   1555    wr::RendererStats* aStats) {
   1556  if (!mWrBridge || !mAsyncImageManager) {
   1557    return;
   1558  }
   1559 
   1560  bool isRoot = mWrBridge->PipelineId() == aPipelineId;
   1561  RefPtr<WebRenderBridgeParent> wrBridge =
   1562      isRoot ? mWrBridge
   1563             : RefPtr<WebRenderBridgeParent>(
   1564                   mAsyncImageManager->GetWrBridge(aPipelineId));
   1565  if (!wrBridge) {
   1566    return;
   1567  }
   1568 
   1569  CompositorBridgeParentBase* compBridge =
   1570      isRoot ? this : wrBridge->GetCompositorBridge();
   1571  if (!compBridge) {
   1572    return;
   1573  }
   1574 
   1575  MOZ_RELEASE_ASSERT(isRoot == wrBridge->IsRootWebRenderBridgeParent());
   1576 
   1577  wrBridge->RemoveEpochDataPriorTo(aEpoch);
   1578 
   1579  nsTArray<FrameStats> stats;
   1580  nsTArray<TransactionId> transactions;
   1581 
   1582  RefPtr<UiCompositorControllerParent> uiController =
   1583      UiCompositorControllerParent::GetFromRootLayerTreeId(mRootLayerTreeID);
   1584 
   1585  wrBridge->FlushTransactionIdsForEpoch(
   1586      aEpoch, aCompositeStartId, aCompositeStart, aRenderStart, aCompositeEnd,
   1587      uiController, aStats, stats, transactions);
   1588  if (transactions.IsEmpty()) {
   1589    MOZ_ASSERT(stats.IsEmpty());
   1590    return;
   1591  }
   1592 
   1593  MaybeDeclareStable();
   1594 
   1595  LayersId layersId = isRoot ? LayersId{0} : wrBridge->GetLayersId();
   1596  (void)compBridge->SendDidComposite(layersId, transactions, aCompositeStart,
   1597                                     aCompositeEnd);
   1598 
   1599  if (!stats.IsEmpty()) {
   1600    (void)SendNotifyFrameStats(stats);
   1601  }
   1602 }
   1603 
   1604 RefPtr<AsyncImagePipelineManager>
   1605 CompositorBridgeParent::GetAsyncImagePipelineManager() const {
   1606  return mAsyncImageManager;
   1607 }
   1608 
   1609 /* static */ CompositorBridgeParent::LayerTreeState*
   1610 CompositorBridgeParent::GetIndirectShadowTreeInternal(LayersId aId) {
   1611  StaticMonitorAutoLock lock(sIndirectLayerTreesLock);
   1612  LayerTreeMap::iterator cit = sIndirectLayerTrees.find(aId);
   1613  if (sIndirectLayerTrees.end() == cit) {
   1614    return nullptr;
   1615  }
   1616  return &cit->second;
   1617 }
   1618 
   1619 /* static */
   1620 bool CompositorBridgeParent::HasIndirectShadowTree(LayersId aId) {
   1621  return GetIndirectShadowTreeInternal(aId) != nullptr;
   1622 }
   1623 
   1624 /* static */ CompositorBridgeParent::LayerTreeState*
   1625 CompositorBridgeParent::GetIndirectShadowTree(LayersId aId) {
   1626  // Only the compositor thread should use this method variant
   1627  MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
   1628 
   1629  return GetIndirectShadowTreeInternal(aId);
   1630 }
   1631 
   1632 /* static */
   1633 bool CompositorBridgeParent::CallWithIndirectShadowTree(
   1634    LayersId aId,
   1635    const std::function<void(CompositorBridgeParent::LayerTreeState&)>& aFunc) {
   1636  // Note that this does not make things universally threadsafe just because the
   1637  // sIndirectLayerTreesLock mutex is held. This is because the compositor
   1638  // thread can mutate the LayerTreeState outside the lock. It does however
   1639  // ensure that the *storage* for the LayerTreeState remains stable, since we
   1640  // should always hold the lock when adding/removing entries to the map.
   1641  StaticMonitorAutoLock lock(sIndirectLayerTreesLock);
   1642  LayerTreeMap::iterator cit = sIndirectLayerTrees.find(aId);
   1643  if (sIndirectLayerTrees.end() == cit) {
   1644    return false;
   1645  }
   1646  aFunc(cit->second);
   1647  return true;
   1648 }
   1649 
   1650 static CompositorBridgeParent::LayerTreeState* GetStateForRoot(
   1651    LayersId aContentLayersId, const StaticMonitorAutoLock& aProofOfLock) {
   1652  CompositorBridgeParent::sIndirectLayerTreesLock.AssertCurrentThreadOwns();
   1653  CompositorBridgeParent::LayerTreeState* contentState = nullptr;
   1654  auto itr = CompositorBridgeParent::sIndirectLayerTrees.find(aContentLayersId);
   1655  if (CompositorBridgeParent::sIndirectLayerTrees.end() != itr) {
   1656    contentState = &itr->second;
   1657  }
   1658 
   1659  // |contentState| is the state for the content process, but we want the
   1660  // APZCTMParent for the parent process owning that content process. So we have
   1661  // to jump to the LayerTreeState for the root layer tree id for that layer
   1662  // tree, and use the mApzcTreeManagerParent from that. This should also work
   1663  // with nested content processes, because RootLayerTreeId() will bypass any
   1664  // intermediate processes' ids and go straight to the root.
   1665  if (contentState && contentState->mParent) {
   1666    LayersId rootLayersId = contentState->mParent->RootLayerTreeId();
   1667    itr = CompositorBridgeParent::sIndirectLayerTrees.find(rootLayersId);
   1668    CompositorBridgeParent::LayerTreeState* rootState =
   1669        (CompositorBridgeParent::sIndirectLayerTrees.end() != itr)
   1670            ? &itr->second
   1671            : nullptr;
   1672    return rootState;
   1673  }
   1674 
   1675  // Don't return contentState, that would be a lie!
   1676  return nullptr;
   1677 }
   1678 
   1679 /* static */
   1680 APZCTreeManagerParent* CompositorBridgeParent::GetApzcTreeManagerParentForRoot(
   1681    LayersId aContentLayersId) {
   1682  StaticMonitorAutoLock lock(sIndirectLayerTreesLock);
   1683  CompositorBridgeParent::LayerTreeState* state =
   1684      GetStateForRoot(aContentLayersId, lock);
   1685  return state ? state->mApzcTreeManagerParent : nullptr;
   1686 }
   1687 
   1688 /* static */
   1689 APZInputBridgeParent* CompositorBridgeParent::GetApzInputBridgeParentForRoot(
   1690    LayersId aContentLayersId) {
   1691  StaticMonitorAutoLock lock(sIndirectLayerTreesLock);
   1692  CompositorBridgeParent::LayerTreeState* state =
   1693      GetStateForRoot(aContentLayersId, lock);
   1694  return state ? state->mApzInputBridgeParent : nullptr;
   1695 }
   1696 
   1697 /* static */
   1698 GeckoContentController*
   1699 CompositorBridgeParent::GetGeckoContentControllerForRoot(
   1700    LayersId aContentLayersId) {
   1701  StaticMonitorAutoLock lock(sIndirectLayerTreesLock);
   1702  CompositorBridgeParent::LayerTreeState* state =
   1703      GetStateForRoot(aContentLayersId, lock);
   1704  return state ? state->mController.get() : nullptr;
   1705 }
   1706 
   1707 PTextureParent* CompositorBridgeParent::AllocPTextureParent(
   1708    const SurfaceDescriptor& aSharedData, ReadLockDescriptor& aReadLock,
   1709    const LayersBackend& aLayersBackend, const TextureFlags& aFlags,
   1710    const LayersId& aId, const uint64_t& aSerial,
   1711    const wr::MaybeExternalImageId& aExternalImageId) {
   1712  return TextureHost::CreateIPDLActor(
   1713      this, aSharedData, std::move(aReadLock), aLayersBackend, aFlags,
   1714      mCompositorManager->GetContentId(), aSerial, aExternalImageId);
   1715 }
   1716 
   1717 bool CompositorBridgeParent::DeallocPTextureParent(PTextureParent* actor) {
   1718  return TextureHost::DestroyIPDLActor(actor);
   1719 }
   1720 
   1721 bool CompositorBridgeParent::IsSameProcess() const {
   1722  return OtherPid() == base::GetCurrentProcId();
   1723 }
   1724 
   1725 void CompositorBridgeParent::NotifyWebRenderDisableNativeCompositor() {
   1726  MOZ_ASSERT(CompositorThread()->IsOnCurrentThread());
   1727  if (mWrBridge) {
   1728    mWrBridge->DisableNativeCompositor();
   1729  }
   1730 }
   1731 
   1732 int32_t RecordContentFrameTime(
   1733    const VsyncId& aTxnId, const TimeStamp& aVsyncStart,
   1734    const TimeStamp& aTxnStart, const VsyncId& aCompositeId,
   1735    const TimeStamp& aCompositeEnd, const TimeDuration& aFullPaintTime,
   1736    const TimeDuration& aVsyncRate, bool aContainsSVGGroup,
   1737    bool aRecordUploadStats, wr::RendererStats* aStats /* = nullptr */) {
   1738  double latencyMs = (aCompositeEnd - aTxnStart).ToMilliseconds();
   1739  double latencyNorm = latencyMs / aVsyncRate.ToMilliseconds();
   1740  int32_t fracLatencyNorm = lround(latencyNorm * 100.0);
   1741 
   1742  if (profiler_thread_is_being_profiled_for_markers()) {
   1743    struct ContentFrameMarker {
   1744      static constexpr Span<const char> MarkerTypeName() {
   1745        return MakeStringSpan("CONTENT_FRAME_TIME");
   1746      }
   1747      static void StreamJSONMarkerData(
   1748          baseprofiler::SpliceableJSONWriter& aWriter) {}
   1749      static MarkerSchema MarkerTypeDisplay() {
   1750        using MS = MarkerSchema;
   1751        MS schema{MS::Location::MarkerChart, MS::Location::MarkerTable};
   1752        // Nothing outside the defaults.
   1753        return schema;
   1754      }
   1755    };
   1756 
   1757    profiler_add_marker("CONTENT_FRAME_TIME", geckoprofiler::category::GRAPHICS,
   1758                        MarkerTiming::Interval(aTxnStart, aCompositeEnd),
   1759                        ContentFrameMarker{});
   1760  }
   1761 
   1762  mozilla::glean::gfx_content_frame_time::from_paint.AccumulateSingleSample(
   1763      static_cast<unsigned long long>(fracLatencyNorm));
   1764 
   1765  if (!(aTxnId == VsyncId()) && aVsyncStart) {
   1766    latencyMs = (aCompositeEnd - aVsyncStart).ToMilliseconds();
   1767    latencyNorm = latencyMs / aVsyncRate.ToMilliseconds();
   1768    fracLatencyNorm = lround(latencyNorm * 100.0);
   1769    int32_t result = fracLatencyNorm;
   1770    mozilla::glean::gfx_content_frame_time::from_vsync.AccumulateSingleSample(
   1771        static_cast<unsigned long long>(fracLatencyNorm));
   1772 
   1773    if (aContainsSVGGroup) {
   1774      mozilla::glean::gfx_content_frame_time::with_svg.AccumulateSingleSample(
   1775          static_cast<unsigned long long>(fracLatencyNorm));
   1776    }
   1777 
   1778    // Record glean::gfx_content_frame_time::reason
   1779    //
   1780    // Note that deseralizing a layers update (RecvUpdate) can delay the receipt
   1781    // of the composite vsync message
   1782    // (CompositorBridgeParent::CompositeToTarget), since they're using the same
   1783    // thread. This can mean that compositing might start significantly late,
   1784    // but this code will still detect it as having successfully started on the
   1785    // right vsync (which is somewhat correct). We'd now have reduced time left
   1786    // in the vsync interval to finish compositing, so the chances of a missed
   1787    // frame increases. This is effectively including the RecvUpdate work as
   1788    // part of the 'compositing' phase for this metric, but it isn't included in
   1789    // COMPOSITE_TIME, and *is* included in CONTENT_FULL_PAINT_TIME.
   1790    //
   1791    // Also of note is that when the root WebRenderBridgeParent decides to
   1792    // skip a composite (due to the Renderer being busy), that won't notify
   1793    // child WebRenderBridgeParents. That failure will show up as the
   1794    // composite starting late (since it did), but it's really a fault of a
   1795    // slow composite on the previous frame, not a slow
   1796    // CONTENT_FULL_PAINT_TIME. It would be nice to have a separate bucket for
   1797    // this category (scene was ready on the next vsync, but we chose not to
   1798    // composite), but I can't find a way to locate the right child
   1799    // WebRenderBridgeParents from the root. WebRender notifies us of the
   1800    // child pipelines contained within a render, after it finishes, but I
   1801    // can't see how to query what child pipeline would have been rendered,
   1802    // when we choose to not do it.
   1803    if (fracLatencyNorm < 200) {
   1804      // Success
   1805      mozilla::glean::gfx_content_frame_time::reason
   1806          .EnumGet(glean::gfx_content_frame_time::ReasonLabel::eOnTime)
   1807          .Add();
   1808    } else {
   1809      if (aCompositeId == VsyncId()) {
   1810        // aCompositeId is 0, possibly something got trigged from
   1811        // outside vsync?
   1812        mozilla::glean::gfx_content_frame_time::reason
   1813            .EnumGet(glean::gfx_content_frame_time::ReasonLabel::eNoVsyncNoId)
   1814            .Add();
   1815      } else if (aTxnId >= aCompositeId) {
   1816        // Vsync ids are nonsensical, maybe we're trying to catch up?
   1817        mozilla::glean::gfx_content_frame_time::reason
   1818            .EnumGet(glean::gfx_content_frame_time::ReasonLabel::eNoVsync)
   1819            .Add();
   1820      } else if (aCompositeId - aTxnId > 1) {
   1821        // Composite started late (and maybe took too long as well)
   1822        if (aFullPaintTime >= TimeDuration::FromMilliseconds(20)) {
   1823          mozilla::glean::gfx_content_frame_time::reason
   1824              .EnumGet(glean::gfx_content_frame_time::ReasonLabel::
   1825                           eMissedCompositeLong)
   1826              .Add();
   1827        } else if (aFullPaintTime >= TimeDuration::FromMilliseconds(10)) {
   1828          mozilla::glean::gfx_content_frame_time::reason
   1829              .EnumGet(glean::gfx_content_frame_time::ReasonLabel::
   1830                           eMissedCompositeMid)
   1831              .Add();
   1832        } else if (aFullPaintTime >= TimeDuration::FromMilliseconds(5)) {
   1833          mozilla::glean::gfx_content_frame_time::reason
   1834              .EnumGet(glean::gfx_content_frame_time::ReasonLabel::
   1835                           eMissedCompositeLow)
   1836              .Add();
   1837        } else {
   1838          mozilla::glean::gfx_content_frame_time::reason
   1839              .EnumGet(
   1840                  glean::gfx_content_frame_time::ReasonLabel::eMissedComposite)
   1841              .Add();
   1842        }
   1843      } else {
   1844        // Composite started on time, but must have taken too long.
   1845        mozilla::glean::gfx_content_frame_time::reason
   1846            .EnumGet(glean::gfx_content_frame_time::ReasonLabel::eSlowComposite)
   1847            .Add();
   1848      }
   1849    }
   1850 
   1851    if (aRecordUploadStats) {
   1852      if (aStats) {
   1853        latencyMs -= (double(aStats->resource_upload_time) / 1000000.0);
   1854        latencyNorm = latencyMs / aVsyncRate.ToMilliseconds();
   1855        fracLatencyNorm = lround(latencyNorm * 100.0);
   1856      }
   1857      mozilla::glean::gfx_content_frame_time::without_resource_upload
   1858          .AccumulateSingleSample(
   1859              static_cast<unsigned long long>(fracLatencyNorm));
   1860 
   1861      mozilla::glean::gfx_content_frame_time::without_resource_upload
   1862          .AccumulateSingleSample(
   1863              static_cast<unsigned long long>(fracLatencyNorm));
   1864    }
   1865    return result;
   1866  }
   1867 
   1868  return 0;
   1869 }
   1870 
   1871 mozilla::ipc::IPCResult CompositorBridgeParent::RecvBeginRecording(
   1872    const TimeStamp& aRecordingStart, BeginRecordingResolver&& aResolve) {
   1873  if (mHaveCompositionRecorder) {
   1874    aResolve(false);
   1875    return IPC_OK();
   1876  }
   1877 
   1878  if (mWrBridge) {
   1879    mWrBridge->BeginRecording(aRecordingStart);
   1880  }
   1881 
   1882  mHaveCompositionRecorder = true;
   1883  aResolve(true);
   1884 
   1885  return IPC_OK();
   1886 }
   1887 
   1888 mozilla::ipc::IPCResult CompositorBridgeParent::RecvEndRecording(
   1889    EndRecordingResolver&& aResolve) {
   1890  if (!mHaveCompositionRecorder) {
   1891    aResolve(Nothing());
   1892    return IPC_OK();
   1893  }
   1894 
   1895  if (mWrBridge) {
   1896    mWrBridge->EndRecording()->Then(
   1897        NS_GetCurrentThread(), __func__,
   1898        [resolve{aResolve}](FrameRecording&& recording) {
   1899          resolve(Some(std::move(recording)));
   1900        },
   1901        [resolve{aResolve}]() { resolve(Nothing()); });
   1902  } else {
   1903    aResolve(Nothing());
   1904  }
   1905 
   1906  mHaveCompositionRecorder = false;
   1907 
   1908  return IPC_OK();
   1909 }
   1910 
   1911 void CompositorBridgeParent::FlushPendingWrTransactionEventsWithWait() {
   1912  if (!mWrBridge) {
   1913    return;
   1914  }
   1915 
   1916  std::vector<RefPtr<WebRenderBridgeParent>> bridgeParents;
   1917  {  // scope lock
   1918    StaticMonitorAutoLock lock(sIndirectLayerTreesLock);
   1919    ForEachIndirectLayerTree([&](LayerTreeState* lts, LayersId) -> void {
   1920      if (lts->mWrBridge) {
   1921        bridgeParents.emplace_back(lts->mWrBridge);
   1922      }
   1923    });
   1924  }
   1925 
   1926  for (auto& bridge : bridgeParents) {
   1927    bridge->FlushPendingWrTransactionEventsWithWait();
   1928  }
   1929 }
   1930 
   1931 void RecordCompositionPayloadsPresented(
   1932    const TimeStamp& aCompositionEndTime,
   1933    const nsTArray<CompositionPayload>& aPayloads) {
   1934  if (aPayloads.Length()) {
   1935    TimeStamp presented = aCompositionEndTime;
   1936    for (const CompositionPayload& payload : aPayloads) {
   1937      if (profiler_thread_is_being_profiled_for_markers()) {
   1938        MOZ_RELEASE_ASSERT(payload.mType <= kHighestCompositionPayloadType);
   1939        nsAutoCString name(
   1940            kCompositionPayloadTypeNames[uint8_t(payload.mType)]);
   1941        name.AppendLiteral(" Payload Presented");
   1942        // This doesn't really need to be a text marker. Once we have a version
   1943        // of profiler_add_marker that accepts both a start time and an end
   1944        // time, we could use that here.
   1945        nsPrintfCString text(
   1946            "Latency: %dms",
   1947            int32_t((presented - payload.mTimeStamp).ToMilliseconds()));
   1948        PROFILER_MARKER_TEXT(
   1949            name, GRAPHICS,
   1950            MarkerTiming::Interval(payload.mTimeStamp, presented), text);
   1951      }
   1952 
   1953      if (payload.mType == CompositionPayloadType::eKeyPress) {
   1954        glean::performance_interaction::keypress_present_latency
   1955            .AccumulateRawDuration(presented - payload.mTimeStamp);
   1956      } else if (payload.mType == CompositionPayloadType::eAPZScroll) {
   1957        mozilla::glean::gfx::scroll_present_latency.AccumulateRawDuration(
   1958            presented - payload.mTimeStamp);
   1959      } else if (payload.mType ==
   1960                 CompositionPayloadType::eMouseUpFollowedByClick) {
   1961        glean::performance_interaction::mouseup_click_present_latency
   1962            .AccumulateRawDuration(presented - payload.mTimeStamp);
   1963      }
   1964    }
   1965  }
   1966 }
   1967 
   1968 }  // namespace layers
   1969 }  // namespace mozilla