aboutsummaryrefslogtreecommitdiffstats
path: root/support
diff options
context:
space:
mode:
Diffstat (limited to 'support')
-rw-r--r--support/magicleap/Servo2D/code/src/Servo2D.cpp6
-rw-r--r--support/magicleap/Servo3D/Servo3D.cpp257
-rw-r--r--support/magicleap/Servo3D/Servo3D.mabu24
-rw-r--r--support/magicleap/Servo3D/Servo3D.package8
-rw-r--r--support/magicleap/Servo3D/fonts.xml19
-rw-r--r--support/magicleap/Servo3D/manifest.xml23
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>