/* -*- 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 GFX_WEBRENDERUSERDATA_H #define GFX_WEBRENDERUSERDATA_H #include #include "mozilla/webrender/WebRenderAPI.h" #include "mozilla/layers/AnimationInfo.h" #include "mozilla/dom/RemoteBrowser.h" #include "mozilla/UniquePtr.h" #include "nsIFrame.h" #include "nsRefPtrHashtable.h" #include "ImageTypes.h" class nsDisplayItemGeometry; namespace mozilla { namespace webgpu { class WebGPUChild; } namespace wr { class IpcResourceUpdateQueue; } namespace gfx { class SourceSurface; } namespace layers { class BasicLayerManager; class CanvasLayer; class ImageClient; class ImageContainer; class WebRenderBridgeChild; class WebRenderCanvasData; class WebRenderCanvasRenderer; class WebRenderCanvasRendererAsync; class WebRenderImageData; class WebRenderFallbackData; class WebRenderLocalCanvasData; class RenderRootStateManager; class WebRenderGroupData; class WebRenderBackgroundData { public: WebRenderBackgroundData(wr::LayoutRect aBounds, wr::ColorF aColor) : mBounds(aBounds), mColor(aColor) {} void AddWebRenderCommands(wr::DisplayListBuilder& aBuilder); protected: wr::LayoutRect mBounds; wr::ColorF mColor; }; /// Parent class for arbitrary WebRender-specific data that can be associated /// to an nsFrame. class WebRenderUserData { public: typedef nsTHashtable> WebRenderUserDataRefTable; static bool SupportsAsyncUpdate(nsIFrame* aFrame); static bool ProcessInvalidateForImage(nsIFrame* aFrame, DisplayItemType aType, ContainerProducerID aProducerId); NS_INLINE_DECL_REFCOUNTING(WebRenderUserData) WebRenderUserData(RenderRootStateManager* aManager, nsDisplayItem* aItem); WebRenderUserData(RenderRootStateManager* aManager, uint32_t mDisplayItemKey, nsIFrame* aFrame); virtual WebRenderImageData* AsImageData() { return nullptr; } virtual WebRenderFallbackData* AsFallbackData() { return nullptr; } virtual WebRenderCanvasData* AsCanvasData() { return nullptr; } virtual WebRenderLocalCanvasData* AsLocalCanvasData() { return nullptr; } virtual WebRenderGroupData* AsGroupData() { return nullptr; } enum class UserDataType { eImage, eFallback, eAPZAnimation, eAnimation, eCanvas, eLocalCanvas, eRemote, eGroup, eMask, }; virtual UserDataType GetType() = 0; bool IsUsed() { return mUsed; } void SetUsed(bool aUsed) { mUsed = aUsed; } nsIFrame* GetFrame() { return mFrame; } uint32_t GetDisplayItemKey() { return mDisplayItemKey; } void RemoveFromTable(); virtual nsDisplayItemGeometry* GetGeometry() { return nullptr; } protected: virtual ~WebRenderUserData(); WebRenderBridgeChild* WrBridge() const; RefPtr mManager; nsIFrame* mFrame; uint32_t mDisplayItemKey; WebRenderUserDataRefTable* mTable; bool mUsed; }; struct WebRenderUserDataKey { WebRenderUserDataKey(uint32_t aFrameKey, WebRenderUserData::UserDataType aType) : mFrameKey(aFrameKey), mType(aType) {} bool operator==(const WebRenderUserDataKey& other) const { return mFrameKey == other.mFrameKey && mType == other.mType; } PLDHashNumber Hash() const { return HashGeneric( mFrameKey, static_cast::type>(mType)); } uint32_t mFrameKey; WebRenderUserData::UserDataType mType; }; typedef nsRefPtrHashtable< nsGenericHashKey, WebRenderUserData> WebRenderUserDataTable; /// Holds some data used to share TextureClient/ImageClient with the parent /// process. class WebRenderImageData : public WebRenderUserData { public: WebRenderImageData(RenderRootStateManager* aManager, nsDisplayItem* aItem); WebRenderImageData(RenderRootStateManager* aManager, uint32_t aDisplayItemKey, nsIFrame* aFrame); virtual ~WebRenderImageData(); WebRenderImageData* AsImageData() override { return this; } UserDataType GetType() override { return UserDataType::eImage; } static UserDataType Type() { return UserDataType::eImage; } Maybe GetImageKey() { return mKey; } void SetImageKey(const wr::ImageKey& aKey); already_AddRefed GetImageClient(); Maybe UpdateImageKey(ImageContainer* aContainer, wr::IpcResourceUpdateQueue& aResources, bool aFallback = false); void CreateAsyncImageWebRenderCommands( mozilla::wr::DisplayListBuilder& aBuilder, ImageContainer* aContainer, const StackingContextHelper& aSc, const LayoutDeviceRect& aBounds, const LayoutDeviceRect& aSCBounds, VideoInfo::Rotation aRotation, const wr::ImageRendering& aFilter, const wr::MixBlendMode& aMixBlendMode, bool aIsBackfaceVisible); void CreateImageClientIfNeeded(); bool IsAsync() { return mPipelineId.isSome(); } bool UsingSharedSurface(ContainerProducerID aProducerId) const; void ClearImageKey(); protected: Maybe mKey; RefPtr mTextureOfImage; RefPtr mImageClient; Maybe mPipelineId; RefPtr mContainer; // The key can be owned by a shared surface that is used by several elements. // when this is the case the shared surface is responsible for managing the // destruction of the key. // TODO: we surely can come up with a simpler/safer way to model this. bool mOwnsKey; }; /// Used for fallback rendering. /// /// In most cases this uses blob images but it can also render on the content /// side directly into a texture. class WebRenderFallbackData : public WebRenderUserData { public: WebRenderFallbackData(RenderRootStateManager* aManager, nsDisplayItem* aItem); virtual ~WebRenderFallbackData(); WebRenderFallbackData* AsFallbackData() override { return this; } UserDataType GetType() override { return UserDataType::eFallback; } static UserDataType Type() { return UserDataType::eFallback; } void SetInvalid(bool aInvalid) { mInvalid = aInvalid; } bool IsInvalid() { return mInvalid; } void SetFonts(const std::vector>& aFonts) { mFonts = aFonts; } Maybe GetBlobImageKey() { return mBlobKey; } void SetBlobImageKey(const wr::BlobImageKey& aKey); Maybe GetImageKey(); /// Create a WebRenderImageData to manage the image we are about to render /// into. WebRenderImageData* PaintIntoImage(); std::vector> mExternalSurfaces; RefPtr mBasicLayerManager; UniquePtr mGeometry; nsRect mBounds; nsRect mBuildingRect; gfx::Size mScale; protected: void ClearImageKey(); std::vector> mFonts; Maybe mBlobKey; // When rendering into a blob image, mImageData is null. It is non-null only // when we render directly into a texture on the content side. RefPtr mImageData; bool mInvalid; }; class WebRenderAPZAnimationData : public WebRenderUserData { public: WebRenderAPZAnimationData(RenderRootStateManager* aManager, nsDisplayItem* aItem); virtual ~WebRenderAPZAnimationData() = default; UserDataType GetType() override { return UserDataType::eAPZAnimation; } static UserDataType Type() { return UserDataType::eAPZAnimation; } uint64_t GetAnimationId() { return mAnimationId; } private: uint64_t mAnimationId; }; class WebRenderAnimationData : public WebRenderUserData { public: WebRenderAnimationData(RenderRootStateManager* aManager, nsDisplayItem* aItem); virtual ~WebRenderAnimationData(); UserDataType GetType() override { return UserDataType::eAnimation; } static UserDataType Type() { return UserDataType::eAnimation; } AnimationInfo& GetAnimationInfo() { return mAnimationInfo; } protected: AnimationInfo mAnimationInfo; }; class WebRenderCanvasData : public WebRenderUserData { public: WebRenderCanvasData(RenderRootStateManager* aManager, nsDisplayItem* aItem); virtual ~WebRenderCanvasData(); WebRenderCanvasData* AsCanvasData() override { return this; } UserDataType GetType() override { return UserDataType::eCanvas; } static UserDataType Type() { return UserDataType::eCanvas; } void ClearCanvasRenderer(); WebRenderCanvasRendererAsync* GetCanvasRenderer(); WebRenderCanvasRendererAsync* CreateCanvasRenderer(); void SetImageContainer(ImageContainer* aImageContainer); ImageContainer* GetImageContainer(); void ClearImageContainer(); protected: RefPtr mCanvasRenderer; RefPtr mContainer; }; // WebRender data assocatiated with canvases that don't need to // synchronize across content-GPU process barrier. class WebRenderLocalCanvasData : public WebRenderUserData { public: WebRenderLocalCanvasData(RenderRootStateManager* aManager, nsDisplayItem* aItem); virtual ~WebRenderLocalCanvasData(); WebRenderLocalCanvasData* AsLocalCanvasData() override { return this; } UserDataType GetType() override { return UserDataType::eLocalCanvas; } static UserDataType Type() { return UserDataType::eLocalCanvas; } void RequestFrameReadback(); void RefreshExternalImage(); // TODO: introduce a CanvasRenderer derivative to store here? WeakPtr mGpuBridge; uint64_t mGpuTextureId = 0; wr::ExternalImageId mExternalImageId = {0}; wr::ImageKey mImageKey = {}; wr::ImageDescriptor mDescriptor; gfx::SurfaceFormat mFormat = gfx::SurfaceFormat::UNKNOWN; bool mDirty = false; }; class WebRenderRemoteData : public WebRenderUserData { public: WebRenderRemoteData(RenderRootStateManager* aManager, nsDisplayItem* aItem); virtual ~WebRenderRemoteData(); UserDataType GetType() override { return UserDataType::eRemote; } static UserDataType Type() { return UserDataType::eRemote; } void SetRemoteBrowser(dom::RemoteBrowser* aBrowser) { mRemoteBrowser = aBrowser; } protected: RefPtr mRemoteBrowser; }; extern void DestroyWebRenderUserDataTable(WebRenderUserDataTable* aTable); struct WebRenderUserDataProperty { NS_DECLARE_FRAME_PROPERTY_WITH_DTOR(Key, WebRenderUserDataTable, DestroyWebRenderUserDataTable) }; template already_AddRefed GetWebRenderUserData(const nsIFrame* aFrame, uint32_t aPerFrameKey) { MOZ_ASSERT(aFrame); WebRenderUserDataTable* userDataTable = aFrame->GetProperty(WebRenderUserDataProperty::Key()); if (!userDataTable) { return nullptr; } WebRenderUserData* data = userDataTable->GetWeak(WebRenderUserDataKey(aPerFrameKey, T::Type())); if (data) { RefPtr result = static_cast(data); return result.forget(); } return nullptr; } } // namespace layers } // namespace mozilla #endif /* GFX_WEBRENDERUSERDATA_H */