CompositorNativeWindow11.cpp (11878B)
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 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 30 bool CompositorNativeWindow11::initialize() 31 { 32 return true; 33 } 34 35 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 62 bool CompositorNativeWindow11::isIconic() const 63 { 64 return false; 65 } 66 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 158 void CompositorNativeWindow11::commitChange() 159 { 160 // Windows::UI::Composition uses an implicit commit model hence no action needed here 161 } 162 163 // static 164 bool CompositorNativeWindow11::IsValidNativeWindow(EGLNativeWindowType window) 165 { 166 return IsSupportedWinRelease() && IsSpriteVisual(window); 167 } 168 169 // static 170 bool CompositorNativeWindow11::IsSupportedWinRelease() 171 { 172 RoHelper helper; 173 if (!helper.WinRtAvailable()) 174 { 175 return false; 176 } 177 178 return helper.SupportedWindowsRelease(); 179 } 180 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> 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 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 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 343 bool RoHelper::WinRtAvailable() const 344 { 345 return mWinRtAvailable; 346 } 347 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 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 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 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 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 438 HRESULT RoHelper::WindowsDeleteString(HSTRING one) 439 { 440 if (!mWinRtAvailable) 441 { 442 return E_FAIL; 443 } 444 return mFpWindowsDeleteString(one); 445 } 446 447 HRESULT RoHelper::RoInitialize(RO_INIT_TYPE type) 448 { 449 return mFpRoInitialize(type); 450 } 451 452 void RoHelper::RoUninitialize() 453 { 454 mFpRoUninitialize(); 455 } 456 457 } // namespace rx