diff --git a/gfx/layers/wr/AsyncImagePipelineManager.cpp b/gfx/layers/wr/AsyncImagePipelineManager.cpp index 0bc223885534..e7d256959ef1 100644 --- a/gfx/layers/wr/AsyncImagePipelineManager.cpp +++ b/gfx/layers/wr/AsyncImagePipelineManager.cpp @@ -205,7 +205,8 @@ Maybe AsyncImagePipelineManager::UpdateImageKeys( MOZ_ASSERT(aKeys.IsEmpty()); MOZ_ASSERT(aPipeline); - TextureHost* texture = aPipeline->mImageHost->GetAsTextureHostForComposite(); + TextureHost* texture = + aPipeline->mImageHost->GetAsTextureHostForComposite(this); TextureHost* previousTexture = aPipeline->mCurrentTexture.get(); if (texture == previousTexture) { diff --git a/gfx/layers/wr/WebRenderBridgeParent.cpp b/gfx/layers/wr/WebRenderBridgeParent.cpp index a7f01f71bc29..8d1c08e55cfe 100644 --- a/gfx/layers/wr/WebRenderBridgeParent.cpp +++ b/gfx/layers/wr/WebRenderBridgeParent.cpp @@ -1789,7 +1789,7 @@ void WebRenderBridgeParent::AddPipelineIdForCompositable( return; } - wrHost->SetWrBridge(this); + wrHost->SetWrBridge(aPipelineId, this); asyncCompositables.emplace(wr::AsUint64(aPipelineId), wrHost); mAsyncImageManager->AddAsyncImagePipeline(aPipelineId, wrHost, RenderRootForExternal(aRenderRoot)); @@ -1821,7 +1821,7 @@ void WebRenderBridgeParent::RemovePipelineIdForCompositable( } RefPtr& wrHost = it->second; - wrHost->ClearWrBridge(this); + wrHost->ClearWrBridge(aPipelineId, this); mAsyncImageManager->RemoveAsyncImagePipeline(aPipelineId, aTxn); aTxn.RemovePipeline(aPipelineId); asyncCompositables.erase(wr::AsUint64(aPipelineId)); @@ -2603,7 +2603,7 @@ void WebRenderBridgeParent::ClearResources() { for (const auto& entry : mAsyncCompositables[renderRoot]) { wr::PipelineId pipelineId = wr::AsPipelineId(entry.first); RefPtr host = entry.second; - host->ClearWrBridge(this); + host->ClearWrBridge(pipelineId, this); mAsyncImageManager->RemoveAsyncImagePipeline(pipelineId, txn); txn.RemovePipeline(pipelineId); } diff --git a/gfx/layers/wr/WebRenderImageHost.cpp b/gfx/layers/wr/WebRenderImageHost.cpp index b9e0e2061e9d..a14fbec3ace8 100644 --- a/gfx/layers/wr/WebRenderImageHost.cpp +++ b/gfx/layers/wr/WebRenderImageHost.cpp @@ -8,6 +8,7 @@ #include "LayersLogging.h" #include "mozilla/Move.h" +#include "mozilla/ScopeExit.h" #include "mozilla/layers/Compositor.h" // for Compositor #include "mozilla/layers/CompositorVsyncScheduler.h" // for CompositorVsyncScheduler #include "mozilla/layers/Effects.h" // for TexturedEffect, Effect, etc @@ -29,9 +30,11 @@ namespace layers { class ISurfaceAllocator; WebRenderImageHost::WebRenderImageHost(const TextureInfo& aTextureInfo) - : CompositableHost(aTextureInfo), ImageComposite(), mWrBridgeBindings(0) {} + : CompositableHost(aTextureInfo), + ImageComposite(), + mCurrentAsyncImageManager(nullptr) {} -WebRenderImageHost::~WebRenderImageHost() { MOZ_ASSERT(!mWrBridge); } +WebRenderImageHost::~WebRenderImageHost() { MOZ_ASSERT(mWrBridges.empty()); } void WebRenderImageHost::UseTextureHost( const nsTArray& aTextures) { @@ -63,9 +66,13 @@ void WebRenderImageHost::UseTextureHost( SetImages(std::move(newImages)); - if (mWrBridge && mWrBridge->CompositorScheduler() && GetAsyncRef()) { - // Will check if we will generate frame. - mWrBridge->CompositorScheduler()->ScheduleComposition(); + if (GetAsyncRef()) { + for (const auto& it : mWrBridges) { + WebRenderBridgeParent* wrBridge = it.second; + if (wrBridge && wrBridge->CompositorScheduler()) { + wrBridge->CompositorScheduler()->ScheduleComposition(); + } + } } // Video producers generally send replacement images with the same frameID but @@ -73,14 +80,18 @@ void WebRenderImageHost::UseTextureHost( // means that any CompositeUntil() call we made in Composite() may no longer // guarantee that we'll composite until the next frame is ready. Fix that // here. - if (mWrBridge && mLastFrameID >= 0) { - MOZ_ASSERT(mWrBridge->AsyncImageManager()); + if (mLastFrameID >= 0 && !mWrBridges.empty()) { for (const auto& img : Images()) { bool frameComesAfter = img.mFrameID > mLastFrameID || img.mProducerID != mLastProducerID; if (frameComesAfter && !img.mTimeStamp.IsNull()) { - mWrBridge->AsyncImageManager()->CompositeUntil( - img.mTimeStamp + TimeDuration::FromMilliseconds(BIAS_TIME_MS)); + for (const auto& it : mWrBridges) { + WebRenderBridgeParent* wrBridge = it.second; + if (wrBridge) { + wrBridge->AsyncImageManager()->CompositeUntil( + img.mTimeStamp + TimeDuration::FromMilliseconds(BIAS_TIME_MS)); + } + } break; } } @@ -104,9 +115,10 @@ void WebRenderImageHost::RemoveTextureHost(TextureHost* aTexture) { TimeStamp WebRenderImageHost::GetCompositionTime() const { TimeStamp time; - if (mWrBridge) { - MOZ_ASSERT(mWrBridge->AsyncImageManager()); - time = mWrBridge->AsyncImageManager()->GetCompositionTime(); + + MOZ_ASSERT(mCurrentAsyncImageManager); + if (mCurrentAsyncImageManager) { + time = mCurrentAsyncImageManager->GetCompositionTime(); } return time; } @@ -119,10 +131,11 @@ TextureHost* WebRenderImageHost::GetAsTextureHost(IntRect* aPictureRect) { return nullptr; } -TextureHost* WebRenderImageHost::GetAsTextureHostForComposite() { - if (!mWrBridge) { - return nullptr; - } +TextureHost* WebRenderImageHost::GetAsTextureHostForComposite( + AsyncImagePipelineManager* aAsyncImageManager) { + mCurrentAsyncImageManager = aAsyncImageManager; + const auto onExit = + mozilla::MakeScopeExit([&]() { mCurrentAsyncImageManager = nullptr; }); int imageIndex = ChooseImageIndex(); if (imageIndex < 0) { @@ -131,8 +144,7 @@ TextureHost* WebRenderImageHost::GetAsTextureHostForComposite() { } if (uint32_t(imageIndex) + 1 < ImagesCount()) { - MOZ_ASSERT(mWrBridge->AsyncImageManager()); - mWrBridge->AsyncImageManager()->CompositeUntil( + mCurrentAsyncImageManager->CompositeUntil( GetImage(imageIndex + 1)->mTimeStamp + TimeDuration::FromMilliseconds(BIAS_TIME_MS)); } @@ -145,9 +157,9 @@ TextureHost* WebRenderImageHost::GetAsTextureHostForComposite() { info.mImageBridgeProcessId = mAsyncRef.mProcessId; info.mNotification = ImageCompositeNotification( mAsyncRef.mHandle, img->mTimeStamp, - mWrBridge->AsyncImageManager()->GetCompositionTime(), img->mFrameID, + mCurrentAsyncImageManager->GetCompositionTime(), img->mFrameID, img->mProducerID); - mWrBridge->AsyncImageManager()->AppendImageCompositeNotification(info); + mCurrentAsyncImageManager->AppendImageCompositeNotification(info); } mLastFrameID = img->mFrameID; mLastProducerID = img->mProducerID; @@ -236,29 +248,28 @@ IntSize WebRenderImageHost::GetImageSize() { return IntSize(); } -void WebRenderImageHost::SetWrBridge(WebRenderBridgeParent* aWrBridge) { - // For image hosts created through ImageBridgeParent, there may be multiple - // references to it due to the order of creation and freeing of layers by - // the layer tree. However this should be limited to things such as video - // which will not be reused across different WebRenderBridgeParent objects. +void WebRenderImageHost::SetWrBridge(const wr::PipelineId& aPipelineId, + WebRenderBridgeParent* aWrBridge) { MOZ_ASSERT(aWrBridge); - MOZ_ASSERT(!mWrBridge || mWrBridge == aWrBridge); - mWrBridge = aWrBridge; - ++mWrBridgeBindings; +#ifdef DEBUG + const auto it = mWrBridges.find(wr::AsUint64(aPipelineId)); + MOZ_ASSERT(it == mWrBridges.end()); +#endif + mWrBridges.emplace(wr::AsUint64(aPipelineId), aWrBridge); } -void WebRenderImageHost::ClearWrBridge(WebRenderBridgeParent* aWrBridge) { +void WebRenderImageHost::ClearWrBridge(const wr::PipelineId& aPipelineId, + WebRenderBridgeParent* aWrBridge) { MOZ_ASSERT(aWrBridge); - MOZ_ASSERT(mWrBridgeBindings > 0); - --mWrBridgeBindings; - if (mWrBridgeBindings == 0) { - MOZ_ASSERT(aWrBridge == mWrBridge); - if (aWrBridge != mWrBridge) { - gfxCriticalNote << "WrBridge mismatch happened"; - } - SetCurrentTextureHost(nullptr); - mWrBridge = nullptr; + + const auto it = mWrBridges.find(wr::AsUint64(aPipelineId)); + MOZ_ASSERT(it != mWrBridges.end()); + if (it == mWrBridges.end()) { + gfxCriticalNote << "WrBridge mismatch happened"; + return; } + mWrBridges.erase(it); + SetCurrentTextureHost(nullptr); } } // namespace layers diff --git a/gfx/layers/wr/WebRenderImageHost.h b/gfx/layers/wr/WebRenderImageHost.h index dc29b4369faf..64d193209e75 100644 --- a/gfx/layers/wr/WebRenderImageHost.h +++ b/gfx/layers/wr/WebRenderImageHost.h @@ -7,6 +7,8 @@ #ifndef MOZILLA_GFX_WEBRENDERIMAGEHOST_H #define MOZILLA_GFX_WEBRENDERIMAGEHOST_H +#include + #include "CompositableHost.h" // for CompositableHost #include "mozilla/layers/ImageComposite.h" // for ImageComposite #include "mozilla/WeakPtr.h" @@ -14,6 +16,7 @@ namespace mozilla { namespace layers { +class AsyncImagePipelineManager; class WebRenderBridgeParent; /** @@ -65,11 +68,14 @@ class WebRenderImageHost : public CompositableHost, public ImageComposite { WebRenderImageHost* AsWebRenderImageHost() override { return this; } - TextureHost* GetAsTextureHostForComposite(); + TextureHost* GetAsTextureHostForComposite( + AsyncImagePipelineManager* aAsyncImageManager); - void SetWrBridge(WebRenderBridgeParent* aWrBridge); + void SetWrBridge(const wr::PipelineId& aPipelineId, + WebRenderBridgeParent* aWrBridge); - void ClearWrBridge(WebRenderBridgeParent* aWrBridge); + void ClearWrBridge(const wr::PipelineId& aPipelineId, + WebRenderBridgeParent* aWrBridge); TextureHost* GetCurrentTextureHost() { return mCurrentTextureHost; } @@ -79,9 +85,9 @@ class WebRenderImageHost : public CompositableHost, public ImageComposite { void SetCurrentTextureHost(TextureHost* aTexture); - WeakPtr mWrBridge; + std::unordered_map> mWrBridges; - uint32_t mWrBridgeBindings; + AsyncImagePipelineManager* mCurrentAsyncImageManager; CompositableTextureHostRef mCurrentTextureHost; };