diff options
Diffstat (limited to 'support')
-rw-r--r-- | support/magicleap/Servo2D/code/src/Servo2D.cpp | 6 | ||||
-rw-r--r-- | support/magicleap/Servo3D/Servo3D.cpp | 257 | ||||
-rw-r--r-- | support/magicleap/Servo3D/Servo3D.mabu | 24 | ||||
-rw-r--r-- | support/magicleap/Servo3D/Servo3D.package | 8 | ||||
-rw-r--r-- | support/magicleap/Servo3D/fonts.xml | 19 | ||||
-rw-r--r-- | support/magicleap/Servo3D/manifest.xml | 23 |
6 files changed, 335 insertions, 2 deletions
diff --git a/support/magicleap/Servo2D/code/src/Servo2D.cpp b/support/magicleap/Servo2D/code/src/Servo2D.cpp index a1859c6411d..2ba1d3a17cb 100644 --- a/support/magicleap/Servo2D/code/src/Servo2D.cpp +++ b/support/magicleap/Servo2D/code/src/Servo2D.cpp @@ -66,7 +66,7 @@ void keyboard(Servo2D* app, bool visible) { } // The functions Servo provides for hooking up to the ML. -extern "C" ServoInstance* init_servo(EGLContext, EGLSurface, EGLDisplay, +extern "C" ServoInstance* init_servo(EGLContext, EGLSurface, EGLDisplay, bool landscape, Servo2D*, MLLogger, MLHistoryUpdate, MLURLUpdate, MLKeyboard, const char* url, const char* args, int width, int height, float hidpi); extern "C" void heartbeat_servo(ServoInstance*); @@ -174,7 +174,9 @@ int Servo2D::init() { EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY); // Hook into servo - servo_ = init_servo(ctx, surf, dpy, this, logger, history, url, keyboard, uri_, args_, VIEWPORT_W, VIEWPORT_H, HIDPI); + servo_ = init_servo(ctx, surf, dpy, true, + this, logger, history, url, keyboard, uri_, args_, + VIEWPORT_W, VIEWPORT_H, HIDPI); if (!servo_) { ML_LOG(Error, "Servo2D Failed to init servo instance"); abort(); diff --git a/support/magicleap/Servo3D/Servo3D.cpp b/support/magicleap/Servo3D/Servo3D.cpp new file mode 100644 index 00000000000..3c095e6f757 --- /dev/null +++ b/support/magicleap/Servo3D/Servo3D.cpp @@ -0,0 +1,257 @@ +/* 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/. */ + +// The immersive mode Servo magicleap demo + +#include <stdio.h> +#include <stdlib.h> + +#include <unistd.h> +#include <sys/syscall.h> + +#ifndef EGL_EGLEXT_PROTOTYPES +#define EGL_EGLEXT_PROTOTYPES +#endif + +#include <EGL/egl.h> +#include <EGL/eglext.h> + +#ifndef GL_GLEXT_PROTOTYPES +#define GL_GLEXT_PROTOTYPES +#endif + +#include <GLES3/gl3.h> +#include <GLES3/gl3ext.h> + +#include <ml_graphics.h> +#include <ml_head_tracking.h> +#include <ml_perception.h> +#include <ml_fileinfo.h> +#include <ml_lifecycle.h> +#include <ml_logging.h> +#include <ml_privileges.h> + +// Constants +const char application_name[] = "com.mozilla.servo3d"; + +// A function which calls the ML logger, suitable for passing into Servo +typedef void (*MLLogger)(MLLogLevel lvl, char* msg); +void logger(MLLogLevel lvl, char* msg) { + if (MLLoggingLogLevelIsEnabled(lvl)) { + MLLoggingLog(lvl, "Servo3D", msg); + } +} + +// Entry points to servo +typedef struct Opaque ServoInstance; +extern "C" ServoInstance* init_servo(EGLContext, EGLSurface, EGLDisplay, bool landscape, + void*, MLLogger, void*, void*, void*, + const char* url, const char* args, + int width, int height, float hidpi); +extern "C" void heartbeat_servo(ServoInstance*); +extern "C" void discard_servo(ServoInstance*); + +// The Servo3D app +struct Servo3D { + ServoInstance* servo; + bool running; +}; + +// Callbacks +static void onStop(void* app) +{ + ML_LOG(Info, "%s: On stop called.", application_name); + Servo3D* servo3d = (Servo3D*)app; + servo3d->running = false; +} + +static void onPause(void* app) +{ + ML_LOG(Info, "%s: On pause called.", application_name); + // Treat a pause the same as a stop + Servo3D* servo3d = (Servo3D*)app; + servo3d->running = false; +} + +static void onResume(void* app) +{ + ML_LOG(Info, "%s: On resume called.", application_name); +} + +static void onNewInitArg(void* app) +{ + // TODO: call servo_navigate when a new URL arrives + ML_LOG(Info, "%s: On new init arg called.", application_name); +} + +int main() { + // set up graphics surface + ML_LOG(Info, "%s: Initializing EGL.", application_name); + EGLDisplay egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY); + + EGLint major = 4; + EGLint minor = 0; + eglInitialize(egl_display, &major, &minor); + + // The GL API used should match https://github.com/servo/rust-offscreen-rendering-context/blob/fcbbb4d40dac5e969233c1519151ad5e07b7f22e/src/platform/with_egl/native_gl_context.rs#L14 + eglBindAPI(EGL_OPENGL_ES_API); + + // Should match https://github.com/servo/rust-offscreen-rendering-context/blob/fcbbb4d40dac5e969233c1519151ad5e07b7f22e/src/platform/with_egl/utils.rs#L46 + EGLint config_attribs[] = { + EGL_RED_SIZE, 8, + EGL_GREEN_SIZE, 8, + EGL_BLUE_SIZE, 8, + EGL_ALPHA_SIZE, 0, + EGL_DEPTH_SIZE, 24, + EGL_STENCIL_SIZE, 0, + EGL_SURFACE_TYPE, EGL_PBUFFER_BIT, + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, + EGL_NONE + }; + EGLConfig egl_config = nullptr; + EGLint config_size = 0; + eglChooseConfig(egl_display, config_attribs, &egl_config, 1, &config_size); + if (config_size < 1) { + ML_LOG(Error, "%s: Failed to choose EGL config. (%x)", application_name, eglGetError()); + return -1; + } + + // Should match https://github.com/servo/rust-offscreen-rendering-context/blob/fcbbb4d40dac5e969233c1519151ad5e07b7f22e/src/platform/with_egl/native_gl_context.rs#L47 + EGLint context_attribs[] = { + EGL_CONTEXT_CLIENT_VERSION, 3, + EGL_NONE + }; + EGLContext egl_context = eglCreateContext(egl_display, egl_config, EGL_NO_CONTEXT, context_attribs); + if (EGL_NO_CONTEXT == egl_context) { + ML_LOG(Error, "%s: Failed to initialize EGL context. (%x)", application_name, eglGetError()); + return -1; + } + + EGLint surface_attribs[] = { + EGL_WIDTH, 1280, + EGL_HEIGHT, 960, + EGL_NONE + }; + EGLSurface egl_surface = eglCreatePbufferSurface(egl_display, egl_config, surface_attribs); + if (EGL_NO_SURFACE == egl_surface) { + ML_LOG(Error, "%s: Failed to initialize EGL surface. (%x)", application_name, eglGetError()); + return -1; + } + + if (!eglMakeCurrent(egl_display, egl_surface, egl_surface, egl_context)) { + ML_LOG(Error, "%s: Failed to make EGL surface current. (%x)", application_name, eglGetError()); + return -1; + } + + GLenum read_status = glCheckFramebufferStatus(GL_READ_FRAMEBUFFER); + GLenum draw_status = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); + if ((read_status != GL_FRAMEBUFFER_COMPLETE) || (draw_status != GL_FRAMEBUFFER_COMPLETE)) { + ML_LOG(Error, "%s: Incomplete GL framebuffer. (%x, %x)", application_name, read_status, draw_status); + return -1; + } + + ML_LOG(Info, "%s: Initialized EGL.", application_name); + + // The app + Servo3D app = { nullptr, true }; + + // let system know our app has started + MLLifecycleCallbacks lifecycle_callbacks = {}; + lifecycle_callbacks.on_stop = onStop; + lifecycle_callbacks.on_pause = onPause; + lifecycle_callbacks.on_resume = onResume; + lifecycle_callbacks.on_new_initarg = onNewInitArg; + + if (MLResult_Ok != MLLifecycleInit(&lifecycle_callbacks, &app)) { + ML_LOG(Error, "%s: Failed to initialize lifecycle.", application_name); + return -1; + } + + // Get the file argument if there is one + MLLifecycleInitArgList* arg_list = nullptr; + const MLLifecycleInitArg* arg = nullptr; + const char* url = "https://webvr.info/samples/03-vr-presentation.html"; + int64_t arg_list_len = 0; + + if (MLResult_Ok != MLLifecycleGetInitArgList(&arg_list)) { + ML_LOG(Error, "%s: Failed to get init args.", application_name); + return -1; + } + + if (MLResult_Ok == MLLifecycleGetInitArgListLength(arg_list, &arg_list_len)) { + if (arg_list_len) { + if (MLResult_Ok != MLLifecycleGetInitArgByIndex(arg_list, 0, &arg)) { + ML_LOG(Error, "%s: Failed to get init arg.", application_name); + return -1; + } + + if (MLResult_Ok != MLLifecycleGetInitArgUri(arg, &url)) { + ML_LOG(Error, "%s: Failed to get init arg uri.", application_name); + return -1; + } + } + } + + // init_servo calls MLLifecycleSetReadyIndication() + + // Check privileges + if (MLResult_Ok != MLPrivilegesStartup()) { + ML_LOG(Error, "%s: Failed to initialize privileges.", application_name); + return -1; + } + if (MLPrivilegesRequestPrivilege(MLPrivilegeID_LowLatencyLightwear) != MLPrivilegesResult_Granted) { + ML_LOG(Error, "Privilege %d denied.", MLPrivilegeID_LowLatencyLightwear); + return -1; + } + if (MLPrivilegesRequestPrivilege(MLPrivilegeID_Internet) != MLPrivilegesResult_Granted) { + ML_LOG(Error, "Privilege %d denied.", MLPrivilegeID_Internet); + return -1; + } + + // initialize perception system + MLPerceptionSettings perception_settings; + if (MLResult_Ok != MLPerceptionInitSettings(&perception_settings)) { + ML_LOG(Error, "%s: Failed to initialize perception.", application_name); + } + + if (MLResult_Ok != MLPerceptionStartup(&perception_settings)) { + ML_LOG(Error, "%s: Failed to startup perception.", application_name); + return -1; + } + + ML_LOG(Info, "%s: Initializing servo for %s.", application_name, url); + + // Initialize servo + app.servo = init_servo(egl_context, egl_surface, egl_display, false, + &app, logger, nullptr, nullptr, nullptr, + url, + "--pref dom.webvr.enabled --pref dom.gamepad.enabled", + 500, 500, 1.0); + + // At this point we can free the memory for the arg list, since the url isn't used after this + MLLifecycleFreeInitArgList(&arg_list); + + // Pin the main thread to the Denver core + // https://forum.magicleap.com/hc/en-us/community/posts/360043120832-How-many-CPUs-does-an-immersive-app-have-access-to- + uint32_t DenverCoreAffinityMask = 1 << 2; // Denver core is CPU2 + pid_t ThreadId = gettid(); + syscall(__NR_sched_setaffinity, ThreadId, sizeof(DenverCoreAffinityMask), &DenverCoreAffinityMask); + + // Run the demo! + ML_LOG(Info, "%s: Begin demo.", application_name); + while (app.running) { + ML_LOG(Debug, "%s: heartbeat.", application_name); + heartbeat_servo(app.servo); + // TODO: check heart_racing. + } + ML_LOG(Info, "%s: End demo.", application_name); + + // Shut down + discard_servo(app.servo); + MLPerceptionShutdown(); + eglDestroyContext(egl_display, egl_context); + eglTerminate(egl_display); + + return 0; +} diff --git a/support/magicleap/Servo3D/Servo3D.mabu b/support/magicleap/Servo3D/Servo3D.mabu new file mode 100644 index 00000000000..4cd3aa1dbed --- /dev/null +++ b/support/magicleap/Servo3D/Servo3D.mabu @@ -0,0 +1,24 @@ +KIND = program + +SRCS = \ + Servo3D.cpp + +USES = ml_sdk + +LIBPATHS.debug = \ + ../../../target/magicleap/aarch64-linux-android/debug + +LIBPATHS.release = \ + ../../../target/magicleap/aarch64-linux-android/release + +LIBPATHS.device = \ + $(MLSDK)/lumin/stl/libc++-lumin/lib \ + +STLIBS = \ + mlservo + +SHLIBS = \ + c++ \ + ml_privileges \ + log \ + z diff --git a/support/magicleap/Servo3D/Servo3D.package b/support/magicleap/Servo3D/Servo3D.package new file mode 100644 index 00000000000..77212bc48eb --- /dev/null +++ b/support/magicleap/Servo3D/Servo3D.package @@ -0,0 +1,8 @@ +REFS = Servo3D + +DATAS = \ + fonts.xml : etc/fonts.xml + +# Servo SEGVs if we don't set the debuggable flag in the mpk's taildata +# https://github.com/servo/servo/issues/22188 +OPTIONS=package/debuggable/on diff --git a/support/magicleap/Servo3D/fonts.xml b/support/magicleap/Servo3D/fonts.xml new file mode 100644 index 00000000000..c994a7e456b --- /dev/null +++ b/support/magicleap/Servo3D/fonts.xml @@ -0,0 +1,19 @@ +<familyset> + <family name="sans-serif"> + <font weight="300" style="normal">/system/etc/ml/kali/Fonts/Lomino/Light/LominoUI_Lt.ttf</font> + <font weight="300" style="italic">/system/etc/ml/kali/Fonts/Lomino/LightItalic/LominoUI_LtIt.ttf</font> + <font weight="400" style="normal">/system/etc/ml/kali/Fonts/Lomino/Regular/LominoUI_Rg.ttf</font> + <font weight="400" style="italic">/system/etc/ml/kali/Fonts/Lomino/Italic/LominoUI_It.ttf</font> + <font weight="500" style="normal">/system/etc/ml/kali/Fonts/Lomino/Medium/LominoUI_Md.ttf</font> + <font weight="500" style="italic">/system/etc/ml/kali/Fonts/Lomino/MediumItalic/LominoUI_MdIt.ttf</font> + <font weight="700" style="normal">/system/etc/ml/kali/Fonts/Lomino/Bold/LominoUI_Bd.ttf</font> + <font weight="700" style="italic">/system/etc/ml/kali/Fonts/Lomino/BoldItalic/LominoUI_BdIt.ttf</font> + <font weight="900" style="normal">/system/etc/ml/kali/Fonts/Lomino/ExtraBold/LominoUI_XBd.ttf</font> + <font weight="900" style="italic">/system/etc/ml/kali/Fonts/Lomino/ExtraBoldItalic/LominoUI_XBdIt.ttf</font> + </family> + + <alias name="arial" to="sans-serif" /> + <alias name="helvetica" to="sans-serif" /> + <alias name="tahoma" to="sans-serif" /> + <alias name="verdana" to="sans-serif" /> +</familyset> diff --git a/support/magicleap/Servo3D/manifest.xml b/support/magicleap/Servo3D/manifest.xml new file mode 100644 index 00000000000..0ae7ca2441c --- /dev/null +++ b/support/magicleap/Servo3D/manifest.xml @@ -0,0 +1,23 @@ +<manifest + xmlns:ml="magicleap" + ml:package="com.mozilla.servo3d" + ml:version_code="1" + ml:version_name="1.0"> + <application + ml:visible_name="Servo3D" + ml:sdk_version="0.20.0" + ml:min_api_level="4"> + <component + ml:name=".servo3d.fullscreen" + ml:visible_name="Servo3D" + ml:binary_name="bin/Servo3D" + ml:type="Fullscreen"> + <icon + ml:model_folder="Icon/Model/" + ml:portal_folder="Icon/Portal/" /> + </component> + <uses-privilege ml:name="ControllerPose"/> + <uses-privilege ml:name="Internet"/> + <uses-privilege ml:name="LowLatencyLightwear"/> + </application> +</manifest> |