bool SwapChainPanelNativeWindow::registerForSizeChangeEvents() { ComPtr<ISizeChangedEventHandler> sizeChangedHandler; ComPtr<IFrameworkElement> frameworkElement; HRESULT result = Microsoft::WRL::MakeAndInitialize<SwapChainPanelSizeChangedHandler>(sizeChangedHandler.ReleaseAndGetAddressOf(), this->shared_from_this()); if (SUCCEEDED(result)) { result = mSwapChainPanel.As(&frameworkElement); } if (SUCCEEDED(result)) { result = RunOnUIThread( [this, frameworkElement, sizeChangedHandler] { return frameworkElement->add_SizeChanged(sizeChangedHandler.Get(), &mSizeChangedEventToken); }, mSwapChainPanelDispatcher); } if (SUCCEEDED(result)) { return true; } return false; }
HRESULT GetSwapChainPanelSize( const ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> &swapChainPanel, const ComPtr<ICoreDispatcher> &dispatcher, SIZE *windowSize) { ComPtr<IUIElement> uiElement; Size renderSize = {0, 0}; HRESULT result = swapChainPanel.As(&uiElement); if (SUCCEEDED(result)) { result = RunOnUIThread( [uiElement, &renderSize] { return uiElement->get_RenderSize(&renderSize); }, dispatcher); } if (SUCCEEDED(result)) { *windowSize = { lround(renderSize.Width), lround(renderSize.Height) }; } return result; }
HRESULT GetSwapChainPanelSize( const ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> &swapChainPanel, const ComPtr<ICoreDispatcher> &dispatcher, Size *windowSize) { ComPtr<IUIElement> uiElement; HRESULT result = swapChainPanel.As(&uiElement); if (SUCCEEDED(result)) { result = RunOnUIThread( [uiElement, windowSize] { return uiElement->get_RenderSize(windowSize); }, dispatcher); } return result; }
void SwapChainPanelNativeWindow::unregisterForSizeChangeEvents() { ComPtr<IFrameworkElement> frameworkElement; if (mSwapChainPanel && SUCCEEDED(mSwapChainPanel.As(&frameworkElement))) { RunOnUIThread( [this, frameworkElement] { return frameworkElement->remove_SizeChanged(mSizeChangedEventToken); }, mSwapChainPanelDispatcher); } mSizeChangedEventToken.value = 0; }
HRESULT SwapChainPanelNativeWindow::createSwapChain(ID3D11Device *device, IDXGIFactory2 *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, bool containsAlpha, IDXGISwapChain1 **swapChain) { if (device == nullptr || factory == nullptr || swapChain == nullptr || width == 0 || height == 0) { return E_INVALIDARG; } DXGI_SWAP_CHAIN_DESC1 swapChainDesc = { 0 }; swapChainDesc.Width = width; swapChainDesc.Height = height; swapChainDesc.Format = format; swapChainDesc.Stereo = FALSE; swapChainDesc.SampleDesc.Count = 1; swapChainDesc.SampleDesc.Quality = 0; swapChainDesc.BufferUsage = DXGI_USAGE_SHADER_INPUT | DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_BACK_BUFFER; swapChainDesc.BufferCount = 2; swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; swapChainDesc.Scaling = DXGI_SCALING_STRETCH; swapChainDesc.AlphaMode = containsAlpha ? DXGI_ALPHA_MODE_PREMULTIPLIED : DXGI_ALPHA_MODE_IGNORE; *swapChain = nullptr; ComPtr<IDXGISwapChain1> newSwapChain; ComPtr<ISwapChainPanelNative> swapChainPanelNative; Size currentPanelSize = {}; HRESULT result = factory->CreateSwapChainForComposition(device, &swapChainDesc, nullptr, newSwapChain.ReleaseAndGetAddressOf()); if (SUCCEEDED(result)) { result = mSwapChainPanel.As(&swapChainPanelNative); } if (SUCCEEDED(result)) { result = RunOnUIThread( [swapChainPanelNative, newSwapChain] { return swapChainPanelNative->SetSwapChain(newSwapChain.Get()); }, mSwapChainPanelDispatcher); } if (SUCCEEDED(result)) { // The swapchain panel host requires an instance of the swapchain set on the SwapChainPanel // to perform the runtime-scale behavior. This swapchain is cached here because there are // no methods for retreiving the currently configured on from ISwapChainPanelNative. mSwapChain = newSwapChain; result = newSwapChain.CopyTo(swapChain); } // If the host is responsible for scaling the output of the swapchain, then // scale it now before returning an instance to the caller. This is done by // first reading the current size of the swapchain panel, then scaling if (SUCCEEDED(result)) { if (mSwapChainSizeSpecified || mSwapChainScaleSpecified) { result = GetSwapChainPanelSize(mSwapChainPanel, mSwapChainPanelDispatcher, ¤tPanelSize); // Scale the swapchain to fit inside the contents of the panel. if (SUCCEEDED(result)) { result = scaleSwapChain(currentPanelSize, mClientRect); } } } return result; }