direct3d_helper.cc revision cedac228d2dd51db4b79ea1e72c7f249408ee061
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "stdafx.h" 6effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include <corewindow.h> 7effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include <windows.applicationmodel.core.h> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <windows.graphics.display.h> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "win8/metro_driver/direct3d_helper.h" 11cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/logging.h" 12cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/win/windows_version.h" 13cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "ui/gfx/win/dpi.h" 14cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "win8/metro_driver/winrt_utils.h" 15cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CheckIfFailed(HRESULT hr) { 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!FAILED(hr)); 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FAILED(hr)) 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DVLOG(0) << "Direct3D call failed, hr = " << hr; 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// TODO(ananta) 25cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// This function does not return the correct value as the IDisplayProperties 26cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// interface does not work correctly in Windows 8 in metro mode. Needs 27cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// more investigation. 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)float GetLogicalDpi() { 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mswr::ComPtr<wingfx::Display::IDisplayPropertiesStatics> display_properties; 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckIfFailed(winrt_utils::CreateActivationFactory( 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RuntimeClass_Windows_Graphics_Display_DisplayProperties, 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) display_properties.GetAddressOf())); 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) float dpi = 0.0; 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckIfFailed(display_properties->get_LogicalDpi(&dpi)); 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return dpi; 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)float ConvertDipsToPixels(float dips) { 39cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return floor(dips * gfx::GetDPIScale() + 0.5f); 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace metro_driver { 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Direct3DHelper::Direct3DHelper() { 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Direct3DHelper::~Direct3DHelper() { 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Direct3DHelper::Initialize(winui::Core::ICoreWindow* window) { 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window_ = window; 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CreateDeviceResources(); 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CreateWindowSizeDependentResources(); 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(scottmg): Need to handle resize messages and recreation. 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Direct3DHelper::CreateDeviceResources() { 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned int creation_flags = D3D11_CREATE_DEVICE_BGRA_SUPPORT; 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) D3D_FEATURE_LEVEL feature_levels[] = { 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) D3D_FEATURE_LEVEL_11_1, 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) D3D_FEATURE_LEVEL_11_0, 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) D3D_FEATURE_LEVEL_10_1, 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) D3D_FEATURE_LEVEL_10_0, 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) D3D_FEATURE_LEVEL_9_3, 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) D3D_FEATURE_LEVEL_9_2, 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) D3D_FEATURE_LEVEL_9_1, 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mswr::ComPtr<ID3D11Device> device; 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mswr::ComPtr<ID3D11DeviceContext> context; 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckIfFailed( 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) D3D11CreateDevice( 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nullptr, 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) D3D_DRIVER_TYPE_HARDWARE, 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nullptr, 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) creation_flags, 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) feature_levels, 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ARRAYSIZE(feature_levels), 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) D3D11_SDK_VERSION, 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &device, 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &feature_level_, 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &context)); 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckIfFailed(device.As(&d3d_device_)); 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckIfFailed(context.As(&d3d_context_)); 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Direct3DHelper::CreateWindowSizeDependentResources() { 91effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch float window_width = 0; 92effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch float window_height = 0; 93effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 94effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (base::win::GetVersion() >= base::win::VERSION_WIN8) { 95effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // Windows 8 returns in DIPs. 96effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch CheckIfFailed(window_->get_Bounds(&window_bounds_)); 97effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch window_width = ConvertDipsToPixels(window_width); 98effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch window_height = ConvertDipsToPixels(window_height); 99effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(scottmg): Orientation. 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (swap_chain_ != nullptr) { 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(scottmg): Resize if it already exists. 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTIMPLEMENTED(); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DXGI_SWAP_CHAIN_DESC1 swap_chain_desc = { 0 }; 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) swap_chain_desc.Width = window_width; 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) swap_chain_desc.Height = window_height; 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) swap_chain_desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) swap_chain_desc.Stereo = false; 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) swap_chain_desc.SampleDesc.Count = 1; 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) swap_chain_desc.SampleDesc.Quality = 0; 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) swap_chain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) swap_chain_desc.BufferCount = 2; // TODO(scottmg): Probably 1 is fine. 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) swap_chain_desc.Scaling = DXGI_SCALING_NONE; 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) swap_chain_desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) swap_chain_desc.Flags = 0; 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mswr::ComPtr<IDXGIDevice1> dxgi_device; 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckIfFailed(d3d_device_.As(&dxgi_device)); 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mswr::ComPtr<IDXGIAdapter> dxgi_adapter; 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckIfFailed(dxgi_device->GetAdapter(&dxgi_adapter)); 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mswr::ComPtr<IDXGIFactory2> dxgi_factory; 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckIfFailed(dxgi_adapter->GetParent( 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) __uuidof(IDXGIFactory2), &dxgi_factory)); 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 130effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (base::win::GetVersion() >= base::win::VERSION_WIN8) { 131effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // On Win8 we need the CoreWindow interface to create the Swapchain. 132effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch CheckIfFailed(dxgi_factory->CreateSwapChainForCoreWindow( 133effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch d3d_device_.Get(), 134effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch reinterpret_cast<IUnknown*>(window_), 135effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch &swap_chain_desc, 136effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch nullptr, 137effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch &swap_chain_)); 138effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } else { 139effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // On Win7 we need the raw HWND to create the Swapchain. 140effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch mswr::ComPtr<ICoreWindowInterop> interop; 141effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch CheckIfFailed(window_->QueryInterface(interop.GetAddressOf())); 142effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch HWND window = NULL; 143effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch interop->get_WindowHandle(&window); 144effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 145effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch swap_chain_desc.Scaling = DXGI_SCALING_STRETCH; 146effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch swap_chain_desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; 147effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 148effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch CheckIfFailed(dxgi_factory->CreateSwapChainForHwnd( 149effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch d3d_device_.Get(), 150effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch window, 151effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch &swap_chain_desc, 152effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch nullptr, 153effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch nullptr, 154effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch &swap_chain_)); 155effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace metro_driver 160