1 /*
2  *  Copyright (C) 2005-2018 Team Kodi
3  *  This file is part of Kodi - https://kodi.tv
4  *
5  *  SPDX-License-Identifier: GPL-2.0-or-later
6  *  See LICENSES/README.md for more information.
7  */
8 
9 #pragma once
10 
11 #include "DirectXHelper.h"
12 #include "HDRStatus.h"
13 #include "guilib/D3DResource.h"
14 
15 #include <functional>
16 #include <memory>
17 
18 #include <concrt.h>
19 #include <dxgi1_5.h>
20 #include <wrl.h>
21 #include <wrl/client.h>
22 
23 struct RESOLUTION_INFO;
24 struct DEBUG_INFO_RENDER;
25 
26 namespace DX
27 {
28   interface IDeviceNotify
29   {
30     virtual void OnDXDeviceLost() = 0;
31     virtual void OnDXDeviceRestored() = 0;
32   };
33 
34   // Controls all the DirectX device resources.
35   class DeviceResources
36   {
37   public:
38     static std::shared_ptr<DX::DeviceResources> Get();
39 
40     DeviceResources();
41     virtual ~DeviceResources();
42     void Release();
43 
44     void ValidateDevice();
45     void HandleDeviceLost(bool removed);
46     bool Begin();
47     void Present();
48 
49     // The size of the render target, in pixels.
GetOutputSize()50     winrt::Windows::Foundation::Size GetOutputSize() const { return m_outputSize; }
51     // The size of the render target, in dips.
GetLogicalSize()52     winrt::Windows::Foundation::Size GetLogicalSize() const { return m_logicalSize; }
53     void SetLogicalSize(float width, float height);
GetDpi()54     float GetDpi() const { return m_effectiveDpi; }
55     void SetDpi(float dpi);
56 
57     // D3D Accessors.
HasValidDevice()58     bool HasValidDevice() const { return m_bDeviceCreated; }
GetD3DDevice()59     ID3D11Device1* GetD3DDevice() const { return m_d3dDevice.Get(); }
GetD3DContext()60     ID3D11DeviceContext1* GetD3DContext() const { return m_deferrContext.Get(); }
GetImmediateContext()61     ID3D11DeviceContext1* GetImmediateContext() const { return m_d3dContext.Get(); }
GetSwapChain()62     IDXGISwapChain1* GetSwapChain() const { return m_swapChain.Get(); }
GetIDXGIFactory2()63     IDXGIFactory2* GetIDXGIFactory2() const { return m_dxgiFactory.Get(); }
GetAdapter()64     IDXGIAdapter1* GetAdapter() const { return m_adapter.Get(); }
GetDSV()65     ID3D11DepthStencilView* GetDSV() const { return m_d3dDepthStencilView.Get(); }
GetDeviceFeatureLevel()66     D3D_FEATURE_LEVEL GetDeviceFeatureLevel() const { return m_d3dFeatureLevel; }
GetBackBuffer()67     CD3DTexture& GetBackBuffer() { return m_backBufferTex; }
68 
69     void GetOutput(IDXGIOutput** ppOutput) const;
70     void GetAdapterDesc(DXGI_ADAPTER_DESC *desc) const;
71     void GetDisplayMode(DXGI_MODE_DESC *mode) const;
72 
GetScreenViewport()73     D3D11_VIEWPORT GetScreenViewport() const { return m_screenViewport; }
74     void SetViewPort(D3D11_VIEWPORT& viewPort) const;
75 
76     void ReleaseBackBuffer();
77     void CreateBackBuffer();
78     void ResizeBuffers();
79 
80     bool SetFullScreen(bool fullscreen, RESOLUTION_INFO& res);
81 
82     // HDR display support
83     HDR_STATUS ToggleHDR();
84     void SetHdrMetaData(DXGI_HDR_METADATA_HDR10& hdr10) const;
85     void SetHdrColorSpace(const DXGI_COLOR_SPACE_TYPE colorSpace);
IsHDROutput()86     bool IsHDROutput() const { return m_IsHDROutput; }
IsTransferPQ()87     bool IsTransferPQ() const { return m_IsTransferPQ; }
88 
89     // DX resources registration
90     void Register(ID3DResource *resource);
91     void Unregister(ID3DResource *resource);
92 
93     void FinishCommandList(bool bExecute = true) const;
94     void ClearDepthStencil() const;
95     void ClearRenderTarget(ID3D11RenderTargetView* pRTView, float color[4]) const;
96     void RegisterDeviceNotify(IDeviceNotify* deviceNotify);
97 
98     bool IsStereoAvailable() const;
IsStereoEnabled()99     bool IsStereoEnabled() const { return m_stereoEnabled; }
SetStereoIdx(byte idx)100     void SetStereoIdx(byte idx) { m_backBufferTex.SetViewIdx(idx); }
101 
102     void SetMonitor(HMONITOR monitor);
103     HMONITOR GetMonitor() const;
104 #if defined(TARGET_WINDOWS_DESKTOP)
105     void SetWindow(HWND window);
106 #elif defined(TARGET_WINDOWS_STORE)
107     void Trim() const;
108     void SetWindow(const winrt::Windows::UI::Core::CoreWindow& window);
109     void SetWindowPos(winrt::Windows::Foundation::Rect rect);
110 #endif // TARGET_WINDOWS_STORE
IsNV12SharedTexturesSupported()111     bool IsNV12SharedTexturesSupported() const { return m_NV12SharedTexturesSupport; }
112 
113     // Gets debug info from swapchain
114     DEBUG_INFO_RENDER GetDebugInfo() const;
115 
116   private:
117     class CBackBuffer : public CD3DTexture
118     {
119     public:
CBackBuffer()120       CBackBuffer() : CD3DTexture() {}
SetViewIdx(unsigned idx)121       void SetViewIdx(unsigned idx) { m_viewIdx = idx; }
122       bool Acquire(ID3D11Texture2D* pTexture);
123     };
124 
125     HRESULT CreateSwapChain(DXGI_SWAP_CHAIN_DESC1 &desc, DXGI_SWAP_CHAIN_FULLSCREEN_DESC &fsDesc, IDXGISwapChain1 **ppSwapChain) const;
126     void DestroySwapChain();
127     void CreateDeviceIndependentResources();
128     void CreateDeviceResources();
129     void CreateWindowSizeDependentResources();
130     void UpdateRenderTargetSize();
131     void OnDeviceLost(bool removed);
132     void OnDeviceRestored();
133     void HandleOutputChange(const std::function<bool(DXGI_OUTPUT_DESC)>& cmpFunc);
134     bool CreateFactory();
135     void CheckNV12SharedTexturesSupport();
136 
137     HWND m_window{ nullptr };
138 #if defined(TARGET_WINDOWS_STORE)
139     winrt::Windows::UI::Core::CoreWindow m_coreWindow = nullptr;
140 #endif
141     Microsoft::WRL::ComPtr<IDXGIFactory2> m_dxgiFactory;
142     Microsoft::WRL::ComPtr<IDXGIAdapter1> m_adapter;
143     Microsoft::WRL::ComPtr<IDXGIOutput1> m_output;
144 
145     Microsoft::WRL::ComPtr<ID3D11Device1> m_d3dDevice;
146     Microsoft::WRL::ComPtr<ID3D11DeviceContext1> m_d3dContext;
147     Microsoft::WRL::ComPtr<ID3D11DeviceContext1> m_deferrContext;
148     Microsoft::WRL::ComPtr<IDXGISwapChain1> m_swapChain;
149 #ifdef _DEBUG
150     Microsoft::WRL::ComPtr<ID3D11Debug> m_d3dDebug;
151 #endif
152 
153     CBackBuffer m_backBufferTex;
154     Microsoft::WRL::ComPtr<ID3D11DepthStencilView> m_d3dDepthStencilView;
155     D3D11_VIEWPORT m_screenViewport;
156 
157     // Cached device properties.
158     D3D_FEATURE_LEVEL m_d3dFeatureLevel;
159     winrt::Windows::Foundation::Size m_outputSize;
160     winrt::Windows::Foundation::Size m_logicalSize;
161     float m_dpi;
162 
163     // This is the DPI that will be reported back to the app. It takes into account whether the app supports high resolution screens or not.
164     float m_effectiveDpi;
165     // The IDeviceNotify can be held directly as it owns the DeviceResources.
166     IDeviceNotify* m_deviceNotify;
167 
168     // scritical section
169     Concurrency::critical_section m_criticalSection;
170     Concurrency::critical_section m_resourceSection;
171     std::vector<ID3DResource*> m_resources;
172 
173     bool m_stereoEnabled;
174     bool m_bDeviceCreated;
175     bool m_IsHDROutput;
176     bool m_IsTransferPQ;
177     bool m_NV12SharedTexturesSupport{false};
178   };
179 }
180