1 /*****************************************************************************
2  * d3d11_fmt.h : D3D11 helper calls
3  *****************************************************************************
4  * Copyright © 2017 VLC authors, VideoLAN and VideoLabs
5  *
6  * Authors: Steve Lhomme <robux4@gmail.com>
7  *
8  * This program is free software; you can redistribute it and/or modify it
9  * under the terms of the GNU Lesser General Public License as published by
10  * the Free Software Foundation; either version 2.1 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public License
19  * along with this program; if not, write to the Free Software Foundation,
20  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21  *****************************************************************************/
22 
23 #ifndef VLC_VIDEOCHROMA_D3D11_FMT_H_
24 #define VLC_VIDEOCHROMA_D3D11_FMT_H_
25 
26 #include <d3d11.h>
27 #include <d3dcompiler.h>
28 
29 #include "dxgi_fmt.h"
30 
31 DEFINE_GUID(GUID_CONTEXT_MUTEX, 0x472e8835, 0x3f8e, 0x4f93, 0xa0, 0xcb, 0x25, 0x79, 0x77, 0x6c, 0xed, 0x86);
32 
33 /* see https://msdn.microsoft.com/windows/hardware/commercialize/design/compatibility/device-graphics */
34 struct wddm_version
35 {
36     int wddm, d3d_features, revision, build;
37 };
38 
39 typedef struct
40 {
41     ID3D11Device             *d3ddevice;       /* D3D device */
42     ID3D11DeviceContext      *d3dcontext;      /* D3D context */
43     bool                     owner;
44     HANDLE                   context_mutex;
45     struct wddm_version      WDDM;
46     D3D_FEATURE_LEVEL        feature_level;
47 } d3d11_device_t;
48 
49 typedef struct
50 {
51 #if !VLC_WINSTORE_APP
52     HINSTANCE                 hdll;         /* handle of the opened d3d11 dll */
53     HINSTANCE                 compiler_dll; /* handle of the opened d3dcompiler dll */
54     pD3DCompile               OurD3DCompile;
55 #if !defined(NDEBUG) && defined(HAVE_DXGIDEBUG_H)
56     HINSTANCE                 dxgidebug_dll;
57 #endif
58 #endif
59 } d3d11_handle_t;
60 
61 /* owned by the vout for VLC_CODEC_D3D11_OPAQUE */
62 struct picture_sys_t
63 {
64     ID3D11VideoDecoderOutputView  *decoder; /* may be NULL for pictures from the pool */
65     union {
66         ID3D11Texture2D           *texture[D3D11_MAX_SHADER_VIEW];
67         ID3D11Resource            *resource[D3D11_MAX_SHADER_VIEW];
68     };
69     ID3D11DeviceContext           *context;
70     unsigned                      slice_index;
71     ID3D11VideoProcessorInputView  *processorInput;  /* when used as processor input */
72     ID3D11VideoProcessorOutputView *processorOutput; /* when used as processor output */
73     ID3D11ShaderResourceView      *resourceView[D3D11_MAX_SHADER_VIEW];
74     DXGI_FORMAT                   formatTexture;
75 };
76 
77 #include "../codec/avcodec/va_surface.h"
78 
79 picture_sys_t *ActivePictureSys(picture_t *p_pic);
80 
81 /* index to use for texture/resource that use a known DXGI format
82  * (ie not DXGI_FORMAT_UNKNWON) */
83 #define KNOWN_DXGI_INDEX   0
84 
is_d3d11_opaque(vlc_fourcc_t chroma)85 static inline bool is_d3d11_opaque(vlc_fourcc_t chroma)
86 {
87     return chroma == VLC_CODEC_D3D11_OPAQUE ||
88            chroma == VLC_CODEC_D3D11_OPAQUE_10B;
89 }
90 
91 void AcquirePictureSys(picture_sys_t *p_sys);
92 
93 void ReleasePictureSys(picture_sys_t *p_sys);
94 
95 /* map texture planes to resource views */
96 int D3D11_AllocateShaderView(vlc_object_t *obj, ID3D11Device *d3ddevice,
97                              const d3d_format_t *format,
98                              ID3D11Texture2D *p_texture[D3D11_MAX_SHADER_VIEW], UINT slice_index,
99                              ID3D11ShaderResourceView *resourceView[D3D11_MAX_SHADER_VIEW]);
100 #define D3D11_AllocateShaderView(a,b,c,d,e,f)  D3D11_AllocateShaderView(VLC_OBJECT(a),b,c,d,e,f)
101 
102 HRESULT D3D11_CreateDevice(vlc_object_t *obj, d3d11_handle_t *,
103                            bool hw_decoding, d3d11_device_t *out);
104 #define D3D11_CreateDevice(a,b,c,d)  D3D11_CreateDevice( VLC_OBJECT(a), b, c, d )
105 
106 void D3D11_ReleaseDevice(d3d11_device_t *);
107 
108 int D3D11_Create(vlc_object_t *, d3d11_handle_t *, bool with_shaders);
109 #define D3D11_Create(a,b,c) D3D11_Create( VLC_OBJECT(a), b, c )
110 
111 void D3D11_Destroy(d3d11_handle_t *);
112 
113 bool isXboxHardware(ID3D11Device *d3ddev);
114 bool CanUseVoutPool(d3d11_device_t *, UINT slices);
115 IDXGIAdapter *D3D11DeviceAdapter(ID3D11Device *d3ddev);
116 int D3D11CheckDriverVersion(d3d11_device_t *, UINT vendorId,
117                             const struct wddm_version *min_ver);
118 void D3D11_GetDriverVersion(vlc_object_t *, d3d11_device_t *);
119 #define D3D11_GetDriverVersion(a,b) D3D11_GetDriverVersion(VLC_OBJECT(a),b)
120 
DeviceSupportsFormat(ID3D11Device * d3ddevice,DXGI_FORMAT format,UINT supportFlags)121 static inline bool DeviceSupportsFormat(ID3D11Device *d3ddevice,
122                                         DXGI_FORMAT format, UINT supportFlags)
123 {
124     UINT i_formatSupport;
125     return SUCCEEDED( ID3D11Device_CheckFormatSupport(d3ddevice, format,
126                                                       &i_formatSupport) )
127             && ( i_formatSupport & supportFlags ) == supportFlags;
128 }
129 
130 const d3d_format_t *FindD3D11Format(vlc_object_t *,
131                                     d3d11_device_t*,
132                                     vlc_fourcc_t i_src_chroma,
133                                     bool rgb_only,
134                                     uint8_t bits_per_channel,
135                                     uint8_t widthDenominator,
136                                     uint8_t heightDenominator,
137                                     bool allow_opaque,
138                                     UINT supportFlags);
139 #define FindD3D11Format(a,b,c,d,e,f,g,h,i)  \
140     FindD3D11Format(VLC_OBJECT(a),b,c,d,e,f,g,h,i)
141 
142 int AllocateTextures(vlc_object_t *, d3d11_device_t *, const d3d_format_t *,
143                      const video_format_t *, unsigned pool_size, ID3D11Texture2D *textures[]);
144 #define AllocateTextures(a,b,c,d,e,f)  AllocateTextures(VLC_OBJECT(a),b,c,d,e,f)
145 
146 #ifndef NDEBUG
147 void D3D11_LogProcessorSupport(vlc_object_t*, ID3D11VideoProcessorEnumerator*);
148 #define D3D11_LogProcessorSupport(a,b) D3D11_LogProcessorSupport( VLC_OBJECT(a), b )
149 #endif
150 
d3d11_device_lock(d3d11_device_t * d3d_dev)151 static inline void d3d11_device_lock(d3d11_device_t *d3d_dev)
152 {
153     if( d3d_dev->context_mutex != INVALID_HANDLE_VALUE )
154         WaitForSingleObjectEx( d3d_dev->context_mutex, INFINITE, FALSE );
155 }
156 
d3d11_device_unlock(d3d11_device_t * d3d_dev)157 static inline void d3d11_device_unlock(d3d11_device_t *d3d_dev)
158 {
159     if( d3d_dev->context_mutex  != INVALID_HANDLE_VALUE )
160         ReleaseMutex( d3d_dev->context_mutex );
161 }
162 
163 #endif /* include-guard */
164