bool SwapChainPanelNativeWindow::initialize(EGLNativeWindowType window, IPropertySet *propertySet) { ComPtr<IPropertySet> props = propertySet; ComPtr<IInspectable> win = window; SIZE swapChainSize = {}; bool swapChainSizeSpecified = false; HRESULT result = S_OK; // IPropertySet is an optional parameter and can be null. // If one is specified, cache as an IMap and read the properties // used for initial host initialization. if (propertySet) { result = props.As(&mPropertyMap); if (SUCCEEDED(result)) { // The EGLRenderSurfaceSizeProperty is optional and may be missing. The IPropertySet // was prevalidated to contain the EGLNativeWindowType before being passed to // this host. result = GetOptionalSizePropertyValue(mPropertyMap, EGLRenderSurfaceSizeProperty, &swapChainSize, &swapChainSizeSpecified); } } if (SUCCEEDED(result)) { result = win.As(&mSwapChainPanel); } if (SUCCEEDED(result)) { // If a swapchain size is specfied, then the automatic resize // behaviors implemented by the host should be disabled. The swapchain // will be still be scaled when being rendered to fit the bounds // of the host. // Scaling of the swapchain output needs to be handled by the // host for swapchain panels even though the scaling mode setting // DXGI_SCALING_STRETCH is configured on the swapchain. if (swapChainSizeSpecified) { mClientRect = { 0, 0, swapChainSize.cx, swapChainSize.cy }; // Enable host swapchain scaling mRequiresSwapChainScaling = true; } else { result = GetSwapChainPanelSize(mSwapChainPanel, &mClientRect); } } if (SUCCEEDED(result)) { mNewClientRect = mClientRect; mClientRectChanged = false; return registerForSizeChangeEvents(); } return false; }
bool SwapChainPanelNativeWindow::initialize(EGLNativeWindowType window, IPropertySet *propertySet) { ComPtr<IPropertySet> props = propertySet; ComPtr<IInspectable> win = window; SIZE swapChainSize = {}; HRESULT result = S_OK; // IPropertySet is an optional parameter and can be null. // If one is specified, cache as an IMap and read the properties // used for initial host initialization. if (propertySet) { result = props.As(&mPropertyMap); if (FAILED(result)) { return false; } // The EGLRenderSurfaceSizeProperty is optional and may be missing. The IPropertySet // was prevalidated to contain the EGLNativeWindowType before being passed to // this host. result = GetOptionalSizePropertyValue(mPropertyMap, EGLRenderSurfaceSizeProperty, &swapChainSize, &mSwapChainSizeSpecified); if (FAILED(result)) { return false; } // The EGLRenderResolutionScaleProperty is optional and may be missing. The IPropertySet // was prevalidated to contain the EGLNativeWindowType before being passed to // this host. result = GetOptionalSinglePropertyValue(mPropertyMap, EGLRenderResolutionScaleProperty, &mSwapChainScale, &mSwapChainScaleSpecified); if (FAILED(result)) { return false; } if (!mSwapChainScaleSpecified) { // Default value for the scale is 1.0f mSwapChainScale = 1.0f; } // A EGLRenderSurfaceSizeProperty and a EGLRenderResolutionScaleProperty can't both be specified if (mSwapChainScaleSpecified && mSwapChainSizeSpecified) { ERR() << "It is invalid to specify both an EGLRenderSurfaceSizeProperty and a " "EGLRenderResolutionScaleProperty."; return false; } } if (SUCCEEDED(result)) { 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 a swapchain size is specfied, then the automatic resize // behaviors implemented by the host should be disabled. The swapchain // will be still be scaled when being rendered to fit the bounds // of the host. // Scaling of the swapchain output needs to be handled by the // host for swapchain panels even though the scaling mode setting // DXGI_SCALING_STRETCH is configured on the swapchain. if (mSwapChainSizeSpecified) { mClientRect = { 0, 0, swapChainSize.cx, swapChainSize.cy }; } else { Size swapChainPanelSize; result = GetSwapChainPanelSize(mSwapChainPanel, mSwapChainPanelDispatcher, &swapChainPanelSize); if (SUCCEEDED(result)) { // Update the client rect to account for any swapchain scale factor mClientRect = clientRect(swapChainPanelSize); } } } if (SUCCEEDED(result)) { mNewClientRect = mClientRect; mClientRectChanged = false; return registerForSizeChangeEvents(); } return false; }
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; }
HRESULT SwapChainPanelNativeWindow::createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain) { if (device == NULL || factory == NULL || swapChain == NULL || 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_RENDER_TARGET_OUTPUT | DXGI_USAGE_BACK_BUFFER; swapChainDesc.BufferCount = 2; swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; swapChainDesc.Scaling = DXGI_SCALING_STRETCH; swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE; *swapChain = nullptr; ComPtr<IDXGISwapChain1> newSwapChain; ComPtr<ISwapChainPanelNative> swapChainPanelNative; RECT currentPanelSize = {}; HRESULT result = factory->CreateSwapChainForComposition(device, &swapChainDesc, nullptr, newSwapChain.ReleaseAndGetAddressOf()); if (SUCCEEDED(result)) { result = mSwapChainPanel.As(&swapChainPanelNative); } if (SUCCEEDED(result)) { result = swapChainPanelNative->SetSwapChain(newSwapChain.Get()); } 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) && mRequiresSwapChainScaling) { result = GetSwapChainPanelSize(mSwapChainPanel, ¤tPanelSize); } // Scale the swapchain to fit inside the contents of the panel. if (SUCCEEDED(result) && mRequiresSwapChainScaling) { SIZE currentSize = { currentPanelSize.right, currentPanelSize.bottom }; result = scaleSwapChain(currentSize); } if (SUCCEEDED(result)) { // If automatic swapchain resize behaviors have been disabled, then // unregister for the resize change events. if (mSupportsSwapChainResize == false) { unregisterForSizeChangeEvents(); } } return result; }