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.
6 #include <corewindow.h>
7 #include <windows.applicationmodel.core.h>
8 #include <windows.graphics.display.h>
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"
18 void CheckIfFailed(HRESULT hr
) {
21 DVLOG(0) << "Direct3D call failed, hr = " << hr
;
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()));
34 CheckIfFailed(display_properties
->get_LogicalDpi(&dpi
));
38 float ConvertDipsToPixels(float dips
) {
39 return floor(dips
* gfx::GetDPIScale() + 0.5f
);
44 namespace metro_driver
{
46 Direct3DHelper::Direct3DHelper() {
49 Direct3DHelper::~Direct3DHelper() {
52 void Direct3DHelper::Initialize(winui::Core::ICoreWindow
* window
) {
54 CreateDeviceResources();
55 CreateWindowSizeDependentResources();
58 // TODO(scottmg): Need to handle resize messages and recreation.
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
,
72 mswr::ComPtr
<ID3D11Device
> device
;
73 mswr::ComPtr
<ID3D11DeviceContext
> context
;
77 D3D_DRIVER_TYPE_HARDWARE
,
81 ARRAYSIZE(feature_levels
),
86 CheckIfFailed(device
.As(&d3d_device_
));
87 CheckIfFailed(context
.As(&d3d_context_
));
90 void Direct3DHelper::CreateWindowSizeDependentResources() {
91 float window_width
= 0;
92 float window_height
= 0;
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
);
101 // TODO(scottmg): Orientation.
103 if (swap_chain_
!= nullptr) {
104 // TODO(scottmg): Resize if it already exists.
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;
120 mswr::ComPtr
<IDXGIDevice1
> dxgi_device
;
121 CheckIfFailed(d3d_device_
.As(&dxgi_device
));
123 mswr::ComPtr
<IDXGIAdapter
> dxgi_adapter
;
124 CheckIfFailed(dxgi_device
->GetAdapter(&dxgi_adapter
));
126 mswr::ComPtr
<IDXGIFactory2
> dxgi_factory
;
127 CheckIfFailed(dxgi_adapter
->GetParent(
128 __uuidof(IDXGIFactory2
), &dxgi_factory
));
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(
134 reinterpret_cast<IUnknown
*>(window_
),
139 // On Win7 we need the raw HWND to create the Swapchain.
140 mswr::ComPtr
<ICoreWindowInterop
> interop
;
141 CheckIfFailed(window_
->QueryInterface(interop
.GetAddressOf()));
143 interop
->get_WindowHandle(&window
);
145 swap_chain_desc
.Scaling
= DXGI_SCALING_STRETCH
;
146 swap_chain_desc
.SwapEffect
= DXGI_SWAP_EFFECT_DISCARD
;
148 CheckIfFailed(dxgi_factory
->CreateSwapChainForHwnd(
155 // Prevent DXGI from monitoring an application message queue and thus
156 // attempt mode changes. For e.g. Alt + Enter by default causes
157 // DXGI to attempt to take the window fullscreen.
158 CheckIfFailed(dxgi_factory
->MakeWindowAssociation(
159 window
, DXGI_MWA_NO_WINDOW_CHANGES
));
164 } // namespace metro_driver