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