#include "App.h" #include using namespace TemplateApp; using namespace concurrency; using namespace Windows::ApplicationModel; using namespace Windows::ApplicationModel::Core; using namespace Windows::ApplicationModel::Activation; using namespace Windows::Foundation::Collections; using namespace Windows::System::Threading; using namespace Windows::UI::Core; using namespace Windows::UI::Input; using namespace Windows::System; using namespace Windows::Storage; using namespace Windows::Foundation; using namespace Windows::Graphics::Display; using namespace Platform; // The main function is only used to initialize our IFrameworkView class. [Platform::MTAThread] int main(Platform::Array^) { auto direct3DApplicationSource = ref new Direct3DApplicationSource(); CoreApplication::Run(direct3DApplicationSource); return 0; } IFrameworkView^ Direct3DApplicationSource::CreateView() { return ref new App(); } App::App() : m_windowClosed(false), m_windowVisible(true) { } // The first method called when the IFrameworkView is being created. void App::Initialize(CoreApplicationView^ applicationView) { // Register event handlers for app lifecycle. This example includes Activated, so that we // can make the CoreWindow active and start rendering on the window. applicationView->Activated += ref new TypedEventHandler(this, &App::OnActivated); CoreApplication::Suspending += ref new Windows::Foundation::EventHandler(this, &App::OnSuspending); CoreApplication::Resuming += ref new Windows::Foundation::EventHandler(this, &App::OnResuming); } void App::OnPointerPressed(CoreWindow^ sender, PointerEventArgs^ args) { PointerPoint^ currentPoint = args->CurrentPoint; Polycode::UWPEvent touchEvent; if (currentPoint->PointerDevice->PointerDeviceType == Windows::Devices::Input::PointerDeviceType::Touch) { touchEvent.eventCode = Polycode::InputEvent::EVENT_MOUSEDOWN; touchEvent.mouseX = currentPoint->Position.X; touchEvent.mouseY = currentPoint->Position.Y; if (currentPoint->Properties->IsLeftButtonPressed) { touchEvent.mouseButton = 0; } else if (currentPoint->Properties->IsMiddleButtonPressed) { touchEvent.mouseButton = 1; } else { touchEvent.mouseButton = 2; } } else { touchEvent.eventCode = Polycode::InputEvent::EVENT_TOUCHES_BEGAN; touchEvent.touch.position = Vector2(currentPoint->Position.X, currentPoint->Position.Y); touchEvent.touch.id = currentPoint->PointerId; if (currentPoint->PointerDevice->PointerDeviceType == Windows::Devices::Input::PointerDeviceType::Touch) { touchEvent.touch.type = TouchInfo::TYPE_TOUCH; } else if (currentPoint->PointerDevice->PointerDeviceType == Windows::Devices::Input::PointerDeviceType::Pen) { touchEvent.touch.type = TouchInfo::TYPE_PEN; } } } void App::OnPointerMoved(CoreWindow^ sender, PointerEventArgs^ args) { // Get the intermediate points and process them in your gestureRecognizer IVector^ pointerPoints = PointerPoint::GetIntermediatePoints(args->CurrentPoint->PointerId); } void App::OnPointerReleased(CoreWindow^ sender, PointerEventArgs^ args) { // Get the current point and process it in your gestureRecognizer PointerPoint^ pointerPoint = args->CurrentPoint; PointerPoint^ currentPoint = args->CurrentPoint; Polycode::UWPEvent touchEvent; if (currentPoint->PointerDevice->PointerDeviceType == Windows::Devices::Input::PointerDeviceType::Touch) { touchEvent.eventCode = Polycode::InputEvent::EVENT_MOUSEUP; touchEvent.mouseX = currentPoint->Position.X; touchEvent.mouseY = currentPoint->Position.Y; if (currentPoint->Properties->IsLeftButtonPressed) { touchEvent.mouseButton = 0; } else if (currentPoint->Properties->IsMiddleButtonPressed) { touchEvent.mouseButton = 1; } else { touchEvent.mouseButton = 2; } } else { touchEvent.eventCode = Polycode::InputEvent::EVENT_TOUCHES_ENDED; touchEvent.touch.position = Vector2(currentPoint->Position.X, currentPoint->Position.Y); touchEvent.touch.id = currentPoint->PointerId; if (currentPoint->PointerDevice->PointerDeviceType == Windows::Devices::Input::PointerDeviceType::Touch) { touchEvent.touch.type = TouchInfo::TYPE_TOUCH; } else if (currentPoint->PointerDevice->PointerDeviceType == Windows::Devices::Input::PointerDeviceType::Pen) { touchEvent.touch.type = TouchInfo::TYPE_PEN; } } } // Called when the CoreWindow object is created (or re-created). void App::SetWindow(CoreWindow^ window) { window->SizeChanged += ref new TypedEventHandler(this, &App::OnWindowSizeChanged); window->VisibilityChanged += ref new TypedEventHandler(this, &App::OnVisibilityChanged); window->Closed += ref new TypedEventHandler(this, &App::OnWindowClosed); window->PointerPressed += ref new TypedEventHandler(this, &App::OnPointerPressed); window->PointerMoved += ref new TypedEventHandler(this, &App::OnPointerMoved); window->PointerReleased += ref new TypedEventHandler(this, &App::OnPointerReleased); DisplayInformation^ currentDisplayInformation = DisplayInformation::GetForCurrentView(); currentDisplayInformation->DpiChanged += ref new TypedEventHandler(this, &App::OnDpiChanged); currentDisplayInformation->OrientationChanged += ref new TypedEventHandler(this, &App::OnOrientationChanged); DisplayInformation::DisplayContentsInvalidated += ref new TypedEventHandler(this, &App::OnDisplayContentsInvalidated); PolycodeView *view = new PolycodeView(); view->window = reinterpret_cast(window); const EGLint configAttributes[] = { EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, EGL_ALPHA_SIZE, 8, EGL_DEPTH_SIZE, 8, EGL_STENCIL_SIZE, 8, EGL_NONE }; const EGLint contextAttributes[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; const EGLint surfaceAttributes[] = { // EGL_ANGLE_SURFACE_RENDER_TO_BACK_BUFFER is part of the same optimization as EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER (see above). // If you have compilation issues with it then please update your Visual Studio templates. EGL_ANGLE_SURFACE_RENDER_TO_BACK_BUFFER, EGL_TRUE, EGL_NONE }; const EGLint defaultDisplayAttributes[] = { // These are the default display attributes, used to request ANGLE's D3D11 renderer. // eglInitialize will only succeed with these attributes if the hardware supports D3D11 Feature Level 10_0+. EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, // EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER is an optimization that can have large performance benefits on mobile devices. // Its syntax is subject to change, though. Please update your Visual Studio templates if you experience compilation issues with it. EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER, EGL_TRUE, // EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE is an option that enables ANGLE to automatically call // the IDXGIDevice3::Trim method on behalf of the application when it gets suspended. // Calling IDXGIDevice3::Trim when an application is suspended is a Windows Store application certification requirement. EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE, EGL_TRUE, EGL_NONE, }; const EGLint fl9_3DisplayAttributes[] = { // These can be used to request ANGLE's D3D11 renderer, with D3D11 Feature Level 9_3. // These attributes are used if the call to eglInitialize fails with the default display attributes. EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, 9, EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, 3, EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER, EGL_TRUE, EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE, EGL_TRUE, EGL_NONE, }; const EGLint warpDisplayAttributes[] = { // These attributes can be used to request D3D11 WARP. // They are used if eglInitialize fails with both the default display attributes and the 9_3 display attributes. EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE, EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER, EGL_TRUE, EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE, EGL_TRUE, EGL_NONE, }; EGLConfig config = NULL; // eglGetPlatformDisplayEXT is an alternative to eglGetDisplay. It allows us to pass in display attributes, used to configure D3D11. PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT = reinterpret_cast(eglGetProcAddress("eglGetPlatformDisplayEXT")); if (!eglGetPlatformDisplayEXT) { throw Exception::CreateException(E_FAIL, L"Failed to get function eglGetPlatformDisplayEXT"); } // // To initialize the display, we make three sets of calls to eglGetPlatformDisplayEXT and eglInitialize, with varying // parameters passed to eglGetPlatformDisplayEXT: // 1) The first calls uses "defaultDisplayAttributes" as a parameter. This corresponds to D3D11 Feature Level 10_0+. // 2) If eglInitialize fails for step 1 (e.g. because 10_0+ isn't supported by the default GPU), then we try again // using "fl9_3DisplayAttributes". This corresponds to D3D11 Feature Level 9_3. // 3) If eglInitialize fails for step 2 (e.g. because 9_3+ isn't supported by the default GPU), then we try again // using "warpDisplayAttributes". This corresponds to D3D11 Feature Level 11_0 on WARP, a D3D11 software rasterizer. // // This tries to initialize EGL to D3D11 Feature Level 10_0+. See above comment for details. mEglDisplay = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY, defaultDisplayAttributes); if (mEglDisplay == EGL_NO_DISPLAY) { throw Exception::CreateException(E_FAIL, L"Failed to get EGL display"); } if (eglInitialize(mEglDisplay, NULL, NULL) == EGL_FALSE) { // This tries to initialize EGL to D3D11 Feature Level 9_3, if 10_0+ is unavailable (e.g. on some mobile devices). mEglDisplay = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY, fl9_3DisplayAttributes); if (mEglDisplay == EGL_NO_DISPLAY) { throw Exception::CreateException(E_FAIL, L"Failed to get EGL display"); } if (eglInitialize(mEglDisplay, NULL, NULL) == EGL_FALSE) { // This initializes EGL to D3D11 Feature Level 11_0 on WARP, if 9_3+ is unavailable on the default GPU. mEglDisplay = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY, warpDisplayAttributes); if (mEglDisplay == EGL_NO_DISPLAY) { throw Exception::CreateException(E_FAIL, L"Failed to get EGL display"); } if (eglInitialize(mEglDisplay, NULL, NULL) == EGL_FALSE) { // If all of the calls to eglInitialize returned EGL_FALSE then an error has occurred. throw Exception::CreateException(E_FAIL, L"Failed to initialize EGL"); } } } EGLint numConfigs = 0; if ((eglChooseConfig(mEglDisplay, configAttributes, &config, 1, &numConfigs) == EGL_FALSE) || (numConfigs == 0)) { throw Exception::CreateException(E_FAIL, L"Failed to choose first EGLConfig"); } // Create a PropertySet and initialize with the EGLNativeWindowType. PropertySet^ surfaceCreationProperties = ref new PropertySet(); surfaceCreationProperties->Insert(ref new Platform::String(EGLNativeWindowTypeProperty), window); // You can configure the surface to render at a lower resolution and be scaled up to // the full window size. This scaling is often free on mobile hardware. // // One way to configure the SwapChainPanel is to specify precisely which resolution it should render at. // Size customRenderSurfaceSize = Size(800, 600); // surfaceCreationProperties->Insert(ref new String(EGLRenderSurfaceSizeProperty), PropertyValue::CreateSize(customRenderSurfaceSize)); // // Another way is to tell the SwapChainPanel to render at a certain scale factor compared to its size. // e.g. if the SwapChainPanel is 1920x1280 then setting a factor of 0.5f will make the app render at 960x640 // float customResolutionScale = 0.5f; // surfaceCreationProperties->Insert(ref new String(EGLRenderResolutionScaleProperty), PropertyValue::CreateSingle(customResolutionScale)); mEglSurface = eglCreateWindowSurface(mEglDisplay, config, reinterpret_cast(surfaceCreationProperties), surfaceAttributes); if (mEglSurface == EGL_NO_SURFACE) { throw Exception::CreateException(E_FAIL, L"Failed to create EGL fullscreen surface"); } mEglContext = eglCreateContext(mEglDisplay, config, EGL_NO_CONTEXT, contextAttributes); if (mEglContext == EGL_NO_CONTEXT) { throw Exception::CreateException(E_FAIL, L"Failed to create EGL context"); } /* surfaceCreationProperties = ref new PropertySet(); surfaceCreationProperties->Insert(ref new Platform::String(EGLNativeWindowTypeProperty), window); view->eglWindow = reinterpret_cast(surfaceCreationProperties); */ view->mEglContext = mEglContext; view->mEglDisplay = mEglDisplay; view->mEglSurface = mEglSurface; app = new PolycodeTemplateApp(view); core = app->getCore(); } // Initializes scene resources, or loads a previously saved app state. void App::Load(Platform::String^ entryPoint) { } // This method is called after the window becomes active. void App::Run() { while (!m_windowClosed) { if (m_windowVisible) { CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent); } else { CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessOneAndAllPending); } EGLint panelWidth = 0; EGLint panelHeight = 0; eglQuerySurface(mEglDisplay, mEglSurface, EGL_WIDTH, &panelWidth); eglQuerySurface(mEglDisplay, mEglSurface, EGL_HEIGHT, &panelHeight); if (panelWidth != lastPanelWidth || panelHeight != lastPanelHeight) { core->resizeTo(panelWidth, panelHeight); } lastPanelWidth = panelWidth; lastPanelHeight = panelHeight; app->Update(); } } // Required for IFrameworkView. // Terminate events do not cause Uninitialize to be called. It will be called if your IFrameworkView // class is torn down while the app is in the foreground. void App::Uninitialize() { } // Application lifecycle event handlers. void App::OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args) { // Run() won't start until the CoreWindow is activated. CoreWindow::GetForCurrentThread()->Activate(); } void App::OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args) { } void App::OnResuming(Platform::Object^ sender, Platform::Object^ args) { } // Window event handlers. void App::OnWindowSizeChanged(CoreWindow^ sender, WindowSizeChangedEventArgs^ args) { } void App::OnVisibilityChanged(CoreWindow^ sender, VisibilityChangedEventArgs^ args) { m_windowVisible = args->Visible; } void App::OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args) { m_windowClosed = true; } // DisplayInformation event handlers. void App::OnDpiChanged(DisplayInformation^ sender, Object^ args) { } void App::OnOrientationChanged(DisplayInformation^ sender, Object^ args) { } void App::OnDisplayContentsInvalidated(DisplayInformation^ sender, Object^ args) { }