mirror of
https://github.com/servo/servo.git
synced 2025-08-03 12:40:06 +01:00
Add new hololens code (winrt + D3D immersive mode example)
This commit is contained in:
parent
13872eb254
commit
24d2213780
51 changed files with 4691 additions and 27 deletions
270
support/hololens/ServoApp/OpenGLES.cpp
Normal file
270
support/hololens/ServoApp/OpenGLES.cpp
Normal file
|
@ -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));
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue