Bug 1874684 - Part 28: Return DateDuration from DifferenceISODateTime. r=mgaudet
[gecko.git] / gfx / webrender_bindings / DCLayerTree.h
blob6d3a6118027b2e6a6a0a6a48f432e5256c38fb41
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>
12 #include <vector>
13 #include <windows.h>
15 #include "Colorspaces.h"
16 #include "GLTypes.h"
17 #include "mozilla/HashFunctions.h"
18 #include "mozilla/layers/OverlayInfo.h"
19 #include "mozilla/Maybe.h"
20 #include "mozilla/RefPtr.h"
21 #include "mozilla/StaticPtr.h"
22 #include "mozilla/UniquePtr.h"
23 #include "mozilla/webrender/WebRenderTypes.h"
25 struct ID3D11Device;
26 struct ID3D11DeviceContext;
27 struct ID3D11VideoDevice;
28 struct ID3D11VideoContext;
29 struct ID3D11VideoProcessor;
30 struct ID3D11VideoProcessorEnumerator;
31 struct ID3D11VideoProcessorOutputView;
32 struct IDCompositionColorMatrixEffect;
33 struct IDCompositionFilterEffect;
34 struct IDCompositionTableTransferEffect;
35 struct IDCompositionDevice2;
36 struct IDCompositionDevice3;
37 struct IDCompositionSurface;
38 struct IDCompositionTarget;
39 struct IDCompositionVisual2;
40 struct IDXGIDecodeSwapChain;
41 struct IDXGIResource;
42 struct IDXGISwapChain1;
43 struct IDCompositionVirtualSurface;
45 namespace mozilla {
47 namespace gl {
48 class GLContext;
51 namespace wr {
53 // The size of the virtual surface. This is large enough such that we
54 // will never render a surface larger than this.
55 #define VIRTUAL_SURFACE_SIZE (1024 * 1024)
57 class DCTile;
58 class DCSurface;
59 class DCSurfaceVideo;
60 class DCSurfaceHandle;
61 class RenderTextureHost;
62 class RenderDcompSurfaceTextureHost;
64 struct GpuOverlayInfo {
65 bool mSupportsOverlays = false;
66 bool mSupportsHardwareOverlays = false;
67 DXGI_FORMAT mOverlayFormatUsed = DXGI_FORMAT_B8G8R8A8_UNORM;
68 DXGI_FORMAT mOverlayFormatUsedHdr = DXGI_FORMAT_R10G10B10A2_UNORM;
69 UINT mNv12OverlaySupportFlags = 0;
70 UINT mYuy2OverlaySupportFlags = 0;
71 UINT mBgra8OverlaySupportFlags = 0;
72 UINT mRgb10a2OverlaySupportFlags = 0;
75 // -
77 struct ColorManagementChain {
78 RefPtr<IDCompositionColorMatrixEffect> srcRgbFromSrcYuv;
79 RefPtr<IDCompositionTableTransferEffect> srcLinearFromSrcTf;
80 RefPtr<IDCompositionColorMatrixEffect> dstLinearFromSrcLinear;
81 RefPtr<IDCompositionTableTransferEffect> dstTfFromDstLinear;
82 RefPtr<IDCompositionFilterEffect> last;
84 static ColorManagementChain From(IDCompositionDevice3& dcomp,
85 const color::ColorProfileConversionDesc&);
87 ~ColorManagementChain();
90 // -
92 enum class DCompOverlayTypes : uint8_t {
93 NO_OVERLAY = 0,
94 HARDWARE_DECODED_VIDEO = 1 << 0,
95 SOFTWARE_DECODED_VIDEO = 1 << 1,
97 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(DCompOverlayTypes)
99 // -
102 * DCLayerTree manages direct composition layers.
103 * It does not manage gecko's layers::Layer.
105 class DCLayerTree {
106 public:
107 static UniquePtr<DCLayerTree> Create(gl::GLContext* aGL, EGLConfig aEGLConfig,
108 ID3D11Device* aDevice,
109 ID3D11DeviceContext* aCtx, HWND aHwnd,
110 nsACString& aError);
112 static void Shutdown();
114 explicit DCLayerTree(gl::GLContext* aGL, EGLConfig aEGLConfig,
115 ID3D11Device* aDevice, ID3D11DeviceContext* aCtx,
116 IDCompositionDevice2* aCompositionDevice);
117 ~DCLayerTree();
119 void SetDefaultSwapChain(IDXGISwapChain1* aSwapChain);
120 void MaybeUpdateDebug();
121 void MaybeCommit();
122 void WaitForCommitCompletion();
123 void DisableNativeCompositor();
125 // Interface for wr::Compositor
126 void CompositorBeginFrame();
127 void CompositorEndFrame();
128 void Bind(wr::NativeTileId aId, wr::DeviceIntPoint* aOffset, uint32_t* aFboId,
129 wr::DeviceIntRect aDirtyRect, wr::DeviceIntRect aValidRect);
130 void Unbind();
131 void CreateSurface(wr::NativeSurfaceId aId, wr::DeviceIntPoint aVirtualOffset,
132 wr::DeviceIntSize aTileSize, bool aIsOpaque);
133 void CreateExternalSurface(wr::NativeSurfaceId aId, bool aIsOpaque);
134 void DestroySurface(NativeSurfaceId aId);
135 void CreateTile(wr::NativeSurfaceId aId, int32_t aX, int32_t aY);
136 void DestroyTile(wr::NativeSurfaceId aId, int32_t aX, int32_t aY);
137 void AttachExternalImage(wr::NativeSurfaceId aId,
138 wr::ExternalImageId aExternalImage);
139 void AddSurface(wr::NativeSurfaceId aId,
140 const wr::CompositorSurfaceTransform& aTransform,
141 wr::DeviceIntRect aClipRect,
142 wr::ImageRendering aImageRendering);
144 gl::GLContext* GetGLContext() const { return mGL; }
145 EGLConfig GetEGLConfig() const { return mEGLConfig; }
146 ID3D11Device* GetDevice() const { return mDevice; }
147 ID3D11DeviceContext* GetDeviceContext() const { return mCtx; }
148 IDCompositionDevice2* GetCompositionDevice() const {
149 return mCompositionDevice;
151 ID3D11VideoDevice* GetVideoDevice() const { return mVideoDevice; }
152 ID3D11VideoContext* GetVideoContext() const { return mVideoContext; }
153 ID3D11VideoProcessor* GetVideoProcessor() const { return mVideoProcessor; }
154 ID3D11VideoProcessorEnumerator* GetVideoProcessorEnumerator() const {
155 return mVideoProcessorEnumerator;
157 bool EnsureVideoProcessor(const gfx::IntSize& aInputSize,
158 const gfx::IntSize& aOutputSize);
160 DCSurface* GetSurface(wr::NativeSurfaceId aId) const;
162 // Get or create an FBO with depth buffer suitable for specified dimensions
163 GLuint GetOrCreateFbo(int aWidth, int aHeight);
165 bool SupportsHardwareOverlays();
166 DXGI_FORMAT GetOverlayFormatForSDR();
168 bool SupportsSwapChainTearing();
170 void SetUsedOverlayTypeInFrame(DCompOverlayTypes aTypes);
172 protected:
173 bool Initialize(HWND aHwnd, nsACString& aError);
174 bool InitializeVideoOverlaySupport();
175 bool MaybeUpdateDebugCounter();
176 bool MaybeUpdateDebugVisualRedrawRegions();
177 void DestroyEGLSurface();
178 GLuint CreateEGLSurfaceForCompositionSurface(
179 wr::DeviceIntRect aDirtyRect, wr::DeviceIntPoint* aOffset,
180 RefPtr<IDCompositionSurface> aCompositionSurface,
181 wr::DeviceIntPoint aSurfaceOffset);
182 void ReleaseNativeCompositorResources();
183 layers::OverlayInfo GetOverlayInfo();
185 RefPtr<gl::GLContext> mGL;
186 EGLConfig mEGLConfig;
188 RefPtr<ID3D11Device> mDevice;
189 RefPtr<ID3D11DeviceContext> mCtx;
191 RefPtr<IDCompositionDevice2> mCompositionDevice;
192 RefPtr<IDCompositionTarget> mCompositionTarget;
193 RefPtr<IDCompositionVisual2> mRootVisual;
194 RefPtr<IDCompositionVisual2> mDefaultSwapChainVisual;
196 RefPtr<ID3D11VideoDevice> mVideoDevice;
197 RefPtr<ID3D11VideoContext> mVideoContext;
198 RefPtr<ID3D11VideoProcessor> mVideoProcessor;
199 RefPtr<ID3D11VideoProcessorEnumerator> mVideoProcessorEnumerator;
200 gfx::IntSize mVideoInputSize;
201 gfx::IntSize mVideoOutputSize;
203 bool mDebugCounter;
204 bool mDebugVisualRedrawRegions;
206 Maybe<RefPtr<IDCompositionSurface>> mCurrentSurface;
208 // The EGL image that is bound to the D3D texture provided by
209 // DirectComposition.
210 EGLImage mEGLImage;
212 // The GL render buffer ID that maps the EGLImage to an RBO for attaching to
213 // an FBO.
214 GLuint mColorRBO;
216 struct SurfaceIdHashFn {
217 std::size_t operator()(const wr::NativeSurfaceId& aId) const {
218 return HashGeneric(wr::AsUint64(aId));
222 std::unordered_map<wr::NativeSurfaceId, UniquePtr<DCSurface>, SurfaceIdHashFn>
223 mDCSurfaces;
225 // A list of layer IDs as they are added to the visual tree this frame.
226 std::vector<wr::NativeSurfaceId> mCurrentLayers;
228 // The previous frame's list of layer IDs in visual order.
229 std::vector<wr::NativeSurfaceId> mPrevLayers;
231 // Information about a cached FBO that is retained between frames.
232 struct CachedFrameBuffer {
233 int width;
234 int height;
235 GLuint fboId;
236 GLuint depthRboId;
237 int lastFrameUsed;
240 // A cache of FBOs, containing a depth buffer allocated to a specific size.
241 // TODO(gw): Might be faster as a hashmap? The length is typically much less
242 // than 10.
243 nsTArray<CachedFrameBuffer> mFrameBuffers;
244 int mCurrentFrame = 0;
246 bool mPendingCommit;
248 static color::ColorProfileDesc QueryOutputColorProfile();
250 mutable Maybe<color::ColorProfileDesc> mOutputColorProfile;
252 DCompOverlayTypes mUsedOverlayTypesInFrame = DCompOverlayTypes::NO_OVERLAY;
253 int mSlowCommitCount = 0;
255 public:
256 const color::ColorProfileDesc& OutputColorProfile() const {
257 if (!mOutputColorProfile) {
258 mOutputColorProfile = Some(QueryOutputColorProfile());
260 return *mOutputColorProfile;
263 protected:
264 static StaticAutoPtr<GpuOverlayInfo> sGpuOverlayInfo;
268 Represents a single picture cache slice. Each surface contains some
269 number of tiles. An implementation may choose to allocate individual
270 tiles to render in to (as the current impl does), or allocate a large
271 single virtual surface to draw into (e.g. the DirectComposition virtual
272 surface API in future).
274 class DCSurface {
275 public:
276 const bool mIsVirtualSurface;
278 explicit DCSurface(wr::DeviceIntSize aTileSize,
279 wr::DeviceIntPoint aVirtualOffset, bool aIsVirtualSurface,
280 bool aIsOpaque, DCLayerTree* aDCLayerTree);
281 virtual ~DCSurface();
283 bool Initialize();
284 void CreateTile(int32_t aX, int32_t aY);
285 void DestroyTile(int32_t aX, int32_t aY);
287 IDCompositionVisual2* GetVisual() const { return mVisual; }
288 DCTile* GetTile(int32_t aX, int32_t aY) const;
290 struct TileKey {
291 TileKey(int32_t aX, int32_t aY) : mX(aX), mY(aY) {}
293 int32_t mX;
294 int32_t mY;
297 wr::DeviceIntSize GetTileSize() const { return mTileSize; }
298 wr::DeviceIntPoint GetVirtualOffset() const { return mVirtualOffset; }
300 IDCompositionVirtualSurface* GetCompositionSurface() const {
301 return mVirtualSurface;
304 void UpdateAllocatedRect();
305 void DirtyAllocatedRect();
307 // Implement these if the inherited surface supports attaching external image.
308 virtual void AttachExternalImage(wr::ExternalImageId aExternalImage) {
309 MOZ_RELEASE_ASSERT(true, "Not support attaching external image");
311 virtual void PresentExternalSurface(gfx::Matrix& aTransform) {
312 MOZ_RELEASE_ASSERT(true, "Not support presenting external surface");
315 virtual DCSurfaceVideo* AsDCSurfaceVideo() { return nullptr; }
316 virtual DCSurfaceHandle* AsDCSurfaceHandle() { return nullptr; }
318 protected:
319 DCLayerTree* mDCLayerTree;
321 struct TileKeyHashFn {
322 std::size_t operator()(const TileKey& aId) const {
323 return HashGeneric(aId.mX, aId.mY);
327 // The visual for this surface. No content is attached to here, but tiles
328 // that belong to this surface are added as children. In this way, we can
329 // set the clip and scroll offset once, on this visual, to affect all
330 // children.
332 // However when using a virtual surface, it is directly attached to this
333 // visual and the tiles do not own visuals.
335 // Whether mIsVirtualSurface is enabled is decided at DCSurface creation
336 // time based on the pref gfx.webrender.dcomp-use-virtual-surfaces
337 RefPtr<IDCompositionVisual2> mVisual;
339 wr::DeviceIntSize mTileSize;
340 bool mIsOpaque;
341 bool mAllocatedRectDirty;
342 std::unordered_map<TileKey, UniquePtr<DCTile>, TileKeyHashFn> mDCTiles;
343 wr::DeviceIntPoint mVirtualOffset;
344 RefPtr<IDCompositionVirtualSurface> mVirtualSurface;
348 * A wrapper surface which can contain either a DCVideo or a DCSurfaceHandle.
350 class DCExternalSurfaceWrapper : public DCSurface {
351 public:
352 DCExternalSurfaceWrapper(bool aIsOpaque, DCLayerTree* aDCLayerTree)
353 : DCSurface(wr::DeviceIntSize{}, wr::DeviceIntPoint{},
354 false /* virtual surface */, false /* opaque */,
355 aDCLayerTree),
356 mIsOpaque(aIsOpaque) {}
357 ~DCExternalSurfaceWrapper() = default;
359 void AttachExternalImage(wr::ExternalImageId aExternalImage) override;
361 void PresentExternalSurface(gfx::Matrix& aTransform) override;
363 DCSurfaceVideo* AsDCSurfaceVideo() override {
364 return mSurface ? mSurface->AsDCSurfaceVideo() : nullptr;
367 DCSurfaceHandle* AsDCSurfaceHandle() override {
368 return mSurface ? mSurface->AsDCSurfaceHandle() : nullptr;
371 private:
372 DCSurface* EnsureSurfaceForExternalImage(wr::ExternalImageId aExternalImage);
374 UniquePtr<DCSurface> mSurface;
375 const bool mIsOpaque;
376 Maybe<ColorManagementChain> mCManageChain;
379 class DCSurfaceVideo : public DCSurface {
380 public:
381 DCSurfaceVideo(bool aIsOpaque, DCLayerTree* aDCLayerTree);
383 void AttachExternalImage(wr::ExternalImageId aExternalImage) override;
384 bool CalculateSwapChainSize(gfx::Matrix& aTransform);
385 void PresentVideo();
387 DCSurfaceVideo* AsDCSurfaceVideo() override { return this; }
389 protected:
390 virtual ~DCSurfaceVideo();
392 DXGI_FORMAT GetSwapChainFormat(bool aUseVpAutoHDR);
393 bool CreateVideoSwapChain(DXGI_FORMAT aFormat);
394 bool CallVideoProcessorBlt();
395 void ReleaseDecodeSwapChainResources();
397 RefPtr<ID3D11VideoProcessorOutputView> mOutputView;
398 RefPtr<IDXGIResource> mDecodeResource;
399 RefPtr<IDXGISwapChain1> mVideoSwapChain;
400 RefPtr<IDXGIDecodeSwapChain> mDecodeSwapChain;
401 HANDLE mSwapChainSurfaceHandle = 0;
402 gfx::IntSize mVideoSize;
403 gfx::IntSize mSwapChainSize;
404 DXGI_FORMAT mSwapChainFormat = DXGI_FORMAT_B8G8R8A8_UNORM;
405 bool mIsDRM = false;
406 bool mFailedYuvSwapChain = false;
407 RefPtr<RenderTextureHost> mRenderTextureHost;
408 RefPtr<RenderTextureHost> mPrevTexture;
409 int mSlowPresentCount = 0;
410 bool mFirstPresent = true;
411 const UINT mSwapChainBufferCount;
412 bool mUseVpAutoHDR = false;
413 bool mVpAutoHDRFailed = false;
414 bool mVpSuperResolutionFailed = false;
418 * A DC surface contains a IDCompositionSurface that is directly constructed by
419 * a handle. This is used by the Media Foundataion media engine, which would
420 * store the decoded video content in the surface.
422 class DCSurfaceHandle : public DCSurface {
423 public:
424 DCSurfaceHandle(bool aIsOpaque, DCLayerTree* aDCLayerTree);
425 ~DCSurfaceHandle() = default;
427 void AttachExternalImage(wr::ExternalImageId aExternalImage) override;
428 void PresentSurfaceHandle();
430 DCSurfaceHandle* AsDCSurfaceHandle() override { return this; }
432 protected:
433 HANDLE GetSurfaceHandle() const;
434 IDCompositionSurface* EnsureSurface();
436 RefPtr<RenderDcompSurfaceTextureHost> mDcompTextureHost;
439 class DCTile {
440 public:
441 gfx::IntRect mValidRect;
443 DCLayerTree* mDCLayerTree;
444 // Indicates that when the first BeginDraw occurs on the surface it must be
445 // full size - required by dcomp on non-virtual surfaces.
446 bool mNeedsFullDraw;
448 explicit DCTile(DCLayerTree* aDCLayerTree);
449 ~DCTile();
450 bool Initialize(int aX, int aY, wr::DeviceIntSize aSize,
451 bool aIsVirtualSurface, bool aIsOpaque,
452 RefPtr<IDCompositionVisual2> mSurfaceVisual);
453 RefPtr<IDCompositionSurface> Bind(wr::DeviceIntRect aValidRect);
454 IDCompositionVisual2* GetVisual() { return mVisual; }
456 protected:
457 // Size in pixels of this tile, some may be unused. Set by Initialize.
458 wr::DeviceIntSize mSize;
459 // Whether the tile is composited as opaque (ignores alpha) or transparent.
460 // Set by Initialize.
461 bool mIsOpaque;
462 // Some code paths differ based on whether parent surface is virtual.
463 bool mIsVirtualSurface;
464 // Visual that displays the composition surface, or NULL if the tile belongs
465 // to a virtual surface.
466 RefPtr<IDCompositionVisual2> mVisual;
467 // Surface for the visual, or NULL if the tile has not had its first Bind or
468 // belongs to a virtual surface.
469 RefPtr<IDCompositionSurface> mCompositionSurface;
471 RefPtr<IDCompositionSurface> CreateCompositionSurface(wr::DeviceIntSize aSize,
472 bool aIsOpaque);
475 static inline bool operator==(const DCSurface::TileKey& a0,
476 const DCSurface::TileKey& a1) {
477 return a0.mX == a1.mX && a0.mY == a1.mY;
480 } // namespace wr
481 } // namespace mozilla
483 #endif