• 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       mComBaseModule(nullptr),
240       mCoreMessagingModule(nullptr)
241 {
242 
243 #ifdef ANGLE_ENABLE_WINDOWS_UWP
244     mFpWindowsCreateStringReference    = &::WindowsCreateStringReference;
245     mFpRoInitialize                    = &::RoInitialize;
246     mFpRoUninitialize                  = &::RoUninitialize;
247     mFpWindowsDeleteString             = &::WindowsDeleteString;
248     mFpGetActivationFactory            = &::RoGetActivationFactory;
249     mFpWindowsCompareStringOrdinal     = &::WindowsCompareStringOrdinal;
250     mFpCreateDispatcherQueueController = &::CreateDispatcherQueueController;
251     mWinRtAvailable                    = true;
252 #else
253 
254     mComBaseModule = LoadLibraryA("ComBase.dll");
255 
256     if (mComBaseModule == nullptr)
257     {
258         return;
259     }
260 
261     if (!AssignProcAddress(mComBaseModule, "WindowsCreateStringReference",
262                            mFpWindowsCreateStringReference))
263     {
264         return;
265     }
266 
267     if (!AssignProcAddress(mComBaseModule, "RoGetActivationFactory", mFpGetActivationFactory))
268     {
269         return;
270     }
271 
272     if (!AssignProcAddress(mComBaseModule, "WindowsCompareStringOrdinal",
273                            mFpWindowsCompareStringOrdinal))
274     {
275         return;
276     }
277 
278     if (!AssignProcAddress(mComBaseModule, "WindowsDeleteString", mFpWindowsDeleteString))
279     {
280         return;
281     }
282 
283     if (!AssignProcAddress(mComBaseModule, "RoInitialize", mFpRoInitialize))
284     {
285         return;
286     }
287 
288     if (!AssignProcAddress(mComBaseModule, "RoUninitialize", mFpRoUninitialize))
289     {
290         return;
291     }
292 
293     mCoreMessagingModule = LoadLibraryA("coremessaging.dll");
294 
295     if (mCoreMessagingModule == nullptr)
296     {
297         return;
298     }
299 
300     if (!AssignProcAddress(mCoreMessagingModule, "CreateDispatcherQueueController",
301                            mFpCreateDispatcherQueueController))
302     {
303         return;
304     }
305 
306     auto result = RoInitialize(RO_INIT_MULTITHREADED);
307 
308     if (SUCCEEDED(result) || result == S_FALSE || result == RPC_E_CHANGED_MODE)
309     {
310         mWinRtAvailable = true;
311     }
312 #endif
313 }
314 
~RoHelper()315 RoHelper::~RoHelper()
316 {
317 #ifndef ANGLE_ENABLE_WINDOWS_UWP
318     if (mWinRtAvailable)
319     {
320         RoUninitialize();
321     }
322 
323     if (mCoreMessagingModule != nullptr)
324     {
325         FreeLibrary(mCoreMessagingModule);
326         mCoreMessagingModule = nullptr;
327     }
328 
329     if (mComBaseModule != nullptr)
330     {
331         FreeLibrary(mComBaseModule);
332         mComBaseModule = nullptr;
333     }
334 #endif
335 }
336 
WinRtAvailable() const337 bool RoHelper::WinRtAvailable() const
338 {
339     return mWinRtAvailable;
340 }
341 
SupportedWindowsRelease()342 bool RoHelper::SupportedWindowsRelease()
343 {
344     if (!mWinRtAvailable)
345     {
346         return false;
347     }
348 
349     HSTRING className, contractName;
350     HSTRING_HEADER classNameHeader, contractNameHeader;
351     boolean isSupported = false;
352 
353     HRESULT hr = GetStringReference(RuntimeClass_Windows_Foundation_Metadata_ApiInformation,
354                                     &className, &classNameHeader);
355 
356     if (FAILED(hr))
357     {
358         return !!isSupported;
359     }
360 
361     Microsoft::WRL::ComPtr<ABI::Windows::Foundation::Metadata::IApiInformationStatics> api;
362 
363     hr = GetActivationFactory(
364         className, __uuidof(ABI::Windows::Foundation::Metadata::IApiInformationStatics), &api);
365 
366     if (FAILED(hr))
367     {
368         return !!isSupported;
369     }
370 
371     hr = GetStringReference(L"Windows.Foundation.UniversalApiContract", &contractName,
372                             &contractNameHeader);
373     if (FAILED(hr))
374     {
375         return !!isSupported;
376     }
377 
378     api->IsApiContractPresentByMajor(contractName, 6, &isSupported);
379 
380     return !!isSupported;
381 }
382 
GetStringReference(PCWSTR source,HSTRING * act,HSTRING_HEADER * header)383 HRESULT RoHelper::GetStringReference(PCWSTR source, HSTRING *act, HSTRING_HEADER *header)
384 {
385     if (!mWinRtAvailable)
386     {
387         return E_FAIL;
388     }
389 
390     const wchar_t *str = static_cast<const wchar_t *>(source);
391 
392     unsigned int length;
393     HRESULT hr = SizeTToUInt32(::wcslen(str), &length);
394     if (FAILED(hr))
395     {
396         return hr;
397     }
398 
399     return mFpWindowsCreateStringReference(source, length, header, act);
400 }
401 
GetActivationFactory(const HSTRING act,const IID & interfaceId,void ** fac)402 HRESULT RoHelper::GetActivationFactory(const HSTRING act, const IID &interfaceId, void **fac)
403 {
404     if (!mWinRtAvailable)
405     {
406         return E_FAIL;
407     }
408     auto hr = mFpGetActivationFactory(act, interfaceId, fac);
409     return hr;
410 }
411 
WindowsCompareStringOrdinal(HSTRING one,HSTRING two,int * result)412 HRESULT RoHelper::WindowsCompareStringOrdinal(HSTRING one, HSTRING two, int *result)
413 {
414     if (!mWinRtAvailable)
415     {
416         return E_FAIL;
417     }
418     return mFpWindowsCompareStringOrdinal(one, two, result);
419 }
420 
CreateDispatcherQueueController(DispatcherQueueOptions options,ABI::Windows::System::IDispatcherQueueController ** dispatcherQueueController)421 HRESULT RoHelper::CreateDispatcherQueueController(
422     DispatcherQueueOptions options,
423     ABI::Windows::System::IDispatcherQueueController **dispatcherQueueController)
424 {
425     if (!mWinRtAvailable)
426     {
427         return E_FAIL;
428     }
429     return mFpCreateDispatcherQueueController(options, dispatcherQueueController);
430 }
431 
WindowsDeleteString(HSTRING one)432 HRESULT RoHelper::WindowsDeleteString(HSTRING one)
433 {
434     if (!mWinRtAvailable)
435     {
436         return E_FAIL;
437     }
438     return mFpWindowsDeleteString(one);
439 }
440 
RoInitialize(RO_INIT_TYPE type)441 HRESULT RoHelper::RoInitialize(RO_INIT_TYPE type)
442 {
443     return mFpRoInitialize(type);
444 }
445 
RoUninitialize()446 void RoHelper::RoUninitialize()
447 {
448     mFpRoUninitialize();
449 }
450 
451 }  // namespace rx
452