From 6accc1036c746ff88b5241d8045d670b27277bb9 Mon Sep 17 00:00:00 2001 From: Lee Salzman Date: Tue, 9 Jan 2024 11:53:14 +0000 Subject: [PATCH] Bug 1873075 - Delay UnregisterTextureOwner until all potential UseRemoteTextures are received. r=aosmond UnregisterTextureOwner, if called before any use of UseRemoteTexture, can cause UseRemoteTexture to wait for the texture owner to be created, since the texture owner does not exist, and there is no evidence it was previously unregistered. This patch attempts to address the issue by delaying the actual UnregisterTextureOwner until all such UseRemoteTexture instances are processed. This is accomplished by noting that UseRemoteTexture ops come in via transactions from a CompositableForwarder and so all are associated with a forwarder transaction with a FwdTransactionId. RecordedTextureData on destruction reports the last FwdTransactionId associated with its final UseRemoteTexture before it attempts to call UnregisterTextureOwner. If RemoteTextureMap has not been notified of a given FwdTransactionId yet, then the UnregisterTextureOwner call will be deferred until it has seen this FwdTransactionId. This adds a RemoteTextureTxnScheduler to track the issuing of dependencies and waiting for FwdTransactionIds. This patch also cleans up the issuing of FwdTransactionIds themselves to be associated with a given top-level protocol so that all sub-protocols have transaction numbers that can be safely compared amongst each other. This makes dependency expiration more robust since any advancement of the transaction number from any source can help retire expired dependencies. Differential Revision: https://phabricator.services.mozilla.com/D197895 --- gfx/layers/LayersTypes.h | 3 + gfx/layers/PersistentBufferProvider.cpp | 5 + gfx/layers/PersistentBufferProvider.h | 5 + gfx/layers/RecordedCanvasEventImpl.h | 16 +- gfx/layers/RemoteTextureMap.cpp | 301 ++++++++++++++------- gfx/layers/RemoteTextureMap.h | 102 ++++++- gfx/layers/ShareableCanvasRenderer.cpp | 4 +- gfx/layers/client/TextureClient.h | 2 + gfx/layers/client/TextureRecorded.cpp | 10 +- gfx/layers/client/TextureRecorded.h | 8 +- gfx/layers/ipc/CanvasTranslator.cpp | 20 +- gfx/layers/ipc/CanvasTranslator.h | 3 +- gfx/layers/ipc/CompositableForwarder.h | 46 +++- gfx/layers/ipc/CompositorBridgeChild.cpp | 8 +- gfx/layers/ipc/CompositorBridgeChild.h | 11 +- gfx/layers/ipc/CompositorManagerChild.cpp | 6 +- gfx/layers/ipc/CompositorManagerChild.h | 12 +- gfx/layers/ipc/CompositorManagerParent.cpp | 7 + gfx/layers/ipc/CompositorManagerParent.h | 2 + gfx/layers/ipc/ImageBridgeChild.cpp | 2 +- gfx/layers/ipc/ImageBridgeChild.h | 7 +- gfx/layers/ipc/ImageBridgeParent.cpp | 17 +- gfx/layers/ipc/ImageBridgeParent.h | 3 + gfx/layers/wr/WebRenderBridgeChild.cpp | 8 +- gfx/layers/wr/WebRenderBridgeChild.h | 4 +- gfx/layers/wr/WebRenderBridgeParent.cpp | 14 + gfx/layers/wr/WebRenderBridgeParent.h | 3 + 27 files changed, 472 insertions(+), 157 deletions(-) diff --git a/gfx/layers/LayersTypes.h b/gfx/layers/LayersTypes.h index a716ff9996c1..a59fad0b9728 100644 --- a/gfx/layers/LayersTypes.h +++ b/gfx/layers/LayersTypes.h @@ -390,6 +390,9 @@ struct RemoteTextureOwnerId { }; }; +typedef uint32_t RemoteTextureTxnType; +typedef uint64_t RemoteTextureTxnId; + // TextureId allocated in GPU process struct GpuProcessTextureId { uint64_t mId = 0; diff --git a/gfx/layers/PersistentBufferProvider.cpp b/gfx/layers/PersistentBufferProvider.cpp index 20405c2c6f05..ee8679ac8eec 100644 --- a/gfx/layers/PersistentBufferProvider.cpp +++ b/gfx/layers/PersistentBufferProvider.cpp @@ -255,6 +255,11 @@ bool PersistentBufferProviderAccelerated::RequiresRefresh() const { return mTexture->GetInternalData()->RequiresRefresh(); } +void PersistentBufferProviderAccelerated::UseCompositableForwarder( + CompositableForwarder* aForwarder) { + mTexture->GetInternalData()->UseCompositableForwarder(aForwarder); +} + // static already_AddRefed PersistentBufferProviderShared::Create(gfx::IntSize aSize, diff --git a/gfx/layers/PersistentBufferProvider.h b/gfx/layers/PersistentBufferProvider.h index 1e1c347dac05..e8683b0f83b3 100644 --- a/gfx/layers/PersistentBufferProvider.h +++ b/gfx/layers/PersistentBufferProvider.h @@ -28,6 +28,7 @@ class DrawTarget; namespace layers { +class CompositableForwarder; class KnowsCompositor; struct RemoteTextureOwnerId; class TextureClient; @@ -106,6 +107,8 @@ class PersistentBufferProvider : public RefCounted, virtual bool RequiresRefresh() const { return false; } virtual Maybe GetFrontBuffer() { return Nothing(); } + + virtual void UseCompositableForwarder(CompositableForwarder* aForwarder) {} }; class PersistentBufferProviderBasic : public PersistentBufferProvider { @@ -171,6 +174,8 @@ class PersistentBufferProviderAccelerated : public PersistentBufferProvider { bool RequiresRefresh() const override; + void UseCompositableForwarder(CompositableForwarder* aForwarder) override; + protected: explicit PersistentBufferProviderAccelerated( const RefPtr& aTexture); diff --git a/gfx/layers/RecordedCanvasEventImpl.h b/gfx/layers/RecordedCanvasEventImpl.h index 725055cbf5fe..6a80b1c6016d 100644 --- a/gfx/layers/RecordedCanvasEventImpl.h +++ b/gfx/layers/RecordedCanvasEventImpl.h @@ -531,8 +531,12 @@ RecordedNextTextureId::RecordedNextTextureId(S& aStream) class RecordedTextureDestruction final : public RecordedEventDerived { public: - explicit RecordedTextureDestruction(int64_t aTextureId) - : RecordedEventDerived(TEXTURE_DESTRUCTION), mTextureId(aTextureId) {} + RecordedTextureDestruction(int64_t aTextureId, RemoteTextureTxnType aTxnType, + RemoteTextureTxnId aTxnId) + : RecordedEventDerived(TEXTURE_DESTRUCTION), + mTextureId(aTextureId), + mTxnType(aTxnType), + mTxnId(aTxnId) {} template MOZ_IMPLICIT RecordedTextureDestruction(S& aStream); @@ -546,23 +550,29 @@ class RecordedTextureDestruction final private: int64_t mTextureId = 0; + RemoteTextureTxnType mTxnType = 0; + RemoteTextureTxnId mTxnId = 0; }; inline bool RecordedTextureDestruction::PlayCanvasEvent( CanvasTranslator* aTranslator) const { - aTranslator->RemoveTexture(mTextureId); + aTranslator->RemoveTexture(mTextureId, mTxnType, mTxnId); return true; } template void RecordedTextureDestruction::Record(S& aStream) const { WriteElement(aStream, mTextureId); + WriteElement(aStream, mTxnType); + WriteElement(aStream, mTxnId); } template RecordedTextureDestruction::RecordedTextureDestruction(S& aStream) : RecordedEventDerived(TEXTURE_DESTRUCTION) { ReadElement(aStream, mTextureId); + ReadElement(aStream, mTxnType); + ReadElement(aStream, mTxnId); } class RecordedCheckpoint final diff --git a/gfx/layers/RemoteTextureMap.cpp b/gfx/layers/RemoteTextureMap.cpp index dd48de5ed64c..d6c1d6ff53f5 100644 --- a/gfx/layers/RemoteTextureMap.cpp +++ b/gfx/layers/RemoteTextureMap.cpp @@ -6,6 +6,7 @@ #include "mozilla/layers/RemoteTextureMap.h" +#include #include #include "CompositableHost.h" @@ -352,8 +353,8 @@ void RemoteTextureMap::PushTexture( owner->mWaitingTextureDataHolders.push_back(std::move(textureData)); { - renderingReadyCallbacks = - GetRenderingReadyCallbacks(lock, owner, aTextureId); + GetRenderingReadyCallbacks(lock, owner, aTextureId, + renderingReadyCallbacks); // Update mRemoteTextureHost. // This happens when PushTexture() with RemoteTextureId is called after // GetRemoteTexture() with the RemoteTextureId. @@ -574,6 +575,66 @@ void RemoteTextureMap::KeepTextureDataAliveForTextureHostIfNecessary( } } +UniquePtr +RemoteTextureMap::UnregisterTextureOwner( + const MonitorAutoLock& aProofOfLock, const RemoteTextureOwnerId aOwnerId, + const base::ProcessId aForPid, + std::vector>& aReleasingTextures, + std::vector>& + aRenderingReadyCallbacks) { + const auto key = std::pair(aForPid, aOwnerId); + auto it = mTextureOwners.find(key); + if (it == mTextureOwners.end()) { + MOZ_ASSERT_UNREACHABLE("unexpected to be called"); + return nullptr; + } + + auto* owner = it->second.get(); + // If waiting for a last use, and it hasn't arrived yet, then defer + // unregistering. + if (owner->mWaitForTxn) { + owner->mDeferUnregister = GetCurrentSerialEventTarget(); + return nullptr; + } + + if (owner->mLatestTextureHost) { + // Release CompositableRef in mMonitor + aReleasingTextures.emplace_back(owner->mLatestTextureHost); + owner->mLatestTextureHost = nullptr; + } + + // mReleasingRenderedTextureHosts and mLatestRenderedTextureHost could + // simply be cleared. Since NumCompositableRefs() > 0 keeps TextureHosts in + // mUsingTextureDataHolders alive. They need to be cleared before + // KeepTextureDataAliveForTextureHostIfNecessary() call. The function uses + // NumCompositableRefs(). + if (!owner->mReleasingRenderedTextureHosts.empty()) { + std::transform(owner->mReleasingRenderedTextureHosts.begin(), + owner->mReleasingRenderedTextureHosts.end(), + std::back_inserter(aReleasingTextures), + [](CompositableTextureHostRef& aRef) { return aRef.get(); }); + owner->mReleasingRenderedTextureHosts.clear(); + } + if (owner->mLatestRenderedTextureHost) { + owner->mLatestRenderedTextureHost = nullptr; + } + + GetAllRenderingReadyCallbacks(aProofOfLock, owner, aRenderingReadyCallbacks); + + KeepTextureDataAliveForTextureHostIfNecessary( + aProofOfLock, owner, owner->mWaitingTextureDataHolders); + + KeepTextureDataAliveForTextureHostIfNecessary( + aProofOfLock, owner, owner->mUsingTextureDataHolders); + + KeepTextureDataAliveForTextureHostIfNecessary( + aProofOfLock, owner, owner->mReleasingTextureDataHolders); + + UniquePtr releasingOwner = std::move(it->second); + mTextureOwners.erase(it); + return releasingOwner; +} + void RemoteTextureMap::UnregisterTextureOwner( const RemoteTextureOwnerId aOwnerId, const base::ProcessId aForPid) { UniquePtr releasingOwner; // Release outside the monitor @@ -584,51 +645,12 @@ void RemoteTextureMap::UnregisterTextureOwner( { MonitorAutoLock lock(mMonitor); - const auto key = std::pair(aForPid, aOwnerId); - auto it = mTextureOwners.find(key); - if (it == mTextureOwners.end()) { - MOZ_ASSERT_UNREACHABLE("unexpected to be called"); + releasingOwner = UnregisterTextureOwner( + lock, aOwnerId, aForPid, releasingTextures, renderingReadyCallbacks); + if (!releasingOwner) { return; } - auto* owner = it->second.get(); - if (owner->mLatestTextureHost) { - // Release CompositableRef in mMonitor - releasingTextures.emplace_back(owner->mLatestTextureHost); - owner->mLatestTextureHost = nullptr; - } - - // mReleasingRenderedTextureHosts and mLatestRenderedTextureHost could - // simply be cleared. Since NumCompositableRefs() > 0 keeps TextureHosts in - // mUsingTextureDataHolders alive. They need to be cleared before - // KeepTextureDataAliveForTextureHostIfNecessary() call. The function uses - // NumCompositableRefs(). - if (!owner->mReleasingRenderedTextureHosts.empty()) { - std::transform( - owner->mReleasingRenderedTextureHosts.begin(), - owner->mReleasingRenderedTextureHosts.end(), - std::back_inserter(releasingTextures), - [](CompositableTextureHostRef& aRef) { return aRef.get(); }); - owner->mReleasingRenderedTextureHosts.clear(); - } - if (owner->mLatestRenderedTextureHost) { - owner->mLatestRenderedTextureHost = nullptr; - } - - renderingReadyCallbacks = GetAllRenderingReadyCallbacks(lock, owner); - - KeepTextureDataAliveForTextureHostIfNecessary( - lock, owner, owner->mWaitingTextureDataHolders); - - KeepTextureDataAliveForTextureHostIfNecessary( - lock, owner, owner->mUsingTextureDataHolders); - - KeepTextureDataAliveForTextureHostIfNecessary( - lock, owner, owner->mReleasingTextureDataHolders); - - releasingOwner = std::move(it->second); - mTextureOwners.erase(it); - mMonitor.Notify(); } @@ -653,50 +675,14 @@ void RemoteTextureMap::UnregisterTextureOwners( MonitorAutoLock lock(mMonitor); for (const auto& id : aOwnerIds) { - const auto key = std::pair(aForPid, id); - auto it = mTextureOwners.find(key); - if (it == mTextureOwners.end()) { - MOZ_ASSERT_UNREACHABLE("unexpected to be called"); - continue; + if (auto releasingOwner = UnregisterTextureOwner( + lock, id, aForPid, releasingTextures, renderingReadyCallbacks)) { + releasingOwners.push_back(std::move(releasingOwner)); } + } - auto* owner = it->second.get(); - if (owner->mLatestTextureHost) { - // Release CompositableRef in mMonitor - releasingTextures.emplace_back(owner->mLatestTextureHost); - owner->mLatestTextureHost = nullptr; - } - - // mReleasingRenderedTextureHosts and mLatestRenderedTextureHost could - // simply be cleared. Since NumCompositableRefs() > 0 keeps TextureHosts - // in mUsingTextureDataHolders alive. They need to be cleared before - // KeepTextureDataAliveForTextureHostIfNecessary() call. The function uses - // NumCompositableRefs(). - if (!owner->mReleasingRenderedTextureHosts.empty()) { - std::transform( - owner->mReleasingRenderedTextureHosts.begin(), - owner->mReleasingRenderedTextureHosts.end(), - std::back_inserter(releasingTextures), - [](CompositableTextureHostRef& aRef) { return aRef.get(); }); - owner->mReleasingRenderedTextureHosts.clear(); - } - if (owner->mLatestRenderedTextureHost) { - owner->mLatestRenderedTextureHost = nullptr; - } - - renderingReadyCallbacks = GetAllRenderingReadyCallbacks(lock, owner); - - KeepTextureDataAliveForTextureHostIfNecessary( - lock, owner, owner->mWaitingTextureDataHolders); - - KeepTextureDataAliveForTextureHostIfNecessary( - lock, owner, owner->mUsingTextureDataHolders); - - KeepTextureDataAliveForTextureHostIfNecessary( - lock, owner, owner->mReleasingTextureDataHolders); - - releasingOwners.push_back(std::move(it->second)); - mTextureOwners.erase(it); + if (releasingOwners.empty()) { + return; } mMonitor.Notify(); @@ -709,6 +695,66 @@ void RemoteTextureMap::UnregisterTextureOwners( } } +already_AddRefed +RemoteTextureMap::RegisterTxnScheduler(base::ProcessId aForPid, + RemoteTextureTxnType aType) { + MonitorAutoLock lock(mMonitor); + + const auto key = std::pair(aForPid, aType); + auto it = mTxnSchedulers.find(key); + if (it != mTxnSchedulers.end()) { + return do_AddRef(it->second); + } + + RefPtr scheduler( + new RemoteTextureTxnScheduler(aForPid, aType)); + mTxnSchedulers.emplace(key, scheduler.get()); + return scheduler.forget(); +} + +void RemoteTextureMap::UnregisterTxnScheduler(base::ProcessId aForPid, + RemoteTextureTxnType aType) { + MonitorAutoLock lock(mMonitor); + + const auto key = std::pair(aForPid, aType); + auto it = mTxnSchedulers.find(key); + if (it == mTxnSchedulers.end()) { + MOZ_ASSERT_UNREACHABLE("Remote texture txn scheduler does not exist."); + return; + } + mTxnSchedulers.erase(it); +} + +RemoteTextureTxnScheduler::~RemoteTextureTxnScheduler() { + NotifyTxn(std::numeric_limits::max()); + RemoteTextureMap::Get()->UnregisterTxnScheduler(mForPid, mType); +} + +void RemoteTextureTxnScheduler::NotifyTxn(RemoteTextureTxnId aTxnId) { + MonitorAutoLock lock(RemoteTextureMap::Get()->mMonitor); + + mLastTxnId = aTxnId; + + for (; !mWaits.empty(); mWaits.pop_front()) { + auto& wait = mWaits.front(); + if (wait.mTxnId > aTxnId) { + break; + } + RemoteTextureMap::Get()->NotifyTxn(lock, wait.mOwnerId, mForPid); + } +} + +bool RemoteTextureTxnScheduler::WaitForTxn(const MonitorAutoLock& aProofOfLock, + RemoteTextureOwnerId aOwnerId, + RemoteTextureTxnId aTxnId) { + if (aTxnId <= mLastTxnId) { + return false; + } + mWaits.insert(std::upper_bound(mWaits.begin(), mWaits.end(), aTxnId), + Wait{aOwnerId, aTxnId}); + return true; +} + void RemoteTextureMap::ClearRecycledTextures( const std::unordered_set& aOwnerIds, @@ -846,37 +892,30 @@ void RemoteTextureMap::UpdateTexture(const MonitorAutoLock& aProofOfLock, } } -std::vector> -RemoteTextureMap::GetRenderingReadyCallbacks( +void RemoteTextureMap::GetRenderingReadyCallbacks( const MonitorAutoLock& aProofOfLock, RemoteTextureMap::TextureOwner* aOwner, - const RemoteTextureId aTextureId) { + const RemoteTextureId aTextureId, + std::vector>& aFunctions) { MOZ_ASSERT(aOwner); - std::vector> functions; - while (!aOwner->mRenderingReadyCallbackHolders.empty()) { auto& front = aOwner->mRenderingReadyCallbackHolders.front(); if (aTextureId < front->mTextureId) { break; } if (front->mCallback) { - functions.push_back(std::move(front->mCallback)); + aFunctions.push_back(std::move(front->mCallback)); } aOwner->mRenderingReadyCallbackHolders.pop_front(); } - - return functions; } -std::vector> -RemoteTextureMap::GetAllRenderingReadyCallbacks( - const MonitorAutoLock& aProofOfLock, - RemoteTextureMap::TextureOwner* aOwner) { - auto functions = - GetRenderingReadyCallbacks(aProofOfLock, aOwner, RemoteTextureId::Max()); +void RemoteTextureMap::GetAllRenderingReadyCallbacks( + const MonitorAutoLock& aProofOfLock, RemoteTextureMap::TextureOwner* aOwner, + std::vector>& aFunctions) { + GetRenderingReadyCallbacks(aProofOfLock, aOwner, RemoteTextureId::Max(), + aFunctions); MOZ_ASSERT(aOwner->mRenderingReadyCallbackHolders.empty()); - - return functions; } bool RemoteTextureMap::GetRemoteTexture( @@ -967,6 +1006,64 @@ bool RemoteTextureMap::GetRemoteTexture( return false; } +void RemoteTextureMap::NotifyTxn(const MonitorAutoLock& aProofOfLock, + const RemoteTextureOwnerId aOwnerId, + const base::ProcessId aForPid) { + if (auto* owner = GetTextureOwner(aProofOfLock, aOwnerId, aForPid)) { + if (!owner->mWaitForTxn) { + MOZ_ASSERT_UNREACHABLE("Expected texture owner to wait for txn."); + return; + } + owner->mWaitForTxn = false; + if (!owner->mDeferUnregister) { + // If unregistering was not deferred, then don't try to force + // unregistering yet. + return; + } + owner->mDeferUnregister->Dispatch(NS_NewRunnableFunction( + "RemoteTextureMap::SetLastRemoteTextureUse::Runnable", + [aOwnerId, aForPid]() { + RemoteTextureMap::Get()->UnregisterTextureOwner(aOwnerId, aForPid); + })); + } +} + +bool RemoteTextureMap::WaitForTxn(const RemoteTextureOwnerId aOwnerId, + const base::ProcessId aForPid, + RemoteTextureTxnType aTxnType, + RemoteTextureTxnId aTxnId) { + MonitorAutoLock lock(mMonitor); + if (auto* owner = GetTextureOwner(lock, aOwnerId, aForPid)) { + if (owner->mDeferUnregister) { + MOZ_ASSERT_UNREACHABLE( + "Texture owner must wait for txn before unregistering."); + return false; + } + if (owner->mWaitForTxn) { + MOZ_ASSERT_UNREACHABLE("Texture owner already waiting for txn."); + return false; + } + const auto key = std::pair(aForPid, aTxnType); + auto it = mTxnSchedulers.find(key); + if (it == mTxnSchedulers.end()) { + // During shutdown, different toplevel protocols may go away in + // disadvantageous orders, causing us to sometimes be processing + // waits even though the source of transactions upon which the + // wait depends shut down. This is generally harmless to ignore, + // as it means no further transactions will be generated of that + // type and all such transactions have been processed before it + // unregistered. + NS_WARNING("Could not find scheduler for txn type."); + return false; + } + if (it->second->WaitForTxn(lock, aOwnerId, aTxnId)) { + owner->mWaitForTxn = true; + } + return true; + } + return false; +} + void RemoteTextureMap::ReleaseRemoteTextureHost( RemoteTextureHostWrapper* aTextureHostWrapper) { MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread()); diff --git a/gfx/layers/RemoteTextureMap.h b/gfx/layers/RemoteTextureMap.h index 02b03f2b191f..9a07f249d437 100644 --- a/gfx/layers/RemoteTextureMap.h +++ b/gfx/layers/RemoteTextureMap.h @@ -134,6 +134,52 @@ class RemoteTextureRecycleBin final { std::list mRecycledTextures; }; +/** + * RemoteTextureTxnScheduler manages dependencies on transaction numbers for a + * given top-level protocol ("type"). It expects that transaction numbers are + * all sequenced and comparable for this top-level protocol. Dependencies may + * then be issued on a given future transaction number. Clients must notify the + * scheduler when transactions are completed, so that any dependencies can be + * cleared as the transaction number advances. Generally, transaction numbers + * will be generated by a FwdTransactionCounter on a top-level protocol child, + * and there should be a RemoteTextureTxnScheduler instantiated on the top-level + * protocol parent that corresponds to the same protocol lifetime as the child. + * To ease sharing in sub-protocols, RemoteTextureTxnScheduler is ref-counted + * and may be multiply-registered by the various sub-protocols that derive from + * a given top-level protocol, without having to directly refer to the original + * top-level protocol. + */ +class RemoteTextureTxnScheduler final { + public: + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(RemoteTextureTxnScheduler) + + void NotifyTxn(RemoteTextureTxnId aTxnId); + + private: + friend class RemoteTextureMap; + + RemoteTextureTxnScheduler(base::ProcessId aForPid, RemoteTextureTxnType aType) + : mForPid(aForPid), mType(aType) {} + ~RemoteTextureTxnScheduler(); + + bool WaitForTxn(const MonitorAutoLock& aProofOfLock, + RemoteTextureOwnerId aOwnerId, RemoteTextureTxnId aTxnId); + + struct Wait { + RemoteTextureOwnerId mOwnerId; + RemoteTextureTxnId mTxnId; + + friend bool operator<(RemoteTextureTxnId aTxnId, const Wait& aWait) { + return aTxnId < aWait.mTxnId; + } + }; + + base::ProcessId mForPid = base::kInvalidProcessId; + RemoteTextureTxnType mType = 0; + RemoteTextureTxnId mLastTxnId = 0; + std::deque mWaits; +}; + /** * A class provides API for remote texture owners. */ @@ -233,7 +279,7 @@ class RemoteTextureMap { void RegisterTextureOwner( const RemoteTextureOwnerId aOwnerId, const base::ProcessId aForPid, const RefPtr& aRecycleBin = nullptr); - void UnregisterTextureOwner(const RemoteTextureOwnerId aOwnerIds, + void UnregisterTextureOwner(const RemoteTextureOwnerId aOwnerId, const base::ProcessId aForPid); void UnregisterTextureOwners( const std::unordered_set&& aReadyCallback, bool aWaitForRemoteTextureOwner = false); + bool WaitForTxn(const RemoteTextureOwnerId aOwnerId, + const base::ProcessId aForPid, RemoteTextureTxnType aTxnType, + RemoteTextureTxnId aTxnId); + void ReleaseRemoteTextureHost(RemoteTextureHostWrapper* aTextureHostWrapper); RefPtr GetOrCreateRemoteTextureHostWrapper( @@ -305,7 +355,19 @@ class RemoteTextureMap { static RefPtr CreateRemoteTexture(TextureData* aTextureData, TextureFlags aTextureFlags); + already_AddRefed RegisterTxnScheduler( + base::ProcessId aForPid, RemoteTextureTxnType aType); + + template + already_AddRefed RegisterTxnScheduler( + P* aProtocol) { + return RegisterTxnScheduler(aProtocol->OtherPid(), + aProtocol->ToplevelProtocol()->GetProtocolId()); + } + protected: + friend class RemoteTextureTxnScheduler; + // Holds data related to remote texture struct TextureDataHolder { TextureDataHolder(const RemoteTextureId aTextureId, @@ -337,6 +399,11 @@ class RemoteTextureMap { struct TextureOwner { bool mIsContextLost = false; + // Whether to wait for a transaction to complete before unregistering. + bool mWaitForTxn = false; + // The thread on which to finally unregister when ready. + RefPtr mDeferUnregister; + // Holds TextureDataHolders that wait to be used for building wr display // list. std::deque> mWaitingTextureDataHolders; @@ -371,14 +438,22 @@ class RemoteTextureMap { RemoteTextureMap::TextureOwner* aOwner, const RemoteTextureId aTextureId); - std::vector> - GetRenderingReadyCallbacks(const MonitorAutoLock& aProofOfLock, - RemoteTextureMap::TextureOwner* aOwner, - const RemoteTextureId aTextureId); + UniquePtr UnregisterTextureOwner( + const MonitorAutoLock& aProofOfLock, const RemoteTextureOwnerId aOwnerId, + const base::ProcessId aForPid, + std::vector>& aReleasingTextures, + std::vector>& + aRenderingReadyCallbacks); - std::vector> - GetAllRenderingReadyCallbacks(const MonitorAutoLock& aProofOfLock, - RemoteTextureMap::TextureOwner* aOwner); + void GetRenderingReadyCallbacks( + const MonitorAutoLock& aProofOfLock, + RemoteTextureMap::TextureOwner* aOwner, const RemoteTextureId aTextureId, + std::vector>& aFunctions); + + void GetAllRenderingReadyCallbacks( + const MonitorAutoLock& aProofOfLock, + RemoteTextureMap::TextureOwner* aOwner, + std::vector>& aFunctions); void KeepTextureDataAliveForTextureHostIfNecessary( const MonitorAutoLock& aProofOfLock, @@ -392,6 +467,13 @@ class RemoteTextureMap { const MonitorAutoLock& aProofOfLock, const RemoteTextureOwnerId aOwnerId, const base::ProcessId aForPid); + void NotifyTxn(const MonitorAutoLock& aProofOfLock, + const RemoteTextureOwnerId aOwnerId, + const base::ProcessId aForPid); + + void UnregisterTxnScheduler(base::ProcessId aForPid, + RemoteTextureTxnType aType); + Monitor mMonitor MOZ_UNANNOTATED; std::map, @@ -406,6 +488,10 @@ class RemoteTextureMap { RefPtr> mRemoteTexturePushListeners; + std::map, + RemoteTextureTxnScheduler*> + mTxnSchedulers; + static StaticAutoPtr sInstance; }; diff --git a/gfx/layers/ShareableCanvasRenderer.cpp b/gfx/layers/ShareableCanvasRenderer.cpp index a8abaa27f9dc..aef3e4a66721 100644 --- a/gfx/layers/ShareableCanvasRenderer.cpp +++ b/gfx/layers/ShareableCanvasRenderer.cpp @@ -196,7 +196,9 @@ void ShareableCanvasRenderer::UpdateCompositableClient() { EnsurePipeline(); forwarder->UseRemoteTexture(mCanvasClient, textureDesc.textureId(), textureDesc.ownerId(), mData.mSize, flags); - + if (provider) { + provider->UseCompositableForwarder(forwarder); + } FireDidTransactionCallback(); return; } diff --git a/gfx/layers/client/TextureClient.h b/gfx/layers/client/TextureClient.h index cec05443be3d..9ddea237c0fe 100644 --- a/gfx/layers/client/TextureClient.h +++ b/gfx/layers/client/TextureClient.h @@ -332,6 +332,8 @@ class TextureData { virtual bool RequiresRefresh() const { return false; } + virtual void UseCompositableForwarder(CompositableForwarder* aForwarder) {} + protected: MOZ_COUNTED_DEFAULT_CTOR(TextureData) }; diff --git a/gfx/layers/client/TextureRecorded.cpp b/gfx/layers/client/TextureRecorded.cpp index cb444e230c82..e686bfd188de 100644 --- a/gfx/layers/client/TextureRecorded.cpp +++ b/gfx/layers/client/TextureRecorded.cpp @@ -5,6 +5,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "TextureRecorded.h" +#include "mozilla/layers/CompositableForwarder.h" #include "RecordedCanvasEventImpl.h" @@ -31,7 +32,8 @@ RecordedTextureData::~RecordedTextureData() { // because the TextureData might need to destroy its DrawTarget within a lock. mDT = nullptr; mCanvasChild->CleanupTexture(mTextureId); - mCanvasChild->RecordEvent(RecordedTextureDestruction(mTextureId)); + mCanvasChild->RecordEvent( + RecordedTextureDestruction(mTextureId, mLastTxnType, mLastTxnId)); } void RecordedTextureData::FillInfo(TextureData::Info& aInfo) const { @@ -165,6 +167,12 @@ bool RecordedTextureData::Serialize(SurfaceDescriptor& aDescriptor) { return true; } +void RecordedTextureData::UseCompositableForwarder( + CompositableForwarder* aForwarder) { + mLastTxnType = (RemoteTextureTxnType)aForwarder->GetFwdTransactionType(); + mLastTxnId = (RemoteTextureTxnId)aForwarder->GetFwdTransactionId(); +} + void RecordedTextureData::OnForwardedToHost() { // Compositing with RecordedTextureData requires RemoteTextureMap. MOZ_CRASH("OnForwardedToHost not supported!"); diff --git a/gfx/layers/client/TextureRecorded.h b/gfx/layers/client/TextureRecorded.h index c0a0db6a4212..353255f18719 100644 --- a/gfx/layers/client/TextureRecorded.h +++ b/gfx/layers/client/TextureRecorded.h @@ -49,6 +49,8 @@ class RecordedTextureData final : public TextureData { bool RequiresRefresh() const final; + void UseCompositableForwarder(CompositableForwarder* aForwarder) final; + private: DISALLOW_COPY_AND_ASSIGN(RecordedTextureData); @@ -62,8 +64,10 @@ class RecordedTextureData final : public TextureData { RefPtr mSnapshot; ThreadSafeWeakPtr mSnapshotWrapper; OpenMode mLockedMode; - layers::RemoteTextureId mLastRemoteTextureId; - layers::RemoteTextureOwnerId mRemoteTextureOwnerId; + RemoteTextureId mLastRemoteTextureId; + RemoteTextureOwnerId mRemoteTextureOwnerId; + RemoteTextureTxnType mLastTxnType = 0; + RemoteTextureTxnId mLastTxnId = 0; bool mUsedRemoteTexture = false; bool mInvalidContents = true; }; diff --git a/gfx/layers/ipc/CanvasTranslator.cpp b/gfx/layers/ipc/CanvasTranslator.cpp index 75816835a642..3cbf3975b744 100644 --- a/gfx/layers/ipc/CanvasTranslator.cpp +++ b/gfx/layers/ipc/CanvasTranslator.cpp @@ -796,19 +796,29 @@ already_AddRefed CanvasTranslator::CreateDrawTarget( return dt.forget(); } -void CanvasTranslator::RemoveTexture(int64_t aTextureId) { +void CanvasTranslator::RemoveTexture(int64_t aTextureId, + RemoteTextureTxnType aTxnType, + RemoteTextureTxnId aTxnId) { // Don't erase the texture if still in use auto result = mTextureInfo.find(aTextureId); - if (result == mTextureInfo.end() || --result->second.mLocked > 0) { + if (result == mTextureInfo.end()) { return; } - if (result->second.mTextureData) { - result->second.mTextureData->Unlock(); + auto& info = result->second; + if (aTxnType && aTxnId) { + RemoteTextureMap::Get()->WaitForTxn(info.mRemoteTextureOwnerId, mOtherPid, + aTxnType, aTxnId); + } + if (--info.mLocked > 0) { + return; + } + if (info.mTextureData) { + info.mTextureData->Unlock(); } if (mRemoteTextureOwner) { // If this texture id was manually registered as a remote texture owner, // unregister it so it does not stick around after the texture id goes away. - RemoteTextureOwnerId owner = result->second.mRemoteTextureOwnerId; + RemoteTextureOwnerId owner = info.mRemoteTextureOwnerId; if (owner.IsValid()) { mRemoteTextureOwner->UnregisterTextureOwner(owner); } diff --git a/gfx/layers/ipc/CanvasTranslator.h b/gfx/layers/ipc/CanvasTranslator.h index 03c6436ab812..bf3ed429ee12 100644 --- a/gfx/layers/ipc/CanvasTranslator.h +++ b/gfx/layers/ipc/CanvasTranslator.h @@ -171,7 +171,8 @@ class CanvasTranslator final : public gfx::InlineTranslator, * * @param aTextureId the texture ID to remove */ - void RemoveTexture(int64_t aTextureId); + void RemoveTexture(int64_t aTextureId, RemoteTextureTxnType aTxnType = 0, + RemoteTextureTxnId aTxnId = 0); bool LockTexture(int64_t aTextureId, OpenMode aMode, bool aInvalidContents = false); diff --git a/gfx/layers/ipc/CompositableForwarder.h b/gfx/layers/ipc/CompositableForwarder.h index da74a142e666..a379e65ce850 100644 --- a/gfx/layers/ipc/CompositableForwarder.h +++ b/gfx/layers/ipc/CompositableForwarder.h @@ -9,8 +9,9 @@ #include // for int32_t, uint32_t, uint64_t #include "mozilla/Assertions.h" // for AssertionConditionType, MOZ_ASSERT, MOZ_ASSERT_HELPER1 -#include "mozilla/RefPtr.h" // for RefPtr -#include "mozilla/TimeStamp.h" // for TimeStamp +#include "mozilla/RefPtr.h" // for RefPtr +#include "mozilla/TimeStamp.h" // for TimeStamp +#include "mozilla/ipc/ProtocolUtils.h" // for IToplevelProtocol, ProtocolID #include "mozilla/layers/KnowsCompositor.h" // for KnowsCompositor #include "nsRect.h" // for nsIntRect #include "nsRegion.h" // for nsIntRegion @@ -25,6 +26,34 @@ class PTextureChild; class SurfaceDescriptorTiles; class TextureClient; +/** + * FwdTransactionCounter issues forwarder transaction numbers that represent a + * sequential stream of transactions to be transported over IPDL. Since every + * top-level protocol represents its own independently-sequenced IPDL queue, + * transaction numbers most naturally align with top-level protocols, rather + * than have different sub-protocols with their own independent transaction + * numbers that can't be usefully sequenced. FwdTransactionCounter expects + * users of it to provide themselves as proof they are a top-level protocol + * to avoid issues. + */ +struct FwdTransactionCounter { + explicit FwdTransactionCounter(mozilla::ipc::IToplevelProtocol* aToplevel) + : mFwdTransactionType(aToplevel->GetProtocolId()) {} + + /** + * The ID of the top-level protocol. This is useful to tag the source of + * the transaction numbers in case different sources must be disambiguated. + */ + mozilla::ipc::ProtocolId mFwdTransactionType; + + /** + * Transaction id of ShadowLayerForwarder. + * It is incremented by UpdateFwdTransactionId() in each BeginTransaction() + * call. + */ + uint64_t mFwdTransactionId = 0; +}; + /** * A transaction is a set of changes that happenned on the content side, that * should be sent to the compositor side. @@ -92,14 +121,23 @@ class CompositableForwarder : public KnowsCompositor { CompositableClient* aCompositable, const RemoteTextureOwnerId aOwnerId, const gfx::IntSize aSize, const TextureFlags aFlags) = 0; - virtual void UpdateFwdTransactionId() = 0; - virtual uint64_t GetFwdTransactionId() = 0; + void UpdateFwdTransactionId() { + ++GetFwdTransactionCounter().mFwdTransactionId; + } + uint64_t GetFwdTransactionId() { + return GetFwdTransactionCounter().mFwdTransactionId; + } + mozilla::ipc::ProtocolId GetFwdTransactionType() { + return GetFwdTransactionCounter().mFwdTransactionType; + } virtual bool InForwarderThread() = 0; void AssertInForwarderThread() { MOZ_ASSERT(InForwarderThread()); } protected: + virtual FwdTransactionCounter& GetFwdTransactionCounter() = 0; + nsTArray> mTexturesToRemove; nsTArray> mCompositableClientsToRemove; }; diff --git a/gfx/layers/ipc/CompositorBridgeChild.cpp b/gfx/layers/ipc/CompositorBridgeChild.cpp index 71c95e657884..070e6d673ed2 100644 --- a/gfx/layers/ipc/CompositorBridgeChild.cpp +++ b/gfx/layers/ipc/CompositorBridgeChild.cpp @@ -80,7 +80,6 @@ CompositorBridgeChild::CompositorBridgeChild(CompositorManagerChild* aManager) mCanSend(false), mActorDestroyed(false), mPaused(false), - mFwdTransactionId(0), mThread(NS_GetCurrentThread()), mProcessToken(0), mSectionAllocator(nullptr) { @@ -470,7 +469,8 @@ void CompositorBridgeChild::HoldUntilCompositableRefReleasedIfNecessary( return; } - aClient->SetLastFwdTransactionId(GetFwdTransactionId()); + aClient->SetLastFwdTransactionId( + GetFwdTransactionCounter().mFwdTransactionId); mTexturesWaitingNotifyNotUsed.emplace(aClient->GetSerial(), aClient); } @@ -632,5 +632,9 @@ wr::PipelineId CompositorBridgeChild::GetNextPipelineId() { return wr::AsPipelineId(GetNextResourceId()); } +FwdTransactionCounter& CompositorBridgeChild::GetFwdTransactionCounter() { + return mCompositorManager->GetFwdTransactionCounter(); +} + } // namespace layers } // namespace mozilla diff --git a/gfx/layers/ipc/CompositorBridgeChild.h b/gfx/layers/ipc/CompositorBridgeChild.h index 22ac8ade98fe..7e0a4799fef6 100644 --- a/gfx/layers/ipc/CompositorBridgeChild.h +++ b/gfx/layers/ipc/CompositorBridgeChild.h @@ -47,6 +47,7 @@ class WebRenderLayerManager; class TextureClient; class TextureClientPool; struct FrameMetrics; +struct FwdTransactionCounter; class CompositorBridgeChild final : public PCompositorBridgeChild, public TextureForwarder { @@ -134,8 +135,7 @@ class CompositorBridgeChild final : public PCompositorBridgeChild, static void ShutDown(); - void UpdateFwdTransactionId() { ++mFwdTransactionId; } - uint64_t GetFwdTransactionId() { return mFwdTransactionId; } + FwdTransactionCounter& GetFwdTransactionCounter(); /** * Hold TextureClient ref until end of usage on host side if @@ -224,13 +224,6 @@ class CompositorBridgeChild final : public PCompositorBridgeChild, bool mPaused; - /** - * Transaction id of ShadowLayerForwarder. - * It is incremented by UpdateFwdTransactionId() in each BeginTransaction() - * call. - */ - uint64_t mFwdTransactionId; - /** * Hold TextureClients refs until end of their usages on host side. * It defer calling of TextureClient recycle callback. diff --git a/gfx/layers/ipc/CompositorManagerChild.cpp b/gfx/layers/ipc/CompositorManagerChild.cpp index 40ce08e8ca3e..0e553745d38d 100644 --- a/gfx/layers/ipc/CompositorManagerChild.cpp +++ b/gfx/layers/ipc/CompositorManagerChild.cpp @@ -176,7 +176,8 @@ CompositorManagerChild::CompositorManagerChild(CompositorManagerParent* aParent, mNamespace(aNamespace), mResourceId(0), mCanSend(false), - mSameProcess(true) { + mSameProcess(true), + mFwdTransactionCounter(this) { MOZ_ASSERT(aParent); SetOtherProcessId(base::GetCurrentProcId()); @@ -195,7 +196,8 @@ CompositorManagerChild::CompositorManagerChild( mNamespace(aNamespace), mResourceId(0), mCanSend(false), - mSameProcess(false) { + mSameProcess(false), + mFwdTransactionCounter(this) { if (NS_WARN_IF(!aEndpoint.Bind(this))) { return; } diff --git a/gfx/layers/ipc/CompositorManagerChild.h b/gfx/layers/ipc/CompositorManagerChild.h index f92ebde4609e..072b0d028ee2 100644 --- a/gfx/layers/ipc/CompositorManagerChild.h +++ b/gfx/layers/ipc/CompositorManagerChild.h @@ -10,9 +10,10 @@ #include // for size_t #include // for uint32_t, uint64_t #include "mozilla/Atomics.h" -#include "mozilla/Attributes.h" // for override -#include "mozilla/RefPtr.h" // for already_AddRefed -#include "mozilla/StaticPtr.h" // for StaticRefPtr +#include "mozilla/Attributes.h" // for override +#include "mozilla/RefPtr.h" // for already_AddRefed +#include "mozilla/StaticPtr.h" // for StaticRefPtr +#include "mozilla/layers/CompositableForwarder.h" // for FwdTransactionCounter #include "mozilla/layers/PCompositorManagerChild.h" namespace mozilla { @@ -92,6 +93,10 @@ class CompositorManagerChild : public PCompositorManagerChild { mozilla::ipc::IPCResult RecvNotifyWebRenderError( const WebRenderError&& aError); + FwdTransactionCounter& GetFwdTransactionCounter() { + return mFwdTransactionCounter; + } + private: static StaticRefPtr sInstance; static Atomic sOtherPid; @@ -111,6 +116,7 @@ class CompositorManagerChild : public PCompositorManagerChild { uint32_t mResourceId; bool mCanSend; bool mSameProcess; + FwdTransactionCounter mFwdTransactionCounter; }; } // namespace layers diff --git a/gfx/layers/ipc/CompositorManagerParent.cpp b/gfx/layers/ipc/CompositorManagerParent.cpp index f0675b72795d..7277db2bc2f3 100644 --- a/gfx/layers/ipc/CompositorManagerParent.cpp +++ b/gfx/layers/ipc/CompositorManagerParent.cpp @@ -12,6 +12,7 @@ #include "mozilla/layers/CompositorBridgeParent.h" #include "mozilla/layers/ContentCompositorBridgeParent.h" #include "mozilla/layers/CompositorThread.h" +#include "mozilla/layers/RemoteTextureMap.h" #include "mozilla/layers/SharedSurfacesParent.h" #include "mozilla/UniquePtr.h" #include "mozilla/Unused.h" @@ -151,6 +152,10 @@ void CompositorManagerParent::ActorDestroy(ActorDestroyReason aReason) { NewRunnableMethod("layers::CompositorManagerParent::DeferredDestroy", this, &CompositorManagerParent::DeferredDestroy)); + if (mRemoteTextureTxnScheduler) { + mRemoteTextureTxnScheduler = nullptr; + } + StaticMonitorAutoLock lock(sMonitor); if (sInstance == this) { sInstance = nullptr; @@ -372,6 +377,8 @@ mozilla::ipc::IPCResult CompositorManagerParent::RecvInitCanvasManager( Endpoint&& aEndpoint) { gfx::CanvasManagerParent::Init(std::move(aEndpoint), mSharedSurfacesHolder, mContentId); + mRemoteTextureTxnScheduler = + RemoteTextureMap::Get()->RegisterTxnScheduler(this); return IPC_OK(); } diff --git a/gfx/layers/ipc/CompositorManagerParent.h b/gfx/layers/ipc/CompositorManagerParent.h index 42de15c65b32..17eeb61c8c47 100644 --- a/gfx/layers/ipc/CompositorManagerParent.h +++ b/gfx/layers/ipc/CompositorManagerParent.h @@ -27,6 +27,7 @@ namespace layers { class CompositorBridgeParent; class CompositorThreadHolder; +class RemoteTextureTxnScheduler; class SharedSurfacesHolder; class CompositorManagerParent final : public PCompositorManagerParent { @@ -104,6 +105,7 @@ class CompositorManagerParent final : public PCompositorManagerParent { const dom::ContentParentId mContentId; const uint32_t mNamespace; uint32_t mLastSharedSurfaceResourceId MOZ_GUARDED_BY(sMonitor) = 0; + RefPtr mRemoteTextureTxnScheduler; }; } // namespace layers diff --git a/gfx/layers/ipc/ImageBridgeChild.cpp b/gfx/layers/ipc/ImageBridgeChild.cpp index 6dcf2be415b8..070ad1b8b07d 100644 --- a/gfx/layers/ipc/ImageBridgeChild.cpp +++ b/gfx/layers/ipc/ImageBridgeChild.cpp @@ -246,7 +246,7 @@ ImageBridgeChild::ImageBridgeChild(uint32_t aNamespace) : mNamespace(aNamespace), mCanSend(false), mDestroyed(false), - mFwdTransactionId(0), + mFwdTransactionCounter(this), mContainerMapLock("ImageBridgeChild.mContainerMapLock") { MOZ_ASSERT(mNamespace); MOZ_ASSERT(NS_IsMainThread()); diff --git a/gfx/layers/ipc/ImageBridgeChild.h b/gfx/layers/ipc/ImageBridgeChild.h index ee8ff9729947..7e02849c20fb 100644 --- a/gfx/layers/ipc/ImageBridgeChild.h +++ b/gfx/layers/ipc/ImageBridgeChild.h @@ -308,8 +308,9 @@ class ImageBridgeChild final : public PImageBridgeChild, bool IsSameProcess() const override; - void UpdateFwdTransactionId() override { ++mFwdTransactionId; } - uint64_t GetFwdTransactionId() override { return mFwdTransactionId; } + FwdTransactionCounter& GetFwdTransactionCounter() override { + return mFwdTransactionCounter; + } bool InForwarderThread() override { return InImageBridgeChildThread(); } @@ -351,7 +352,7 @@ class ImageBridgeChild final : public PImageBridgeChild, * It is incrementaed by UpdateFwdTransactionId() in each BeginTransaction() * call. */ - uint64_t mFwdTransactionId; + FwdTransactionCounter mFwdTransactionCounter; /** * Hold TextureClients refs until end of their usages on host side. diff --git a/gfx/layers/ipc/ImageBridgeParent.cpp b/gfx/layers/ipc/ImageBridgeParent.cpp index f88d1e8f01ec..d933e0fa49d4 100644 --- a/gfx/layers/ipc/ImageBridgeParent.cpp +++ b/gfx/layers/ipc/ImageBridgeParent.cpp @@ -22,6 +22,7 @@ #include "mozilla/layers/PImageBridgeParent.h" #include "mozilla/layers/TextureHostOGL.h" // for TextureHostOGL #include "mozilla/layers/Compositor.h" +#include "mozilla/layers/RemoteTextureMap.h" #include "mozilla/Monitor.h" #include "mozilla/mozalloc.h" // for operator new, etc #include "mozilla/ProfilerLabels.h" @@ -70,6 +71,8 @@ ImageBridgeParent::ImageBridgeParent(nsISerialEventTarget* aThread, mCompositorThreadHolder(CompositorThreadHolder::GetSingleton()) { MOZ_ASSERT(NS_IsMainThread()); SetOtherProcessId(aChildProcessId); + mRemoteTextureTxnScheduler = + RemoteTextureMap::Get()->RegisterTxnScheduler(this); } ImageBridgeParent::~ImageBridgeParent() = default; @@ -142,6 +145,9 @@ void ImageBridgeParent::ActorDestroy(ActorDestroyReason aWhy) { // Can't alloc/dealloc shmems from now on. mClosed = true; + if (mRemoteTextureTxnScheduler) { + mRemoteTextureTxnScheduler = nullptr; + } for (const auto& entry : mCompositables) { entry.second->OnReleased(); } @@ -198,13 +204,16 @@ mozilla::ipc::IPCResult ImageBridgeParent::RecvUpdate( &aToDestroy); UpdateFwdTransactionId(aFwdTransactionId); + auto result = IPC_OK(); + for (const auto& edit : aEdits) { RefPtr compositable = FindCompositable(edit.compositable()); if (!compositable || !ReceiveCompositableUpdate(edit.detail(), WrapNotNull(compositable), edit.compositable())) { - return IPC_FAIL_NO_REASON(this); + result = IPC_FAIL_NO_REASON(this); + break; } uint32_t dropped = compositable->GetDroppedFrames(); if (dropped) { @@ -212,7 +221,11 @@ mozilla::ipc::IPCResult ImageBridgeParent::RecvUpdate( } } - return IPC_OK(); + if (mRemoteTextureTxnScheduler) { + mRemoteTextureTxnScheduler->NotifyTxn(aFwdTransactionId); + } + + return result; } /* static */ diff --git a/gfx/layers/ipc/ImageBridgeParent.h b/gfx/layers/ipc/ImageBridgeParent.h index 7f2c7ce4ce8d..0267be3eaafd 100644 --- a/gfx/layers/ipc/ImageBridgeParent.h +++ b/gfx/layers/ipc/ImageBridgeParent.h @@ -28,6 +28,7 @@ class Shmem; namespace layers { struct ImageCompositeNotificationInfo; +class RemoteTextureTxnScheduler; /** * ImageBridgeParent is the manager Protocol of async Compositables. @@ -143,6 +144,8 @@ class ImageBridgeParent final : public PImageBridgeParent, static ImageBridgeMap sImageBridges; RefPtr mCompositorThreadHolder; + + RefPtr mRemoteTextureTxnScheduler; }; } // namespace layers diff --git a/gfx/layers/wr/WebRenderBridgeChild.cpp b/gfx/layers/wr/WebRenderBridgeChild.cpp index 8a7555d917e3..9de503d8a960 100644 --- a/gfx/layers/wr/WebRenderBridgeChild.cpp +++ b/gfx/layers/wr/WebRenderBridgeChild.cpp @@ -460,12 +460,8 @@ void WebRenderBridgeChild::EnableRemoteTexturePushCallback( OpEnableRemoteTexturePushCallback(aOwnerId, aSize, aFlags))); } -void WebRenderBridgeChild::UpdateFwdTransactionId() { - GetCompositorBridgeChild()->UpdateFwdTransactionId(); -} - -uint64_t WebRenderBridgeChild::GetFwdTransactionId() { - return GetCompositorBridgeChild()->GetFwdTransactionId(); +FwdTransactionCounter& WebRenderBridgeChild::GetFwdTransactionCounter() { + return GetCompositorBridgeChild()->GetFwdTransactionCounter(); } bool WebRenderBridgeChild::InForwarderThread() { return NS_IsMainThread(); } diff --git a/gfx/layers/wr/WebRenderBridgeChild.h b/gfx/layers/wr/WebRenderBridgeChild.h index 683041fe460a..54bbbb455a22 100644 --- a/gfx/layers/wr/WebRenderBridgeChild.h +++ b/gfx/layers/wr/WebRenderBridgeChild.h @@ -206,8 +206,8 @@ class WebRenderBridgeChild final : public PWebRenderBridgeChild, const RemoteTextureOwnerId aOwnerId, const gfx::IntSize aSize, const TextureFlags aFlags) override; - void UpdateFwdTransactionId() override; - uint64_t GetFwdTransactionId() override; + FwdTransactionCounter& GetFwdTransactionCounter() override; + bool InForwarderThread() override; void ActorDestroy(ActorDestroyReason why) override; diff --git a/gfx/layers/wr/WebRenderBridgeParent.cpp b/gfx/layers/wr/WebRenderBridgeParent.cpp index 5f3d1b082651..b88d8c8d8105 100644 --- a/gfx/layers/wr/WebRenderBridgeParent.cpp +++ b/gfx/layers/wr/WebRenderBridgeParent.cpp @@ -34,6 +34,7 @@ #include "mozilla/layers/ImageDataSerializer.h" #include "mozilla/layers/IpcResourceUpdateQueue.h" #include "mozilla/layers/OMTASampler.h" +#include "mozilla/layers/RemoteTextureMap.h" #include "mozilla/layers/SharedSurfacesParent.h" #include "mozilla/layers/TextureHost.h" #include "mozilla/layers/AsyncImagePipelineManager.h" @@ -314,6 +315,8 @@ WebRenderBridgeParent::WebRenderBridgeParent( mBoolParameterBits = ~gfxVars::WebRenderBoolParameters(); UpdateBoolParameters(); } + mRemoteTextureTxnScheduler = + RemoteTextureMap::Get()->RegisterTxnScheduler(aCompositorBridge); } WebRenderBridgeParent::WebRenderBridgeParent(const wr::PipelineId& aPipelineId, @@ -391,6 +394,9 @@ void WebRenderBridgeParent::Destroy() { IsRootWebRenderBridgeParent()); mDestroyed = true; + if (mRemoteTextureTxnScheduler) { + mRemoteTextureTxnScheduler = nullptr; + } if (mWebRenderBridgeRef) { // Break mutual reference mWebRenderBridgeRef->Clear(); @@ -1232,6 +1238,10 @@ 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."); } @@ -1383,6 +1393,10 @@ 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/WebRenderBridgeParent.h b/gfx/layers/wr/WebRenderBridgeParent.h index 062840a87f60..d8d80d104726 100644 --- a/gfx/layers/wr/WebRenderBridgeParent.h +++ b/gfx/layers/wr/WebRenderBridgeParent.h @@ -47,6 +47,7 @@ class Compositor; class CompositorBridgeParentBase; class CompositorVsyncScheduler; class OMTASampler; +class RemoteTextureTxnScheduler; class UiCompositorControllerParent; class WebRenderBridgeParentRef; class WebRenderImageHost; @@ -496,6 +497,8 @@ class WebRenderBridgeParent final : public PWebRenderBridgeParent, // These payloads are being used for SCROLL_PRESENT_LATENCY telemetry DataMutex>> mPendingScrollPayloads; + + RefPtr mRemoteTextureTxnScheduler; }; // Use this class, since WebRenderBridgeParent could not supports