aboutsummaryrefslogtreecommitdiffstats
path: root/support/hololens/ServoApp/OpenGLES.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'support/hololens/ServoApp/OpenGLES.cpp')
-rw-r--r--support/hololens/ServoApp/OpenGLES.cpp270
1 files changed, 270 insertions, 0 deletions
diff --git a/support/hololens/ServoApp/OpenGLES.cpp b/support/hololens/ServoApp/OpenGLES.cpp
new file mode 100644
index 00000000000..31467a4ed60
--- /dev/null
+++ b/support/hololens/ServoApp/OpenGLES.cpp
@@ -0,0 +1,270 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
+
+#include "pch.h"
+#include "logs.h"
+#include "OpenGLES.h"
+
+using namespace winrt::Windows::UI::Xaml::Controls;
+using namespace winrt::Windows::Foundation;
+using namespace winrt::Windows::Foundation::Collections;
+
+OpenGLES::OpenGLES()
+ : mEglConfig(nullptr), mEglDisplay(EGL_NO_DISPLAY),
+ mEglContext(EGL_NO_CONTEXT) {
+ log("OpenGLES::OpenGLES()");
+ Initialize();
+}
+
+OpenGLES::~OpenGLES() { Cleanup(); }
+
+void OpenGLES::Initialize() {
+ const EGLint configAttributes[] = {EGL_RENDERABLE_TYPE,
+ EGL_OPENGL_ES2_BIT,
+ EGL_RED_SIZE,
+ 8,
+ EGL_GREEN_SIZE,
+ 8,
+ EGL_BLUE_SIZE,
+ 8,
+ EGL_ALPHA_SIZE,
+ 8,
+ EGL_DEPTH_SIZE,
+ 24,
+ EGL_STENCIL_SIZE,
+ 8,
+ EGL_NONE};
+
+ const EGLint contextAttributes[] = {EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE};
+
+ // Based on Angle MS template.
+
+ 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,
+ };
+
+ // 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 winrt::hresult_error(
+ 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 winrt::hresult_error(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 winrt::hresult_error(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 winrt::hresult_error(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 winrt::hresult_error(E_FAIL, L"Failed to initialize EGL");
+ }
+ }
+ }
+
+ EGLint numConfigs = 0;
+ if ((eglChooseConfig(mEglDisplay, configAttributes, &mEglConfig, 1,
+ &numConfigs) == EGL_FALSE) ||
+ (numConfigs == 0)) {
+ throw winrt::hresult_error(E_FAIL, L"Failed to choose first EGLConfig");
+ }
+
+ mEglContext = eglCreateContext(mEglDisplay, mEglConfig, EGL_NO_CONTEXT,
+ contextAttributes);
+ if (mEglContext == EGL_NO_CONTEXT) {
+ throw winrt::hresult_error(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();
+}
+
+// FIXME: simplify this. Duplicating code with CreateSurface(SwapChainPanel)
+EGLSurface
+OpenGLES::CreateSurface(winrt::Windows::UI::Core::CoreWindow const &cwin) {
+ EGLSurface surface = EGL_NO_SURFACE;
+
+ const EGLint surfaceAttributes[] = {EGL_ANGLE_SURFACE_RENDER_TO_BACK_BUFFER,
+ EGL_TRUE, EGL_NONE};
+
+ PropertySet surfaceCreationProperties;
+
+ surfaceCreationProperties.Insert(EGLNativeWindowTypeProperty, cwin);
+ // How to set size and or scale:
+ // Insert(EGLRenderSurfaceSizeProperty),
+ // PropertyValue::CreateSize(*renderSurfaceSize));
+ // Insert(EGLRenderResolutionScaleProperty),
+ // PropertyValue::CreateSingle(*resolutionScale));
+
+ EGLNativeWindowType win = static_cast<EGLNativeWindowType>(
+ winrt::get_abi(surfaceCreationProperties));
+ surface =
+ eglCreateWindowSurface(mEglDisplay, mEglConfig, win, surfaceAttributes);
+
+ if (surface == EGL_NO_SURFACE) {
+ throw winrt::hresult_error(E_FAIL, L"Failed to create EGL surface");
+ }
+
+ return surface;
+}
+
+EGLSurface OpenGLES::CreateSurface(SwapChainPanel const &panel) {
+ EGLSurface surface = EGL_NO_SURFACE;
+
+ const EGLint surfaceAttributes[] = {EGL_ANGLE_SURFACE_RENDER_TO_BACK_BUFFER,
+ EGL_TRUE, EGL_NONE};
+
+ PropertySet surfaceCreationProperties;
+
+ surfaceCreationProperties.Insert(EGLNativeWindowTypeProperty, panel);
+ // How to set size and or scale:
+ // Insert(EGLRenderSurfaceSizeProperty),
+ // PropertyValue::CreateSize(*renderSurfaceSize));
+ // Insert(EGLRenderResolutionScaleProperty),
+ // PropertyValue::CreateSingle(*resolutionScale));
+
+ EGLNativeWindowType win = static_cast<EGLNativeWindowType>(
+ winrt::get_abi(surfaceCreationProperties));
+ surface =
+ eglCreateWindowSurface(mEglDisplay, mEglConfig, win, surfaceAttributes);
+
+ if (surface == EGL_NO_SURFACE) {
+ throw winrt::hresult_error(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 winrt::hresult_error(E_FAIL, L"Failed to make EGLSurface current");
+ }
+}
+
+EGLBoolean OpenGLES::SwapBuffers(const EGLSurface surface) {
+ return (eglSwapBuffers(mEglDisplay, surface));
+}