• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #ifndef ANGLE_ENABLE_WINDOWS_UWP
122     swapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG::DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT;
123 #endif
124     Microsoft::WRL::ComPtr<IDXGISwapChain1> swapChain1;
125     hr = factory2->CreateSwapChainForComposition(device, &swapChainDesc, nullptr, &swapChain1);
126     if (SUCCEEDED(hr))
127     {
128         swapChain1.CopyTo(swapChain);
129     }
130 
131     hr = interop->CreateCompositionSurfaceForSwapChain(swapChain1.Get(), &mSurface);
132     if (FAILED(hr))
133     {
134         return hr;
135     }
136 
137     hr = compositor->CreateSurfaceBrushWithSurface(mSurface.Get(), &mSurfaceBrush);
138     if (FAILED(hr))
139     {
140         return hr;
141     }
142 
143     hr = mSurfaceBrush.As(&mCompositionBrush);
144     if (FAILED(hr))
145     {
146         return hr;
147     }
148 
149     hr = mHostVisual->put_Brush(mCompositionBrush.Get());
150     if (FAILED(hr))
151     {
152         return hr;
153     }
154 
155     return hr;
156 }
157 
commitChange()158 void CompositorNativeWindow11::commitChange()
159 {
160     // Windows::UI::Composition uses an implicit commit model hence no action needed here
161 }
162 
163 // static
IsValidNativeWindow(EGLNativeWindowType window)164 bool CompositorNativeWindow11::IsValidNativeWindow(EGLNativeWindowType window)
165 {
166     return IsSupportedWinRelease() && IsSpriteVisual(window);
167 }
168 
169 // static
IsSupportedWinRelease()170 bool CompositorNativeWindow11::IsSupportedWinRelease()
171 {
172     RoHelper helper;
173     if (!helper.WinRtAvailable())
174     {
175         return false;
176     }
177 
178     return helper.SupportedWindowsRelease();
179 }
180 
IsSpriteVisual(EGLNativeWindowType window)181 bool CompositorNativeWindow11::IsSpriteVisual(EGLNativeWindowType window)
182 {
183     RoHelper helper;
184 
185     ABI::Windows::UI::Composition::ISpriteVisual *inspp =
186         reinterpret_cast<ABI::Windows::UI::Composition::ISpriteVisual *>(window);
187     HSTRING className, spriteClassName;
188     HSTRING_HEADER spriteClassNameHeader;
189 
190     auto hr = helper.GetStringReference(RuntimeClass_Windows_UI_Composition_SpriteVisual,
191                                         &spriteClassName, &spriteClassNameHeader);
192     if (FAILED(hr))
193     {
194         return false;
195     }
196 
197     hr = inspp->GetRuntimeClassName(&className);
198     if (FAILED(hr))
199     {
200         return false;
201     }
202 
203     INT32 result = -1;
204     hr           = helper.WindowsCompareStringOrdinal(className, spriteClassName, &result);
205 
206     helper.WindowsDeleteString(className);
207 
208     if (FAILED(hr))
209     {
210         return false;
211     }
212 
213     if (result == 0)
214     {
215         return true;
216     }
217 
218     return false;
219 }
220 
221 // RoHelperImpl
222 
223 template <typename T>
AssignProcAddress(HMODULE comBaseModule,const char * name,T * & outProc)224 bool AssignProcAddress(HMODULE comBaseModule, const char *name, T *&outProc)
225 {
226     outProc = reinterpret_cast<T *>(GetProcAddress(comBaseModule, name));
227     return *outProc != nullptr;
228 }
229 
RoHelper()230 RoHelper::RoHelper()
231     : mFpWindowsCreateStringReference(nullptr),
232       mFpGetActivationFactory(nullptr),
233       mFpWindowsCompareStringOrdinal(nullptr),
234       mFpCreateDispatcherQueueController(nullptr),
235       mFpWindowsDeleteString(nullptr),
236       mFpRoInitialize(nullptr),
237       mFpRoUninitialize(nullptr),
238       mWinRtAvailable(false),
239       mWinRtInitialized(false),
240       mComBaseModule(nullptr),
241       mCoreMessagingModule(nullptr)
242 {
243 
244 #ifdef ANGLE_ENABLE_WINDOWS_UWP
245     mFpWindowsCreateStringReference    = &::WindowsCreateStringReference;
246     mFpRoInitialize                    = &::RoInitialize;
247     mFpRoUninitialize                  = &::RoUninitialize;
248     mFpWindowsDeleteString             = &::WindowsDeleteString;
249     mFpGetActivationFactory            = &::RoGetActivationFactory;
250     mFpWindowsCompareStringOrdinal     = &::WindowsCompareStringOrdinal;
251     mFpCreateDispatcherQueueController = &::CreateDispatcherQueueController;
252     mWinRtAvailable                    = true;
253 #else
254 
255     mComBaseModule = LoadLibraryA("ComBase.dll");
256 
257     if (mComBaseModule == nullptr)
258     {
259         return;
260     }
261 
262     if (!AssignProcAddress(mComBaseModule, "WindowsCreateStringReference",
263                            mFpWindowsCreateStringReference))
264     {
265         return;
266     }
267 
268     if (!AssignProcAddress(mComBaseModule, "RoGetActivationFactory", mFpGetActivationFactory))
269     {
270         return;
271     }
272 
273     if (!AssignProcAddress(mComBaseModule, "WindowsCompareStringOrdinal",
274                            mFpWindowsCompareStringOrdinal))
275     {
276         return;
277     }
278 
279     if (!AssignProcAddress(mComBaseModule, "WindowsDeleteString", mFpWindowsDeleteString))
280     {
281         return;
282     }
283 
284     if (!AssignProcAddress(mComBaseModule, "RoInitialize", mFpRoInitialize))
285     {
286         return;
287     }
288 
289     if (!AssignProcAddress(mComBaseModule, "RoUninitialize", mFpRoUninitialize))
290     {
291         return;
292     }
293 
294     mCoreMessagingModule = LoadLibraryA("coremessaging.dll");
295 
296     if (mCoreMessagingModule == nullptr)
297     {
298         return;
299     }
300 
301     if (!AssignProcAddress(mCoreMessagingModule, "CreateDispatcherQueueController",
302                            mFpCreateDispatcherQueueController))
303     {
304         return;
305     }
306 
307     auto result = RoInitialize(RO_INIT_MULTITHREADED);
308 
309     if (SUCCEEDED(result) || result == RPC_E_CHANGED_MODE)
310     {
311         mWinRtAvailable = true;
312 
313         if (SUCCEEDED(result))
314         {
315             mWinRtInitialized = true;
316         }
317     }
318 #endif
319 }
320 
~RoHelper()321 RoHelper::~RoHelper()
322 {
323 #ifndef ANGLE_ENABLE_WINDOWS_UWP
324     if (mWinRtInitialized)
325     {
326         RoUninitialize();
327     }
328 
329     if (mCoreMessagingModule != nullptr)
330     {
331         FreeLibrary(mCoreMessagingModule);
332         mCoreMessagingModule = nullptr;
333     }
334 
335     if (mComBaseModule != nullptr)
336     {
337         FreeLibrary(mComBaseModule);
338         mComBaseModule = nullptr;
339     }
340 #endif
341 }
342 
WinRtAvailable() const343 bool RoHelper::WinRtAvailable() const
344 {
345     return mWinRtAvailable;
346 }
347 
SupportedWindowsRelease()348 bool RoHelper::SupportedWindowsRelease()
349 {
350     if (!mWinRtAvailable)
351     {
352         return false;
353     }
354 
355     HSTRING className, contractName;
356     HSTRING_HEADER classNameHeader, contractNameHeader;
357     boolean isSupported = false;
358 
359     HRESULT hr = GetStringReference(RuntimeClass_Windows_Foundation_Metadata_ApiInformation,
360                                     &className, &classNameHeader);
361 
362     if (FAILED(hr))
363     {
364         return !!isSupported;
365     }
366 
367     Microsoft::WRL::ComPtr<ABI::Windows::Foundation::Metadata::IApiInformationStatics> api;
368 
369     hr = GetActivationFactory(
370         className, __uuidof(ABI::Windows::Foundation::Metadata::IApiInformationStatics), &api);
371 
372     if (FAILED(hr))
373     {
374         return !!isSupported;
375     }
376 
377     hr = GetStringReference(L"Windows.Foundation.UniversalApiContract", &contractName,
378                             &contractNameHeader);
379     if (FAILED(hr))
380     {
381         return !!isSupported;
382     }
383 
384     api->IsApiContractPresentByMajor(contractName, 6, &isSupported);
385 
386     return !!isSupported;
387 }
388 
GetStringReference(PCWSTR source,HSTRING * act,HSTRING_HEADER * header)389 HRESULT RoHelper::GetStringReference(PCWSTR source, HSTRING *act, HSTRING_HEADER *header)
390 {
391     if (!mWinRtAvailable)
392     {
393         return E_FAIL;
394     }
395 
396     const wchar_t *str = static_cast<const wchar_t *>(source);
397 
398     unsigned int length;
399     HRESULT hr = SizeTToUInt32(::wcslen(str), &length);
400     if (FAILED(hr))
401     {
402         return hr;
403     }
404 
405     return mFpWindowsCreateStringReference(source, length, header, act);
406 }
407 
GetActivationFactory(const HSTRING act,const IID & interfaceId,void ** fac)408 HRESULT RoHelper::GetActivationFactory(const HSTRING act, const IID &interfaceId, void **fac)
409 {
410     if (!mWinRtAvailable)
411     {
412         return E_FAIL;
413     }
414     auto hr = mFpGetActivationFactory(act, interfaceId, fac);
415     return hr;
416 }
417 
WindowsCompareStringOrdinal(HSTRING one,HSTRING two,int * result)418 HRESULT RoHelper::WindowsCompareStringOrdinal(HSTRING one, HSTRING two, int *result)
419 {
420     if (!mWinRtAvailable)
421     {
422         return E_FAIL;
423     }
424     return mFpWindowsCompareStringOrdinal(one, two, result);
425 }
426 
CreateDispatcherQueueController(DispatcherQueueOptions options,ABI::Windows::System::IDispatcherQueueController ** dispatcherQueueController)427 HRESULT RoHelper::CreateDispatcherQueueController(
428     DispatcherQueueOptions options,
429     ABI::Windows::System::IDispatcherQueueController **dispatcherQueueController)
430 {
431     if (!mWinRtAvailable)
432     {
433         return E_FAIL;
434     }
435     return mFpCreateDispatcherQueueController(options, dispatcherQueueController);
436 }
437 
WindowsDeleteString(HSTRING one)438 HRESULT RoHelper::WindowsDeleteString(HSTRING one)
439 {
440     if (!mWinRtAvailable)
441     {
442         return E_FAIL;
443     }
444     return mFpWindowsDeleteString(one);
445 }
446 
RoInitialize(RO_INIT_TYPE type)447 HRESULT RoHelper::RoInitialize(RO_INIT_TYPE type)
448 {
449     return mFpRoInitialize(type);
450 }
451 
RoUninitialize()452 void RoHelper::RoUninitialize()
453 {
454     mFpRoUninitialize();
455 }
456 
457 }  // namespace rx
458