Bug 1877010 - Track forwarder transaction ids for RemoteTextureMap with WebGL and WebGPU. r=sotaro

Differential Revision: https://phabricator.services.mozilla.com/D199876
This commit is contained in:
Lee Salzman
2024-01-30 15:44:04 +00:00
parent 23705875ae
commit 25a04a247d
33 changed files with 286 additions and 94 deletions

View File

@@ -1786,6 +1786,15 @@ Maybe<SurfaceDescriptor> CanvasRenderingContext2D::GetFrontBuffer(
return Nothing();
}
already_AddRefed<layers::FwdTransactionTracker>
CanvasRenderingContext2D::UseCompositableForwarder(
layers::CompositableForwarder* aForwarder) {
if (mBufferProvider) {
return mBufferProvider->UseCompositableForwarder(aForwarder);
}
return nullptr;
}
PresShell* CanvasRenderingContext2D::GetPresShell() {
if (mCanvasElement) {
return mCanvasElement->OwnerDoc()->GetPresShell();

View File

@@ -107,6 +107,9 @@ class CanvasRenderingContext2D : public nsICanvasRenderingContextInternal,
Maybe<layers::SurfaceDescriptor> GetFrontBuffer(
WebGLFramebufferJS*, const bool webvr = false) override;
already_AddRefed<layers::FwdTransactionTracker> UseCompositableForwarder(
layers::CompositableForwarder* aForwarder) override;
void Save();
void Restore();

View File

@@ -22,6 +22,7 @@
#include "mozilla/gfx/CanvasManagerChild.h"
#include "mozilla/ipc/Shmem.h"
#include "mozilla/gfx/Swizzle.h"
#include "mozilla/layers/CompositableForwarder.h"
#include "mozilla/layers/CompositorBridgeChild.h"
#include "mozilla/layers/ImageBridgeChild.h"
#include "mozilla/layers/OOPCanvasRenderer.h"
@@ -52,7 +53,7 @@ webgl::NotLostData::NotLostData(ClientWebGLContext& _context)
webgl::NotLostData::~NotLostData() {
if (outOfProcess) {
Unused << dom::WebGLChild::Send__delete__(outOfProcess.get());
outOfProcess->Destroy();
}
}
@@ -484,24 +485,25 @@ webgl::SwapChainOptions ClientWebGLContext::PrepareAsyncSwapChainOptions(
// Currently remote texture ids should only be set internally.
MOZ_ASSERT(!options.remoteTextureOwnerId.IsValid() &&
!options.remoteTextureId.IsValid());
auto& ownerId = fb ? fb->mRemoteTextureOwnerId : mRemoteTextureOwnerId;
auto& textureId = fb ? fb->mLastRemoteTextureId : mLastRemoteTextureId;
// Async present only works when out-of-process. It is not supported in WebVR.
// Allow it if it is either forced or if the pref is set.
if (!IsContextLost() && !mNotLost->inProcess && !webvr &&
if (fb || webvr) {
return options;
}
if (!IsContextLost() && !mNotLost->inProcess &&
(options.forceAsyncPresent ||
StaticPrefs::webgl_out_of_process_async_present())) {
if (!ownerId) {
ownerId = Some(layers::RemoteTextureOwnerId::GetNext());
if (!mRemoteTextureOwnerId) {
mRemoteTextureOwnerId = Some(layers::RemoteTextureOwnerId::GetNext());
}
textureId = Some(layers::RemoteTextureId::GetNext());
mLastRemoteTextureId = Some(layers::RemoteTextureId::GetNext());
webgl::SwapChainOptions asyncOptions = options;
asyncOptions.remoteTextureOwnerId = *ownerId;
asyncOptions.remoteTextureId = *textureId;
asyncOptions.remoteTextureOwnerId = *mRemoteTextureOwnerId;
asyncOptions.remoteTextureId = *mLastRemoteTextureId;
return asyncOptions;
}
// Clear the current remote texture id so that we disable async.
textureId = Nothing();
mRemoteTextureOwnerId = Nothing();
return options;
}
@@ -550,19 +552,13 @@ Maybe<layers::SurfaceDescriptor> ClientWebGLContext::GetFrontBuffer(
auto& info = child->GetFlushedCmdInfo();
// If valid remote texture data was set for async present, then use it.
const auto& ownerId = fb ? fb->mRemoteTextureOwnerId : mRemoteTextureOwnerId;
const auto& textureId = fb ? fb->mLastRemoteTextureId : mLastRemoteTextureId;
auto& needsSync = fb ? fb->mNeedsRemoteTextureSync : mNeedsRemoteTextureSync;
if (ownerId && textureId) {
if (!fb && !vr && mRemoteTextureOwnerId && mLastRemoteTextureId) {
const auto tooManyFlushes = 10;
// If there are many flushed cmds, force synchronous IPC to avoid too many
// pending ipc messages.
if (info.flushesSinceLastCongestionCheck > tooManyFlushes) {
needsSync = true;
}
if (XRE_IsParentProcess() ||
gfx::gfxVars::WebglOopAsyncPresentForceSync() || needsSync) {
needsSync = false;
gfx::gfxVars::WebglOopAsyncPresentForceSync() ||
info.flushesSinceLastCongestionCheck > tooManyFlushes) {
// Request the front buffer from IPDL to cause a sync, even though we
// will continue to use the remote texture descriptor after.
(void)child->SendGetFrontBuffer(fb ? fb->mId : 0, vr, &ret);
@@ -571,7 +567,8 @@ Maybe<layers::SurfaceDescriptor> ClientWebGLContext::GetFrontBuffer(
info.flushesSinceLastCongestionCheck = 0;
info.congestionCheckGeneration++;
return Some(layers::SurfaceDescriptorRemoteTexture(*textureId, *ownerId));
return Some(layers::SurfaceDescriptorRemoteTexture(*mLastRemoteTextureId,
*mRemoteTextureOwnerId));
}
if (!child->SendGetFrontBuffer(fb ? fb->mId : 0, vr, &ret)) return {};
@@ -589,6 +586,27 @@ Maybe<layers::SurfaceDescriptor> ClientWebGLContext::PresentFrontBuffer(
return GetFrontBuffer(fb, webvr);
}
already_AddRefed<layers::FwdTransactionTracker>
ClientWebGLContext::UseCompositableForwarder(
layers::CompositableForwarder* aForwarder) {
if (mRemoteTextureOwnerId) {
return layers::FwdTransactionTracker::GetOrCreate(mFwdTransactionTracker);
}
return nullptr;
}
void ClientWebGLContext::OnDestroyChild(dom::WebGLChild* aChild) {
// Since NotLostData may be destructing at this point, the RefPtr to
// WebGLChild may be unreliable. Instead, it must be explicitly passed in.
if (mRemoteTextureOwnerId && mFwdTransactionTracker &&
mFwdTransactionTracker->IsUsed()) {
(void)aChild->SendWaitForTxn(
*mRemoteTextureOwnerId,
layers::ToRemoteTextureTxnType(mFwdTransactionTracker),
layers::ToRemoteTextureTxnId(mFwdTransactionTracker));
}
}
void ClientWebGLContext::ClearVRSwapChain() { Run<RPROC(ClearVRSwapChain)>(); }
// -
@@ -622,7 +640,6 @@ bool ClientWebGLContext::UpdateWebRenderCanvasData(
MOZ_ASSERT(renderer);
mResetLayer = false;
mNeedsRemoteTextureSync = true;
return true;
}
@@ -865,6 +882,7 @@ bool ClientWebGLContext::CreateHostContext(const uvec2& requestedSize) {
// WebGLParent.
if (mRemoteTextureOwnerId.isSome()) {
mRemoteTextureOwnerId = Nothing();
mFwdTransactionTracker = nullptr;
}
if (!outOfProcess->SendInitialize(initDesc, &notLost.info)) {

View File

@@ -300,12 +300,6 @@ class WebGLFramebufferJS final : public nsWrapperCache, public webgl::ObjectJS {
private:
bool mHasBeenBound = false; // !IsFramebuffer until Bind
std::unordered_map<GLenum, Attachment> mAttachments;
// Holds Some Id if async present is used
Maybe<layers::RemoteTextureId> mLastRemoteTextureId;
Maybe<layers::RemoteTextureOwnerId> mRemoteTextureOwnerId;
// Needs sync IPC to ensure that the remote texture exists in the
// RemoteTextureMap.
bool mNeedsRemoteTextureSync = true;
public:
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLFramebufferJS)
@@ -787,12 +781,12 @@ class ClientWebGLContext final : public nsICanvasRenderingContextInternal,
mutable GLenum mNextError = 0;
mutable webgl::LossStatus mLossStatus = webgl::LossStatus::Ready;
mutable bool mAwaitingRestore = false;
public:
// Holds Some Id if async present is used
mutable Maybe<layers::RemoteTextureId> mLastRemoteTextureId;
mutable Maybe<layers::RemoteTextureOwnerId> mRemoteTextureOwnerId;
// Needs sync IPC to ensure that the remote texture exists in the
// RemoteTextureMap.
bool mNeedsRemoteTextureSync = true;
mutable RefPtr<layers::FwdTransactionTracker> mFwdTransactionTracker;
// -
@@ -1084,6 +1078,9 @@ class ClientWebGLContext final : public nsICanvasRenderingContextInternal,
const bool webvr = false) override;
RefPtr<gfx::SourceSurface> GetFrontBufferSnapshot(
bool requireAlphaPremult = true) override;
already_AddRefed<layers::FwdTransactionTracker> UseCompositableForwarder(
layers::CompositableForwarder* aForwarder) override;
void OnDestroyChild(dom::WebGLChild* aChild);
void ClearVRSwapChain();

View File

@@ -176,6 +176,11 @@ class HostWebGLContext final : public SupportsWeakPtr {
const webgl::SwapChainOptions& options) const {
return (void)mContext->CopyToSwapChain(AutoResolve(fb), t, options);
}
void WaitForTxn(const layers::RemoteTextureOwnerId aOwnerId,
const layers::RemoteTextureTxnType txnType,
const layers::RemoteTextureTxnId txnId) {
mContext->WaitForTxn(aOwnerId, txnType, txnId);
}
void EndOfFrame() const { return (void)mContext->EndOfFrame(); }
Maybe<layers::SurfaceDescriptor> GetFrontBuffer(ObjectId xrFb,
const bool webvr) const;

View File

@@ -195,6 +195,7 @@ bool OffscreenCanvasDisplayHelper::CommitFrameToCompositor(
RefPtr<layers::TextureClient> texture;
RefPtr<gfx::SourceSurface> surface;
Maybe<layers::SurfaceDescriptor> desc;
RefPtr<layers::FwdTransactionTracker> tracker;
{
MutexAutoUnlock unlock(mMutex);
@@ -207,6 +208,12 @@ bool OffscreenCanvasDisplayHelper::CommitFrameToCompositor(
hasRemoteTextureDesc =
desc->type() ==
layers::SurfaceDescriptor::TSurfaceDescriptorRemoteTexture;
if (hasRemoteTextureDesc) {
tracker = aContext->UseCompositableForwarder(imageBridge);
if (tracker) {
flags |= layers::TextureFlags::WAIT_FOR_REMOTE_TEXTURE_OWNER;
}
}
} else {
if (layers::PersistentBufferProvider* provider =
aContext->GetBufferProvider()) {
@@ -245,7 +252,8 @@ bool OffscreenCanvasDisplayHelper::CommitFrameToCompositor(
if (hasRemoteTextureDesc) {
const auto& textureDesc = desc->get_SurfaceDescriptorRemoteTexture();
imageBridge->UpdateCompositable(mImageContainer, textureDesc.textureId(),
textureDesc.ownerId(), mData.mSize, flags);
textureDesc.ownerId(), mData.mSize, flags,
tracker);
return true;
}

View File

@@ -9,6 +9,9 @@ include protocol PCanvasManager;
include "mozilla/layers/LayersMessageUtils.h";
[MoveOnly] using class mozilla::ipc::BigBuffer from "mozilla/ipc/BigBuffer.h";
using mozilla::layers::RemoteTextureOwnerId from "mozilla/layers/LayersTypes.h";
using mozilla::layers::RemoteTextureTxnType from "mozilla/layers/LayersTypes.h";
using mozilla::layers::RemoteTextureTxnId from "mozilla/layers/LayersTypes.h";
using mozilla::layers::SurfaceDescriptor from "mozilla/layers/LayersTypes.h";
using std::string from "string";
using mozilla::uvec2 from "mozilla/dom/WebGLIpdl.h";
@@ -54,6 +57,8 @@ parent:
async __delete__();
async WaitForTxn(RemoteTextureOwnerId ownerId, RemoteTextureTxnType txnType, RemoteTextureTxnId txnId);
// -
async DispatchCommands(BigBuffer commands, uint64_t size);

View File

@@ -15,7 +15,17 @@ WebGLChild::WebGLChild(ClientWebGLContext& context)
: mContext(&context),
mDefaultCmdsShmemSize(StaticPrefs::webgl_out_of_process_shmem_size()) {}
WebGLChild::~WebGLChild() { (void)Send__delete__(this); }
WebGLChild::~WebGLChild() { Destroy(); }
void WebGLChild::Destroy() {
if (!CanSend()) {
return;
}
if (mContext) {
mContext->OnDestroyChild(this);
}
(void)Send__delete__(this);
}
void WebGLChild::ActorDestroy(ActorDestroyReason why) {
mPendingCmdsShmem = {};

View File

@@ -46,6 +46,7 @@ class WebGLChild final : public PWebGLChild, public SupportsWeakPtr {
Maybe<Range<uint8_t>> AllocPendingCmdBytes(size_t,
size_t fyiAlignmentOverhead);
void FlushPendingCmds();
void Destroy();
void ActorDestroy(ActorDestroyReason why) override;
FlushedCmdInfo& GetFlushedCmdInfo() { return mFlushedCmdInfo; }

View File

@@ -1082,6 +1082,17 @@ void WebGLContext::Present(WebGLFramebuffer* const xrFb,
}
}
void WebGLContext::WaitForTxn(layers::RemoteTextureOwnerId ownerId,
layers::RemoteTextureTxnType txnType,
layers::RemoteTextureTxnId txnId) {
if (!ownerId.IsValid() || !txnType || !txnId) {
return;
}
if (mRemoteTextureOwner && mRemoteTextureOwner->IsRegistered(ownerId)) {
mRemoteTextureOwner->WaitForTxn(ownerId, txnType, txnId);
}
}
bool WebGLContext::CopyToSwapChain(
WebGLFramebuffer* const srcFb, const layers::TextureType consumerType,
const webgl::SwapChainOptions& options,

View File

@@ -1269,8 +1269,14 @@ class WebGLContext : public VRefCounted, public SupportsWeakPtr {
void EnsureContextLostRemoteTextureOwner(
const webgl::SwapChainOptions& options);
public:
void WaitForTxn(layers::RemoteTextureOwnerId ownerId,
layers::RemoteTextureTxnType txnType,
layers::RemoteTextureTxnId txnId);
// --
protected:
bool EnsureDefaultFB();
bool ValidateAndInitFB(
const WebGLFramebuffer* fb,

View File

@@ -98,6 +98,15 @@ mozilla::ipc::IPCResult WebGLParent::Recv__delete__() {
void WebGLParent::ActorDestroy(ActorDestroyReason aWhy) { mHost = nullptr; }
mozilla::ipc::IPCResult WebGLParent::RecvWaitForTxn(
layers::RemoteTextureOwnerId aOwnerId,
layers::RemoteTextureTxnType aTxnType, layers::RemoteTextureTxnId aTxnId) {
if (mHost) {
mHost->WaitForTxn(aOwnerId, aTxnType, aTxnId);
}
return IPC_OK();
}
// -
IPCResult WebGLParent::RecvGetFrontBufferSnapshot(

View File

@@ -118,6 +118,10 @@ class WebGLParent : public PWebGLParent, public SupportsWeakPtr {
void ActorDestroy(ActorDestroyReason aWhy) override;
mozilla::ipc::IPCResult RecvWaitForTxn(layers::RemoteTextureOwnerId aOwnerId,
layers::RemoteTextureTxnType aTxnType,
layers::RemoteTextureTxnId aTxnId);
UniquePtr<HostWebGLContext> mHost;
// Runnable that repeatedly processes our WebGL command queue

View File

@@ -42,6 +42,8 @@ class PresShell;
class WebGLFramebufferJS;
namespace layers {
class CanvasRenderer;
class CompositableForwarder;
class FwdTransactionTracker;
class Layer;
class Image;
class LayerManager;
@@ -212,6 +214,11 @@ class nsICanvasRenderingContextInternal : public nsISupports,
return GetFrontBuffer(fb, webvr);
}
virtual already_AddRefed<mozilla::layers::FwdTransactionTracker>
UseCompositableForwarder(mozilla::layers::CompositableForwarder* aForwarder) {
return nullptr;
}
void DoSecurityCheck(nsIPrincipal* aPrincipal, bool forceWriteOnly,
bool CORSUsed);

View File

@@ -11,6 +11,7 @@
#include "mozilla/dom/HTMLCanvasElement.h"
#include "mozilla/gfx/CanvasManagerChild.h"
#include "mozilla/layers/CanvasRenderer.h"
#include "mozilla/layers/CompositableForwarder.h"
#include "mozilla/layers/ImageDataSerializer.h"
#include "mozilla/layers/LayersSurfaces.h"
#include "mozilla/layers/RenderRootStateManager.h"
@@ -142,10 +143,14 @@ void CanvasContext::Configure(const dom::GPUCanvasConfiguration& aConfig) {
}
void CanvasContext::Unconfigure() {
if (mBridge && mBridge->IsOpen() && mRemoteTextureOwnerId.isSome()) {
mBridge->SendSwapChainDrop(*mRemoteTextureOwnerId);
if (mBridge && mBridge->IsOpen() && mRemoteTextureOwnerId) {
mBridge->SendSwapChainDrop(
*mRemoteTextureOwnerId,
layers::ToRemoteTextureTxnType(mFwdTransactionTracker),
layers::ToRemoteTextureTxnId(mFwdTransactionTracker));
}
mRemoteTextureOwnerId = Nothing();
mFwdTransactionTracker = nullptr;
mBridge = nullptr;
mConfig = nullptr;
mTexture = nullptr;
@@ -340,6 +345,12 @@ Maybe<layers::SurfaceDescriptor> CanvasContext::GetFrontBuffer(
return Nothing();
}
already_AddRefed<layers::FwdTransactionTracker>
CanvasContext::UseCompositableForwarder(
layers::CompositableForwarder* aForwarder) {
return layers::FwdTransactionTracker::GetOrCreate(mFwdTransactionTracker);
}
void CanvasContext::ForceNewFrame() {
if (!mCanvasElement && !mOffscreenCanvas) {
return;

View File

@@ -81,6 +81,9 @@ class CanvasContext final : public nsICanvasRenderingContextInternal,
Maybe<layers::SurfaceDescriptor> GetFrontBuffer(WebGLFramebufferJS*,
const bool) override;
already_AddRefed<layers::FwdTransactionTracker> UseCompositableForwarder(
layers::CompositableForwarder* aForwarder) override;
public:
void GetCanvas(dom::OwningHTMLCanvasElementOrOffscreenCanvas&) const;
@@ -105,6 +108,7 @@ class CanvasContext final : public nsICanvasRenderingContextInternal,
Maybe<layers::RemoteTextureId> mLastRemoteTextureId;
Maybe<layers::RemoteTextureOwnerId> mRemoteTextureOwnerId;
RefPtr<layers::FwdTransactionTracker> mFwdTransactionTracker;
bool mUseExternalTextureInSwapChain = false;
bool mNewTextureRequested = false;
};

View File

@@ -8,6 +8,8 @@
using mozilla::layers::RGBDescriptor from "mozilla/layers/LayersSurfaces.h";
using mozilla::layers::RemoteTextureId from "mozilla/layers/LayersTypes.h";
using mozilla::layers::RemoteTextureOwnerId from "mozilla/layers/LayersTypes.h";
using mozilla::layers::RemoteTextureTxnType from "mozilla/layers/LayersTypes.h";
using mozilla::layers::RemoteTextureTxnId from "mozilla/layers/LayersTypes.h";
using mozilla::webgpu::RawId from "mozilla/webgpu/WebGPUTypes.h";
using mozilla::dom::GPUErrorFilter from "mozilla/dom/WebGPUBinding.h";
using mozilla::dom::GPURequestAdapterOptions from "mozilla/dom/WebGPUBinding.h";
@@ -78,7 +80,7 @@ parent:
async ImplicitLayoutDrop(RawId implicitPlId, RawId[] implicitBglIds);
async DeviceCreateSwapChain(RawId selfId, RawId queueId, RGBDescriptor desc, RawId[] bufferIds, RemoteTextureOwnerId ownerId, bool useExternalTextureInSwapChain);
async SwapChainPresent(RawId textureId, RawId commandEncoderId, RemoteTextureId remoteTextureId, RemoteTextureOwnerId remoteTextureOwnerId);
async SwapChainDrop(RemoteTextureOwnerId ownerId);
async SwapChainDrop(RemoteTextureOwnerId ownerId, RemoteTextureTxnType txnType, RemoteTextureTxnId txnId);
async DevicePushErrorScope(RawId selfId, GPUErrorFilter aFilter);
async DevicePopErrorScope(RawId selfId) returns (PopErrorScopeResult result);

View File

@@ -1310,10 +1310,8 @@ ipc::IPCResult WebGPUParent::RecvSwapChainPresent(
}
ipc::IPCResult WebGPUParent::RecvSwapChainDrop(
const layers::RemoteTextureOwnerId& aOwnerId) {
if (mRemoteTextureOwner) {
mRemoteTextureOwner->UnregisterTextureOwner(aOwnerId);
}
const layers::RemoteTextureOwnerId& aOwnerId,
layers::RemoteTextureTxnType aTxnType, layers::RemoteTextureTxnId aTxnId) {
const auto& lookup = mPresentationDataMap.find(aOwnerId);
MOZ_ASSERT(lookup != mPresentationDataMap.end());
if (lookup == mPresentationDataMap.end()) {
@@ -1322,6 +1320,14 @@ ipc::IPCResult WebGPUParent::RecvSwapChainDrop(
}
RefPtr<PresentationData> data = lookup->second.get();
if (mRemoteTextureOwner) {
if (aTxnType && aTxnId) {
mRemoteTextureOwner->WaitForTxn(aOwnerId, aTxnType, aTxnId);
}
mRemoteTextureOwner->UnregisterTextureOwner(aOwnerId);
}
mPresentationDataMap.erase(lookup);
MutexAutoLock lock(data->mBuffersLock);

View File

@@ -105,8 +105,9 @@ class WebGPUParent final : public PWebGPUParent, public SupportsWeakPtr {
RawId aTextureId, RawId aCommandEncoderId,
const layers::RemoteTextureId& aRemoteTextureId,
const layers::RemoteTextureOwnerId& aOwnerId);
ipc::IPCResult RecvSwapChainDrop(
const layers::RemoteTextureOwnerId& aOwnerId);
ipc::IPCResult RecvSwapChainDrop(const layers::RemoteTextureOwnerId& aOwnerId,
layers::RemoteTextureTxnType aTxnType,
layers::RemoteTextureTxnId aTxnId);
ipc::IPCResult RecvDeviceAction(RawId aDeviceId,
const ipc::ByteBuf& aByteBuf);

View File

@@ -255,9 +255,10 @@ bool PersistentBufferProviderAccelerated::RequiresRefresh() const {
return mTexture->GetInternalData()->RequiresRefresh();
}
void PersistentBufferProviderAccelerated::UseCompositableForwarder(
already_AddRefed<FwdTransactionTracker>
PersistentBufferProviderAccelerated::UseCompositableForwarder(
CompositableForwarder* aForwarder) {
mTexture->GetInternalData()->UseCompositableForwarder(aForwarder);
return mTexture->GetInternalData()->UseCompositableForwarder(aForwarder);
}
// static

View File

@@ -29,6 +29,7 @@ class DrawTarget;
namespace layers {
class CompositableForwarder;
class FwdTransactionTracker;
class KnowsCompositor;
struct RemoteTextureOwnerId;
class TextureClient;
@@ -108,9 +109,10 @@ class PersistentBufferProvider : public RefCounted<PersistentBufferProvider>,
virtual Maybe<SurfaceDescriptor> GetFrontBuffer() { return Nothing(); }
virtual void UseCompositableForwarder(CompositableForwarder* aForwarder) {}
virtual bool WaitForRemoteTextureOwner() const { return false; }
virtual already_AddRefed<FwdTransactionTracker> UseCompositableForwarder(
CompositableForwarder* aForwarder) {
return nullptr;
}
};
class PersistentBufferProviderBasic : public PersistentBufferProvider {
@@ -176,9 +178,8 @@ class PersistentBufferProviderAccelerated : public PersistentBufferProvider {
bool RequiresRefresh() const override;
void UseCompositableForwarder(CompositableForwarder* aForwarder) override;
bool WaitForRemoteTextureOwner() const override { return true; }
already_AddRefed<FwdTransactionTracker> UseCompositableForwarder(
CompositableForwarder* aForwarder) override;
protected:
explicit PersistentBufferProviderAccelerated(

View File

@@ -79,6 +79,17 @@ void RemoteTextureOwnerClient::UnregisterAllTextureOwners() {
mSharedRecycleBin = nullptr;
}
bool RemoteTextureOwnerClient::WaitForTxn(const RemoteTextureOwnerId aOwnerId,
RemoteTextureTxnType aTxnType,
RemoteTextureTxnId aTxnId) {
auto it = mOwnerIds.find(aOwnerId);
if (it == mOwnerIds.end() || !aTxnType || !aTxnId) {
return false;
}
return RemoteTextureMap::Get()->WaitForTxn(aOwnerId, mForPid, aTxnType,
aTxnId);
}
void RemoteTextureOwnerClient::ClearRecycledTextures() {
RemoteTextureMap::Get()->ClearRecycledTextures(mOwnerIds, mForPid,
mSharedRecycleBin);
@@ -587,7 +598,7 @@ void RemoteTextureMap::KeepTextureDataAliveForTextureHostIfNecessary(
UniquePtr<RemoteTextureMap::TextureOwner>
RemoteTextureMap::UnregisterTextureOwner(
const MonitorAutoLock& aProofOfLock, const RemoteTextureOwnerId aOwnerId,
MonitorAutoLock& aProofOfLock, const RemoteTextureOwnerId aOwnerId,
const base::ProcessId aForPid,
std::vector<RefPtr<TextureHost>>& aReleasingTextures,
std::vector<std::function<void(const RemoteTextureInfo&)>>&
@@ -604,6 +615,12 @@ RemoteTextureMap::UnregisterTextureOwner(
// unregistering.
if (owner->mWaitForTxn) {
owner->mDeferUnregister = GetCurrentSerialEventTarget();
// If another thread is waiting on this owner to produce textures,
// it must be notified that owner is going away.
if (!owner->mLatestTextureHost &&
owner->mWaitingTextureDataHolders.empty()) {
aProofOfLock.Notify();
}
return nullptr;
}
@@ -977,7 +994,7 @@ bool RemoteTextureMap::GetRemoteTexture(
const TimeDuration timeout = TimeDuration::FromMilliseconds(10000);
while (!owner || (!owner->mLatestTextureHost &&
owner->mWaitingTextureDataHolders.empty())) {
if (owner && owner->mIsContextLost) {
if (owner && (owner->mIsContextLost || owner->mDeferUnregister)) {
// If the context was lost, no further updates are expected.
return false;
}

View File

@@ -204,6 +204,8 @@ class RemoteTextureOwnerClient final {
bool aSharedRecycling = false);
void UnregisterTextureOwner(const RemoteTextureOwnerId aOwnerId);
void UnregisterAllTextureOwners();
bool WaitForTxn(const RemoteTextureOwnerId aOwnerId,
RemoteTextureTxnType aTxnType, RemoteTextureTxnId aTxnId);
void ClearRecycledTextures();
void NotifyContextLost(const RemoteTextureOwnerIdSet* aOwnerIds = nullptr);
void NotifyContextRestored(
@@ -426,7 +428,7 @@ class RemoteTextureMap {
const RemoteTextureId aTextureId);
UniquePtr<TextureOwner> UnregisterTextureOwner(
const MonitorAutoLock& aProofOfLock, const RemoteTextureOwnerId aOwnerId,
MonitorAutoLock& aProofOfLock, const RemoteTextureOwnerId aOwnerId,
const base::ProcessId aForPid,
std::vector<RefPtr<TextureHost>>& aReleasingTextures,
std::vector<std::function<void(const RemoteTextureInfo&)>>&

View File

@@ -179,16 +179,15 @@ void ShareableCanvasRenderer::UpdateCompositableClient() {
if (!mData.mIsAlphaPremult) {
flags |= TextureFlags::NON_PREMULTIPLIED;
}
if ((provider && provider->WaitForRemoteTextureOwner()) ||
mData.mRemoteTextureOwnerId.isSome()) {
EnsurePipeline();
RefPtr<FwdTransactionTracker> tracker =
context->UseCompositableForwarder(forwarder);
if (tracker) {
flags |= TextureFlags::WAIT_FOR_REMOTE_TEXTURE_OWNER;
}
EnsurePipeline();
forwarder->UseRemoteTexture(mCanvasClient, textureDesc.textureId(),
textureDesc.ownerId(), mData.mSize, flags);
if (provider) {
provider->UseCompositableForwarder(forwarder);
}
textureDesc.ownerId(), mData.mSize, flags,
tracker);
FireDidTransactionCallback();
return;
}

View File

@@ -55,6 +55,7 @@ namespace layers {
class AndroidHardwareBufferTextureData;
class BufferTextureData;
class CompositableForwarder;
class FwdTransactionTracker;
class KnowsCompositor;
class LayersIPCChannel;
class CompositableClient;
@@ -330,7 +331,10 @@ class TextureData {
virtual bool RequiresRefresh() const { return false; }
virtual void UseCompositableForwarder(CompositableForwarder* aForwarder) {}
virtual already_AddRefed<FwdTransactionTracker> UseCompositableForwarder(
CompositableForwarder* aForwarder) {
return nullptr;
}
protected:
MOZ_COUNTED_DEFAULT_CTOR(TextureData)

View File

@@ -32,8 +32,9 @@ RecordedTextureData::~RecordedTextureData() {
// because the TextureData might need to destroy its DrawTarget within a lock.
mDT = nullptr;
mCanvasChild->CleanupTexture(mTextureId);
mCanvasChild->RecordEvent(
RecordedTextureDestruction(mTextureId, mLastTxnType, mLastTxnId));
mCanvasChild->RecordEvent(RecordedTextureDestruction(
mTextureId, ToRemoteTextureTxnType(mFwdTransactionTracker),
ToRemoteTextureTxnId(mFwdTransactionTracker)));
}
void RecordedTextureData::FillInfo(TextureData::Info& aInfo) const {
@@ -168,10 +169,10 @@ bool RecordedTextureData::Serialize(SurfaceDescriptor& aDescriptor) {
return true;
}
void RecordedTextureData::UseCompositableForwarder(
already_AddRefed<FwdTransactionTracker>
RecordedTextureData::UseCompositableForwarder(
CompositableForwarder* aForwarder) {
mLastTxnType = (RemoteTextureTxnType)aForwarder->GetFwdTransactionType();
mLastTxnId = (RemoteTextureTxnId)aForwarder->GetFwdTransactionId();
return FwdTransactionTracker::GetOrCreate(mFwdTransactionTracker);
}
void RecordedTextureData::OnForwardedToHost() {

View File

@@ -49,7 +49,8 @@ class RecordedTextureData final : public TextureData {
bool RequiresRefresh() const final;
void UseCompositableForwarder(CompositableForwarder* aForwarder) final;
already_AddRefed<FwdTransactionTracker> UseCompositableForwarder(
CompositableForwarder* aForwarder) final;
private:
DISALLOW_COPY_AND_ASSIGN(RecordedTextureData);
@@ -66,8 +67,7 @@ class RecordedTextureData final : public TextureData {
OpenMode mLockedMode;
RemoteTextureId mLastRemoteTextureId;
RemoteTextureOwnerId mRemoteTextureOwnerId;
RemoteTextureTxnType mLastTxnType = 0;
RemoteTextureTxnId mLastTxnId = 0;
RefPtr<layers::FwdTransactionTracker> mFwdTransactionTracker;
bool mUsedRemoteTexture = false;
bool mInvalidContents = true;
};

View File

@@ -959,9 +959,9 @@ void CanvasTranslator::RemoveTexture(int64_t aTextureId,
return;
}
auto& info = result->second;
if (aTxnType && aTxnId) {
RemoteTextureMap::Get()->WaitForTxn(info.mRemoteTextureOwnerId, mOtherPid,
aTxnType, aTxnId);
if (mRemoteTextureOwner && aTxnType && aTxnId) {
mRemoteTextureOwner->WaitForTxn(info.mRemoteTextureOwnerId, aTxnType,
aTxnId);
}
if (--info.mLocked > 0) {
return;

View File

@@ -9,6 +9,7 @@
#include <stdint.h> // for int32_t, uint32_t, uint64_t
#include "mozilla/Assertions.h" // for AssertionConditionType, MOZ_ASSERT, MOZ_ASSERT_HELPER1
#include "mozilla/Atomics.h"
#include "mozilla/RefPtr.h" // for RefPtr
#include "mozilla/TimeStamp.h" // for TimeStamp
#include "mozilla/ipc/ProtocolUtils.h" // for IToplevelProtocol, ProtocolID
@@ -54,6 +55,48 @@ struct FwdTransactionCounter {
uint64_t mFwdTransactionId = 0;
};
/**
* FwdTransactionTracker is to be used by CompositableForwarder consumers that
* must remember the last transaction in which they were used.
*/
class FwdTransactionTracker {
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(FwdTransactionTracker)
static already_AddRefed<FwdTransactionTracker> GetOrCreate(
RefPtr<FwdTransactionTracker>& aTracker) {
if (!aTracker) {
aTracker = new FwdTransactionTracker;
}
return do_AddRef(aTracker);
}
bool IsUsed() const { return mFwdTransactionType && mFwdTransactionId; }
void Use(const FwdTransactionCounter& aCounter) {
mFwdTransactionType = aCounter.mFwdTransactionType;
mFwdTransactionId = aCounter.mFwdTransactionId;
}
Atomic<mozilla::ipc::ProtocolId> mFwdTransactionType{
(mozilla::ipc::ProtocolId)0};
Atomic<uint64_t> mFwdTransactionId{0};
private:
FwdTransactionTracker() = default;
~FwdTransactionTracker() = default;
};
inline RemoteTextureTxnType ToRemoteTextureTxnType(
const RefPtr<FwdTransactionTracker>& aTracker) {
return aTracker ? (RemoteTextureTxnType)aTracker->mFwdTransactionType : 0;
}
inline RemoteTextureTxnId ToRemoteTextureTxnId(
const RefPtr<FwdTransactionTracker>& aTracker) {
return aTracker ? (RemoteTextureTxnId)aTracker->mFwdTransactionId : 0;
}
/**
* A transaction is a set of changes that happenned on the content side, that
* should be sent to the compositor side.
@@ -111,11 +154,11 @@ class CompositableForwarder : public KnowsCompositor {
virtual void UseTextures(CompositableClient* aCompositable,
const nsTArray<TimedTextureClient>& aTextures) = 0;
virtual void UseRemoteTexture(CompositableClient* aCompositable,
const RemoteTextureId aTextureId,
const RemoteTextureOwnerId aOwnerId,
const gfx::IntSize aSize,
const TextureFlags aFlags) = 0;
virtual void UseRemoteTexture(
CompositableClient* aCompositable, const RemoteTextureId aTextureId,
const RemoteTextureOwnerId aOwnerId, const gfx::IntSize aSize,
const TextureFlags aFlags,
const RefPtr<layers::FwdTransactionTracker>& aTracker) = 0;
void UpdateFwdTransactionId() {
++GetFwdTransactionCounter().mFwdTransactionId;
@@ -134,6 +177,12 @@ class CompositableForwarder : public KnowsCompositor {
protected:
virtual FwdTransactionCounter& GetFwdTransactionCounter() = 0;
void TrackFwdTransaction(const RefPtr<FwdTransactionTracker>& aTracker) {
if (aTracker) {
aTracker->Use(GetFwdTransactionCounter());
}
}
nsTArray<RefPtr<TextureClient>> mTexturesToRemove;
nsTArray<RefPtr<CompositableClient>> mCompositableClientsToRemove;
};

View File

@@ -119,11 +119,10 @@ void ImageBridgeChild::UseTextures(
OpUseTexture(textures)));
}
void ImageBridgeChild::UseRemoteTexture(CompositableClient* aCompositable,
const RemoteTextureId aTextureId,
const RemoteTextureOwnerId aOwnerId,
const gfx::IntSize aSize,
const TextureFlags aFlags) {
void ImageBridgeChild::UseRemoteTexture(
CompositableClient* aCompositable, const RemoteTextureId aTextureId,
const RemoteTextureOwnerId aOwnerId, const gfx::IntSize aSize,
const TextureFlags aFlags, const RefPtr<FwdTransactionTracker>& aTracker) {
MOZ_ASSERT(aCompositable);
MOZ_ASSERT(aCompositable->GetIPCHandle());
MOZ_ASSERT(aCompositable->IsConnected());
@@ -131,6 +130,7 @@ void ImageBridgeChild::UseRemoteTexture(CompositableClient* aCompositable,
mTxn->AddNoSwapEdit(CompositableOperation(
aCompositable->GetIPCHandle(),
OpUseRemoteTexture(aTextureId, aOwnerId, aSize, aFlags)));
TrackFwdTransaction(aTracker);
}
void ImageBridgeChild::HoldUntilCompositableRefReleasedIfNecessary(
@@ -322,7 +322,7 @@ void ImageBridgeChild::UpdateImageClient(RefPtr<ImageContainer> aContainer) {
void ImageBridgeChild::UpdateCompositable(
const RefPtr<ImageContainer> aContainer, const RemoteTextureId aTextureId,
const RemoteTextureOwnerId aOwnerId, const gfx::IntSize aSize,
const TextureFlags aFlags) {
const TextureFlags aFlags, const RefPtr<FwdTransactionTracker> aTracker) {
if (!aContainer) {
return;
}
@@ -330,7 +330,7 @@ void ImageBridgeChild::UpdateCompositable(
if (!InImageBridgeChildThread()) {
RefPtr<Runnable> runnable = WrapRunnable(
RefPtr<ImageBridgeChild>(this), &ImageBridgeChild::UpdateCompositable,
aContainer, aTextureId, aOwnerId, aSize, aFlags);
aContainer, aTextureId, aOwnerId, aSize, aFlags, aTracker);
GetThread()->Dispatch(runnable.forget());
return;
}
@@ -351,7 +351,7 @@ void ImageBridgeChild::UpdateCompositable(
}
BeginTransaction();
UseRemoteTexture(client, aTextureId, aOwnerId, aSize, aFlags);
UseRemoteTexture(client, aTextureId, aOwnerId, aSize, aFlags, aTracker);
EndTransaction();
}

View File

@@ -200,7 +200,8 @@ class ImageBridgeChild final : public PImageBridgeChild,
void UpdateCompositable(const RefPtr<ImageContainer> aContainer,
const RemoteTextureId aTextureId,
const RemoteTextureOwnerId aOwnerId,
const gfx::IntSize aSize, const TextureFlags aFlags);
const gfx::IntSize aSize, const TextureFlags aFlags,
const RefPtr<FwdTransactionTracker> aTracker);
/**
* Flush all Images sent to CompositableHost.
@@ -251,8 +252,8 @@ class ImageBridgeChild final : public PImageBridgeChild,
void UseRemoteTexture(CompositableClient* aCompositable,
const RemoteTextureId aTextureId,
const RemoteTextureOwnerId aOwnerId,
const gfx::IntSize aSize,
const TextureFlags aFlags) override;
const gfx::IntSize aSize, const TextureFlags aFlags,
const RefPtr<FwdTransactionTracker>& aTracker) override;
void ReleaseCompositable(const CompositableHandle& aHandle) override;

View File

@@ -442,14 +442,14 @@ void WebRenderBridgeChild::UseTextures(
OpUseTexture(textures)));
}
void WebRenderBridgeChild::UseRemoteTexture(CompositableClient* aCompositable,
const RemoteTextureId aTextureId,
const RemoteTextureOwnerId aOwnerId,
const gfx::IntSize aSize,
const TextureFlags aFlags) {
void WebRenderBridgeChild::UseRemoteTexture(
CompositableClient* aCompositable, const RemoteTextureId aTextureId,
const RemoteTextureOwnerId aOwnerId, const gfx::IntSize aSize,
const TextureFlags aFlags, const RefPtr<FwdTransactionTracker>& aTracker) {
AddWebRenderParentCommand(CompositableOperation(
aCompositable->GetIPCHandle(),
OpUseRemoteTexture(aTextureId, aOwnerId, aSize, aFlags)));
TrackFwdTransaction(aTracker);
}
FwdTransactionCounter& WebRenderBridgeChild::GetFwdTransactionCounter() {

View File

@@ -200,8 +200,8 @@ class WebRenderBridgeChild final : public PWebRenderBridgeChild,
void UseRemoteTexture(CompositableClient* aCompositable,
const RemoteTextureId aTextureId,
const RemoteTextureOwnerId aOwnerId,
const gfx::IntSize aSize,
const TextureFlags aFlags) override;
const gfx::IntSize aSize, const TextureFlags aFlags,
const RefPtr<FwdTransactionTracker>& aTracker) override;
FwdTransactionCounter& GetFwdTransactionCounter() override;
bool InForwarderThread() override;