diff --git a/gfx/layers/RemoteTextureMap.cpp b/gfx/layers/RemoteTextureMap.cpp index 95db67665153..507eafc4c2e2 100644 --- a/gfx/layers/RemoteTextureMap.cpp +++ b/gfx/layers/RemoteTextureMap.cpp @@ -574,6 +574,13 @@ void RemoteTextureMap::RegisterTextureOwner( owner->mRecycleBin = new RemoteTextureRecycleBin(false); } + auto itWaiting = mWaitingTextureOwners.find(key); + if (itWaiting != mWaitingTextureOwners.end()) { + owner->mRenderingReadyCallbackHolders.swap( + itWaiting->second->mRenderingReadyCallbackHolders); + mWaitingTextureOwners.erase(itWaiting); + } + mTextureOwners.emplace(key, std::move(owner)); } @@ -1002,14 +1009,13 @@ bool RemoteTextureMap::WaitForRemoteTextureOwner( return true; } -bool RemoteTextureMap::GetRemoteTexture( - RemoteTextureHostWrapper* aTextureHostWrapper, - std::function&& aReadyCallback) { +void RemoteTextureMap::GetRemoteTexture( + RemoteTextureHostWrapper* aTextureHostWrapper) { MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread()); MOZ_ASSERT(aTextureHostWrapper); if (aTextureHostWrapper->IsReadyForRendering()) { - return false; + return; } const auto& textureId = aTextureHostWrapper->mTextureId; @@ -1023,7 +1029,7 @@ bool RemoteTextureMap::GetRemoteTexture( auto* owner = GetTextureOwner(lock, ownerId, forPid); if (!owner) { - return false; + return; } UpdateTexture(lock, owner, textureId); @@ -1031,7 +1037,7 @@ bool RemoteTextureMap::GetRemoteTexture( if (owner->mLatestTextureHost && (owner->mLatestTextureHost->GetFlags() & TextureFlags::DUMMY_TEXTURE)) { // Remote texture allocation was failed. - return false; + return; } if (textureId == owner->mLatestUsingTextureId) { @@ -1043,14 +1049,6 @@ bool RemoteTextureMap::GetRemoteTexture( << " expected: " << size; } textureHost = owner->mLatestTextureHost; - } else { - if (aReadyCallback) { - auto callbackHolder = MakeUnique( - textureId, std::move(aReadyCallback)); - owner->mRenderingReadyCallbackHolders.push_back( - std::move(callbackHolder)); - return true; - } } // Update mRemoteTextureHost @@ -1070,8 +1068,6 @@ bool RemoteTextureMap::GetRemoteTexture( aTextureHostWrapper->ApplyTextureFlagsToRemoteTexture(); } } - - return false; } void RemoteTextureMap::NotifyTxn(const MonitorAutoLock& aProofOfLock, @@ -1201,6 +1197,28 @@ bool RemoteTextureMap::CheckRemoteTextureReady( MonitorAutoLock lock(mMonitor); auto* owner = GetTextureOwner(lock, aInfo.mOwnerId, aInfo.mForPid); + if (aInfo.mWaitForRemoteTextureOwner && !owner) { + // Remote texture owner is not registered yet. Waiting for remote texture + // owner + + const auto key = std::pair(aInfo.mForPid, aInfo.mOwnerId); + if (!mWaitingTextureOwners[key]) { + auto waitingOwner = MakeUnique(); + mWaitingTextureOwners[key] = std::move(waitingOwner); + } + + MOZ_ASSERT(mWaitingTextureOwners[key]); + + WaitingTextureOwner* waitingOwner = mWaitingTextureOwners[key].get(); + + auto callbackHolder = MakeUnique( + aInfo.mTextureId, std::move(aCallback)); + waitingOwner->mRenderingReadyCallbackHolders.push_back( + std::move(callbackHolder)); + + return false; + } + if (!owner || owner->mIsContextLost) { // Owner is already removed or context lost. No need to wait texture ready. return true; @@ -1232,6 +1250,24 @@ bool RemoteTextureMap::WaitRemoteTextureReady(const RemoteTextureInfo& aInfo) { MonitorAutoLock lock(mMonitor); auto* owner = GetTextureOwner(lock, aInfo.mOwnerId, aInfo.mForPid); + if (aInfo.mWaitForRemoteTextureOwner && + (!owner || (!owner->mLatestTextureHost && + owner->mWaitingTextureDataHolders.empty()))) { + const TimeDuration timeout = TimeDuration::FromMilliseconds(10000); + while (!owner || (!owner->mLatestTextureHost && + owner->mWaitingTextureDataHolders.empty())) { + if (owner && (owner->mIsContextLost || owner->mDeferUnregister)) { + // If the context was lost, no further updates are expected. + return false; + } + CVStatus status = mMonitor.Wait(timeout); + if (status == CVStatus::Timeout) { + return false; + } + owner = GetTextureOwner(lock, aInfo.mOwnerId, aInfo.mForPid); + } + } + if (!owner || owner->mIsContextLost) { // Owner is already removed or context lost. return false; @@ -1275,11 +1311,18 @@ bool RemoteTextureMap::WaitRemoteTextureReady(const RemoteTextureInfo& aInfo) { } void RemoteTextureMap::SuppressRemoteTextureReadyCheck( - const RemoteTextureId aTextureId, const base::ProcessId aForPid) { + const RemoteTextureInfo& aInfo) { MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread()); MonitorAutoLock lock(mMonitor); - const auto key = std::pair(aForPid, aTextureId); + // Clear if WaitingTextureOwner exists. + auto itWaiting = + mWaitingTextureOwners.find(std::pair(aInfo.mForPid, aInfo.mOwnerId)); + if (itWaiting != mWaitingTextureOwners.end()) { + mWaitingTextureOwners.erase(itWaiting); + } + + const auto key = std::pair(aInfo.mForPid, aInfo.mTextureId); auto it = mRemoteTextureHostWrapperHolders.find(key); if (it == mRemoteTextureHostWrapperHolders.end()) { MOZ_ASSERT_UNREACHABLE("unexpected to be called"); diff --git a/gfx/layers/RemoteTextureMap.h b/gfx/layers/RemoteTextureMap.h index 8aee1c6f7d08..cf41c15da50e 100644 --- a/gfx/layers/RemoteTextureMap.h +++ b/gfx/layers/RemoteTextureMap.h @@ -55,11 +55,24 @@ struct RemoteTextureInfo { RemoteTextureInfo(const RemoteTextureId aTextureId, const RemoteTextureOwnerId aOwnerId, const base::ProcessId aForPid) - : mTextureId(aTextureId), mOwnerId(aOwnerId), mForPid(aForPid) {} + : mTextureId(aTextureId), + mOwnerId(aOwnerId), + mForPid(aForPid), + mWaitForRemoteTextureOwner(false) {} + + RemoteTextureInfo(const RemoteTextureId aTextureId, + const RemoteTextureOwnerId aOwnerId, + const base::ProcessId aForPid, + const bool aWaitForRemoteTextureOwner) + : mTextureId(aTextureId), + mOwnerId(aOwnerId), + mForPid(aForPid), + mWaitForRemoteTextureOwner(aWaitForRemoteTextureOwner) {} const RemoteTextureId mTextureId; const RemoteTextureOwnerId mOwnerId; const base::ProcessId mForPid; + const bool mWaitForRemoteTextureOwner; }; struct RemoteTextureInfoList { @@ -307,11 +320,7 @@ class RemoteTextureMap { bool WaitForRemoteTextureOwner(RemoteTextureHostWrapper* aTextureHostWrapper); // Get remote texture's TextureHost for RemoteTextureHostWrapper. - // - // return true when aReadyCallback will be called. - bool GetRemoteTexture( - RemoteTextureHostWrapper* aTextureHostWrapper, - std::function&& aReadyCallback); + void GetRemoteTexture(RemoteTextureHostWrapper* aTextureHostWrapper); bool WaitForTxn(const RemoteTextureOwnerId aOwnerId, const base::ProcessId aForPid, RemoteTextureTxnType aTxnType, @@ -334,8 +343,7 @@ class RemoteTextureMap { bool WaitRemoteTextureReady(const RemoteTextureInfo& aInfo); - void SuppressRemoteTextureReadyCheck(const RemoteTextureId aTextureId, - const base::ProcessId aForPid); + void SuppressRemoteTextureReadyCheck(const RemoteTextureInfo& aInfo); UniquePtr GetRecycledTextureData( const RemoteTextureOwnerId aOwnerId, const base::ProcessId aForPid, @@ -387,6 +395,11 @@ class RemoteTextureMap { std::function mCallback; }; + struct WaitingTextureOwner { + std::deque> + mRenderingReadyCallbackHolders; + }; + struct TextureOwner { bool mIsContextLost = false; // Whether to wait for a transaction to complete before unregistering. @@ -467,6 +480,10 @@ class RemoteTextureMap { Monitor mMonitor MOZ_UNANNOTATED; + std::map, + UniquePtr> + mWaitingTextureOwners; + std::map, UniquePtr> mTextureOwners; diff --git a/gfx/layers/composite/RemoteTextureHostWrapper.h b/gfx/layers/composite/RemoteTextureHostWrapper.h index 5131ee4ae3f8..d20bc406c0fe 100644 --- a/gfx/layers/composite/RemoteTextureHostWrapper.h +++ b/gfx/layers/composite/RemoteTextureHostWrapper.h @@ -7,6 +7,7 @@ #ifndef MOZILLA_GFX_RemoteTextureHostWrapper_H #define MOZILLA_GFX_RemoteTextureHostWrapper_H +#include "mozilla/layers/RemoteTextureMap.h" #include "mozilla/layers/TextureHost.h" #include "mozilla/Monitor.h" @@ -80,6 +81,15 @@ class RemoteTextureHostWrapper : public TextureHost { void ApplyTextureFlagsToRemoteTexture(); + void EnableWaitForRemoteTextureOwner(bool aEnable) { + mWaitForRemoteTextureOwner = true; + } + + RemoteTextureInfo GetRemoteTextureInfo() const { + return RemoteTextureInfo(mTextureId, mOwnerId, mForPid, + mWaitForRemoteTextureOwner); + } + const RemoteTextureId mTextureId; const RemoteTextureOwnerId mOwnerId; const base::ProcessId mForPid; @@ -108,6 +118,8 @@ class RemoteTextureHostWrapper : public TextureHost { bool mRenderTextureCreated = false; + bool mWaitForRemoteTextureOwner = false; + friend class RemoteTextureMap; }; diff --git a/gfx/layers/wr/AsyncImagePipelineManager.cpp b/gfx/layers/wr/AsyncImagePipelineManager.cpp index 8a49ffef69ad..30badb0333fe 100644 --- a/gfx/layers/wr/AsyncImagePipelineManager.cpp +++ b/gfx/layers/wr/AsyncImagePipelineManager.cpp @@ -228,8 +228,7 @@ Maybe AsyncImagePipelineManager::UpdateImageKeys( auto* wrapper = aTexture ? aTexture->AsRemoteTextureHostWrapper() : nullptr; if (wrapper && !aPipeline->mImageHost->GetAsyncRef()) { - std::function function; - RemoteTextureMap::Get()->GetRemoteTexture(wrapper, std::move(function)); + RemoteTextureMap::Get()->GetRemoteTexture(wrapper); } if (!aTexture || aTexture->NumSubTextures() == 0) { @@ -523,8 +522,7 @@ void AsyncImagePipelineManager::ApplyAsyncImageForPipeline( // Store pending remote texture that is used for waiting at WebRenderAPI. if (aPendingRemoteTextures && texture && texture != pipeline->mCurrentTexture && wrapper) { - aPendingRemoteTextures->mList.emplace(wrapper->mTextureId, - wrapper->mOwnerId, wrapper->mForPid); + aPendingRemoteTextures->mList.emplace(wrapper->GetRemoteTextureInfo()); } if (aPendingOps && !pipeline->mImageHost->GetAsyncRef()) { diff --git a/gfx/layers/wr/WebRenderBridgeParent.cpp b/gfx/layers/wr/WebRenderBridgeParent.cpp index 68e0c7af8cc9..7f2820ea554d 100644 --- a/gfx/layers/wr/WebRenderBridgeParent.cpp +++ b/gfx/layers/wr/WebRenderBridgeParent.cpp @@ -1120,7 +1120,8 @@ bool WebRenderBridgeParent::SetDisplayList( bool WebRenderBridgeParent::ProcessDisplayListData( DisplayListData& aDisplayList, wr::Epoch aWrEpoch, const TimeStamp& aTxnStartTime, bool aValidTransaction) { - wr::TransactionBuilder txn(mApi); + wr::TransactionBuilder txn(mApi, /* aUseSceneBuilderThread */ true, + mRemoteTextureTxnScheduler, mFwdTransactionId); Maybe sender; if (aDisplayList.mScrollData && !aDisplayList.mScrollData->Validate()) { @@ -1239,10 +1240,6 @@ mozilla::ipc::IPCResult WebRenderBridgeParent::RecvSetDisplayList( wr::IpcResourceUpdateQueue::ReleaseShmems(this, aDisplayList.mSmallShmems); wr::IpcResourceUpdateQueue::ReleaseShmems(this, aDisplayList.mLargeShmems); - if (mRemoteTextureTxnScheduler) { - mRemoteTextureTxnScheduler->NotifyTxn(aFwdTransactionId); - } - if (!success) { return IPC_FAIL(this, "Failed to process DisplayListData."); } @@ -1253,7 +1250,8 @@ mozilla::ipc::IPCResult WebRenderBridgeParent::RecvSetDisplayList( bool WebRenderBridgeParent::ProcessEmptyTransactionUpdates( TransactionData& aData, bool* aScheduleComposite) { *aScheduleComposite = false; - wr::TransactionBuilder txn(mApi); + wr::TransactionBuilder txn(mApi, /* aUseSceneBuilderThread */ true, + mRemoteTextureTxnScheduler, mFwdTransactionId); txn.SetLowPriority(!IsRootWebRenderBridgeParent()); if (!aData.mScrollUpdates.IsEmpty()) { @@ -1395,10 +1393,6 @@ mozilla::ipc::IPCResult WebRenderBridgeParent::RecvEmptyTransaction( aTransactionData->mLargeShmems); } - if (mRemoteTextureTxnScheduler) { - mRemoteTextureTxnScheduler->NotifyTxn(aFwdTransactionId); - } - if (!success) { return IPC_FAIL(this, "Failed to process empty transaction update."); } diff --git a/gfx/layers/wr/WebRenderImageHost.cpp b/gfx/layers/wr/WebRenderImageHost.cpp index 3febc5872baa..97457ebc4c7f 100644 --- a/gfx/layers/wr/WebRenderImageHost.cpp +++ b/gfx/layers/wr/WebRenderImageHost.cpp @@ -199,15 +199,17 @@ void WebRenderImageHost::UseRemoteTexture() { while (!mPendingRemoteTextureWrappers.empty()) { auto* wrapper = mPendingRemoteTextureWrappers.front()->AsRemoteTextureHostWrapper(); + if (mWaitForRemoteTextureOwner) { + // XXX remove sync wait RemoteTextureMap::Get()->WaitForRemoteTextureOwner(wrapper); } - mWaitingReadyCallback = - RemoteTextureMap::Get()->GetRemoteTexture(wrapper, readyCallback); - MOZ_ASSERT_IF(mWaitingReadyCallback, !wrapper->IsReadyForRendering()); - if (!wrapper->IsReadyForRendering()) { + mWaitingReadyCallback = !RemoteTextureMap::Get()->CheckRemoteTextureReady( + wrapper->GetRemoteTextureInfo(), readyCallback); + if (mWaitingReadyCallback) { break; } + RemoteTextureMap::Get()->GetRemoteTexture(wrapper); texture = mPendingRemoteTextureWrappers.front(); mPendingRemoteTextureWrappers.pop_front(); } @@ -218,7 +220,7 @@ void WebRenderImageHost::UseRemoteTexture() { MOZ_ASSERT(mPendingRemoteTextureWrappers.empty()); if (mWaitForRemoteTextureOwner) { - RemoteTextureMap::Get()->WaitForRemoteTextureOwner(wrapper); + wrapper->EnableWaitForRemoteTextureOwner(true); } mWaitForRemoteTextureOwner = false; } diff --git a/gfx/webrender_bindings/WebRenderAPI.cpp b/gfx/webrender_bindings/WebRenderAPI.cpp index 105c2dff986f..8521680e961d 100644 --- a/gfx/webrender_bindings/WebRenderAPI.cpp +++ b/gfx/webrender_bindings/WebRenderAPI.cpp @@ -213,18 +213,26 @@ class RemoveRenderer : public RendererEvent { layers::SynchronousTask* mTask; }; -TransactionBuilder::TransactionBuilder(WebRenderAPI* aApi, - bool aUseSceneBuilderThread) - : mUseSceneBuilderThread(aUseSceneBuilderThread), +TransactionBuilder::TransactionBuilder( + WebRenderAPI* aApi, bool aUseSceneBuilderThread, + layers::RemoteTextureTxnScheduler* aRemoteTextureTxnScheduler, + layers::RemoteTextureTxnId aRemoteTextureTxnId) + : mRemoteTextureTxnScheduler(aRemoteTextureTxnScheduler), + mRemoteTextureTxnId(aRemoteTextureTxnId), + mUseSceneBuilderThread(aUseSceneBuilderThread), mApiBackend(aApi->GetBackendType()), mOwnsData(true) { mTxn = wr_transaction_new(mUseSceneBuilderThread); } -TransactionBuilder::TransactionBuilder(WebRenderAPI* aApi, Transaction* aTxn, - bool aUseSceneBuilderThread, - bool aOwnsData) - : mTxn(aTxn), +TransactionBuilder::TransactionBuilder( + WebRenderAPI* aApi, Transaction* aTxn, bool aUseSceneBuilderThread, + bool aOwnsData, + layers::RemoteTextureTxnScheduler* aRemoteTextureTxnScheduler, + layers::RemoteTextureTxnId aRemoteTextureTxnId) + : mRemoteTextureTxnScheduler(aRemoteTextureTxnScheduler), + mRemoteTextureTxnId(aRemoteTextureTxnId), + mTxn(aTxn), mUseSceneBuilderThread(aUseSceneBuilderThread), mApiBackend(aApi->GetBackendType()), mOwnsData(aOwnsData) {} @@ -473,17 +481,19 @@ void WebRenderAPI::SendTransaction(TransactionBuilder& aTxn) { !mPendingAsyncImagePipelineOps->mList.empty()) { mPendingWrTransactionEvents.emplace( WrTransactionEvent::PendingAsyncImagePipelineOps( - std::move(mPendingAsyncImagePipelineOps), this, aTxn.Raw(), - aTxn.UseSceneBuilderThread())); + std::move(mPendingAsyncImagePipelineOps), this, aTxn)); } if (!mPendingWrTransactionEvents.empty()) { - mPendingWrTransactionEvents.emplace(WrTransactionEvent::Transaction( - this, aTxn.Take(), aTxn.UseSceneBuilderThread())); + mPendingWrTransactionEvents.emplace( + WrTransactionEvent::Transaction(this, aTxn)); HandleWrTransactionEvents(RemoteTextureWaitType::AsyncWait); } else { wr_api_send_transaction(mDocHandle, aTxn.Raw(), aTxn.UseSceneBuilderThread()); + if (aTxn.mRemoteTextureTxnScheduler) { + aTxn.mRemoteTextureTxnScheduler->NotifyTxn(aTxn.mRemoteTextureTxnId); + } } } @@ -598,6 +608,10 @@ void WebRenderAPI::HandleWrTransactionEvents(RemoteTextureWaitType aType) { case WrTransactionEvent::Tag::Transaction: wr_api_send_transaction(mDocHandle, front.RawTransaction(), front.UseSceneBuilderThread()); + if (front.GetTransactionBuilder()->mRemoteTextureTxnScheduler) { + front.GetTransactionBuilder()->mRemoteTextureTxnScheduler->NotifyTxn( + front.GetTransactionBuilder()->mRemoteTextureTxnId); + } break; case WrTransactionEvent::Tag::PendingRemoteTextures: { bool isReady = true; @@ -612,7 +626,7 @@ void WebRenderAPI::HandleWrTransactionEvents(RemoteTextureWaitType aType) { while (!list->mList.empty()) { auto& front = list->mList.front(); layers::RemoteTextureMap::Get()->SuppressRemoteTextureReadyCheck( - front.mTextureId, front.mForPid); + front); list->mList.pop(); } } diff --git a/gfx/webrender_bindings/WebRenderAPI.h b/gfx/webrender_bindings/WebRenderAPI.h index eff7b3039afc..495951ea4305 100644 --- a/gfx/webrender_bindings/WebRenderAPI.h +++ b/gfx/webrender_bindings/WebRenderAPI.h @@ -103,11 +103,16 @@ struct WrHitResult { class TransactionBuilder final { public: - explicit TransactionBuilder(WebRenderAPI* aApi, - bool aUseSceneBuilderThread = true); + explicit TransactionBuilder( + WebRenderAPI* aApi, bool aUseSceneBuilderThread = true, + layers::RemoteTextureTxnScheduler* aRemoteTextureTxnScheduler = nullptr, + layers::RemoteTextureTxnId aRemoteTextureTxnId = 0); - TransactionBuilder(WebRenderAPI* aApi, Transaction* aTxn, - bool aUseSceneBuilderThread, bool aOwnsData); + TransactionBuilder( + WebRenderAPI* aApi, Transaction* aTxn, bool aUseSceneBuilderThread, + bool aOwnsData, + layers::RemoteTextureTxnScheduler* aRemoteTextureTxnScheduler, + layers::RemoteTextureTxnId aRemoteTextureTxnId); ~TransactionBuilder(); @@ -207,7 +212,10 @@ class TransactionBuilder final { bool UseSceneBuilderThread() const { return mUseSceneBuilderThread; } layers::WebRenderBackend GetBackendType() { return mApiBackend; } - Transaction* Raw() { return mTxn; } + Transaction* Raw() const { return mTxn; } + + const RefPtr mRemoteTextureTxnScheduler; + const layers::RemoteTextureTxnId mRemoteTextureTxnId; protected: Transaction* mTxn; @@ -391,10 +399,10 @@ class WebRenderAPI final { public: static WrTransactionEvent Transaction(WebRenderAPI* aApi, - wr::Transaction* aTxn, - bool aUseSceneBuilderThread) { + TransactionBuilder& aTxn) { auto transaction = MakeUnique( - aApi, aTxn, aUseSceneBuilderThread, /* aOwnsData */ true); + aApi, aTxn.Take(), aTxn.UseSceneBuilderThread(), /* aOwnsData */ true, + aTxn.mRemoteTextureTxnScheduler, aTxn.mRemoteTextureTxnId); return WrTransactionEvent(Tag::Transaction, std::move(transaction)); } @@ -407,10 +415,10 @@ class WebRenderAPI final { static WrTransactionEvent PendingAsyncImagePipelineOps( UniquePtr&& aPendingAsyncImagePipelineOps, - WebRenderAPI* aApi, wr::Transaction* aTxn, - bool aUseSceneBuilderThread) { + WebRenderAPI* aApi, const TransactionBuilder& aTxn) { auto transaction = MakeUnique( - aApi, aTxn, aUseSceneBuilderThread, /* aOwnsData */ false); + aApi, aTxn.Raw(), aTxn.UseSceneBuilderThread(), /* aOwnsData */ false, + aTxn.mRemoteTextureTxnScheduler, aTxn.mRemoteTextureTxnId); return WrTransactionEvent(Tag::PendingAsyncImagePipelineOps, std::move(aPendingAsyncImagePipelineOps), std::move(transaction)); @@ -425,7 +433,8 @@ class WebRenderAPI final { } TransactionBuilder* GetTransactionBuilder() { - if (mTag == Tag::PendingAsyncImagePipelineOps) { + if (mTag == Tag::Transaction || + mTag == Tag::PendingAsyncImagePipelineOps) { return mTransaction.get(); } MOZ_CRASH("Should not be called");