// Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "stdafx.h" #include "win8/metro_driver/direct3d_helper.h" #include "win8/metro_driver/winrt_utils.h" #include "base/logging.h" #include <windows.graphics.display.h> namespace { void CheckIfFailed(HRESULT hr) { DCHECK(!FAILED(hr)); if (FAILED(hr)) DVLOG(0) << "Direct3D call failed, hr = " << hr; } float GetLogicalDpi() { mswr::ComPtr<wingfx::Display::IDisplayPropertiesStatics> display_properties; CheckIfFailed(winrt_utils::CreateActivationFactory( RuntimeClass_Windows_Graphics_Display_DisplayProperties, display_properties.GetAddressOf())); float dpi = 0.0; CheckIfFailed(display_properties->get_LogicalDpi(&dpi)); return dpi; } float ConvertDipsToPixels(float dips) { static const float dips_per_inch = 96.f; float logical_dpi = GetLogicalDpi(); return floor(dips * logical_dpi / dips_per_inch + 0.5f); } } namespace metro_driver { Direct3DHelper::Direct3DHelper() { } Direct3DHelper::~Direct3DHelper() { } void Direct3DHelper::Initialize(winui::Core::ICoreWindow* window) { window_ = window; CreateDeviceResources(); CreateWindowSizeDependentResources(); } // TODO(scottmg): Need to handle resize messages and recreation. void Direct3DHelper::CreateDeviceResources() { unsigned int creation_flags = D3D11_CREATE_DEVICE_BGRA_SUPPORT; D3D_FEATURE_LEVEL feature_levels[] = { D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_10_0, D3D_FEATURE_LEVEL_9_3, D3D_FEATURE_LEVEL_9_2, D3D_FEATURE_LEVEL_9_1, }; mswr::ComPtr<ID3D11Device> device; mswr::ComPtr<ID3D11DeviceContext> context; CheckIfFailed( D3D11CreateDevice( nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, creation_flags, feature_levels, ARRAYSIZE(feature_levels), D3D11_SDK_VERSION, &device, &feature_level_, &context)); CheckIfFailed(device.As(&d3d_device_)); CheckIfFailed(context.As(&d3d_context_)); } void Direct3DHelper::CreateWindowSizeDependentResources() { CheckIfFailed(window_->get_Bounds(&window_bounds_)); float window_width = ConvertDipsToPixels(window_bounds_.Width); float window_height = ConvertDipsToPixels(window_bounds_.Height); // TODO(scottmg): Orientation. if (swap_chain_ != nullptr) { // TODO(scottmg): Resize if it already exists. NOTIMPLEMENTED(); } else { DXGI_SWAP_CHAIN_DESC1 swap_chain_desc = { 0 }; swap_chain_desc.Width = window_width; swap_chain_desc.Height = window_height; swap_chain_desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; swap_chain_desc.Stereo = false; swap_chain_desc.SampleDesc.Count = 1; swap_chain_desc.SampleDesc.Quality = 0; swap_chain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; swap_chain_desc.BufferCount = 2; // TODO(scottmg): Probably 1 is fine. swap_chain_desc.Scaling = DXGI_SCALING_NONE; swap_chain_desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; swap_chain_desc.Flags = 0; mswr::ComPtr<IDXGIDevice1> dxgi_device; CheckIfFailed(d3d_device_.As(&dxgi_device)); mswr::ComPtr<IDXGIAdapter> dxgi_adapter; CheckIfFailed(dxgi_device->GetAdapter(&dxgi_adapter)); mswr::ComPtr<IDXGIFactory2> dxgi_factory; CheckIfFailed(dxgi_adapter->GetParent( __uuidof(IDXGIFactory2), &dxgi_factory)); CheckIfFailed(dxgi_factory->CreateSwapChainForCoreWindow( d3d_device_.Get(), reinterpret_cast<IUnknown*>(window_), &swap_chain_desc, nullptr, &swap_chain_)); } } } // namespace metro_driver