| // Copyright 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "stdafx.h" |
| #include <corewindow.h> |
| #include <windows.applicationmodel.core.h> |
| #include <windows.graphics.display.h> |
| |
| #include "win8/metro_driver/direct3d_helper.h" |
| #include "base/logging.h" |
| #include "base/win/windows_version.h" |
| #include "ui/gfx/win/dpi.h" |
| #include "win8/metro_driver/winrt_utils.h" |
| |
| namespace { |
| |
| void CheckIfFailed(HRESULT hr) { |
| DCHECK(!FAILED(hr)); |
| if (FAILED(hr)) |
| DVLOG(0) << "Direct3D call failed, hr = " << hr; |
| } |
| |
| // TODO(ananta) |
| // This function does not return the correct value as the IDisplayProperties |
| // interface does not work correctly in Windows 8 in metro mode. Needs |
| // more investigation. |
| float GetLogicalDpi() { |
| mswr::ComPtr<wingfx::Display::IDisplayPropertiesStatics> display_properties; |
| CheckIfFailed(winrt_utils::CreateActivationFactory( |
| RuntimeClass_Windows_Graphics_Display_DisplayProperties, |
| display_properties.GetAddressOf())); |
| float dpi = 0.0; |
| CheckIfFailed(display_properties->get_LogicalDpi(&dpi)); |
| return dpi; |
| } |
| |
| float ConvertDipsToPixels(float dips) { |
| return floor(dips * gfx::GetDPIScale() + 0.5f); |
| } |
| |
| } |
| |
| namespace metro_driver { |
| |
| Direct3DHelper::Direct3DHelper() { |
| } |
| |
| Direct3DHelper::~Direct3DHelper() { |
| } |
| |
| void Direct3DHelper::Initialize(winui::Core::ICoreWindow* window) { |
| window_ = window; |
| CreateDeviceResources(); |
| CreateWindowSizeDependentResources(); |
| } |
| |
| // TODO(scottmg): Need to handle resize messages and recreation. |
| |
| void Direct3DHelper::CreateDeviceResources() { |
| unsigned int creation_flags = D3D11_CREATE_DEVICE_BGRA_SUPPORT; |
| D3D_FEATURE_LEVEL feature_levels[] = { |
| D3D_FEATURE_LEVEL_11_1, |
| D3D_FEATURE_LEVEL_11_0, |
| D3D_FEATURE_LEVEL_10_1, |
| D3D_FEATURE_LEVEL_10_0, |
| D3D_FEATURE_LEVEL_9_3, |
| D3D_FEATURE_LEVEL_9_2, |
| D3D_FEATURE_LEVEL_9_1, |
| }; |
| |
| mswr::ComPtr<ID3D11Device> device; |
| mswr::ComPtr<ID3D11DeviceContext> context; |
| CheckIfFailed( |
| D3D11CreateDevice( |
| nullptr, |
| D3D_DRIVER_TYPE_HARDWARE, |
| nullptr, |
| creation_flags, |
| feature_levels, |
| ARRAYSIZE(feature_levels), |
| D3D11_SDK_VERSION, |
| &device, |
| &feature_level_, |
| &context)); |
| CheckIfFailed(device.As(&d3d_device_)); |
| CheckIfFailed(context.As(&d3d_context_)); |
| } |
| |
| void Direct3DHelper::CreateWindowSizeDependentResources() { |
| float window_width = 0; |
| float window_height = 0; |
| |
| if (base::win::GetVersion() >= base::win::VERSION_WIN8) { |
| // Windows 8 returns in DIPs. |
| CheckIfFailed(window_->get_Bounds(&window_bounds_)); |
| window_width = ConvertDipsToPixels(window_width); |
| window_height = ConvertDipsToPixels(window_height); |
| } |
| |
| // TODO(scottmg): Orientation. |
| |
| if (swap_chain_ != nullptr) { |
| // TODO(scottmg): Resize if it already exists. |
| NOTIMPLEMENTED(); |
| } else { |
| DXGI_SWAP_CHAIN_DESC1 swap_chain_desc = { 0 }; |
| swap_chain_desc.Width = window_width; |
| swap_chain_desc.Height = window_height; |
| swap_chain_desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; |
| swap_chain_desc.Stereo = false; |
| swap_chain_desc.SampleDesc.Count = 1; |
| swap_chain_desc.SampleDesc.Quality = 0; |
| swap_chain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; |
| swap_chain_desc.BufferCount = 2; // TODO(scottmg): Probably 1 is fine. |
| swap_chain_desc.Scaling = DXGI_SCALING_NONE; |
| swap_chain_desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; |
| swap_chain_desc.Flags = 0; |
| |
| mswr::ComPtr<IDXGIDevice1> dxgi_device; |
| CheckIfFailed(d3d_device_.As(&dxgi_device)); |
| |
| mswr::ComPtr<IDXGIAdapter> dxgi_adapter; |
| CheckIfFailed(dxgi_device->GetAdapter(&dxgi_adapter)); |
| |
| mswr::ComPtr<IDXGIFactory2> dxgi_factory; |
| CheckIfFailed(dxgi_adapter->GetParent( |
| __uuidof(IDXGIFactory2), &dxgi_factory)); |
| |
| if (base::win::GetVersion() >= base::win::VERSION_WIN8) { |
| // On Win8 we need the CoreWindow interface to create the Swapchain. |
| CheckIfFailed(dxgi_factory->CreateSwapChainForCoreWindow( |
| d3d_device_.Get(), |
| reinterpret_cast<IUnknown*>(window_), |
| &swap_chain_desc, |
| nullptr, |
| &swap_chain_)); |
| } else { |
| // On Win7 we need the raw HWND to create the Swapchain. |
| mswr::ComPtr<ICoreWindowInterop> interop; |
| CheckIfFailed(window_->QueryInterface(interop.GetAddressOf())); |
| HWND window = NULL; |
| interop->get_WindowHandle(&window); |
| |
| swap_chain_desc.Scaling = DXGI_SCALING_STRETCH; |
| swap_chain_desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; |
| |
| CheckIfFailed(dxgi_factory->CreateSwapChainForHwnd( |
| d3d_device_.Get(), |
| window, |
| &swap_chain_desc, |
| nullptr, |
| nullptr, |
| &swap_chain_)); |
| // Prevent DXGI from monitoring an application message queue and thus |
| // attempt mode changes. For e.g. Alt + Enter by default causes |
| // DXGI to attempt to take the window fullscreen. |
| CheckIfFailed(dxgi_factory->MakeWindowAssociation( |
| window, DXGI_MWA_NO_WINDOW_CHANGES)); |
| } |
| } |
| } |
| |
| } // namespace metro_driver |