1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef MOZILLA_GFX_DCLAYER_TREE_H
8 #define MOZILLA_GFX_DCLAYER_TREE_H
10 #include <dxgiformat.h>
11 #include <unordered_map>
16 #include "mozilla/HashFunctions.h"
17 #include "mozilla/Maybe.h"
18 #include "mozilla/RefPtr.h"
19 #include "mozilla/UniquePtr.h"
20 #include "mozilla/webrender/WebRenderTypes.h"
23 struct ID3D11DeviceContext
;
24 struct ID3D11VideoDevice
;
25 struct ID3D11VideoContext
;
26 struct ID3D11VideoProcessor
;
27 struct ID3D11VideoProcessorEnumerator
;
28 struct ID3D11VideoProcessorOutputView
;
29 struct IDCompositionDevice2
;
30 struct IDCompositionSurface
;
31 struct IDCompositionTarget
;
32 struct IDCompositionVisual2
;
33 struct IDXGIDecodeSwapChain
;
35 struct IDXGISwapChain1
;
36 struct IDCompositionVirtualSurface
;
46 // The size of the virtual surface. This is large enough such that we
47 // will never render a surface larger than this.
48 #define VIRTUAL_SURFACE_SIZE (1024 * 1024)
53 class RenderTextureHost
;
55 struct GpuOverlayInfo
{
56 bool mSupportsOverlays
= false;
57 bool mSupportsHardwareOverlays
= false;
58 DXGI_FORMAT mOverlayFormatUsed
= DXGI_FORMAT_B8G8R8A8_UNORM
;
59 DXGI_FORMAT mOverlayFormatUsedHdr
= DXGI_FORMAT_R10G10B10A2_UNORM
;
60 UINT mNv12OverlaySupportFlags
= 0;
61 UINT mYuy2OverlaySupportFlags
= 0;
62 UINT mRgb10a2OverlaySupportFlags
= 0;
66 * DCLayerTree manages direct composition layers.
67 * It does not manage gecko's layers::Layer.
71 static UniquePtr
<DCLayerTree
> Create(gl::GLContext
* aGL
, EGLConfig aEGLConfig
,
72 ID3D11Device
* aDevice
,
73 ID3D11DeviceContext
* aCtx
, HWND aHwnd
,
76 static void Shutdown();
78 explicit DCLayerTree(gl::GLContext
* aGL
, EGLConfig aEGLConfig
,
79 ID3D11Device
* aDevice
, ID3D11DeviceContext
* aCtx
,
80 IDCompositionDevice2
* aCompositionDevice
);
83 void SetDefaultSwapChain(IDXGISwapChain1
* aSwapChain
);
84 void MaybeUpdateDebug();
86 void WaitForCommitCompletion();
87 void DisableNativeCompositor();
89 // Interface for wr::Compositor
90 void CompositorBeginFrame();
91 void CompositorEndFrame();
92 void Bind(wr::NativeTileId aId
, wr::DeviceIntPoint
* aOffset
, uint32_t* aFboId
,
93 wr::DeviceIntRect aDirtyRect
, wr::DeviceIntRect aValidRect
);
95 void CreateSurface(wr::NativeSurfaceId aId
, wr::DeviceIntPoint aVirtualOffset
,
96 wr::DeviceIntSize aTileSize
, bool aIsOpaque
);
97 void CreateExternalSurface(wr::NativeSurfaceId aId
, bool aIsOpaque
);
98 void DestroySurface(NativeSurfaceId aId
);
99 void CreateTile(wr::NativeSurfaceId aId
, int32_t aX
, int32_t aY
);
100 void DestroyTile(wr::NativeSurfaceId aId
, int32_t aX
, int32_t aY
);
101 void AttachExternalImage(wr::NativeSurfaceId aId
,
102 wr::ExternalImageId aExternalImage
);
103 void AddSurface(wr::NativeSurfaceId aId
,
104 const wr::CompositorSurfaceTransform
& aTransform
,
105 wr::DeviceIntRect aClipRect
,
106 wr::ImageRendering aImageRendering
);
108 gl::GLContext
* GetGLContext() const { return mGL
; }
109 EGLConfig
GetEGLConfig() const { return mEGLConfig
; }
110 ID3D11Device
* GetDevice() const { return mDevice
; }
111 IDCompositionDevice2
* GetCompositionDevice() const {
112 return mCompositionDevice
;
114 ID3D11VideoDevice
* GetVideoDevice() const { return mVideoDevice
; }
115 ID3D11VideoContext
* GetVideoContext() const { return mVideoContext
; }
116 ID3D11VideoProcessor
* GetVideoProcessor() const { return mVideoProcessor
; }
117 ID3D11VideoProcessorEnumerator
* GetVideoProcessorEnumerator() const {
118 return mVideoProcessorEnumerator
;
120 bool EnsureVideoProcessor(const gfx::IntSize
& aVideoSize
);
122 DCSurface
* GetSurface(wr::NativeSurfaceId aId
) const;
124 // Get or create an FBO with depth buffer suitable for specified dimensions
125 GLuint
GetOrCreateFbo(int aWidth
, int aHeight
);
127 bool SupportsHardwareOverlays();
128 DXGI_FORMAT
GetOverlayFormatForSDR();
131 bool Initialize(HWND aHwnd
, nsACString
& aError
);
132 bool InitializeVideoOverlaySupport();
133 bool MaybeUpdateDebugCounter();
134 bool MaybeUpdateDebugVisualRedrawRegions();
135 void DestroyEGLSurface();
136 GLuint
CreateEGLSurfaceForCompositionSurface(
137 wr::DeviceIntRect aDirtyRect
, wr::DeviceIntPoint
* aOffset
,
138 RefPtr
<IDCompositionSurface
> aCompositionSurface
,
139 wr::DeviceIntPoint aSurfaceOffset
);
140 void ReleaseNativeCompositorResources();
142 RefPtr
<gl::GLContext
> mGL
;
143 EGLConfig mEGLConfig
;
145 RefPtr
<ID3D11Device
> mDevice
;
146 RefPtr
<ID3D11DeviceContext
> mCtx
;
148 RefPtr
<IDCompositionDevice2
> mCompositionDevice
;
149 RefPtr
<IDCompositionTarget
> mCompositionTarget
;
150 RefPtr
<IDCompositionVisual2
> mRootVisual
;
151 RefPtr
<IDCompositionVisual2
> mDefaultSwapChainVisual
;
153 RefPtr
<ID3D11VideoDevice
> mVideoDevice
;
154 RefPtr
<ID3D11VideoContext
> mVideoContext
;
155 RefPtr
<ID3D11VideoProcessor
> mVideoProcessor
;
156 RefPtr
<ID3D11VideoProcessorEnumerator
> mVideoProcessorEnumerator
;
157 gfx::IntSize mVideoSize
;
160 bool mDebugVisualRedrawRegions
;
162 Maybe
<RefPtr
<IDCompositionSurface
>> mCurrentSurface
;
164 // The EGL image that is bound to the D3D texture provided by
165 // DirectComposition.
168 // The GL render buffer ID that maps the EGLImage to an RBO for attaching to
172 struct SurfaceIdHashFn
{
173 std::size_t operator()(const wr::NativeSurfaceId
& aId
) const {
174 return HashGeneric(wr::AsUint64(aId
));
178 std::unordered_map
<wr::NativeSurfaceId
, UniquePtr
<DCSurface
>, SurfaceIdHashFn
>
181 // A list of layer IDs as they are added to the visual tree this frame.
182 std::vector
<wr::NativeSurfaceId
> mCurrentLayers
;
184 // The previous frame's list of layer IDs in visual order.
185 std::vector
<wr::NativeSurfaceId
> mPrevLayers
;
187 // Information about a cached FBO that is retained between frames.
188 struct CachedFrameBuffer
{
196 // A cache of FBOs, containing a depth buffer allocated to a specific size.
197 // TODO(gw): Might be faster as a hashmap? The length is typically much less
199 nsTArray
<CachedFrameBuffer
> mFrameBuffers
;
200 int mCurrentFrame
= 0;
204 static UniquePtr
<GpuOverlayInfo
> sGpuOverlayInfo
;
208 Represents a single picture cache slice. Each surface contains some
209 number of tiles. An implementation may choose to allocate individual
210 tiles to render in to (as the current impl does), or allocate a large
211 single virtual surface to draw into (e.g. the DirectComposition virtual
212 surface API in future).
216 explicit DCSurface(wr::DeviceIntSize aTileSize
,
217 wr::DeviceIntPoint aVirtualOffset
, bool aIsOpaque
,
218 DCLayerTree
* aDCLayerTree
);
219 virtual ~DCSurface();
222 void CreateTile(int32_t aX
, int32_t aY
);
223 void DestroyTile(int32_t aX
, int32_t aY
);
225 IDCompositionVisual2
* GetVisual() const { return mVisual
; }
226 DCTile
* GetTile(int32_t aX
, int32_t aY
) const;
229 TileKey(int32_t aX
, int32_t aY
) : mX(aX
), mY(aY
) {}
235 wr::DeviceIntSize
GetTileSize() const { return mTileSize
; }
236 wr::DeviceIntPoint
GetVirtualOffset() const { return mVirtualOffset
; }
238 IDCompositionVirtualSurface
* GetCompositionSurface() const {
239 return mVirtualSurface
;
242 void UpdateAllocatedRect();
243 void DirtyAllocatedRect();
245 virtual DCSurfaceVideo
* AsDCSurfaceVideo() { return nullptr; }
248 DCLayerTree
* mDCLayerTree
;
250 struct TileKeyHashFn
{
251 std::size_t operator()(const TileKey
& aId
) const {
252 return HashGeneric(aId
.mX
, aId
.mY
);
256 // The visual for this surface. No content is attached to here, but tiles
257 // that belong to this surface are added as children. In this way, we can
258 // set the clip and scroll offset once, on this visual, to affect all
260 RefPtr
<IDCompositionVisual2
> mVisual
;
262 wr::DeviceIntSize mTileSize
;
264 bool mAllocatedRectDirty
;
265 std::unordered_map
<TileKey
, UniquePtr
<DCTile
>, TileKeyHashFn
> mDCTiles
;
266 wr::DeviceIntPoint mVirtualOffset
;
267 RefPtr
<IDCompositionVirtualSurface
> mVirtualSurface
;
270 class DCSurfaceVideo
: public DCSurface
{
272 DCSurfaceVideo(bool aIsOpaque
, DCLayerTree
* aDCLayerTree
);
274 void AttachExternalImage(wr::ExternalImageId aExternalImage
);
276 DCSurfaceVideo
* AsDCSurfaceVideo() override
{ return this; }
279 DXGI_FORMAT
GetSwapChainFormat();
280 bool CreateVideoSwapChain(RenderTextureHost
* aTexture
);
281 bool CallVideoProcessorBlt(RenderTextureHost
* aTexture
);
282 void ReleaseDecodeSwapChainResources();
284 RefPtr
<ID3D11VideoProcessorOutputView
> mOutputView
;
285 RefPtr
<IDXGIResource
> mDecodeResource
;
286 RefPtr
<IDXGISwapChain1
> mVideoSwapChain
;
287 RefPtr
<IDXGIDecodeSwapChain
> mDecodeSwapChain
;
288 HANDLE mSwapChainSurfaceHandle
;
289 gfx::IntSize mSwapChainSize
;
290 DXGI_FORMAT mSwapChainFormat
= DXGI_FORMAT_B8G8R8A8_UNORM
;
291 bool mFailedToCreateYuvSwapChain
= false;
292 RefPtr
<RenderTextureHost
> mPrevTexture
;
297 explicit DCTile(DCLayerTree
* aDCLayerTree
);
299 bool Initialize(int aX
, int aY
, wr::DeviceIntSize aSize
, bool aIsOpaque
);
301 gfx::IntRect mValidRect
;
303 DCLayerTree
* mDCLayerTree
;
306 static inline bool operator==(const DCSurface::TileKey
& a0
,
307 const DCSurface::TileKey
& a1
) {
308 return a0
.mX
== a1
.mX
&& a0
.mY
== a1
.mY
;
312 } // namespace mozilla