Advertisement
Guest User

Untitled

a guest
Jun 26th, 2017
79
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 27.89 KB | None | 0 0
  1. /**
  2. App.cpp
  3. */
  4.  
  5. #include "pch.h"
  6.  
  7. #include <agile.h>
  8. #include <dxgi1_4.h>
  9. #include <d3d11_3.h>
  10. #include <DirectXMath.h>
  11.  
  12. using namespace Windows::ApplicationModel;
  13. using namespace Windows::ApplicationModel::Core;
  14. using namespace Windows::ApplicationModel::Activation;
  15. using namespace Windows::UI::Core;
  16. using namespace Windows::UI::Input;
  17. using namespace Windows::System;
  18. using namespace Windows::Foundation;
  19. using namespace Windows::Graphics::Display;
  20. using namespace Microsoft::WRL;
  21. using namespace DirectX;
  22.  
  23. static float MOUSE_SCALE = 100.0f;
  24.  
  25. static inline void ChkTrue(bool x)
  26. {
  27. assert(x);
  28. if (!x) abort();
  29. }
  30.  
  31. static inline void ChkOk(HRESULT hr)
  32. {
  33. ChkTrue(hr == S_OK);
  34. }
  35.  
  36. ref class AppView sealed : public IFrameworkView
  37. {
  38.  
  39. public:
  40.  
  41. // IFrameworkView Methods.
  42. virtual void Initialize(Windows::ApplicationModel::Core::CoreApplicationView^ applicationView);
  43. virtual void SetWindow(Windows::UI::Core::CoreWindow^ window);
  44. virtual void Load(Platform::String^ entryPoint);
  45. virtual void Run();
  46. virtual void Uninitialize();
  47.  
  48. private:
  49.  
  50. // Event handlers.
  51. void OnActivated(Windows::ApplicationModel::Core::CoreApplicationView^ applicationView, Windows::ApplicationModel::Activation::IActivatedEventArgs^ args);
  52. void OnWindowSizeChanged(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::WindowSizeChangedEventArgs^ args);
  53. void OnVisibilityChanged(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::VisibilityChangedEventArgs^ args);
  54. void OnWindowClosed(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::CoreWindowEventArgs^ args);
  55. void OnDpiChanged(Windows::Graphics::Display::DisplayInformation^ sender, Platform::Object^ args);
  56. void OnOrientationChanged(Windows::Graphics::Display::DisplayInformation^ sender, Platform::Object^ args);
  57. void OnDisplayContentsInvalidated(Windows::Graphics::Display::DisplayInformation^ sender, Platform::Object^ args);
  58. void OnPointerPressed(Windows::UI::Core::CoreWindow ^sender, Windows::UI::Core::PointerEventArgs ^args);
  59. void OnPointerReleased(Windows::UI::Core::CoreWindow ^sender, Windows::UI::Core::PointerEventArgs ^args);
  60. void OnPointerWheelChanged(Windows::UI::Core::CoreWindow ^sender, Windows::UI::Core::PointerEventArgs ^args);
  61. void OnMouseMoved(Windows::Devices::Input::MouseDevice ^sender, Windows::Devices::Input::MouseEventArgs ^args);
  62.  
  63. // Internal methods.
  64. void HandleDeviceLost();
  65. void CreateDeviceResources();
  66. void CreateWindowSizeDependentResources();
  67. DXGI_MODE_ROTATION ComputeDisplayRotation();
  68. float ConvertDipsToPixels(float dips);
  69. void UpdatePointerButtons(Windows::UI::Core::PointerEventArgs^ args);
  70.  
  71. // Window state.
  72. bool m_windowClosed = false;
  73. bool m_windowVisible = true;
  74.  
  75. // Cached window and display properties.
  76. Platform::Agile<Windows::UI::Core::CoreWindow> m_window;
  77. float m_dpi = -1.0f;
  78.  
  79. // Direct3D objects.
  80. Microsoft::WRL::ComPtr<ID3D11Device3> m_device;
  81. Microsoft::WRL::ComPtr<ID3D11DeviceContext3> m_context;
  82. Microsoft::WRL::ComPtr<IDXGISwapChain3> m_swapChain;
  83.  
  84. // Direct3D rendering objects. Required for 3D.
  85. Microsoft::WRL::ComPtr<ID3D11RenderTargetView1> m_renderTargetView;
  86. Microsoft::WRL::ComPtr<ID3D11DepthStencilView> m_depthStencilView;
  87. D3D11_VIEWPORT m_viewport = D3D11_VIEWPORT();
  88.  
  89. // Cached device properties.
  90. D3D_FEATURE_LEVEL m_featureLevel = D3D_FEATURE_LEVEL_9_1;
  91. Windows::Foundation::Size m_renderTargetSize = Windows::Foundation::Size();
  92. Windows::Foundation::Size m_outputSize = Windows::Foundation::Size();
  93. Windows::Foundation::Size m_logicalSize = Windows::Foundation::Size();
  94. Windows::Graphics::Display::DisplayOrientations m_nativeOrientation = Windows::Graphics::Display::DisplayOrientations::None;
  95. Windows::Graphics::Display::DisplayOrientations m_currentOrientation = Windows::Graphics::Display::DisplayOrientations::None;
  96.  
  97. // Transforms used for display orientation.
  98. DirectX::XMFLOAT4X4 m_orientationTransform;
  99.  
  100. // Mouse state.
  101. float MouseDeltaX = 0.0f;
  102. float MouseDeltaY = 0.0f;
  103. float MouseDeltaWheel = 0.0f;
  104. bool MouseButtonL = false;
  105. bool MouseButtonM = false;
  106. bool MouseButtonR = false;
  107.  
  108. // Previous pointer position. Used to compute deltas.
  109. Windows::UI::Core::CoreCursor^ _defaultCursor;
  110. Windows::UI::Core::CoreCursor^ _cursor;
  111.  
  112. // TODO: Add application specific state here!
  113. };
  114.  
  115. /**
  116. Startup view provider class.
  117. */
  118. ref class FrameworkViewSource sealed : Windows::ApplicationModel::Core::IFrameworkViewSource
  119. {
  120. public:
  121. virtual Windows::ApplicationModel::Core::IFrameworkView^ CreateView() { return ref new AppView(); }
  122. private:
  123. };
  124.  
  125. /**
  126. Application entry point.
  127. */
  128. [Platform::MTAThread]
  129. int main(Platform::Array<Platform::String^>^ args)
  130. {
  131. CoreApplication::Run(ref new FrameworkViewSource());
  132. return 0;
  133. }
  134.  
  135. /**
  136. Initialize the view.
  137. */
  138. void AppView::Initialize(CoreApplicationView^ applicationView)
  139. {
  140. // TODO: Add application specific initialization code here!
  141. applicationView->Activated += ref new TypedEventHandler<CoreApplicationView^, IActivatedEventArgs^>(this, &AppView::OnActivated);
  142. }
  143.  
  144. /**
  145. Associate a CoreWindow with the view.
  146. */
  147. void AppView::SetWindow(CoreWindow^ window)
  148. {
  149. m_window = window;
  150. m_logicalSize = Windows::Foundation::Size(window->Bounds.Width, window->Bounds.Height);
  151. window->SizeChanged += ref new TypedEventHandler<CoreWindow^, WindowSizeChangedEventArgs^>(this, &AppView::OnWindowSizeChanged);
  152. window->VisibilityChanged += ref new TypedEventHandler<CoreWindow^, VisibilityChangedEventArgs^>(this, &AppView::OnVisibilityChanged);
  153. window->Closed += ref new TypedEventHandler<CoreWindow^, CoreWindowEventArgs^>(this, &AppView::OnWindowClosed);
  154. window->PointerPressed += ref new Windows::Foundation::TypedEventHandler<Windows::UI::Core::CoreWindow ^, Windows::UI::Core::PointerEventArgs ^>(this, &AppView::OnPointerPressed);
  155. window->PointerReleased += ref new Windows::Foundation::TypedEventHandler<Windows::UI::Core::CoreWindow ^, Windows::UI::Core::PointerEventArgs ^>(this, &AppView::OnPointerReleased);
  156. window->PointerWheelChanged += ref new Windows::Foundation::TypedEventHandler<Windows::UI::Core::CoreWindow ^, Windows::UI::Core::PointerEventArgs ^>(this, &AppView::OnPointerWheelChanged);
  157.  
  158. Windows::Devices::Input::MouseDevice::GetForCurrentView()->MouseMoved += ref new Windows::Foundation::TypedEventHandler<Windows::Devices::Input::MouseDevice ^, Windows::Devices::Input::MouseEventArgs ^>(this, &AppView::OnMouseMoved);
  159. _defaultCursor = m_window->PointerCursor;
  160. _cursor = _defaultCursor;
  161.  
  162. DisplayInformation^ currentDisplayInformation = DisplayInformation::GetForCurrentView();
  163. m_nativeOrientation = currentDisplayInformation->NativeOrientation;
  164. m_currentOrientation = currentDisplayInformation->CurrentOrientation;
  165. m_dpi = currentDisplayInformation->LogicalDpi;
  166. currentDisplayInformation->DpiChanged += ref new TypedEventHandler<DisplayInformation^, Object^>(this, &AppView::OnDpiChanged);
  167. currentDisplayInformation->OrientationChanged += ref new TypedEventHandler<DisplayInformation^, Object^>(this, &AppView::OnOrientationChanged);
  168. DisplayInformation::DisplayContentsInvalidated += ref new TypedEventHandler<DisplayInformation^, Object^>(this, &AppView::OnDisplayContentsInvalidated);
  169.  
  170. // TODO: Add application specific SetWindow() code here!
  171. }
  172.  
  173. /**
  174. Create the D3D swap chain, etc.
  175. */
  176. void AppView::Load(Platform::String^ entryPoint)
  177. {
  178. CreateDeviceResources();
  179. CreateWindowSizeDependentResources();
  180.  
  181. // TODO: Add application specific Load() code here!
  182. }
  183.  
  184. /**
  185. Run the app.
  186. */
  187. void AppView::Run()
  188. {
  189. while (!m_windowClosed)
  190. {
  191. if (m_windowVisible)
  192. {
  193. CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent);
  194.  
  195. // Reset the viewport to target the whole screen.
  196. m_context->RSSetViewports(1, &m_viewport);
  197.  
  198. // Reset render targets to the screen.
  199. ID3D11RenderTargetView *const targets[1] = { m_renderTargetView.Get() };
  200. m_context->OMSetRenderTargets(1, targets, m_depthStencilView.Get());
  201.  
  202. // Clear the back buffer and depth stencil view.
  203. FLOAT clearColor[] = { 0.25f, 0.15f, 0.5f, 1 };
  204. m_context->ClearRenderTargetView(m_renderTargetView.Get(), clearColor);
  205. m_context->ClearDepthStencilView(m_depthStencilView.Get(), D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0);
  206.  
  207. // Get device rotation.
  208. DXGI_MODE_ROTATION swapChainRotation = DXGI_MODE_ROTATION_IDENTITY;
  209. m_swapChain->GetRotation(&swapChainRotation); // can fail (see docs) but ignore & just use default
  210.  
  211. // TODO: Add application specific Run() code here!
  212. // NOTE: In particular, this is where your rendering call will happen.
  213.  
  214. // Reset mouse look state for next frame.
  215. Windows::UI::Core::CoreWindow::GetForCurrentThread()->PointerCursor = _cursor;
  216. MouseDeltaX = 0.0f;
  217. MouseDeltaY = 0.0f;
  218. MouseDeltaWheel = 0.0f;
  219.  
  220. // The first argument instructs DXGI to block until VSync, putting the application
  221. // to sleep until the next VSync. This ensures we don't waste any cycles rendering
  222. // frames that will never be displayed to the screen.
  223. DXGI_PRESENT_PARAMETERS parameters = { 0 };
  224. HRESULT hrPresent = m_swapChain->Present1(1, 0, &parameters);
  225.  
  226. // Discard the contents of the render target.
  227. // This is a valid operation only when the existing contents will be entirely
  228. // overwritten. If dirty or scroll rects are used, this call should be removed.
  229. m_context->DiscardView1(m_renderTargetView.Get(), nullptr, 0);
  230.  
  231. // Discard the contents of the depth stencil.
  232. m_context->DiscardView1(m_depthStencilView.Get(), nullptr, 0);
  233.  
  234. // If the device was removed either by a disconnection or a driver upgrade, we
  235. // must recreate all device resources.
  236. if (hrPresent == DXGI_ERROR_DEVICE_REMOVED ||
  237. hrPresent == DXGI_ERROR_DEVICE_RESET)
  238. {
  239. HandleDeviceLost();
  240. }
  241. else
  242. {
  243. ChkOk(hrPresent);
  244. }
  245. }
  246. else
  247. {
  248. CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessOneAndAllPending);
  249. }
  250. }
  251. }
  252.  
  253. /**
  254. Uninitialize the view.
  255. */
  256. void AppView::Uninitialize()
  257. {
  258. // nothing!
  259. }
  260.  
  261. /**
  262. Handle app view activation.
  263. */
  264. void AppView::OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args)
  265. {
  266. CoreWindow::GetForCurrentThread()->Activate();
  267. }
  268.  
  269. /**
  270. Handle window size change.
  271. */
  272. void AppView::OnWindowSizeChanged(CoreWindow^ sender, WindowSizeChangedEventArgs^ args)
  273. {
  274. Size logicalSize(sender->Bounds.Width, sender->Bounds.Height);
  275.  
  276. if (m_logicalSize != logicalSize)
  277. {
  278. m_logicalSize = logicalSize;
  279.  
  280. CreateWindowSizeDependentResources();
  281. }
  282. }
  283.  
  284. /**
  285. Handle window visibility change.
  286. */
  287. void AppView::OnVisibilityChanged(CoreWindow^ sender, VisibilityChangedEventArgs^ args)
  288. {
  289. m_windowVisible = args->Visible;
  290. }
  291.  
  292. /**
  293. Handle window close.
  294. */
  295. void AppView::OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args)
  296. {
  297. m_windowClosed = true;
  298. }
  299.  
  300. /**
  301. Handle DPI change.
  302. */
  303. void AppView::OnDpiChanged(DisplayInformation^ sender, Object^ args)
  304. {
  305. if (sender->LogicalDpi != m_dpi)
  306. {
  307. m_dpi = sender->LogicalDpi;
  308.  
  309. // When the display DPI changes, the logical size of the window
  310. // (measured in Dips) also changes and needs to be updated.
  311.  
  312. m_logicalSize = Windows::Foundation::Size(m_window->Bounds.Width, m_window->Bounds.Height);
  313.  
  314. CreateWindowSizeDependentResources();
  315. }
  316. }
  317.  
  318. /**
  319. Handle orientation change.
  320. */
  321. void AppView::OnOrientationChanged(DisplayInformation^ sender, Object^ args)
  322. {
  323. if (m_currentOrientation != sender->CurrentOrientation)
  324. {
  325. m_currentOrientation = sender->CurrentOrientation;
  326.  
  327. CreateWindowSizeDependentResources();
  328. }
  329. }
  330.  
  331. /**
  332. */
  333. void AppView::OnDisplayContentsInvalidated(DisplayInformation^ sender, Object^ args)
  334. {
  335. // The D3D Device is no longer valid if the default adapter changed
  336. // since the device was created or if the device has been removed.
  337.  
  338. // First, get the information for the default adapter from when the
  339. // device was created.
  340.  
  341. ComPtr<IDXGIDevice3> dxgiDevice;
  342. ChkOk(m_device.As(&dxgiDevice));
  343. ComPtr<IDXGIAdapter> deviceAdapter;
  344. ChkOk(dxgiDevice->GetAdapter(&deviceAdapter));
  345. ComPtr<IDXGIFactory4> deviceFactory;
  346. ChkOk(deviceAdapter->GetParent(IID_PPV_ARGS(&deviceFactory)));
  347. ComPtr<IDXGIAdapter1> previousDefaultAdapter;
  348. ChkOk(deviceFactory->EnumAdapters1(0, &previousDefaultAdapter));
  349. DXGI_ADAPTER_DESC1 previousDesc;
  350. ChkOk(previousDefaultAdapter->GetDesc1(&previousDesc));
  351.  
  352. // Next, get the information for the current default adapter.
  353.  
  354. ComPtr<IDXGIFactory4> currentFactory;
  355. ChkOk(CreateDXGIFactory1(IID_PPV_ARGS(&currentFactory)));
  356. ComPtr<IDXGIAdapter1> currentDefaultAdapter;
  357. ChkOk(currentFactory->EnumAdapters1(0, &currentDefaultAdapter));
  358. DXGI_ADAPTER_DESC1 currentDesc;
  359. ChkOk(currentDefaultAdapter->GetDesc1(&currentDesc));
  360.  
  361. // If the adapter LUIDs don't match, or if the device reports
  362. // that it has been removed, a new D3D device must be created.
  363.  
  364. if (previousDesc.AdapterLuid.LowPart != currentDesc.AdapterLuid.LowPart ||
  365. previousDesc.AdapterLuid.HighPart != currentDesc.AdapterLuid.HighPart ||
  366. FAILED(m_device->GetDeviceRemovedReason()))
  367. {
  368. // Release references to resources related to the old device.
  369. dxgiDevice = nullptr;
  370. deviceAdapter = nullptr;
  371. deviceFactory = nullptr;
  372. previousDefaultAdapter = nullptr;
  373.  
  374. // Create a new device and swap chain.
  375. HandleDeviceLost();
  376. }
  377. }
  378.  
  379. /**
  380. Create the Direct3D device.
  381. */
  382. void AppView::CreateDeviceResources()
  383. {
  384. UINT creationFlags = 0;
  385.  
  386. #if defined(_DEBUG)
  387.  
  388. HRESULT hrSdkLayersCheck = D3D11CreateDevice(
  389. nullptr,
  390. D3D_DRIVER_TYPE_NULL, // There is no need to create a real hardware device.
  391. 0,
  392. D3D11_CREATE_DEVICE_DEBUG, // Check for the SDK layers.
  393. nullptr, // Any feature level will do.
  394. 0,
  395. D3D11_SDK_VERSION, // Always set this to D3D11_SDK_VERSION for Windows Store apps.
  396. nullptr, // No need to keep the D3D device reference.
  397. nullptr, // No need to know the feature level.
  398. nullptr // No need to keep the D3D device context reference.
  399. );
  400.  
  401. if (SUCCEEDED(hrSdkLayersCheck))
  402. {
  403. // If the project is in a debug build, enable debugging via SDK Layers with this flag.
  404. creationFlags |= D3D11_CREATE_DEVICE_DEBUG;
  405. }
  406.  
  407. #endif
  408.  
  409. // This array defines the set of DirectX hardware feature levels this app will support.
  410. // Note the ordering should be preserved.
  411. // Don't forget to declare your application's minimum required feature level in its
  412. // description. All applications are assumed to support 9.1 unless otherwise stated.
  413. static const D3D_FEATURE_LEVEL featureLevels[] =
  414. {
  415. D3D_FEATURE_LEVEL_12_1,
  416. D3D_FEATURE_LEVEL_12_0,
  417. D3D_FEATURE_LEVEL_11_1,
  418. D3D_FEATURE_LEVEL_11_0,
  419. D3D_FEATURE_LEVEL_10_1,
  420. D3D_FEATURE_LEVEL_10_0,
  421. D3D_FEATURE_LEVEL_9_3,
  422. D3D_FEATURE_LEVEL_9_2,
  423. D3D_FEATURE_LEVEL_9_1
  424. };
  425.  
  426. // Create the Direct3D 11 API device object and a corresponding context.
  427. ComPtr<ID3D11Device> device;
  428. ComPtr<ID3D11DeviceContext> context;
  429.  
  430. HRESULT hr = D3D11CreateDevice(
  431. nullptr, // Specify nullptr to use the default adapter.
  432. D3D_DRIVER_TYPE_HARDWARE, // Create a device using the hardware graphics driver.
  433. 0, // Should be 0 unless the driver is D3D_DRIVER_TYPE_SOFTWARE.
  434. creationFlags, // Set debug and Direct2D compatibility flags.
  435. featureLevels, // List of feature levels this app can support.
  436. ARRAYSIZE(featureLevels), // Size of the list above.
  437. D3D11_SDK_VERSION, // Always set this to D3D11_SDK_VERSION for Windows Store apps.
  438. &device, // Returns the Direct3D device created.
  439. &m_featureLevel, // Returns feature level of device created.
  440. &context // Returns the device immediate context.
  441. );
  442.  
  443. if (FAILED(hr))
  444. {
  445. // Initialization failed, fall back to the WARP device.
  446. ChkOk(
  447. D3D11CreateDevice(
  448. nullptr,
  449. D3D_DRIVER_TYPE_WARP,
  450. 0,
  451. creationFlags,
  452. featureLevels,
  453. ARRAYSIZE(featureLevels),
  454. D3D11_SDK_VERSION,
  455. &device,
  456. &m_featureLevel,
  457. &context));
  458. }
  459.  
  460. // Store pointers to the Direct3D 11.3 API device and immediate context.
  461. ChkOk(device.As(&m_device));
  462. ChkOk(context.As(&m_context));
  463.  
  464. // Create the Direct2D device object and a corresponding context.
  465. ComPtr<IDXGIDevice3> dxgiDevice;
  466. ChkOk(m_device.As(&dxgiDevice));
  467. }
  468.  
  469. /**
  470. This method determines the rotation between the display device's native
  471. orientation and the current display orientation.
  472. */
  473. DXGI_MODE_ROTATION AppView::ComputeDisplayRotation()
  474. {
  475. // Note: m_nativeOrientation can only be Landscape or Portrait even though
  476. // the DisplayOrientations enum has other values.
  477.  
  478. switch (m_nativeOrientation)
  479. {
  480. case DisplayOrientations::Landscape:
  481. {
  482. switch (m_currentOrientation)
  483. {
  484. case DisplayOrientations::Landscape: return DXGI_MODE_ROTATION_IDENTITY;
  485. case DisplayOrientations::Portrait: return DXGI_MODE_ROTATION_ROTATE270;
  486. case DisplayOrientations::LandscapeFlipped: return DXGI_MODE_ROTATION_ROTATE180;
  487. case DisplayOrientations::PortraitFlipped: return DXGI_MODE_ROTATION_ROTATE90;
  488. }
  489. }
  490. break;
  491.  
  492. case DisplayOrientations::Portrait:
  493. {
  494. switch (m_currentOrientation)
  495. {
  496. case DisplayOrientations::Landscape: return DXGI_MODE_ROTATION_ROTATE90;
  497. case DisplayOrientations::Portrait: return DXGI_MODE_ROTATION_IDENTITY;
  498. case DisplayOrientations::LandscapeFlipped: return DXGI_MODE_ROTATION_ROTATE270;
  499. case DisplayOrientations::PortraitFlipped: return DXGI_MODE_ROTATION_ROTATE180;
  500. }
  501. }
  502. break;
  503. }
  504.  
  505. return DXGI_MODE_ROTATION_UNSPECIFIED;
  506. }
  507.  
  508. /**
  509. Converts a length in device-independent pixels to a length in physical pixels.
  510. */
  511. float AppView::ConvertDipsToPixels(float dips)
  512. {
  513. static const float dipsPerInch = 96.0f;
  514. return floorf(dips * m_dpi / dipsPerInch + 0.5f); // Round to nearest integer.
  515. }
  516.  
  517. /**
  518. These resources need to be recreated every time the window size is changed.
  519. */
  520. void AppView::CreateWindowSizeDependentResources()
  521. {
  522. // Clear the previous window size specific context.
  523. ID3D11RenderTargetView* nullViews[] = { nullptr };
  524. m_context->OMSetRenderTargets(ARRAYSIZE(nullViews), nullViews, nullptr);
  525. m_renderTargetView = nullptr;
  526. m_depthStencilView = nullptr;
  527. m_context->Flush1(D3D11_CONTEXT_TYPE_ALL, nullptr);
  528.  
  529. // Calculate the necessary render target size in pixels.
  530. // The std::max calls make sure we don't pass zero to D3D.
  531. m_outputSize.Width = (std::max)(1.0f, ConvertDipsToPixels(m_logicalSize.Width));
  532. m_outputSize.Height = (std::max)(1.0f, ConvertDipsToPixels(m_logicalSize.Height));
  533.  
  534. // The width and height of the swap chain must be based on the window's
  535. // natively-oriented width and height. If the window is not in the native
  536. // orientation, the dimensions must be reversed.
  537. DXGI_MODE_ROTATION displayRotation = ComputeDisplayRotation();
  538. bool swapDimensions = displayRotation == DXGI_MODE_ROTATION_ROTATE90 || displayRotation == DXGI_MODE_ROTATION_ROTATE270;
  539. m_renderTargetSize.Width = swapDimensions ? m_outputSize.Height : m_outputSize.Width;
  540. m_renderTargetSize.Height = swapDimensions ? m_outputSize.Width : m_outputSize.Height;
  541.  
  542. if (m_swapChain != nullptr)
  543. {
  544. // The swap chain already exists, resize it.
  545. HRESULT hr = m_swapChain->ResizeBuffers(
  546. 2, // Double-buffered swap chain.
  547. lround(m_renderTargetSize.Width),
  548. lround(m_renderTargetSize.Height),
  549. DXGI_FORMAT_B8G8R8A8_UNORM,
  550. 0);
  551.  
  552. if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET)
  553. {
  554. // If the device was removed for any reason, a new device
  555. // and swap chain will need to be created.
  556. HandleDeviceLost();
  557.  
  558. // Everything is set up now. Do not continue execution of this
  559. // method. HandleDeviceLost will reenter this method and correctly
  560. // set up the new device.
  561. return;
  562. }
  563. else
  564. {
  565. ChkOk(hr);
  566. }
  567. }
  568. else
  569. {
  570. // Create a new swap chain using the same adapter as the existing device.
  571. DXGI_SWAP_CHAIN_DESC1 swapChainDesc = { 0 };
  572. swapChainDesc.Width = lround(m_renderTargetSize.Width); // Match the size of the window.
  573. swapChainDesc.Height = lround(m_renderTargetSize.Height);
  574. swapChainDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; // This is the most common swap chain format.
  575. swapChainDesc.Stereo = FALSE;
  576. swapChainDesc.SampleDesc.Count = 1; // Don't use multi-sampling.
  577. swapChainDesc.SampleDesc.Quality = 0;
  578. swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
  579. swapChainDesc.BufferCount = 2; // Use double-buffering to minimize latency.
  580. swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; // All Windows Store apps must use this SwapEffect.
  581. swapChainDesc.Flags = 0;
  582. swapChainDesc.Scaling = DXGI_SCALING_STRETCH;
  583. swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE;
  584.  
  585. // This sequence obtains the DXGI factory that was used to create the Direct3D device above.
  586. ComPtr<IDXGIDevice3> dxgiDevice;
  587. ChkOk(m_device.As(&dxgiDevice));
  588. ComPtr<IDXGIAdapter> dxgiAdapter;
  589. ChkOk(dxgiDevice->GetAdapter(&dxgiAdapter));
  590. ComPtr<IDXGIFactory4> dxgiFactory;
  591. ChkOk(dxgiAdapter->GetParent(IID_PPV_ARGS(&dxgiFactory)));
  592.  
  593. ComPtr<IDXGISwapChain1> swapChain;
  594. ChkOk(
  595. dxgiFactory->CreateSwapChainForCoreWindow(
  596. m_device.Get(),
  597. reinterpret_cast<IUnknown*>(m_window.Get()),
  598. &swapChainDesc,
  599. nullptr,
  600. &swapChain));
  601. ChkOk(swapChain.As(&m_swapChain));
  602.  
  603. // Ensure that DXGI does not queue more than one frame at a time. This both reduces latency and
  604. // ensures that the application will only render after each VSync, minimizing power consumption.
  605. ChkOk(dxgiDevice->SetMaximumFrameLatency(1));
  606. }
  607.  
  608. // Set the proper orientation for the swap chain and
  609. // the transform for rendering to the rotated swap chain.
  610.  
  611. ChkOk(m_swapChain->SetRotation(displayRotation));
  612.  
  613. // 0-degree Z-rotation
  614. static const XMFLOAT4X4 Rotation0(
  615. 1.0f, 0.0f, 0.0f, 0.0f,
  616. 0.0f, 1.0f, 0.0f, 0.0f,
  617. 0.0f, 0.0f, 1.0f, 0.0f,
  618. 0.0f, 0.0f, 0.0f, 1.0f);
  619.  
  620. // 90-degree Z-rotation
  621. static const XMFLOAT4X4 Rotation90(
  622. 0.0f, 1.0f, 0.0f, 0.0f,
  623. -1.0f, 0.0f, 0.0f, 0.0f,
  624. 0.0f, 0.0f, 1.0f, 0.0f,
  625. 0.0f, 0.0f, 0.0f, 1.0f);
  626.  
  627. // 180-degree Z-rotation
  628. static const XMFLOAT4X4 Rotation180(
  629. -1.0f, 0.0f, 0.0f, 0.0f,
  630. 0.0f, -1.0f, 0.0f, 0.0f,
  631. 0.0f, 0.0f, 1.0f, 0.0f,
  632. 0.0f, 0.0f, 0.0f, 1.0f);
  633.  
  634. // 270-degree Z-rotation
  635. static const XMFLOAT4X4 Rotation270(
  636. 0.0f, -1.0f, 0.0f, 0.0f,
  637. 1.0f, 0.0f, 0.0f, 0.0f,
  638. 0.0f, 0.0f, 1.0f, 0.0f,
  639. 0.0f, 0.0f, 0.0f, 1.0f);
  640.  
  641. switch (displayRotation)
  642. {
  643. case DXGI_MODE_ROTATION_IDENTITY: m_orientationTransform = Rotation0; break;
  644. case DXGI_MODE_ROTATION_ROTATE90: m_orientationTransform = Rotation270; break;
  645. case DXGI_MODE_ROTATION_ROTATE180: m_orientationTransform = Rotation180; break;
  646. case DXGI_MODE_ROTATION_ROTATE270: m_orientationTransform = Rotation90; break;
  647. default: ChkTrue(false);
  648. }
  649.  
  650. // Create a render target view of the swap chain back buffer.
  651. ComPtr<ID3D11Texture2D1> backBuffer;
  652. ChkOk(m_swapChain->GetBuffer(0, IID_PPV_ARGS(&backBuffer)));
  653. ChkOk(m_device->CreateRenderTargetView1(backBuffer.Get(), nullptr, &m_renderTargetView));
  654.  
  655. // Create a depth stencil view for use with 3D rendering if needed.
  656. CD3D11_TEXTURE2D_DESC1 depthStencilDesc(
  657. DXGI_FORMAT_D24_UNORM_S8_UINT,
  658. lround(m_renderTargetSize.Width),
  659. lround(m_renderTargetSize.Height),
  660. 1, // This depth stencil view has only one texture.
  661. 1, // Use a single mipmap level.
  662. D3D11_BIND_DEPTH_STENCIL);
  663.  
  664. ComPtr<ID3D11Texture2D1> depthStencil;
  665. ChkOk(m_device->CreateTexture2D1(&depthStencilDesc, nullptr, &depthStencil));
  666.  
  667. CD3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc(D3D11_DSV_DIMENSION_TEXTURE2D);
  668. ChkOk(m_device->CreateDepthStencilView(depthStencil.Get(), &depthStencilViewDesc, &m_depthStencilView));
  669.  
  670. // Set the 3D rendering viewport to target the entire window.
  671. m_viewport = CD3D11_VIEWPORT(0.0f, 0.0f, m_renderTargetSize.Width, m_renderTargetSize.Height);
  672. m_context->RSSetViewports(1, &m_viewport);
  673.  
  674. // TODO: Add application specific device resource creation here!
  675. }
  676.  
  677. /**
  678. Recreate all device resources and set them back to the current state.
  679. */
  680. void AppView::HandleDeviceLost()
  681. {
  682. m_swapChain = nullptr;
  683. CreateDeviceResources();
  684. CreateWindowSizeDependentResources();
  685. }
  686.  
  687. /**
  688. */
  689. void AppView::OnPointerPressed(Windows::UI::Core::CoreWindow ^sender, Windows::UI::Core::PointerEventArgs ^args)
  690. {
  691. // NOTE: If implementing ImGui wrap this in the following condition
  692. // if (!ImGui::GetIO().WantCaptureMouse) { ... }
  693. // to prevent our mouse look behavior when an ImGui control has
  694. // captured the pointer.
  695.  
  696. // This assumes we're implementing some kind of "mouse look" functionality,
  697. // i.e. if the pointer is pressed we're dragging the view direction around.
  698. // By settings _cursor to nullptr we will hide the mouse pointer (see the
  699. // AppView::Run method) and trigger calculation of mouse pointer deltas in
  700. // the AppView::OnMouseMoved method.
  701.  
  702. UpdatePointerButtons(args);
  703. _cursor = nullptr;
  704. }
  705.  
  706. /**
  707. */
  708. void AppView::OnPointerReleased(Windows::UI::Core::CoreWindow ^sender, Windows::UI::Core::PointerEventArgs ^args)
  709. {
  710. UpdatePointerButtons(args);
  711. _cursor = _defaultCursor;
  712. }
  713.  
  714. /**
  715. */
  716. void AppView::OnMouseMoved(Windows::Devices::Input::MouseDevice ^sender, Windows::Devices::Input::MouseEventArgs ^args)
  717. {
  718. if (_cursor == nullptr)
  719. {
  720. float dx = float(args->MouseDelta.X) / MOUSE_SCALE;
  721. float dy = float(args->MouseDelta.Y) / MOUSE_SCALE;
  722. MouseDeltaX = (std::max)(-1.0f, (std::min)(+1.0f, dx));
  723. MouseDeltaY = (std::max)(-1.0f, (std::min)(+1.0f, dy));
  724. }
  725. }
  726.  
  727. /**
  728. */
  729. void AppView::OnPointerWheelChanged(Windows::UI::Core::CoreWindow ^sender, Windows::UI::Core::PointerEventArgs ^args)
  730. {
  731. auto d = args->CurrentPoint->Properties->MouseWheelDelta;
  732. auto nd = float(d) / float(WHEEL_DELTA * MOUSE_SCALE);
  733. MouseDeltaWheel = (std::max)(-1.0f, (std::min)(+1.0f, nd));
  734. }
  735.  
  736. /**
  737. */
  738. void AppView::UpdatePointerButtons(Windows::UI::Core::PointerEventArgs^ args)
  739. {
  740. auto device = args->CurrentPoint->PointerDevice;
  741.  
  742. if (device->PointerDeviceType == Windows::Devices::Input::PointerDeviceType::Mouse)
  743. {
  744. auto properties = args->CurrentPoint->Properties;
  745. MouseButtonL = properties->IsLeftButtonPressed;
  746. MouseButtonM = properties->IsMiddleButtonPressed;
  747. MouseButtonR = properties->IsRightButtonPressed;
  748. }
  749. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement