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