forked from mirrors/gecko-dev
Bug 1869346 - Rework how canvas accesses shared surfaces in the compositor process. r=gfx-reviewers,lsalzman
This patch adds plumbing to allow sharing ExternalImageId via SurfaceDescriptor. This will be used in a future patch by WebGL and WebGPU to avoid extra copies. It also refactors how CanvasTranslator gets a SourceSurfaceSharedDataWrapper pointer by ensuring the surfaces are kept alive long enough even if the CompositorManagerParent actor is destroyed before CanvasManagerParent and its children. Now we keep the surfaces around until all of these dependent objects have been freed. Differential Revision: https://phabricator.services.mozilla.com/D196067
This commit is contained in:
parent
58a3a1839f
commit
e96409bd27
13 changed files with 114 additions and 15 deletions
|
|
@ -14,6 +14,7 @@
|
|||
#include "mozilla/layers/CanvasTranslator.h"
|
||||
#include "mozilla/layers/CompositorThread.h"
|
||||
#include "mozilla/layers/ISurfaceAllocator.h"
|
||||
#include "mozilla/layers/SharedSurfacesParent.h"
|
||||
#include "mozilla/webgpu/WebGPUParent.h"
|
||||
#include "nsIThread.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
|
@ -29,10 +30,12 @@ bool CanvasManagerParent::sReplayTexturesEnabled(true);
|
|||
|
||||
/* static */ void CanvasManagerParent::Init(
|
||||
Endpoint<PCanvasManagerParent>&& aEndpoint,
|
||||
layers::SharedSurfacesHolder* aSharedSurfacesHolder,
|
||||
const dom::ContentParentId& aContentId) {
|
||||
MOZ_ASSERT(layers::CompositorThreadHolder::IsInCompositorThread());
|
||||
|
||||
auto manager = MakeRefPtr<CanvasManagerParent>(aContentId);
|
||||
auto manager =
|
||||
MakeRefPtr<CanvasManagerParent>(aSharedSurfacesHolder, aContentId);
|
||||
|
||||
nsCOMPtr<nsIThread> owningThread =
|
||||
gfx::CanvasRenderThread::GetCanvasRenderThread();
|
||||
|
|
@ -220,8 +223,10 @@ CanvasManagerParent::WaitForReplayTexture(layers::HostIPCAllocator* aAllocator,
|
|||
return desc;
|
||||
}
|
||||
|
||||
CanvasManagerParent::CanvasManagerParent(const dom::ContentParentId& aContentId)
|
||||
: mContentId(aContentId) {}
|
||||
CanvasManagerParent::CanvasManagerParent(
|
||||
layers::SharedSurfacesHolder* aSharedSurfacesHolder,
|
||||
const dom::ContentParentId& aContentId)
|
||||
: mSharedSurfacesHolder(aSharedSurfacesHolder), mContentId(aContentId) {}
|
||||
|
||||
CanvasManagerParent::~CanvasManagerParent() = default;
|
||||
|
||||
|
|
@ -273,7 +278,8 @@ mozilla::ipc::IPCResult CanvasManagerParent::RecvInitialize(
|
|||
already_AddRefed<layers::PCanvasParent>
|
||||
CanvasManagerParent::AllocPCanvasParent() {
|
||||
MOZ_RELEASE_ASSERT(mId != 0);
|
||||
return MakeAndAddRef<layers::CanvasTranslator>(mContentId, mId);
|
||||
return MakeAndAddRef<layers::CanvasTranslator>(mSharedSurfacesHolder,
|
||||
mContentId, mId);
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult CanvasManagerParent::RecvGetSnapshot(
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ namespace mozilla {
|
|||
namespace layers {
|
||||
class CanvasTranslator;
|
||||
class HostIPCAllocator;
|
||||
class SharedSurfacesHolder;
|
||||
class SurfaceDescriptor;
|
||||
} // namespace layers
|
||||
|
||||
|
|
@ -27,6 +28,7 @@ class CanvasManagerParent final : public PCanvasManagerParent {
|
|||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CanvasManagerParent, override);
|
||||
|
||||
static void Init(Endpoint<PCanvasManagerParent>&& aEndpoint,
|
||||
layers::SharedSurfacesHolder* aSharedSurfacesHolder,
|
||||
const dom::ContentParentId& aContentId);
|
||||
|
||||
static void Shutdown();
|
||||
|
|
@ -45,7 +47,8 @@ class CanvasManagerParent final : public PCanvasManagerParent {
|
|||
static UniquePtr<layers::SurfaceDescriptor> WaitForReplayTexture(
|
||||
layers::HostIPCAllocator* aAllocator, int64_t aTextureId);
|
||||
|
||||
explicit CanvasManagerParent(const dom::ContentParentId& aContentId);
|
||||
CanvasManagerParent(layers::SharedSurfacesHolder* aSharedSurfacesHolder,
|
||||
const dom::ContentParentId& aContentId);
|
||||
|
||||
void Bind(Endpoint<PCanvasManagerParent>&& aEndpoint);
|
||||
void ActorDestroy(ActorDestroyReason aWhy) override;
|
||||
|
|
@ -70,6 +73,7 @@ class CanvasManagerParent final : public PCanvasManagerParent {
|
|||
|
||||
~CanvasManagerParent() override;
|
||||
|
||||
RefPtr<layers::SharedSurfacesHolder> mSharedSurfacesHolder;
|
||||
const dom::ContentParentId mContentId;
|
||||
uint32_t mId = 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -50,9 +50,11 @@ TextureData* CanvasTranslator::CreateTextureData(TextureType aTextureType,
|
|||
return textureData;
|
||||
}
|
||||
|
||||
CanvasTranslator::CanvasTranslator(const dom::ContentParentId& aContentId,
|
||||
uint32_t aManagerId)
|
||||
: mMaxSpinCount(StaticPrefs::gfx_canvas_remote_max_spin_count()),
|
||||
CanvasTranslator::CanvasTranslator(
|
||||
layers::SharedSurfacesHolder* aSharedSurfacesHolder,
|
||||
const dom::ContentParentId& aContentId, uint32_t aManagerId)
|
||||
: mSharedSurfacesHolder(aSharedSurfacesHolder),
|
||||
mMaxSpinCount(StaticPrefs::gfx_canvas_remote_max_spin_count()),
|
||||
mContentId(aContentId),
|
||||
mManagerId(aManagerId) {
|
||||
mNextEventTimeout = TimeDuration::FromMilliseconds(
|
||||
|
|
@ -640,7 +642,7 @@ TextureData* CanvasTranslator::LookupTextureData(int64_t aTextureId) {
|
|||
|
||||
already_AddRefed<gfx::SourceSurface> CanvasTranslator::LookupExternalSurface(
|
||||
uint64_t aKey) {
|
||||
return SharedSurfacesParent::Get(wr::ToExternalImageId(aKey));
|
||||
return mSharedSurfacesHolder->Get(wr::ToExternalImageId(aKey));
|
||||
}
|
||||
|
||||
void CanvasTranslator::CheckpointReached() { CheckAndSignalWriter(); }
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ class TaskQueue;
|
|||
|
||||
namespace layers {
|
||||
|
||||
class SharedSurfacesHolder;
|
||||
class TextureData;
|
||||
|
||||
class CanvasTranslator final : public gfx::InlineTranslator,
|
||||
|
|
@ -37,7 +38,8 @@ class CanvasTranslator final : public gfx::InlineTranslator,
|
|||
|
||||
friend class PProtocolParent;
|
||||
|
||||
CanvasTranslator(const dom::ContentParentId& aContentId, uint32_t aManagerId);
|
||||
CanvasTranslator(layers::SharedSurfacesHolder* aSharedSurfacesHolder,
|
||||
const dom::ContentParentId& aContentId, uint32_t aManagerId);
|
||||
|
||||
const dom::ContentParentId& GetContentId() const { return mContentId; }
|
||||
|
||||
|
|
@ -292,6 +294,7 @@ class CanvasTranslator final : public gfx::InlineTranslator,
|
|||
void NotifyDeviceChanged();
|
||||
|
||||
RefPtr<TaskQueue> mTranslationTaskQueue;
|
||||
RefPtr<SharedSurfacesHolder> mSharedSurfacesHolder;
|
||||
#if defined(XP_WIN)
|
||||
RefPtr<ID3D11Device> mDevice;
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -117,6 +117,7 @@ CompositorManagerParent::CreateSameProcessWidgetCompositorBridge(
|
|||
CompositorManagerParent::CompositorManagerParent(
|
||||
dom::ContentParentId aContentId, uint32_t aNamespace)
|
||||
: mCompositorThreadHolder(CompositorThreadHolder::GetSingleton()),
|
||||
mSharedSurfacesHolder(MakeRefPtr<SharedSurfacesHolder>(aNamespace)),
|
||||
mContentId(aContentId),
|
||||
mNamespace(aNamespace) {}
|
||||
|
||||
|
|
@ -146,8 +147,6 @@ void CompositorManagerParent::BindComplete(bool aIsRoot) {
|
|||
}
|
||||
|
||||
void CompositorManagerParent::ActorDestroy(ActorDestroyReason aReason) {
|
||||
SharedSurfacesParent::RemoveAll(mNamespace);
|
||||
|
||||
GetCurrentSerialEventTarget()->Dispatch(
|
||||
NewRunnableMethod("layers::CompositorManagerParent::DeferredDestroy",
|
||||
this, &CompositorManagerParent::DeferredDestroy));
|
||||
|
|
@ -349,7 +348,8 @@ mozilla::ipc::IPCResult CompositorManagerParent::RecvReportMemory(
|
|||
|
||||
mozilla::ipc::IPCResult CompositorManagerParent::RecvInitCanvasManager(
|
||||
Endpoint<PCanvasManagerParent>&& aEndpoint) {
|
||||
gfx::CanvasManagerParent::Init(std::move(aEndpoint), mContentId);
|
||||
gfx::CanvasManagerParent::Init(std::move(aEndpoint), mSharedSurfacesHolder,
|
||||
mContentId);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ namespace layers {
|
|||
|
||||
class CompositorBridgeParent;
|
||||
class CompositorThreadHolder;
|
||||
class SharedSurfacesHolder;
|
||||
|
||||
class CompositorManagerParent final : public PCompositorManagerParent {
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CompositorManagerParent, final)
|
||||
|
|
@ -90,6 +91,7 @@ class CompositorManagerParent final : public PCompositorManagerParent {
|
|||
void DeferredDestroy();
|
||||
|
||||
RefPtr<CompositorThreadHolder> mCompositorThreadHolder;
|
||||
RefPtr<SharedSurfacesHolder> mSharedSurfacesHolder;
|
||||
AutoTArray<RefPtr<CompositorBridgeParent>, 1> mPendingCompositorBridges;
|
||||
const dom::ContentParentId mContentId;
|
||||
const uint32_t mNamespace;
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
include "gfxipc/ShadowLayerUtils.h";
|
||||
include "mozilla/GfxMessageUtils.h";
|
||||
include "mozilla/layers/LayersMessageUtils.h";
|
||||
include "mozilla/layers/WebRenderMessageUtils.h";
|
||||
|
||||
using gfxPoint from "gfxPoint.h";
|
||||
using nsIntRegion from "nsRegion.h";
|
||||
|
|
@ -27,6 +28,8 @@ using mozilla::layers::MaybeVideoBridgeSource from "mozilla/layers/VideoBridgeUt
|
|||
using mozilla::layers::RemoteTextureId from "mozilla/layers/LayersTypes.h";
|
||||
using mozilla::layers::RemoteTextureOwnerId from "mozilla/layers/LayersTypes.h";
|
||||
using mozilla::layers::GpuProcessTextureId from "mozilla/layers/LayersTypes.h";
|
||||
using mozilla::wr::ExternalImageSource from "mozilla/webrender/WebRenderTypes.h";
|
||||
using mozilla::wr::ExternalImageId from "mozilla/webrender/WebRenderTypes.h";
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
|
@ -178,6 +181,12 @@ namespace layers {
|
|||
Handle handle;
|
||||
};
|
||||
|
||||
[Comparable] struct SurfaceDescriptorExternalImage
|
||||
{
|
||||
ExternalImageSource source;
|
||||
ExternalImageId id;
|
||||
};
|
||||
|
||||
[Comparable] struct SurfaceDescriptorRecorded {
|
||||
int64_t textureId;
|
||||
};
|
||||
|
|
@ -201,6 +210,7 @@ namespace layers {
|
|||
SurfaceDescriptorRecorded;
|
||||
SurfaceDescriptorRemoteTexture;
|
||||
SurfaceDescriptorDcompSurface;
|
||||
SurfaceDescriptorExternalImage;
|
||||
null_t;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -350,6 +350,30 @@ nsresult SharedSurfacesChild::Share(SourceSurface* aSurface,
|
|||
return rv;
|
||||
}
|
||||
|
||||
/* static */ nsresult SharedSurfacesChild::Share(
|
||||
gfx::SourceSurface* aSurface, Maybe<SurfaceDescriptor>& aDesc) {
|
||||
if (!aSurface) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
// TODO(aosmond): With a refactor of how we store the external image ID, we
|
||||
// could probably make it safe to access off the main thread. This would be
|
||||
// useful for OffscreenCanvas on DOM workers.
|
||||
if (!NS_IsMainThread()) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
wr::ExternalImageId extId{};
|
||||
nsresult rv = Share(aSurface, extId);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
aDesc = Some(SurfaceDescriptorExternalImage(
|
||||
wr::ExternalImageSource::SharedSurfaces, extId));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* static */
|
||||
void SharedSurfacesChild::Unshare(const wr::ExternalImageId& aId,
|
||||
bool aReleaseId,
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
#include "mozilla/RefPtr.h" // for already_AddRefed
|
||||
#include "mozilla/StaticPtr.h" // for StaticRefPtr
|
||||
#include "mozilla/gfx/UserData.h" // for UserDataKey
|
||||
#include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor
|
||||
#include "mozilla/webrender/WebRenderTypes.h" // for wr::ImageKey
|
||||
#include "nsTArray.h" // for AutoTArray
|
||||
#include "nsThreadUtils.h" // for Runnable
|
||||
|
|
@ -64,6 +65,14 @@ class SharedSurfacesChild {
|
|||
*/
|
||||
static nsresult Share(gfx::SourceSurface* aSurface, wr::ExternalImageId& aId);
|
||||
|
||||
/**
|
||||
* Request that the surface be mapped into the compositor thread's memory
|
||||
* space, and a valid ExternalImageId be generated for it for use with
|
||||
* WebRender. This must be called from the main thread.
|
||||
*/
|
||||
static nsresult Share(gfx::SourceSurface* aSurface,
|
||||
Maybe<SurfaceDescriptor>& aDesc);
|
||||
|
||||
/**
|
||||
* Request that the surface be mapped into the compositor thread's memory
|
||||
* space, and a valid ImageKey be generated for it for use with WebRender.
|
||||
|
|
|
|||
|
|
@ -206,6 +206,8 @@ void SharedSurfacesParent::RemoveAll(uint32_t aNamespace) {
|
|||
return;
|
||||
}
|
||||
|
||||
auto* renderThread = wr::RenderThread::Get();
|
||||
|
||||
// Note that the destruction of a parent may not be cheap if it still has a
|
||||
// lot of surfaces still bound that require unmapping.
|
||||
for (auto i = sInstance->mSurfaces.Iter(); !i.Done(); i.Next()) {
|
||||
|
|
@ -217,8 +219,9 @@ void SharedSurfacesParent::RemoveAll(uint32_t aNamespace) {
|
|||
if (surface->HasCreatorRef() &&
|
||||
surface->RemoveConsumer(/* aForCreator */ true)) {
|
||||
RemoveTrackingLocked(surface, lock);
|
||||
wr::RenderThread::Get()->UnregisterExternalImage(
|
||||
wr::ToExternalImageId(i.Key()));
|
||||
if (renderThread) {
|
||||
renderThread->UnregisterExternalImage(wr::ToExternalImageId(i.Key()));
|
||||
}
|
||||
i.Remove();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -129,6 +129,33 @@ class SharedSurfacesParent final {
|
|||
MappingTracker mTracker;
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper class that is used to keep SourceSurfaceSharedDataWrapper objects
|
||||
* around as long as one of the dependent IPDL actors is still alive and may
|
||||
* reference them for a given PCompositorManager namespace.
|
||||
*/
|
||||
class SharedSurfacesHolder final {
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(SharedSurfacesHolder)
|
||||
|
||||
public:
|
||||
explicit SharedSurfacesHolder(uint32_t aNamespace) : mNamespace(aNamespace) {}
|
||||
|
||||
already_AddRefed<gfx::DataSourceSurface> Get(const wr::ExternalImageId& aId) {
|
||||
uint32_t extNamespace = static_cast<uint32_t>(wr::AsUint64(aId) >> 32);
|
||||
if (NS_WARN_IF(extNamespace != mNamespace)) {
|
||||
MOZ_ASSERT_UNREACHABLE("Wrong namespace?");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return SharedSurfacesParent::Get(aId);
|
||||
}
|
||||
|
||||
private:
|
||||
~SharedSurfacesHolder() { SharedSurfacesParent::RemoveAll(mNamespace); }
|
||||
|
||||
uint32_t mNamespace;
|
||||
};
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
||||
|
|
|
|||
|
|
@ -218,6 +218,13 @@ template <>
|
|||
struct ParamTraits<mozilla::wr::RenderReasons>
|
||||
: public PlainOldDataSerializer<mozilla::wr::RenderReasons> {};
|
||||
|
||||
template <>
|
||||
struct ParamTraits<mozilla::wr::ExternalImageSource>
|
||||
: public ContiguousEnumSerializer<mozilla::wr::ExternalImageSource,
|
||||
mozilla::wr::ExternalImageSource::Unknown,
|
||||
mozilla::wr::ExternalImageSource::Last> {
|
||||
};
|
||||
|
||||
} // namespace IPC
|
||||
|
||||
#endif // GFX_WEBRENDERMESSAGEUTILS_H
|
||||
|
|
|
|||
|
|
@ -903,6 +903,8 @@ static inline wr::HasScrollLinkedEffect ToWrHasScrollLinkedEffect(
|
|||
: wr::HasScrollLinkedEffect::No;
|
||||
}
|
||||
|
||||
enum class ExternalImageSource : uint8_t { Unknown = 0, SharedSurfaces, Last };
|
||||
|
||||
} // namespace wr
|
||||
} // namespace mozilla
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue