Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / win8 / metro_driver / direct3d_helper.cc
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       // 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));
160     }
161   }
162 }
163
164 }  // namespace metro_driver