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