Home | History | Annotate | Download | only in metro_driver
      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