From fdebb373b1532c70e8dd8fa479594613dbd20753 Mon Sep 17 00:00:00 2001 From: Dale Stammen Date: Fri, 16 Oct 2015 15:36:34 -0700 Subject: [PATCH] updated cocos2d-x/angle template files to version 0edf96a2f54a43d068244a86aaf9133c1bf71fe5 --- cocos/platform/win8.1-universal/OpenGLES.cpp | 43 ++- cocos/platform/win8.1-universal/OpenGLES.h | 4 +- .../win8.1-universal/OpenGLESPage.xaml.cpp | 306 ++++++++---------- .../win8.1-universal/OpenGLESPage.xaml.h | 8 - cocos/platform/winrt/CCGL.h | 1 - .../proj.win10/App/Cocos2dEngine/OpenGLES.cpp | 43 ++- .../proj.win10/App/Cocos2dEngine/OpenGLES.h | 4 +- .../App/Cocos2dEngine/OpenGLESPage.xaml.cpp | 306 ++++++++---------- .../App/Cocos2dEngine/OpenGLESPage.xaml.h | 8 - .../App.Shared/OpenGLES.cpp | 43 ++- .../App.Shared/OpenGLES.h | 4 +- .../App.Shared/OpenGLESPage.xaml.cpp | 306 ++++++++---------- .../App.Shared/OpenGLESPage.xaml.h | 8 - .../App.Shared/OpenGLES.cpp | 43 ++- .../App.Shared/OpenGLES.h | 4 +- .../App.Shared/OpenGLESPage.xaml.cpp | 306 ++++++++---------- .../App.Shared/OpenGLESPage.xaml.h | 8 - 17 files changed, 672 insertions(+), 773 deletions(-) diff --git a/cocos/platform/win8.1-universal/OpenGLES.cpp b/cocos/platform/win8.1-universal/OpenGLES.cpp index 837e7a615f..2721b1ee4f 100644 --- a/cocos/platform/win8.1-universal/OpenGLES.cpp +++ b/cocos/platform/win8.1-universal/OpenGLES.cpp @@ -62,8 +62,8 @@ void OpenGLES::Initialize() // 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_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. @@ -78,7 +78,7 @@ void OpenGLES::Initialize() 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_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER, EGL_TRUE, EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE, EGL_TRUE, EGL_NONE, }; @@ -89,7 +89,7 @@ void OpenGLES::Initialize() // 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_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER, EGL_TRUE, EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE, EGL_TRUE, EGL_NONE, }; @@ -112,14 +112,7 @@ void OpenGLES::Initialize() // 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. // - // Note: On Windows Phone, we #ifdef out the first set of calls to eglPlatformDisplayEXT and eglInitialize. - // Windows Phones devices only support D3D11 Feature Level 9_3, but the Windows Phone emulator supports 11_0+. - // We use this #ifdef to limit the Phone emulator to Feature Level 9_3, making it behave more like - // real Windows Phone devices. - // If you wish to test Feature Level 10_0+ in the Windows Phone emulator then you should remove this #ifdef. - // -#if (WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP) // 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) @@ -128,9 +121,8 @@ void OpenGLES::Initialize() } if (eglInitialize(mEglDisplay, NULL, NULL) == EGL_FALSE) -#endif { - // This tries to initialize EGL to D3D11 Feature Level 9_3, if 10_0+ is unavailable (e.g. on Windows Phone, or certain Windows tablets). + // 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) { @@ -139,7 +131,7 @@ void OpenGLES::Initialize() 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 (e.g. on Surface RT). + // 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) { @@ -188,12 +180,17 @@ void OpenGLES::Reset() Initialize(); } -EGLSurface OpenGLES::CreateSurface(SwapChainPanel^ panel, const Size* renderSurfaceSize) +EGLSurface OpenGLES::CreateSurface(SwapChainPanel^ panel, const Size* renderSurfaceSize, const float* resolutionScale) { if (!panel) { throw Exception::CreateException(E_INVALIDARG, L"SwapChainPanel parameter is invalid"); } + + if (renderSurfaceSize != nullptr && resolutionScale != nullptr) + { + throw Exception::CreateException(E_INVALIDARG, L"A size and a scale can't both be specified"); + } EGLSurface surface = EGL_NO_SURFACE; @@ -207,12 +204,18 @@ EGLSurface OpenGLES::CreateSurface(SwapChainPanel^ panel, const Size* renderSurf // Create a PropertySet and initialize with the EGLNativeWindowType. PropertySet^ surfaceCreationProperties = ref new PropertySet(); - surfaceCreationProperties->Insert(ref new Platform::String(EGLNativeWindowTypeProperty), panel); + surfaceCreationProperties->Insert(ref new String(EGLNativeWindowTypeProperty), panel); // If a render surface size is specified, add it to the surface creation properties if (renderSurfaceSize != nullptr) { - surfaceCreationProperties->Insert(ref new Platform::String(EGLRenderSurfaceSizeProperty), PropertyValue::CreateSize(*renderSurfaceSize)); + surfaceCreationProperties->Insert(ref new String(EGLRenderSurfaceSizeProperty), PropertyValue::CreateSize(*renderSurfaceSize)); + } + + // If a resolution scale is specified, add it to the surface creation properties + if (resolutionScale != nullptr) + { + surfaceCreationProperties->Insert(ref new String(EGLRenderResolutionScaleProperty), PropertyValue::CreateSingle(*resolutionScale)); } surface = eglCreateWindowSurface(mEglDisplay, mEglConfig, reinterpret_cast(surfaceCreationProperties), surfaceAttributes); @@ -224,6 +227,12 @@ EGLSurface OpenGLES::CreateSurface(SwapChainPanel^ panel, const Size* renderSurf return surface; } +void OpenGLES::GetSurfaceDimensions(const EGLSurface surface, EGLint* width, EGLint* height) +{ + eglQuerySurface(mEglDisplay, surface, EGL_WIDTH, width); + eglQuerySurface(mEglDisplay, surface, EGL_HEIGHT, height); +} + void OpenGLES::DestroySurface(const EGLSurface surface) { if (mEglDisplay != EGL_NO_DISPLAY && surface != EGL_NO_SURFACE) diff --git a/cocos/platform/win8.1-universal/OpenGLES.h b/cocos/platform/win8.1-universal/OpenGLES.h index e2e7d7e8aa..a6942ccb1d 100644 --- a/cocos/platform/win8.1-universal/OpenGLES.h +++ b/cocos/platform/win8.1-universal/OpenGLES.h @@ -20,7 +20,6 @@ // OpenGL ES includes #include -#include // EGL includes #include @@ -34,7 +33,8 @@ public: OpenGLES(); ~OpenGLES(); - EGLSurface CreateSurface(Windows::UI::Xaml::Controls::SwapChainPanel^ panel, const Windows::Foundation::Size* renderSurfaceSize); + EGLSurface CreateSurface(Windows::UI::Xaml::Controls::SwapChainPanel^ panel, const Windows::Foundation::Size* renderSurfaceSize, const float* renderResolutionScale); + void GetSurfaceDimensions(const EGLSurface surface, EGLint *width, EGLint *height); void DestroySurface(const EGLSurface surface); void MakeCurrent(const EGLSurface surface); EGLBoolean SwapBuffers(const EGLSurface surface); diff --git a/cocos/platform/win8.1-universal/OpenGLESPage.xaml.cpp b/cocos/platform/win8.1-universal/OpenGLESPage.xaml.cpp index e19c6ac5f6..f55d7ba89f 100644 --- a/cocos/platform/win8.1-universal/OpenGLESPage.xaml.cpp +++ b/cocos/platform/win8.1-universal/OpenGLESPage.xaml.cpp @@ -24,7 +24,6 @@ using namespace cocos2d; using namespace Platform; using namespace Concurrency; using namespace Windows::Foundation; -using namespace Windows::Foundation::Collections; using namespace Windows::Graphics::Display; using namespace Windows::System::Threading; using namespace Windows::UI::Core; @@ -50,8 +49,6 @@ OpenGLESPage::OpenGLESPage() : OpenGLESPage::OpenGLESPage(OpenGLES* openGLES) : mOpenGLES(openGLES), mRenderSurface(EGL_NO_SURFACE), - mCustomRenderSurfaceSize(0,0), - mUseCustomRenderSurfaceSize(false), mCoreInput(nullptr), mDpi(0.0f), mDeviceLost(false), @@ -72,8 +69,6 @@ OpenGLESPage::OpenGLESPage(OpenGLES* openGLES) : window->CharacterReceived += ref new TypedEventHandler(this, &OpenGLESPage::OnCharacterReceived); - swapChainPanel->SizeChanged += - ref new Windows::UI::Xaml::SizeChangedEventHandler(this, &OpenGLESPage::OnSwapChainPanelSizeChanged); DisplayInformation^ currentDisplayInformation = DisplayInformation::GetForCurrentView(); @@ -85,8 +80,6 @@ OpenGLESPage::OpenGLESPage(OpenGLES* openGLES) : this->Loaded += ref new Windows::UI::Xaml::RoutedEventHandler(this, &OpenGLESPage::OnPageLoaded); - mSwapChainPanelSize = { swapChainPanel->RenderSize.Width, swapChainPanel->RenderSize.Height }; - #if _MSC_VER >= 1900 if (Windows::Foundation::Metadata::ApiInformation::IsTypePresent("Windows.UI.ViewManagement.StatusBar")) { @@ -158,166 +151,26 @@ void OpenGLESPage::OnPageLoaded(Platform::Object^ sender, Windows::UI::Xaml::Rou mVisible = true; } -void OpenGLESPage::OnPointerPressed(Object^ sender, PointerEventArgs^ e) -{ - bool isMouseEvent = e->CurrentPoint->PointerDevice->PointerDeviceType == Windows::Devices::Input::PointerDeviceType::Mouse; - if (mRenderer) - { - mRenderer->QueuePointerEvent(isMouseEvent ? PointerEventType::MousePressed : PointerEventType::PointerPressed, e); - } -} - -void OpenGLESPage::OnPointerMoved(Object^ sender, PointerEventArgs^ e) -{ - bool isMouseEvent = e->CurrentPoint->PointerDevice->PointerDeviceType == Windows::Devices::Input::PointerDeviceType::Mouse; - if (mRenderer) - { - mRenderer->QueuePointerEvent(isMouseEvent ? PointerEventType::MouseMoved : PointerEventType::PointerMoved, e); - } -} - -void OpenGLESPage::OnPointerReleased(Object^ sender, PointerEventArgs^ e) -{ - bool isMouseEvent = e->CurrentPoint->PointerDevice->PointerDeviceType == Windows::Devices::Input::PointerDeviceType::Mouse; - - if (mRenderer) - { - mRenderer->QueuePointerEvent(isMouseEvent ? PointerEventType::MouseReleased : PointerEventType::PointerReleased, e); - } -} - -void OpenGLESPage::OnPointerWheelChanged(Object^ sender, PointerEventArgs^ e) -{ - bool isMouseEvent = e->CurrentPoint->PointerDevice->PointerDeviceType == Windows::Devices::Input::PointerDeviceType::Mouse; - if (mRenderer && isMouseEvent) - { - mRenderer->QueuePointerEvent(PointerEventType::MouseWheelChanged, e); - } -} - -void OpenGLESPage::OnKeyPressed(CoreWindow^ sender, KeyEventArgs^ e) -{ - if (!e->KeyStatus.WasKeyDown) - { - //log("OpenGLESPage::OnKeyPressed %d", e->VirtualKey); - if (mRenderer) - { - mRenderer->QueueKeyboardEvent(WinRTKeyboardEventType::KeyPressed, e); - } - } -} - -void OpenGLESPage::OnCharacterReceived(CoreWindow^ sender, CharacterReceivedEventArgs^ e) -{ -#if 0 - if (!e->KeyStatus.WasKeyDown) - { - log("OpenGLESPage::OnCharacterReceived %d", e->KeyCode); - } -#endif -} - -void OpenGLESPage::OnKeyReleased(CoreWindow^ sender, KeyEventArgs^ e) -{ - //log("OpenGLESPage::OnKeyReleased %d", e->VirtualKey); - if (mRenderer) - { - mRenderer->QueueKeyboardEvent(WinRTKeyboardEventType::KeyReleased, e); - } -} - - -void OpenGLESPage::OnOrientationChanged(DisplayInformation^ sender, Object^ args) -{ - critical_section::scoped_lock lock(mSwapChainPanelSizeCriticalSection); - mOrientation = sender->CurrentOrientation; -} - -void OpenGLESPage::SetVisibility(bool isVisible) -{ - if (isVisible && mRenderSurface != EGL_NO_SURFACE) - { - std::unique_lock locker(mSleepMutex); - mVisible = true; - mSleepCondition.notify_one(); - } - else - { - mVisible = false; - } -} - -void OpenGLESPage::OnVisibilityChanged(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::VisibilityChangedEventArgs^ args) -{ - if (args->Visible && mRenderSurface != EGL_NO_SURFACE) - { - SetVisibility(true); - } - else - { - SetVisibility(false); - } -} - -#if (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) || _MSC_VER >= 1900 -/* - We set args->Handled = true to prevent the app from quitting when the back button is pressed. - This is because this back button event happens on the XAML UI thread and not the cocos2d-x UI thread. - We need to give the game developer a chance to decide to exit the app depending on where they - are in their game. They can receive the back button event by listening for the - EventKeyboard::KeyCode::KEY_ESCAPE event. - - The default behavior is to exit the app if the EventKeyboard::KeyCode::KEY_ESCAPE event - is not handled by the game. -*/ -void OpenGLESPage::OnBackButtonPressed(Object^ sender, BackPressedEventArgs^ args) -{ - if (mRenderer) - { - mRenderer->QueueBackButtonEvent(); - args->Handled = true; - } -} -#endif - -void OpenGLESPage::OnSwapChainPanelSizeChanged(Object^ sender, Windows::UI::Xaml::SizeChangedEventArgs^ e) -{ - // Size change events occur outside of the render thread. A lock is required when updating - // the swapchainpanel size - critical_section::scoped_lock lock(mSwapChainPanelSizeCriticalSection); - mSwapChainPanelSize = { e->NewSize.Width, e->NewSize.Height }; -} - -void OpenGLESPage::GetSwapChainPanelSize(GLsizei* width, GLsizei* height) -{ - critical_section::scoped_lock lock(mSwapChainPanelSizeCriticalSection); - // If a custom render surface size is specified, return its size instead of - // the swapchain panel size. - if (mUseCustomRenderSurfaceSize) - { - *width = static_cast(mCustomRenderSurfaceSize.Width); - *height = static_cast(mCustomRenderSurfaceSize.Height); - } - else - { - *width = static_cast(mSwapChainPanelSize.Width); - *height = static_cast(mSwapChainPanelSize.Height); - } -} - void OpenGLESPage::CreateRenderSurface() { if (mOpenGLES && mRenderSurface == EGL_NO_SURFACE) { - // - // A Custom render surface size can be specified by uncommenting the following lines. - // The render surface will be automatically scaled to fit the entire window. Using a - // smaller sized render surface can result in a performance gain. - // - //mCustomRenderSurfaceSize = Size(800, 600); - //mUseCustomRenderSurfaceSize = true; + // The app can configure the the SwapChainPanel which may boost performance. + // By default, this template uses the default configuration. + mRenderSurface = mOpenGLES->CreateSurface(swapChainPanel, nullptr, nullptr); - mRenderSurface = mOpenGLES->CreateSurface(swapChainPanel, mUseCustomRenderSurfaceSize ? &mCustomRenderSurfaceSize : nullptr); + // You can configure the SwapChainPanel to render at a lower resolution and be scaled up to + // the swapchain panel 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); + // mRenderSurface = mOpenGLES->CreateSurface(swapChainPanel, &customRenderSurfaceSize, nullptr); + // + // 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; + // mRenderSurface = mOpenGLES->CreateSurface(swapChainPanel, nullptr, &customResolutionScale); + // } } @@ -375,7 +228,7 @@ void OpenGLESPage::StartRenderLoop() GLsizei panelWidth = 0; GLsizei panelHeight = 0; - GetSwapChainPanelSize(&panelWidth, &panelHeight); + mOpenGLES->GetSurfaceDimensions(mRenderSurface, &panelWidth, &panelHeight); if (mRenderer.get() == nullptr) { @@ -412,7 +265,7 @@ void OpenGLESPage::StartRenderLoop() } } - GetSwapChainPanelSize(&panelWidth, &panelHeight); + mOpenGLES->GetSurfaceDimensions(mRenderSurface, &panelWidth, &panelHeight); mRenderer.get()->Draw(panelWidth, panelHeight, mDpi, mOrientation); // Recreate input dispatch @@ -425,7 +278,7 @@ void OpenGLESPage::StartRenderLoop() if (mRenderer->AppShouldExit()) { // run on main UI thread - swapChainPanel->Dispatcher->RunAsync(Windows::UI::Core::CoreDispatcherPriority::Normal, ref new DispatchedHandler([this]() + swapChainPanel->Dispatcher->RunAsync(Windows::UI::Core::CoreDispatcherPriority::High, ref new DispatchedHandler([=]() { TerminateApp(); })); @@ -491,4 +344,125 @@ void OpenGLESPage::StopRenderLoop() mSleepCondition.notify_one(); mRenderLoopWorker = nullptr; } -} \ No newline at end of file +} + +void OpenGLESPage::OnPointerPressed(Object^ sender, PointerEventArgs^ e) +{ + bool isMouseEvent = e->CurrentPoint->PointerDevice->PointerDeviceType == Windows::Devices::Input::PointerDeviceType::Mouse; + if (mRenderer) + { + mRenderer->QueuePointerEvent(isMouseEvent ? PointerEventType::MousePressed : PointerEventType::PointerPressed, e); + } +} + +void OpenGLESPage::OnPointerMoved(Object^ sender, PointerEventArgs^ e) +{ + bool isMouseEvent = e->CurrentPoint->PointerDevice->PointerDeviceType == Windows::Devices::Input::PointerDeviceType::Mouse; + if (mRenderer) + { + mRenderer->QueuePointerEvent(isMouseEvent ? PointerEventType::MouseMoved : PointerEventType::PointerMoved, e); + } +} + +void OpenGLESPage::OnPointerReleased(Object^ sender, PointerEventArgs^ e) +{ + bool isMouseEvent = e->CurrentPoint->PointerDevice->PointerDeviceType == Windows::Devices::Input::PointerDeviceType::Mouse; + + if (mRenderer) + { + mRenderer->QueuePointerEvent(isMouseEvent ? PointerEventType::MouseReleased : PointerEventType::PointerReleased, e); + } +} + +void OpenGLESPage::OnPointerWheelChanged(Object^ sender, PointerEventArgs^ e) +{ + bool isMouseEvent = e->CurrentPoint->PointerDevice->PointerDeviceType == Windows::Devices::Input::PointerDeviceType::Mouse; + if (mRenderer && isMouseEvent) + { + mRenderer->QueuePointerEvent(PointerEventType::MouseWheelChanged, e); + } +} + +void OpenGLESPage::OnKeyPressed(CoreWindow^ sender, KeyEventArgs^ e) +{ + if (!e->KeyStatus.WasKeyDown) + { + //log("OpenGLESPage::OnKeyPressed %d", e->VirtualKey); + if (mRenderer) + { + mRenderer->QueueKeyboardEvent(WinRTKeyboardEventType::KeyPressed, e); + } + } +} + +void OpenGLESPage::OnCharacterReceived(CoreWindow^ sender, CharacterReceivedEventArgs^ e) +{ +#if 0 + if (!e->KeyStatus.WasKeyDown) + { + log("OpenGLESPage::OnCharacterReceived %d", e->KeyCode); + } +#endif +} + +void OpenGLESPage::OnKeyReleased(CoreWindow^ sender, KeyEventArgs^ e) +{ + //log("OpenGLESPage::OnKeyReleased %d", e->VirtualKey); + if (mRenderer) + { + mRenderer->QueueKeyboardEvent(WinRTKeyboardEventType::KeyReleased, e); + } +} + + +void OpenGLESPage::OnOrientationChanged(DisplayInformation^ sender, Object^ args) +{ + mOrientation = sender->CurrentOrientation; +} + +void OpenGLESPage::SetVisibility(bool isVisible) +{ + if (isVisible && mRenderSurface != EGL_NO_SURFACE) + { + std::unique_lock locker(mSleepMutex); + mVisible = true; + mSleepCondition.notify_one(); + } + else + { + mVisible = false; + } +} + +void OpenGLESPage::OnVisibilityChanged(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::VisibilityChangedEventArgs^ args) +{ + if (args->Visible && mRenderSurface != EGL_NO_SURFACE) + { + SetVisibility(true); + } + else + { + SetVisibility(false); + } +} + +#if (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) || _MSC_VER >= 1900 +/* +We set args->Handled = true to prevent the app from quitting when the back button is pressed. +This is because this back button event happens on the XAML UI thread and not the cocos2d-x UI thread. +We need to give the game developer a chance to decide to exit the app depending on where they +are in their game. They can receive the back button event by listening for the +EventKeyboard::KeyCode::KEY_ESCAPE event. + +The default behavior is to exit the app if the EventKeyboard::KeyCode::KEY_ESCAPE event +is not handled by the game. +*/ +void OpenGLESPage::OnBackButtonPressed(Object^ sender, BackPressedEventArgs^ args) +{ + if (mRenderer) + { + mRenderer->QueueBackButtonEvent(); + args->Handled = true; + } +} +#endif \ No newline at end of file diff --git a/cocos/platform/win8.1-universal/OpenGLESPage.xaml.h b/cocos/platform/win8.1-universal/OpenGLESPage.xaml.h index 8fac8fdf0c..83fa8215c8 100644 --- a/cocos/platform/win8.1-universal/OpenGLESPage.xaml.h +++ b/cocos/platform/win8.1-universal/OpenGLESPage.xaml.h @@ -41,11 +41,9 @@ namespace CocosAppWinRT private: void OnPageLoaded(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e); void OnVisibilityChanged(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::VisibilityChangedEventArgs^ args); - void OnSwapChainPanelSizeChanged(Platform::Object^ sender, Windows::UI::Xaml::SizeChangedEventArgs^ e); #if (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) || _MSC_VER >= 1900 void OnBackButtonPressed(Platform::Object^ sender, Windows::Phone::UI::Input::BackPressedEventArgs^ args); #endif - void GetSwapChainPanelSize(GLsizei* width, GLsizei* height); void CreateRenderSurface(); void DestroyRenderSurface(); void RecoverFromLostDevice(); @@ -58,12 +56,6 @@ namespace CocosAppWinRT OpenGLES* mOpenGLES; std::shared_ptr mRenderer; - Windows::Foundation::Size mSwapChainPanelSize; - Concurrency::critical_section mSwapChainPanelSizeCriticalSection; - - Windows::Foundation::Size mCustomRenderSurfaceSize; - bool mUseCustomRenderSurfaceSize; - EGLSurface mRenderSurface; // This surface is associated with a swapChainPanel on the page Concurrency::critical_section mRenderSurfaceCriticalSection; Windows::Foundation::IAsyncAction^ mRenderLoopWorker; diff --git a/cocos/platform/winrt/CCGL.h b/cocos/platform/winrt/CCGL.h index 37a9ef5b32..feeafe282b 100644 --- a/cocos/platform/winrt/CCGL.h +++ b/cocos/platform/winrt/CCGL.h @@ -37,7 +37,6 @@ THE SOFTWARE. #include "GLES2/gl2.h" #include "GLES2/gl2ext.h" #include "GLES3/gl3.h" -#include "GLES3/gl3ext.h" #define glMapBuffer glMapBufferOES diff --git a/templates/cpp-template-default/proj.win10/App/Cocos2dEngine/OpenGLES.cpp b/templates/cpp-template-default/proj.win10/App/Cocos2dEngine/OpenGLES.cpp index 837e7a615f..2721b1ee4f 100644 --- a/templates/cpp-template-default/proj.win10/App/Cocos2dEngine/OpenGLES.cpp +++ b/templates/cpp-template-default/proj.win10/App/Cocos2dEngine/OpenGLES.cpp @@ -62,8 +62,8 @@ void OpenGLES::Initialize() // 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_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. @@ -78,7 +78,7 @@ void OpenGLES::Initialize() 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_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER, EGL_TRUE, EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE, EGL_TRUE, EGL_NONE, }; @@ -89,7 +89,7 @@ void OpenGLES::Initialize() // 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_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER, EGL_TRUE, EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE, EGL_TRUE, EGL_NONE, }; @@ -112,14 +112,7 @@ void OpenGLES::Initialize() // 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. // - // Note: On Windows Phone, we #ifdef out the first set of calls to eglPlatformDisplayEXT and eglInitialize. - // Windows Phones devices only support D3D11 Feature Level 9_3, but the Windows Phone emulator supports 11_0+. - // We use this #ifdef to limit the Phone emulator to Feature Level 9_3, making it behave more like - // real Windows Phone devices. - // If you wish to test Feature Level 10_0+ in the Windows Phone emulator then you should remove this #ifdef. - // -#if (WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP) // 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) @@ -128,9 +121,8 @@ void OpenGLES::Initialize() } if (eglInitialize(mEglDisplay, NULL, NULL) == EGL_FALSE) -#endif { - // This tries to initialize EGL to D3D11 Feature Level 9_3, if 10_0+ is unavailable (e.g. on Windows Phone, or certain Windows tablets). + // 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) { @@ -139,7 +131,7 @@ void OpenGLES::Initialize() 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 (e.g. on Surface RT). + // 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) { @@ -188,12 +180,17 @@ void OpenGLES::Reset() Initialize(); } -EGLSurface OpenGLES::CreateSurface(SwapChainPanel^ panel, const Size* renderSurfaceSize) +EGLSurface OpenGLES::CreateSurface(SwapChainPanel^ panel, const Size* renderSurfaceSize, const float* resolutionScale) { if (!panel) { throw Exception::CreateException(E_INVALIDARG, L"SwapChainPanel parameter is invalid"); } + + if (renderSurfaceSize != nullptr && resolutionScale != nullptr) + { + throw Exception::CreateException(E_INVALIDARG, L"A size and a scale can't both be specified"); + } EGLSurface surface = EGL_NO_SURFACE; @@ -207,12 +204,18 @@ EGLSurface OpenGLES::CreateSurface(SwapChainPanel^ panel, const Size* renderSurf // Create a PropertySet and initialize with the EGLNativeWindowType. PropertySet^ surfaceCreationProperties = ref new PropertySet(); - surfaceCreationProperties->Insert(ref new Platform::String(EGLNativeWindowTypeProperty), panel); + surfaceCreationProperties->Insert(ref new String(EGLNativeWindowTypeProperty), panel); // If a render surface size is specified, add it to the surface creation properties if (renderSurfaceSize != nullptr) { - surfaceCreationProperties->Insert(ref new Platform::String(EGLRenderSurfaceSizeProperty), PropertyValue::CreateSize(*renderSurfaceSize)); + surfaceCreationProperties->Insert(ref new String(EGLRenderSurfaceSizeProperty), PropertyValue::CreateSize(*renderSurfaceSize)); + } + + // If a resolution scale is specified, add it to the surface creation properties + if (resolutionScale != nullptr) + { + surfaceCreationProperties->Insert(ref new String(EGLRenderResolutionScaleProperty), PropertyValue::CreateSingle(*resolutionScale)); } surface = eglCreateWindowSurface(mEglDisplay, mEglConfig, reinterpret_cast(surfaceCreationProperties), surfaceAttributes); @@ -224,6 +227,12 @@ EGLSurface OpenGLES::CreateSurface(SwapChainPanel^ panel, const Size* renderSurf return surface; } +void OpenGLES::GetSurfaceDimensions(const EGLSurface surface, EGLint* width, EGLint* height) +{ + eglQuerySurface(mEglDisplay, surface, EGL_WIDTH, width); + eglQuerySurface(mEglDisplay, surface, EGL_HEIGHT, height); +} + void OpenGLES::DestroySurface(const EGLSurface surface) { if (mEglDisplay != EGL_NO_DISPLAY && surface != EGL_NO_SURFACE) diff --git a/templates/cpp-template-default/proj.win10/App/Cocos2dEngine/OpenGLES.h b/templates/cpp-template-default/proj.win10/App/Cocos2dEngine/OpenGLES.h index e2e7d7e8aa..a6942ccb1d 100644 --- a/templates/cpp-template-default/proj.win10/App/Cocos2dEngine/OpenGLES.h +++ b/templates/cpp-template-default/proj.win10/App/Cocos2dEngine/OpenGLES.h @@ -20,7 +20,6 @@ // OpenGL ES includes #include -#include // EGL includes #include @@ -34,7 +33,8 @@ public: OpenGLES(); ~OpenGLES(); - EGLSurface CreateSurface(Windows::UI::Xaml::Controls::SwapChainPanel^ panel, const Windows::Foundation::Size* renderSurfaceSize); + EGLSurface CreateSurface(Windows::UI::Xaml::Controls::SwapChainPanel^ panel, const Windows::Foundation::Size* renderSurfaceSize, const float* renderResolutionScale); + void GetSurfaceDimensions(const EGLSurface surface, EGLint *width, EGLint *height); void DestroySurface(const EGLSurface surface); void MakeCurrent(const EGLSurface surface); EGLBoolean SwapBuffers(const EGLSurface surface); diff --git a/templates/cpp-template-default/proj.win10/App/Cocos2dEngine/OpenGLESPage.xaml.cpp b/templates/cpp-template-default/proj.win10/App/Cocos2dEngine/OpenGLESPage.xaml.cpp index e19c6ac5f6..f55d7ba89f 100644 --- a/templates/cpp-template-default/proj.win10/App/Cocos2dEngine/OpenGLESPage.xaml.cpp +++ b/templates/cpp-template-default/proj.win10/App/Cocos2dEngine/OpenGLESPage.xaml.cpp @@ -24,7 +24,6 @@ using namespace cocos2d; using namespace Platform; using namespace Concurrency; using namespace Windows::Foundation; -using namespace Windows::Foundation::Collections; using namespace Windows::Graphics::Display; using namespace Windows::System::Threading; using namespace Windows::UI::Core; @@ -50,8 +49,6 @@ OpenGLESPage::OpenGLESPage() : OpenGLESPage::OpenGLESPage(OpenGLES* openGLES) : mOpenGLES(openGLES), mRenderSurface(EGL_NO_SURFACE), - mCustomRenderSurfaceSize(0,0), - mUseCustomRenderSurfaceSize(false), mCoreInput(nullptr), mDpi(0.0f), mDeviceLost(false), @@ -72,8 +69,6 @@ OpenGLESPage::OpenGLESPage(OpenGLES* openGLES) : window->CharacterReceived += ref new TypedEventHandler(this, &OpenGLESPage::OnCharacterReceived); - swapChainPanel->SizeChanged += - ref new Windows::UI::Xaml::SizeChangedEventHandler(this, &OpenGLESPage::OnSwapChainPanelSizeChanged); DisplayInformation^ currentDisplayInformation = DisplayInformation::GetForCurrentView(); @@ -85,8 +80,6 @@ OpenGLESPage::OpenGLESPage(OpenGLES* openGLES) : this->Loaded += ref new Windows::UI::Xaml::RoutedEventHandler(this, &OpenGLESPage::OnPageLoaded); - mSwapChainPanelSize = { swapChainPanel->RenderSize.Width, swapChainPanel->RenderSize.Height }; - #if _MSC_VER >= 1900 if (Windows::Foundation::Metadata::ApiInformation::IsTypePresent("Windows.UI.ViewManagement.StatusBar")) { @@ -158,166 +151,26 @@ void OpenGLESPage::OnPageLoaded(Platform::Object^ sender, Windows::UI::Xaml::Rou mVisible = true; } -void OpenGLESPage::OnPointerPressed(Object^ sender, PointerEventArgs^ e) -{ - bool isMouseEvent = e->CurrentPoint->PointerDevice->PointerDeviceType == Windows::Devices::Input::PointerDeviceType::Mouse; - if (mRenderer) - { - mRenderer->QueuePointerEvent(isMouseEvent ? PointerEventType::MousePressed : PointerEventType::PointerPressed, e); - } -} - -void OpenGLESPage::OnPointerMoved(Object^ sender, PointerEventArgs^ e) -{ - bool isMouseEvent = e->CurrentPoint->PointerDevice->PointerDeviceType == Windows::Devices::Input::PointerDeviceType::Mouse; - if (mRenderer) - { - mRenderer->QueuePointerEvent(isMouseEvent ? PointerEventType::MouseMoved : PointerEventType::PointerMoved, e); - } -} - -void OpenGLESPage::OnPointerReleased(Object^ sender, PointerEventArgs^ e) -{ - bool isMouseEvent = e->CurrentPoint->PointerDevice->PointerDeviceType == Windows::Devices::Input::PointerDeviceType::Mouse; - - if (mRenderer) - { - mRenderer->QueuePointerEvent(isMouseEvent ? PointerEventType::MouseReleased : PointerEventType::PointerReleased, e); - } -} - -void OpenGLESPage::OnPointerWheelChanged(Object^ sender, PointerEventArgs^ e) -{ - bool isMouseEvent = e->CurrentPoint->PointerDevice->PointerDeviceType == Windows::Devices::Input::PointerDeviceType::Mouse; - if (mRenderer && isMouseEvent) - { - mRenderer->QueuePointerEvent(PointerEventType::MouseWheelChanged, e); - } -} - -void OpenGLESPage::OnKeyPressed(CoreWindow^ sender, KeyEventArgs^ e) -{ - if (!e->KeyStatus.WasKeyDown) - { - //log("OpenGLESPage::OnKeyPressed %d", e->VirtualKey); - if (mRenderer) - { - mRenderer->QueueKeyboardEvent(WinRTKeyboardEventType::KeyPressed, e); - } - } -} - -void OpenGLESPage::OnCharacterReceived(CoreWindow^ sender, CharacterReceivedEventArgs^ e) -{ -#if 0 - if (!e->KeyStatus.WasKeyDown) - { - log("OpenGLESPage::OnCharacterReceived %d", e->KeyCode); - } -#endif -} - -void OpenGLESPage::OnKeyReleased(CoreWindow^ sender, KeyEventArgs^ e) -{ - //log("OpenGLESPage::OnKeyReleased %d", e->VirtualKey); - if (mRenderer) - { - mRenderer->QueueKeyboardEvent(WinRTKeyboardEventType::KeyReleased, e); - } -} - - -void OpenGLESPage::OnOrientationChanged(DisplayInformation^ sender, Object^ args) -{ - critical_section::scoped_lock lock(mSwapChainPanelSizeCriticalSection); - mOrientation = sender->CurrentOrientation; -} - -void OpenGLESPage::SetVisibility(bool isVisible) -{ - if (isVisible && mRenderSurface != EGL_NO_SURFACE) - { - std::unique_lock locker(mSleepMutex); - mVisible = true; - mSleepCondition.notify_one(); - } - else - { - mVisible = false; - } -} - -void OpenGLESPage::OnVisibilityChanged(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::VisibilityChangedEventArgs^ args) -{ - if (args->Visible && mRenderSurface != EGL_NO_SURFACE) - { - SetVisibility(true); - } - else - { - SetVisibility(false); - } -} - -#if (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) || _MSC_VER >= 1900 -/* - We set args->Handled = true to prevent the app from quitting when the back button is pressed. - This is because this back button event happens on the XAML UI thread and not the cocos2d-x UI thread. - We need to give the game developer a chance to decide to exit the app depending on where they - are in their game. They can receive the back button event by listening for the - EventKeyboard::KeyCode::KEY_ESCAPE event. - - The default behavior is to exit the app if the EventKeyboard::KeyCode::KEY_ESCAPE event - is not handled by the game. -*/ -void OpenGLESPage::OnBackButtonPressed(Object^ sender, BackPressedEventArgs^ args) -{ - if (mRenderer) - { - mRenderer->QueueBackButtonEvent(); - args->Handled = true; - } -} -#endif - -void OpenGLESPage::OnSwapChainPanelSizeChanged(Object^ sender, Windows::UI::Xaml::SizeChangedEventArgs^ e) -{ - // Size change events occur outside of the render thread. A lock is required when updating - // the swapchainpanel size - critical_section::scoped_lock lock(mSwapChainPanelSizeCriticalSection); - mSwapChainPanelSize = { e->NewSize.Width, e->NewSize.Height }; -} - -void OpenGLESPage::GetSwapChainPanelSize(GLsizei* width, GLsizei* height) -{ - critical_section::scoped_lock lock(mSwapChainPanelSizeCriticalSection); - // If a custom render surface size is specified, return its size instead of - // the swapchain panel size. - if (mUseCustomRenderSurfaceSize) - { - *width = static_cast(mCustomRenderSurfaceSize.Width); - *height = static_cast(mCustomRenderSurfaceSize.Height); - } - else - { - *width = static_cast(mSwapChainPanelSize.Width); - *height = static_cast(mSwapChainPanelSize.Height); - } -} - void OpenGLESPage::CreateRenderSurface() { if (mOpenGLES && mRenderSurface == EGL_NO_SURFACE) { - // - // A Custom render surface size can be specified by uncommenting the following lines. - // The render surface will be automatically scaled to fit the entire window. Using a - // smaller sized render surface can result in a performance gain. - // - //mCustomRenderSurfaceSize = Size(800, 600); - //mUseCustomRenderSurfaceSize = true; + // The app can configure the the SwapChainPanel which may boost performance. + // By default, this template uses the default configuration. + mRenderSurface = mOpenGLES->CreateSurface(swapChainPanel, nullptr, nullptr); - mRenderSurface = mOpenGLES->CreateSurface(swapChainPanel, mUseCustomRenderSurfaceSize ? &mCustomRenderSurfaceSize : nullptr); + // You can configure the SwapChainPanel to render at a lower resolution and be scaled up to + // the swapchain panel 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); + // mRenderSurface = mOpenGLES->CreateSurface(swapChainPanel, &customRenderSurfaceSize, nullptr); + // + // 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; + // mRenderSurface = mOpenGLES->CreateSurface(swapChainPanel, nullptr, &customResolutionScale); + // } } @@ -375,7 +228,7 @@ void OpenGLESPage::StartRenderLoop() GLsizei panelWidth = 0; GLsizei panelHeight = 0; - GetSwapChainPanelSize(&panelWidth, &panelHeight); + mOpenGLES->GetSurfaceDimensions(mRenderSurface, &panelWidth, &panelHeight); if (mRenderer.get() == nullptr) { @@ -412,7 +265,7 @@ void OpenGLESPage::StartRenderLoop() } } - GetSwapChainPanelSize(&panelWidth, &panelHeight); + mOpenGLES->GetSurfaceDimensions(mRenderSurface, &panelWidth, &panelHeight); mRenderer.get()->Draw(panelWidth, panelHeight, mDpi, mOrientation); // Recreate input dispatch @@ -425,7 +278,7 @@ void OpenGLESPage::StartRenderLoop() if (mRenderer->AppShouldExit()) { // run on main UI thread - swapChainPanel->Dispatcher->RunAsync(Windows::UI::Core::CoreDispatcherPriority::Normal, ref new DispatchedHandler([this]() + swapChainPanel->Dispatcher->RunAsync(Windows::UI::Core::CoreDispatcherPriority::High, ref new DispatchedHandler([=]() { TerminateApp(); })); @@ -491,4 +344,125 @@ void OpenGLESPage::StopRenderLoop() mSleepCondition.notify_one(); mRenderLoopWorker = nullptr; } -} \ No newline at end of file +} + +void OpenGLESPage::OnPointerPressed(Object^ sender, PointerEventArgs^ e) +{ + bool isMouseEvent = e->CurrentPoint->PointerDevice->PointerDeviceType == Windows::Devices::Input::PointerDeviceType::Mouse; + if (mRenderer) + { + mRenderer->QueuePointerEvent(isMouseEvent ? PointerEventType::MousePressed : PointerEventType::PointerPressed, e); + } +} + +void OpenGLESPage::OnPointerMoved(Object^ sender, PointerEventArgs^ e) +{ + bool isMouseEvent = e->CurrentPoint->PointerDevice->PointerDeviceType == Windows::Devices::Input::PointerDeviceType::Mouse; + if (mRenderer) + { + mRenderer->QueuePointerEvent(isMouseEvent ? PointerEventType::MouseMoved : PointerEventType::PointerMoved, e); + } +} + +void OpenGLESPage::OnPointerReleased(Object^ sender, PointerEventArgs^ e) +{ + bool isMouseEvent = e->CurrentPoint->PointerDevice->PointerDeviceType == Windows::Devices::Input::PointerDeviceType::Mouse; + + if (mRenderer) + { + mRenderer->QueuePointerEvent(isMouseEvent ? PointerEventType::MouseReleased : PointerEventType::PointerReleased, e); + } +} + +void OpenGLESPage::OnPointerWheelChanged(Object^ sender, PointerEventArgs^ e) +{ + bool isMouseEvent = e->CurrentPoint->PointerDevice->PointerDeviceType == Windows::Devices::Input::PointerDeviceType::Mouse; + if (mRenderer && isMouseEvent) + { + mRenderer->QueuePointerEvent(PointerEventType::MouseWheelChanged, e); + } +} + +void OpenGLESPage::OnKeyPressed(CoreWindow^ sender, KeyEventArgs^ e) +{ + if (!e->KeyStatus.WasKeyDown) + { + //log("OpenGLESPage::OnKeyPressed %d", e->VirtualKey); + if (mRenderer) + { + mRenderer->QueueKeyboardEvent(WinRTKeyboardEventType::KeyPressed, e); + } + } +} + +void OpenGLESPage::OnCharacterReceived(CoreWindow^ sender, CharacterReceivedEventArgs^ e) +{ +#if 0 + if (!e->KeyStatus.WasKeyDown) + { + log("OpenGLESPage::OnCharacterReceived %d", e->KeyCode); + } +#endif +} + +void OpenGLESPage::OnKeyReleased(CoreWindow^ sender, KeyEventArgs^ e) +{ + //log("OpenGLESPage::OnKeyReleased %d", e->VirtualKey); + if (mRenderer) + { + mRenderer->QueueKeyboardEvent(WinRTKeyboardEventType::KeyReleased, e); + } +} + + +void OpenGLESPage::OnOrientationChanged(DisplayInformation^ sender, Object^ args) +{ + mOrientation = sender->CurrentOrientation; +} + +void OpenGLESPage::SetVisibility(bool isVisible) +{ + if (isVisible && mRenderSurface != EGL_NO_SURFACE) + { + std::unique_lock locker(mSleepMutex); + mVisible = true; + mSleepCondition.notify_one(); + } + else + { + mVisible = false; + } +} + +void OpenGLESPage::OnVisibilityChanged(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::VisibilityChangedEventArgs^ args) +{ + if (args->Visible && mRenderSurface != EGL_NO_SURFACE) + { + SetVisibility(true); + } + else + { + SetVisibility(false); + } +} + +#if (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) || _MSC_VER >= 1900 +/* +We set args->Handled = true to prevent the app from quitting when the back button is pressed. +This is because this back button event happens on the XAML UI thread and not the cocos2d-x UI thread. +We need to give the game developer a chance to decide to exit the app depending on where they +are in their game. They can receive the back button event by listening for the +EventKeyboard::KeyCode::KEY_ESCAPE event. + +The default behavior is to exit the app if the EventKeyboard::KeyCode::KEY_ESCAPE event +is not handled by the game. +*/ +void OpenGLESPage::OnBackButtonPressed(Object^ sender, BackPressedEventArgs^ args) +{ + if (mRenderer) + { + mRenderer->QueueBackButtonEvent(); + args->Handled = true; + } +} +#endif \ No newline at end of file diff --git a/templates/cpp-template-default/proj.win10/App/Cocos2dEngine/OpenGLESPage.xaml.h b/templates/cpp-template-default/proj.win10/App/Cocos2dEngine/OpenGLESPage.xaml.h index 8fac8fdf0c..83fa8215c8 100644 --- a/templates/cpp-template-default/proj.win10/App/Cocos2dEngine/OpenGLESPage.xaml.h +++ b/templates/cpp-template-default/proj.win10/App/Cocos2dEngine/OpenGLESPage.xaml.h @@ -41,11 +41,9 @@ namespace CocosAppWinRT private: void OnPageLoaded(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e); void OnVisibilityChanged(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::VisibilityChangedEventArgs^ args); - void OnSwapChainPanelSizeChanged(Platform::Object^ sender, Windows::UI::Xaml::SizeChangedEventArgs^ e); #if (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) || _MSC_VER >= 1900 void OnBackButtonPressed(Platform::Object^ sender, Windows::Phone::UI::Input::BackPressedEventArgs^ args); #endif - void GetSwapChainPanelSize(GLsizei* width, GLsizei* height); void CreateRenderSurface(); void DestroyRenderSurface(); void RecoverFromLostDevice(); @@ -58,12 +56,6 @@ namespace CocosAppWinRT OpenGLES* mOpenGLES; std::shared_ptr mRenderer; - Windows::Foundation::Size mSwapChainPanelSize; - Concurrency::critical_section mSwapChainPanelSizeCriticalSection; - - Windows::Foundation::Size mCustomRenderSurfaceSize; - bool mUseCustomRenderSurfaceSize; - EGLSurface mRenderSurface; // This surface is associated with a swapChainPanel on the page Concurrency::critical_section mRenderSurfaceCriticalSection; Windows::Foundation::IAsyncAction^ mRenderLoopWorker; diff --git a/templates/cpp-template-default/proj.win8.1-universal/App.Shared/OpenGLES.cpp b/templates/cpp-template-default/proj.win8.1-universal/App.Shared/OpenGLES.cpp index 837e7a615f..2721b1ee4f 100644 --- a/templates/cpp-template-default/proj.win8.1-universal/App.Shared/OpenGLES.cpp +++ b/templates/cpp-template-default/proj.win8.1-universal/App.Shared/OpenGLES.cpp @@ -62,8 +62,8 @@ void OpenGLES::Initialize() // 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_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. @@ -78,7 +78,7 @@ void OpenGLES::Initialize() 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_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER, EGL_TRUE, EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE, EGL_TRUE, EGL_NONE, }; @@ -89,7 +89,7 @@ void OpenGLES::Initialize() // 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_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER, EGL_TRUE, EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE, EGL_TRUE, EGL_NONE, }; @@ -112,14 +112,7 @@ void OpenGLES::Initialize() // 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. // - // Note: On Windows Phone, we #ifdef out the first set of calls to eglPlatformDisplayEXT and eglInitialize. - // Windows Phones devices only support D3D11 Feature Level 9_3, but the Windows Phone emulator supports 11_0+. - // We use this #ifdef to limit the Phone emulator to Feature Level 9_3, making it behave more like - // real Windows Phone devices. - // If you wish to test Feature Level 10_0+ in the Windows Phone emulator then you should remove this #ifdef. - // -#if (WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP) // 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) @@ -128,9 +121,8 @@ void OpenGLES::Initialize() } if (eglInitialize(mEglDisplay, NULL, NULL) == EGL_FALSE) -#endif { - // This tries to initialize EGL to D3D11 Feature Level 9_3, if 10_0+ is unavailable (e.g. on Windows Phone, or certain Windows tablets). + // 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) { @@ -139,7 +131,7 @@ void OpenGLES::Initialize() 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 (e.g. on Surface RT). + // 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) { @@ -188,12 +180,17 @@ void OpenGLES::Reset() Initialize(); } -EGLSurface OpenGLES::CreateSurface(SwapChainPanel^ panel, const Size* renderSurfaceSize) +EGLSurface OpenGLES::CreateSurface(SwapChainPanel^ panel, const Size* renderSurfaceSize, const float* resolutionScale) { if (!panel) { throw Exception::CreateException(E_INVALIDARG, L"SwapChainPanel parameter is invalid"); } + + if (renderSurfaceSize != nullptr && resolutionScale != nullptr) + { + throw Exception::CreateException(E_INVALIDARG, L"A size and a scale can't both be specified"); + } EGLSurface surface = EGL_NO_SURFACE; @@ -207,12 +204,18 @@ EGLSurface OpenGLES::CreateSurface(SwapChainPanel^ panel, const Size* renderSurf // Create a PropertySet and initialize with the EGLNativeWindowType. PropertySet^ surfaceCreationProperties = ref new PropertySet(); - surfaceCreationProperties->Insert(ref new Platform::String(EGLNativeWindowTypeProperty), panel); + surfaceCreationProperties->Insert(ref new String(EGLNativeWindowTypeProperty), panel); // If a render surface size is specified, add it to the surface creation properties if (renderSurfaceSize != nullptr) { - surfaceCreationProperties->Insert(ref new Platform::String(EGLRenderSurfaceSizeProperty), PropertyValue::CreateSize(*renderSurfaceSize)); + surfaceCreationProperties->Insert(ref new String(EGLRenderSurfaceSizeProperty), PropertyValue::CreateSize(*renderSurfaceSize)); + } + + // If a resolution scale is specified, add it to the surface creation properties + if (resolutionScale != nullptr) + { + surfaceCreationProperties->Insert(ref new String(EGLRenderResolutionScaleProperty), PropertyValue::CreateSingle(*resolutionScale)); } surface = eglCreateWindowSurface(mEglDisplay, mEglConfig, reinterpret_cast(surfaceCreationProperties), surfaceAttributes); @@ -224,6 +227,12 @@ EGLSurface OpenGLES::CreateSurface(SwapChainPanel^ panel, const Size* renderSurf return surface; } +void OpenGLES::GetSurfaceDimensions(const EGLSurface surface, EGLint* width, EGLint* height) +{ + eglQuerySurface(mEglDisplay, surface, EGL_WIDTH, width); + eglQuerySurface(mEglDisplay, surface, EGL_HEIGHT, height); +} + void OpenGLES::DestroySurface(const EGLSurface surface) { if (mEglDisplay != EGL_NO_DISPLAY && surface != EGL_NO_SURFACE) diff --git a/templates/cpp-template-default/proj.win8.1-universal/App.Shared/OpenGLES.h b/templates/cpp-template-default/proj.win8.1-universal/App.Shared/OpenGLES.h index e2e7d7e8aa..a6942ccb1d 100644 --- a/templates/cpp-template-default/proj.win8.1-universal/App.Shared/OpenGLES.h +++ b/templates/cpp-template-default/proj.win8.1-universal/App.Shared/OpenGLES.h @@ -20,7 +20,6 @@ // OpenGL ES includes #include -#include // EGL includes #include @@ -34,7 +33,8 @@ public: OpenGLES(); ~OpenGLES(); - EGLSurface CreateSurface(Windows::UI::Xaml::Controls::SwapChainPanel^ panel, const Windows::Foundation::Size* renderSurfaceSize); + EGLSurface CreateSurface(Windows::UI::Xaml::Controls::SwapChainPanel^ panel, const Windows::Foundation::Size* renderSurfaceSize, const float* renderResolutionScale); + void GetSurfaceDimensions(const EGLSurface surface, EGLint *width, EGLint *height); void DestroySurface(const EGLSurface surface); void MakeCurrent(const EGLSurface surface); EGLBoolean SwapBuffers(const EGLSurface surface); diff --git a/templates/cpp-template-default/proj.win8.1-universal/App.Shared/OpenGLESPage.xaml.cpp b/templates/cpp-template-default/proj.win8.1-universal/App.Shared/OpenGLESPage.xaml.cpp index e19c6ac5f6..f55d7ba89f 100644 --- a/templates/cpp-template-default/proj.win8.1-universal/App.Shared/OpenGLESPage.xaml.cpp +++ b/templates/cpp-template-default/proj.win8.1-universal/App.Shared/OpenGLESPage.xaml.cpp @@ -24,7 +24,6 @@ using namespace cocos2d; using namespace Platform; using namespace Concurrency; using namespace Windows::Foundation; -using namespace Windows::Foundation::Collections; using namespace Windows::Graphics::Display; using namespace Windows::System::Threading; using namespace Windows::UI::Core; @@ -50,8 +49,6 @@ OpenGLESPage::OpenGLESPage() : OpenGLESPage::OpenGLESPage(OpenGLES* openGLES) : mOpenGLES(openGLES), mRenderSurface(EGL_NO_SURFACE), - mCustomRenderSurfaceSize(0,0), - mUseCustomRenderSurfaceSize(false), mCoreInput(nullptr), mDpi(0.0f), mDeviceLost(false), @@ -72,8 +69,6 @@ OpenGLESPage::OpenGLESPage(OpenGLES* openGLES) : window->CharacterReceived += ref new TypedEventHandler(this, &OpenGLESPage::OnCharacterReceived); - swapChainPanel->SizeChanged += - ref new Windows::UI::Xaml::SizeChangedEventHandler(this, &OpenGLESPage::OnSwapChainPanelSizeChanged); DisplayInformation^ currentDisplayInformation = DisplayInformation::GetForCurrentView(); @@ -85,8 +80,6 @@ OpenGLESPage::OpenGLESPage(OpenGLES* openGLES) : this->Loaded += ref new Windows::UI::Xaml::RoutedEventHandler(this, &OpenGLESPage::OnPageLoaded); - mSwapChainPanelSize = { swapChainPanel->RenderSize.Width, swapChainPanel->RenderSize.Height }; - #if _MSC_VER >= 1900 if (Windows::Foundation::Metadata::ApiInformation::IsTypePresent("Windows.UI.ViewManagement.StatusBar")) { @@ -158,166 +151,26 @@ void OpenGLESPage::OnPageLoaded(Platform::Object^ sender, Windows::UI::Xaml::Rou mVisible = true; } -void OpenGLESPage::OnPointerPressed(Object^ sender, PointerEventArgs^ e) -{ - bool isMouseEvent = e->CurrentPoint->PointerDevice->PointerDeviceType == Windows::Devices::Input::PointerDeviceType::Mouse; - if (mRenderer) - { - mRenderer->QueuePointerEvent(isMouseEvent ? PointerEventType::MousePressed : PointerEventType::PointerPressed, e); - } -} - -void OpenGLESPage::OnPointerMoved(Object^ sender, PointerEventArgs^ e) -{ - bool isMouseEvent = e->CurrentPoint->PointerDevice->PointerDeviceType == Windows::Devices::Input::PointerDeviceType::Mouse; - if (mRenderer) - { - mRenderer->QueuePointerEvent(isMouseEvent ? PointerEventType::MouseMoved : PointerEventType::PointerMoved, e); - } -} - -void OpenGLESPage::OnPointerReleased(Object^ sender, PointerEventArgs^ e) -{ - bool isMouseEvent = e->CurrentPoint->PointerDevice->PointerDeviceType == Windows::Devices::Input::PointerDeviceType::Mouse; - - if (mRenderer) - { - mRenderer->QueuePointerEvent(isMouseEvent ? PointerEventType::MouseReleased : PointerEventType::PointerReleased, e); - } -} - -void OpenGLESPage::OnPointerWheelChanged(Object^ sender, PointerEventArgs^ e) -{ - bool isMouseEvent = e->CurrentPoint->PointerDevice->PointerDeviceType == Windows::Devices::Input::PointerDeviceType::Mouse; - if (mRenderer && isMouseEvent) - { - mRenderer->QueuePointerEvent(PointerEventType::MouseWheelChanged, e); - } -} - -void OpenGLESPage::OnKeyPressed(CoreWindow^ sender, KeyEventArgs^ e) -{ - if (!e->KeyStatus.WasKeyDown) - { - //log("OpenGLESPage::OnKeyPressed %d", e->VirtualKey); - if (mRenderer) - { - mRenderer->QueueKeyboardEvent(WinRTKeyboardEventType::KeyPressed, e); - } - } -} - -void OpenGLESPage::OnCharacterReceived(CoreWindow^ sender, CharacterReceivedEventArgs^ e) -{ -#if 0 - if (!e->KeyStatus.WasKeyDown) - { - log("OpenGLESPage::OnCharacterReceived %d", e->KeyCode); - } -#endif -} - -void OpenGLESPage::OnKeyReleased(CoreWindow^ sender, KeyEventArgs^ e) -{ - //log("OpenGLESPage::OnKeyReleased %d", e->VirtualKey); - if (mRenderer) - { - mRenderer->QueueKeyboardEvent(WinRTKeyboardEventType::KeyReleased, e); - } -} - - -void OpenGLESPage::OnOrientationChanged(DisplayInformation^ sender, Object^ args) -{ - critical_section::scoped_lock lock(mSwapChainPanelSizeCriticalSection); - mOrientation = sender->CurrentOrientation; -} - -void OpenGLESPage::SetVisibility(bool isVisible) -{ - if (isVisible && mRenderSurface != EGL_NO_SURFACE) - { - std::unique_lock locker(mSleepMutex); - mVisible = true; - mSleepCondition.notify_one(); - } - else - { - mVisible = false; - } -} - -void OpenGLESPage::OnVisibilityChanged(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::VisibilityChangedEventArgs^ args) -{ - if (args->Visible && mRenderSurface != EGL_NO_SURFACE) - { - SetVisibility(true); - } - else - { - SetVisibility(false); - } -} - -#if (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) || _MSC_VER >= 1900 -/* - We set args->Handled = true to prevent the app from quitting when the back button is pressed. - This is because this back button event happens on the XAML UI thread and not the cocos2d-x UI thread. - We need to give the game developer a chance to decide to exit the app depending on where they - are in their game. They can receive the back button event by listening for the - EventKeyboard::KeyCode::KEY_ESCAPE event. - - The default behavior is to exit the app if the EventKeyboard::KeyCode::KEY_ESCAPE event - is not handled by the game. -*/ -void OpenGLESPage::OnBackButtonPressed(Object^ sender, BackPressedEventArgs^ args) -{ - if (mRenderer) - { - mRenderer->QueueBackButtonEvent(); - args->Handled = true; - } -} -#endif - -void OpenGLESPage::OnSwapChainPanelSizeChanged(Object^ sender, Windows::UI::Xaml::SizeChangedEventArgs^ e) -{ - // Size change events occur outside of the render thread. A lock is required when updating - // the swapchainpanel size - critical_section::scoped_lock lock(mSwapChainPanelSizeCriticalSection); - mSwapChainPanelSize = { e->NewSize.Width, e->NewSize.Height }; -} - -void OpenGLESPage::GetSwapChainPanelSize(GLsizei* width, GLsizei* height) -{ - critical_section::scoped_lock lock(mSwapChainPanelSizeCriticalSection); - // If a custom render surface size is specified, return its size instead of - // the swapchain panel size. - if (mUseCustomRenderSurfaceSize) - { - *width = static_cast(mCustomRenderSurfaceSize.Width); - *height = static_cast(mCustomRenderSurfaceSize.Height); - } - else - { - *width = static_cast(mSwapChainPanelSize.Width); - *height = static_cast(mSwapChainPanelSize.Height); - } -} - void OpenGLESPage::CreateRenderSurface() { if (mOpenGLES && mRenderSurface == EGL_NO_SURFACE) { - // - // A Custom render surface size can be specified by uncommenting the following lines. - // The render surface will be automatically scaled to fit the entire window. Using a - // smaller sized render surface can result in a performance gain. - // - //mCustomRenderSurfaceSize = Size(800, 600); - //mUseCustomRenderSurfaceSize = true; + // The app can configure the the SwapChainPanel which may boost performance. + // By default, this template uses the default configuration. + mRenderSurface = mOpenGLES->CreateSurface(swapChainPanel, nullptr, nullptr); - mRenderSurface = mOpenGLES->CreateSurface(swapChainPanel, mUseCustomRenderSurfaceSize ? &mCustomRenderSurfaceSize : nullptr); + // You can configure the SwapChainPanel to render at a lower resolution and be scaled up to + // the swapchain panel 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); + // mRenderSurface = mOpenGLES->CreateSurface(swapChainPanel, &customRenderSurfaceSize, nullptr); + // + // 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; + // mRenderSurface = mOpenGLES->CreateSurface(swapChainPanel, nullptr, &customResolutionScale); + // } } @@ -375,7 +228,7 @@ void OpenGLESPage::StartRenderLoop() GLsizei panelWidth = 0; GLsizei panelHeight = 0; - GetSwapChainPanelSize(&panelWidth, &panelHeight); + mOpenGLES->GetSurfaceDimensions(mRenderSurface, &panelWidth, &panelHeight); if (mRenderer.get() == nullptr) { @@ -412,7 +265,7 @@ void OpenGLESPage::StartRenderLoop() } } - GetSwapChainPanelSize(&panelWidth, &panelHeight); + mOpenGLES->GetSurfaceDimensions(mRenderSurface, &panelWidth, &panelHeight); mRenderer.get()->Draw(panelWidth, panelHeight, mDpi, mOrientation); // Recreate input dispatch @@ -425,7 +278,7 @@ void OpenGLESPage::StartRenderLoop() if (mRenderer->AppShouldExit()) { // run on main UI thread - swapChainPanel->Dispatcher->RunAsync(Windows::UI::Core::CoreDispatcherPriority::Normal, ref new DispatchedHandler([this]() + swapChainPanel->Dispatcher->RunAsync(Windows::UI::Core::CoreDispatcherPriority::High, ref new DispatchedHandler([=]() { TerminateApp(); })); @@ -491,4 +344,125 @@ void OpenGLESPage::StopRenderLoop() mSleepCondition.notify_one(); mRenderLoopWorker = nullptr; } -} \ No newline at end of file +} + +void OpenGLESPage::OnPointerPressed(Object^ sender, PointerEventArgs^ e) +{ + bool isMouseEvent = e->CurrentPoint->PointerDevice->PointerDeviceType == Windows::Devices::Input::PointerDeviceType::Mouse; + if (mRenderer) + { + mRenderer->QueuePointerEvent(isMouseEvent ? PointerEventType::MousePressed : PointerEventType::PointerPressed, e); + } +} + +void OpenGLESPage::OnPointerMoved(Object^ sender, PointerEventArgs^ e) +{ + bool isMouseEvent = e->CurrentPoint->PointerDevice->PointerDeviceType == Windows::Devices::Input::PointerDeviceType::Mouse; + if (mRenderer) + { + mRenderer->QueuePointerEvent(isMouseEvent ? PointerEventType::MouseMoved : PointerEventType::PointerMoved, e); + } +} + +void OpenGLESPage::OnPointerReleased(Object^ sender, PointerEventArgs^ e) +{ + bool isMouseEvent = e->CurrentPoint->PointerDevice->PointerDeviceType == Windows::Devices::Input::PointerDeviceType::Mouse; + + if (mRenderer) + { + mRenderer->QueuePointerEvent(isMouseEvent ? PointerEventType::MouseReleased : PointerEventType::PointerReleased, e); + } +} + +void OpenGLESPage::OnPointerWheelChanged(Object^ sender, PointerEventArgs^ e) +{ + bool isMouseEvent = e->CurrentPoint->PointerDevice->PointerDeviceType == Windows::Devices::Input::PointerDeviceType::Mouse; + if (mRenderer && isMouseEvent) + { + mRenderer->QueuePointerEvent(PointerEventType::MouseWheelChanged, e); + } +} + +void OpenGLESPage::OnKeyPressed(CoreWindow^ sender, KeyEventArgs^ e) +{ + if (!e->KeyStatus.WasKeyDown) + { + //log("OpenGLESPage::OnKeyPressed %d", e->VirtualKey); + if (mRenderer) + { + mRenderer->QueueKeyboardEvent(WinRTKeyboardEventType::KeyPressed, e); + } + } +} + +void OpenGLESPage::OnCharacterReceived(CoreWindow^ sender, CharacterReceivedEventArgs^ e) +{ +#if 0 + if (!e->KeyStatus.WasKeyDown) + { + log("OpenGLESPage::OnCharacterReceived %d", e->KeyCode); + } +#endif +} + +void OpenGLESPage::OnKeyReleased(CoreWindow^ sender, KeyEventArgs^ e) +{ + //log("OpenGLESPage::OnKeyReleased %d", e->VirtualKey); + if (mRenderer) + { + mRenderer->QueueKeyboardEvent(WinRTKeyboardEventType::KeyReleased, e); + } +} + + +void OpenGLESPage::OnOrientationChanged(DisplayInformation^ sender, Object^ args) +{ + mOrientation = sender->CurrentOrientation; +} + +void OpenGLESPage::SetVisibility(bool isVisible) +{ + if (isVisible && mRenderSurface != EGL_NO_SURFACE) + { + std::unique_lock locker(mSleepMutex); + mVisible = true; + mSleepCondition.notify_one(); + } + else + { + mVisible = false; + } +} + +void OpenGLESPage::OnVisibilityChanged(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::VisibilityChangedEventArgs^ args) +{ + if (args->Visible && mRenderSurface != EGL_NO_SURFACE) + { + SetVisibility(true); + } + else + { + SetVisibility(false); + } +} + +#if (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) || _MSC_VER >= 1900 +/* +We set args->Handled = true to prevent the app from quitting when the back button is pressed. +This is because this back button event happens on the XAML UI thread and not the cocos2d-x UI thread. +We need to give the game developer a chance to decide to exit the app depending on where they +are in their game. They can receive the back button event by listening for the +EventKeyboard::KeyCode::KEY_ESCAPE event. + +The default behavior is to exit the app if the EventKeyboard::KeyCode::KEY_ESCAPE event +is not handled by the game. +*/ +void OpenGLESPage::OnBackButtonPressed(Object^ sender, BackPressedEventArgs^ args) +{ + if (mRenderer) + { + mRenderer->QueueBackButtonEvent(); + args->Handled = true; + } +} +#endif \ No newline at end of file diff --git a/templates/cpp-template-default/proj.win8.1-universal/App.Shared/OpenGLESPage.xaml.h b/templates/cpp-template-default/proj.win8.1-universal/App.Shared/OpenGLESPage.xaml.h index 8fac8fdf0c..83fa8215c8 100644 --- a/templates/cpp-template-default/proj.win8.1-universal/App.Shared/OpenGLESPage.xaml.h +++ b/templates/cpp-template-default/proj.win8.1-universal/App.Shared/OpenGLESPage.xaml.h @@ -41,11 +41,9 @@ namespace CocosAppWinRT private: void OnPageLoaded(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e); void OnVisibilityChanged(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::VisibilityChangedEventArgs^ args); - void OnSwapChainPanelSizeChanged(Platform::Object^ sender, Windows::UI::Xaml::SizeChangedEventArgs^ e); #if (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) || _MSC_VER >= 1900 void OnBackButtonPressed(Platform::Object^ sender, Windows::Phone::UI::Input::BackPressedEventArgs^ args); #endif - void GetSwapChainPanelSize(GLsizei* width, GLsizei* height); void CreateRenderSurface(); void DestroyRenderSurface(); void RecoverFromLostDevice(); @@ -58,12 +56,6 @@ namespace CocosAppWinRT OpenGLES* mOpenGLES; std::shared_ptr mRenderer; - Windows::Foundation::Size mSwapChainPanelSize; - Concurrency::critical_section mSwapChainPanelSizeCriticalSection; - - Windows::Foundation::Size mCustomRenderSurfaceSize; - bool mUseCustomRenderSurfaceSize; - EGLSurface mRenderSurface; // This surface is associated with a swapChainPanel on the page Concurrency::critical_section mRenderSurfaceCriticalSection; Windows::Foundation::IAsyncAction^ mRenderLoopWorker; diff --git a/templates/js-template-default/frameworks/runtime-src/proj.win8.1-universal/App.Shared/OpenGLES.cpp b/templates/js-template-default/frameworks/runtime-src/proj.win8.1-universal/App.Shared/OpenGLES.cpp index 837e7a615f..2721b1ee4f 100644 --- a/templates/js-template-default/frameworks/runtime-src/proj.win8.1-universal/App.Shared/OpenGLES.cpp +++ b/templates/js-template-default/frameworks/runtime-src/proj.win8.1-universal/App.Shared/OpenGLES.cpp @@ -62,8 +62,8 @@ void OpenGLES::Initialize() // 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_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. @@ -78,7 +78,7 @@ void OpenGLES::Initialize() 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_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER, EGL_TRUE, EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE, EGL_TRUE, EGL_NONE, }; @@ -89,7 +89,7 @@ void OpenGLES::Initialize() // 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_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER, EGL_TRUE, EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE, EGL_TRUE, EGL_NONE, }; @@ -112,14 +112,7 @@ void OpenGLES::Initialize() // 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. // - // Note: On Windows Phone, we #ifdef out the first set of calls to eglPlatformDisplayEXT and eglInitialize. - // Windows Phones devices only support D3D11 Feature Level 9_3, but the Windows Phone emulator supports 11_0+. - // We use this #ifdef to limit the Phone emulator to Feature Level 9_3, making it behave more like - // real Windows Phone devices. - // If you wish to test Feature Level 10_0+ in the Windows Phone emulator then you should remove this #ifdef. - // -#if (WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP) // 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) @@ -128,9 +121,8 @@ void OpenGLES::Initialize() } if (eglInitialize(mEglDisplay, NULL, NULL) == EGL_FALSE) -#endif { - // This tries to initialize EGL to D3D11 Feature Level 9_3, if 10_0+ is unavailable (e.g. on Windows Phone, or certain Windows tablets). + // 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) { @@ -139,7 +131,7 @@ void OpenGLES::Initialize() 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 (e.g. on Surface RT). + // 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) { @@ -188,12 +180,17 @@ void OpenGLES::Reset() Initialize(); } -EGLSurface OpenGLES::CreateSurface(SwapChainPanel^ panel, const Size* renderSurfaceSize) +EGLSurface OpenGLES::CreateSurface(SwapChainPanel^ panel, const Size* renderSurfaceSize, const float* resolutionScale) { if (!panel) { throw Exception::CreateException(E_INVALIDARG, L"SwapChainPanel parameter is invalid"); } + + if (renderSurfaceSize != nullptr && resolutionScale != nullptr) + { + throw Exception::CreateException(E_INVALIDARG, L"A size and a scale can't both be specified"); + } EGLSurface surface = EGL_NO_SURFACE; @@ -207,12 +204,18 @@ EGLSurface OpenGLES::CreateSurface(SwapChainPanel^ panel, const Size* renderSurf // Create a PropertySet and initialize with the EGLNativeWindowType. PropertySet^ surfaceCreationProperties = ref new PropertySet(); - surfaceCreationProperties->Insert(ref new Platform::String(EGLNativeWindowTypeProperty), panel); + surfaceCreationProperties->Insert(ref new String(EGLNativeWindowTypeProperty), panel); // If a render surface size is specified, add it to the surface creation properties if (renderSurfaceSize != nullptr) { - surfaceCreationProperties->Insert(ref new Platform::String(EGLRenderSurfaceSizeProperty), PropertyValue::CreateSize(*renderSurfaceSize)); + surfaceCreationProperties->Insert(ref new String(EGLRenderSurfaceSizeProperty), PropertyValue::CreateSize(*renderSurfaceSize)); + } + + // If a resolution scale is specified, add it to the surface creation properties + if (resolutionScale != nullptr) + { + surfaceCreationProperties->Insert(ref new String(EGLRenderResolutionScaleProperty), PropertyValue::CreateSingle(*resolutionScale)); } surface = eglCreateWindowSurface(mEglDisplay, mEglConfig, reinterpret_cast(surfaceCreationProperties), surfaceAttributes); @@ -224,6 +227,12 @@ EGLSurface OpenGLES::CreateSurface(SwapChainPanel^ panel, const Size* renderSurf return surface; } +void OpenGLES::GetSurfaceDimensions(const EGLSurface surface, EGLint* width, EGLint* height) +{ + eglQuerySurface(mEglDisplay, surface, EGL_WIDTH, width); + eglQuerySurface(mEglDisplay, surface, EGL_HEIGHT, height); +} + void OpenGLES::DestroySurface(const EGLSurface surface) { if (mEglDisplay != EGL_NO_DISPLAY && surface != EGL_NO_SURFACE) diff --git a/templates/js-template-default/frameworks/runtime-src/proj.win8.1-universal/App.Shared/OpenGLES.h b/templates/js-template-default/frameworks/runtime-src/proj.win8.1-universal/App.Shared/OpenGLES.h index e2e7d7e8aa..a6942ccb1d 100644 --- a/templates/js-template-default/frameworks/runtime-src/proj.win8.1-universal/App.Shared/OpenGLES.h +++ b/templates/js-template-default/frameworks/runtime-src/proj.win8.1-universal/App.Shared/OpenGLES.h @@ -20,7 +20,6 @@ // OpenGL ES includes #include -#include // EGL includes #include @@ -34,7 +33,8 @@ public: OpenGLES(); ~OpenGLES(); - EGLSurface CreateSurface(Windows::UI::Xaml::Controls::SwapChainPanel^ panel, const Windows::Foundation::Size* renderSurfaceSize); + EGLSurface CreateSurface(Windows::UI::Xaml::Controls::SwapChainPanel^ panel, const Windows::Foundation::Size* renderSurfaceSize, const float* renderResolutionScale); + void GetSurfaceDimensions(const EGLSurface surface, EGLint *width, EGLint *height); void DestroySurface(const EGLSurface surface); void MakeCurrent(const EGLSurface surface); EGLBoolean SwapBuffers(const EGLSurface surface); diff --git a/templates/js-template-default/frameworks/runtime-src/proj.win8.1-universal/App.Shared/OpenGLESPage.xaml.cpp b/templates/js-template-default/frameworks/runtime-src/proj.win8.1-universal/App.Shared/OpenGLESPage.xaml.cpp index e19c6ac5f6..f55d7ba89f 100644 --- a/templates/js-template-default/frameworks/runtime-src/proj.win8.1-universal/App.Shared/OpenGLESPage.xaml.cpp +++ b/templates/js-template-default/frameworks/runtime-src/proj.win8.1-universal/App.Shared/OpenGLESPage.xaml.cpp @@ -24,7 +24,6 @@ using namespace cocos2d; using namespace Platform; using namespace Concurrency; using namespace Windows::Foundation; -using namespace Windows::Foundation::Collections; using namespace Windows::Graphics::Display; using namespace Windows::System::Threading; using namespace Windows::UI::Core; @@ -50,8 +49,6 @@ OpenGLESPage::OpenGLESPage() : OpenGLESPage::OpenGLESPage(OpenGLES* openGLES) : mOpenGLES(openGLES), mRenderSurface(EGL_NO_SURFACE), - mCustomRenderSurfaceSize(0,0), - mUseCustomRenderSurfaceSize(false), mCoreInput(nullptr), mDpi(0.0f), mDeviceLost(false), @@ -72,8 +69,6 @@ OpenGLESPage::OpenGLESPage(OpenGLES* openGLES) : window->CharacterReceived += ref new TypedEventHandler(this, &OpenGLESPage::OnCharacterReceived); - swapChainPanel->SizeChanged += - ref new Windows::UI::Xaml::SizeChangedEventHandler(this, &OpenGLESPage::OnSwapChainPanelSizeChanged); DisplayInformation^ currentDisplayInformation = DisplayInformation::GetForCurrentView(); @@ -85,8 +80,6 @@ OpenGLESPage::OpenGLESPage(OpenGLES* openGLES) : this->Loaded += ref new Windows::UI::Xaml::RoutedEventHandler(this, &OpenGLESPage::OnPageLoaded); - mSwapChainPanelSize = { swapChainPanel->RenderSize.Width, swapChainPanel->RenderSize.Height }; - #if _MSC_VER >= 1900 if (Windows::Foundation::Metadata::ApiInformation::IsTypePresent("Windows.UI.ViewManagement.StatusBar")) { @@ -158,166 +151,26 @@ void OpenGLESPage::OnPageLoaded(Platform::Object^ sender, Windows::UI::Xaml::Rou mVisible = true; } -void OpenGLESPage::OnPointerPressed(Object^ sender, PointerEventArgs^ e) -{ - bool isMouseEvent = e->CurrentPoint->PointerDevice->PointerDeviceType == Windows::Devices::Input::PointerDeviceType::Mouse; - if (mRenderer) - { - mRenderer->QueuePointerEvent(isMouseEvent ? PointerEventType::MousePressed : PointerEventType::PointerPressed, e); - } -} - -void OpenGLESPage::OnPointerMoved(Object^ sender, PointerEventArgs^ e) -{ - bool isMouseEvent = e->CurrentPoint->PointerDevice->PointerDeviceType == Windows::Devices::Input::PointerDeviceType::Mouse; - if (mRenderer) - { - mRenderer->QueuePointerEvent(isMouseEvent ? PointerEventType::MouseMoved : PointerEventType::PointerMoved, e); - } -} - -void OpenGLESPage::OnPointerReleased(Object^ sender, PointerEventArgs^ e) -{ - bool isMouseEvent = e->CurrentPoint->PointerDevice->PointerDeviceType == Windows::Devices::Input::PointerDeviceType::Mouse; - - if (mRenderer) - { - mRenderer->QueuePointerEvent(isMouseEvent ? PointerEventType::MouseReleased : PointerEventType::PointerReleased, e); - } -} - -void OpenGLESPage::OnPointerWheelChanged(Object^ sender, PointerEventArgs^ e) -{ - bool isMouseEvent = e->CurrentPoint->PointerDevice->PointerDeviceType == Windows::Devices::Input::PointerDeviceType::Mouse; - if (mRenderer && isMouseEvent) - { - mRenderer->QueuePointerEvent(PointerEventType::MouseWheelChanged, e); - } -} - -void OpenGLESPage::OnKeyPressed(CoreWindow^ sender, KeyEventArgs^ e) -{ - if (!e->KeyStatus.WasKeyDown) - { - //log("OpenGLESPage::OnKeyPressed %d", e->VirtualKey); - if (mRenderer) - { - mRenderer->QueueKeyboardEvent(WinRTKeyboardEventType::KeyPressed, e); - } - } -} - -void OpenGLESPage::OnCharacterReceived(CoreWindow^ sender, CharacterReceivedEventArgs^ e) -{ -#if 0 - if (!e->KeyStatus.WasKeyDown) - { - log("OpenGLESPage::OnCharacterReceived %d", e->KeyCode); - } -#endif -} - -void OpenGLESPage::OnKeyReleased(CoreWindow^ sender, KeyEventArgs^ e) -{ - //log("OpenGLESPage::OnKeyReleased %d", e->VirtualKey); - if (mRenderer) - { - mRenderer->QueueKeyboardEvent(WinRTKeyboardEventType::KeyReleased, e); - } -} - - -void OpenGLESPage::OnOrientationChanged(DisplayInformation^ sender, Object^ args) -{ - critical_section::scoped_lock lock(mSwapChainPanelSizeCriticalSection); - mOrientation = sender->CurrentOrientation; -} - -void OpenGLESPage::SetVisibility(bool isVisible) -{ - if (isVisible && mRenderSurface != EGL_NO_SURFACE) - { - std::unique_lock locker(mSleepMutex); - mVisible = true; - mSleepCondition.notify_one(); - } - else - { - mVisible = false; - } -} - -void OpenGLESPage::OnVisibilityChanged(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::VisibilityChangedEventArgs^ args) -{ - if (args->Visible && mRenderSurface != EGL_NO_SURFACE) - { - SetVisibility(true); - } - else - { - SetVisibility(false); - } -} - -#if (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) || _MSC_VER >= 1900 -/* - We set args->Handled = true to prevent the app from quitting when the back button is pressed. - This is because this back button event happens on the XAML UI thread and not the cocos2d-x UI thread. - We need to give the game developer a chance to decide to exit the app depending on where they - are in their game. They can receive the back button event by listening for the - EventKeyboard::KeyCode::KEY_ESCAPE event. - - The default behavior is to exit the app if the EventKeyboard::KeyCode::KEY_ESCAPE event - is not handled by the game. -*/ -void OpenGLESPage::OnBackButtonPressed(Object^ sender, BackPressedEventArgs^ args) -{ - if (mRenderer) - { - mRenderer->QueueBackButtonEvent(); - args->Handled = true; - } -} -#endif - -void OpenGLESPage::OnSwapChainPanelSizeChanged(Object^ sender, Windows::UI::Xaml::SizeChangedEventArgs^ e) -{ - // Size change events occur outside of the render thread. A lock is required when updating - // the swapchainpanel size - critical_section::scoped_lock lock(mSwapChainPanelSizeCriticalSection); - mSwapChainPanelSize = { e->NewSize.Width, e->NewSize.Height }; -} - -void OpenGLESPage::GetSwapChainPanelSize(GLsizei* width, GLsizei* height) -{ - critical_section::scoped_lock lock(mSwapChainPanelSizeCriticalSection); - // If a custom render surface size is specified, return its size instead of - // the swapchain panel size. - if (mUseCustomRenderSurfaceSize) - { - *width = static_cast(mCustomRenderSurfaceSize.Width); - *height = static_cast(mCustomRenderSurfaceSize.Height); - } - else - { - *width = static_cast(mSwapChainPanelSize.Width); - *height = static_cast(mSwapChainPanelSize.Height); - } -} - void OpenGLESPage::CreateRenderSurface() { if (mOpenGLES && mRenderSurface == EGL_NO_SURFACE) { - // - // A Custom render surface size can be specified by uncommenting the following lines. - // The render surface will be automatically scaled to fit the entire window. Using a - // smaller sized render surface can result in a performance gain. - // - //mCustomRenderSurfaceSize = Size(800, 600); - //mUseCustomRenderSurfaceSize = true; + // The app can configure the the SwapChainPanel which may boost performance. + // By default, this template uses the default configuration. + mRenderSurface = mOpenGLES->CreateSurface(swapChainPanel, nullptr, nullptr); - mRenderSurface = mOpenGLES->CreateSurface(swapChainPanel, mUseCustomRenderSurfaceSize ? &mCustomRenderSurfaceSize : nullptr); + // You can configure the SwapChainPanel to render at a lower resolution and be scaled up to + // the swapchain panel 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); + // mRenderSurface = mOpenGLES->CreateSurface(swapChainPanel, &customRenderSurfaceSize, nullptr); + // + // 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; + // mRenderSurface = mOpenGLES->CreateSurface(swapChainPanel, nullptr, &customResolutionScale); + // } } @@ -375,7 +228,7 @@ void OpenGLESPage::StartRenderLoop() GLsizei panelWidth = 0; GLsizei panelHeight = 0; - GetSwapChainPanelSize(&panelWidth, &panelHeight); + mOpenGLES->GetSurfaceDimensions(mRenderSurface, &panelWidth, &panelHeight); if (mRenderer.get() == nullptr) { @@ -412,7 +265,7 @@ void OpenGLESPage::StartRenderLoop() } } - GetSwapChainPanelSize(&panelWidth, &panelHeight); + mOpenGLES->GetSurfaceDimensions(mRenderSurface, &panelWidth, &panelHeight); mRenderer.get()->Draw(panelWidth, panelHeight, mDpi, mOrientation); // Recreate input dispatch @@ -425,7 +278,7 @@ void OpenGLESPage::StartRenderLoop() if (mRenderer->AppShouldExit()) { // run on main UI thread - swapChainPanel->Dispatcher->RunAsync(Windows::UI::Core::CoreDispatcherPriority::Normal, ref new DispatchedHandler([this]() + swapChainPanel->Dispatcher->RunAsync(Windows::UI::Core::CoreDispatcherPriority::High, ref new DispatchedHandler([=]() { TerminateApp(); })); @@ -491,4 +344,125 @@ void OpenGLESPage::StopRenderLoop() mSleepCondition.notify_one(); mRenderLoopWorker = nullptr; } -} \ No newline at end of file +} + +void OpenGLESPage::OnPointerPressed(Object^ sender, PointerEventArgs^ e) +{ + bool isMouseEvent = e->CurrentPoint->PointerDevice->PointerDeviceType == Windows::Devices::Input::PointerDeviceType::Mouse; + if (mRenderer) + { + mRenderer->QueuePointerEvent(isMouseEvent ? PointerEventType::MousePressed : PointerEventType::PointerPressed, e); + } +} + +void OpenGLESPage::OnPointerMoved(Object^ sender, PointerEventArgs^ e) +{ + bool isMouseEvent = e->CurrentPoint->PointerDevice->PointerDeviceType == Windows::Devices::Input::PointerDeviceType::Mouse; + if (mRenderer) + { + mRenderer->QueuePointerEvent(isMouseEvent ? PointerEventType::MouseMoved : PointerEventType::PointerMoved, e); + } +} + +void OpenGLESPage::OnPointerReleased(Object^ sender, PointerEventArgs^ e) +{ + bool isMouseEvent = e->CurrentPoint->PointerDevice->PointerDeviceType == Windows::Devices::Input::PointerDeviceType::Mouse; + + if (mRenderer) + { + mRenderer->QueuePointerEvent(isMouseEvent ? PointerEventType::MouseReleased : PointerEventType::PointerReleased, e); + } +} + +void OpenGLESPage::OnPointerWheelChanged(Object^ sender, PointerEventArgs^ e) +{ + bool isMouseEvent = e->CurrentPoint->PointerDevice->PointerDeviceType == Windows::Devices::Input::PointerDeviceType::Mouse; + if (mRenderer && isMouseEvent) + { + mRenderer->QueuePointerEvent(PointerEventType::MouseWheelChanged, e); + } +} + +void OpenGLESPage::OnKeyPressed(CoreWindow^ sender, KeyEventArgs^ e) +{ + if (!e->KeyStatus.WasKeyDown) + { + //log("OpenGLESPage::OnKeyPressed %d", e->VirtualKey); + if (mRenderer) + { + mRenderer->QueueKeyboardEvent(WinRTKeyboardEventType::KeyPressed, e); + } + } +} + +void OpenGLESPage::OnCharacterReceived(CoreWindow^ sender, CharacterReceivedEventArgs^ e) +{ +#if 0 + if (!e->KeyStatus.WasKeyDown) + { + log("OpenGLESPage::OnCharacterReceived %d", e->KeyCode); + } +#endif +} + +void OpenGLESPage::OnKeyReleased(CoreWindow^ sender, KeyEventArgs^ e) +{ + //log("OpenGLESPage::OnKeyReleased %d", e->VirtualKey); + if (mRenderer) + { + mRenderer->QueueKeyboardEvent(WinRTKeyboardEventType::KeyReleased, e); + } +} + + +void OpenGLESPage::OnOrientationChanged(DisplayInformation^ sender, Object^ args) +{ + mOrientation = sender->CurrentOrientation; +} + +void OpenGLESPage::SetVisibility(bool isVisible) +{ + if (isVisible && mRenderSurface != EGL_NO_SURFACE) + { + std::unique_lock locker(mSleepMutex); + mVisible = true; + mSleepCondition.notify_one(); + } + else + { + mVisible = false; + } +} + +void OpenGLESPage::OnVisibilityChanged(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::VisibilityChangedEventArgs^ args) +{ + if (args->Visible && mRenderSurface != EGL_NO_SURFACE) + { + SetVisibility(true); + } + else + { + SetVisibility(false); + } +} + +#if (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) || _MSC_VER >= 1900 +/* +We set args->Handled = true to prevent the app from quitting when the back button is pressed. +This is because this back button event happens on the XAML UI thread and not the cocos2d-x UI thread. +We need to give the game developer a chance to decide to exit the app depending on where they +are in their game. They can receive the back button event by listening for the +EventKeyboard::KeyCode::KEY_ESCAPE event. + +The default behavior is to exit the app if the EventKeyboard::KeyCode::KEY_ESCAPE event +is not handled by the game. +*/ +void OpenGLESPage::OnBackButtonPressed(Object^ sender, BackPressedEventArgs^ args) +{ + if (mRenderer) + { + mRenderer->QueueBackButtonEvent(); + args->Handled = true; + } +} +#endif \ No newline at end of file diff --git a/templates/js-template-default/frameworks/runtime-src/proj.win8.1-universal/App.Shared/OpenGLESPage.xaml.h b/templates/js-template-default/frameworks/runtime-src/proj.win8.1-universal/App.Shared/OpenGLESPage.xaml.h index 8fac8fdf0c..83fa8215c8 100644 --- a/templates/js-template-default/frameworks/runtime-src/proj.win8.1-universal/App.Shared/OpenGLESPage.xaml.h +++ b/templates/js-template-default/frameworks/runtime-src/proj.win8.1-universal/App.Shared/OpenGLESPage.xaml.h @@ -41,11 +41,9 @@ namespace CocosAppWinRT private: void OnPageLoaded(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e); void OnVisibilityChanged(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::VisibilityChangedEventArgs^ args); - void OnSwapChainPanelSizeChanged(Platform::Object^ sender, Windows::UI::Xaml::SizeChangedEventArgs^ e); #if (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) || _MSC_VER >= 1900 void OnBackButtonPressed(Platform::Object^ sender, Windows::Phone::UI::Input::BackPressedEventArgs^ args); #endif - void GetSwapChainPanelSize(GLsizei* width, GLsizei* height); void CreateRenderSurface(); void DestroyRenderSurface(); void RecoverFromLostDevice(); @@ -58,12 +56,6 @@ namespace CocosAppWinRT OpenGLES* mOpenGLES; std::shared_ptr mRenderer; - Windows::Foundation::Size mSwapChainPanelSize; - Concurrency::critical_section mSwapChainPanelSizeCriticalSection; - - Windows::Foundation::Size mCustomRenderSurfaceSize; - bool mUseCustomRenderSurfaceSize; - EGLSurface mRenderSurface; // This surface is associated with a swapChainPanel on the page Concurrency::critical_section mRenderSurfaceCriticalSection; Windows::Foundation::IAsyncAction^ mRenderLoopWorker;