// 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_)); } } } } // namespace metro_driver