direct3d_helper.cc revision effb81e5f8246d0db0270817048dc992db66e9fb
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" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "win8/metro_driver/direct3d_helper.h" 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "win8/metro_driver/winrt_utils.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 10effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "base/win/windows_version.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include <corewindow.h> 13effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include <windows.applicationmodel.core.h> 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <windows.graphics.display.h> 155821806d5e7f356e8fa4b058a389a808ea183019Torne (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) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)float GetLogicalDpi() { 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mswr::ComPtr<wingfx::Display::IDisplayPropertiesStatics> display_properties; 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckIfFailed(winrt_utils::CreateActivationFactory( 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RuntimeClass_Windows_Graphics_Display_DisplayProperties, 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) display_properties.GetAddressOf())); 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) float dpi = 0.0; 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckIfFailed(display_properties->get_LogicalDpi(&dpi)); 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return dpi; 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)float ConvertDipsToPixels(float dips) { 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const float dips_per_inch = 96.f; 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) float logical_dpi = GetLogicalDpi(); 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return floor(dips * logical_dpi / dips_per_inch + 0.5f); 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace metro_driver { 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Direct3DHelper::Direct3DHelper() { 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Direct3DHelper::~Direct3DHelper() { 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Direct3DHelper::Initialize(winui::Core::ICoreWindow* window) { 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window_ = window; 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CreateDeviceResources(); 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CreateWindowSizeDependentResources(); 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(scottmg): Need to handle resize messages and recreation. 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Direct3DHelper::CreateDeviceResources() { 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned int creation_flags = D3D11_CREATE_DEVICE_BGRA_SUPPORT; 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) D3D_FEATURE_LEVEL feature_levels[] = { 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) D3D_FEATURE_LEVEL_11_1, 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) D3D_FEATURE_LEVEL_11_0, 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) D3D_FEATURE_LEVEL_10_1, 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) D3D_FEATURE_LEVEL_10_0, 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) D3D_FEATURE_LEVEL_9_3, 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) D3D_FEATURE_LEVEL_9_2, 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) D3D_FEATURE_LEVEL_9_1, 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mswr::ComPtr<ID3D11Device> device; 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mswr::ComPtr<ID3D11DeviceContext> context; 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckIfFailed( 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) D3D11CreateDevice( 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nullptr, 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) D3D_DRIVER_TYPE_HARDWARE, 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nullptr, 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) creation_flags, 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) feature_levels, 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ARRAYSIZE(feature_levels), 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) D3D11_SDK_VERSION, 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &device, 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &feature_level_, 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &context)); 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckIfFailed(device.As(&d3d_device_)); 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckIfFailed(context.As(&d3d_context_)); 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Direct3DHelper::CreateWindowSizeDependentResources() { 89effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch float window_width = 0; 90effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch float window_height = 0; 91effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 92effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (base::win::GetVersion() >= base::win::VERSION_WIN8) { 93effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // Windows 8 returns in DIPs. 94effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch CheckIfFailed(window_->get_Bounds(&window_bounds_)); 95effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch window_width = ConvertDipsToPixels(window_width); 96effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch window_height = ConvertDipsToPixels(window_height); 97effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(scottmg): Orientation. 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (swap_chain_ != nullptr) { 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(scottmg): Resize if it already exists. 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTIMPLEMENTED(); 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DXGI_SWAP_CHAIN_DESC1 swap_chain_desc = { 0 }; 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) swap_chain_desc.Width = window_width; 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) swap_chain_desc.Height = window_height; 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) swap_chain_desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) swap_chain_desc.Stereo = false; 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) swap_chain_desc.SampleDesc.Count = 1; 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) swap_chain_desc.SampleDesc.Quality = 0; 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) swap_chain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) swap_chain_desc.BufferCount = 2; // TODO(scottmg): Probably 1 is fine. 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) swap_chain_desc.Scaling = DXGI_SCALING_NONE; 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) swap_chain_desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) swap_chain_desc.Flags = 0; 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mswr::ComPtr<IDXGIDevice1> dxgi_device; 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckIfFailed(d3d_device_.As(&dxgi_device)); 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mswr::ComPtr<IDXGIAdapter> dxgi_adapter; 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckIfFailed(dxgi_device->GetAdapter(&dxgi_adapter)); 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mswr::ComPtr<IDXGIFactory2> dxgi_factory; 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckIfFailed(dxgi_adapter->GetParent( 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) __uuidof(IDXGIFactory2), &dxgi_factory)); 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 128effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (base::win::GetVersion() >= base::win::VERSION_WIN8) { 129effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // On Win8 we need the CoreWindow interface to create the Swapchain. 130effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch CheckIfFailed(dxgi_factory->CreateSwapChainForCoreWindow( 131effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch d3d_device_.Get(), 132effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch reinterpret_cast<IUnknown*>(window_), 133effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch &swap_chain_desc, 134effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch nullptr, 135effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch &swap_chain_)); 136effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } else { 137effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // On Win7 we need the raw HWND to create the Swapchain. 138effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch mswr::ComPtr<ICoreWindowInterop> interop; 139effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch CheckIfFailed(window_->QueryInterface(interop.GetAddressOf())); 140effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch HWND window = NULL; 141effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch interop->get_WindowHandle(&window); 142effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 143effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch swap_chain_desc.Scaling = DXGI_SCALING_STRETCH; 144effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch swap_chain_desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; 145effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 146effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch CheckIfFailed(dxgi_factory->CreateSwapChainForHwnd( 147effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch d3d_device_.Get(), 148effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch window, 149effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch &swap_chain_desc, 150effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch nullptr, 151effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch nullptr, 152effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch &swap_chain_)); 153effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace metro_driver 158