diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
commit | 2aa4a82499d4becd2284cdb482213d541b8804dd (patch) | |
tree | b80bf8bf13c3766139fbacc530efd0dd9d54394c /gfx/webrender_bindings/DCLayerTree.h | |
parent | Initial commit. (diff) | |
download | firefox-2aa4a82499d4becd2284cdb482213d541b8804dd.tar.xz firefox-2aa4a82499d4becd2284cdb482213d541b8804dd.zip |
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'gfx/webrender_bindings/DCLayerTree.h')
-rw-r--r-- | gfx/webrender_bindings/DCLayerTree.h | 294 |
1 files changed, 294 insertions, 0 deletions
diff --git a/gfx/webrender_bindings/DCLayerTree.h b/gfx/webrender_bindings/DCLayerTree.h new file mode 100644 index 0000000000..eba2780ceb --- /dev/null +++ b/gfx/webrender_bindings/DCLayerTree.h @@ -0,0 +1,294 @@ +/* -*- 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_DCLAYER_TREE_H +#define MOZILLA_GFX_DCLAYER_TREE_H + +#include <unordered_map> +#include <vector> +#include <windows.h> + +#include "GLTypes.h" +#include "mozilla/HashFunctions.h" +#include "mozilla/Maybe.h" +#include "mozilla/RefPtr.h" +#include "mozilla/UniquePtr.h" +#include "mozilla/webrender/WebRenderTypes.h" + +struct ID3D11Device; +struct ID3D11DeviceContext; +struct ID3D11VideoDevice; +struct ID3D11VideoContext; +struct ID3D11VideoProcessor; +struct ID3D11VideoProcessorEnumerator; +struct ID3D11VideoProcessorOutputView; +struct IDCompositionDevice2; +struct IDCompositionSurface; +struct IDCompositionTarget; +struct IDCompositionVisual2; +struct IDXGIDecodeSwapChain; +struct IDXGIResource; +struct IDXGISwapChain1; +struct IDCompositionVirtualSurface; + +namespace mozilla { + +namespace gl { +class GLContext; +} + +namespace wr { + +// The size of the virtual surface. This is large enough such that we +// will never render a surface larger than this. +#define VIRTUAL_SURFACE_SIZE (1024 * 1024) + +class DCTile; +class DCSurface; +class DCSurfaceVideo; +class RenderTextureHost; + +/** + * DCLayerTree manages direct composition layers. + * It does not manage gecko's layers::Layer. + */ +class DCLayerTree { + public: + static UniquePtr<DCLayerTree> Create(gl::GLContext* aGL, EGLConfig aEGLConfig, + ID3D11Device* aDevice, + ID3D11DeviceContext* aCtx, HWND aHwnd, + nsACString& aError); + explicit DCLayerTree(gl::GLContext* aGL, EGLConfig aEGLConfig, + ID3D11Device* aDevice, ID3D11DeviceContext* aCtx, + IDCompositionDevice2* aCompositionDevice); + ~DCLayerTree(); + + void SetDefaultSwapChain(IDXGISwapChain1* aSwapChain); + void MaybeUpdateDebug(); + void MaybeCommit(); + void WaitForCommitCompletion(); + void DisableNativeCompositor(); + + // Interface for wr::Compositor + void CompositorBeginFrame(); + void CompositorEndFrame(); + void Bind(wr::NativeTileId aId, wr::DeviceIntPoint* aOffset, uint32_t* aFboId, + wr::DeviceIntRect aDirtyRect, wr::DeviceIntRect aValidRect); + void Unbind(); + void CreateSurface(wr::NativeSurfaceId aId, wr::DeviceIntPoint aVirtualOffset, + wr::DeviceIntSize aTileSize, bool aIsOpaque); + void CreateExternalSurface(wr::NativeSurfaceId aId, bool aIsOpaque); + void DestroySurface(NativeSurfaceId aId); + void CreateTile(wr::NativeSurfaceId aId, int32_t aX, int32_t aY); + void DestroyTile(wr::NativeSurfaceId aId, int32_t aX, int32_t aY); + void AttachExternalImage(wr::NativeSurfaceId aId, + wr::ExternalImageId aExternalImage); + void AddSurface(wr::NativeSurfaceId aId, + const wr::CompositorSurfaceTransform& aTransform, + wr::DeviceIntRect aClipRect, + wr::ImageRendering aImageRendering); + + gl::GLContext* GetGLContext() const { return mGL; } + EGLConfig GetEGLConfig() const { return mEGLConfig; } + ID3D11Device* GetDevice() const { return mDevice; } + IDCompositionDevice2* GetCompositionDevice() const { + return mCompositionDevice; + } + ID3D11VideoDevice* GetVideoDevice() const { return mVideoDevice; } + ID3D11VideoContext* GetVideoContext() const { return mVideoContext; } + ID3D11VideoProcessor* GetVideoProcessor() const { return mVideoProcessor; } + ID3D11VideoProcessorEnumerator* GetVideoProcessorEnumerator() const { + return mVideoProcessorEnumerator; + } + bool EnsureVideoProcessor(const gfx::IntSize& aVideoSize); + + DCSurface* GetSurface(wr::NativeSurfaceId aId) const; + + // Get or create an FBO with depth buffer suitable for specified dimensions + GLuint GetOrCreateFbo(int aWidth, int aHeight); + + protected: + bool Initialize(HWND aHwnd, nsACString& aError); + bool InitializeVideoOverlaySupport(); + bool MaybeUpdateDebugCounter(); + bool MaybeUpdateDebugVisualRedrawRegions(); + void DestroyEGLSurface(); + GLuint CreateEGLSurfaceForCompositionSurface( + wr::DeviceIntRect aDirtyRect, wr::DeviceIntPoint* aOffset, + RefPtr<IDCompositionSurface> aCompositionSurface, + wr::DeviceIntPoint aSurfaceOffset); + void ReleaseNativeCompositorResources(); + + RefPtr<gl::GLContext> mGL; + EGLConfig mEGLConfig; + + RefPtr<ID3D11Device> mDevice; + RefPtr<ID3D11DeviceContext> mCtx; + + RefPtr<IDCompositionDevice2> mCompositionDevice; + RefPtr<IDCompositionTarget> mCompositionTarget; + RefPtr<IDCompositionVisual2> mRootVisual; + RefPtr<IDCompositionVisual2> mDefaultSwapChainVisual; + + RefPtr<ID3D11VideoDevice> mVideoDevice; + RefPtr<ID3D11VideoContext> mVideoContext; + RefPtr<ID3D11VideoProcessor> mVideoProcessor; + RefPtr<ID3D11VideoProcessorEnumerator> mVideoProcessorEnumerator; + gfx::IntSize mVideoSize; + + bool mVideoOverlaySupported; + + bool mDebugCounter; + bool mDebugVisualRedrawRegions; + + Maybe<RefPtr<IDCompositionSurface>> mCurrentSurface; + + // The EGL image that is bound to the D3D texture provided by + // DirectComposition. + EGLImage mEGLImage; + + // The GL render buffer ID that maps the EGLImage to an RBO for attaching to + // an FBO. + GLuint mColorRBO; + + struct SurfaceIdHashFn { + std::size_t operator()(const wr::NativeSurfaceId& aId) const { + return HashGeneric(wr::AsUint64(aId)); + } + }; + + std::unordered_map<wr::NativeSurfaceId, UniquePtr<DCSurface>, SurfaceIdHashFn> + mDCSurfaces; + + // A list of layer IDs as they are added to the visual tree this frame. + std::vector<wr::NativeSurfaceId> mCurrentLayers; + + // The previous frame's list of layer IDs in visual order. + std::vector<wr::NativeSurfaceId> mPrevLayers; + + // Information about a cached FBO that is retained between frames. + struct CachedFrameBuffer { + int width; + int height; + GLuint fboId; + GLuint depthRboId; + int lastFrameUsed; + }; + + // A cache of FBOs, containing a depth buffer allocated to a specific size. + // TODO(gw): Might be faster as a hashmap? The length is typically much less + // than 10. + nsTArray<CachedFrameBuffer> mFrameBuffers; + int mCurrentFrame = 0; + + bool mPendingCommit; +}; + +/** + Represents a single picture cache slice. Each surface contains some + number of tiles. An implementation may choose to allocate individual + tiles to render in to (as the current impl does), or allocate a large + single virtual surface to draw into (e.g. the DirectComposition virtual + surface API in future). + */ +class DCSurface { + public: + explicit DCSurface(wr::DeviceIntSize aTileSize, + wr::DeviceIntPoint aVirtualOffset, bool aIsOpaque, + DCLayerTree* aDCLayerTree); + virtual ~DCSurface(); + + bool Initialize(); + void CreateTile(int32_t aX, int32_t aY); + void DestroyTile(int32_t aX, int32_t aY); + + IDCompositionVisual2* GetVisual() const { return mVisual; } + DCTile* GetTile(int32_t aX, int32_t aY) const; + + struct TileKey { + TileKey(int32_t aX, int32_t aY) : mX(aX), mY(aY) {} + + int32_t mX; + int32_t mY; + }; + + wr::DeviceIntSize GetTileSize() const { return mTileSize; } + wr::DeviceIntPoint GetVirtualOffset() const { return mVirtualOffset; } + + IDCompositionVirtualSurface* GetCompositionSurface() const { + return mVirtualSurface; + } + + void UpdateAllocatedRect(); + void DirtyAllocatedRect(); + + virtual DCSurfaceVideo* AsDCSurfaceVideo() { return nullptr; } + + protected: + DCLayerTree* mDCLayerTree; + + struct TileKeyHashFn { + std::size_t operator()(const TileKey& aId) const { + return HashGeneric(aId.mX, aId.mY); + } + }; + + // The visual for this surface. No content is attached to here, but tiles + // that belong to this surface are added as children. In this way, we can + // set the clip and scroll offset once, on this visual, to affect all + // children. + RefPtr<IDCompositionVisual2> mVisual; + + wr::DeviceIntSize mTileSize; + bool mIsOpaque; + bool mAllocatedRectDirty; + std::unordered_map<TileKey, UniquePtr<DCTile>, TileKeyHashFn> mDCTiles; + wr::DeviceIntPoint mVirtualOffset; + RefPtr<IDCompositionVirtualSurface> mVirtualSurface; +}; + +class DCSurfaceVideo : public DCSurface { + public: + DCSurfaceVideo(bool aIsOpaque, DCLayerTree* aDCLayerTree); + + void AttachExternalImage(wr::ExternalImageId aExternalImage); + + DCSurfaceVideo* AsDCSurfaceVideo() override { return this; } + + protected: + bool CreateVideoSwapChain(RenderTextureHost* aTexture); + bool CallVideoProcessorBlt(RenderTextureHost* aTexture); + void ReleaseDecodeSwapChainResources(); + + RefPtr<ID3D11VideoProcessorOutputView> mOutputView; + RefPtr<IDXGIResource> mDecodeResource; + RefPtr<IDXGISwapChain1> mVideoSwapChain; + RefPtr<IDXGIDecodeSwapChain> mDecodeSwapChain; + HANDLE mSwapChainSurfaceHandle; + gfx::IntSize mSwapChainSize; + RefPtr<RenderTextureHost> mPrevTexture; +}; + +class DCTile { + public: + explicit DCTile(DCLayerTree* aDCLayerTree); + ~DCTile(); + bool Initialize(int aX, int aY, wr::DeviceIntSize aSize, bool aIsOpaque); + + gfx::IntRect mValidRect; + + DCLayerTree* mDCLayerTree; +}; + +static inline bool operator==(const DCSurface::TileKey& a0, + const DCSurface::TileKey& a1) { + return a0.mX == a1.mX && a0.mY == a1.mY; +} + +} // namespace wr +} // namespace mozilla + +#endif |