forked from mirrors/gecko-dev
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
This commit is contained in:
parent
9a8f92d48a
commit
6accc1036c
27 changed files with 472 additions and 157 deletions
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
PersistentBufferProviderShared::Create(gfx::IntSize aSize,
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ class DrawTarget;
|
|||
|
||||
namespace layers {
|
||||
|
||||
class CompositableForwarder;
|
||||
class KnowsCompositor;
|
||||
struct RemoteTextureOwnerId;
|
||||
class TextureClient;
|
||||
|
|
@ -106,6 +107,8 @@ class PersistentBufferProvider : public RefCounted<PersistentBufferProvider>,
|
|||
virtual bool RequiresRefresh() const { return false; }
|
||||
|
||||
virtual Maybe<SurfaceDescriptor> 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<TextureClient>& aTexture);
|
||||
|
|
|
|||
|
|
@ -531,8 +531,12 @@ RecordedNextTextureId::RecordedNextTextureId(S& aStream)
|
|||
class RecordedTextureDestruction final
|
||||
: public RecordedEventDerived<RecordedTextureDestruction> {
|
||||
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 <class S>
|
||||
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 <class S>
|
||||
void RecordedTextureDestruction::Record(S& aStream) const {
|
||||
WriteElement(aStream, mTextureId);
|
||||
WriteElement(aStream, mTxnType);
|
||||
WriteElement(aStream, mTxnId);
|
||||
}
|
||||
|
||||
template <class S>
|
||||
RecordedTextureDestruction::RecordedTextureDestruction(S& aStream)
|
||||
: RecordedEventDerived(TEXTURE_DESTRUCTION) {
|
||||
ReadElement(aStream, mTextureId);
|
||||
ReadElement(aStream, mTxnType);
|
||||
ReadElement(aStream, mTxnId);
|
||||
}
|
||||
|
||||
class RecordedCheckpoint final
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include "mozilla/layers/RemoteTextureMap.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
#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::TextureOwner>
|
||||
RemoteTextureMap::UnregisterTextureOwner(
|
||||
const MonitorAutoLock& aProofOfLock, const RemoteTextureOwnerId aOwnerId,
|
||||
const base::ProcessId aForPid,
|
||||
std::vector<RefPtr<TextureHost>>& aReleasingTextures,
|
||||
std::vector<std::function<void(const RemoteTextureInfo&)>>&
|
||||
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<TextureOwner> releasingOwner = std::move(it->second);
|
||||
mTextureOwners.erase(it);
|
||||
return releasingOwner;
|
||||
}
|
||||
|
||||
void RemoteTextureMap::UnregisterTextureOwner(
|
||||
const RemoteTextureOwnerId aOwnerId, const base::ProcessId aForPid) {
|
||||
UniquePtr<TextureOwner> 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<RemoteTextureTxnScheduler>
|
||||
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<RemoteTextureTxnScheduler> 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<RemoteTextureTxnId>::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<RemoteTextureOwnerId,
|
||||
RemoteTextureOwnerId::HashFn>& aOwnerIds,
|
||||
|
|
@ -846,37 +892,30 @@ void RemoteTextureMap::UpdateTexture(const MonitorAutoLock& aProofOfLock,
|
|||
}
|
||||
}
|
||||
|
||||
std::vector<std::function<void(const RemoteTextureInfo&)>>
|
||||
RemoteTextureMap::GetRenderingReadyCallbacks(
|
||||
void RemoteTextureMap::GetRenderingReadyCallbacks(
|
||||
const MonitorAutoLock& aProofOfLock, RemoteTextureMap::TextureOwner* aOwner,
|
||||
const RemoteTextureId aTextureId) {
|
||||
const RemoteTextureId aTextureId,
|
||||
std::vector<std::function<void(const RemoteTextureInfo&)>>& aFunctions) {
|
||||
MOZ_ASSERT(aOwner);
|
||||
|
||||
std::vector<std::function<void(const RemoteTextureInfo&)>> 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<std::function<void(const RemoteTextureInfo&)>>
|
||||
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<std::function<void(const RemoteTextureInfo&)>>& 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());
|
||||
|
|
|
|||
|
|
@ -134,6 +134,52 @@ class RemoteTextureRecycleBin final {
|
|||
std::list<RecycledTextureHolder> 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<Wait> 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<RemoteTextureRecycleBin>& aRecycleBin = nullptr);
|
||||
void UnregisterTextureOwner(const RemoteTextureOwnerId aOwnerIds,
|
||||
void UnregisterTextureOwner(const RemoteTextureOwnerId aOwnerId,
|
||||
const base::ProcessId aForPid);
|
||||
void UnregisterTextureOwners(
|
||||
const std::unordered_set<RemoteTextureOwnerId,
|
||||
|
|
@ -262,6 +308,10 @@ class RemoteTextureMap {
|
|||
std::function<void(const RemoteTextureInfo&)>&& aReadyCallback,
|
||||
bool aWaitForRemoteTextureOwner = false);
|
||||
|
||||
bool WaitForTxn(const RemoteTextureOwnerId aOwnerId,
|
||||
const base::ProcessId aForPid, RemoteTextureTxnType aTxnType,
|
||||
RemoteTextureTxnId aTxnId);
|
||||
|
||||
void ReleaseRemoteTextureHost(RemoteTextureHostWrapper* aTextureHostWrapper);
|
||||
|
||||
RefPtr<TextureHost> GetOrCreateRemoteTextureHostWrapper(
|
||||
|
|
@ -305,7 +355,19 @@ class RemoteTextureMap {
|
|||
static RefPtr<TextureHost> CreateRemoteTexture(TextureData* aTextureData,
|
||||
TextureFlags aTextureFlags);
|
||||
|
||||
already_AddRefed<RemoteTextureTxnScheduler> RegisterTxnScheduler(
|
||||
base::ProcessId aForPid, RemoteTextureTxnType aType);
|
||||
|
||||
template <typename P>
|
||||
already_AddRefed<RemoteTextureTxnScheduler> 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<nsISerialEventTarget> mDeferUnregister;
|
||||
|
||||
// Holds TextureDataHolders that wait to be used for building wr display
|
||||
// list.
|
||||
std::deque<UniquePtr<TextureDataHolder>> mWaitingTextureDataHolders;
|
||||
|
|
@ -371,14 +438,22 @@ class RemoteTextureMap {
|
|||
RemoteTextureMap::TextureOwner* aOwner,
|
||||
const RemoteTextureId aTextureId);
|
||||
|
||||
std::vector<std::function<void(const RemoteTextureInfo&)>>
|
||||
GetRenderingReadyCallbacks(const MonitorAutoLock& aProofOfLock,
|
||||
RemoteTextureMap::TextureOwner* aOwner,
|
||||
const RemoteTextureId aTextureId);
|
||||
UniquePtr<TextureOwner> UnregisterTextureOwner(
|
||||
const MonitorAutoLock& aProofOfLock, const RemoteTextureOwnerId aOwnerId,
|
||||
const base::ProcessId aForPid,
|
||||
std::vector<RefPtr<TextureHost>>& aReleasingTextures,
|
||||
std::vector<std::function<void(const RemoteTextureInfo&)>>&
|
||||
aRenderingReadyCallbacks);
|
||||
|
||||
std::vector<std::function<void(const RemoteTextureInfo&)>>
|
||||
GetAllRenderingReadyCallbacks(const MonitorAutoLock& aProofOfLock,
|
||||
RemoteTextureMap::TextureOwner* aOwner);
|
||||
void GetRenderingReadyCallbacks(
|
||||
const MonitorAutoLock& aProofOfLock,
|
||||
RemoteTextureMap::TextureOwner* aOwner, const RemoteTextureId aTextureId,
|
||||
std::vector<std::function<void(const RemoteTextureInfo&)>>& aFunctions);
|
||||
|
||||
void GetAllRenderingReadyCallbacks(
|
||||
const MonitorAutoLock& aProofOfLock,
|
||||
RemoteTextureMap::TextureOwner* aOwner,
|
||||
std::vector<std::function<void(const RemoteTextureInfo&)>>& 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<std::pair<base::ProcessId, RemoteTextureOwnerId>,
|
||||
|
|
@ -406,6 +488,10 @@ class RemoteTextureMap {
|
|||
RefPtr<CompositableHost>>
|
||||
mRemoteTexturePushListeners;
|
||||
|
||||
std::map<std::pair<base::ProcessId, RemoteTextureTxnType>,
|
||||
RemoteTextureTxnScheduler*>
|
||||
mTxnSchedulers;
|
||||
|
||||
static StaticAutoPtr<RemoteTextureMap> sInstance;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -332,6 +332,8 @@ class TextureData {
|
|||
|
||||
virtual bool RequiresRefresh() const { return false; }
|
||||
|
||||
virtual void UseCompositableForwarder(CompositableForwarder* aForwarder) {}
|
||||
|
||||
protected:
|
||||
MOZ_COUNTED_DEFAULT_CTOR(TextureData)
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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!");
|
||||
|
|
|
|||
|
|
@ -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<gfx::SourceSurface> mSnapshot;
|
||||
ThreadSafeWeakPtr<gfx::SourceSurface> 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;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -796,19 +796,29 @@ already_AddRefed<gfx::DrawTarget> 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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -9,8 +9,9 @@
|
|||
|
||||
#include <stdint.h> // 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<RefPtr<TextureClient>> mTexturesToRemove;
|
||||
nsTArray<RefPtr<CompositableClient>> mCompositableClientsToRemove;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,9 +10,10 @@
|
|||
#include <stddef.h> // for size_t
|
||||
#include <stdint.h> // 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<CompositorManagerChild> sInstance;
|
||||
static Atomic<base::ProcessId> sOtherPid;
|
||||
|
|
@ -111,6 +116,7 @@ class CompositorManagerChild : public PCompositorManagerChild {
|
|||
uint32_t mResourceId;
|
||||
bool mCanSend;
|
||||
bool mSameProcess;
|
||||
FwdTransactionCounter mFwdTransactionCounter;
|
||||
};
|
||||
|
||||
} // namespace layers
|
||||
|
|
|
|||
|
|
@ -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<PCanvasManagerParent>&& aEndpoint) {
|
||||
gfx::CanvasManagerParent::Init(std::move(aEndpoint), mSharedSurfacesHolder,
|
||||
mContentId);
|
||||
mRemoteTextureTxnScheduler =
|
||||
RemoteTextureMap::Get()->RegisterTxnScheduler(this);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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<RemoteTextureTxnScheduler> mRemoteTextureTxnScheduler;
|
||||
};
|
||||
|
||||
} // namespace layers
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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<CompositableHost> 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 */
|
||||
|
|
|
|||
|
|
@ -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<CompositorThreadHolder> mCompositorThreadHolder;
|
||||
|
||||
RefPtr<RemoteTextureTxnScheduler> mRemoteTextureTxnScheduler;
|
||||
};
|
||||
|
||||
} // namespace layers
|
||||
|
|
|
|||
|
|
@ -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(); }
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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.");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<nsClassHashtable<nsUint64HashKey, nsTArray<CompositionPayload>>>
|
||||
mPendingScrollPayloads;
|
||||
|
||||
RefPtr<RemoteTextureTxnScheduler> mRemoteTextureTxnScheduler;
|
||||
};
|
||||
|
||||
// Use this class, since WebRenderBridgeParent could not supports
|
||||
|
|
|
|||
Loading…
Reference in a new issue