1 // Copyright 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "stdafx.h" 6 #include <corewindow.h> 7 #include <windows.applicationmodel.core.h> 8 #include <windows.graphics.display.h> 9 10 #include "win8/metro_driver/direct3d_helper.h" 11 #include "base/logging.h" 12 #include "base/win/windows_version.h" 13 #include "ui/gfx/win/dpi.h" 14 #include "win8/metro_driver/winrt_utils.h" 15 16 namespace { 17 18 void CheckIfFailed(HRESULT hr) { 19 DCHECK(!FAILED(hr)); 20 if (FAILED(hr)) 21 DVLOG(0) << "Direct3D call failed, hr = " << hr; 22 } 23 24 // TODO(ananta) 25 // This function does not return the correct value as the IDisplayProperties 26 // interface does not work correctly in Windows 8 in metro mode. Needs 27 // more investigation. 28 float GetLogicalDpi() { 29 mswr::ComPtr<wingfx::Display::IDisplayPropertiesStatics> display_properties; 30 CheckIfFailed(winrt_utils::CreateActivationFactory( 31 RuntimeClass_Windows_Graphics_Display_DisplayProperties, 32 display_properties.GetAddressOf())); 33 float dpi = 0.0; 34 CheckIfFailed(display_properties->get_LogicalDpi(&dpi)); 35 return dpi; 36 } 37 38 float ConvertDipsToPixels(float dips) { 39 return floor(dips * gfx::GetDPIScale() + 0.5f); 40 } 41 42 } 43 44 namespace metro_driver { 45 46 Direct3DHelper::Direct3DHelper() { 47 } 48 49 Direct3DHelper::~Direct3DHelper() { 50 } 51 52 void Direct3DHelper::Initialize(winui::Core::ICoreWindow* window) { 53 window_ = window; 54 CreateDeviceResources(); 55 CreateWindowSizeDependentResources(); 56 } 57 58 // TODO(scottmg): Need to handle resize messages and recreation. 59 60 void Direct3DHelper::CreateDeviceResources() { 61 unsigned int creation_flags = D3D11_CREATE_DEVICE_BGRA_SUPPORT; 62 D3D_FEATURE_LEVEL feature_levels[] = { 63 D3D_FEATURE_LEVEL_11_1, 64 D3D_FEATURE_LEVEL_11_0, 65 D3D_FEATURE_LEVEL_10_1, 66 D3D_FEATURE_LEVEL_10_0, 67 D3D_FEATURE_LEVEL_9_3, 68 D3D_FEATURE_LEVEL_9_2, 69 D3D_FEATURE_LEVEL_9_1, 70 }; 71 72 mswr::ComPtr<ID3D11Device> device; 73 mswr::ComPtr<ID3D11DeviceContext> context; 74 CheckIfFailed( 75 D3D11CreateDevice( 76 nullptr, 77 D3D_DRIVER_TYPE_HARDWARE, 78 nullptr, 79 creation_flags, 80 feature_levels, 81 ARRAYSIZE(feature_levels), 82 D3D11_SDK_VERSION, 83 &device, 84 &feature_level_, 85 &context)); 86 CheckIfFailed(device.As(&d3d_device_)); 87 CheckIfFailed(context.As(&d3d_context_)); 88 } 89 90 void Direct3DHelper::CreateWindowSizeDependentResources() { 91 float window_width = 0; 92 float window_height = 0; 93 94 if (base::win::GetVersion() >= base::win::VERSION_WIN8) { 95 // Windows 8 returns in DIPs. 96 CheckIfFailed(window_->get_Bounds(&window_bounds_)); 97 window_width = ConvertDipsToPixels(window_width); 98 window_height = ConvertDipsToPixels(window_height); 99 } 100 101 // TODO(scottmg): Orientation. 102 103 if (swap_chain_ != nullptr) { 104 // TODO(scottmg): Resize if it already exists. 105 NOTIMPLEMENTED(); 106 } else { 107 DXGI_SWAP_CHAIN_DESC1 swap_chain_desc = { 0 }; 108 swap_chain_desc.Width = window_width; 109 swap_chain_desc.Height = window_height; 110 swap_chain_desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; 111 swap_chain_desc.Stereo = false; 112 swap_chain_desc.SampleDesc.Count = 1; 113 swap_chain_desc.SampleDesc.Quality = 0; 114 swap_chain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; 115 swap_chain_desc.BufferCount = 2; // TODO(scottmg): Probably 1 is fine. 116 swap_chain_desc.Scaling = DXGI_SCALING_NONE; 117 swap_chain_desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; 118 swap_chain_desc.Flags = 0; 119 120 mswr::ComPtr<IDXGIDevice1> dxgi_device; 121 CheckIfFailed(d3d_device_.As(&dxgi_device)); 122 123 mswr::ComPtr<IDXGIAdapter> dxgi_adapter; 124 CheckIfFailed(dxgi_device->GetAdapter(&dxgi_adapter)); 125 126 mswr::ComPtr<IDXGIFactory2> dxgi_factory; 127 CheckIfFailed(dxgi_adapter->GetParent( 128 __uuidof(IDXGIFactory2), &dxgi_factory)); 129 130 if (base::win::GetVersion() >= base::win::VERSION_WIN8) { 131 // On Win8 we need the CoreWindow interface to create the Swapchain. 132 CheckIfFailed(dxgi_factory->CreateSwapChainForCoreWindow( 133 d3d_device_.Get(), 134 reinterpret_cast<IUnknown*>(window_), 135 &swap_chain_desc, 136 nullptr, 137 &swap_chain_)); 138 } else { 139 // On Win7 we need the raw HWND to create the Swapchain. 140 mswr::ComPtr<ICoreWindowInterop> interop; 141 CheckIfFailed(window_->QueryInterface(interop.GetAddressOf())); 142 HWND window = NULL; 143 interop->get_WindowHandle(&window); 144 145 swap_chain_desc.Scaling = DXGI_SCALING_STRETCH; 146 swap_chain_desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; 147 148 CheckIfFailed(dxgi_factory->CreateSwapChainForHwnd( 149 d3d_device_.Get(), 150 window, 151 &swap_chain_desc, 152 nullptr, 153 nullptr, 154 &swap_chain_)); 155 } 156 } 157 } 158 159 } // namespace metro_driver 160