OpenGLES.cpp 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. /*
  2. * cocos2d-x http://www.cocos2d-x.org
  3. *
  4. * Copyright (c) 2010-2014 - cocos2d-x community
  5. *
  6. * Portions Copyright (c) Microsoft Open Technologies, Inc.
  7. * All Rights Reserved
  8. *
  9. * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
  10. * You may obtain a copy of the License at
  11. *
  12. * http://www.apache.org/licenses/LICENSE-2.0
  13. *
  14. * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
  15. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  16. * See the License for the specific language governing permissions and limitations under the License.
  17. */
  18. #include "OpenGLES.h"
  19. using namespace Platform;
  20. using namespace Windows::UI::Xaml::Controls;
  21. using namespace Windows::Foundation;
  22. using namespace Windows::Foundation::Collections;
  23. OpenGLES::OpenGLES() :
  24. mEglDisplay(EGL_NO_DISPLAY),
  25. mEglContext(EGL_NO_CONTEXT),
  26. mEglConfig(nullptr)
  27. {
  28. Initialize();
  29. }
  30. OpenGLES::~OpenGLES()
  31. {
  32. Cleanup();
  33. }
  34. void OpenGLES::Initialize()
  35. {
  36. const EGLint configAttributes[] =
  37. {
  38. EGL_RED_SIZE, 8,
  39. EGL_GREEN_SIZE, 8,
  40. EGL_BLUE_SIZE, 8,
  41. EGL_ALPHA_SIZE, 8,
  42. EGL_DEPTH_SIZE, 8,
  43. EGL_STENCIL_SIZE, 8,
  44. EGL_NONE
  45. };
  46. const EGLint contextAttributes[] =
  47. {
  48. EGL_CONTEXT_CLIENT_VERSION, 2,
  49. EGL_NONE
  50. };
  51. const EGLint defaultDisplayAttributes[] =
  52. {
  53. // These are the default display attributes, used to request ANGLE's D3D11 renderer.
  54. // eglInitialize will only succeed with these attributes if the hardware supports D3D11 Feature Level 10_0+.
  55. EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
  56. // EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER is an optimization that can have large performance benefits on mobile devices.
  57. // Its syntax is subject to change, though. Please update your Visual Studio templates if you experience compilation issues with it.
  58. EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER, EGL_TRUE,
  59. // EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE is an option that enables ANGLE to automatically call
  60. // the IDXGIDevice3::Trim method on behalf of the application when it gets suspended.
  61. // Calling IDXGIDevice3::Trim when an application is suspended is a Windows Store application certification requirement.
  62. EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE, EGL_TRUE,
  63. EGL_NONE,
  64. };
  65. const EGLint fl9_3DisplayAttributes[] =
  66. {
  67. // These can be used to request ANGLE's D3D11 renderer, with D3D11 Feature Level 9_3.
  68. // These attributes are used if the call to eglInitialize fails with the default display attributes.
  69. EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
  70. EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, 9,
  71. EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, 3,
  72. EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER, EGL_TRUE,
  73. EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE, EGL_TRUE,
  74. EGL_NONE,
  75. };
  76. const EGLint warpDisplayAttributes[] =
  77. {
  78. // These attributes can be used to request D3D11 WARP.
  79. // They are used if eglInitialize fails with both the default display attributes and the 9_3 display attributes.
  80. EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
  81. EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE,
  82. EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER, EGL_TRUE,
  83. EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE, EGL_TRUE,
  84. EGL_NONE,
  85. };
  86. EGLConfig config = NULL;
  87. // eglGetPlatformDisplayEXT is an alternative to eglGetDisplay. It allows us to pass in display attributes, used to configure D3D11.
  88. PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT = reinterpret_cast<PFNEGLGETPLATFORMDISPLAYEXTPROC>(eglGetProcAddress("eglGetPlatformDisplayEXT"));
  89. if (!eglGetPlatformDisplayEXT)
  90. {
  91. throw Exception::CreateException(E_FAIL, L"Failed to get function eglGetPlatformDisplayEXT");
  92. }
  93. //
  94. // To initialize the display, we make three sets of calls to eglGetPlatformDisplayEXT and eglInitialize, with varying
  95. // parameters passed to eglGetPlatformDisplayEXT:
  96. // 1) The first calls uses "defaultDisplayAttributes" as a parameter. This corresponds to D3D11 Feature Level 10_0+.
  97. // 2) If eglInitialize fails for step 1 (e.g. because 10_0+ isn't supported by the default GPU), then we try again
  98. // using "fl9_3DisplayAttributes". This corresponds to D3D11 Feature Level 9_3.
  99. // 3) If eglInitialize fails for step 2 (e.g. because 9_3+ isn't supported by the default GPU), then we try again
  100. // using "warpDisplayAttributes". This corresponds to D3D11 Feature Level 11_0 on WARP, a D3D11 software rasterizer.
  101. //
  102. // This tries to initialize EGL to D3D11 Feature Level 10_0+. See above comment for details.
  103. mEglDisplay = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY, defaultDisplayAttributes);
  104. if (mEglDisplay == EGL_NO_DISPLAY)
  105. {
  106. throw Exception::CreateException(E_FAIL, L"Failed to get EGL display");
  107. }
  108. if (eglInitialize(mEglDisplay, NULL, NULL) == EGL_FALSE)
  109. {
  110. // This tries to initialize EGL to D3D11 Feature Level 9_3, if 10_0+ is unavailable (e.g. on some mobile devices).
  111. mEglDisplay = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY, fl9_3DisplayAttributes);
  112. if (mEglDisplay == EGL_NO_DISPLAY)
  113. {
  114. throw Exception::CreateException(E_FAIL, L"Failed to get EGL display");
  115. }
  116. if (eglInitialize(mEglDisplay, NULL, NULL) == EGL_FALSE)
  117. {
  118. // This initializes EGL to D3D11 Feature Level 11_0 on WARP, if 9_3+ is unavailable on the default GPU.
  119. mEglDisplay = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY, warpDisplayAttributes);
  120. if (mEglDisplay == EGL_NO_DISPLAY)
  121. {
  122. throw Exception::CreateException(E_FAIL, L"Failed to get EGL display");
  123. }
  124. if (eglInitialize(mEglDisplay, NULL, NULL) == EGL_FALSE)
  125. {
  126. // If all of the calls to eglInitialize returned EGL_FALSE then an error has occurred.
  127. throw Exception::CreateException(E_FAIL, L"Failed to initialize EGL");
  128. }
  129. }
  130. }
  131. EGLint numConfigs = 0;
  132. if ((eglChooseConfig(mEglDisplay, configAttributes, &mEglConfig, 1, &numConfigs) == EGL_FALSE) || (numConfigs == 0))
  133. {
  134. throw Exception::CreateException(E_FAIL, L"Failed to choose first EGLConfig");
  135. }
  136. mEglContext = eglCreateContext(mEglDisplay, mEglConfig, EGL_NO_CONTEXT, contextAttributes);
  137. if (mEglContext == EGL_NO_CONTEXT)
  138. {
  139. throw Exception::CreateException(E_FAIL, L"Failed to create EGL context");
  140. }
  141. }
  142. void OpenGLES::Cleanup()
  143. {
  144. if (mEglDisplay != EGL_NO_DISPLAY && mEglContext != EGL_NO_CONTEXT)
  145. {
  146. eglDestroyContext(mEglDisplay, mEglContext);
  147. mEglContext = EGL_NO_CONTEXT;
  148. }
  149. if (mEglDisplay != EGL_NO_DISPLAY)
  150. {
  151. eglTerminate(mEglDisplay);
  152. mEglDisplay = EGL_NO_DISPLAY;
  153. }
  154. }
  155. void OpenGLES::Reset()
  156. {
  157. Cleanup();
  158. Initialize();
  159. }
  160. EGLSurface OpenGLES::CreateSurface(SwapChainPanel^ panel, const Size* renderSurfaceSize, const float* resolutionScale)
  161. {
  162. if (!panel)
  163. {
  164. throw Exception::CreateException(E_INVALIDARG, L"SwapChainPanel parameter is invalid");
  165. }
  166. if (renderSurfaceSize != nullptr && resolutionScale != nullptr)
  167. {
  168. throw Exception::CreateException(E_INVALIDARG, L"A size and a scale can't both be specified");
  169. }
  170. EGLSurface surface = EGL_NO_SURFACE;
  171. const EGLint surfaceAttributes[] =
  172. {
  173. // EGL_ANGLE_SURFACE_RENDER_TO_BACK_BUFFER is part of the same optimization as EGL_ANGLE_DISPLAY_ALLOW_RENDER_TO_BACK_BUFFER (see above).
  174. // If you have compilation issues with it then please update your Visual Studio templates.
  175. EGL_ANGLE_SURFACE_RENDER_TO_BACK_BUFFER, EGL_TRUE,
  176. EGL_NONE
  177. };
  178. // Create a PropertySet and initialize with the EGLNativeWindowType.
  179. PropertySet^ surfaceCreationProperties = ref new PropertySet();
  180. surfaceCreationProperties->Insert(ref new String(EGLNativeWindowTypeProperty), panel);
  181. // If a render surface size is specified, add it to the surface creation properties
  182. if (renderSurfaceSize != nullptr)
  183. {
  184. surfaceCreationProperties->Insert(ref new String(EGLRenderSurfaceSizeProperty), PropertyValue::CreateSize(*renderSurfaceSize));
  185. }
  186. // If a resolution scale is specified, add it to the surface creation properties
  187. if (resolutionScale != nullptr)
  188. {
  189. surfaceCreationProperties->Insert(ref new String(EGLRenderResolutionScaleProperty), PropertyValue::CreateSingle(*resolutionScale));
  190. }
  191. surface = eglCreateWindowSurface(mEglDisplay, mEglConfig, reinterpret_cast<IInspectable*>(surfaceCreationProperties), surfaceAttributes);
  192. if (surface == EGL_NO_SURFACE)
  193. {
  194. throw Exception::CreateException(E_FAIL, L"Failed to create EGL surface");
  195. }
  196. return surface;
  197. }
  198. void OpenGLES::GetSurfaceDimensions(const EGLSurface surface, EGLint* width, EGLint* height)
  199. {
  200. eglQuerySurface(mEglDisplay, surface, EGL_WIDTH, width);
  201. eglQuerySurface(mEglDisplay, surface, EGL_HEIGHT, height);
  202. }
  203. void OpenGLES::DestroySurface(const EGLSurface surface)
  204. {
  205. if (mEglDisplay != EGL_NO_DISPLAY && surface != EGL_NO_SURFACE)
  206. {
  207. eglDestroySurface(mEglDisplay, surface);
  208. }
  209. }
  210. void OpenGLES::MakeCurrent(const EGLSurface surface)
  211. {
  212. if (eglMakeCurrent(mEglDisplay, surface, surface, mEglContext) == EGL_FALSE)
  213. {
  214. throw Exception::CreateException(E_FAIL, L"Failed to make EGLSurface current");
  215. }
  216. }
  217. EGLBoolean OpenGLES::SwapBuffers(const EGLSurface surface)
  218. {
  219. return (eglSwapBuffers(mEglDisplay, surface));
  220. }