LCOV - code coverage report
Current view: top level - gfx/layers/ipc - CompositorBridgeParent.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 336 995 33.8 %
Date: 2017-07-14 16:53:18 Functions: 54 153 35.3 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13