FreeRDP
win_dxgi.c
1 
19 #include <freerdp/config.h>
20 
21 #include <winpr/crt.h>
22 #include <winpr/print.h>
23 #include <winpr/library.h>
24 #include <freerdp/log.h>
25 
26 #include "win_dxgi.h"
27 
28 #define TAG SERVER_TAG("shadow.win")
29 
30 #ifdef WITH_DXGI_1_2
31 
32 static D3D_DRIVER_TYPE DriverTypes[] = {
33  D3D_DRIVER_TYPE_HARDWARE,
34  D3D_DRIVER_TYPE_WARP,
35  D3D_DRIVER_TYPE_REFERENCE,
36 };
37 
38 static UINT NumDriverTypes = ARRAYSIZE(DriverTypes);
39 
40 static D3D_FEATURE_LEVEL FeatureLevels[] = { D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1,
41  D3D_FEATURE_LEVEL_10_0, D3D_FEATURE_LEVEL_9_1 };
42 
43 static UINT NumFeatureLevels = ARRAYSIZE(FeatureLevels);
44 
45 static HMODULE d3d11_module = NULL;
46 
47 typedef HRESULT(WINAPI* fnD3D11CreateDevice)(IDXGIAdapter* pAdapter, D3D_DRIVER_TYPE DriverType,
48  HMODULE Software, UINT Flags,
49  CONST D3D_FEATURE_LEVEL* pFeatureLevels,
50  UINT FeatureLevels, UINT SDKVersion,
51  ID3D11Device** ppDevice,
52  D3D_FEATURE_LEVEL* pFeatureLevel,
53  ID3D11DeviceContext** ppImmediateContext);
54 
55 static fnD3D11CreateDevice pfnD3D11CreateDevice = NULL;
56 
57 #undef DEFINE_GUID
58 #define INITGUID
59 
60 #include <initguid.h>
61 
62 /* d3d11.h GUIDs */
63 
64 DEFINE_GUID(IID_ID3D11DeviceChild, 0x1841e5c8, 0x16b0, 0x489b, 0xbc, 0xc8, 0x44, 0xcf, 0xb0, 0xd5,
65  0xde, 0xae);
66 DEFINE_GUID(IID_ID3D11DepthStencilState, 0x03823efb, 0x8d8f, 0x4e1c, 0x9a, 0xa2, 0xf6, 0x4b, 0xb2,
67  0xcb, 0xfd, 0xf1);
68 DEFINE_GUID(IID_ID3D11BlendState, 0x75b68faa, 0x347d, 0x4159, 0x8f, 0x45, 0xa0, 0x64, 0x0f, 0x01,
69  0xcd, 0x9a);
70 DEFINE_GUID(IID_ID3D11RasterizerState, 0x9bb4ab81, 0xab1a, 0x4d8f, 0xb5, 0x06, 0xfc, 0x04, 0x20,
71  0x0b, 0x6e, 0xe7);
72 DEFINE_GUID(IID_ID3D11Resource, 0xdc8e63f3, 0xd12b, 0x4952, 0xb4, 0x7b, 0x5e, 0x45, 0x02, 0x6a,
73  0x86, 0x2d);
74 DEFINE_GUID(IID_ID3D11Buffer, 0x48570b85, 0xd1ee, 0x4fcd, 0xa2, 0x50, 0xeb, 0x35, 0x07, 0x22, 0xb0,
75  0x37);
76 DEFINE_GUID(IID_ID3D11Texture1D, 0xf8fb5c27, 0xc6b3, 0x4f75, 0xa4, 0xc8, 0x43, 0x9a, 0xf2, 0xef,
77  0x56, 0x4c);
78 DEFINE_GUID(IID_ID3D11Texture2D, 0x6f15aaf2, 0xd208, 0x4e89, 0x9a, 0xb4, 0x48, 0x95, 0x35, 0xd3,
79  0x4f, 0x9c);
80 DEFINE_GUID(IID_ID3D11Texture3D, 0x037e866e, 0xf56d, 0x4357, 0xa8, 0xaf, 0x9d, 0xab, 0xbe, 0x6e,
81  0x25, 0x0e);
82 DEFINE_GUID(IID_ID3D11View, 0x839d1216, 0xbb2e, 0x412b, 0xb7, 0xf4, 0xa9, 0xdb, 0xeb, 0xe0, 0x8e,
83  0xd1);
84 DEFINE_GUID(IID_ID3D11ShaderResourceView, 0xb0e06fe0, 0x8192, 0x4e1a, 0xb1, 0xca, 0x36, 0xd7, 0x41,
85  0x47, 0x10, 0xb2);
86 DEFINE_GUID(IID_ID3D11RenderTargetView, 0xdfdba067, 0x0b8d, 0x4865, 0x87, 0x5b, 0xd7, 0xb4, 0x51,
87  0x6c, 0xc1, 0x64);
88 DEFINE_GUID(IID_ID3D11DepthStencilView, 0x9fdac92a, 0x1876, 0x48c3, 0xaf, 0xad, 0x25, 0xb9, 0x4f,
89  0x84, 0xa9, 0xb6);
90 DEFINE_GUID(IID_ID3D11UnorderedAccessView, 0x28acf509, 0x7f5c, 0x48f6, 0x86, 0x11, 0xf3, 0x16, 0x01,
91  0x0a, 0x63, 0x80);
92 DEFINE_GUID(IID_ID3D11VertexShader, 0x3b301d64, 0xd678, 0x4289, 0x88, 0x97, 0x22, 0xf8, 0x92, 0x8b,
93  0x72, 0xf3);
94 DEFINE_GUID(IID_ID3D11HullShader, 0x8e5c6061, 0x628a, 0x4c8e, 0x82, 0x64, 0xbb, 0xe4, 0x5c, 0xb3,
95  0xd5, 0xdd);
96 DEFINE_GUID(IID_ID3D11DomainShader, 0xf582c508, 0x0f36, 0x490c, 0x99, 0x77, 0x31, 0xee, 0xce, 0x26,
97  0x8c, 0xfa);
98 DEFINE_GUID(IID_ID3D11GeometryShader, 0x38325b96, 0xeffb, 0x4022, 0xba, 0x02, 0x2e, 0x79, 0x5b,
99  0x70, 0x27, 0x5c);
100 DEFINE_GUID(IID_ID3D11PixelShader, 0xea82e40d, 0x51dc, 0x4f33, 0x93, 0xd4, 0xdb, 0x7c, 0x91, 0x25,
101  0xae, 0x8c);
102 DEFINE_GUID(IID_ID3D11ComputeShader, 0x4f5b196e, 0xc2bd, 0x495e, 0xbd, 0x01, 0x1f, 0xde, 0xd3, 0x8e,
103  0x49, 0x69);
104 DEFINE_GUID(IID_ID3D11InputLayout, 0xe4819ddc, 0x4cf0, 0x4025, 0xbd, 0x26, 0x5d, 0xe8, 0x2a, 0x3e,
105  0x07, 0xb7);
106 DEFINE_GUID(IID_ID3D11SamplerState, 0xda6fea51, 0x564c, 0x4487, 0x98, 0x10, 0xf0, 0xd0, 0xf9, 0xb4,
107  0xe3, 0xa5);
108 DEFINE_GUID(IID_ID3D11Asynchronous, 0x4b35d0cd, 0x1e15, 0x4258, 0x9c, 0x98, 0x1b, 0x13, 0x33, 0xf6,
109  0xdd, 0x3b);
110 DEFINE_GUID(IID_ID3D11Query, 0xd6c00747, 0x87b7, 0x425e, 0xb8, 0x4d, 0x44, 0xd1, 0x08, 0x56, 0x0a,
111  0xfd);
112 DEFINE_GUID(IID_ID3D11Predicate, 0x9eb576dd, 0x9f77, 0x4d86, 0x81, 0xaa, 0x8b, 0xab, 0x5f, 0xe4,
113  0x90, 0xe2);
114 DEFINE_GUID(IID_ID3D11Counter, 0x6e8c49fb, 0xa371, 0x4770, 0xb4, 0x40, 0x29, 0x08, 0x60, 0x22, 0xb7,
115  0x41);
116 DEFINE_GUID(IID_ID3D11ClassInstance, 0xa6cd7faa, 0xb0b7, 0x4a2f, 0x94, 0x36, 0x86, 0x62, 0xa6, 0x57,
117  0x97, 0xcb);
118 DEFINE_GUID(IID_ID3D11ClassLinkage, 0xddf57cba, 0x9543, 0x46e4, 0xa1, 0x2b, 0xf2, 0x07, 0xa0, 0xfe,
119  0x7f, 0xed);
120 DEFINE_GUID(IID_ID3D11CommandList, 0xa24bc4d1, 0x769e, 0x43f7, 0x80, 0x13, 0x98, 0xff, 0x56, 0x6c,
121  0x18, 0xe2);
122 DEFINE_GUID(IID_ID3D11DeviceContext, 0xc0bfa96c, 0xe089, 0x44fb, 0x8e, 0xaf, 0x26, 0xf8, 0x79, 0x61,
123  0x90, 0xda);
124 DEFINE_GUID(IID_ID3D11VideoDecoder, 0x3C9C5B51, 0x995D, 0x48d1, 0x9B, 0x8D, 0xFA, 0x5C, 0xAE, 0xDE,
125  0xD6, 0x5C);
126 DEFINE_GUID(IID_ID3D11VideoProcessorEnumerator, 0x31627037, 0x53AB, 0x4200, 0x90, 0x61, 0x05, 0xFA,
127  0xA9, 0xAB, 0x45, 0xF9);
128 DEFINE_GUID(IID_ID3D11VideoProcessor, 0x1D7B0652, 0x185F, 0x41c6, 0x85, 0xCE, 0x0C, 0x5B, 0xE3,
129  0xD4, 0xAE, 0x6C);
130 DEFINE_GUID(IID_ID3D11AuthenticatedChannel, 0x3015A308, 0xDCBD, 0x47aa, 0xA7, 0x47, 0x19, 0x24,
131  0x86, 0xD1, 0x4D, 0x4A);
132 DEFINE_GUID(IID_ID3D11CryptoSession, 0x9B32F9AD, 0xBDCC, 0x40a6, 0xA3, 0x9D, 0xD5, 0xC8, 0x65, 0x84,
133  0x57, 0x20);
134 DEFINE_GUID(IID_ID3D11VideoDecoderOutputView, 0xC2931AEA, 0x2A85, 0x4f20, 0x86, 0x0F, 0xFB, 0xA1,
135  0xFD, 0x25, 0x6E, 0x18);
136 DEFINE_GUID(IID_ID3D11VideoProcessorInputView, 0x11EC5A5F, 0x51DC, 0x4945, 0xAB, 0x34, 0x6E, 0x8C,
137  0x21, 0x30, 0x0E, 0xA5);
138 DEFINE_GUID(IID_ID3D11VideoProcessorOutputView, 0xA048285E, 0x25A9, 0x4527, 0xBD, 0x93, 0xD6, 0x8B,
139  0x68, 0xC4, 0x42, 0x54);
140 DEFINE_GUID(IID_ID3D11VideoContext, 0x61F21C45, 0x3C0E, 0x4a74, 0x9C, 0xEA, 0x67, 0x10, 0x0D, 0x9A,
141  0xD5, 0xE4);
142 DEFINE_GUID(IID_ID3D11VideoDevice, 0x10EC4D5B, 0x975A, 0x4689, 0xB9, 0xE4, 0xD0, 0xAA, 0xC3, 0x0F,
143  0xE3, 0x33);
144 DEFINE_GUID(IID_ID3D11Device, 0xdb6f6ddb, 0xac77, 0x4e88, 0x82, 0x53, 0x81, 0x9d, 0xf9, 0xbb, 0xf1,
145  0x40);
146 
147 /* dxgi.h GUIDs */
148 
149 DEFINE_GUID(IID_IDXGIObject, 0xaec22fb8, 0x76f3, 0x4639, 0x9b, 0xe0, 0x28, 0xeb, 0x43, 0xa6, 0x7a,
150  0x2e);
151 DEFINE_GUID(IID_IDXGIDeviceSubObject, 0x3d3e0379, 0xf9de, 0x4d58, 0xbb, 0x6c, 0x18, 0xd6, 0x29,
152  0x92, 0xf1, 0xa6);
153 DEFINE_GUID(IID_IDXGIResource, 0x035f3ab4, 0x482e, 0x4e50, 0xb4, 0x1f, 0x8a, 0x7f, 0x8b, 0xd8, 0x96,
154  0x0b);
155 DEFINE_GUID(IID_IDXGIKeyedMutex, 0x9d8e1289, 0xd7b3, 0x465f, 0x81, 0x26, 0x25, 0x0e, 0x34, 0x9a,
156  0xf8, 0x5d);
157 DEFINE_GUID(IID_IDXGISurface, 0xcafcb56c, 0x6ac3, 0x4889, 0xbf, 0x47, 0x9e, 0x23, 0xbb, 0xd2, 0x60,
158  0xec);
159 DEFINE_GUID(IID_IDXGISurface1, 0x4AE63092, 0x6327, 0x4c1b, 0x80, 0xAE, 0xBF, 0xE1, 0x2E, 0xA3, 0x2B,
160  0x86);
161 DEFINE_GUID(IID_IDXGIAdapter, 0x2411e7e1, 0x12ac, 0x4ccf, 0xbd, 0x14, 0x97, 0x98, 0xe8, 0x53, 0x4d,
162  0xc0);
163 DEFINE_GUID(IID_IDXGIOutput, 0xae02eedb, 0xc735, 0x4690, 0x8d, 0x52, 0x5a, 0x8d, 0xc2, 0x02, 0x13,
164  0xaa);
165 DEFINE_GUID(IID_IDXGISwapChain, 0x310d36a0, 0xd2e7, 0x4c0a, 0xaa, 0x04, 0x6a, 0x9d, 0x23, 0xb8,
166  0x88, 0x6a);
167 DEFINE_GUID(IID_IDXGIFactory, 0x7b7166ec, 0x21c7, 0x44ae, 0xb2, 0x1a, 0xc9, 0xae, 0x32, 0x1a, 0xe3,
168  0x69);
169 DEFINE_GUID(IID_IDXGIDevice, 0x54ec77fa, 0x1377, 0x44e6, 0x8c, 0x32, 0x88, 0xfd, 0x5f, 0x44, 0xc8,
170  0x4c);
171 DEFINE_GUID(IID_IDXGIFactory1, 0x770aae78, 0xf26f, 0x4dba, 0xa8, 0x29, 0x25, 0x3c, 0x83, 0xd1, 0xb3,
172  0x87);
173 DEFINE_GUID(IID_IDXGIAdapter1, 0x29038f61, 0x3839, 0x4626, 0x91, 0xfd, 0x08, 0x68, 0x79, 0x01, 0x1a,
174  0x05);
175 DEFINE_GUID(IID_IDXGIDevice1, 0x77db970f, 0x6276, 0x48ba, 0xba, 0x28, 0x07, 0x01, 0x43, 0xb4, 0x39,
176  0x2c);
177 
178 /* dxgi1_2.h GUIDs */
179 
180 DEFINE_GUID(IID_IDXGIDisplayControl, 0xea9dbf1a, 0xc88e, 0x4486, 0x85, 0x4a, 0x98, 0xaa, 0x01, 0x38,
181  0xf3, 0x0c);
182 DEFINE_GUID(IID_IDXGIOutputDuplication, 0x191cfac3, 0xa341, 0x470d, 0xb2, 0x6e, 0xa8, 0x64, 0xf4,
183  0x28, 0x31, 0x9c);
184 DEFINE_GUID(IID_IDXGISurface2, 0xaba496dd, 0xb617, 0x4cb8, 0xa8, 0x66, 0xbc, 0x44, 0xd7, 0xeb, 0x1f,
185  0xa2);
186 DEFINE_GUID(IID_IDXGIResource1, 0x30961379, 0x4609, 0x4a41, 0x99, 0x8e, 0x54, 0xfe, 0x56, 0x7e,
187  0xe0, 0xc1);
188 DEFINE_GUID(IID_IDXGIDevice2, 0x05008617, 0xfbfd, 0x4051, 0xa7, 0x90, 0x14, 0x48, 0x84, 0xb4, 0xf6,
189  0xa9);
190 DEFINE_GUID(IID_IDXGISwapChain1, 0x790a45f7, 0x0d42, 0x4876, 0x98, 0x3a, 0x0a, 0x55, 0xcf, 0xe6,
191  0xf4, 0xaa);
192 DEFINE_GUID(IID_IDXGIFactory2, 0x50c83a1c, 0xe072, 0x4c48, 0x87, 0xb0, 0x36, 0x30, 0xfa, 0x36, 0xa6,
193  0xd0);
194 DEFINE_GUID(IID_IDXGIAdapter2, 0x0AA1AE0A, 0xFA0E, 0x4B84, 0x86, 0x44, 0xE0, 0x5F, 0xF8, 0xE5, 0xAC,
195  0xB5);
196 DEFINE_GUID(IID_IDXGIOutput1, 0x00cddea8, 0x939b, 0x4b83, 0xa3, 0x40, 0xa6, 0x85, 0x22, 0x66, 0x66,
197  0xcc);
198 
199 const char* GetDxgiErrorString(HRESULT hr)
200 {
201  switch (hr)
202  {
203  case DXGI_STATUS_OCCLUDED:
204  return "DXGI_STATUS_OCCLUDED";
205  case DXGI_STATUS_CLIPPED:
206  return "DXGI_STATUS_CLIPPED";
207  case DXGI_STATUS_NO_REDIRECTION:
208  return "DXGI_STATUS_NO_REDIRECTION";
209  case DXGI_STATUS_NO_DESKTOP_ACCESS:
210  return "DXGI_STATUS_NO_DESKTOP_ACCESS";
211  case DXGI_STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE:
212  return "DXGI_STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE";
213  case DXGI_STATUS_MODE_CHANGED:
214  return "DXGI_STATUS_MODE_CHANGED";
215  case DXGI_STATUS_MODE_CHANGE_IN_PROGRESS:
216  return "DXGI_STATUS_MODE_CHANGE_IN_PROGRESS";
217  case DXGI_ERROR_INVALID_CALL:
218  return "DXGI_ERROR_INVALID_CALL";
219  case DXGI_ERROR_NOT_FOUND:
220  return "DXGI_ERROR_NOT_FOUND";
221  case DXGI_ERROR_MORE_DATA:
222  return "DXGI_ERROR_MORE_DATA";
223  case DXGI_ERROR_UNSUPPORTED:
224  return "DXGI_ERROR_UNSUPPORTED";
225  case DXGI_ERROR_DEVICE_REMOVED:
226  return "DXGI_ERROR_DEVICE_REMOVED";
227  case DXGI_ERROR_DEVICE_HUNG:
228  return "DXGI_ERROR_DEVICE_HUNG";
229  case DXGI_ERROR_DEVICE_RESET:
230  return "DXGI_ERROR_DEVICE_RESET";
231  case DXGI_ERROR_WAS_STILL_DRAWING:
232  return "DXGI_ERROR_WAS_STILL_DRAWING";
233  case DXGI_ERROR_FRAME_STATISTICS_DISJOINT:
234  return "DXGI_ERROR_FRAME_STATISTICS_DISJOINT";
235  case DXGI_ERROR_GRAPHICS_VIDPN_SOURCE_IN_USE:
236  return "DXGI_ERROR_GRAPHICS_VIDPN_SOURCE_IN_USE";
237  case DXGI_ERROR_DRIVER_INTERNAL_ERROR:
238  return "DXGI_ERROR_DRIVER_INTERNAL_ERROR";
239  case DXGI_ERROR_NONEXCLUSIVE:
240  return "DXGI_ERROR_NONEXCLUSIVE";
241  case DXGI_ERROR_NOT_CURRENTLY_AVAILABLE:
242  return "DXGI_ERROR_NOT_CURRENTLY_AVAILABLE";
243  case DXGI_ERROR_REMOTE_CLIENT_DISCONNECTED:
244  return "DXGI_ERROR_REMOTE_CLIENT_DISCONNECTED";
245  case DXGI_ERROR_REMOTE_OUTOFMEMORY:
246  return "DXGI_ERROR_REMOTE_OUTOFMEMORY";
247  case DXGI_ERROR_ACCESS_LOST:
248  return "DXGI_ERROR_ACCESS_LOST";
249  case DXGI_ERROR_WAIT_TIMEOUT:
250  return "DXGI_ERROR_WAIT_TIMEOUT";
251  case DXGI_ERROR_SESSION_DISCONNECTED:
252  return "DXGI_ERROR_SESSION_DISCONNECTED";
253  case DXGI_ERROR_RESTRICT_TO_OUTPUT_STALE:
254  return "DXGI_ERROR_RESTRICT_TO_OUTPUT_STALE";
255  case DXGI_ERROR_CANNOT_PROTECT_CONTENT:
256  return "DXGI_ERROR_CANNOT_PROTECT_CONTENT";
257  case DXGI_ERROR_ACCESS_DENIED:
258  return "DXGI_ERROR_ACCESS_DENIED";
259  case DXGI_ERROR_NAME_ALREADY_EXISTS:
260  return "DXGI_ERROR_NAME_ALREADY_EXISTS";
261  case DXGI_ERROR_SDK_COMPONENT_MISSING:
262  return "DXGI_ERROR_SDK_COMPONENT_MISSING";
263  case DXGI_STATUS_UNOCCLUDED:
264  return "DXGI_STATUS_UNOCCLUDED";
265  case DXGI_STATUS_DDA_WAS_STILL_DRAWING:
266  return "DXGI_STATUS_DDA_WAS_STILL_DRAWING";
267  case DXGI_ERROR_MODE_CHANGE_IN_PROGRESS:
268  return "DXGI_ERROR_MODE_CHANGE_IN_PROGRESS";
269  case DXGI_DDI_ERR_WASSTILLDRAWING:
270  return "DXGI_DDI_ERR_WASSTILLDRAWING";
271  case DXGI_DDI_ERR_UNSUPPORTED:
272  return "DXGI_DDI_ERR_UNSUPPORTED";
273  case DXGI_DDI_ERR_NONEXCLUSIVE:
274  return "DXGI_DDI_ERR_NONEXCLUSIVE";
275  case 0x80070005:
276  return "DXGI_ERROR_ACCESS_DENIED";
277  }
278 
279  return "DXGI_ERROR_UNKNOWN";
280 }
281 
282 static void win_shadow_d3d11_module_init()
283 {
284  if (d3d11_module)
285  return;
286 
287  d3d11_module = LoadLibraryA("d3d11.dll");
288 
289  if (!d3d11_module)
290  return;
291 
292  pfnD3D11CreateDevice = GetProcAddressAs(d3d11_module, "D3D11CreateDevice", fnD3D11CreateDevice);
293 }
294 
295 int win_shadow_dxgi_init_duplication(winShadowSubsystem* subsystem)
296 {
297  HRESULT hr;
298  UINT dTop, i = 0;
299  IDXGIOutput* pOutput;
300  DXGI_OUTPUT_DESC outputDesc = { 0 };
301  DXGI_OUTPUT_DESC* pOutputDesc;
302  D3D11_TEXTURE2D_DESC textureDesc;
303  IDXGIDevice* dxgiDevice = NULL;
304  IDXGIAdapter* dxgiAdapter = NULL;
305  IDXGIOutput* dxgiOutput = NULL;
306  IDXGIOutput1* dxgiOutput1 = NULL;
307 
308  hr = subsystem->dxgiDevice->lpVtbl->QueryInterface(subsystem->dxgiDevice, &IID_IDXGIDevice,
309  (void**)&dxgiDevice);
310 
311  if (FAILED(hr))
312  {
313  WLog_ERR(TAG, "ID3D11Device::QueryInterface(IDXGIDevice) failure: %s (0x%08lX)",
314  GetDxgiErrorString(hr), hr);
315  return -1;
316  }
317 
318  hr = dxgiDevice->lpVtbl->GetParent(dxgiDevice, &IID_IDXGIAdapter, (void**)&dxgiAdapter);
319 
320  if (dxgiDevice)
321  {
322  dxgiDevice->lpVtbl->Release(dxgiDevice);
323  dxgiDevice = NULL;
324  }
325 
326  if (FAILED(hr))
327  {
328  WLog_ERR(TAG, "IDXGIDevice::GetParent(IDXGIAdapter) failure: %s (0x%08lX)",
329  GetDxgiErrorString(hr), hr);
330  return -1;
331  }
332 
333  pOutput = NULL;
334 
335  while (dxgiAdapter->lpVtbl->EnumOutputs(dxgiAdapter, i, &pOutput) != DXGI_ERROR_NOT_FOUND)
336  {
337  pOutputDesc = &outputDesc;
338 
339  hr = pOutput->lpVtbl->GetDesc(pOutput, pOutputDesc);
340 
341  if (FAILED(hr))
342  {
343  WLog_ERR(TAG, "IDXGIOutput::GetDesc failure: %s (0x%08lX)", GetDxgiErrorString(hr), hr);
344  return -1;
345  }
346 
347  if (pOutputDesc->AttachedToDesktop)
348  dTop = i;
349 
350  pOutput->lpVtbl->Release(pOutput);
351  i++;
352  }
353 
354  dTop = 0; /* screen id */
355 
356  hr = dxgiAdapter->lpVtbl->EnumOutputs(dxgiAdapter, dTop, &dxgiOutput);
357 
358  if (dxgiAdapter)
359  {
360  dxgiAdapter->lpVtbl->Release(dxgiAdapter);
361  dxgiAdapter = NULL;
362  }
363 
364  if (FAILED(hr))
365  {
366  WLog_ERR(TAG, "IDXGIAdapter::EnumOutputs failure: %s (0x%08lX)", GetDxgiErrorString(hr),
367  hr);
368  return -1;
369  }
370 
371  hr = dxgiOutput->lpVtbl->QueryInterface(dxgiOutput, &IID_IDXGIOutput1, (void**)&dxgiOutput1);
372 
373  if (dxgiOutput)
374  {
375  dxgiOutput->lpVtbl->Release(dxgiOutput);
376  dxgiOutput = NULL;
377  }
378 
379  if (FAILED(hr))
380  {
381  WLog_ERR(TAG, "IDXGIOutput::QueryInterface(IDXGIOutput1) failure: %s (0x%08lX)",
382  GetDxgiErrorString(hr), hr);
383  return -1;
384  }
385 
386  hr = dxgiOutput1->lpVtbl->DuplicateOutput(dxgiOutput1, (IUnknown*)subsystem->dxgiDevice,
387  &(subsystem->dxgiOutputDuplication));
388 
389  if (dxgiOutput1)
390  {
391  dxgiOutput1->lpVtbl->Release(dxgiOutput1);
392  dxgiOutput1 = NULL;
393  }
394 
395  if (FAILED(hr))
396  {
397  WLog_ERR(TAG, "IDXGIOutput1::DuplicateOutput failure: %s (0x%08lX)", GetDxgiErrorString(hr),
398  hr);
399  return -1;
400  }
401 
402  textureDesc.Width = subsystem->width;
403  textureDesc.Height = subsystem->height;
404  textureDesc.MipLevels = 1;
405  textureDesc.ArraySize = 1;
406  textureDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
407  textureDesc.SampleDesc.Count = 1;
408  textureDesc.SampleDesc.Quality = 0;
409  textureDesc.Usage = D3D11_USAGE_STAGING;
410  textureDesc.BindFlags = 0;
411  textureDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
412  textureDesc.MiscFlags = 0;
413 
414  hr = subsystem->dxgiDevice->lpVtbl->CreateTexture2D(subsystem->dxgiDevice, &textureDesc, NULL,
415  &(subsystem->dxgiStage));
416 
417  if (FAILED(hr))
418  {
419  WLog_ERR(TAG, "ID3D11Device::CreateTexture2D failure: %s (0x%08lX)", GetDxgiErrorString(hr),
420  hr);
421  return -1;
422  }
423 
424  return 1;
425 }
426 
427 int win_shadow_dxgi_init(winShadowSubsystem* subsystem)
428 {
429  UINT i = 0;
430  HRESULT hr;
431  int status;
432  UINT DriverTypeIndex;
433  IDXGIDevice* DxgiDevice = NULL;
434  IDXGIAdapter* DxgiAdapter = NULL;
435  IDXGIOutput* DxgiOutput = NULL;
436  IDXGIOutput1* DxgiOutput1 = NULL;
437 
438  win_shadow_d3d11_module_init();
439 
440  if (!pfnD3D11CreateDevice)
441  return -1;
442 
443  for (DriverTypeIndex = 0; DriverTypeIndex < NumDriverTypes; ++DriverTypeIndex)
444  {
445  hr = pfnD3D11CreateDevice(NULL, DriverTypes[DriverTypeIndex], NULL, 0, FeatureLevels,
446  NumFeatureLevels, D3D11_SDK_VERSION, &(subsystem->dxgiDevice),
447  &(subsystem->featureLevel), &(subsystem->dxgiDeviceContext));
448 
449  if (SUCCEEDED(hr))
450  break;
451  }
452 
453  if (FAILED(hr))
454  {
455  WLog_ERR(TAG, "D3D11CreateDevice failure: 0x%08lX", hr);
456  return -1;
457  }
458 
459  status = win_shadow_dxgi_init_duplication(subsystem);
460 
461  return status;
462 }
463 
464 int win_shadow_dxgi_uninit(winShadowSubsystem* subsystem)
465 {
466  if (subsystem->dxgiStage)
467  {
468  subsystem->dxgiStage->lpVtbl->Release(subsystem->dxgiStage);
469  subsystem->dxgiStage = NULL;
470  }
471 
472  if (subsystem->dxgiDesktopImage)
473  {
474  subsystem->dxgiDesktopImage->lpVtbl->Release(subsystem->dxgiDesktopImage);
475  subsystem->dxgiDesktopImage = NULL;
476  }
477 
478  if (subsystem->dxgiOutputDuplication)
479  {
480  subsystem->dxgiOutputDuplication->lpVtbl->Release(subsystem->dxgiOutputDuplication);
481  subsystem->dxgiOutputDuplication = NULL;
482  }
483 
484  if (subsystem->dxgiDeviceContext)
485  {
486  subsystem->dxgiDeviceContext->lpVtbl->Release(subsystem->dxgiDeviceContext);
487  subsystem->dxgiDeviceContext = NULL;
488  }
489 
490  if (subsystem->dxgiDevice)
491  {
492  subsystem->dxgiDevice->lpVtbl->Release(subsystem->dxgiDevice);
493  subsystem->dxgiDevice = NULL;
494  }
495 
496  return 1;
497 }
498 
499 int win_shadow_dxgi_fetch_frame_data(winShadowSubsystem* subsystem, BYTE** ppDstData,
500  int* pnDstStep, int x, int y, int width, int height)
501 {
502  int status;
503  HRESULT hr;
504  D3D11_BOX Box;
505  DXGI_MAPPED_RECT mappedRect;
506 
507  if ((width * height) < 1)
508  return 0;
509 
510  Box.top = x;
511  Box.left = y;
512  Box.right = x + width;
513  Box.bottom = y + height;
514  Box.front = 0;
515  Box.back = 1;
516 
517  subsystem->dxgiDeviceContext->lpVtbl->CopySubresourceRegion(
518  subsystem->dxgiDeviceContext, (ID3D11Resource*)subsystem->dxgiStage, 0, 0, 0, 0,
519  (ID3D11Resource*)subsystem->dxgiDesktopImage, 0, &Box);
520 
521  hr = subsystem->dxgiStage->lpVtbl->QueryInterface(subsystem->dxgiStage, &IID_IDXGISurface,
522  (void**)&(subsystem->dxgiSurface));
523 
524  if (FAILED(hr))
525  {
526  WLog_ERR(TAG, "ID3D11Texture2D::QueryInterface(IDXGISurface) failure: %s 0x%08lX",
527  GetDxgiErrorString(hr), hr);
528  return -1;
529  }
530 
531  hr = subsystem->dxgiSurface->lpVtbl->Map(subsystem->dxgiSurface, &mappedRect, DXGI_MAP_READ);
532 
533  if (FAILED(hr))
534  {
535  WLog_ERR(TAG, "IDXGISurface::Map failure: %s 0x%08lX", GetDxgiErrorString(hr), hr);
536 
537  if (hr == DXGI_ERROR_DEVICE_REMOVED)
538  {
539  win_shadow_dxgi_uninit(subsystem);
540 
541  status = win_shadow_dxgi_init(subsystem);
542 
543  if (status < 0)
544  return -1;
545 
546  return 0;
547  }
548 
549  return -1;
550  }
551 
552  subsystem->dxgiSurfaceMapped = TRUE;
553 
554  *ppDstData = mappedRect.pBits;
555  *pnDstStep = mappedRect.Pitch;
556 
557  return 1;
558 }
559 
560 int win_shadow_dxgi_release_frame_data(winShadowSubsystem* subsystem)
561 {
562  if (subsystem->dxgiSurface)
563  {
564  if (subsystem->dxgiSurfaceMapped)
565  {
566  subsystem->dxgiSurface->lpVtbl->Unmap(subsystem->dxgiSurface);
567  subsystem->dxgiSurfaceMapped = FALSE;
568  }
569 
570  subsystem->dxgiSurface->lpVtbl->Release(subsystem->dxgiSurface);
571  subsystem->dxgiSurface = NULL;
572  }
573 
574  if (subsystem->dxgiOutputDuplication)
575  {
576  if (subsystem->dxgiFrameAcquired)
577  {
578  subsystem->dxgiOutputDuplication->lpVtbl->ReleaseFrame(
579  subsystem->dxgiOutputDuplication);
580  subsystem->dxgiFrameAcquired = FALSE;
581  }
582  }
583 
584  subsystem->pendingFrames = 0;
585 
586  return 1;
587 }
588 
589 int win_shadow_dxgi_get_next_frame(winShadowSubsystem* subsystem)
590 {
591  UINT i = 0;
592  int status;
593  HRESULT hr = 0;
594  UINT timeout = 15;
595  UINT DataBufferSize = 0;
596  BYTE* DataBuffer = NULL;
597 
598  if (subsystem->dxgiFrameAcquired)
599  {
600  win_shadow_dxgi_release_frame_data(subsystem);
601  }
602 
603  if (subsystem->dxgiDesktopImage)
604  {
605  subsystem->dxgiDesktopImage->lpVtbl->Release(subsystem->dxgiDesktopImage);
606  subsystem->dxgiDesktopImage = NULL;
607  }
608 
609  hr = subsystem->dxgiOutputDuplication->lpVtbl->AcquireNextFrame(
610  subsystem->dxgiOutputDuplication, timeout, &(subsystem->dxgiFrameInfo),
611  &(subsystem->dxgiResource));
612 
613  if (SUCCEEDED(hr))
614  {
615  subsystem->dxgiFrameAcquired = TRUE;
616  subsystem->pendingFrames = subsystem->dxgiFrameInfo.AccumulatedFrames;
617  }
618 
619  if (hr == DXGI_ERROR_WAIT_TIMEOUT)
620  return 0;
621 
622  if (FAILED(hr))
623  {
624  WLog_ERR(TAG, "IDXGIOutputDuplication::AcquireNextFrame failure: %s (0x%08lX)",
625  GetDxgiErrorString(hr), hr);
626 
627  if (hr == DXGI_ERROR_ACCESS_LOST)
628  {
629  win_shadow_dxgi_release_frame_data(subsystem);
630 
631  if (subsystem->dxgiDesktopImage)
632  {
633  subsystem->dxgiDesktopImage->lpVtbl->Release(subsystem->dxgiDesktopImage);
634  subsystem->dxgiDesktopImage = NULL;
635  }
636 
637  if (subsystem->dxgiOutputDuplication)
638  {
639  subsystem->dxgiOutputDuplication->lpVtbl->Release(subsystem->dxgiOutputDuplication);
640  subsystem->dxgiOutputDuplication = NULL;
641  }
642 
643  status = win_shadow_dxgi_init_duplication(subsystem);
644 
645  if (status < 0)
646  return -1;
647 
648  return 0;
649  }
650  else if (hr == DXGI_ERROR_INVALID_CALL)
651  {
652  win_shadow_dxgi_uninit(subsystem);
653 
654  status = win_shadow_dxgi_init(subsystem);
655 
656  if (status < 0)
657  return -1;
658 
659  return 0;
660  }
661 
662  return -1;
663  }
664 
665  hr = subsystem->dxgiResource->lpVtbl->QueryInterface(
666  subsystem->dxgiResource, &IID_ID3D11Texture2D, (void**)&(subsystem->dxgiDesktopImage));
667 
668  if (subsystem->dxgiResource)
669  {
670  subsystem->dxgiResource->lpVtbl->Release(subsystem->dxgiResource);
671  subsystem->dxgiResource = NULL;
672  }
673 
674  if (FAILED(hr))
675  {
676  WLog_ERR(TAG, "IDXGIResource::QueryInterface(ID3D11Texture2D) failure: %s (0x%08lX)",
677  GetDxgiErrorString(hr), hr);
678  return -1;
679  }
680 
681  return 1;
682 }
683 
684 int win_shadow_dxgi_get_invalid_region(winShadowSubsystem* subsystem)
685 {
686  HRESULT hr;
687  POINT* pSrcPt;
688  RECT* pDstRect;
689  RECT* pDirtyRect;
690  UINT numMoveRects;
691  UINT numDirtyRects;
692  UINT UsedBufferSize;
693  RECTANGLE_16 invalidRect;
694  UINT MetadataBufferSize;
695  UINT MoveRectsBufferSize;
696  UINT DirtyRectsBufferSize;
697  RECT* pDirtyRectsBuffer;
698  DXGI_OUTDUPL_MOVE_RECT* pMoveRect;
699  DXGI_OUTDUPL_MOVE_RECT* pMoveRectBuffer;
700  rdpShadowSurface* surface = subsystem->server->surface;
701 
702  if (subsystem->dxgiFrameInfo.AccumulatedFrames == 0)
703  return 0;
704 
705  if (subsystem->dxgiFrameInfo.TotalMetadataBufferSize == 0)
706  return 0;
707 
708  MetadataBufferSize = subsystem->dxgiFrameInfo.TotalMetadataBufferSize;
709 
710  if (MetadataBufferSize > subsystem->MetadataBufferSize)
711  {
712  subsystem->MetadataBuffer = (BYTE*)realloc(subsystem->MetadataBuffer, MetadataBufferSize);
713 
714  if (!subsystem->MetadataBuffer)
715  return -1;
716 
717  subsystem->MetadataBufferSize = MetadataBufferSize;
718  }
719 
720  /* GetFrameMoveRects */
721 
722  UsedBufferSize = 0;
723 
724  MoveRectsBufferSize = MetadataBufferSize - UsedBufferSize;
725  pMoveRectBuffer = (DXGI_OUTDUPL_MOVE_RECT*)&(subsystem->MetadataBuffer[UsedBufferSize]);
726 
727  hr = subsystem->dxgiOutputDuplication->lpVtbl->GetFrameMoveRects(
728  subsystem->dxgiOutputDuplication, MoveRectsBufferSize, pMoveRectBuffer,
729  &MoveRectsBufferSize);
730 
731  if (FAILED(hr))
732  {
733  WLog_ERR(TAG,
734  "IDXGIOutputDuplication::GetFrameMoveRects failure: %s (0x%08lX) Size: %u Total "
735  "%u Used: %u",
736  GetDxgiErrorString(hr), hr, MoveRectsBufferSize, MetadataBufferSize,
737  UsedBufferSize);
738  return -1;
739  }
740 
741  /* GetFrameDirtyRects */
742 
743  UsedBufferSize += MoveRectsBufferSize;
744 
745  DirtyRectsBufferSize = MetadataBufferSize - UsedBufferSize;
746  pDirtyRectsBuffer = (RECT*)&(subsystem->MetadataBuffer[UsedBufferSize]);
747 
748  hr = subsystem->dxgiOutputDuplication->lpVtbl->GetFrameDirtyRects(
749  subsystem->dxgiOutputDuplication, DirtyRectsBufferSize, pDirtyRectsBuffer,
750  &DirtyRectsBufferSize);
751 
752  if (FAILED(hr))
753  {
754  WLog_ERR(TAG,
755  "IDXGIOutputDuplication::GetFrameDirtyRects failure: %s (0x%08lX) Size: %u Total "
756  "%u Used: %u",
757  GetDxgiErrorString(hr), hr, DirtyRectsBufferSize, MetadataBufferSize,
758  UsedBufferSize);
759  return -1;
760  }
761 
762  numMoveRects = MoveRectsBufferSize / sizeof(DXGI_OUTDUPL_MOVE_RECT);
763 
764  for (UINT i = 0; i < numMoveRects; i++)
765  {
766  pMoveRect = &pMoveRectBuffer[i];
767  pSrcPt = &(pMoveRect->SourcePoint);
768  pDstRect = &(pMoveRect->DestinationRect);
769 
770  invalidRect.left = (UINT16)pDstRect->left;
771  invalidRect.top = (UINT16)pDstRect->top;
772  invalidRect.right = (UINT16)pDstRect->right;
773  invalidRect.bottom = (UINT16)pDstRect->bottom;
774 
775  region16_union_rect(&(surface->invalidRegion), &(surface->invalidRegion), &invalidRect);
776  }
777 
778  numDirtyRects = DirtyRectsBufferSize / sizeof(RECT);
779 
780  for (UINT i = 0; i < numDirtyRects; i++)
781  {
782  pDirtyRect = &pDirtyRectsBuffer[i];
783 
784  invalidRect.left = (UINT16)pDirtyRect->left;
785  invalidRect.top = (UINT16)pDirtyRect->top;
786  invalidRect.right = (UINT16)pDirtyRect->right;
787  invalidRect.bottom = (UINT16)pDirtyRect->bottom;
788 
789  region16_union_rect(&(surface->invalidRegion), &(surface->invalidRegion), &invalidRect);
790  }
791 
792  return 1;
793 }
794 
795 #endif