summaryrefslogtreecommitdiffstats
path: root/gfx/layers/RemoteTextureMap.h
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--gfx/layers/RemoteTextureMap.h486
1 files changed, 486 insertions, 0 deletions
diff --git a/gfx/layers/RemoteTextureMap.h b/gfx/layers/RemoteTextureMap.h
new file mode 100644
index 0000000000..a60bfd4c3c
--- /dev/null
+++ b/gfx/layers/RemoteTextureMap.h
@@ -0,0 +1,486 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef MOZILLA_GFX_RemoteTextureMap_H
+#define MOZILLA_GFX_RemoteTextureMap_H
+
+#include <deque>
+#include <functional>
+#include <list>
+#include <map>
+#include <memory>
+#include <queue>
+#include <unordered_set>
+#include <utility>
+
+#include "mozilla/gfx/Point.h" // for IntSize
+#include "mozilla/gfx/Types.h" // for SurfaceFormat
+#include "mozilla/ipc/Shmem.h"
+#include "mozilla/layers/CompositorTypes.h" // for TextureFlags, etc
+#include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor
+#include "mozilla/layers/TextureHost.h"
+#include "mozilla/Monitor.h"
+#include "mozilla/StaticPtr.h"
+#include "mozilla/ThreadSafeWeakPtr.h"
+#include "mozilla/UniquePtr.h"
+#include "mozilla/webrender/WebRenderTypes.h"
+
+class nsISerialEventTarget;
+
+namespace mozilla {
+
+namespace ipc {
+class IProtocol;
+}
+
+namespace gl {
+class SharedSurface;
+}
+
+namespace webgpu {
+class ExternalTexture;
+}
+
+namespace layers {
+
+class CompositableHost;
+class RemoteTextureHostWrapper;
+class TextureData;
+class TextureHost;
+
+struct RemoteTextureInfo {
+ RemoteTextureInfo(const RemoteTextureId aTextureId,
+ const RemoteTextureOwnerId aOwnerId,
+ const base::ProcessId aForPid)
+ : mTextureId(aTextureId), mOwnerId(aOwnerId), mForPid(aForPid) {}
+
+ const RemoteTextureId mTextureId;
+ const RemoteTextureOwnerId mOwnerId;
+ const base::ProcessId mForPid;
+};
+
+struct RemoteTextureInfoList {
+ std::queue<RemoteTextureInfo> mList;
+};
+
+class SharedResourceWrapper {
+ public:
+ enum class Tag { SharedSurface, ExternalTexture };
+ const Tag mTag;
+
+ static UniquePtr<SharedResourceWrapper> SharedSurface(
+ const std::shared_ptr<gl::SharedSurface>& aSharedSurface) {
+ return MakeUnique<SharedResourceWrapper>(Tag::SharedSurface,
+ aSharedSurface);
+ }
+
+ static UniquePtr<SharedResourceWrapper> ExternalTexture(
+ const std::shared_ptr<webgpu::ExternalTexture>& aExternalTexture) {
+ return MakeUnique<SharedResourceWrapper>(Tag::ExternalTexture,
+ aExternalTexture);
+ }
+
+ SharedResourceWrapper(
+ const Tag aTag, const std::shared_ptr<gl::SharedSurface>& aSharedSurface)
+ : mTag(aTag), mSharedSurface(aSharedSurface) {
+ MOZ_ASSERT(mTag == Tag::SharedSurface);
+ }
+ SharedResourceWrapper(
+ const Tag aTag,
+ const std::shared_ptr<webgpu::ExternalTexture>& aExternalTexture)
+ : mTag(aTag), mExternalTexture(aExternalTexture) {
+ MOZ_ASSERT(mTag == Tag::ExternalTexture);
+ }
+
+ const std::shared_ptr<gl::SharedSurface> mSharedSurface;
+ const std::shared_ptr<webgpu::ExternalTexture> mExternalTexture;
+
+ std::shared_ptr<gl::SharedSurface> SharedSurface() {
+ if (mTag == Tag::SharedSurface) {
+ return mSharedSurface;
+ }
+ MOZ_ASSERT_UNREACHABLE("unexpected to be called");
+ return nullptr;
+ }
+
+ std::shared_ptr<webgpu::ExternalTexture> ExternalTexture() {
+ if (mTag == Tag::ExternalTexture) {
+ return mExternalTexture;
+ }
+ MOZ_ASSERT_UNREACHABLE("unexpected to be called");
+ return nullptr;
+ }
+};
+
+class RemoteTextureRecycleBin final {
+ public:
+ NS_INLINE_DECL_THREADSAFE_REFCOUNTING(RemoteTextureRecycleBin)
+
+ explicit RemoteTextureRecycleBin(bool aIsShared);
+
+ private:
+ friend class RemoteTextureMap;
+
+ ~RemoteTextureRecycleBin();
+
+ struct RecycledTextureHolder {
+ gfx::IntSize mSize;
+ gfx::SurfaceFormat mFormat = gfx::SurfaceFormat::UNKNOWN;
+ SurfaceDescriptor::Type mType = SurfaceDescriptor::Tnull_t;
+ UniquePtr<TextureData> mTextureData;
+ UniquePtr<SharedResourceWrapper> mResourceWrapper;
+ };
+
+ bool mIsShared = false;
+ 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)
+
+ static already_AddRefed<RemoteTextureTxnScheduler> Create(
+ mozilla::ipc::IProtocol* aProtocol);
+
+ 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;
+};
+
+typedef std::unordered_set<RemoteTextureOwnerId, RemoteTextureOwnerId::HashFn>
+ RemoteTextureOwnerIdSet;
+
+/**
+ * A class provides API for remote texture owners.
+ */
+class RemoteTextureOwnerClient final {
+ public:
+ NS_INLINE_DECL_THREADSAFE_REFCOUNTING(RemoteTextureOwnerClient)
+
+ explicit RemoteTextureOwnerClient(const base::ProcessId aForPid);
+
+ bool IsRegistered(const RemoteTextureOwnerId aOwnerId);
+ void RegisterTextureOwner(const RemoteTextureOwnerId aOwnerId,
+ 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(
+ const RemoteTextureOwnerIdSet* aOwnerIds = nullptr);
+ void PushTexture(const RemoteTextureId aTextureId,
+ const RemoteTextureOwnerId aOwnerId,
+ UniquePtr<TextureData>&& aTextureData);
+ void PushTexture(const RemoteTextureId aTextureId,
+ const RemoteTextureOwnerId aOwnerId,
+ const std::shared_ptr<gl::SharedSurface>& aSharedSurface,
+ const gfx::IntSize& aSize, gfx::SurfaceFormat aFormat,
+ const SurfaceDescriptor& aDesc);
+ void PushTexture(
+ const RemoteTextureId aTextureId, const RemoteTextureOwnerId aOwnerId,
+ const std::shared_ptr<webgpu::ExternalTexture>& aExternalTexture,
+ const gfx::IntSize& aSize, gfx::SurfaceFormat aFormat,
+ const SurfaceDescriptor& aDesc);
+ void PushDummyTexture(const RemoteTextureId aTextureId,
+ const RemoteTextureOwnerId aOwnerId);
+ void GetLatestBufferSnapshot(const RemoteTextureOwnerId aOwnerId,
+ const mozilla::ipc::Shmem& aDestShmem,
+ const gfx::IntSize& aSize);
+ UniquePtr<TextureData> GetRecycledTextureData(
+ const gfx::IntSize& aSize, gfx::SurfaceFormat aFormat,
+ TextureType aTextureType,
+ RemoteTextureOwnerId aOwnerId = RemoteTextureOwnerId());
+ UniquePtr<TextureData> CreateOrRecycleBufferTextureData(
+ const gfx::IntSize& aSize, gfx::SurfaceFormat aFormat,
+ RemoteTextureOwnerId aOwnerId = RemoteTextureOwnerId());
+ std::shared_ptr<gl::SharedSurface> GetRecycledSharedSurface(
+ const gfx::IntSize& aSize, gfx::SurfaceFormat aFormat,
+ SurfaceDescriptor::Type aType,
+ RemoteTextureOwnerId aOwnerId = RemoteTextureOwnerId());
+ std::shared_ptr<webgpu::ExternalTexture> GetRecycledExternalTexture(
+ const gfx::IntSize& aSize, gfx::SurfaceFormat aFormat,
+ SurfaceDescriptor::Type aType,
+ RemoteTextureOwnerId aOwnerId = RemoteTextureOwnerId());
+
+ const base::ProcessId mForPid;
+
+ protected:
+ ~RemoteTextureOwnerClient();
+
+ RemoteTextureOwnerIdSet mOwnerIds;
+ RefPtr<RemoteTextureRecycleBin> mSharedRecycleBin;
+};
+
+/**
+ * A class to map RemoteTextureId to remote texture(TextureHost).
+ * Remote textures are provided by texture owner.
+ */
+class RemoteTextureMap {
+ public:
+ static void Init();
+ static void Shutdown();
+ static RemoteTextureMap* Get() { return sInstance; }
+
+ RemoteTextureMap();
+ ~RemoteTextureMap();
+
+ // Push remote texture data and gl::SharedSurface from texture owner.
+ // The texture data is used for creating TextureHost.
+ // gl::SharedSurface is pushed only when the surface needs to be kept alive
+ // during TextureHost usage. The texture data and the surface might be
+ // recycled when TextureHost is destroyed.
+ void PushTexture(const RemoteTextureId aTextureId,
+ const RemoteTextureOwnerId aOwnerId,
+ const base::ProcessId aForPid,
+ UniquePtr<TextureData>&& aTextureData,
+ RefPtr<TextureHost>& aTextureHost,
+ UniquePtr<SharedResourceWrapper>&& aResourceWrapper);
+
+ // Remove waiting texture that will not be used.
+ bool RemoveTexture(const RemoteTextureId aTextureId,
+ const RemoteTextureOwnerId aOwnerId,
+ const base::ProcessId aForPid);
+
+ void GetLatestBufferSnapshot(const RemoteTextureOwnerId aOwnerId,
+ const base::ProcessId aForPid,
+ const mozilla::ipc::Shmem& aDestShmem,
+ const gfx::IntSize& aSize);
+
+ void RegisterTextureOwner(
+ const RemoteTextureOwnerId aOwnerId, const base::ProcessId aForPid,
+ const RefPtr<RemoteTextureRecycleBin>& aRecycleBin = nullptr);
+ void UnregisterTextureOwner(const RemoteTextureOwnerId aOwnerId,
+ const base::ProcessId aForPid);
+ void UnregisterTextureOwners(const RemoteTextureOwnerIdSet& aOwnerIds,
+ const base::ProcessId aForPid);
+
+ void ClearRecycledTextures(
+ const RemoteTextureOwnerIdSet& aOwnerIds, const base::ProcessId aForPid,
+ const RefPtr<RemoteTextureRecycleBin>& aRecycleBin = nullptr);
+ void NotifyContextLost(const RemoteTextureOwnerIdSet& aOwnerIds,
+ const base::ProcessId aForPid);
+ void NotifyContextRestored(const RemoteTextureOwnerIdSet& aOwnerIds,
+ const base::ProcessId aForPid);
+
+ // Get remote texture's TextureHost for RemoteTextureHostWrapper.
+ //
+ // return true when aReadyCallback will be called.
+ bool GetRemoteTexture(
+ RemoteTextureHostWrapper* aTextureHostWrapper,
+ 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(
+ const RemoteTextureId aTextureId, const RemoteTextureOwnerId aOwnerId,
+ const base::ProcessId aForPid, const gfx::IntSize& aSize,
+ const TextureFlags aFlags);
+
+ void UnregisterRemoteTextureHostWrapper(const RemoteTextureId aTextureId,
+ const RemoteTextureOwnerId aOwnerId,
+ const base::ProcessId aForPid);
+
+ bool CheckRemoteTextureReady(
+ const RemoteTextureInfo& aInfo,
+ std::function<void(const RemoteTextureInfo&)>&& aCallback);
+
+ bool WaitRemoteTextureReady(const RemoteTextureInfo& aInfo);
+
+ void SuppressRemoteTextureReadyCheck(const RemoteTextureId aTextureId,
+ const base::ProcessId aForPid);
+
+ UniquePtr<TextureData> GetRecycledTextureData(
+ const RemoteTextureOwnerId aOwnerId, const base::ProcessId aForPid,
+ const RefPtr<RemoteTextureRecycleBin>& aRecycleBin,
+ const gfx::IntSize& aSize, gfx::SurfaceFormat aFormat,
+ TextureType aTextureType);
+
+ UniquePtr<SharedResourceWrapper> GetRecycledSharedTexture(
+ const RemoteTextureOwnerId aOwnerId, const base::ProcessId aForPid,
+ const RefPtr<RemoteTextureRecycleBin>& aRecycleBin,
+ const gfx::IntSize& aSize, gfx::SurfaceFormat aFormat,
+ SurfaceDescriptor::Type aType);
+
+ static RefPtr<TextureHost> CreateRemoteTexture(TextureData* aTextureData,
+ TextureFlags aTextureFlags);
+
+ already_AddRefed<RemoteTextureTxnScheduler> RegisterTxnScheduler(
+ base::ProcessId aForPid, RemoteTextureTxnType aType);
+
+ protected:
+ friend class RemoteTextureTxnScheduler;
+
+ // Holds data related to remote texture
+ struct TextureDataHolder {
+ TextureDataHolder(const RemoteTextureId aTextureId,
+ RefPtr<TextureHost> aTextureHost,
+ UniquePtr<TextureData>&& aTextureData,
+ UniquePtr<SharedResourceWrapper>&& aResourceWrapper);
+
+ const RemoteTextureId mTextureId;
+ // TextureHost of remote texture
+ // Compositable ref of the mTextureHost should be updated within mMonitor.
+ // The compositable ref is used to check if TextureHost(remote texture) is
+ // still in use by WebRender.
+ RefPtr<TextureHost> mTextureHost;
+ // Holds BufferTextureData of TextureHost
+ UniquePtr<TextureData> mTextureData;
+ // Holds gl::SharedSurface of TextureHost
+ UniquePtr<SharedResourceWrapper> mResourceWrapper;
+ };
+
+ struct RenderingReadyCallbackHolder {
+ RenderingReadyCallbackHolder(
+ const RemoteTextureId aTextureId,
+ std::function<void(const RemoteTextureInfo&)>&& aCallback);
+
+ const RemoteTextureId mTextureId;
+ // callback of RemoteTexture ready
+ std::function<void(const RemoteTextureInfo&)> mCallback;
+ };
+
+ 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;
+ // Holds TextureDataHolders that are used for building wr display list.
+ std::deque<UniquePtr<TextureDataHolder>> mUsingTextureDataHolders;
+ std::deque<UniquePtr<TextureDataHolder>> mReleasingTextureDataHolders;
+ // Holds RemoteTexture ready callbacks.
+ std::deque<UniquePtr<RenderingReadyCallbackHolder>>
+ mRenderingReadyCallbackHolders;
+
+ RemoteTextureId mLatestTextureId = {0};
+ CompositableTextureHostRef mLatestTextureHost;
+ CompositableTextureHostRef mLatestRenderedTextureHost;
+ // Holds compositable refs to TextureHosts of RenderTextureHosts that are
+ // waiting to be released in non-RenderThread.
+ std::deque<CompositableTextureHostRef> mReleasingRenderedTextureHosts;
+ RefPtr<RemoteTextureRecycleBin> mRecycleBin;
+ };
+
+ // Holds data related to remote texture wrapper
+ struct RemoteTextureHostWrapperHolder {
+ explicit RemoteTextureHostWrapperHolder(
+ RefPtr<TextureHost> aRemoteTextureHostWrapper);
+
+ const RefPtr<TextureHost> mRemoteTextureHostWrapper;
+ // Hold compositable ref of remote texture of the RemoteTextureId.
+ CompositableTextureHostRef mRemoteTextureHost;
+ bool mReadyCheckSuppressed = false;
+ };
+
+ void UpdateTexture(const MonitorAutoLock& aProofOfLock,
+ RemoteTextureMap::TextureOwner* aOwner,
+ const RemoteTextureId aTextureId);
+
+ UniquePtr<TextureOwner> UnregisterTextureOwner(
+ MonitorAutoLock& aProofOfLock, const RemoteTextureOwnerId aOwnerId,
+ const base::ProcessId aForPid,
+ std::vector<RefPtr<TextureHost>>& aReleasingTextures,
+ std::vector<std::function<void(const RemoteTextureInfo&)>>&
+ aRenderingReadyCallbacks);
+
+ 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,
+ RemoteTextureMap::TextureOwner* aOwner,
+ std::deque<UniquePtr<TextureDataHolder>>& aHolders);
+
+ bool RecycleTexture(const RefPtr<RemoteTextureRecycleBin>& aRecycleBin,
+ TextureDataHolder& aHolder, bool aExpireOldTextures);
+
+ RemoteTextureMap::TextureOwner* GetTextureOwner(
+ 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>,
+ UniquePtr<TextureOwner>>
+ mTextureOwners;
+
+ std::map<std::pair<base::ProcessId, RemoteTextureId>,
+ UniquePtr<RemoteTextureHostWrapperHolder>>
+ mRemoteTextureHostWrapperHolders;
+
+ std::map<std::pair<base::ProcessId, RemoteTextureTxnType>,
+ RemoteTextureTxnScheduler*>
+ mTxnSchedulers;
+
+ static StaticAutoPtr<RemoteTextureMap> sInstance;
+};
+
+} // namespace layers
+} // namespace mozilla
+
+#endif // MOZILLA_GFX_RemoteTextureMap_H