123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255 |
- /*
- * cocos2d-x http://www.cocos2d-x.org
- *
- * Copyright (c) 2010-2014 - cocos2d-x community
- *
- * Portions Copyright (c) Microsoft Open Technologies, Inc.
- * All Rights Reserved
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and limitations under the License.
- */
- #include "OpenGLES.h"
- using namespace Platform;
- using namespace Windows::UI::Xaml::Controls;
- using namespace Windows::Foundation;
- using namespace Windows::Foundation::Collections;
- OpenGLES::OpenGLES() :
- mEglDisplay(EGL_NO_DISPLAY),
- mEglContext(EGL_NO_CONTEXT),
- mEglConfig(nullptr)
- {
- Initialize();
- }
- OpenGLES::~OpenGLES()
- {
- Cleanup();
- }
- void OpenGLES::Initialize()
- {
- const EGLint configAttributes[] =
- {
- EGL_RED_SIZE, 8,
- EGL_GREEN_SIZE, 8,
- EGL_BLUE_SIZE, 8,
- EGL_ALPHA_SIZE, 8,
- EGL_DEPTH_SIZE, 8,
- EGL_STENCIL_SIZE, 8,
- EGL_NONE
- };
- const EGLint contextAttributes[] =
- {
- EGL_CONTEXT_CLIENT_VERSION, 2,
- EGL_NONE
- };
- const EGLint defaultDisplayAttributes[] =
- {
- // These are the default display attributes, used to request ANGLE's D3D11 renderer.
- // eglInitialize will only succeed with these attributes if the hardware supports D3D11 Feature Level 10_0+.
- EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
- // EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER is an optimization that can have large performance benefits on mobile devices.
- // Its syntax is subject to change, though. Please update your Visual Studio templates if you experience compilation issues with it.
- EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER, EGL_TRUE,
-
- // EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE is an option that enables ANGLE to automatically call
- // the IDXGIDevice3::Trim method on behalf of the application when it gets suspended.
- // Calling IDXGIDevice3::Trim when an application is suspended is a Windows Store application certification requirement.
- EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE, EGL_TRUE,
- EGL_NONE,
- };
-
- const EGLint fl9_3DisplayAttributes[] =
- {
- // These can be used to request ANGLE's D3D11 renderer, with D3D11 Feature Level 9_3.
- // These attributes are used if the call to eglInitialize fails with the default display attributes.
- EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
- EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, 9,
- EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, 3,
- EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER, EGL_TRUE,
- EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE, EGL_TRUE,
- EGL_NONE,
- };
- const EGLint warpDisplayAttributes[] =
- {
- // These attributes can be used to request D3D11 WARP.
- // They are used if eglInitialize fails with both the default display attributes and the 9_3 display attributes.
- EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
- EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE,
- EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER, EGL_TRUE,
- EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE, EGL_TRUE,
- EGL_NONE,
- };
-
- EGLConfig config = NULL;
- // eglGetPlatformDisplayEXT is an alternative to eglGetDisplay. It allows us to pass in display attributes, used to configure D3D11.
- PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT = reinterpret_cast<PFNEGLGETPLATFORMDISPLAYEXTPROC>(eglGetProcAddress("eglGetPlatformDisplayEXT"));
- if (!eglGetPlatformDisplayEXT)
- {
- throw Exception::CreateException(E_FAIL, L"Failed to get function eglGetPlatformDisplayEXT");
- }
- //
- // To initialize the display, we make three sets of calls to eglGetPlatformDisplayEXT and eglInitialize, with varying
- // parameters passed to eglGetPlatformDisplayEXT:
- // 1) The first calls uses "defaultDisplayAttributes" as a parameter. This corresponds to D3D11 Feature Level 10_0+.
- // 2) If eglInitialize fails for step 1 (e.g. because 10_0+ isn't supported by the default GPU), then we try again
- // using "fl9_3DisplayAttributes". This corresponds to D3D11 Feature Level 9_3.
- // 3) If eglInitialize fails for step 2 (e.g. because 9_3+ isn't supported by the default GPU), then we try again
- // using "warpDisplayAttributes". This corresponds to D3D11 Feature Level 11_0 on WARP, a D3D11 software rasterizer.
- //
-
- // This tries to initialize EGL to D3D11 Feature Level 10_0+. See above comment for details.
- mEglDisplay = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY, defaultDisplayAttributes);
- if (mEglDisplay == EGL_NO_DISPLAY)
- {
- throw Exception::CreateException(E_FAIL, L"Failed to get EGL display");
- }
- if (eglInitialize(mEglDisplay, NULL, NULL) == EGL_FALSE)
- {
- // This tries to initialize EGL to D3D11 Feature Level 9_3, if 10_0+ is unavailable (e.g. on some mobile devices).
- mEglDisplay = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY, fl9_3DisplayAttributes);
- if (mEglDisplay == EGL_NO_DISPLAY)
- {
- throw Exception::CreateException(E_FAIL, L"Failed to get EGL display");
- }
- if (eglInitialize(mEglDisplay, NULL, NULL) == EGL_FALSE)
- {
- // This initializes EGL to D3D11 Feature Level 11_0 on WARP, if 9_3+ is unavailable on the default GPU.
- mEglDisplay = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY, warpDisplayAttributes);
- if (mEglDisplay == EGL_NO_DISPLAY)
- {
- throw Exception::CreateException(E_FAIL, L"Failed to get EGL display");
- }
- if (eglInitialize(mEglDisplay, NULL, NULL) == EGL_FALSE)
- {
- // If all of the calls to eglInitialize returned EGL_FALSE then an error has occurred.
- throw Exception::CreateException(E_FAIL, L"Failed to initialize EGL");
- }
- }
- }
- EGLint numConfigs = 0;
- if ((eglChooseConfig(mEglDisplay, configAttributes, &mEglConfig, 1, &numConfigs) == EGL_FALSE) || (numConfigs == 0))
- {
- throw Exception::CreateException(E_FAIL, L"Failed to choose first EGLConfig");
- }
- mEglContext = eglCreateContext(mEglDisplay, mEglConfig, EGL_NO_CONTEXT, contextAttributes);
- if (mEglContext == EGL_NO_CONTEXT)
- {
- throw Exception::CreateException(E_FAIL, L"Failed to create EGL context");
- }
- }
- void OpenGLES::Cleanup()
- {
- if (mEglDisplay != EGL_NO_DISPLAY && mEglContext != EGL_NO_CONTEXT)
- {
- eglDestroyContext(mEglDisplay, mEglContext);
- mEglContext = EGL_NO_CONTEXT;
- }
- if (mEglDisplay != EGL_NO_DISPLAY)
- {
- eglTerminate(mEglDisplay);
- mEglDisplay = EGL_NO_DISPLAY;
- }
- }
- void OpenGLES::Reset()
- {
- Cleanup();
- Initialize();
- }
- 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[] =
- {
- // EGL_ANGLE_SURFACE_RENDER_TO_BACK_BUFFER is part of the same optimization as EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER (see above).
- // If you have compilation issues with it then please update your Visual Studio templates.
- EGL_ANGLE_SURFACE_RENDER_TO_BACK_BUFFER, EGL_TRUE,
- EGL_NONE
- };
-
- // Create a PropertySet and initialize with the EGLNativeWindowType.
- PropertySet^ surfaceCreationProperties = ref new PropertySet();
- 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 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);
- if (surface == EGL_NO_SURFACE)
- {
- throw Exception::CreateException(E_FAIL, L"Failed to create EGL surface");
- }
- 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)
- {
- eglDestroySurface(mEglDisplay, surface);
- }
- }
- void OpenGLES::MakeCurrent(const EGLSurface surface)
- {
- if (eglMakeCurrent(mEglDisplay, surface, surface, mEglContext) == EGL_FALSE)
- {
- throw Exception::CreateException(E_FAIL, L"Failed to make EGLSurface current");
- }
- }
- EGLBoolean OpenGLES::SwapBuffers(const EGLSurface surface)
- {
- return (eglSwapBuffers(mEglDisplay, surface));
- }
|