summaryrefslogtreecommitdiffstats
path: root/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/converged/CompositorNativeWindow11.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/converged/CompositorNativeWindow11.cpp457
1 files changed, 457 insertions, 0 deletions
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/converged/CompositorNativeWindow11.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/converged/CompositorNativeWindow11.cpp
new file mode 100644
index 0000000000..0e64f78d53
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/d3d11/converged/CompositorNativeWindow11.cpp
@@ -0,0 +1,457 @@
+//
+// Copyright 2018 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// CompositorNativeWindow11.cpp: Implementation of NativeWindow11 using Windows.UI.Composition APIs
+// which work in both Win32 and WinRT contexts.
+
+#include "libANGLE/renderer/d3d/d3d11/converged/CompositorNativeWindow11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+
+#include "common/debug.h"
+
+using namespace Microsoft::WRL;
+
+namespace rx
+{
+
+CompositorNativeWindow11::CompositorNativeWindow11(EGLNativeWindowType window, bool hasAlpha)
+ : NativeWindow11(window), mHasAlpha(hasAlpha)
+{
+ ABI::Windows::UI::Composition::ISpriteVisual *inspPtr =
+ reinterpret_cast<ABI::Windows::UI::Composition::ISpriteVisual *>(window);
+ mHostVisual = Microsoft::WRL::ComPtr<ABI::Windows::UI::Composition::ISpriteVisual>{inspPtr};
+}
+
+CompositorNativeWindow11::~CompositorNativeWindow11() = default;
+
+bool CompositorNativeWindow11::initialize()
+{
+ return true;
+}
+
+bool CompositorNativeWindow11::getClientRect(LPRECT rect) const
+{
+ ComPtr<ABI::Windows::UI::Composition::IVisual> visual;
+ mHostVisual.As(&visual);
+
+ ABI::Windows::Foundation::Numerics::Vector2 size;
+ HRESULT hr = visual->get_Size(&size);
+ if (FAILED(hr))
+ {
+ return false;
+ }
+
+ ABI::Windows::Foundation::Numerics::Vector3 offset;
+ hr = visual->get_Offset(&offset);
+ if (FAILED(hr))
+ {
+ return false;
+ }
+
+ rect->top = static_cast<LONG>(offset.Y);
+ rect->left = static_cast<LONG>(offset.X);
+ rect->right = static_cast<LONG>(offset.X) + static_cast<LONG>(size.X);
+ rect->bottom = static_cast<LONG>(offset.Y) + static_cast<LONG>(size.Y);
+
+ return true;
+}
+
+bool CompositorNativeWindow11::isIconic() const
+{
+ return false;
+}
+
+HRESULT CompositorNativeWindow11::createSwapChain(ID3D11Device *device,
+ IDXGIFactory *factory,
+ DXGI_FORMAT format,
+ UINT width,
+ UINT height,
+ UINT samples,
+ IDXGISwapChain **swapChain)
+{
+ if (device == nullptr || factory == nullptr || swapChain == nullptr || width == 0 ||
+ height == 0)
+ {
+ return E_INVALIDARG;
+ }
+
+ HRESULT hr{E_FAIL};
+
+ ComPtr<ABI::Windows::UI::Composition::ICompositionObject> hostVisual;
+ hr = mHostVisual.As(&hostVisual);
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+
+ Microsoft::WRL::ComPtr<ABI::Windows::UI::Composition::ICompositor> compositor;
+ hr = hostVisual->get_Compositor(&compositor);
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+
+ ComPtr<ABI::Windows::UI::Composition::ICompositorInterop> interop;
+
+ hr = compositor.As(&interop);
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+
+ ComPtr<IDXGIFactory2> factory2;
+ factory2.Attach(d3d11::DynamicCastComObject<IDXGIFactory2>(factory));
+
+ DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {};
+ swapChainDesc.Width = width;
+ swapChainDesc.Height = height;
+ swapChainDesc.Format = format;
+ swapChainDesc.Stereo = FALSE;
+ swapChainDesc.SampleDesc.Count = 1;
+ swapChainDesc.SampleDesc.Quality = 0;
+ swapChainDesc.BufferUsage =
+ DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_BACK_BUFFER | DXGI_USAGE_SHADER_INPUT;
+ swapChainDesc.BufferCount = 2;
+ swapChainDesc.Scaling = DXGI_SCALING_STRETCH;
+ swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
+ swapChainDesc.AlphaMode = mHasAlpha ? DXGI_ALPHA_MODE_PREMULTIPLIED : DXGI_ALPHA_MODE_IGNORE;
+#ifndef ANGLE_ENABLE_WINDOWS_UWP
+ swapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG::DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT;
+#endif
+ Microsoft::WRL::ComPtr<IDXGISwapChain1> swapChain1;
+ hr = factory2->CreateSwapChainForComposition(device, &swapChainDesc, nullptr, &swapChain1);
+ if (SUCCEEDED(hr))
+ {
+ swapChain1.CopyTo(swapChain);
+ }
+
+ hr = interop->CreateCompositionSurfaceForSwapChain(swapChain1.Get(), &mSurface);
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+
+ hr = compositor->CreateSurfaceBrushWithSurface(mSurface.Get(), &mSurfaceBrush);
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+
+ hr = mSurfaceBrush.As(&mCompositionBrush);
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+
+ hr = mHostVisual->put_Brush(mCompositionBrush.Get());
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+
+ return hr;
+}
+
+void CompositorNativeWindow11::commitChange()
+{
+ // Windows::UI::Composition uses an implicit commit model hence no action needed here
+}
+
+// static
+bool CompositorNativeWindow11::IsValidNativeWindow(EGLNativeWindowType window)
+{
+ return IsSupportedWinRelease() && IsSpriteVisual(window);
+}
+
+// static
+bool CompositorNativeWindow11::IsSupportedWinRelease()
+{
+ RoHelper helper;
+ if (!helper.WinRtAvailable())
+ {
+ return false;
+ }
+
+ return helper.SupportedWindowsRelease();
+}
+
+bool CompositorNativeWindow11::IsSpriteVisual(EGLNativeWindowType window)
+{
+ RoHelper helper;
+
+ ABI::Windows::UI::Composition::ISpriteVisual *inspp =
+ reinterpret_cast<ABI::Windows::UI::Composition::ISpriteVisual *>(window);
+ HSTRING className, spriteClassName;
+ HSTRING_HEADER spriteClassNameHeader;
+
+ auto hr = helper.GetStringReference(RuntimeClass_Windows_UI_Composition_SpriteVisual,
+ &spriteClassName, &spriteClassNameHeader);
+ if (FAILED(hr))
+ {
+ return false;
+ }
+
+ hr = inspp->GetRuntimeClassName(&className);
+ if (FAILED(hr))
+ {
+ return false;
+ }
+
+ INT32 result = -1;
+ hr = helper.WindowsCompareStringOrdinal(className, spriteClassName, &result);
+
+ helper.WindowsDeleteString(className);
+
+ if (FAILED(hr))
+ {
+ return false;
+ }
+
+ if (result == 0)
+ {
+ return true;
+ }
+
+ return false;
+}
+
+// RoHelperImpl
+
+template <typename T>
+bool AssignProcAddress(HMODULE comBaseModule, const char *name, T *&outProc)
+{
+ outProc = reinterpret_cast<T *>(GetProcAddress(comBaseModule, name));
+ return *outProc != nullptr;
+}
+
+RoHelper::RoHelper()
+ : mFpWindowsCreateStringReference(nullptr),
+ mFpGetActivationFactory(nullptr),
+ mFpWindowsCompareStringOrdinal(nullptr),
+ mFpCreateDispatcherQueueController(nullptr),
+ mFpWindowsDeleteString(nullptr),
+ mFpRoInitialize(nullptr),
+ mFpRoUninitialize(nullptr),
+ mWinRtAvailable(false),
+ mWinRtInitialized(false),
+ mComBaseModule(nullptr),
+ mCoreMessagingModule(nullptr)
+{
+
+#ifdef ANGLE_ENABLE_WINDOWS_UWP
+ mFpWindowsCreateStringReference = &::WindowsCreateStringReference;
+ mFpRoInitialize = &::RoInitialize;
+ mFpRoUninitialize = &::RoUninitialize;
+ mFpWindowsDeleteString = &::WindowsDeleteString;
+ mFpGetActivationFactory = &::RoGetActivationFactory;
+ mFpWindowsCompareStringOrdinal = &::WindowsCompareStringOrdinal;
+ mFpCreateDispatcherQueueController = &::CreateDispatcherQueueController;
+ mWinRtAvailable = true;
+#else
+
+ mComBaseModule = LoadLibraryA("ComBase.dll");
+
+ if (mComBaseModule == nullptr)
+ {
+ return;
+ }
+
+ if (!AssignProcAddress(mComBaseModule, "WindowsCreateStringReference",
+ mFpWindowsCreateStringReference))
+ {
+ return;
+ }
+
+ if (!AssignProcAddress(mComBaseModule, "RoGetActivationFactory", mFpGetActivationFactory))
+ {
+ return;
+ }
+
+ if (!AssignProcAddress(mComBaseModule, "WindowsCompareStringOrdinal",
+ mFpWindowsCompareStringOrdinal))
+ {
+ return;
+ }
+
+ if (!AssignProcAddress(mComBaseModule, "WindowsDeleteString", mFpWindowsDeleteString))
+ {
+ return;
+ }
+
+ if (!AssignProcAddress(mComBaseModule, "RoInitialize", mFpRoInitialize))
+ {
+ return;
+ }
+
+ if (!AssignProcAddress(mComBaseModule, "RoUninitialize", mFpRoUninitialize))
+ {
+ return;
+ }
+
+ mCoreMessagingModule = LoadLibraryA("coremessaging.dll");
+
+ if (mCoreMessagingModule == nullptr)
+ {
+ return;
+ }
+
+ if (!AssignProcAddress(mCoreMessagingModule, "CreateDispatcherQueueController",
+ mFpCreateDispatcherQueueController))
+ {
+ return;
+ }
+
+ auto result = RoInitialize(RO_INIT_MULTITHREADED);
+
+ if (SUCCEEDED(result) || result == RPC_E_CHANGED_MODE)
+ {
+ mWinRtAvailable = true;
+
+ if (SUCCEEDED(result))
+ {
+ mWinRtInitialized = true;
+ }
+ }
+#endif
+}
+
+RoHelper::~RoHelper()
+{
+#ifndef ANGLE_ENABLE_WINDOWS_UWP
+ if (mWinRtInitialized)
+ {
+ RoUninitialize();
+ }
+
+ if (mCoreMessagingModule != nullptr)
+ {
+ FreeLibrary(mCoreMessagingModule);
+ mCoreMessagingModule = nullptr;
+ }
+
+ if (mComBaseModule != nullptr)
+ {
+ FreeLibrary(mComBaseModule);
+ mComBaseModule = nullptr;
+ }
+#endif
+}
+
+bool RoHelper::WinRtAvailable() const
+{
+ return mWinRtAvailable;
+}
+
+bool RoHelper::SupportedWindowsRelease()
+{
+ if (!mWinRtAvailable)
+ {
+ return false;
+ }
+
+ HSTRING className, contractName;
+ HSTRING_HEADER classNameHeader, contractNameHeader;
+ boolean isSupported = false;
+
+ HRESULT hr = GetStringReference(RuntimeClass_Windows_Foundation_Metadata_ApiInformation,
+ &className, &classNameHeader);
+
+ if (FAILED(hr))
+ {
+ return !!isSupported;
+ }
+
+ Microsoft::WRL::ComPtr<ABI::Windows::Foundation::Metadata::IApiInformationStatics> api;
+
+ hr = GetActivationFactory(
+ className, __uuidof(ABI::Windows::Foundation::Metadata::IApiInformationStatics), &api);
+
+ if (FAILED(hr))
+ {
+ return !!isSupported;
+ }
+
+ hr = GetStringReference(L"Windows.Foundation.UniversalApiContract", &contractName,
+ &contractNameHeader);
+ if (FAILED(hr))
+ {
+ return !!isSupported;
+ }
+
+ api->IsApiContractPresentByMajor(contractName, 6, &isSupported);
+
+ return !!isSupported;
+}
+
+HRESULT RoHelper::GetStringReference(PCWSTR source, HSTRING *act, HSTRING_HEADER *header)
+{
+ if (!mWinRtAvailable)
+ {
+ return E_FAIL;
+ }
+
+ const wchar_t *str = static_cast<const wchar_t *>(source);
+
+ unsigned int length;
+ HRESULT hr = SizeTToUInt32(::wcslen(str), &length);
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+
+ return mFpWindowsCreateStringReference(source, length, header, act);
+}
+
+HRESULT RoHelper::GetActivationFactory(const HSTRING act, const IID &interfaceId, void **fac)
+{
+ if (!mWinRtAvailable)
+ {
+ return E_FAIL;
+ }
+ auto hr = mFpGetActivationFactory(act, interfaceId, fac);
+ return hr;
+}
+
+HRESULT RoHelper::WindowsCompareStringOrdinal(HSTRING one, HSTRING two, int *result)
+{
+ if (!mWinRtAvailable)
+ {
+ return E_FAIL;
+ }
+ return mFpWindowsCompareStringOrdinal(one, two, result);
+}
+
+HRESULT RoHelper::CreateDispatcherQueueController(
+ DispatcherQueueOptions options,
+ ABI::Windows::System::IDispatcherQueueController **dispatcherQueueController)
+{
+ if (!mWinRtAvailable)
+ {
+ return E_FAIL;
+ }
+ return mFpCreateDispatcherQueueController(options, dispatcherQueueController);
+}
+
+HRESULT RoHelper::WindowsDeleteString(HSTRING one)
+{
+ if (!mWinRtAvailable)
+ {
+ return E_FAIL;
+ }
+ return mFpWindowsDeleteString(one);
+}
+
+HRESULT RoHelper::RoInitialize(RO_INIT_TYPE type)
+{
+ return mFpRoInitialize(type);
+}
+
+void RoHelper::RoUninitialize()
+{
+ mFpRoUninitialize();
+}
+
+} // namespace rx