1 //
2 // Copyright 2018 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6
7 // CompositorNativeWindow11.cpp: Implementation of NativeWindow11 using Windows.UI.Composition APIs
8 // which work in both Win32 and WinRT contexts.
9
10 #include "libANGLE/renderer/d3d/d3d11/converged/CompositorNativeWindow11.h"
11 #include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
12
13 #include "common/debug.h"
14
15 using namespace Microsoft::WRL;
16
17 namespace rx
18 {
19
CompositorNativeWindow11(EGLNativeWindowType window,bool hasAlpha)20 CompositorNativeWindow11::CompositorNativeWindow11(EGLNativeWindowType window, bool hasAlpha)
21 : NativeWindow11(window), mHasAlpha(hasAlpha)
22 {
23 ABI::Windows::UI::Composition::ISpriteVisual *inspPtr =
24 reinterpret_cast<ABI::Windows::UI::Composition::ISpriteVisual *>(window);
25 mHostVisual = Microsoft::WRL::ComPtr<ABI::Windows::UI::Composition::ISpriteVisual>{inspPtr};
26 }
27
28 CompositorNativeWindow11::~CompositorNativeWindow11() = default;
29
initialize()30 bool CompositorNativeWindow11::initialize()
31 {
32 return true;
33 }
34
getClientRect(LPRECT rect) const35 bool CompositorNativeWindow11::getClientRect(LPRECT rect) const
36 {
37 ComPtr<ABI::Windows::UI::Composition::IVisual> visual;
38 mHostVisual.As(&visual);
39
40 ABI::Windows::Foundation::Numerics::Vector2 size;
41 HRESULT hr = visual->get_Size(&size);
42 if (FAILED(hr))
43 {
44 return false;
45 }
46
47 ABI::Windows::Foundation::Numerics::Vector3 offset;
48 hr = visual->get_Offset(&offset);
49 if (FAILED(hr))
50 {
51 return false;
52 }
53
54 rect->top = static_cast<LONG>(offset.Y);
55 rect->left = static_cast<LONG>(offset.X);
56 rect->right = static_cast<LONG>(offset.X) + static_cast<LONG>(size.X);
57 rect->bottom = static_cast<LONG>(offset.Y) + static_cast<LONG>(size.Y);
58
59 return true;
60 }
61
isIconic() const62 bool CompositorNativeWindow11::isIconic() const
63 {
64 return false;
65 }
66
createSwapChain(ID3D11Device * device,IDXGIFactory * factory,DXGI_FORMAT format,UINT width,UINT height,UINT samples,IDXGISwapChain ** swapChain)67 HRESULT CompositorNativeWindow11::createSwapChain(ID3D11Device *device,
68 IDXGIFactory *factory,
69 DXGI_FORMAT format,
70 UINT width,
71 UINT height,
72 UINT samples,
73 IDXGISwapChain **swapChain)
74 {
75 if (device == nullptr || factory == nullptr || swapChain == nullptr || width == 0 ||
76 height == 0)
77 {
78 return E_INVALIDARG;
79 }
80
81 HRESULT hr{E_FAIL};
82
83 ComPtr<ABI::Windows::UI::Composition::ICompositionObject> hostVisual;
84 hr = mHostVisual.As(&hostVisual);
85 if (FAILED(hr))
86 {
87 return hr;
88 }
89
90 Microsoft::WRL::ComPtr<ABI::Windows::UI::Composition::ICompositor> compositor;
91 hr = hostVisual->get_Compositor(&compositor);
92 if (FAILED(hr))
93 {
94 return hr;
95 }
96
97 ComPtr<ABI::Windows::UI::Composition::ICompositorInterop> interop;
98
99 hr = compositor.As(&interop);
100 if (FAILED(hr))
101 {
102 return hr;
103 }
104
105 ComPtr<IDXGIFactory2> factory2;
106 factory2.Attach(d3d11::DynamicCastComObject<IDXGIFactory2>(factory));
107
108 DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {};
109 swapChainDesc.Width = width;
110 swapChainDesc.Height = height;
111 swapChainDesc.Format = format;
112 swapChainDesc.Stereo = FALSE;
113 swapChainDesc.SampleDesc.Count = 1;
114 swapChainDesc.SampleDesc.Quality = 0;
115 swapChainDesc.BufferUsage =
116 DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_BACK_BUFFER | DXGI_USAGE_SHADER_INPUT;
117 swapChainDesc.BufferCount = 2;
118 swapChainDesc.Scaling = DXGI_SCALING_STRETCH;
119 swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
120 swapChainDesc.AlphaMode = mHasAlpha ? DXGI_ALPHA_MODE_PREMULTIPLIED : DXGI_ALPHA_MODE_IGNORE;
121 swapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG::DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT;
122 Microsoft::WRL::ComPtr<IDXGISwapChain1> swapChain1;
123 hr = factory2->CreateSwapChainForComposition(device, &swapChainDesc, nullptr, &swapChain1);
124 if (SUCCEEDED(hr))
125 {
126 swapChain1.CopyTo(swapChain);
127 }
128
129 hr = interop->CreateCompositionSurfaceForSwapChain(swapChain1.Get(), &mSurface);
130 if (FAILED(hr))
131 {
132 return hr;
133 }
134
135 hr = compositor->CreateSurfaceBrushWithSurface(mSurface.Get(), &mSurfaceBrush);
136 if (FAILED(hr))
137 {
138 return hr;
139 }
140
141 hr = mSurfaceBrush.As(&mCompositionBrush);
142 if (FAILED(hr))
143 {
144 return hr;
145 }
146
147 hr = mHostVisual->put_Brush(mCompositionBrush.Get());
148 if (FAILED(hr))
149 {
150 return hr;
151 }
152
153 return hr;
154 }
155
commitChange()156 void CompositorNativeWindow11::commitChange()
157 {
158 // Windows::UI::Composition uses an implicit commit model hence no action needed here
159 }
160
161 // static
IsValidNativeWindow(EGLNativeWindowType window)162 bool CompositorNativeWindow11::IsValidNativeWindow(EGLNativeWindowType window)
163 {
164 return IsSupportedWinRelease() && IsSpriteVisual(window);
165 }
166
167 // static
IsSupportedWinRelease()168 bool CompositorNativeWindow11::IsSupportedWinRelease()
169 {
170 RoHelper helper;
171 if (!helper.WinRtAvailable())
172 {
173 return false;
174 }
175
176 return helper.SupportedWindowsRelease();
177 }
178
IsSpriteVisual(EGLNativeWindowType window)179 bool CompositorNativeWindow11::IsSpriteVisual(EGLNativeWindowType window)
180 {
181 RoHelper helper;
182
183 ABI::Windows::UI::Composition::ISpriteVisual *inspp =
184 reinterpret_cast<ABI::Windows::UI::Composition::ISpriteVisual *>(window);
185 HSTRING className, spriteClassName;
186 HSTRING_HEADER spriteClassNameHeader;
187
188 auto hr = helper.GetStringReference(RuntimeClass_Windows_UI_Composition_SpriteVisual,
189 &spriteClassName, &spriteClassNameHeader);
190 if (FAILED(hr))
191 {
192 return false;
193 }
194
195 hr = inspp->GetRuntimeClassName(&className);
196 if (FAILED(hr))
197 {
198 return false;
199 }
200
201 INT32 result = -1;
202 hr = helper.WindowsCompareStringOrdinal(className, spriteClassName, &result);
203
204 helper.WindowsDeleteString(className);
205
206 if (FAILED(hr))
207 {
208 return false;
209 }
210
211 if (result == 0)
212 {
213 return true;
214 }
215
216 return false;
217 }
218
219 // RoHelperImpl
220
221 template <typename T>
AssignProcAddress(HMODULE comBaseModule,const char * name,T * & outProc)222 bool AssignProcAddress(HMODULE comBaseModule, const char *name, T *&outProc)
223 {
224 outProc = reinterpret_cast<T *>(GetProcAddress(comBaseModule, name));
225 return *outProc != nullptr;
226 }
227
RoHelper()228 RoHelper::RoHelper()
229 : mFpWindowsCreateStringReference(nullptr),
230 mFpGetActivationFactory(nullptr),
231 mFpWindowsCompareStringOrdinal(nullptr),
232 mFpCreateDispatcherQueueController(nullptr),
233 mFpWindowsDeleteString(nullptr),
234 mFpRoInitialize(nullptr),
235 mFpRoUninitialize(nullptr),
236 mWinRtAvailable(false),
237 mComBaseModule(nullptr),
238 mCoreMessagingModule(nullptr)
239 {
240 if (!IsWindows10OrGreater())
241 {
242 return;
243 }
244
245 mComBaseModule = LoadLibraryA("ComBase.dll");
246
247 if (mComBaseModule == nullptr)
248 {
249 return;
250 }
251
252 if (!AssignProcAddress(mComBaseModule, "WindowsCreateStringReference",
253 mFpWindowsCreateStringReference))
254 {
255 return;
256 }
257
258 if (!AssignProcAddress(mComBaseModule, "RoGetActivationFactory", mFpGetActivationFactory))
259 {
260 return;
261 }
262
263 if (!AssignProcAddress(mComBaseModule, "WindowsCompareStringOrdinal",
264 mFpWindowsCompareStringOrdinal))
265 {
266 return;
267 }
268
269 if (!AssignProcAddress(mComBaseModule, "WindowsDeleteString", mFpWindowsDeleteString))
270 {
271 return;
272 }
273
274 if (!AssignProcAddress(mComBaseModule, "RoInitialize", mFpRoInitialize))
275 {
276 return;
277 }
278
279 if (!AssignProcAddress(mComBaseModule, "RoUninitialize", mFpRoUninitialize))
280 {
281 return;
282 }
283
284 mCoreMessagingModule = LoadLibraryA("coremessaging.dll");
285
286 if (mCoreMessagingModule == nullptr)
287 {
288 return;
289 }
290
291 if (!AssignProcAddress(mCoreMessagingModule, "CreateDispatcherQueueController",
292 mFpCreateDispatcherQueueController))
293 {
294 return;
295 }
296
297 if (SUCCEEDED(RoInitialize(RO_INIT_MULTITHREADED)))
298 {
299 mWinRtAvailable = true;
300 }
301 }
302
~RoHelper()303 RoHelper::~RoHelper()
304 {
305 if (mWinRtAvailable)
306 {
307 RoUninitialize();
308 }
309
310 if (mCoreMessagingModule != nullptr)
311 {
312 FreeLibrary(mCoreMessagingModule);
313 mCoreMessagingModule = nullptr;
314 }
315
316 if (mComBaseModule != nullptr)
317 {
318 FreeLibrary(mComBaseModule);
319 mComBaseModule = nullptr;
320 }
321 }
322
WinRtAvailable() const323 bool RoHelper::WinRtAvailable() const
324 {
325 return mWinRtAvailable;
326 }
327
SupportedWindowsRelease()328 bool RoHelper::SupportedWindowsRelease()
329 {
330 if (!IsWindows10OrGreater() || !mWinRtAvailable)
331 {
332 return false;
333 }
334
335 HSTRING className, contractName;
336 HSTRING_HEADER classNameHeader, contractNameHeader;
337 boolean isSupported = false;
338
339 HRESULT hr = GetStringReference(RuntimeClass_Windows_Foundation_Metadata_ApiInformation,
340 &className, &classNameHeader);
341
342 if (FAILED(hr))
343 {
344 return !!isSupported;
345 }
346
347 Microsoft::WRL::ComPtr<ABI::Windows::Foundation::Metadata::IApiInformationStatics> api;
348
349 hr = GetActivationFactory(
350 className, __uuidof(ABI::Windows::Foundation::Metadata::IApiInformationStatics), &api);
351
352 if (FAILED(hr))
353 {
354 return !!isSupported;
355 }
356
357 hr = GetStringReference(L"Windows.Foundation.UniversalApiContract", &contractName,
358 &contractNameHeader);
359 if (FAILED(hr))
360 {
361 return !!isSupported;
362 }
363
364 api->IsApiContractPresentByMajor(contractName, 6, &isSupported);
365
366 return !!isSupported;
367 }
368
GetStringReference(PCWSTR source,HSTRING * act,HSTRING_HEADER * header)369 HRESULT RoHelper::GetStringReference(PCWSTR source, HSTRING *act, HSTRING_HEADER *header)
370 {
371 if (!mWinRtAvailable)
372 {
373 return E_FAIL;
374 }
375
376 const wchar_t *str = static_cast<const wchar_t *>(source);
377
378 unsigned int length;
379 HRESULT hr = SizeTToUInt32(::wcslen(str), &length);
380 if (FAILED(hr))
381 {
382 return hr;
383 }
384
385 return mFpWindowsCreateStringReference(source, length, header, act);
386 }
387
GetActivationFactory(const HSTRING act,const IID & interfaceId,void ** fac)388 HRESULT RoHelper::GetActivationFactory(const HSTRING act, const IID &interfaceId, void **fac)
389 {
390 if (!mWinRtAvailable)
391 {
392 return E_FAIL;
393 }
394 auto hr = mFpGetActivationFactory(act, interfaceId, fac);
395 return hr;
396 }
397
WindowsCompareStringOrdinal(HSTRING one,HSTRING two,int * result)398 HRESULT RoHelper::WindowsCompareStringOrdinal(HSTRING one, HSTRING two, int *result)
399 {
400 if (!mWinRtAvailable)
401 {
402 return E_FAIL;
403 }
404 return mFpWindowsCompareStringOrdinal(one, two, result);
405 }
406
CreateDispatcherQueueController(DispatcherQueueOptions options,ABI::Windows::System::IDispatcherQueueController ** dispatcherQueueController)407 HRESULT RoHelper::CreateDispatcherQueueController(
408 DispatcherQueueOptions options,
409 ABI::Windows::System::IDispatcherQueueController **dispatcherQueueController)
410 {
411 if (!mWinRtAvailable)
412 {
413 return E_FAIL;
414 }
415 return mFpCreateDispatcherQueueController(options, dispatcherQueueController);
416 }
417
WindowsDeleteString(HSTRING one)418 HRESULT RoHelper::WindowsDeleteString(HSTRING one)
419 {
420 if (!mWinRtAvailable)
421 {
422 return E_FAIL;
423 }
424 return mFpWindowsDeleteString(one);
425 }
426
RoInitialize(RO_INIT_TYPE type)427 HRESULT RoHelper::RoInitialize(RO_INIT_TYPE type)
428 {
429 return mFpRoInitialize(type);
430 }
431
RoUninitialize()432 void RoHelper::RoUninitialize()
433 {
434 mFpRoUninitialize();
435 }
436
437 } // namespace rx
438