Commit 8f68be8b by Austin Kinross Committed by Geoff Lang

In WinRT XAML, allow eglCreateWindowSurface to be called from any thread

Before this change, eglCreateWindowSurface had to be called from one specific XAML thread, which may have been a different thread to the one where rendering was performed. This change fixes this, so eglCreateWindowSurface can be called from any thread. Change-Id: Ic383a508c223d1b0463e8a8f1d8e8d6880c26844 Reviewed-on: https://chromium-review.googlesource.com/300131Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Tested-by: 's avatarAustin Kinross <aukinros@microsoft.com> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent 3c7fee36
...@@ -11,7 +11,11 @@ ...@@ -11,7 +11,11 @@
#include <algorithm> #include <algorithm>
#include <math.h> #include <math.h>
using namespace ABI::Windows::Foundation;
using namespace ABI::Windows::Foundation::Collections; using namespace ABI::Windows::Foundation::Collections;
using namespace ABI::Windows::UI::Core;
using namespace ABI::Windows::UI::Xaml;
using namespace Microsoft::WRL;
namespace rx namespace rx
{ {
...@@ -20,6 +24,69 @@ SwapChainPanelNativeWindow::~SwapChainPanelNativeWindow() ...@@ -20,6 +24,69 @@ SwapChainPanelNativeWindow::~SwapChainPanelNativeWindow()
unregisterForSizeChangeEvents(); unregisterForSizeChangeEvents();
} }
template <typename T>
struct AddFtmBase
{
typedef Implements<RuntimeClassFlags<ClassicCom>, T, FtmBase> Type;
};
template <typename CODE>
HRESULT RunOnUIThread(CODE &&code, const ComPtr<ICoreDispatcher> &dispatcher)
{
ComPtr<IAsyncAction> asyncAction;
HRESULT result = S_OK;
boolean hasThreadAccess;
result = dispatcher->get_HasThreadAccess(&hasThreadAccess);
if (FAILED(result))
{
return result;
}
if (hasThreadAccess)
{
return code();
}
else
{
Event waitEvent(CreateEventEx(NULL, NULL, CREATE_EVENT_MANUAL_RESET, EVENT_ALL_ACCESS));
if (!waitEvent.IsValid())
{
return E_FAIL;
}
HRESULT codeResult = E_FAIL;
auto handler =
Callback<AddFtmBase<IDispatchedHandler>::Type>([&codeResult, &code, &waitEvent]
{
codeResult = code();
SetEvent(waitEvent.Get());
return S_OK;
});
result = dispatcher->RunAsync(CoreDispatcherPriority_Normal, handler.Get(),
asyncAction.GetAddressOf());
if (FAILED(result))
{
return result;
}
auto waitResult = WaitForSingleObjectEx(waitEvent.Get(), 10 * 1000, true);
if (waitResult != WAIT_OBJECT_0)
{
// Wait 10 seconds before giving up. At this point, the application is in an
// unrecoverable state (probably deadlocked). We therefore terminate the application
// entirely. This also prevents stack corruption if the async operation is eventually
// run.
ERR("Timeout waiting for async action on UI thread. The UI thread might be blocked.");
std::terminate();
return E_FAIL;
}
return codeResult;
}
}
bool SwapChainPanelNativeWindow::initialize(EGLNativeWindowType window, IPropertySet *propertySet) bool SwapChainPanelNativeWindow::initialize(EGLNativeWindowType window, IPropertySet *propertySet)
{ {
ComPtr<IPropertySet> props = propertySet; ComPtr<IPropertySet> props = propertySet;
...@@ -75,6 +142,18 @@ bool SwapChainPanelNativeWindow::initialize(EGLNativeWindowType window, IPropert ...@@ -75,6 +142,18 @@ bool SwapChainPanelNativeWindow::initialize(EGLNativeWindowType window, IPropert
result = win.As(&mSwapChainPanel); result = win.As(&mSwapChainPanel);
} }
ComPtr<IDependencyObject> swapChainPanelDependencyObject;
if (SUCCEEDED(result))
{
result = mSwapChainPanel.As(&swapChainPanelDependencyObject);
}
if (SUCCEEDED(result))
{
result = swapChainPanelDependencyObject->get_Dispatcher(
mSwapChainPanelDispatcher.GetAddressOf());
}
if (SUCCEEDED(result)) if (SUCCEEDED(result))
{ {
// If a swapchain size is specfied, then the automatic resize // If a swapchain size is specfied, then the automatic resize
...@@ -91,7 +170,8 @@ bool SwapChainPanelNativeWindow::initialize(EGLNativeWindowType window, IPropert ...@@ -91,7 +170,8 @@ bool SwapChainPanelNativeWindow::initialize(EGLNativeWindowType window, IPropert
else else
{ {
SIZE swapChainPanelSize; SIZE swapChainPanelSize;
result = GetSwapChainPanelSize(mSwapChainPanel, &swapChainPanelSize); result = GetSwapChainPanelSize(mSwapChainPanel, mSwapChainPanelDispatcher,
&swapChainPanelSize);
if (SUCCEEDED(result)) if (SUCCEEDED(result))
{ {
...@@ -113,8 +193,8 @@ bool SwapChainPanelNativeWindow::initialize(EGLNativeWindowType window, IPropert ...@@ -113,8 +193,8 @@ bool SwapChainPanelNativeWindow::initialize(EGLNativeWindowType window, IPropert
bool SwapChainPanelNativeWindow::registerForSizeChangeEvents() bool SwapChainPanelNativeWindow::registerForSizeChangeEvents()
{ {
ComPtr<ABI::Windows::UI::Xaml::ISizeChangedEventHandler> sizeChangedHandler; ComPtr<ISizeChangedEventHandler> sizeChangedHandler;
ComPtr<ABI::Windows::UI::Xaml::IFrameworkElement> frameworkElement; ComPtr<IFrameworkElement> frameworkElement;
HRESULT result = Microsoft::WRL::MakeAndInitialize<SwapChainPanelSizeChangedHandler>(sizeChangedHandler.ReleaseAndGetAddressOf(), this->shared_from_this()); HRESULT result = Microsoft::WRL::MakeAndInitialize<SwapChainPanelSizeChangedHandler>(sizeChangedHandler.ReleaseAndGetAddressOf(), this->shared_from_this());
if (SUCCEEDED(result)) if (SUCCEEDED(result))
...@@ -124,7 +204,13 @@ bool SwapChainPanelNativeWindow::registerForSizeChangeEvents() ...@@ -124,7 +204,13 @@ bool SwapChainPanelNativeWindow::registerForSizeChangeEvents()
if (SUCCEEDED(result)) if (SUCCEEDED(result))
{ {
result = frameworkElement->add_SizeChanged(sizeChangedHandler.Get(), &mSizeChangedEventToken); result = RunOnUIThread(
[this, frameworkElement, sizeChangedHandler]
{
return frameworkElement->add_SizeChanged(sizeChangedHandler.Get(),
&mSizeChangedEventToken);
},
mSwapChainPanelDispatcher);
} }
if (SUCCEEDED(result)) if (SUCCEEDED(result))
...@@ -137,10 +223,15 @@ bool SwapChainPanelNativeWindow::registerForSizeChangeEvents() ...@@ -137,10 +223,15 @@ bool SwapChainPanelNativeWindow::registerForSizeChangeEvents()
void SwapChainPanelNativeWindow::unregisterForSizeChangeEvents() void SwapChainPanelNativeWindow::unregisterForSizeChangeEvents()
{ {
ComPtr<ABI::Windows::UI::Xaml::IFrameworkElement> frameworkElement; ComPtr<IFrameworkElement> frameworkElement;
if (mSwapChainPanel && SUCCEEDED(mSwapChainPanel.As(&frameworkElement))) if (mSwapChainPanel && SUCCEEDED(mSwapChainPanel.As(&frameworkElement)))
{ {
(void)frameworkElement->remove_SizeChanged(mSizeChangedEventToken); RunOnUIThread(
[this, frameworkElement]
{
return frameworkElement->remove_SizeChanged(mSizeChangedEventToken);
},
mSwapChainPanelDispatcher);
} }
mSizeChangedEventToken.value = 0; mSizeChangedEventToken.value = 0;
...@@ -188,7 +279,12 @@ HRESULT SwapChainPanelNativeWindow::createSwapChain(ID3D11Device *device, ...@@ -188,7 +279,12 @@ HRESULT SwapChainPanelNativeWindow::createSwapChain(ID3D11Device *device,
if (SUCCEEDED(result)) if (SUCCEEDED(result))
{ {
result = swapChainPanelNative->SetSwapChain(newSwapChain.Get()); result = RunOnUIThread(
[swapChainPanelNative, newSwapChain]
{
return swapChainPanelNative->SetSwapChain(newSwapChain.Get());
},
mSwapChainPanelDispatcher);
} }
if (SUCCEEDED(result)) if (SUCCEEDED(result))
...@@ -207,7 +303,8 @@ HRESULT SwapChainPanelNativeWindow::createSwapChain(ID3D11Device *device, ...@@ -207,7 +303,8 @@ HRESULT SwapChainPanelNativeWindow::createSwapChain(ID3D11Device *device,
{ {
if (mSwapChainSizeSpecified || mSwapChainScaleSpecified) if (mSwapChainSizeSpecified || mSwapChainScaleSpecified)
{ {
result = GetSwapChainPanelSize(mSwapChainPanel, &currentPanelSize); result = GetSwapChainPanelSize(mSwapChainPanel, mSwapChainPanelDispatcher,
&currentPanelSize);
// Scale the swapchain to fit inside the contents of the panel. // Scale the swapchain to fit inside the contents of the panel.
if (SUCCEEDED(result)) if (SUCCEEDED(result))
...@@ -222,7 +319,8 @@ HRESULT SwapChainPanelNativeWindow::createSwapChain(ID3D11Device *device, ...@@ -222,7 +319,8 @@ HRESULT SwapChainPanelNativeWindow::createSwapChain(ID3D11Device *device,
HRESULT SwapChainPanelNativeWindow::scaleSwapChain(const SIZE &windowSize, const RECT &clientRect) HRESULT SwapChainPanelNativeWindow::scaleSwapChain(const SIZE &windowSize, const RECT &clientRect)
{ {
ABI::Windows::Foundation::Size renderScale = { (float)windowSize.cx / (float)clientRect.right, (float)windowSize.cy / (float)clientRect.bottom }; Size renderScale = {(float)windowSize.cx / (float)clientRect.right,
(float)windowSize.cy / (float)clientRect.bottom};
// Setup a scale matrix for the swap chain // Setup a scale matrix for the swap chain
DXGI_MATRIX_3X2_F scaleMatrix = {}; DXGI_MATRIX_3X2_F scaleMatrix = {};
scaleMatrix._11 = renderScale.Width; scaleMatrix._11 = renderScale.Width;
...@@ -238,14 +336,22 @@ HRESULT SwapChainPanelNativeWindow::scaleSwapChain(const SIZE &windowSize, const ...@@ -238,14 +336,22 @@ HRESULT SwapChainPanelNativeWindow::scaleSwapChain(const SIZE &windowSize, const
return result; return result;
} }
HRESULT GetSwapChainPanelSize(const ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> &swapChainPanel, SIZE *windowSize) HRESULT GetSwapChainPanelSize(
const ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> &swapChainPanel,
const ComPtr<ICoreDispatcher> &dispatcher,
SIZE *windowSize)
{ {
ComPtr<ABI::Windows::UI::Xaml::IUIElement> uiElement; ComPtr<IUIElement> uiElement;
ABI::Windows::Foundation::Size renderSize = { 0, 0 }; Size renderSize = {0, 0};
HRESULT result = swapChainPanel.As(&uiElement); HRESULT result = swapChainPanel.As(&uiElement);
if (SUCCEEDED(result)) if (SUCCEEDED(result))
{ {
result = uiElement->get_RenderSize(&renderSize); result = RunOnUIThread(
[uiElement, &renderSize]
{
return uiElement->get_RenderSize(&renderSize);
},
dispatcher);
} }
if (SUCCEEDED(result)) if (SUCCEEDED(result))
......
...@@ -35,6 +35,7 @@ class SwapChainPanelNativeWindow : public InspectableNativeWindow, public std::e ...@@ -35,6 +35,7 @@ class SwapChainPanelNativeWindow : public InspectableNativeWindow, public std::e
private: private:
ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> mSwapChainPanel; ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> mSwapChainPanel;
ComPtr<ABI::Windows::UI::Core::ICoreDispatcher> mSwapChainPanelDispatcher;
ComPtr<IMap<HSTRING, IInspectable*>> mPropertyMap; ComPtr<IMap<HSTRING, IInspectable*>> mPropertyMap;
ComPtr<DXGISwapChain> mSwapChain; ComPtr<DXGISwapChain> mSwapChain;
}; };
...@@ -83,6 +84,9 @@ class SwapChainPanelSizeChangedHandler : ...@@ -83,6 +84,9 @@ class SwapChainPanelSizeChangedHandler :
std::weak_ptr<InspectableNativeWindow> mHost; std::weak_ptr<InspectableNativeWindow> mHost;
}; };
HRESULT GetSwapChainPanelSize(const ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> &swapChainPanel, SIZE *windowSize); HRESULT GetSwapChainPanelSize(
const ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> &swapChainPanel,
const ComPtr<ABI::Windows::UI::Core::ICoreDispatcher> &dispatcher,
SIZE *windowSize);
} }
#endif // LIBANGLE_RENDERER_D3D_D3D11_WINRT_SWAPCHAINPANELNATIVEWINDOW_H_ #endif // LIBANGLE_RENDERER_D3D_D3D11_WINRT_SWAPCHAINPANELNATIVEWINDOW_H_
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment