App.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435
  1. #include "App.h"
  2. #include <ppltasks.h>
  3. using namespace TemplateApp;
  4. using namespace concurrency;
  5. using namespace Windows::ApplicationModel;
  6. using namespace Windows::ApplicationModel::Core;
  7. using namespace Windows::ApplicationModel::Activation;
  8. using namespace Windows::Foundation::Collections;
  9. using namespace Windows::System::Threading;
  10. using namespace Windows::UI::Core;
  11. using namespace Windows::UI::Input;
  12. using namespace Windows::System;
  13. using namespace Windows::Storage;
  14. using namespace Windows::Foundation;
  15. using namespace Windows::Graphics::Display;
  16. using namespace Platform;
  17. // The main function is only used to initialize our IFrameworkView class.
  18. [Platform::MTAThread]
  19. int main(Platform::Array<Platform::String^>^)
  20. {
  21. auto direct3DApplicationSource = ref new Direct3DApplicationSource();
  22. CoreApplication::Run(direct3DApplicationSource);
  23. return 0;
  24. }
  25. IFrameworkView^ Direct3DApplicationSource::CreateView()
  26. {
  27. return ref new App();
  28. }
  29. App::App() :
  30. m_windowClosed(false),
  31. m_windowVisible(true)
  32. {
  33. }
  34. // The first method called when the IFrameworkView is being created.
  35. void App::Initialize(CoreApplicationView^ applicationView)
  36. {
  37. // Register event handlers for app lifecycle. This example includes Activated, so that we
  38. // can make the CoreWindow active and start rendering on the window.
  39. applicationView->Activated +=
  40. ref new TypedEventHandler<CoreApplicationView^, IActivatedEventArgs^>(this, &App::OnActivated);
  41. CoreApplication::Suspending +=
  42. ref new Windows::Foundation::EventHandler<SuspendingEventArgs^>(this, &App::OnSuspending);
  43. CoreApplication::Resuming +=
  44. ref new Windows::Foundation::EventHandler<Platform::Object^>(this, &App::OnResuming);
  45. }
  46. void App::OnPointerPressed(CoreWindow^ sender, PointerEventArgs^ args)
  47. {
  48. PointerPoint^ currentPoint = args->CurrentPoint;
  49. Polycode::UWPEvent touchEvent;
  50. if (currentPoint->PointerDevice->PointerDeviceType == Windows::Devices::Input::PointerDeviceType::Touch) {
  51. touchEvent.eventCode = Polycode::InputEvent::EVENT_MOUSEDOWN;
  52. touchEvent.mouseX = currentPoint->Position.X;
  53. touchEvent.mouseY = currentPoint->Position.Y;
  54. if (currentPoint->Properties->IsLeftButtonPressed) {
  55. touchEvent.mouseButton = 0;
  56. }
  57. else if (currentPoint->Properties->IsMiddleButtonPressed) {
  58. touchEvent.mouseButton = 1;
  59. } else {
  60. touchEvent.mouseButton = 2;
  61. }
  62. }
  63. else {
  64. touchEvent.eventCode = Polycode::InputEvent::EVENT_TOUCHES_BEGAN;
  65. touchEvent.touch.position = Vector2(currentPoint->Position.X, currentPoint->Position.Y);
  66. touchEvent.touch.id = currentPoint->PointerId;
  67. if (currentPoint->PointerDevice->PointerDeviceType == Windows::Devices::Input::PointerDeviceType::Touch) {
  68. touchEvent.touch.type = TouchInfo::TYPE_TOUCH;
  69. }
  70. else if (currentPoint->PointerDevice->PointerDeviceType == Windows::Devices::Input::PointerDeviceType::Pen) {
  71. touchEvent.touch.type = TouchInfo::TYPE_PEN;
  72. }
  73. }
  74. }
  75. void App::OnPointerMoved(CoreWindow^ sender, PointerEventArgs^ args)
  76. {
  77. // Get the intermediate points and process them in your gestureRecognizer
  78. IVector<PointerPoint^>^ pointerPoints = PointerPoint::GetIntermediatePoints(args->CurrentPoint->PointerId);
  79. }
  80. void App::OnPointerReleased(CoreWindow^ sender, PointerEventArgs^ args)
  81. {
  82. // Get the current point and process it in your gestureRecognizer
  83. PointerPoint^ pointerPoint = args->CurrentPoint;
  84. PointerPoint^ currentPoint = args->CurrentPoint;
  85. Polycode::UWPEvent touchEvent;
  86. if (currentPoint->PointerDevice->PointerDeviceType == Windows::Devices::Input::PointerDeviceType::Touch) {
  87. touchEvent.eventCode = Polycode::InputEvent::EVENT_MOUSEUP;
  88. touchEvent.mouseX = currentPoint->Position.X;
  89. touchEvent.mouseY = currentPoint->Position.Y;
  90. if (currentPoint->Properties->IsLeftButtonPressed) {
  91. touchEvent.mouseButton = 0;
  92. }
  93. else if (currentPoint->Properties->IsMiddleButtonPressed) {
  94. touchEvent.mouseButton = 1;
  95. }
  96. else {
  97. touchEvent.mouseButton = 2;
  98. }
  99. }
  100. else {
  101. touchEvent.eventCode = Polycode::InputEvent::EVENT_TOUCHES_ENDED;
  102. touchEvent.touch.position = Vector2(currentPoint->Position.X, currentPoint->Position.Y);
  103. touchEvent.touch.id = currentPoint->PointerId;
  104. if (currentPoint->PointerDevice->PointerDeviceType == Windows::Devices::Input::PointerDeviceType::Touch) {
  105. touchEvent.touch.type = TouchInfo::TYPE_TOUCH;
  106. }
  107. else if (currentPoint->PointerDevice->PointerDeviceType == Windows::Devices::Input::PointerDeviceType::Pen) {
  108. touchEvent.touch.type = TouchInfo::TYPE_PEN;
  109. }
  110. }
  111. }
  112. // Called when the CoreWindow object is created (or re-created).
  113. void App::SetWindow(CoreWindow^ window)
  114. {
  115. window->SizeChanged +=
  116. ref new TypedEventHandler<CoreWindow^, WindowSizeChangedEventArgs^>(this, &App::OnWindowSizeChanged);
  117. window->VisibilityChanged +=
  118. ref new TypedEventHandler<CoreWindow^, VisibilityChangedEventArgs^>(this, &App::OnVisibilityChanged);
  119. window->Closed +=
  120. ref new TypedEventHandler<CoreWindow^, CoreWindowEventArgs^>(this, &App::OnWindowClosed);
  121. window->PointerPressed +=
  122. ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &App::OnPointerPressed);
  123. window->PointerMoved +=
  124. ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &App::OnPointerMoved);
  125. window->PointerReleased +=
  126. ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &App::OnPointerReleased);
  127. DisplayInformation^ currentDisplayInformation = DisplayInformation::GetForCurrentView();
  128. currentDisplayInformation->DpiChanged +=
  129. ref new TypedEventHandler<DisplayInformation^, Object^>(this, &App::OnDpiChanged);
  130. currentDisplayInformation->OrientationChanged +=
  131. ref new TypedEventHandler<DisplayInformation^, Object^>(this, &App::OnOrientationChanged);
  132. DisplayInformation::DisplayContentsInvalidated +=
  133. ref new TypedEventHandler<DisplayInformation^, Object^>(this, &App::OnDisplayContentsInvalidated);
  134. PolycodeView *view = new PolycodeView();
  135. view->window = reinterpret_cast<IUnknown*>(window);
  136. const EGLint configAttributes[] =
  137. {
  138. EGL_RED_SIZE, 8,
  139. EGL_GREEN_SIZE, 8,
  140. EGL_BLUE_SIZE, 8,
  141. EGL_ALPHA_SIZE, 8,
  142. EGL_DEPTH_SIZE, 8,
  143. EGL_STENCIL_SIZE, 8,
  144. EGL_NONE
  145. };
  146. const EGLint contextAttributes[] =
  147. {
  148. EGL_CONTEXT_CLIENT_VERSION, 2,
  149. EGL_NONE
  150. };
  151. const EGLint surfaceAttributes[] =
  152. {
  153. // EGL_ANGLE_SURFACE_RENDER_TO_BACK_BUFFER is part of the same optimization as EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER (see above).
  154. // If you have compilation issues with it then please update your Visual Studio templates.
  155. EGL_ANGLE_SURFACE_RENDER_TO_BACK_BUFFER, EGL_TRUE,
  156. EGL_NONE
  157. };
  158. const EGLint defaultDisplayAttributes[] =
  159. {
  160. // These are the default display attributes, used to request ANGLE's D3D11 renderer.
  161. // eglInitialize will only succeed with these attributes if the hardware supports D3D11 Feature Level 10_0+.
  162. EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
  163. // EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER is an optimization that can have large performance benefits on mobile devices.
  164. // Its syntax is subject to change, though. Please update your Visual Studio templates if you experience compilation issues with it.
  165. EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER, EGL_TRUE,
  166. // EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE is an option that enables ANGLE to automatically call
  167. // the IDXGIDevice3::Trim method on behalf of the application when it gets suspended.
  168. // Calling IDXGIDevice3::Trim when an application is suspended is a Windows Store application certification requirement.
  169. EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE, EGL_TRUE,
  170. EGL_NONE,
  171. };
  172. const EGLint fl9_3DisplayAttributes[] =
  173. {
  174. // These can be used to request ANGLE's D3D11 renderer, with D3D11 Feature Level 9_3.
  175. // These attributes are used if the call to eglInitialize fails with the default display attributes.
  176. EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
  177. EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, 9,
  178. EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, 3,
  179. EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER, EGL_TRUE,
  180. EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE, EGL_TRUE,
  181. EGL_NONE,
  182. };
  183. const EGLint warpDisplayAttributes[] =
  184. {
  185. // These attributes can be used to request D3D11 WARP.
  186. // They are used if eglInitialize fails with both the default display attributes and the 9_3 display attributes.
  187. EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
  188. EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE,
  189. EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER, EGL_TRUE,
  190. EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE, EGL_TRUE,
  191. EGL_NONE,
  192. };
  193. EGLConfig config = NULL;
  194. // eglGetPlatformDisplayEXT is an alternative to eglGetDisplay. It allows us to pass in display attributes, used to configure D3D11.
  195. PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT = reinterpret_cast<PFNEGLGETPLATFORMDISPLAYEXTPROC>(eglGetProcAddress("eglGetPlatformDisplayEXT"));
  196. if (!eglGetPlatformDisplayEXT)
  197. {
  198. throw Exception::CreateException(E_FAIL, L"Failed to get function eglGetPlatformDisplayEXT");
  199. }
  200. //
  201. // To initialize the display, we make three sets of calls to eglGetPlatformDisplayEXT and eglInitialize, with varying
  202. // parameters passed to eglGetPlatformDisplayEXT:
  203. // 1) The first calls uses "defaultDisplayAttributes" as a parameter. This corresponds to D3D11 Feature Level 10_0+.
  204. // 2) If eglInitialize fails for step 1 (e.g. because 10_0+ isn't supported by the default GPU), then we try again
  205. // using "fl9_3DisplayAttributes". This corresponds to D3D11 Feature Level 9_3.
  206. // 3) If eglInitialize fails for step 2 (e.g. because 9_3+ isn't supported by the default GPU), then we try again
  207. // using "warpDisplayAttributes". This corresponds to D3D11 Feature Level 11_0 on WARP, a D3D11 software rasterizer.
  208. //
  209. // This tries to initialize EGL to D3D11 Feature Level 10_0+. See above comment for details.
  210. mEglDisplay = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY, defaultDisplayAttributes);
  211. if (mEglDisplay == EGL_NO_DISPLAY)
  212. {
  213. throw Exception::CreateException(E_FAIL, L"Failed to get EGL display");
  214. }
  215. if (eglInitialize(mEglDisplay, NULL, NULL) == EGL_FALSE)
  216. {
  217. // This tries to initialize EGL to D3D11 Feature Level 9_3, if 10_0+ is unavailable (e.g. on some mobile devices).
  218. mEglDisplay = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY, fl9_3DisplayAttributes);
  219. if (mEglDisplay == EGL_NO_DISPLAY)
  220. {
  221. throw Exception::CreateException(E_FAIL, L"Failed to get EGL display");
  222. }
  223. if (eglInitialize(mEglDisplay, NULL, NULL) == EGL_FALSE)
  224. {
  225. // This initializes EGL to D3D11 Feature Level 11_0 on WARP, if 9_3+ is unavailable on the default GPU.
  226. mEglDisplay = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY, warpDisplayAttributes);
  227. if (mEglDisplay == EGL_NO_DISPLAY)
  228. {
  229. throw Exception::CreateException(E_FAIL, L"Failed to get EGL display");
  230. }
  231. if (eglInitialize(mEglDisplay, NULL, NULL) == EGL_FALSE)
  232. {
  233. // If all of the calls to eglInitialize returned EGL_FALSE then an error has occurred.
  234. throw Exception::CreateException(E_FAIL, L"Failed to initialize EGL");
  235. }
  236. }
  237. }
  238. EGLint numConfigs = 0;
  239. if ((eglChooseConfig(mEglDisplay, configAttributes, &config, 1, &numConfigs) == EGL_FALSE) || (numConfigs == 0))
  240. {
  241. throw Exception::CreateException(E_FAIL, L"Failed to choose first EGLConfig");
  242. }
  243. // Create a PropertySet and initialize with the EGLNativeWindowType.
  244. PropertySet^ surfaceCreationProperties = ref new PropertySet();
  245. surfaceCreationProperties->Insert(ref new Platform::String(EGLNativeWindowTypeProperty), window);
  246. // You can configure the surface to render at a lower resolution and be scaled up to
  247. // the full window size. This scaling is often free on mobile hardware.
  248. //
  249. // One way to configure the SwapChainPanel is to specify precisely which resolution it should render at.
  250. // Size customRenderSurfaceSize = Size(800, 600);
  251. // surfaceCreationProperties->Insert(ref new String(EGLRenderSurfaceSizeProperty), PropertyValue::CreateSize(customRenderSurfaceSize));
  252. //
  253. // Another way is to tell the SwapChainPanel to render at a certain scale factor compared to its size.
  254. // e.g. if the SwapChainPanel is 1920x1280 then setting a factor of 0.5f will make the app render at 960x640
  255. // float customResolutionScale = 0.5f;
  256. // surfaceCreationProperties->Insert(ref new String(EGLRenderResolutionScaleProperty), PropertyValue::CreateSingle(customResolutionScale));
  257. mEglSurface = eglCreateWindowSurface(mEglDisplay, config, reinterpret_cast<IInspectable*>(surfaceCreationProperties), surfaceAttributes);
  258. if (mEglSurface == EGL_NO_SURFACE)
  259. {
  260. throw Exception::CreateException(E_FAIL, L"Failed to create EGL fullscreen surface");
  261. }
  262. mEglContext = eglCreateContext(mEglDisplay, config, EGL_NO_CONTEXT, contextAttributes);
  263. if (mEglContext == EGL_NO_CONTEXT)
  264. {
  265. throw Exception::CreateException(E_FAIL, L"Failed to create EGL context");
  266. }
  267. /*
  268. surfaceCreationProperties = ref new PropertySet();
  269. surfaceCreationProperties->Insert(ref new Platform::String(EGLNativeWindowTypeProperty), window);
  270. view->eglWindow = reinterpret_cast<IInspectable*>(surfaceCreationProperties);
  271. */
  272. view->mEglContext = mEglContext;
  273. view->mEglDisplay = mEglDisplay;
  274. view->mEglSurface = mEglSurface;
  275. app = new PolycodeTemplateApp(view);
  276. core = app->getCore();
  277. }
  278. // Initializes scene resources, or loads a previously saved app state.
  279. void App::Load(Platform::String^ entryPoint)
  280. {
  281. }
  282. // This method is called after the window becomes active.
  283. void App::Run()
  284. {
  285. while (!m_windowClosed)
  286. {
  287. if (m_windowVisible)
  288. {
  289. CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent);
  290. }
  291. else
  292. {
  293. CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessOneAndAllPending);
  294. }
  295. EGLint panelWidth = 0;
  296. EGLint panelHeight = 0;
  297. eglQuerySurface(mEglDisplay, mEglSurface, EGL_WIDTH, &panelWidth);
  298. eglQuerySurface(mEglDisplay, mEglSurface, EGL_HEIGHT, &panelHeight);
  299. if (panelWidth != lastPanelWidth || panelHeight != lastPanelHeight) {
  300. core->resizeTo(panelWidth, panelHeight);
  301. }
  302. lastPanelWidth = panelWidth;
  303. lastPanelHeight = panelHeight;
  304. app->Update();
  305. }
  306. }
  307. // Required for IFrameworkView.
  308. // Terminate events do not cause Uninitialize to be called. It will be called if your IFrameworkView
  309. // class is torn down while the app is in the foreground.
  310. void App::Uninitialize()
  311. {
  312. }
  313. // Application lifecycle event handlers.
  314. void App::OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args)
  315. {
  316. // Run() won't start until the CoreWindow is activated.
  317. CoreWindow::GetForCurrentThread()->Activate();
  318. }
  319. void App::OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args)
  320. {
  321. }
  322. void App::OnResuming(Platform::Object^ sender, Platform::Object^ args)
  323. {
  324. }
  325. // Window event handlers.
  326. void App::OnWindowSizeChanged(CoreWindow^ sender, WindowSizeChangedEventArgs^ args)
  327. {
  328. }
  329. void App::OnVisibilityChanged(CoreWindow^ sender, VisibilityChangedEventArgs^ args)
  330. {
  331. m_windowVisible = args->Visible;
  332. }
  333. void App::OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args)
  334. {
  335. m_windowClosed = true;
  336. }
  337. // DisplayInformation event handlers.
  338. void App::OnDpiChanged(DisplayInformation^ sender, Object^ args)
  339. {
  340. }
  341. void App::OnOrientationChanged(DisplayInformation^ sender, Object^ args)
  342. {
  343. }
  344. void App::OnDisplayContentsInvalidated(DisplayInformation^ sender, Object^ args)
  345. {
  346. }