updated cocos2d-x/angle template files to version 0edf96a2f54a43d068244a86aaf9133c1bf71fe5

This commit is contained in:
Dale Stammen 2015-10-16 15:36:34 -07:00
parent ce88dbdee4
commit fdebb373b1
17 changed files with 672 additions and 773 deletions

View File

@ -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,13 +180,18 @@ 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;
const EGLint surfaceAttributes[] =
@ -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<IInspectable*>(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)

View File

@ -20,7 +20,6 @@
// OpenGL ES includes
#include <GLES3/gl3.h>
#include <GLES3/gl3ext.h>
// EGL includes
#include <EGL/egl.h>
@ -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);

View File

@ -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<CoreWindow^, CharacterReceivedEventArgs^>(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<std::mutex> 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<GLsizei>(mCustomRenderSurfaceSize.Width);
*height = static_cast<GLsizei>(mCustomRenderSurfaceSize.Height);
}
else
{
*width = static_cast<GLsizei>(mSwapChainPanelSize.Width);
*height = static_cast<GLsizei>(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();
}));
@ -492,3 +345,124 @@ void OpenGLESPage::StopRenderLoop()
mRenderLoopWorker = nullptr;
}
}
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<std::mutex> 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

View File

@ -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<Cocos2dRenderer> 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;

View File

@ -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

View File

@ -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,13 +180,18 @@ 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;
const EGLint surfaceAttributes[] =
@ -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<IInspectable*>(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)

View File

@ -20,7 +20,6 @@
// OpenGL ES includes
#include <GLES3/gl3.h>
#include <GLES3/gl3ext.h>
// EGL includes
#include <EGL/egl.h>
@ -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);

View File

@ -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<CoreWindow^, CharacterReceivedEventArgs^>(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<std::mutex> 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<GLsizei>(mCustomRenderSurfaceSize.Width);
*height = static_cast<GLsizei>(mCustomRenderSurfaceSize.Height);
}
else
{
*width = static_cast<GLsizei>(mSwapChainPanelSize.Width);
*height = static_cast<GLsizei>(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();
}));
@ -492,3 +345,124 @@ void OpenGLESPage::StopRenderLoop()
mRenderLoopWorker = nullptr;
}
}
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<std::mutex> 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

View File

@ -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<Cocos2dRenderer> 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;

View File

@ -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,13 +180,18 @@ 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;
const EGLint surfaceAttributes[] =
@ -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<IInspectable*>(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)

View File

@ -20,7 +20,6 @@
// OpenGL ES includes
#include <GLES3/gl3.h>
#include <GLES3/gl3ext.h>
// EGL includes
#include <EGL/egl.h>
@ -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);

View File

@ -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<CoreWindow^, CharacterReceivedEventArgs^>(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<std::mutex> 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<GLsizei>(mCustomRenderSurfaceSize.Width);
*height = static_cast<GLsizei>(mCustomRenderSurfaceSize.Height);
}
else
{
*width = static_cast<GLsizei>(mSwapChainPanelSize.Width);
*height = static_cast<GLsizei>(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();
}));
@ -492,3 +345,124 @@ void OpenGLESPage::StopRenderLoop()
mRenderLoopWorker = nullptr;
}
}
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<std::mutex> 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

View File

@ -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<Cocos2dRenderer> 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;

View File

@ -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,13 +180,18 @@ 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;
const EGLint surfaceAttributes[] =
@ -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<IInspectable*>(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)

View File

@ -20,7 +20,6 @@
// OpenGL ES includes
#include <GLES3/gl3.h>
#include <GLES3/gl3ext.h>
// EGL includes
#include <EGL/egl.h>
@ -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);

View File

@ -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<CoreWindow^, CharacterReceivedEventArgs^>(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<std::mutex> 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<GLsizei>(mCustomRenderSurfaceSize.Width);
*height = static_cast<GLsizei>(mCustomRenderSurfaceSize.Height);
}
else
{
*width = static_cast<GLsizei>(mSwapChainPanelSize.Width);
*height = static_cast<GLsizei>(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();
}));
@ -492,3 +345,124 @@ void OpenGLESPage::StopRenderLoop()
mRenderLoopWorker = nullptr;
}
}
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<std::mutex> 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

View File

@ -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<Cocos2dRenderer> 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;