Bug 1622360 - Downgrade mApis from a RenderRootArray. r=jrmuizel

This is a bigger patch but it was hard to split. Some of the changes look
non-trivial; the guiding principle in these changes was "look at what the code
was like before document splitting landed".

Differential Revision: https://phabricator.services.mozilla.com/D73879
This commit is contained in:
Kartikaya Gupta 2020-05-05 18:15:43 +00:00
parent 9b72e95f96
commit 5db69b1b8c
9 changed files with 103 additions and 229 deletions

View file

@ -2795,7 +2795,7 @@ APZCTreeManager::HitTestResult APZCTreeManager::GetAPZCAtPointWR(
const ScreenPoint& aHitTestPoint, const ScreenPoint& aHitTestPoint,
const RecursiveMutexAutoLock& aProofOfTreeLock) { const RecursiveMutexAutoLock& aProofOfTreeLock) {
HitTestResult hit; HitTestResult hit;
RefPtr<wr::WebRenderAPI> wr = GetWebRenderAPIAtPoint(aHitTestPoint); RefPtr<wr::WebRenderAPI> wr = GetWebRenderAPI();
if (!wr) { if (!wr) {
// If WebRender isn't running, fall back to the root APZC. // If WebRender isn't running, fall back to the root APZC.
// This is mostly for the benefit of GTests which do not // This is mostly for the benefit of GTests which do not
@ -3606,25 +3606,12 @@ LayerToParentLayerMatrix4x4 APZCTreeManager::ComputeTransformForNode(
return aNode->GetTransform() * AsyncTransformMatrix(); return aNode->GetTransform() * AsyncTransformMatrix();
} }
already_AddRefed<wr::WebRenderAPI> APZCTreeManager::GetWebRenderAPI( already_AddRefed<wr::WebRenderAPI> APZCTreeManager::GetWebRenderAPI() const {
wr::RenderRoot aRenderRoot) const {
RefPtr<wr::WebRenderAPI> api; RefPtr<wr::WebRenderAPI> api;
CompositorBridgeParent::CallWithIndirectShadowTree( CompositorBridgeParent::CallWithIndirectShadowTree(
mRootLayersId, [&](LayerTreeState& aState) -> void { mRootLayersId, [&](LayerTreeState& aState) -> void {
if (aState.mWrBridge) { if (aState.mWrBridge) {
api = aState.mWrBridge->GetWebRenderAPI(aRenderRoot); api = aState.mWrBridge->GetWebRenderAPI();
}
});
return api.forget();
}
already_AddRefed<wr::WebRenderAPI> APZCTreeManager::GetWebRenderAPIAtPoint(
const ScreenPoint& aPoint) const {
RefPtr<wr::WebRenderAPI> api;
CompositorBridgeParent::CallWithIndirectShadowTree(
mRootLayersId, [&](LayerTreeState& aState) -> void {
if (aState.mWrBridge) {
api = aState.mWrBridge->GetWebRenderAPIAtPoint(aPoint);
} }
}); });
return api.forget(); return api.forget();

View file

@ -506,20 +506,9 @@ class APZCTreeManager : public IAPZCTreeManager, public APZInputBridge {
// Assert that the current thread is the updater thread for this APZCTM. // Assert that the current thread is the updater thread for this APZCTM.
void AssertOnUpdaterThread(); void AssertOnUpdaterThread();
// Returns a pointer to the WebRenderAPI this APZCTreeManager is for, for // Returns a pointer to the WebRenderAPI this APZCTreeManager is for.
// the provided RenderRoot (since an APZCTreeManager can cover multiple
// RenderRoots). This might be null (for example, if WebRender is not
// enabled).
already_AddRefed<wr::WebRenderAPI> GetWebRenderAPI(
wr::RenderRoot aRenderRoot) const;
// Returns a pointer to the root WebRenderAPI for the RenderRoot that owns
// the given point. For example, if aPoint is in the content area and
// RenderRoot splitting is enabled, this will return the WebRenderAPI for
// the Content RenderRoot.
// This might be null (for example, if WebRender is not enabled). // This might be null (for example, if WebRender is not enabled).
already_AddRefed<wr::WebRenderAPI> GetWebRenderAPIAtPoint( already_AddRefed<wr::WebRenderAPI> GetWebRenderAPI() const;
const ScreenPoint& aPoint) const;
protected: protected:
// Protected destructor, to discourage deletion outside of Release(): // Protected destructor, to discourage deletion outside of Release():

View file

@ -358,8 +358,7 @@ void APZUpdater::RunOnUpdaterThread(LayersId aLayersId,
mUpdaterQueue.push_back(QueuedTask{aLayersId, task}); mUpdaterQueue.push_back(QueuedTask{aLayersId, task});
} }
if (sendWakeMessage) { if (sendWakeMessage) {
RefPtr<wr::WebRenderAPI> api = RefPtr<wr::WebRenderAPI> api = mApz->GetWebRenderAPI();
mApz->GetWebRenderAPI(wr::RenderRoot::Default);
if (api) { if (api) {
api->WakeSceneBuilder(); api->WakeSceneBuilder();
} else { } else {

View file

@ -496,8 +496,7 @@ void CompositorBridgeParent::StopAndClearResources() {
} }
indirectBridgeParents.clear(); indirectBridgeParents.clear();
RefPtr<wr::WebRenderAPI> api = RefPtr<wr::WebRenderAPI> api = mWrBridge->GetWebRenderAPI();
mWrBridge->GetWebRenderAPI(wr::RenderRoot::Default);
// Ensure we are not holding the sIndirectLayerTreesLock here because we // Ensure we are not holding the sIndirectLayerTreesLock here because we
// are going to block on WR threads in order to shut it down properly. // are going to block on WR threads in order to shut it down properly.
mWrBridge->Destroy(); mWrBridge->Destroy();
@ -1209,8 +1208,7 @@ CompositorBridgeParent::GetCompositorBridgeParentFromWindowId(
// state->mWrBridge might be a root WebRenderBridgeParent or one of a // state->mWrBridge might be a root WebRenderBridgeParent or one of a
// content process, but in either case the state->mParent will be the same. // content process, but in either case the state->mParent will be the same.
// So we don't need to distinguish between the two. // So we don't need to distinguish between the two.
if (RefPtr<wr::WebRenderAPI> api = if (RefPtr<wr::WebRenderAPI> api = state->mWrBridge->GetWebRenderAPI()) {
state->mWrBridge->GetWebRenderAPI(wr::RenderRoot::Default)) {
if (api->GetId() == aWindowId) { if (api->GetId() == aWindowId) {
return state->mParent; return state->mParent;
} }
@ -1827,11 +1825,10 @@ mozilla::ipc::IPCResult CompositorBridgeParent::RecvAdoptChild(
if (childWrBridge) { if (childWrBridge) {
MOZ_ASSERT(mWrBridge); MOZ_ASSERT(mWrBridge);
nsTArray<RefPtr<wr::WebRenderAPI>> apis; RefPtr<wr::WebRenderAPI> api = mWrBridge->GetWebRenderAPI();
DebugOnly<bool> cloneSuccess = mWrBridge->CloneWebRenderAPIs(apis); api = api->Clone();
MOZ_ASSERT(cloneSuccess);
wr::Epoch newEpoch = childWrBridge->UpdateWebRender( wr::Epoch newEpoch = childWrBridge->UpdateWebRender(
mWrBridge->CompositorScheduler(), std::move(apis), mWrBridge->CompositorScheduler(), std::move(api),
mWrBridge->AsyncImageManager(), GetAnimationStorage(), mWrBridge->AsyncImageManager(), GetAnimationStorage(),
mWrBridge->GetTextureFactoryIdentifier()); mWrBridge->GetTextureFactoryIdentifier());
// Pretend we composited, since parent CompositorBridgeParent was replaced. // Pretend we composited, since parent CompositorBridgeParent was replaced.
@ -1898,33 +1895,28 @@ PWebRenderBridgeParent* CompositorBridgeParent::AllocPWebRenderBridgeParent(
// Same as for mApzUpdater, but for the sampler thread. // Same as for mApzUpdater, but for the sampler thread.
mApzSampler->SetWebRenderWindowId(windowId); mApzSampler->SetWebRenderWindowId(windowId);
} }
nsTArray<RefPtr<wr::WebRenderAPI>> apis; RefPtr<wr::WebRenderAPI> api =
apis.AppendElement( wr::WebRenderAPI::Create(this, std::move(widget), windowId, aSize);
wr::WebRenderAPI::Create(this, std::move(widget), windowId, aSize)); if (!api) {
if (!apis[0]) {
mWrBridge = WebRenderBridgeParent::CreateDestroyed(aPipelineId); mWrBridge = WebRenderBridgeParent::CreateDestroyed(aPipelineId);
mWrBridge.get()->AddRef(); // IPDL reference mWrBridge.get()->AddRef(); // IPDL reference
return mWrBridge; return mWrBridge;
} }
nsTArray<RefPtr<wr::WebRenderAPI>> clonedApis;
for (auto& api : apis) {
wr::TransactionBuilder txn; wr::TransactionBuilder txn;
txn.SetRootPipeline(aPipelineId); txn.SetRootPipeline(aPipelineId);
api->SendTransaction(txn); api->SendTransaction(txn);
clonedApis.AppendElement(api->Clone());
}
bool useCompositorWnd = false; bool useCompositorWnd = false;
#ifdef XP_WIN #ifdef XP_WIN
useCompositorWnd = !!mWidget->AsWindows()->GetCompositorHwnd(); useCompositorWnd = !!mWidget->AsWindows()->GetCompositorHwnd();
#endif #endif
mAsyncImageManager = mAsyncImageManager =
new AsyncImagePipelineManager(std::move(clonedApis), useCompositorWnd); new AsyncImagePipelineManager(api->Clone(), useCompositorWnd);
RefPtr<AsyncImagePipelineManager> asyncMgr = mAsyncImageManager; RefPtr<AsyncImagePipelineManager> asyncMgr = mAsyncImageManager;
RefPtr<CompositorAnimationStorage> animStorage = GetAnimationStorage(); RefPtr<CompositorAnimationStorage> animStorage = GetAnimationStorage();
mWrBridge = new WebRenderBridgeParent(this, aPipelineId, mWidget, nullptr, mWrBridge = new WebRenderBridgeParent(this, aPipelineId, mWidget, nullptr,
std::move(apis), std::move(asyncMgr), std::move(api), std::move(asyncMgr),
std::move(animStorage), mVsyncRate); std::move(animStorage), mVsyncRate);
mWrBridge.get()->AddRef(); // IPDL reference mWrBridge.get()->AddRef(); // IPDL reference
@ -1970,8 +1962,7 @@ bool CompositorBridgeParent::DeallocPWebGPUParent(
void CompositorBridgeParent::NotifyMemoryPressure() { void CompositorBridgeParent::NotifyMemoryPressure() {
if (mWrBridge) { if (mWrBridge) {
RefPtr<wr::WebRenderAPI> api = RefPtr<wr::WebRenderAPI> api = mWrBridge->GetWebRenderAPI();
mWrBridge->GetWebRenderAPI(wr::RenderRoot::Default);
if (api) { if (api) {
api->NotifyMemoryPressure(); api->NotifyMemoryPressure();
} }
@ -1980,8 +1971,7 @@ void CompositorBridgeParent::NotifyMemoryPressure() {
void CompositorBridgeParent::AccumulateMemoryReport(wr::MemoryReport* aReport) { void CompositorBridgeParent::AccumulateMemoryReport(wr::MemoryReport* aReport) {
if (mWrBridge) { if (mWrBridge) {
RefPtr<wr::WebRenderAPI> api = RefPtr<wr::WebRenderAPI> api = mWrBridge->GetWebRenderAPI();
mWrBridge->GetWebRenderAPI(wr::RenderRoot::Default);
if (api) { if (api) {
api->AccumulateMemoryReport(aReport); api->AccumulateMemoryReport(aReport);
} }
@ -2528,8 +2518,7 @@ bool CompositorBridgeParent::IsSameProcess() const {
void CompositorBridgeParent::NotifyWebRenderContextPurge() { void CompositorBridgeParent::NotifyWebRenderContextPurge() {
MOZ_ASSERT(CompositorLoop() == MessageLoop::current()); MOZ_ASSERT(CompositorLoop() == MessageLoop::current());
RefPtr<wr::WebRenderAPI> api = RefPtr<wr::WebRenderAPI> api = mWrBridge->GetWebRenderAPI();
mWrBridge->GetWebRenderAPI(wr::RenderRoot::Default);
api->ClearAllCaches(); api->ClearAllCaches();
} }

View file

@ -227,13 +227,12 @@ ContentCompositorBridgeParent::AllocPWebRenderBridgeParent(
} }
} }
nsTArray<RefPtr<wr::WebRenderAPI>> apis; RefPtr<wr::WebRenderAPI> api;
bool cloneSuccess = false;
if (root) { if (root) {
cloneSuccess = root->CloneWebRenderAPIs(apis); api = root->GetWebRenderAPI();
} }
if (!cloneSuccess) { if (!root || !api) {
// This could happen when this function is called after // This could happen when this function is called after
// CompositorBridgeParent destruction. This was observed during Tab move // CompositorBridgeParent destruction. This was observed during Tab move
// between different windows. // between different windows.
@ -247,10 +246,11 @@ ContentCompositorBridgeParent::AllocPWebRenderBridgeParent(
return parent; return parent;
} }
api = api->Clone();
RefPtr<AsyncImagePipelineManager> holder = root->AsyncImageManager(); RefPtr<AsyncImagePipelineManager> holder = root->AsyncImageManager();
RefPtr<CompositorAnimationStorage> animStorage = cbp->GetAnimationStorage(); RefPtr<CompositorAnimationStorage> animStorage = cbp->GetAnimationStorage();
WebRenderBridgeParent* parent = new WebRenderBridgeParent( WebRenderBridgeParent* parent = new WebRenderBridgeParent(
this, aPipelineId, nullptr, root->CompositorScheduler(), std::move(apis), this, aPipelineId, nullptr, root->CompositorScheduler(), std::move(api),
std::move(holder), std::move(animStorage), cbp->GetVsyncInterval()); std::move(holder), std::move(animStorage), cbp->GetVsyncInterval());
parent->AddRef(); // IPDL reference parent->AddRef(); // IPDL reference

View file

@ -37,11 +37,11 @@ AsyncImagePipelineManager::AsyncImagePipeline::AsyncImagePipeline()
mMixBlendMode(wr::MixBlendMode::Normal) {} mMixBlendMode(wr::MixBlendMode::Normal) {}
AsyncImagePipelineManager::AsyncImagePipelineManager( AsyncImagePipelineManager::AsyncImagePipelineManager(
nsTArray<RefPtr<wr::WebRenderAPI>>&& aApis, bool aUseCompositorWnd) RefPtr<wr::WebRenderAPI>&& aApi, bool aUseCompositorWnd)
: mApis(std::move(aApis)), : mApi(aApi),
mUseCompositorWnd(aUseCompositorWnd), mUseCompositorWnd(aUseCompositorWnd),
mIdNamespace(mApis[0]->GetNamespace()), mIdNamespace(mApi->GetNamespace()),
mUseTripleBuffering(mApis[0]->GetUseTripleBuffering()), mUseTripleBuffering(mApi->GetUseTripleBuffering()),
mResourceId(0), mResourceId(0),
mAsyncImageEpoch{0}, mAsyncImageEpoch{0},
mWillGenerateFrame{}, mWillGenerateFrame{},
@ -57,7 +57,7 @@ AsyncImagePipelineManager::~AsyncImagePipelineManager() {
void AsyncImagePipelineManager::Destroy() { void AsyncImagePipelineManager::Destroy() {
MOZ_ASSERT(!mDestroyed); MOZ_ASSERT(!mDestroyed);
mApis.Clear(); mApi = nullptr;
mPipelineTexturesHolders.Clear(); mPipelineTexturesHolders.Clear();
mDestroyed = true; mDestroyed = true;
} }
@ -431,9 +431,8 @@ void AsyncImagePipelineManager::ApplyAsyncImageForPipeline(
if (!pipeline) { if (!pipeline) {
return; return;
} }
wr::WebRenderAPI* api = mApis[(size_t)pipeline->mRenderRoot];
wr::TransactionBuilder fastTxn(/* aUseSceneBuilderThread */ false); wr::TransactionBuilder fastTxn(/* aUseSceneBuilderThread */ false);
wr::AutoTransactionSender sender(api, &fastTxn); wr::AutoTransactionSender sender(mApi, &fastTxn);
// Transaction for async image pipeline that uses ImageBridge always need to // Transaction for async image pipeline that uses ImageBridge always need to
// be non low priority. // be non low priority.

View file

@ -36,7 +36,7 @@ class AsyncImagePipelineManager final {
public: public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AsyncImagePipelineManager) NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AsyncImagePipelineManager)
explicit AsyncImagePipelineManager(nsTArray<RefPtr<wr::WebRenderAPI>>&& aApis, explicit AsyncImagePipelineManager(RefPtr<wr::WebRenderAPI>&& aApi,
bool aUseCompositorWnd); bool aUseCompositorWnd);
protected: protected:
@ -219,7 +219,7 @@ class AsyncImagePipelineManager final {
void CheckForTextureHostsNotUsedByGPU(); void CheckForTextureHostsNotUsedByGPU();
nsTArray<RefPtr<wr::WebRenderAPI>> mApis; RefPtr<wr::WebRenderAPI> mApi;
bool mUseCompositorWnd; bool mUseCompositorWnd;
const wr::IdNamespace mIdNamespace; const wr::IdNamespace mIdNamespace;

View file

@ -328,13 +328,13 @@ class MOZ_STACK_CLASS AutoWebRenderBridgeParentAsyncMessageSender final {
WebRenderBridgeParent::WebRenderBridgeParent( WebRenderBridgeParent::WebRenderBridgeParent(
CompositorBridgeParentBase* aCompositorBridge, CompositorBridgeParentBase* aCompositorBridge,
const wr::PipelineId& aPipelineId, widget::CompositorWidget* aWidget, const wr::PipelineId& aPipelineId, widget::CompositorWidget* aWidget,
CompositorVsyncScheduler* aScheduler, CompositorVsyncScheduler* aScheduler, RefPtr<wr::WebRenderAPI>&& aApi,
nsTArray<RefPtr<wr::WebRenderAPI>>&& aApis,
RefPtr<AsyncImagePipelineManager>&& aImageMgr, RefPtr<AsyncImagePipelineManager>&& aImageMgr,
RefPtr<CompositorAnimationStorage>&& aAnimStorage, TimeDuration aVsyncRate) RefPtr<CompositorAnimationStorage>&& aAnimStorage, TimeDuration aVsyncRate)
: mCompositorBridge(aCompositorBridge), : mCompositorBridge(aCompositorBridge),
mPipelineId(aPipelineId), mPipelineId(aPipelineId),
mWidget(aWidget), mWidget(aWidget),
mApi(aApi),
mAsyncImageManager(aImageMgr), mAsyncImageManager(aImageMgr),
mCompositorScheduler(aScheduler), mCompositorScheduler(aScheduler),
mAnimStorage(aAnimStorage), mAnimStorage(aAnimStorage),
@ -342,7 +342,7 @@ WebRenderBridgeParent::WebRenderBridgeParent(
mChildLayersObserverEpoch{0}, mChildLayersObserverEpoch{0},
mParentLayersObserverEpoch{0}, mParentLayersObserverEpoch{0},
mWrEpoch{0}, mWrEpoch{0},
mIdNamespace(aApis[0]->GetNamespace()), mIdNamespace(aApi->GetNamespace()),
mRenderRootRectMutex("WebRenderBridgeParent::mRenderRootRectMutex"), mRenderRootRectMutex("WebRenderBridgeParent::mRenderRootRectMutex"),
#if defined(MOZ_WIDGET_ANDROID) #if defined(MOZ_WIDGET_ANDROID)
mScreenPixelsTarget(nullptr), mScreenPixelsTarget(nullptr),
@ -364,11 +364,6 @@ WebRenderBridgeParent::WebRenderBridgeParent(
mRenderRoot = Some(wr::RenderRoot::Default); mRenderRoot = Some(wr::RenderRoot::Default);
for (auto& api : aApis) {
MOZ_ASSERT(api);
mApis[api->GetRenderRoot()] = api;
}
UpdateDebugFlags(); UpdateDebugFlags();
UpdateQualitySettings(); UpdateQualitySettings();
} }
@ -487,7 +482,7 @@ bool WebRenderBridgeParent::HandleDeferredPipelineData(
return false; return false;
} }
Api(wr::RenderRoot::Default)->SendTransaction(txn); mApi->SendTransaction(txn);
wr::IpcResourceUpdateQueue::ReleaseShmems(this, data.mSmallShmems); wr::IpcResourceUpdateQueue::ReleaseShmems(this, data.mSmallShmems);
wr::IpcResourceUpdateQueue::ReleaseShmems(this, data.mLargeShmems); wr::IpcResourceUpdateQueue::ReleaseShmems(this, data.mLargeShmems);
return true; return true;
@ -500,7 +495,7 @@ bool WebRenderBridgeParent::HandleDeferredPipelineData(
return false; return false;
} }
Api(wr::RenderRoot::Default)->SendTransaction(txn); mApi->SendTransaction(txn);
return true; return true;
}, },
[&](FocusTarget& data) { [&](FocusTarget& data) {
@ -998,7 +993,7 @@ mozilla::ipc::IPCResult WebRenderBridgeParent::RecvUpdateResources(
return IPC_FAIL(this, "Invalid WebRender resource data shmem or address."); return IPC_FAIL(this, "Invalid WebRender resource data shmem or address.");
} }
Api(aRenderRoot)->SendTransaction(txn); mApi->SendTransaction(txn);
return IPC_OK(); return IPC_OK();
} }
@ -1043,17 +1038,17 @@ bool WebRenderBridgeParent::IsRootWebRenderBridgeParent() const {
void WebRenderBridgeParent::SetCompositionRecorder( void WebRenderBridgeParent::SetCompositionRecorder(
UniquePtr<layers::WebRenderCompositionRecorder> aRecorder) { UniquePtr<layers::WebRenderCompositionRecorder> aRecorder) {
Api(wr::RenderRoot::Default)->SetCompositionRecorder(std::move(aRecorder)); mApi->SetCompositionRecorder(std::move(aRecorder));
} }
RefPtr<wr::WebRenderAPI::WriteCollectedFramesPromise> RefPtr<wr::WebRenderAPI::WriteCollectedFramesPromise>
WebRenderBridgeParent::WriteCollectedFrames() { WebRenderBridgeParent::WriteCollectedFrames() {
return Api(wr::RenderRoot::Default)->WriteCollectedFrames(); return mApi->WriteCollectedFrames();
} }
RefPtr<wr::WebRenderAPI::GetCollectedFramesPromise> RefPtr<wr::WebRenderAPI::GetCollectedFramesPromise>
WebRenderBridgeParent::GetCollectedFrames() { WebRenderBridgeParent::GetCollectedFrames() {
return Api(wr::RenderRoot::Default)->GetCollectedFrames(); return mApi->GetCollectedFrames();
} }
void WebRenderBridgeParent::AddPendingScrollPayload( void WebRenderBridgeParent::AddPendingScrollPayload(
@ -1217,7 +1212,7 @@ bool WebRenderBridgeParent::SetDisplayList(
MakeUnique<SceneBuiltNotification>(this, aWrEpoch, aTxnStartTime)); MakeUnique<SceneBuiltNotification>(this, aWrEpoch, aTxnStartTime));
} }
Api(aRenderRoot)->SendTransaction(aTxn); mApi->SendTransaction(aTxn);
// We will schedule generating a frame after the scene // We will schedule generating a frame after the scene
// build is done, so we don't need to do it here. // build is done, so we don't need to do it here.
@ -1248,7 +1243,7 @@ bool WebRenderBridgeParent::ProcessRenderRootDisplayListData(
txn.SetLowPriority(!IsRootWebRenderBridgeParent()); txn.SetLowPriority(!IsRootWebRenderBridgeParent());
if (aValidTransaction) { if (aValidTransaction) {
MOZ_ASSERT(aDisplayList.mIdNamespace == mIdNamespace); MOZ_ASSERT(aDisplayList.mIdNamespace == mIdNamespace);
sender.emplace(Api(renderRoot), &txn); sender.emplace(mApi, &txn);
} }
if (NS_WARN_IF(!ProcessWebRenderParentCommands(aDisplayList.mCommands, txn, if (NS_WARN_IF(!ProcessWebRenderParentCommands(aDisplayList.mCommands, txn,
@ -1466,7 +1461,7 @@ bool WebRenderBridgeParent::ProcessEmptyTransactionUpdates(
} }
if (!txn.IsEmpty()) { if (!txn.IsEmpty()) {
Api(aUpdates.mRenderRoot)->SendTransaction(txn); mApi->SendTransaction(txn);
} }
if (*aScheduleComposite) { if (*aScheduleComposite) {
@ -1602,7 +1597,7 @@ mozilla::ipc::IPCResult WebRenderBridgeParent::RecvParentCommands(
return IPC_FAIL(this, "Invalid parent command found"); return IPC_FAIL(this, "Invalid parent command found");
} }
Api(aRenderRoot)->SendTransaction(txn); mApi->SendTransaction(txn);
return IPC_OK(); return IPC_OK();
} }
@ -1612,7 +1607,7 @@ bool WebRenderBridgeParent::ProcessWebRenderParentCommands(
// Transaction for async image pipeline that uses ImageBridge always need to // Transaction for async image pipeline that uses ImageBridge always need to
// be non low priority. // be non low priority.
wr::TransactionBuilder txnForImageBridge; wr::TransactionBuilder txnForImageBridge;
wr::AutoTransactionSender sender(Api(aRenderRoot), &txnForImageBridge); wr::AutoTransactionSender sender(mApi, &txnForImageBridge);
for (nsTArray<WebRenderParentCommand>::index_type i = 0; for (nsTArray<WebRenderParentCommand>::index_type i = 0;
i < aCommands.Length(); ++i) { i < aCommands.Length(); ++i) {
@ -1700,7 +1695,7 @@ void WebRenderBridgeParent::FlushSceneBuilds() {
// to block until all the inflight transactions have been processed. This // to block until all the inflight transactions have been processed. This
// flush message blocks until all previously sent scenes have been built // flush message blocks until all previously sent scenes have been built
// and received by the render backend thread. // and received by the render backend thread.
mApis[wr::RenderRoot::Default]->FlushSceneBuilder(); mApi->FlushSceneBuilder();
// The post-swap hook for async-scene-building calls the // The post-swap hook for async-scene-building calls the
// ScheduleRenderOnCompositorThread function from the scene builder thread, // ScheduleRenderOnCompositorThread function from the scene builder thread,
// which then triggers a call to ScheduleGenerateFrame() on the compositor // which then triggers a call to ScheduleGenerateFrame() on the compositor
@ -1740,14 +1735,14 @@ void WebRenderBridgeParent::FlushFramePresentation() {
// this effectively blocks on the render backend and renderer threads, // this effectively blocks on the render backend and renderer threads,
// following the same codepath that WebRender takes to render and composite // following the same codepath that WebRender takes to render and composite
// a frame. // a frame.
mApis[wr::RenderRoot::Default]->WaitFlushed(); mApi->WaitFlushed();
} }
void WebRenderBridgeParent::DisableNativeCompositor() { void WebRenderBridgeParent::DisableNativeCompositor() {
// Make sure that SceneBuilder thread does not have a task. // Make sure that SceneBuilder thread does not have a task.
mApis[wr::RenderRoot::Default]->FlushSceneBuilder(); mApi->FlushSceneBuilder();
// Disable WebRender's native compositor usage // Disable WebRender's native compositor usage
mApis[wr::RenderRoot::Default]->EnableNativeCompositor(false); mApi->EnableNativeCompositor(false);
// Ensure we generate and render a frame immediately. // Ensure we generate and render a frame immediately.
ScheduleForcedGenerateFrame(); ScheduleForcedGenerateFrame();
@ -1755,44 +1750,22 @@ void WebRenderBridgeParent::DisableNativeCompositor() {
} }
void WebRenderBridgeParent::UpdateQualitySettings() { void WebRenderBridgeParent::UpdateQualitySettings() {
for (auto& api : mApis) {
if (!api) {
continue;
}
wr::TransactionBuilder txn; wr::TransactionBuilder txn;
txn.UpdateQualitySettings(gfxVars::AllowSacrificingSubpixelAA()); txn.UpdateQualitySettings(gfxVars::AllowSacrificingSubpixelAA());
api->SendTransaction(txn); mApi->SendTransaction(txn);
}
} }
void WebRenderBridgeParent::UpdateDebugFlags() { void WebRenderBridgeParent::UpdateDebugFlags() {
auto flags = gfxVars::WebRenderDebugFlags(); mApi->UpdateDebugFlags(gfxVars::WebRenderDebugFlags());
for (auto& api : mApis) {
if (!api) {
continue;
}
api->UpdateDebugFlags(flags);
}
} }
void WebRenderBridgeParent::UpdateMultithreading() { void WebRenderBridgeParent::UpdateMultithreading() {
bool multithreading = gfxVars::UseWebRenderMultithreading(); mApi->EnableMultithreading(gfxVars::UseWebRenderMultithreading());
for (auto& api : mApis) {
if (!api) {
continue;
}
api->EnableMultithreading(multithreading);
}
} }
void WebRenderBridgeParent::UpdateBatchingParameters() { void WebRenderBridgeParent::UpdateBatchingParameters() {
uint32_t count = gfxVars::WebRenderBatchingLookback(); uint32_t count = gfxVars::WebRenderBatchingLookback();
for (auto& api : mApis) { mApi->SetBatchingLookback(count);
if (!api) {
continue;
}
api->SetBatchingLookback(count);
}
} }
#if defined(MOZ_WIDGET_ANDROID) #if defined(MOZ_WIDGET_ANDROID)
@ -1827,8 +1800,7 @@ void WebRenderBridgeParent::MaybeCaptureScreenPixels() {
IntSize size(client_size.width, client_size.height); IntSize size(client_size.width, client_size.height);
mApis[wr::RenderRoot::Default]->Readback( mApi->Readback(TimeStamp::Now(), size, format,
TimeStamp::Now(), size, format,
Range<uint8_t>(mem.get<uint8_t>(), buffer_size)); Range<uint8_t>(mem.get<uint8_t>(), buffer_size));
Unused << mScreenPixelsTarget->SendScreenPixels( Unused << mScreenPixelsTarget->SendScreenPixels(
@ -1890,8 +1862,7 @@ mozilla::ipc::IPCResult WebRenderBridgeParent::RecvGetSnapshot(
FlushSceneBuilds(); FlushSceneBuilds();
FlushFrameGeneration(); FlushFrameGeneration();
mApis[wr::RenderRoot::Default]->Readback(start, size, mApi->Readback(start, size, bufferTexture->GetFormat(),
bufferTexture->GetFormat(),
Range<uint8_t>(buffer, buffer_size)); Range<uint8_t>(buffer, buffer_size));
return IPC_OK(); return IPC_OK();
@ -2028,7 +1999,7 @@ mozilla::ipc::IPCResult WebRenderBridgeParent::RecvClearCachedResources() {
MakeUnique<ScheduleObserveLayersUpdate>( MakeUnique<ScheduleObserveLayersUpdate>(
mCompositorBridge, GetLayersId(), mCompositorBridge, GetLayersId(),
mChildLayersObserverEpoch, false)); mChildLayersObserverEpoch, false));
Api(renderRoot)->SendTransaction(txn); mApi->SendTransaction(txn);
} else { } else {
if (RefPtr<WebRenderBridgeParent> root = if (RefPtr<WebRenderBridgeParent> root =
GetRootWebRenderBridgeParent()) { GetRootWebRenderBridgeParent()) {
@ -2052,14 +2023,13 @@ mozilla::ipc::IPCResult WebRenderBridgeParent::RecvClearCachedResources() {
} }
wr::Epoch WebRenderBridgeParent::UpdateWebRender( wr::Epoch WebRenderBridgeParent::UpdateWebRender(
CompositorVsyncScheduler* aScheduler, CompositorVsyncScheduler* aScheduler, RefPtr<wr::WebRenderAPI>&& aApi,
nsTArray<RefPtr<wr::WebRenderAPI>>&& aApis,
AsyncImagePipelineManager* aImageMgr, AsyncImagePipelineManager* aImageMgr,
CompositorAnimationStorage* aAnimStorage, CompositorAnimationStorage* aAnimStorage,
const TextureFactoryIdentifier& aTextureFactoryIdentifier) { const TextureFactoryIdentifier& aTextureFactoryIdentifier) {
MOZ_ASSERT(!IsRootWebRenderBridgeParent()); MOZ_ASSERT(!IsRootWebRenderBridgeParent());
MOZ_ASSERT(aScheduler); MOZ_ASSERT(aScheduler);
MOZ_ASSERT(!aApis.IsEmpty()); MOZ_ASSERT(aApi);
MOZ_ASSERT(aImageMgr); MOZ_ASSERT(aImageMgr);
MOZ_ASSERT(aAnimStorage); MOZ_ASSERT(aAnimStorage);
@ -2069,7 +2039,7 @@ wr::Epoch WebRenderBridgeParent::UpdateWebRender(
// Update id name space to identify obsoleted keys. // Update id name space to identify obsoleted keys.
// Since usage of invalid keys could cause crash in webrender. // Since usage of invalid keys could cause crash in webrender.
mIdNamespace = aApis[0]->GetNamespace(); mIdNamespace = aApi->GetNamespace();
// XXX Remove it when webrender supports sharing/moving Keys between different // XXX Remove it when webrender supports sharing/moving Keys between different
// webrender instances. // webrender instances.
// XXX It requests client to update/reallocate webrender related resources, // XXX It requests client to update/reallocate webrender related resources,
@ -2087,9 +2057,7 @@ wr::Epoch WebRenderBridgeParent::UpdateWebRender(
ClearResources(); ClearResources();
mCompositorBridge = cBridge; mCompositorBridge = cBridge;
mCompositorScheduler = aScheduler; mCompositorScheduler = aScheduler;
for (auto& api : aApis) { mApi = aApi;
mApis[api->GetRenderRoot()] = api;
}
mAsyncImageManager = aImageMgr; mAsyncImageManager = aImageMgr;
mAnimStorage = aAnimStorage; mAnimStorage = aAnimStorage;
@ -2123,7 +2091,7 @@ void WebRenderBridgeParent::InvalidateRenderedFrame() {
if (renderRoot == wr::RenderRoot::Default) { if (renderRoot == wr::RenderRoot::Default) {
wr::TransactionBuilder fastTxn(/* aUseSceneBuilderThread */ false); wr::TransactionBuilder fastTxn(/* aUseSceneBuilderThread */ false);
fastTxn.InvalidateRenderedFrame(); fastTxn.InvalidateRenderedFrame();
Api(renderRoot)->SendTransaction(fastTxn); mApi->SendTransaction(fastTxn);
} }
} }
} }
@ -2139,14 +2107,14 @@ void WebRenderBridgeParent::ScheduleForcedGenerateFrame() {
mozilla::ipc::IPCResult WebRenderBridgeParent::RecvCapture() { mozilla::ipc::IPCResult WebRenderBridgeParent::RecvCapture() {
if (!mDestroyed) { if (!mDestroyed) {
mApis[wr::RenderRoot::Default]->Capture(); mApi->Capture();
} }
return IPC_OK(); return IPC_OK();
} }
mozilla::ipc::IPCResult WebRenderBridgeParent::RecvToggleCaptureSequence() { mozilla::ipc::IPCResult WebRenderBridgeParent::RecvToggleCaptureSequence() {
if (!mDestroyed) { if (!mDestroyed) {
mApis[wr::RenderRoot::Default]->ToggleCaptureSequence(); mApi->ToggleCaptureSequence();
} }
return IPC_OK(); return IPC_OK();
} }
@ -2154,7 +2122,7 @@ mozilla::ipc::IPCResult WebRenderBridgeParent::RecvToggleCaptureSequence() {
mozilla::ipc::IPCResult WebRenderBridgeParent::RecvSetTransactionLogging( mozilla::ipc::IPCResult WebRenderBridgeParent::RecvSetTransactionLogging(
const bool& aValue) { const bool& aValue) {
if (!mDestroyed) { if (!mDestroyed) {
mApis[wr::RenderRoot::Default]->SetTransactionLogging(aValue); mApi->SetTransactionLogging(aValue);
} }
return IPC_OK(); return IPC_OK();
} }
@ -2342,8 +2310,8 @@ void WebRenderBridgeParent::CompositeToTarget(VsyncId aId,
return; return;
} }
if (mSkippedComposite || wr::RenderThread::Get()->TooManyPendingFrames( if (mSkippedComposite ||
mApis[wr::RenderRoot::Default]->GetId())) { wr::RenderThread::Get()->TooManyPendingFrames(mApi->GetId())) {
// Render thread is busy, try next time. // Render thread is busy, try next time.
mSkippedComposite = true; mSkippedComposite = true;
mSkippedCompositeId = aId; mSkippedCompositeId = aId;
@ -2394,8 +2362,7 @@ void WebRenderBridgeParent::MaybeGenerateFrame(VsyncId aId,
wr::TransactionBuilder fastTxn(false /* useSceneBuilderThread */); wr::TransactionBuilder fastTxn(false /* useSceneBuilderThread */);
// Handle transaction that is related to DisplayList. // Handle transaction that is related to DisplayList.
wr::TransactionBuilder sceneBuilderTxn; wr::TransactionBuilder sceneBuilderTxn;
wr::AutoTransactionSender senders(mApis[wr::RenderRoot::Default], wr::AutoTransactionSender sender(mApi, &sceneBuilderTxn);
&sceneBuilderTxn);
// Adding and updating wr::ImageKeys of ImageHosts that uses ImageBridge are // Adding and updating wr::ImageKeys of ImageHosts that uses ImageBridge are
// done without using transaction of scene builder thread. With it, updating // done without using transaction of scene builder thread. With it, updating
@ -2433,20 +2400,16 @@ void WebRenderBridgeParent::MaybeGenerateFrame(VsyncId aId,
SetAPZSampleTime(); SetAPZSampleTime();
wr::RenderThread::Get()->IncPendingFrameCount( wr::RenderThread::Get()->IncPendingFrameCount(mApi->GetId(), aId, start);
mApis[wr::RenderRoot::Default]->GetId(), aId, start);
#if defined(ENABLE_FRAME_LATENCY_LOG) #if defined(ENABLE_FRAME_LATENCY_LOG)
auto startTime = TimeStamp::Now(); auto startTime = TimeStamp::Now();
mApis[wr::RenderRoot::Default]->SetFrameStartTime(startTime); mApi->SetFrameStartTime(startTime);
#endif #endif
MOZ_ASSERT(generateFrame); MOZ_ASSERT(generateFrame);
fastTxn.GenerateFrame(); fastTxn.GenerateFrame();
mApi->SendTransaction(fastTxn);
wr::RenderRootArray<wr::TransactionBuilder*> generateFrameTxns;
generateFrameTxns[wr::RenderRoot::Default] = &fastTxn;
wr::WebRenderAPI::SendTransactions(mApis, generateFrameTxns);
#if defined(MOZ_WIDGET_ANDROID) #if defined(MOZ_WIDGET_ANDROID)
MaybeCaptureScreenPixels(); MaybeCaptureScreenPixels();
@ -2479,12 +2442,6 @@ void WebRenderBridgeParent::HoldPendingTransactionId(
aUseForTelemetry, std::move(aPayloads))); aUseForTelemetry, std::move(aPayloads)));
} }
already_AddRefed<wr::WebRenderAPI>
WebRenderBridgeParent::GetWebRenderAPIAtPoint(const ScreenPoint& aPoint) {
MutexAutoLock lock(mRenderRootRectMutex);
return do_AddRef(Api(wr::RenderRoot::Default));
}
TransactionId WebRenderBridgeParent::LastPendingTransactionId() { TransactionId WebRenderBridgeParent::LastPendingTransactionId() {
TransactionId id{0}; TransactionId id{0};
if (!mPendingTransactionIds.empty()) { if (!mPendingTransactionIds.empty()) {
@ -2675,7 +2632,7 @@ void WebRenderBridgeParent::Pause() {
return; return;
} }
mApis[wr::RenderRoot::Default]->Pause(); mApi->Pause();
mPaused = true; mPaused = true;
} }
@ -2686,7 +2643,7 @@ bool WebRenderBridgeParent::Resume() {
return false; return false;
} }
if (!mApis[wr::RenderRoot::Default]->Resume()) { if (!mApi->Resume()) {
return false; return false;
} }
@ -2698,7 +2655,7 @@ bool WebRenderBridgeParent::Resume() {
} }
void WebRenderBridgeParent::ClearResources() { void WebRenderBridgeParent::ClearResources() {
if (!mApis[wr::RenderRoot::Default]) { if (!mApi) {
return; return;
} }
@ -2724,15 +2681,10 @@ void WebRenderBridgeParent::ClearResources() {
mAsyncImageManager->RemovePipeline(mPipelineId, wrEpoch); mAsyncImageManager->RemovePipeline(mPipelineId, wrEpoch);
for (auto& api : mApis) {
if (!api) {
continue;
}
wr::TransactionBuilder txn; wr::TransactionBuilder txn;
txn.SetLowPriority(true); txn.SetLowPriority(true);
txn.ClearDisplayList(wrEpoch, mPipelineId); txn.ClearDisplayList(wrEpoch, mPipelineId);
auto renderRoot = api->GetRenderRoot();
for (const auto& entry : mAsyncCompositables) { for (const auto& entry : mAsyncCompositables) {
wr::PipelineId pipelineId = wr::AsPipelineId(entry.first); wr::PipelineId pipelineId = wr::AsPipelineId(entry.first);
RefPtr<WebRenderImageHost> host = entry.second; RefPtr<WebRenderImageHost> host = entry.second;
@ -2742,8 +2694,7 @@ void WebRenderBridgeParent::ClearResources() {
} }
mAsyncCompositables.clear(); mAsyncCompositables.clear();
txn.RemovePipeline(mPipelineId); txn.RemovePipeline(mPipelineId);
api->SendTransaction(txn); mApi->SendTransaction(txn);
}
for (const auto& id : mActiveAnimations) { for (const auto& id : mActiveAnimations) {
mAnimStorage->ClearById(id.first); mAnimStorage->ClearById(id.first);
@ -2759,9 +2710,7 @@ void WebRenderBridgeParent::ClearResources() {
mAnimStorage = nullptr; mAnimStorage = nullptr;
mCompositorScheduler = nullptr; mCompositorScheduler = nullptr;
mAsyncImageManager = nullptr; mAsyncImageManager = nullptr;
for (auto& api : mApis) { mApi = nullptr;
api = nullptr;
}
mCompositorBridge = nullptr; mCompositorBridge = nullptr;
} }
@ -2823,15 +2772,13 @@ mozilla::ipc::IPCResult WebRenderBridgeParent::RecvReleaseCompositable(
} }
TextureFactoryIdentifier WebRenderBridgeParent::GetTextureFactoryIdentifier() { TextureFactoryIdentifier WebRenderBridgeParent::GetTextureFactoryIdentifier() {
MOZ_ASSERT(!!mApis[wr::RenderRoot::Default]); MOZ_ASSERT(mApi);
return TextureFactoryIdentifier( return TextureFactoryIdentifier(
LayersBackend::LAYERS_WR, XRE_GetProcessType(), LayersBackend::LAYERS_WR, XRE_GetProcessType(), mApi->GetMaxTextureSize(),
mApis[wr::RenderRoot::Default]->GetMaxTextureSize(), false, false, mApi->GetUseANGLE(), mApi->GetUseDComp(),
mApis[wr::RenderRoot::Default]->GetUseANGLE(),
mApis[wr::RenderRoot::Default]->GetUseDComp(),
mAsyncImageManager->UseCompositorWnd(), false, false, false, mAsyncImageManager->UseCompositorWnd(), false, false, false,
mApis[wr::RenderRoot::Default]->GetSyncHandle()); mApi->GetSyncHandle());
} }
wr::Epoch WebRenderBridgeParent::GetNextWrEpoch() { wr::Epoch WebRenderBridgeParent::GetNextWrEpoch() {

View file

@ -100,7 +100,7 @@ class WebRenderBridgeParent final
const wr::PipelineId& aPipelineId, const wr::PipelineId& aPipelineId,
widget::CompositorWidget* aWidget, widget::CompositorWidget* aWidget,
CompositorVsyncScheduler* aScheduler, CompositorVsyncScheduler* aScheduler,
nsTArray<RefPtr<wr::WebRenderAPI>>&& aApis, RefPtr<wr::WebRenderAPI>&& aApi,
RefPtr<AsyncImagePipelineManager>&& aImageMgr, RefPtr<AsyncImagePipelineManager>&& aImageMgr,
RefPtr<CompositorAnimationStorage>&& aAnimStorage, RefPtr<CompositorAnimationStorage>&& aAnimStorage,
TimeDuration aVsyncRate); TimeDuration aVsyncRate);
@ -109,27 +109,8 @@ class WebRenderBridgeParent final
const wr::PipelineId& aPipelineId); const wr::PipelineId& aPipelineId);
wr::PipelineId PipelineId() { return mPipelineId; } wr::PipelineId PipelineId() { return mPipelineId; }
already_AddRefed<wr::WebRenderAPI> GetWebRenderAPI() {
bool CloneWebRenderAPIs(nsTArray<RefPtr<wr::WebRenderAPI>>& aOutAPIs) { return do_AddRef(mApi);
for (auto& api : mApis) {
if (api) {
RefPtr<wr::WebRenderAPI> clone = api->Clone();
if (!clone) {
return false;
}
aOutAPIs.AppendElement(clone);
}
}
return true;
}
already_AddRefed<wr::WebRenderAPI> GetWebRenderAPIAtPoint(
const ScreenPoint& aPoint);
already_AddRefed<wr::WebRenderAPI> GetWebRenderAPI(
wr::RenderRoot aRenderRoot) {
if (aRenderRoot > wr::kHighestRenderRoot) {
return nullptr;
}
return do_AddRef(mApis[aRenderRoot]);
} }
AsyncImagePipelineManager* AsyncImageManager() { return mAsyncImageManager; } AsyncImagePipelineManager* AsyncImageManager() { return mAsyncImageManager; }
CompositorVsyncScheduler* CompositorScheduler() { CompositorVsyncScheduler* CompositorScheduler() {
@ -304,8 +285,7 @@ class WebRenderBridgeParent final
RefPtr<const wr::WebRenderPipelineInfo> aInfo); RefPtr<const wr::WebRenderPipelineInfo> aInfo);
wr::Epoch UpdateWebRender( wr::Epoch UpdateWebRender(
CompositorVsyncScheduler* aScheduler, CompositorVsyncScheduler* aScheduler, RefPtr<wr::WebRenderAPI>&& aApi,
nsTArray<RefPtr<wr::WebRenderAPI>>&& aApis,
AsyncImagePipelineManager* aImageMgr, AsyncImagePipelineManager* aImageMgr,
CompositorAnimationStorage* aAnimStorage, CompositorAnimationStorage* aAnimStorage,
const TextureFactoryIdentifier& aTextureFactoryIdentifier); const TextureFactoryIdentifier& aTextureFactoryIdentifier);
@ -381,15 +361,6 @@ class WebRenderBridgeParent final
explicit WebRenderBridgeParent(const wr::PipelineId& aPipelineId); explicit WebRenderBridgeParent(const wr::PipelineId& aPipelineId);
virtual ~WebRenderBridgeParent(); virtual ~WebRenderBridgeParent();
wr::WebRenderAPI* Api(wr::RenderRoot aRenderRoot) {
if (IsRootWebRenderBridgeParent()) {
return mApis[aRenderRoot];
} else {
MOZ_ASSERT(aRenderRoot == wr::RenderRoot::Default);
return mApis[*mRenderRoot];
}
}
// Within WebRenderBridgeParent, we can use wr::RenderRoot::Default to // Within WebRenderBridgeParent, we can use wr::RenderRoot::Default to
// refer to DefaultApi(), which can be the content API if this // refer to DefaultApi(), which can be the content API if this
// WebRenderBridgeParent is for a content WebRenderBridgeChild. However, // WebRenderBridgeParent is for a content WebRenderBridgeChild. However,
@ -573,14 +544,7 @@ class WebRenderBridgeParent final
CompositorBridgeParentBase* MOZ_NON_OWNING_REF mCompositorBridge; CompositorBridgeParentBase* MOZ_NON_OWNING_REF mCompositorBridge;
wr::PipelineId mPipelineId; wr::PipelineId mPipelineId;
RefPtr<widget::CompositorWidget> mWidget; RefPtr<widget::CompositorWidget> mWidget;
// The RenderRootArray means there will always be a fixed number of apis, RefPtr<wr::WebRenderAPI> mApi;
// one for each RenderRoot, even if renderroot splitting isn't enabled.
// In this case, the unused apis will be nullptrs. Also, if this is not
// the root WebRenderBridgeParent, there should only be one api in this
// list. We avoid using a dynamically sized array for this because we
// need to be able to null these out in a thread-safe way from
// ClearResources, and there's no way to do that with an nsTArray.
wr::RenderRootArray<RefPtr<wr::WebRenderAPI>> mApis;
// This is a map from pipeline id to render root, that tracks the render // This is a map from pipeline id to render root, that tracks the render
// roots of all subpipelines (including nested subpipelines, e.g. in the // roots of all subpipelines (including nested subpipelines, e.g. in the
// Fission case) attached to this WebRenderBridgeParent. This is only // Fission case) attached to this WebRenderBridgeParent. This is only