CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
Path: blob/master/UWP/Common/DeviceResources.cpp
Views: 1401
#include "pch.h"1#include <algorithm>2#include "DeviceResources.h"3#include "DirectXHelper.h"45#include "Core/Config.h"6#include "Common/StringUtils.h"7#include "Common/Data/Encoding/Utf8.h"89using namespace D2D1;10using namespace DirectX;11using namespace Microsoft::WRL;12using namespace Windows::Foundation;13using namespace Windows::Graphics::Display;14using namespace Windows::UI::Core;15using namespace Windows::UI::Xaml::Controls;16using namespace Platform;1718namespace DisplayMetrics19{20// High resolution displays can require a lot of GPU and battery power to render.21// High resolution phones, for example, may suffer from poor battery life if22// games attempt to render at 60 frames per second at full fidelity.23// The decision to render at full fidelity across all platforms and form factors24// should be deliberate.25static const bool SupportHighResolutions = true;2627// The default thresholds that define a "high resolution" display. If the thresholds28// are exceeded and SupportHighResolutions is false, the dimensions will be scaled29// by 50%.30static const float DpiThreshold = 192.0f; // 200% of standard desktop display.31static const float WidthThreshold = 1920.0f; // 1080p width.32static const float HeightThreshold = 1080.0f; // 1080p height.33};3435// Constants used to calculate screen rotations36namespace ScreenRotation37{38// 0-degree Z-rotation39static const XMFLOAT4X4 Rotation0(401.0f, 0.0f, 0.0f, 0.0f,410.0f, 1.0f, 0.0f, 0.0f,420.0f, 0.0f, 1.0f, 0.0f,430.0f, 0.0f, 0.0f, 1.0f44);4546// 90-degree Z-rotation47static const XMFLOAT4X4 Rotation90(480.0f, 1.0f, 0.0f, 0.0f,49-1.0f, 0.0f, 0.0f, 0.0f,500.0f, 0.0f, 1.0f, 0.0f,510.0f, 0.0f, 0.0f, 1.0f52);5354// 180-degree Z-rotation55static const XMFLOAT4X4 Rotation180(56-1.0f, 0.0f, 0.0f, 0.0f,570.0f, -1.0f, 0.0f, 0.0f,580.0f, 0.0f, 1.0f, 0.0f,590.0f, 0.0f, 0.0f, 1.0f60);6162// 270-degree Z-rotation63static const XMFLOAT4X4 Rotation270(640.0f, -1.0f, 0.0f, 0.0f,651.0f, 0.0f, 0.0f, 0.0f,660.0f, 0.0f, 1.0f, 0.0f,670.0f, 0.0f, 0.0f, 1.0f68);69};7071// Constructor for DeviceResources.72DX::DeviceResources::DeviceResources() :73m_screenViewport(),74m_d3dFeatureLevel(D3D_FEATURE_LEVEL_9_1),75m_d3dRenderTargetSize(),76m_outputSize(),77m_logicalSize(),78m_nativeOrientation(DisplayOrientations::None),79m_currentOrientation(DisplayOrientations::None),80m_dpi(-1.0f),81m_effectiveDpi(-1.0f),82m_deviceNotify(nullptr)83{84CreateDeviceIndependentResources();85CreateDeviceResources();86}8788// Configures resources that don't depend on the Direct3D device.89void DX::DeviceResources::CreateDeviceIndependentResources()90{91// Initialize Direct2D resources.92D2D1_FACTORY_OPTIONS options;93ZeroMemory(&options, sizeof(D2D1_FACTORY_OPTIONS));9495#if defined(_DEBUG)96// If the project is in a debug build, enable Direct2D debugging via SDK Layers.97options.debugLevel = D2D1_DEBUG_LEVEL_INFORMATION;98#endif99100// Initialize the Direct2D Factory.101DX::ThrowIfFailed(102D2D1CreateFactory(103D2D1_FACTORY_TYPE_SINGLE_THREADED,104__uuidof(ID2D1Factory3),105&options,106&m_d2dFactory107)108);109110// Initialize the DirectWrite Factory.111DX::ThrowIfFailed(112DWriteCreateFactory(113DWRITE_FACTORY_TYPE_SHARED,114__uuidof(IDWriteFactory3),115&m_dwriteFactory116)117);118119// Initialize the Windows Imaging Component (WIC) Factory.120DX::ThrowIfFailed(121CoCreateInstance(122CLSID_WICImagingFactory2,123nullptr,124CLSCTX_INPROC_SERVER,125IID_PPV_ARGS(&m_wicFactory)126)127);128}129130// Configures the Direct3D device, and stores handles to it and the device context.131void DX::DeviceResources::CreateDeviceResources(IDXGIAdapter* vAdapter)132{133// This flag adds support for surfaces with a different color channel ordering134// than the API default. It is required for compatibility with Direct2D.135UINT creationFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;136137#if defined(_DEBUG)138if (DX::SdkLayersAvailable())139{140// If the project is in a debug build, enable debugging via SDK Layers with this flag.141creationFlags |= D3D11_CREATE_DEVICE_DEBUG;142}143#endif144145// This array defines the set of DirectX hardware feature levels this app will support.146// Note the ordering should be preserved.147// Don't forget to declare your application's minimum required feature level in its148// description. All applications are assumed to support 9.1 unless otherwise stated.149D3D_FEATURE_LEVEL featureLevels[] =150{151D3D_FEATURE_LEVEL_12_1,152D3D_FEATURE_LEVEL_12_0,153D3D_FEATURE_LEVEL_11_1,154D3D_FEATURE_LEVEL_11_0,155D3D_FEATURE_LEVEL_10_1,156D3D_FEATURE_LEVEL_10_0,157D3D_FEATURE_LEVEL_9_3,158D3D_FEATURE_LEVEL_9_2,159D3D_FEATURE_LEVEL_9_1160};161162// Create the Direct3D 11 API device object and a corresponding context.163ComPtr<ID3D11Device> device;164ComPtr<ID3D11DeviceContext> context;165auto hardwareType = (vAdapter != nullptr ? D3D_DRIVER_TYPE_UNKNOWN : D3D_DRIVER_TYPE_HARDWARE);166HRESULT hr = D3D11CreateDevice(167vAdapter, // Specify nullptr to use the default adapter.168hardwareType, // Create a device using the hardware graphics driver.1690, // Should be 0 unless the driver is D3D_DRIVER_TYPE_SOFTWARE.170creationFlags, // Set debug and Direct2D compatibility flags.171featureLevels, // List of feature levels this app can support.172ARRAYSIZE(featureLevels), // Size of the list above.173D3D11_SDK_VERSION, // Always set this to D3D11_SDK_VERSION for Windows Store apps.174&device, // Returns the Direct3D device created.175&m_d3dFeatureLevel, // Returns feature level of device created.176&context // Returns the device immediate context.177);178179if (FAILED(hr))180{181// If the initialization fails, fall back to the WARP device.182// For more information on WARP, see:183// http://go.microsoft.com/fwlink/?LinkId=286690184DX::ThrowIfFailed(185D3D11CreateDevice(186nullptr,187D3D_DRIVER_TYPE_WARP, // Create a WARP device instead of a hardware device.1880,189creationFlags,190featureLevels,191ARRAYSIZE(featureLevels),192D3D11_SDK_VERSION,193&device,194&m_d3dFeatureLevel,195&context196)197);198}199200if (!vAdapter && CreateAdaptersList(device)) {201// While fetching the adapters list202// we will check if the configs has custom adapter203// then will recall this function to create device with custom adapter204// so we have to stop here, if the `CreateAdaptersList` return true205return;206}207208// Store pointers to the Direct3D 11.3 API device and immediate context.209DX::ThrowIfFailed(210device.As(&m_d3dDevice)211);212213DX::ThrowIfFailed(214context.As(&m_d3dContext)215);216217DX::ThrowIfFailed(218m_d3dDevice.As(&m_dxgiDevice)219);220221DX::ThrowIfFailed(222m_dxgiDevice->GetAdapter(&m_dxgiAdapter)223);224225DX::ThrowIfFailed(226m_dxgiAdapter->GetParent(IID_PPV_ARGS(&m_dxgiFactory))227);228229// Create the Direct2D device object and a corresponding context.230DX::ThrowIfFailed(231m_d3dDevice.As(&m_dxgiDevice)232);233234DX::ThrowIfFailed(235m_d2dFactory->CreateDevice(m_dxgiDevice.Get(), &m_d2dDevice)236);237238DX::ThrowIfFailed(239m_d2dDevice->CreateDeviceContext(240D2D1_DEVICE_CONTEXT_OPTIONS_NONE,241&m_d2dContext242)243);244}245246bool DX::DeviceResources::CreateAdaptersList(ComPtr<ID3D11Device> device) {247ComPtr<IDXGIDevice3> dxgi_device;248DX::ThrowIfFailed(249device.As(&dxgi_device)250);251252Microsoft::WRL::ComPtr<IDXGIAdapter> deviceAdapter;253dxgi_device->GetAdapter(&deviceAdapter);254255Microsoft::WRL::ComPtr<IDXGIFactory4> deviceFactory;256deviceAdapter->GetParent(IID_PPV_ARGS(&deviceFactory));257258// Current adapter (Get current adapter name)259DXGI_ADAPTER_DESC currentDefaultAdapterDesc;260deviceAdapter->GetDesc(¤tDefaultAdapterDesc);261std::string currentDefaultAdapterName = ConvertWStringToUTF8(currentDefaultAdapterDesc.Description);262263UINT i = 0;264IDXGIAdapter* pAdapter;265IDXGIAdapter* customAdapter = nullptr;266auto deviceInfo = Windows::System::Profile::AnalyticsInfo::VersionInfo;267bool isXbox = deviceInfo->DeviceFamily == "Windows.Xbox";268while (deviceFactory->EnumAdapters(i, &pAdapter) != DXGI_ERROR_NOT_FOUND)269{270++i;271DXGI_ADAPTER_DESC vAdapterDesc;272pAdapter->GetDesc(&vAdapterDesc);273auto adapterDescription = ConvertWStringToUTF8(vAdapterDesc.Description);274if (isXbox && adapterDescription == "Microsoft Basic Render Driver") {275// Skip, very slow and not usefull for Xbox276continue;277}278m_vAdapters.push_back(adapterDescription);279if (!g_Config.sD3D11Device.empty() && g_Config.sD3D11Device == adapterDescription) {280// Double check if it's the same default adapter281if (adapterDescription != currentDefaultAdapterName) {282customAdapter = pAdapter;283}284}285}286deviceFactory->Release();287288if (m_vAdapters.size() == 1) {289// Only one (default) adapter, clear the list to hide device option from settings290m_vAdapters.clear();291}292293bool reCreateDevice = false;294if (customAdapter) {295reCreateDevice = true;296// Recreate device with custom adapter297CreateDeviceResources(customAdapter);298}299300return reCreateDevice;301}302303// These resources need to be recreated every time the window size is changed.304void DX::DeviceResources::CreateWindowSizeDependentResources()305{306// Window pointer was previously submited by `SetWindow` called from (App.cpp)307// we don't have to do that since we can easily get the current window308auto coreWindow = CoreWindow::GetForCurrentThread();309310SetWindow(coreWindow);311312// Clear the previous window size specific context.313ID3D11RenderTargetView* nullViews[] = {nullptr};314m_d3dContext->OMSetRenderTargets(ARRAYSIZE(nullViews), nullViews, nullptr);315m_d3dRenderTargetView = nullptr;316m_d2dContext->SetTarget(nullptr);317m_d2dTargetBitmap = nullptr;318m_d3dContext->Flush1(D3D11_CONTEXT_TYPE_ALL, nullptr);319320UpdateRenderTargetSize();321322// The width and height of the swap chain must be based on the window's323// natively-oriented width and height. If the window is not in the native324// orientation, the dimensions must be reversed.325DXGI_MODE_ROTATION displayRotation = ComputeDisplayRotation();326327bool swapDimensions = displayRotation == DXGI_MODE_ROTATION_ROTATE90 || displayRotation == DXGI_MODE_ROTATION_ROTATE270;328m_d3dRenderTargetSize.Width = swapDimensions ? m_outputSize.Height : m_outputSize.Width;329m_d3dRenderTargetSize.Height = swapDimensions ? m_outputSize.Width : m_outputSize.Height;330331if (m_swapChain != nullptr)332{333// If the swap chain already exists, resize it.334HRESULT hr = m_swapChain->ResizeBuffers(3352, // Double-buffered swap chain.336lround(m_d3dRenderTargetSize.Width),337lround(m_d3dRenderTargetSize.Height),338DXGI_FORMAT_B8G8R8A8_UNORM,3390340);341342if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET)343{344// If the device was removed for any reason, a new device and swap chain will need to be created.345HandleDeviceLost();346347// Everything is set up now. Do not continue execution of this method. HandleDeviceLost will reenter this method348// and correctly set up the new device.349return;350}351else352{353DX::ThrowIfFailed(hr);354}355}356else357{358// Otherwise, create a new one using the same adapter as the existing Direct3D device.359DXGI_SCALING scaling = DisplayMetrics::SupportHighResolutions ? DXGI_SCALING_NONE : DXGI_SCALING_STRETCH;360DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {0};361362swapChainDesc.Width = lround(m_d3dRenderTargetSize.Width); // Match the size of the window.363swapChainDesc.Height = lround(m_d3dRenderTargetSize.Height);364swapChainDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; // This is the most common swap chain format.365swapChainDesc.Stereo = false;366swapChainDesc.SampleDesc.Count = 1; // Don't use multi-sampling.367swapChainDesc.SampleDesc.Quality = 0;368swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;369swapChainDesc.BufferCount = 2; // Use double-buffering to minimize latency.370swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; // All Windows Store apps must use this SwapEffect.371swapChainDesc.Flags = 0;372swapChainDesc.Scaling = scaling;373swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE;374375ComPtr<IDXGISwapChain1> swapChain;376DX::ThrowIfFailed(377m_dxgiFactory->CreateSwapChainForCoreWindow(378m_d3dDevice.Get(),379reinterpret_cast<IUnknown*>(coreWindow),380&swapChainDesc,381nullptr,382&swapChain383)384);385DX::ThrowIfFailed(386swapChain.As(&m_swapChain)387);388389// Ensure that DXGI does not queue more than one frame at a time. This both reduces latency and390// ensures that the application will only render after each VSync, minimizing power consumption.391DX::ThrowIfFailed(392m_dxgiDevice->SetMaximumFrameLatency(1)393);394}395396// Set the proper orientation for the swap chain, and generate 2D and397// 3D matrix transformations for rendering to the rotated swap chain.398// Note the rotation angle for the 2D and 3D transforms are different.399// This is due to the difference in coordinate spaces. Additionally,400// the 3D matrix is specified explicitly to avoid rounding errors.401402switch (displayRotation)403{404case DXGI_MODE_ROTATION_IDENTITY:405m_orientationTransform2D = Matrix3x2F::Identity();406m_orientationTransform3D = ScreenRotation::Rotation0;407break;408409case DXGI_MODE_ROTATION_ROTATE90:410m_orientationTransform2D =411Matrix3x2F::Rotation(90.0f) *412Matrix3x2F::Translation(m_logicalSize.Height, 0.0f);413m_orientationTransform3D = ScreenRotation::Rotation270;414break;415416case DXGI_MODE_ROTATION_ROTATE180:417m_orientationTransform2D =418Matrix3x2F::Rotation(180.0f) *419Matrix3x2F::Translation(m_logicalSize.Width, m_logicalSize.Height);420m_orientationTransform3D = ScreenRotation::Rotation180;421break;422423case DXGI_MODE_ROTATION_ROTATE270:424m_orientationTransform2D =425Matrix3x2F::Rotation(270.0f) *426Matrix3x2F::Translation(0.0f, m_logicalSize.Width);427m_orientationTransform3D = ScreenRotation::Rotation90;428break;429430default:431throw ref new FailureException();432}433434DX::ThrowIfFailed(435m_swapChain->SetRotation(displayRotation)436);437438// Create a render target view of the swap chain back buffer.439ComPtr<ID3D11Texture2D1> backBuffer;440DX::ThrowIfFailed(441m_swapChain->GetBuffer(0, IID_PPV_ARGS(&backBuffer))442);443444DX::ThrowIfFailed(445m_d3dDevice->CreateRenderTargetView1(446backBuffer.Get(),447nullptr,448&m_d3dRenderTargetView449)450);451452// Set the 3D rendering viewport to target the entire window.453m_screenViewport = CD3D11_VIEWPORT(4540.0f,4550.0f,456m_d3dRenderTargetSize.Width,457m_d3dRenderTargetSize.Height458);459460m_d3dContext->RSSetViewports(1, &m_screenViewport);461462// Create a Direct2D target bitmap associated with the463// swap chain back buffer and set it as the current target.464D2D1_BITMAP_PROPERTIES1 bitmapProperties =465D2D1::BitmapProperties1(466D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW,467D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED),468m_dpi,469m_dpi470);471472ComPtr<IDXGISurface2> dxgiBackBuffer;473DX::ThrowIfFailed(474m_swapChain->GetBuffer(0, IID_PPV_ARGS(&dxgiBackBuffer))475);476477DX::ThrowIfFailed(478m_d2dContext->CreateBitmapFromDxgiSurface(479dxgiBackBuffer.Get(),480&bitmapProperties,481&m_d2dTargetBitmap482)483);484485m_d2dContext->SetTarget(m_d2dTargetBitmap.Get());486m_d2dContext->SetDpi(m_effectiveDpi, m_effectiveDpi);487488// Grayscale text anti-aliasing is recommended for all Windows Store apps.489m_d2dContext->SetTextAntialiasMode(D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE);490}491492// Determine the dimensions of the render target and whether it will be scaled down.493void DX::DeviceResources::UpdateRenderTargetSize()494{495m_effectiveDpi = m_dpi;496if (Windows::System::Profile::AnalyticsInfo::VersionInfo->DeviceFamily == L"Windows.Xbox")497{498m_effectiveDpi = 96.0f / static_cast<float>(m_logicalSize.Height) * 1080.0f;499}500else501{502// To improve battery life on high resolution devices, render to a smaller render target503// and allow the GPU to scale the output when it is presented.504if (!DisplayMetrics::SupportHighResolutions && m_dpi >= DisplayMetrics::DpiThreshold)505{506float width = DX::ConvertDipsToPixels(m_logicalSize.Width, m_dpi);507float height = DX::ConvertDipsToPixels(m_logicalSize.Height, m_dpi);508509// When the device is in portrait orientation, height > width. Compare the510// larger dimension against the width threshold and the smaller dimension511// against the height threshold.512if (std::max(width, height) > DisplayMetrics::WidthThreshold && std::min(width, height) > DisplayMetrics::HeightThreshold)513{514// To scale the app we change the effective DPI. Logical size does not change.515m_effectiveDpi /= 2.0f;516}517}518}519// Calculate the necessary render target size in pixels.520m_outputSize.Width = DX::ConvertDipsToPixels(m_logicalSize.Width, m_effectiveDpi);521m_outputSize.Height = DX::ConvertDipsToPixels(m_logicalSize.Height, m_effectiveDpi);522523// Prevent zero size DirectX content from being created.524m_outputSize.Width = std::max(m_outputSize.Width, 1.0f);525m_outputSize.Height = std::max(m_outputSize.Height, 1.0f);526}527528// This method is called when the CoreWindow is created (or re-created).529void DX::DeviceResources::SetWindow(CoreWindow^ window)530{531DisplayInformation^ currentDisplayInformation = DisplayInformation::GetForCurrentView();532533if (Windows::System::Profile::AnalyticsInfo::VersionInfo->DeviceFamily == L"Windows.Xbox")534{535const auto hdi = Windows::Graphics::Display::Core::HdmiDisplayInformation::GetForCurrentView();536if (hdi)537{538try539{540const auto dm = hdi->GetCurrentDisplayMode();541const float hdmi_width = (float)dm->ResolutionWidthInRawPixels;542const float hdmi_height = (float)dm->ResolutionHeightInRawPixels;543// If we're running on Xbox, use the HDMI mode instead of the CoreWindow size.544// In UWP, the CoreWindow is always 1920x1080, even when running at 4K.545546m_logicalSize = Windows::Foundation::Size(hdmi_width, hdmi_height);547m_dpi = currentDisplayInformation->LogicalDpi * 1.5f;548}549catch (const Platform::Exception^)550{551m_logicalSize = Windows::Foundation::Size(window->Bounds.Width, window->Bounds.Height);552m_dpi = currentDisplayInformation->LogicalDpi;553}554}555}556else557{558m_logicalSize = Windows::Foundation::Size(window->Bounds.Width, window->Bounds.Height);559m_dpi = currentDisplayInformation->LogicalDpi;560}561m_nativeOrientation = currentDisplayInformation->NativeOrientation;562m_currentOrientation = currentDisplayInformation->CurrentOrientation;563564m_d2dContext->SetDpi(m_dpi, m_dpi);565}566567// This method is called in the event handler for the SizeChanged event.568void DX::DeviceResources::SetLogicalSize(Windows::Foundation::Size logicalSize)569{570if (m_logicalSize != logicalSize)571{572m_logicalSize = logicalSize;573CreateWindowSizeDependentResources();574}575}576577// This method is called in the event handler for the DpiChanged event.578void DX::DeviceResources::SetDpi(float dpi)579{580if (dpi != m_dpi)581{582m_dpi = dpi;583584// When the display DPI changes, the logical size of the window (measured in Dips)585// also changes and needs to be updated.586CreateWindowSizeDependentResources();587}588}589590// This method is called in the event handler for the OrientationChanged event.591void DX::DeviceResources::SetCurrentOrientation(DisplayOrientations currentOrientation)592{593if (m_currentOrientation != currentOrientation)594{595m_currentOrientation = currentOrientation;596CreateWindowSizeDependentResources();597}598}599600// This method is called in the event handler for the DisplayContentsInvalidated event.601void DX::DeviceResources::ValidateDevice()602{603// The D3D Device is no longer valid if the default adapter changed since the device604// was created or if the device has been removed.605606// First, get the information for the default adapter from when the device was created.607ComPtr<IDXGIAdapter1> previousDefaultAdapter;608DX::ThrowIfFailed(m_dxgiFactory->EnumAdapters1(0, &previousDefaultAdapter));609610DXGI_ADAPTER_DESC1 previousDesc;611DX::ThrowIfFailed(previousDefaultAdapter->GetDesc1(&previousDesc));612613// Next, get the information for the current default adapter.614615ComPtr<IDXGIFactory4> currentFactory;616DX::ThrowIfFailed(CreateDXGIFactory1(IID_PPV_ARGS(¤tFactory)));617618ComPtr<IDXGIAdapter1> currentDefaultAdapter;619DX::ThrowIfFailed(currentFactory->EnumAdapters1(0, ¤tDefaultAdapter));620621DXGI_ADAPTER_DESC1 currentDesc;622DX::ThrowIfFailed(currentDefaultAdapter->GetDesc1(¤tDesc));623624// If the adapter LUIDs don't match, or if the device reports that it has been removed,625// a new D3D device must be created.626627if (previousDesc.AdapterLuid.LowPart != currentDesc.AdapterLuid.LowPart ||628previousDesc.AdapterLuid.HighPart != currentDesc.AdapterLuid.HighPart ||629FAILED(m_d3dDevice->GetDeviceRemovedReason()))630{631// Release references to resources related to the old device.632previousDefaultAdapter = nullptr;633634// Create a new device and swap chain.635HandleDeviceLost();636}637}638639// Recreate all device resources and set them back to the current state.640void DX::DeviceResources::HandleDeviceLost()641{642m_swapChain = nullptr;643644if (m_deviceNotify != nullptr)645{646m_deviceNotify->OnDeviceLost();647}648649CreateDeviceResources();650m_d2dContext->SetDpi(m_dpi, m_dpi);651CreateWindowSizeDependentResources();652653if (m_deviceNotify != nullptr)654{655m_deviceNotify->OnDeviceRestored();656}657}658659// Register our DeviceNotify to be informed on device lost and creation.660void DX::DeviceResources::RegisterDeviceNotify(DX::IDeviceNotify* deviceNotify)661{662m_deviceNotify = deviceNotify;663}664665// Call this method when the app suspends. It provides a hint to the driver that the app666// is entering an idle state and that temporary buffers can be reclaimed for use by other apps.667void DX::DeviceResources::Trim()668{669ComPtr<IDXGIDevice3> dxgiDevice;670m_d3dDevice.As(&dxgiDevice);671672dxgiDevice->Trim();673}674675// Present the contents of the swap chain to the screen.676void DX::DeviceResources::Present()677{678// The first argument instructs DXGI to block until VSync, putting the application679// to sleep until the next VSync. This ensures we don't waste any cycles rendering680// frames that will never be displayed to the screen.681DXGI_PRESENT_PARAMETERS parameters = { 0 };682HRESULT hr = m_swapChain->Present1(1, 0, ¶meters);683684// Discard the contents of the render target.685// This is a valid operation only when the existing contents will be entirely686// overwritten. If dirty or scroll rects are used, this call should be removed.687m_d3dContext->DiscardView1(m_d3dRenderTargetView.Get(), nullptr, 0);688689// If the device was removed either by a disconnection or a driver upgrade, we690// must recreate all device resources.691if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET)692{693HandleDeviceLost();694}695else696{697DX::ThrowIfFailed(hr);698}699}700701// This method determines the rotation between the display device's native orientation and the702// current display orientation.703DXGI_MODE_ROTATION DX::DeviceResources::ComputeDisplayRotation()704{705DXGI_MODE_ROTATION rotation = DXGI_MODE_ROTATION_UNSPECIFIED;706707// Note: NativeOrientation can only be Landscape or Portrait even though708// the DisplayOrientations enum has other values.709switch (m_nativeOrientation)710{711case DisplayOrientations::Landscape:712switch (m_currentOrientation)713{714case DisplayOrientations::Landscape:715rotation = DXGI_MODE_ROTATION_IDENTITY;716break;717718case DisplayOrientations::Portrait:719rotation = DXGI_MODE_ROTATION_ROTATE270;720break;721722case DisplayOrientations::LandscapeFlipped:723rotation = DXGI_MODE_ROTATION_ROTATE180;724break;725726case DisplayOrientations::PortraitFlipped:727rotation = DXGI_MODE_ROTATION_ROTATE90;728break;729}730break;731732case DisplayOrientations::Portrait:733switch (m_currentOrientation)734{735case DisplayOrientations::Landscape:736rotation = DXGI_MODE_ROTATION_ROTATE90;737break;738739case DisplayOrientations::Portrait:740rotation = DXGI_MODE_ROTATION_IDENTITY;741break;742743case DisplayOrientations::LandscapeFlipped:744rotation = DXGI_MODE_ROTATION_ROTATE270;745break;746747case DisplayOrientations::PortraitFlipped:748rotation = DXGI_MODE_ROTATION_ROTATE180;749break;750}751break;752}753return rotation;754}755756757