diff options
34 files changed, 1601 insertions, 7 deletions
diff --git a/Cargo.lock b/Cargo.lock index 6aac1d1109d..1058bfdac39 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1902,6 +1902,16 @@ dependencies = [ ] [[package]] +name = "libmlservo" +version = "0.0.1" +dependencies = [ + "libservo 0.0.1", + "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "servo-egl 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] name = "libservo" version = "0.0.1" dependencies = [ @@ -2234,13 +2244,13 @@ dependencies = [ "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "mozjs_sys 0.61.1 (registry+https://github.com/rust-lang/crates.io-index)", + "mozjs_sys 0.61.2 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "mozjs_sys" -version = "0.61.1" +version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bindgen 0.39.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -4506,7 +4516,7 @@ dependencies = [ "checksum mitochondria 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9de3eca27871df31c33b807f834b94ef7d000956f57aa25c5aed9c5f0aae8f6f" "checksum mozangle 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "45a8a18a41cfab0fde25cc2f43ea89064d211a0fbb33225b8ff93ab20406e0e7" "checksum mozjs 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bd0bdded611cb03c8ca638e0b663befe67eb7fbcb1fe2dfd25061656ee4ff365" -"checksum mozjs_sys 0.61.1 (registry+https://github.com/rust-lang/crates.io-index)" = "070dd9dcd0be8b524fe4f6fcc791d56d630518652f98c2b152fdebe28eb71a5b" +"checksum mozjs_sys 0.61.2 (registry+https://github.com/rust-lang/crates.io-index)" = "28276d28cc79226f3a26c790f00c8ce74459d097d3698f17df05ab9f683c1e52" "checksum msdos_time 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "aad9dfe950c057b1bfe9c1f2aa51583a8468ef2a5baba2ebbe06d775efeb7729" "checksum muldiv 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "451a9a05d2a32c566c897835e0ea95cf79ed2fdfe957924045a1721a36c9980f" "checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" diff --git a/Cargo.toml b/Cargo.toml index bb452af5fa6..f20f4d1194e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,6 +2,7 @@ members = [ "ports/servo", "ports/libsimpleservo/", + "ports/libmlservo/", "tests/unit/*", ] exclude = [".cargo"] diff --git a/components/gfx/platform/freetype/android/font_list.rs b/components/gfx/platform/freetype/android/font_list.rs index ebca244078e..9cf9c512e09 100644 --- a/components/gfx/platform/freetype/android/font_list.rs +++ b/components/gfx/platform/freetype/android/font_list.rs @@ -127,7 +127,7 @@ struct FontList { impl FontList { fn new() -> FontList { // Possible paths containing the font mapping xml file. - let paths = ["/etc/fonts.xml", "/system/etc/system_fonts.xml"]; + let paths = ["/etc/fonts.xml", "/system/etc/system_fonts.xml", "/package/etc/fonts.xml"]; // Try to load and parse paths until one of them success. let mut result = None; @@ -136,6 +136,10 @@ impl FontList { !result.is_some() }); + if result.is_none() { + warn!("Couldn't find font list"); + } + match result { Some(result) => result, // If no xml mapping file is found fallback to some default @@ -209,6 +213,7 @@ impl FontList { let alternatives = [ ("sans-serif", "Roboto-Regular.ttf"), ("Droid Sans", "DroidSans.ttf"), + ("Lomino", "/system/etc/ml/kali/Fonts/Lomino/Medium/LominoUI_Md.ttf"), ]; alternatives @@ -225,7 +230,11 @@ impl FontList { // All Android fonts are located in /system/fonts fn font_absolute_path(filename: &str) -> String { - format!("/system/fonts/{}", filename) + if filename.starts_with("/") { + String::from(filename) + } else { + format!("/system/fonts/{}", filename) + } } fn find_family(&self, name: &str) -> Option<&FontFamily> { diff --git a/ports/libmlservo/Cargo.toml b/ports/libmlservo/Cargo.toml new file mode 100644 index 00000000000..793435db093 --- /dev/null +++ b/ports/libmlservo/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "libmlservo" +version = "0.0.1" +authors = ["The Servo Project Developers"] +license = "MPL-2.0" +publish = false + +[lib] +name = "mlservo" +crate-type = ["staticlib"] +test = false +bench = false + +[dependencies] +libservo = { path = "../../components/servo" } +log = "0.4" +servo-egl = "0.2" +smallvec = "0.6" + diff --git a/ports/libmlservo/src/lib.rs b/ports/libmlservo/src/lib.rs new file mode 100644 index 00000000000..109279c7ee2 --- /dev/null +++ b/ports/libmlservo/src/lib.rs @@ -0,0 +1,232 @@ +/* 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 http://mozilla.org/MPL/2.0/. */ + +extern crate egl; +#[macro_use] extern crate log; +extern crate servo; +extern crate smallvec; + +use egl::eglext::eglGetProcAddress; +use servo::BrowserId; +use servo::Servo; +use servo::compositing::windowing::AnimationState; +use servo::compositing::windowing::EmbedderCoordinates; +use servo::compositing::windowing::WindowEvent; +use servo::compositing::windowing::WindowMethods; +use servo::embedder_traits::EventLoopWaker; +use servo::embedder_traits::resources::Resource; +use servo::embedder_traits::resources::ResourceReaderMethods; +use servo::euclid::Length; +use servo::euclid::TypedPoint2D; +use servo::euclid::TypedRect; +use servo::euclid::TypedScale; +use servo::euclid::TypedSize2D; +use servo::gl; +use servo::gl::Gl; +use servo::gl::GlesFns; +use servo::servo_url::ServoUrl; +use servo::style_traits::DevicePixel; +use smallvec::SmallVec; +use std::ffi::CStr; +use std::ffi::CString; +use std::io::Write; +use std::os::raw::c_char; +use std::os::raw::c_void; +use std::path::PathBuf; +use std::rc::Rc; + +type EGLContext = *const c_void; +type EGLSurface = *const c_void; +type EGLDisplay = *const c_void; + +type ServoInstance = *mut c_void; + +#[repr(u32)] +pub enum MLLogLevel { + Fatal = 0, + Error = 1, + Warning = 2, + Info = 3, + Debug = 4, + Verbose = 5, +} + +#[repr(transparent)] +pub struct MLLogger(extern "C" fn (MLLogLevel, *const c_char)); + +const LOG_LEVEL: log::LevelFilter = log::LevelFilter::Info; + +#[no_mangle] +pub unsafe extern "C" fn init_servo(_ctxt: EGLContext, + _surf: EGLSurface, + _disp: EGLDisplay, + logger: MLLogger, + url: *const c_char, + width: u32, + height: u32, + hidpi: f32) -> ServoInstance +{ + // Servo initialization goes here! + servo::embedder_traits::resources::set(Box::new(ResourceReaderInstance::new())); + let _ = log::set_boxed_logger(Box::new(logger)); + log::set_max_level(LOG_LEVEL); + let gl = GlesFns::load_with(|symbol| { + let cstr = CString::new(symbol).expect("Failed to convert GL symbol to a char*"); + eglGetProcAddress(cstr.as_ptr() as _) as _ + }); + + info!("OpenGL version {}", gl.get_string(gl::VERSION)); + let window = Rc::new(WindowInstance::new(gl, width, height, hidpi)); + + info!("Starting servo"); + let mut servo = Box::new(Servo::new(window)); + + let browser_id = BrowserId::new(); + let blank_url = ServoUrl::parse("about:blank").expect("Failed to parse about:blank!"); + let url = CStr::from_ptr(url).to_str().unwrap_or("about:blank"); + let url = ServoUrl::parse(url).unwrap_or(blank_url); + servo.handle_events(vec![ + WindowEvent::NewBrowser(url, browser_id), + ]); + + Box::into_raw(servo) as ServoInstance +} + +#[no_mangle] +pub unsafe extern "C" fn heartbeat_servo(servo: ServoInstance) { + // Servo heartbeat goes here! + if let Some(servo) = (servo as *mut Servo<WindowInstance>).as_mut() { + servo.handle_events(vec![]); + } +} + +#[no_mangle] +pub unsafe extern "C" fn discard_servo(servo: ServoInstance) { + // Servo drop goes here! + if !servo.is_null() { + Box::from_raw(servo as *mut Servo<WindowInstance>); + } +} + +struct WindowInstance { + gl: Rc<Gl>, + width: u32, + height: u32, + hidpi: f32, +} + +impl WindowInstance { + fn new(gl: Rc<Gl>, width: u32, height: u32, hidpi: f32) -> WindowInstance { + WindowInstance { + gl: gl, + width: width, + height: height, + hidpi: hidpi, + } + } +} + +impl WindowMethods for WindowInstance { + fn present(&self) { + } + + fn prepare_for_composite(&self, _w: Length<u32, DevicePixel>, _h: Length<u32, DevicePixel>) -> bool { + true + } + + fn gl(&self) -> Rc<Gl> { + self.gl.clone() + } + + fn create_event_loop_waker(&self) -> Box<EventLoopWaker> { + Box::new(EventLoopWakerInstance::new()) + } + + fn get_coordinates(&self) -> EmbedderCoordinates { + EmbedderCoordinates { + hidpi_factor: TypedScale::new(self.hidpi), + screen: TypedSize2D::new(self.width, self.height), + screen_avail: TypedSize2D::new(self.width, self.height), + window: (TypedSize2D::new(self.width, self.height), TypedPoint2D::new(0, 0)), + framebuffer: TypedSize2D::new(self.width, self.height), + viewport: TypedRect::new(TypedPoint2D::new(0, 0), TypedSize2D::new(self.width, self.height)), + } + } + + fn set_animation_state(&self, _state: AnimationState) { + } +} + +struct EventLoopWakerInstance; + +impl EventLoopWakerInstance { + fn new() -> EventLoopWakerInstance { + EventLoopWakerInstance + } +} + +impl EventLoopWaker for EventLoopWakerInstance { + fn clone(&self) -> Box<EventLoopWaker + Send> { + Box::new(EventLoopWakerInstance) + } + + fn wake(&self) { + } +} + +struct ResourceReaderInstance; + +impl ResourceReaderInstance { + fn new() -> ResourceReaderInstance { + ResourceReaderInstance + } +} + +impl ResourceReaderMethods for ResourceReaderInstance { + fn read(&self, res: Resource) -> Vec<u8> { + Vec::from(match res { + Resource::Preferences => &include_bytes!("../../../resources/prefs.json")[..], + Resource::HstsPreloadList => &include_bytes!("../../../resources/hsts_preload.json")[..], + Resource::SSLCertificates => &include_bytes!("../../../resources/certs")[..], + Resource::BadCertHTML => &include_bytes!("../../../resources/badcert.html")[..], + Resource::NetErrorHTML => &include_bytes!("../../../resources/neterror.html")[..], + Resource::UserAgentCSS => &include_bytes!("../../../resources/user-agent.css")[..], + Resource::ServoCSS => &include_bytes!("../../../resources/servo.css")[..], + Resource::PresentationalHintsCSS => &include_bytes!("../../../resources/presentational-hints.css")[..], + Resource::QuirksModeCSS => &include_bytes!("../../../resources/quirks-mode.css")[..], + Resource::RippyPNG => &include_bytes!("../../../resources/rippy.png")[..], + Resource::DomainList => &include_bytes!("../../../resources/public_domains.txt")[..], + Resource::BluetoothBlocklist => &include_bytes!("../../../resources/gatt_blocklist.txt")[..], + }) + } + + fn sandbox_access_files(&self) -> Vec<PathBuf> { + vec![] + } + + fn sandbox_access_files_dirs(&self) -> Vec<PathBuf> { + vec![] + } +} + +impl log::Log for MLLogger { + fn enabled(&self, metadata: &log::Metadata) -> bool { + metadata.level() <= LOG_LEVEL + } + + fn log(&self, record: &log::Record) { + let lvl = match record.level() { + log::Level::Error => MLLogLevel::Error, + log::Level::Warn => MLLogLevel::Warning, + log::Level::Info => MLLogLevel::Info, + log::Level::Debug => MLLogLevel::Debug, + log::Level::Trace => MLLogLevel::Verbose, + }; + let mut msg = SmallVec::<[c_char; 128]>::new(); + write!(msg, "{}\0", record.args()); + (self.0)(lvl, &msg[0] as *const _ as *const _); + } + + fn flush(&self) {} +} diff --git a/python/servo/build_commands.py b/python/servo/build_commands.py index a241763542c..de9bf1b42cb 100644 --- a/python/servo/build_commands.py +++ b/python/servo/build_commands.py @@ -165,6 +165,10 @@ class MachCommands(CommandBase): default=None, action='store_true', help='Build for Android') + @CommandArgument('--magicleap', + default=None, + action='store_true', + help='Build for Magic Leap') @CommandArgument('--no-package', action='store_true', help='For Android, disable packaging into a .apk after building') @@ -189,7 +193,7 @@ class MachCommands(CommandBase): action='store_true', help='Build the libsimpleservo library instead of the servo executable') def build(self, target=None, release=False, dev=False, jobs=None, - features=None, android=None, no_package=False, verbose=False, very_verbose=False, + features=None, android=None, magicleap=None, no_package=False, verbose=False, very_verbose=False, debug_mozjs=False, params=None, with_debug_assertions=False, libsimpleservo=False): @@ -244,6 +248,9 @@ class MachCommands(CommandBase): if android: target = self.config["android"]["target"] + if magicleap and not target: + target = "aarch64-linux-android" + if target: if self.config["tools"]["use-rustup"]: # 'rustup target add' fails if the toolchain is not installed at all. @@ -253,7 +260,7 @@ class MachCommands(CommandBase): "--toolchain", self.toolchain(), target]) opts += ["--target", target] - if not android: + if not android and not magicleap: android = self.handle_android_target(target) self.ensure_bootstrapped(target=target) @@ -442,6 +449,89 @@ class MachCommands(CommandBase): expr = "s#libdir=.*#libdir=%s#g" % gst_lib_path subprocess.call(["perl", "-i", "-pe", expr, pc]) + if magicleap: + if platform.system() not in ["Darwin"]: + raise Exception("Magic Leap builds are only supported on macOS.") + + ml_sdk = env.get("MAGICLEAP_SDK") + if not ml_sdk: + raise Exception("Magic Leap builds need the MAGICLEAP_SDK environment variable") + + ml_support = path.join(self.get_top_dir(), "support", "magicleap") + + # We pretend to be an Android build + env.setdefault("ANDROID_VERSION", "21") + env.setdefault("ANDROID_NDK", env["MAGICLEAP_SDK"]) + env.setdefault("ANDROID_NDK_VERSION", "16.0.0") + env.setdefault("ANDROID_PLATFORM_DIR", path.join(env["MAGICLEAP_SDK"], "lumin")) + env.setdefault("ANDROID_TOOLCHAIN_DIR", path.join(env["MAGICLEAP_SDK"], "tools", "toolchains")) + env.setdefault("ANDROID_CLANG", path.join(env["ANDROID_TOOLCHAIN_DIR"], "bin", "clang")) + + # A random collection of search paths + env.setdefault("STLPORT_LIBS", " ".join([ + "-L" + path.join(env["MAGICLEAP_SDK"], "lumin", "stl", "libc++-lumin", "lib"), + "-lc++" + ])) + env.setdefault("STLPORT_CPPFLAGS", " ".join([ + "-I" + path.join(env["MAGICLEAP_SDK"], "lumin", "stl", "libc++-lumin", "include") + ])) + env.setdefault("CPPFLAGS", " ".join([ + "--no-standard-includes", + "--sysroot=" + env["ANDROID_PLATFORM_DIR"], + "-I" + path.join(env["ANDROID_PLATFORM_DIR"], "usr", "include"), + "-isystem" + path.join(env["ANDROID_TOOLCHAIN_DIR"], "lib64", "clang", "3.8", "include"), + ])) + env.setdefault("CFLAGS", " ".join([ + env["CPPFLAGS"], + "-L" + path.join(env["ANDROID_TOOLCHAIN_DIR"], "lib", "gcc", target, "4.9.x"), + ])) + env.setdefault("CXXFLAGS", " ".join([ + # Sigh, Angle gets confused if there's another EGL around + "-I./gfx/angle/checkout/include", + env["STLPORT_CPPFLAGS"], + env["CFLAGS"] + ])) + + # The toolchain commands + env.setdefault("AR", path.join(env["ANDROID_TOOLCHAIN_DIR"], "bin", "aarch64-linux-android-ar")) + env.setdefault("AS", path.join(env["ANDROID_TOOLCHAIN_DIR"], "bin", "aarch64-linux-android-as")) + env.setdefault("CC", path.join(env["ANDROID_TOOLCHAIN_DIR"], "bin", "aarch64-linux-android-clang")) + env.setdefault("CPP", path.join(env["ANDROID_TOOLCHAIN_DIR"], "bin", "aarch64-linux-android-clang -E")) + env.setdefault("CXX", path.join(env["ANDROID_TOOLCHAIN_DIR"], "bin", "aarch64-linux-android-clang++")) + env.setdefault("LD", path.join(env["ANDROID_TOOLCHAIN_DIR"], "bin", "aarch64-linux-android-ld")) + env.setdefault("OBJCOPY", path.join(env["ANDROID_TOOLCHAIN_DIR"], "bin", "aarch64-linux-android-objcopy")) + env.setdefault("OBJDUMP", path.join(env["ANDROID_TOOLCHAIN_DIR"], "bin", "aarch64-linux-android-objdump")) + env.setdefault("RANLIB", path.join(env["ANDROID_TOOLCHAIN_DIR"], "bin", "aarch64-linux-android-ranlib")) + env.setdefault("STRIP", path.join(env["ANDROID_TOOLCHAIN_DIR"], "bin", "aarch64-linux-android-strip")) + + # Undo all of that when compiling build tools for the host + env.setdefault("HOST_CFLAGS", "") + env.setdefault("HOST_CXXFLAGS", "") + env.setdefault("HOST_CC", "gcc") + env.setdefault("HOST_CXX", "g++") + env.setdefault("HOST_LD", "ld") + + # Some random build configurations + env.setdefault("HARFBUZZ_SYS_NO_PKG_CONFIG", "1") + env.setdefault("PKG_CONFIG_ALLOW_CROSS", "1") + env.setdefault("CMAKE_TOOLCHAIN_FILE", path.join(ml_support, "toolchain.cmake")) + + # The Open SSL configuration + env.setdefault("OPENSSL_DIR", path.join(self.get_target_dir(), target, "magicleap", "openssl")) + env.setdefault("OPENSSL_VERSION", "1.0.2k") + env.setdefault("OPENSSL_STATIC", "1") + + # Override the linker set in .cargo/config + env.setdefault("CARGO_TARGET_AARCH64_LINUX_ANDROID_LINKER", path.join(ml_support, "fake-ld.sh")) + + # Only build libmlservo + opts += ["--package", "libmlservo"] + + # Download and build OpenSSL if necessary + status = call(path.join(ml_support, "openssl.sh"), env=env, verbose=verbose) + if status: + return status + if very_verbose: print (["Calling", "cargo", "build"] + opts) for key in env: diff --git a/servo-tidy.toml b/servo-tidy.toml index b270f5645d5..06aac102079 100644 --- a/servo-tidy.toml +++ b/servo-tidy.toml @@ -77,6 +77,10 @@ files = [ directories = [ # Upstream "./support/android/apk", + "./support/magicleap/Servo2D/.vscode", + "./support/magicleap/Servo2D/code/inc.gen", + "./support/magicleap/Servo2D/code/src.gen", + "./support/magicleap/Servo2D/pipeline", "./tests/wpt/harness", "./tests/wpt/update", "./tests/wpt/web-platform-tests", diff --git a/support/magicleap/.gitignore b/support/magicleap/.gitignore new file mode 100644 index 00000000000..6ef202d33ef --- /dev/null +++ b/support/magicleap/.gitignore @@ -0,0 +1,3 @@ +.out +*.log +*.lock diff --git a/support/magicleap/README.md b/support/magicleap/README.md new file mode 100644 index 00000000000..5aee8dbaea8 --- /dev/null +++ b/support/magicleap/README.md @@ -0,0 +1,31 @@ +# Servo for Magic Leap + +## Build requirements + +Currently, we only support building Servo for the Magic Leap on macOS. + +Install the Magic Leap Lumin and Lumin Runtime SDKs. + +Get a signing key for the magic leap app. + +Optionally, install Visual Studio Code and the Magic Leap plugin. + +## Building the mlservo library + +Build the mlservo library: +``` +MAGICLEAP_SDK=*directory* ./mach build -d --magicleap +``` +This builds a static library `target/aarch64-linux-android/debug/libmlservo.a`. + +## Building the Servo2D application + +From inside the `support/magicleap/Servo2D` directory: +``` +mabu Servo2D.package -t device -s *signing key* +``` +This builds the application `.out/Servo2D/Servo2D.mpk`. + +Alternatively, in Visual Studio code, open the `support/magicleap/Servo2D` directory, +and use the `Terminal/Run Build Task...` menu option to build the +Servo2D application. diff --git a/support/magicleap/Servo2D/.vscode/launch.json b/support/magicleap/Servo2D/.vscode/launch.json new file mode 100644 index 00000000000..647968810ff --- /dev/null +++ b/support/magicleap/Servo2D/.vscode/launch.json @@ -0,0 +1,65 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Host OS Debug", + "request": "launch", + "type": "cppdbg", + "stopAtEntry": true, + "externalConsole": false, + "logging": { + "engineLogging": false, + "trace": false + }, + "windows": { + "type": "cppvsdbg", + "cwd": "${workspaceFolder}/.out/${config:lumin_package_name}", + "environment": [{"name": "PATH", "value": "${config:lumin_sdk}/VirtualDevice/bin;${config:lumin_sdk}/VirtualDevice/lib;${config:lumin_sdk}/lib/win64;${env.PATH}"}], + "program": "${workspaceFolder}/.out/debug_win_${config:lumin_host_toolchain}/${config:lumin_exe_name}.exe" + }, + "osx": { + "type": "cppdbg", + "MIMode": "lldb", + "cwd": "${workspaceFolder}/.out/${config:lumin_package_name}", + "environment": [{"name": "DYLD_LIBRARY_PATH", "value": "${config:lumin_sdk}/VirtualDevice/bin:${config:lumin_sdk}/VirtualDevice/lib:${config:lumin_sdk}/lib/osx:${env.DYLD_LIBRARY_PATH}"}], + "program": "${workspaceFolder}/.out/debug_osx_${config:lumin_host_toolchain}/${config:lumin_exe_name}" + }, + "linux": { + "type": "cppdbg", + "MIMode": "lldb", + "cwd": "${workspaceFolder}/.out/${config:lumin_package_name}", + "environment": [{"name": "LD_LIBRARY_PATH", "value": "${config:lumin_sdk}/VirtualDevice/bin:${config:lumin_sdk}/VirtualDevice/lib:${config:lumin_sdk}/lib/linux64:${env.LD_LIBRARY_PATH}"}], + "program": "${workspaceFolder}/.out/debug_linux_${config:lumin_host_toolchain}/${config:lumin_exe_name}" + }, + "preLaunchTask": "Build (Host OS Debug)" + }, + { + "name": "Lumin OS Debug", + "request": "launch", + "type": "cppdbg", + "stopAtEntry": true, + "externalConsole": false, + "logging": { + "engineLogging": false, + "trace": false + }, + "cwd": "${workspaceFolder}/.out/${config:lumin_package_name}", + "targetArchitecture": "arm64", + "MIMode": "gdb", + "miDebuggerPath": "${config:lumin_sdk}/tools/toolchains/bin/gdb", + "windows": { + "miDebuggerPath": "${config:lumin_sdk}/tools/toolchains/bin/gdb.exe", + }, + "miDebuggerServerAddress": "localhost:7777", + "program": "${workspaceFolder}/.out/debug_lumin_${config:lumin_device_toolchain}/${config:lumin_exe_name}", + "customLaunchSetupCommands": [ + {"text": "-file-exec-and-symbols \"${workspaceFolder}/.out/debug_lumin_${config:lumin_device_toolchain}/${config:lumin_exe_name}\""}, + {"text": "source ${workspaceFolder}/.out/debug_lumin_${config:lumin_device_toolchain}/${config:lumin_exe_name}.gdbinit"}, + {"text": "-enable-pretty-printing"}, + {"text": "continue", "ignoreFailures": true}, + {"text": "continue", "ignoreFailures": true} + ], + "preLaunchTask": "Lumin: Setup for remote debugging", + } + ] +}
\ No newline at end of file diff --git a/support/magicleap/Servo2D/.vscode/settings.json b/support/magicleap/Servo2D/.vscode/settings.json new file mode 100644 index 00000000000..b367781dc14 --- /dev/null +++ b/support/magicleap/Servo2D/.vscode/settings.json @@ -0,0 +1,22 @@ +{ + "lumin_mabu_file": "Servo2D.package", + "lumin_package_name": "Servo2D", + "lumin_exe_name": "Servo2D", + "C_Cpp.default.includePath": [ + "${workspaceFolder}/code/**", + "${config.lumin_sdk}/lumin/usr/include/", + "${config.lumin_sdk}/include/runtime/app", + "${config.lumin_sdk}/include/runtime/core", + "${config.lumin_sdk}/include/runtime/external", + "${config.lumin_sdk}/include/runtime/intergen", + "${config.lumin_sdk}/include/runtime/loader", + "${config.lumin_sdk}/include/runtime/uikit", + "${config.lumin_sdk}/include/runtime/util", + "${config.lumin_sdk}/include/" + ], + "C_Cpp.default.defines": [ + "ANDROID" + ], + "C_Cpp.default.cppStandard": "c++11", + "debug.allowBreakpointsEverywhere": true +} diff --git a/support/magicleap/Servo2D/.vscode/tasks.json b/support/magicleap/Servo2D/.vscode/tasks.json new file mode 100644 index 00000000000..c2824f4cf02 --- /dev/null +++ b/support/magicleap/Servo2D/.vscode/tasks.json @@ -0,0 +1,223 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "Build (Lumin OS Debug)", + "type": "shell", + "command": "${config:lumin_sdk}/mabu", + "windows": { + "command": "${config:lumin_sdk}/mabu.cmd", + }, + "args": [ + "${workspaceFolder}/${config:lumin_mabu_file}", + "-t", + "device_debug", + "-s", + "${config:lumin_cert}" + ], + "group": "build", + "problemMatcher": [ + "$msCompile", + "$gcc" + ] + }, + { + "label": "Clean (Lumin OS Debug)", + "type": "shell", + "command": "${config:lumin_sdk}/mabu", + "windows": { + "command": "${config:lumin_sdk}/mabu.cmd", + }, + "args": [ + "${workspaceFolder}/${config:lumin_mabu_file}", + "-t", + "device_debug", + "-c" + ], + "group": "build", + "problemMatcher": [ + "$msCompile", + "$gcc" + ] + }, + { + "label": "Run (Lumin OS Debug)", + "type": "shell", + "command": "${config:lumin_sdk}/mabu", + "windows": { + "command": "${config:lumin_sdk}/mabu.cmd", + }, + "args": [ + "${workspaceFolder}/${config:lumin_mabu_file}", + "-t", + "device_debug", + "-s", + "${config:lumin_cert}", + "--invoke" + ], + "problemMatcher": [ + "$msCompile", + "$gcc" + ] + }, + { + "label": "Build (Lumin OS Release)", + "type": "shell", + "command": "${config:lumin_sdk}/mabu", + "windows": { + "command": "${config:lumin_sdk}/mabu.cmd", + }, + "args": [ + "${workspaceFolder}/${config:lumin_mabu_file}", + "-t", + "device_release", + "-s", + "${config:lumin_cert}" + ], + "group": "build", + "problemMatcher": [ + "$msCompile", + "$gcc" + ] + }, + { + "label": "Clean (Lumin OS Release)", + "type": "shell", + "command": "${config:lumin_sdk}/mabu", + "windows": { + "command": "${config:lumin_sdk}/mabu.cmd", + }, + "args": [ + "${workspaceFolder}/${config:lumin_mabu_file}", + "-t", + "device_release", + "-c" + ], + "group": "build", + "problemMatcher": [ + "$msCompile", + "$gcc" + ] + }, + { + "label": "Run (Lumin OS Release)", + "type": "shell", + "command": "${config:lumin_sdk}/mabu", + "windows": { + "command": "${config:lumin_sdk}/mabu.cmd", + }, + "args": [ + "${workspaceFolder}/${config:lumin_mabu_file}", + "-t", + "device_release", + "-s", + "${config:lumin_cert}", + "--invoke" + ], + "problemMatcher": [ + "$msCompile", + "$gcc" + ] + }, + { + "label": "Build (Host OS Debug)", + "type": "shell", + "command": "${config:lumin_sdk}/mabu", + "windows": { + "command": "${config:lumin_sdk}/mabu.cmd", + "options": { + "env": { + "VisualStudioVersion": "15.0" + } + } + }, + "args": [ + "${workspaceFolder}/${config:lumin_mabu_file}", + "-t", + "host_debug" + ], + "group": "build", + "problemMatcher": [ + "$msCompile", + "$gcc" + ] + }, + { + "label": "Clean (Host OS Debug)", + "type": "shell", + "command": "${config:lumin_sdk}/mabu", + "windows": { + "command": "${config:lumin_sdk}/mabu.cmd", + }, + "args": [ + "${workspaceFolder}/${config:lumin_mabu_file}", + "-t", + "host_debug", + "-c" + ], + "group": "build", + "problemMatcher": [ + "$msCompile", + "$gcc" + ] + }, + { + "label": "Run (Host OS Debug)", + "type": "shell", + "command": "${config:lumin_sdk}/mabu", + "windows": { + "command": "${config:lumin_sdk}/mabu.cmd", + "options": { + "env": { + "VisualStudioVersion": "15.0", + "PATH": "${config:lumin_sdk}/VirtualDevice/bin;${config:lumin_sdk}/VirtualDevice/lib;${config:lumin_sdk}/lib/win64;${env.PATH}" + } + } + }, + "osx": { + "options": { + "env": { + "ML_LIBRARY_PATH": "${config:lumin_sdk}/VirtualDevice/bin:${config:lumin_sdk}/VirtualDevice/lib:${config:lumin_sdk}/lib/osx" + } + } + }, + "linux": { + "options": { + "env": { + "LD_LIBRARY_PATH": "${config:lumin_sdk}/VirtualDevice/bin:${config:lumin_sdk}/VirtualDevice/lib:${config:lumin_sdk}/lib/linux64:${env.LD_LIBRARY_PATH}" + } + } + }, + "args": [ + "${workspaceFolder}/${config:lumin_mabu_file}", + "-t", + "host_debug", + "--invoke" + ], + "problemMatcher": [ + "$msCompile", + "$gcc" + ] + }, + { + "label": "Lumin: Setup for remote debugging", + "type": "shell", + "command": "${config:lumin_sdk}/debug", + "windows": { + "command": "${config:lumin_sdk}/debug.cmd", + }, + "args": [ + "--setup-only", + "-v", + "--sopaths", + "${workspaceFolder}/.out/debug_lumin_${config:lumin_device_toolchain}/", + "--deploy-mpk", + "${workspaceFolder}/.out/${config:lumin_package_name}/${config:lumin_exe_name}.mpk", + "${workspaceFolder}/.out/debug_lumin_${config:lumin_device_toolchain}/${config:lumin_exe_name}" + ], + "dependsOn": [ + "Build (Lumin OS Debug)" + ] + } + ] +} diff --git a/support/magicleap/Servo2D/Servo2D.mabu b/support/magicleap/Servo2D/Servo2D.mabu new file mode 100644 index 00000000000..60221b2875b --- /dev/null +++ b/support/magicleap/Servo2D/Servo2D.mabu @@ -0,0 +1,26 @@ +KIND = program + +INCS = \ + code/inc/ \ + code/inc.gen/ + +SRCS = \ + code/src/main.cpp \ + code/src/Servo2D.cpp + +LIBPATHS.debug = \ + ../../../target/aarch64-linux-android/debug + +LIBPATHS.release = \ + ../../../target/aarch64-linux-android/release + +STLIBS = \ + mlservo + +SHLIBS = \ + log \ + z + +USES = \ + lumin_runtime \ + code/srcsGen diff --git a/support/magicleap/Servo2D/Servo2D.mlproject b/support/magicleap/Servo2D/Servo2D.mlproject new file mode 100644 index 00000000000..0c6dde70b06 --- /dev/null +++ b/support/magicleap/Servo2D/Servo2D.mlproject @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="ASCII"?> +<mlproject:mlproject xmlns:mlproject="http://www.magicleap.com/uidesigner/mlproject" generated="false"> + <designFile path="scenes/Servo2D.design"/> + <pipelineDirectory path="pipeline"/> +</mlproject:mlproject>
\ No newline at end of file diff --git a/support/magicleap/Servo2D/Servo2D.package b/support/magicleap/Servo2D/Servo2D.package new file mode 100644 index 00000000000..c8020d772ca --- /dev/null +++ b/support/magicleap/Servo2D/Servo2D.package @@ -0,0 +1,7 @@ + +USES = "scenes" "pipeline/cache/AssetManifest" + +DATAS = \ + fonts.xml : etc/fonts.xml + +REFS = Servo2D
\ No newline at end of file diff --git a/support/magicleap/Servo2D/code/inc.gen/SceneDescriptor.h b/support/magicleap/Servo2D/code/inc.gen/SceneDescriptor.h new file mode 100644 index 00000000000..db950700a13 --- /dev/null +++ b/support/magicleap/Servo2D/code/inc.gen/SceneDescriptor.h @@ -0,0 +1,48 @@ +// -- WARNING -- WARNING -- WARNING -- WARNING -- WARNING -- WARNING -- +// +// THE CONTENTS OF THIS FILE IS GENERATED BY CODE AND +// ANY MODIFICATIONS WILL BE OVERWRITTEN +// +// -- WARNING -- WARNING -- WARNING -- WARNING -- WARNING -- WARNING -- + +// %BANNER_BEGIN% +// --------------------------------------------------------------------- +// %COPYRIGHT_BEGIN% +// +// Copyright (c) 2018 Magic Leap, Inc. All Rights Reserved. +// Use of this file is governed by the Creator Agreement, located +// here: https://id.magicleap.com/creator-terms +// +// %COPYRIGHT_END% +// --------------------------------------------------------------------- +// %BANNER_END% + +#pragma once + +#include <string> +#include <map> + +// data class +class SceneDescriptor { + public: + + typedef std::map<std::string /* exportedNodeName */, const std::string& /* exportedNodeId */> ExportedNodeReferences; + + SceneDescriptor(const char* exportedName, const char* id, const char* sceneGraphFilePath, const char* resourceModelFilePath, const ExportedNodeReferences& exportedNodeReferences, bool initiallyInstanced); + const std::string& getExportedName() const; + const std::string& getId() const; + const std::string& getSceneGraphPath() const; + const std::string& getResourceModelPath() const; + const ExportedNodeReferences & getExportedNodeReferences() const; + bool getInitiallyInstanced() const; + + private: + std::string exportedName_; + std::string id_; + std::string sceneGraphPath_; + std::string resourceModelPath_; + const ExportedNodeReferences& exportedNodeReferences_; + bool initiallyInstanced_; +}; + +typedef std::map<std::string /* exportedName */, const SceneDescriptor&> SceneDescriptorReferences; diff --git a/support/magicleap/Servo2D/code/inc.gen/scenesGen.h b/support/magicleap/Servo2D/code/inc.gen/scenesGen.h new file mode 100644 index 00000000000..eae1ce2e957 --- /dev/null +++ b/support/magicleap/Servo2D/code/inc.gen/scenesGen.h @@ -0,0 +1,34 @@ +// -- WARNING -- WARNING -- WARNING -- WARNING -- WARNING -- WARNING -- +// +// THE CONTENTS OF THIS FILE IS GENERATED BY CODE AND +// ANY MODIFICATIONS WILL BE OVERWRITTEN +// +// -- WARNING -- WARNING -- WARNING -- WARNING -- WARNING -- WARNING -- + +// %BANNER_BEGIN% +// --------------------------------------------------------------------- +// %COPYRIGHT_BEGIN% +// +// Copyright (c) 2018 Magic Leap, Inc. All Rights Reserved. +// Use of this file is governed by the Creator Agreement, located +// here: https://id.magicleap.com/creator-terms +// +// %COPYRIGHT_END% +// --------------------------------------------------------------------- +// %BANNER_END% + +#pragma once + +#include <SceneDescriptor.h> + +namespace Servo2D_exportedNodes { + extern const std::string content; + extern const std::string backButton; + extern const std::string fwdButton; + extern const std::string urlBar; +} + +namespace scenes { + extern const SceneDescriptor Servo2D; + extern const SceneDescriptorReferences exportedScenes; +} diff --git a/support/magicleap/Servo2D/code/inc/Servo2D.h b/support/magicleap/Servo2D/code/inc/Servo2D.h new file mode 100644 index 00000000000..866f2e09e6c --- /dev/null +++ b/support/magicleap/Servo2D/code/inc/Servo2D.h @@ -0,0 +1,96 @@ +/* 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 http://mozilla.org/MPL/2.0/. */ + +#include <lumin/LandscapeApp.h> +#include <lumin/Prism.h> +#include <lumin/event/ServerEvent.h> +#include <lumin/resource/PlanarResource.h> +#include <SceneDescriptor.h> + +typedef void* ServoInstance; + +/** + * Servo2D Landscape Application + */ +class Servo2D : public lumin::LandscapeApp { +public: + /** + * Constructs the Landscape Application. + */ + Servo2D(); + + /** + * Destroys the Landscape Application. + */ + virtual ~Servo2D(); + + /** + * Disallows the copy constructor. + */ + Servo2D(const Servo2D&) = delete; + + /** + * Disallows the move constructor. + */ + Servo2D(Servo2D&&) = delete; + + /** + * Disallows the copy assignment operator. + */ + Servo2D& operator=(const Servo2D&) = delete; + + /** + * Disallows the move assignment operator. + */ + Servo2D& operator=(Servo2D&&) = delete; + +protected: + /** + * Initializes the Landscape Application. + * @return - 0 on success, error code on failure. + */ + int init() override; + + /** + * Deinitializes the Landscape Application. + * @return - 0 on success, error code on failure. + */ + int deInit() override; + + /** + * Returns the size of the Prism, default = +/- (1.0f, 1.0f, 1.0f) meters. + * Used in createPrism(). + */ + const glm::vec3 getInitialPrismExtents() const; + + /** + * Creates the prism, updates the private variable prism_ with the created prism. + */ + int createInitialPrism(); + + /** + * Initializes and creates the scene of all scenes marked as initially instanced + */ + void instanceInitialScenes(); + + /** + * Initializes and creates the scene of the scene and instances it into the prism + */ + lumin::Node* instanceScene(const SceneDescriptor & sceneToInit); + + /** + * Run application login + */ + virtual bool updateLoop(float fDelta) override; + + /** + * Handle events from the server + */ + virtual bool eventListener(lumin::ServerEvent* event) override; + +private: + lumin::Prism* prism_ = nullptr; // represents the bounded space where the App renders. + lumin::PlanarResource* plane_ = nullptr; // the plane we're rendering into + ServoInstance servo_ = nullptr; // the servo instance we're embedding +}; diff --git a/support/magicleap/Servo2D/code/src.gen/SceneDescriptor.cpp b/support/magicleap/Servo2D/code/src.gen/SceneDescriptor.cpp new file mode 100644 index 00000000000..08bb47d61ac --- /dev/null +++ b/support/magicleap/Servo2D/code/src.gen/SceneDescriptor.cpp @@ -0,0 +1,54 @@ +// -- WARNING -- WARNING -- WARNING -- WARNING -- WARNING -- WARNING -- +// +// THE CONTENTS OF THIS FILE IS GENERATED BY CODE AND +// ANY MODIFICATIONS WILL BE OVERWRITTEN +// +// -- WARNING -- WARNING -- WARNING -- WARNING -- WARNING -- WARNING -- + +// %BANNER_BEGIN% +// --------------------------------------------------------------------- +// %COPYRIGHT_BEGIN% +// +// Copyright (c) 2018 Magic Leap, Inc. All Rights Reserved. +// Use of this file is governed by the Creator Agreement, located +// here: https://id.magicleap.com/creator-terms +// +// %COPYRIGHT_END% +// --------------------------------------------------------------------- +// %BANNER_END% + +#include <SceneDescriptor.h> + +SceneDescriptor::SceneDescriptor(const char * exportedName, const char * id, const char * sceneGraphPath, const char * resourceModelPath, const ExportedNodeReferences& exportedNodeReferences, bool initiallyInstanced) +: + exportedName_(exportedName), + id_(id), + sceneGraphPath_(sceneGraphPath), + resourceModelPath_(resourceModelPath), + exportedNodeReferences_(exportedNodeReferences), + initiallyInstanced_(initiallyInstanced) { +} + +const std::string & SceneDescriptor::getExportedName() const { + return exportedName_; +} + +const std::string & SceneDescriptor::getId() const { + return id_; +} + +const std::string & SceneDescriptor::getSceneGraphPath() const { + return sceneGraphPath_; +} + +const std::string & SceneDescriptor::getResourceModelPath() const { + return resourceModelPath_; +} + +const SceneDescriptor::ExportedNodeReferences & SceneDescriptor::getExportedNodeReferences() const { + return exportedNodeReferences_; +} + +bool SceneDescriptor::getInitiallyInstanced() const { + return initiallyInstanced_; +} diff --git a/support/magicleap/Servo2D/code/src.gen/scenesGen.cpp b/support/magicleap/Servo2D/code/src.gen/scenesGen.cpp new file mode 100644 index 00000000000..6c40880be9e --- /dev/null +++ b/support/magicleap/Servo2D/code/src.gen/scenesGen.cpp @@ -0,0 +1,49 @@ +// -- WARNING -- WARNING -- WARNING -- WARNING -- WARNING -- WARNING -- +// +// THE CONTENTS OF THIS FILE IS GENERATED BY CODE AND +// ANY MODIFICATIONS WILL BE OVERWRITTEN +// +// -- WARNING -- WARNING -- WARNING -- WARNING -- WARNING -- WARNING -- + +// %BANNER_BEGIN% +// --------------------------------------------------------------------- +// %COPYRIGHT_BEGIN% +// +// Copyright (c) 2018 Magic Leap, Inc. All Rights Reserved. +// Use of this file is governed by the Creator Agreement, located +// here: https://id.magicleap.com/creator-terms +// +// %COPYRIGHT_END% +// --------------------------------------------------------------------- +// %BANNER_END% + +#include <scenesGen.h> + +namespace Servo2D_exportedNodes { + const std::string content = "content"; + const std::string backButton = "backButton"; + const std::string fwdButton = "fwdButton"; + const std::string urlBar = "urlBar"; +} + +namespace scenes { + + const SceneDescriptor::ExportedNodeReferences Servo2D_exportedNodesMap = { + {"content", Servo2D_exportedNodes::content}, + {"backButton", Servo2D_exportedNodes::backButton}, + {"fwdButton", Servo2D_exportedNodes::fwdButton}, + {"urlBar", Servo2D_exportedNodes::urlBar} + }; + + const SceneDescriptor Servo2D( + "Servo2D", + "root", + "/assets/scenes/scenes/Servo2D.scene.xml", + "/assets/scenes/scenes/Servo2D.scene.res.xml", + Servo2D_exportedNodesMap, + true); + + const SceneDescriptorReferences exportedScenes = { + {Servo2D.getExportedName(), Servo2D} + }; +} diff --git a/support/magicleap/Servo2D/code/src/Servo2D.cpp b/support/magicleap/Servo2D/code/src/Servo2D.cpp new file mode 100644 index 00000000000..3d6c0ca905e --- /dev/null +++ b/support/magicleap/Servo2D/code/src/Servo2D.cpp @@ -0,0 +1,200 @@ +/* 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 http://mozilla.org/MPL/2.0/. */ + +#include <Servo2D.h> +#include <lumin/node/RootNode.h> +#include <lumin/node/QuadNode.h> +#include <lumin/ui/Cursor.h> +#include <ml_logging.h> +#include <scenesGen.h> +#include <SceneDescriptor.h> +#include <EGL/egl.h> +#include <GLES/gl.h> +#include <string.h> + +// The viewport dimensions (in px). +const unsigned int VIEWPORT_W = 500; +const unsigned int VIEWPORT_H = 500; + +// The hidpi factor. +const float HIDPI = 1.0; + +// The prism dimensions (in m). +const float PRISM_W = 0.5; +const float PRISM_H = 0.5; +const float PRISM_D = 0.5; + +// 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, ML_DEFAULT_LOG_TAG, msg); + } +} + +// The functions Servo provides for hooking up to the ML. +// For the moment, this doesn't handle input events. +extern "C" ServoInstance init_servo(EGLContext, EGLSurface, EGLDisplay, MLLogger, + const char* url, int width, int height, float hidpi); +extern "C" void heartbeat_servo(ServoInstance); +extern "C" void discard_servo(ServoInstance); + +// Create a Servo2D instance +Servo2D::Servo2D() { + ML_LOG(Debug, "Servo2D Constructor."); +} + +// Destroy a Servo 2D instance +Servo2D::~Servo2D() { + ML_LOG(Debug, "Servo2D Destructor."); + discard_servo(servo_); + servo_ = nullptr; +} + +// The prism dimensions +const glm::vec3 Servo2D::getInitialPrismExtents() const { + return glm::vec3(PRISM_W, PRISM_H, PRISM_D); +} + +// Create the prism for Servo +int Servo2D::createInitialPrism() { + prism_ = requestNewPrism(getInitialPrismExtents()); + if (!prism_) { + ML_LOG(Error, "Servo2D Error creating default prism."); + return 1; + } + return 0; +} + +// Initialize a Servo instance +int Servo2D::init() { + + ML_LOG(Debug, "Servo2D Initializing."); + + // Set up the prism + createInitialPrism(); + lumin::ui::Cursor::SetScale(prism_, 0.03f); + instanceInitialScenes(); + + // Get the planar resource that holds the EGL context + lumin::RootNode* root_node = prism_->getRootNode(); + if (!root_node) { + ML_LOG(Error, "Servo2D Failed to get root node"); + abort(); + return 1; + } + + std::string content_node_id = Servo2D_exportedNodes::content; + lumin::QuadNode* content_node = lumin::QuadNode::CastFrom(prism_->findNode(content_node_id, root_node)); + if (!content_node) { + ML_LOG(Error, "Servo2D Failed to get content node"); + abort(); + return 1; + } + + lumin::ResourceIDType plane_id = prism_->createPlanarEGLResourceId(); + if (!plane_id) { + ML_LOG(Error, "Servo2D Failed to create EGL resource"); + abort(); + return 1; + } + + plane_ = static_cast<lumin::PlanarResource*>(prism_->getResource(plane_id)); + if (!plane_) { + ML_LOG(Error, "Servo2D Failed to create plane"); + abort(); + return 1; + } + + content_node->setRenderResource(plane_id); + + // Get the EGL context, surface and display. + EGLContext ctx = plane_->getEGLContext(); + EGLSurface surf = plane_->getEGLSurface(); + EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY); + eglMakeCurrent(dpy, surf, surf, ctx); + glViewport(0, 0, VIEWPORT_W, VIEWPORT_H); + + // Hook into servo + servo_ = init_servo(ctx, surf, dpy, logger, "https://servo.org", VIEWPORT_H, VIEWPORT_W, HIDPI); + if (!servo_) { + ML_LOG(Error, "Servo2D Failed to init servo instance"); + abort(); + return 1; + } + + // Flush GL + glFlush(); + eglSwapBuffers(dpy, surf); + return 0; +} + +int Servo2D::deInit() { + ML_LOG(Debug, "Servo2D Deinitializing."); + return 0; +} + +lumin::Node* Servo2D::instanceScene(const SceneDescriptor& scene) { + // Load resources. + if (!prism_->loadResourceModel(scene.getResourceModelPath())) { + ML_LOG(Info, "No resource model loaded"); + } + + // Load a scene file. + std::string editorObjectModelName; + if (!prism_->loadObjectModel(scene.getSceneGraphPath(), editorObjectModelName)) { + ML_LOG(Error, "Servo2D Failed to load object model"); + abort(); + return nullptr; + } + + // Add scene to this prism. + lumin::Node* newTree = prism_->createAll(editorObjectModelName); + if (!prism_->getRootNode()->addChild(newTree)) { + ML_LOG(Error, "Servo2D Failed to add newTree to the prism root node"); + abort(); + return nullptr; + } + + return newTree; +} + +void Servo2D::instanceInitialScenes() { + // Iterate over all the exported scenes + for (auto& exportedSceneEntry : scenes::exportedScenes ) { + + // If this scene was marked to be instanced at app initialization, do it + const SceneDescriptor &sd = exportedSceneEntry.second; + if (sd.getInitiallyInstanced()) { + instanceScene(sd); + } + } +} + +bool Servo2D::updateLoop(float fDelta) { + // Get the EGL context, surface and display. + EGLContext ctx = plane_->getEGLContext(); + EGLSurface surf = plane_->getEGLSurface(); + EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY); + eglMakeCurrent(dpy, surf, surf, ctx); + glViewport(0, 0, VIEWPORT_W, VIEWPORT_H); + + // Hook into servo + heartbeat_servo(servo_); + + // Flush GL + glFlush(); + eglSwapBuffers(dpy, surf); + + // Return true for your app to continue running, false to terminate the app. + return true; +} + +bool Servo2D::eventListener(lumin::ServerEvent* event) { + + // Place your event handling here. + + // Return true if the event is consumed. + return false; +} diff --git a/support/magicleap/Servo2D/code/src/main.cpp b/support/magicleap/Servo2D/code/src/main.cpp new file mode 100644 index 00000000000..d8abed18c34 --- /dev/null +++ b/support/magicleap/Servo2D/code/src/main.cpp @@ -0,0 +1,13 @@ +/* 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 http://mozilla.org/MPL/2.0/. */ + +#include <Servo2D.h> +#include <ml_logging.h> + +int main(int argc, char **argv) +{ + ML_LOG(Debug, "Servo2D Starting."); + Servo2D myApp; + return myApp.run(); +} diff --git a/support/magicleap/Servo2D/code/srcsGen.comp b/support/magicleap/Servo2D/code/srcsGen.comp new file mode 100644 index 00000000000..d46daea0bbb --- /dev/null +++ b/support/magicleap/Servo2D/code/srcsGen.comp @@ -0,0 +1,3 @@ +SRCS = \ + src.gen/scenesGen.cpp \ + src.gen/SceneDescriptor.cpp \ diff --git a/support/magicleap/Servo2D/fonts.xml b/support/magicleap/Servo2D/fonts.xml new file mode 100644 index 00000000000..c994a7e456b --- /dev/null +++ b/support/magicleap/Servo2D/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/Servo2D/manifest.xml b/support/magicleap/Servo2D/manifest.xml new file mode 100644 index 00000000000..81fc300b097 --- /dev/null +++ b/support/magicleap/Servo2D/manifest.xml @@ -0,0 +1,17 @@ +<manifest + xmlns:ml="magicleap" + ml:package="com.mozilla.servo2d" + ml:version_code="1" + ml:version_name="1.0"> + <application + ml:visible_name="Servo2D" + ml:sdk_version="1.0"> + <component + ml:name=".servo2d.universe" + ml:visible_name="Servo2D" + ml:binary_name="bin/Servo2D" + ml:type="Universe"> + </component> + <uses-privilege ml:name="Internet"/> + </application> +</manifest> diff --git a/support/magicleap/Servo2D/pipeline/cache/AssetManifest.comp b/support/magicleap/Servo2D/pipeline/cache/AssetManifest.comp new file mode 100644 index 00000000000..a1c45b39d6b --- /dev/null +++ b/support/magicleap/Servo2D/pipeline/cache/AssetManifest.comp @@ -0,0 +1 @@ +DATAS=
\ No newline at end of file diff --git a/support/magicleap/Servo2D/pipeline/lap/project.json b/support/magicleap/Servo2D/pipeline/lap/project.json new file mode 100644 index 00000000000..db27f7df84a --- /dev/null +++ b/support/magicleap/Servo2D/pipeline/lap/project.json @@ -0,0 +1,36 @@ +{ + "intermediate-storage": { + "path": "cache", + "kind": "in-tree" + }, + "project-schema-version": 4, + "types": { + "assets": [ + "lap/types/asset/material", + "lap/types/asset/model", + "lap/types/asset/outline-font", + "lap/types/asset/texture" + ], + "files": [ + "lap/types/file/dds", + "lap/types/file/fbx", + "lap/types/file/files", + "lap/types/file/gltf", + "lap/types/file/jpg", + "lap/types/file/kmat", + "lap/types/file/otf", + "lap/types/file/png" + ] + }, + "checkpoint-hash": "74689acde6571e19f86366dd94d8890be66acfceb26d14ac3ca14228fa31959087b8771fbb5a86764b4e7dc121bd78c3b0ee4c9c0716f0d91c90a59315f8acd8", + "templates": [ + "lap/template/passthru_material_from_kmat", + "lap/template/passthru_model_from_fbx", + "lap/template/passthru_model_from_gltf", + "lap/template/passthru_outline_font_from_otf", + "lap/template/passthru_texture_from_dds", + "lap/template/passthru_texture_from_jpg", + "lap/template/passthru_texture_from_png" + ], + "nodes": {} +}
\ No newline at end of file diff --git a/support/magicleap/Servo2D/scenes.comp b/support/magicleap/Servo2D/scenes.comp new file mode 100644 index 00000000000..a5c3213a275 --- /dev/null +++ b/support/magicleap/Servo2D/scenes.comp @@ -0,0 +1,3 @@ +DATAS = \ + scenes/Servo2D.scene.res.xml : assets/scenes/scenes/Servo2D.scene.res.xml \ + scenes/Servo2D.scene.xml : assets/scenes/scenes/Servo2D.scene.xml diff --git a/support/magicleap/Servo2D/scenes/Servo2D.design b/support/magicleap/Servo2D/scenes/Servo2D.design new file mode 100644 index 00000000000..0def50dc082 --- /dev/null +++ b/support/magicleap/Servo2D/scenes/Servo2D.design @@ -0,0 +1,177 @@ +<?xml version="1.0" encoding="ASCII"?> +<design:rootNode xmlns:design="http://www.magicleap.com/uidesigner/rcp/document/design" name="root" nodeTypeId="lumin.root" modelId="lumin" version="1.7.2"> + <property id="name" value="root"/> + <node name="content" nodeTypeId="lumin.quad"> + <property id="color"> + <property id="rgb" value="1 1 1"/> + <property id="alpha" value="1.0"/> + </property> + <property id="externalName" value="content"/> + <property id="name" value="content"/> + <property id="position"> + <property id="x" value="-0.25"/> + <property id="y" value="-0.19"/> + </property> + <property id="rotation"/> + <property id="scale"> + <property id="x" value="1.0"/> + <property id="y" value="1.0"/> + <property id="z" value="1.0"/> + </property> + <property id="size"> + <property id="x" value="0.5"/> + <property id="y" value="0.44"/> + </property> + <property id="texCoords"> + <property id="x"> + <property id="y" value="1.0"/> + </property> + <property id="y"> + <property id="x" value="1.0"/> + <property id="y" value="1.0"/> + </property> + <property id="z"> + <property id="x" value="1.0"/> + </property> + <property id="w"/> + </property> + </node> + <node name="uiLinearLayout1" nodeTypeId="lumin.ui.linearLayout"> + <property id="alignment"> + <property id="horizontalAlignment" value="Center"/> + </property> + <property id="defaultItemAlignment"> + <property id="verticalAlignment" value="Center"/> + </property> + <property id="defaultItemPadding"> + <property id="right" value="0.01"/> + <property id="left" value="0.01"/> + </property> + <property id="gravityWellProperties"> + <property id="boundaryShape"> + <property id="size"/> + <property id="offset"/> + </property> + </property> + <property id="itemAlignment"/> + <property id="itemPadding"/> + <property id="name" value="uiLinearLayout1"/> + <property id="orientation" value="Horizontal"/> + <property id="position"> + <property id="y" value="-0.2"/> + </property> + <property id="rotation"/> + <property id="scale"> + <property id="x" value="1.0"/> + <property id="y" value="1.0"/> + <property id="z" value="1.0"/> + </property> + <property id="size"> + <property id="x" value="0.5"/> + <property id="y" value="0.05"/> + </property> + <node name="backButton" nodeTypeId="lumin.ui.button"> + <property id="externalName" value="backButton"/> + <property id="gravityWellProperties"> + <property id="boundaryShape"> + <property id="size"/> + <property id="offset"/> + </property> + </property> + <property id="height" value="0.1"/> + <property id="iconColor"> + <property id="rgb" value="1 1 1"/> + <property id="alpha" value="1.0"/> + </property> + <property id="iconSize"/> + <property id="name" value="backButton"/> + <property id="position"> + <property id="y" value="-0.6"/> + </property> + <property id="rotation"/> + <property id="scale"> + <property id="x" value="1.0"/> + <property id="y" value="1.0"/> + <property id="z" value="1.0"/> + </property> + <property id="text" value="Back"/> + <property id="textColor"> + <property id="rgb" value="1 1 1"/> + <property id="alpha" value="1.0"/> + </property> + <property id="textSize" value="0.05"/> + <property id="textSizeChanged" value="true"/> + <property id="width" value="0.1"/> + </node> + <node name="fwdButton" nodeTypeId="lumin.ui.button"> + <property id="externalName" value="fwdButton"/> + <property id="gravityWellProperties"> + <property id="boundaryShape"> + <property id="size"/> + <property id="offset"/> + </property> + </property> + <property id="height" value="0.1"/> + <property id="iconColor"> + <property id="rgb" value="1 1 1"/> + <property id="alpha" value="1.0"/> + </property> + <property id="iconSize"/> + <property id="name" value="fwdButton"/> + <property id="position"/> + <property id="rotation"/> + <property id="scale"> + <property id="x" value="1.0"/> + <property id="y" value="1.0"/> + <property id="z" value="1.0"/> + </property> + <property id="text" value="Fwd"/> + <property id="textColor"> + <property id="rgb" value="1 1 1"/> + <property id="alpha" value="1.0"/> + </property> + <property id="textSize" value="0.05"/> + <property id="textSizeChanged" value="true"/> + <property id="width" value="0.1"/> + </node> + <node name="urlBar" nodeTypeId="lumin.ui.textEdit"> + <property id="alignment"> + <property id="verticalAlignment" value="Center"/> + </property> + <property id="externalName" value="urlBar"/> + <property id="gravityWellProperties"> + <property id="boundaryShape"> + <property id="size"/> + <property id="offset"/> + </property> + </property> + <property id="height" value="0.05"/> + <property id="hintTextColor"> + <property id="rgb" value="1 1 1"/> + <property id="alpha" value="1.0"/> + </property> + <property id="name" value="urlBar"/> + <property id="position"/> + <property id="rotation"/> + <property id="scale"> + <property id="x" value="1.0"/> + <property id="y" value="1.0"/> + <property id="z" value="1.0"/> + </property> + <property id="scrollBarVisibilityMode" value="Off"/> + <property id="text" value="https://servo.org/"/> + <property id="textColor"> + <property id="rgb" value="1 1 1"/> + <property id="alpha" value="1.0"/> + </property> + <property id="textPadding"> + <property id="top" value="0.003"/> + <property id="right" value="0.003"/> + <property id="bottom" value="0.003"/> + <property id="left" value="0.003"/> + </property> + <property id="textSize" value="0.05"/> + <property id="width" value="0.6"/> + </node> + </node> +</design:rootNode>
\ No newline at end of file diff --git a/support/magicleap/Servo2D/scenes/Servo2D.scene.res.xml b/support/magicleap/Servo2D/scenes/Servo2D.scene.res.xml new file mode 100644 index 00000000000..e69de29bb2d --- /dev/null +++ b/support/magicleap/Servo2D/scenes/Servo2D.scene.res.xml diff --git a/support/magicleap/Servo2D/scenes/Servo2D.scene.xml b/support/magicleap/Servo2D/scenes/Servo2D.scene.xml new file mode 100644 index 00000000000..ad895bc4d5c --- /dev/null +++ b/support/magicleap/Servo2D/scenes/Servo2D.scene.xml @@ -0,0 +1,15 @@ +<ObjectModel name="Servo2D" version="1"> + <TransformNode/> + <QuadNode castShadow="false" name="content" pos="-0.250000, -0.190000, 0.000000" receiveShadow="false" shader="UnlitColorTex2d" size="0.500000, 0.440000"/> + <UiLinearLayout alignment="Top, Center" gravityWellEnabled="false" gravityWellRoundness="0.000000" gravityWellSize="0.000000, 0.000000" gravityWellSnap="ClosestEdge" itemAlignment="Center, Left" itemPadding="0.000000, 0.010000, 0.000000, 0.010000" name="uiLinearLayout1" orientation="Horizontal" pos="0.000000, -0.200000, 0.000000" size="0.500000, 0.050000"> + <Content> + <UiButton gravityWellEnabled="false" gravityWellRoundness="0.000000" gravityWellSize="0.000000, 0.000000" gravityWellSnap="ClosestEdge" name="backButton" pos="0.000000, -0.600000, 0.000000" size="0.100000, 0.100000" text="Back" textSize="0.050000"/> + </Content> + <Content> + <UiButton gravityWellEnabled="false" gravityWellRoundness="0.000000" gravityWellSize="0.000000, 0.000000" gravityWellSnap="ClosestEdge" name="fwdButton" size="0.100000, 0.100000" text="Fwd" textSize="0.050000"/> + </Content> + <Content> + <UiTextEdit alignment="Center, Left" font="" gravityWellEnabled="false" gravityWellRoundness="0.000000" gravityWellSize="0.000000, 0.000000" gravityWellSnap="ClosestEdge" name="urlBar" scrollSpeed="0.500000" size="0.600000, 0.050000" text="https://servo.org/" textSize="0.050000"/> + </Content> + </UiLinearLayout> +</ObjectModel> diff --git a/support/magicleap/fake-ld.sh b/support/magicleap/fake-ld.sh new file mode 100755 index 00000000000..99c01c3a5ce --- /dev/null +++ b/support/magicleap/fake-ld.sh @@ -0,0 +1,21 @@ +#!/usr/bin/env bash + +# 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 http://mozilla.org/MPL/2.0/. + +set -o errexit +set -o nounset +set -o pipefail + +MAGICLEAP_TOOLCHAIN=${MAGICLEAP_TOOLCHAIN:-"${MAGICLEAP_SDK}/tools/toolchains"} +TARGET=${TARGET:-"aarch64-linux-android"} +LD=${LD:-"${MAGICLEAP_TOOLCHAIN}/bin/${TARGET}-ld"} +LDFLAGS=${LDFLAGS:-"-L${MAGICLEAP_SDK}/lumin/stl/libc++/lib -L${MAGICLEAP_SDK}/lumin/usr/lib -L${MAGICLEAP_TOOLCHAIN}/lib/gcc/${TARGET}/4.9.x ${MAGICLEAP_SDK}/lumin/usr/lib/crtbegin_so.o"} + +# Remove the -landroid flag, grr +ARGS=("$@") +ARGS=${ARGS[@]/-landroid} + +echo ${LD} ${LDFLAGS} ${ARGS} +${LD} ${LDFLAGS} ${ARGS} diff --git a/support/magicleap/openssl.sh b/support/magicleap/openssl.sh new file mode 100755 index 00000000000..d45b84ec83a --- /dev/null +++ b/support/magicleap/openssl.sh @@ -0,0 +1,60 @@ +#!/usr/bin/env bash + +# 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 http://mozilla.org/MPL/2.0/. + +set -o errexit +set -o nounset +set -o pipefail + +if [[ -z "${OPENSSL_DIR}" ]]; then + echo "No OPENSSL_DIR." + exit 1 +fi + +if [[ -z "${OPENSSL_VERSION}" ]]; then + echo "No OPENSSL_VERSION." + exit 1 +fi + +if [[ -f "${OPENSSL_DIR}/lib/libssl.so" ]] && \ + [[ "${OPENSSL_DIR}/lib/libssl.so" -nt "${0}" ]] ; then + exit 0 +fi + +echo "Building ${OPENSSL_DIR}/lib/libssl.so" + +S3_BUCKET="https://s3.amazonaws.com/servo-deps/android-deps" +S3_URL="${S3_BUCKET}/openssl-${OPENSSL_VERSION}.tar.gz" + +if [[ ! -d "${OPENSSL_DIR}/src/openssl-${OPENSSL_VERSION}" ]]; then + mkdir -p "${OPENSSL_DIR}/src" + curl "${S3_URL}" | tar xzf - -C "${OPENSSL_DIR}/src" +fi + +if [[ ! -d "${OPENSSL_DIR}/src/openssl-${OPENSSL_VERSION}" ]]; then + echo "Failed to download ${OPENSSL_DIR}/src/openssl-${OPENSSL_VERSION}" + exit 1 +fi + +cd "${OPENSSL_DIR}/src/openssl-${OPENSSL_VERSION}" + +./Configure shared \ + --prefix="${OPENSSL_DIR}" \ + --openssldir="${OPENSSL_DIR}" \ + -no-ssl2 -no-ssl3 -no-comp -no-engine -no-hw \ + linux-generic64 \ + -fPIC -fno-omit-frame-pointer \ + -Wall -Wno-error=macro-redefined -Wno-unknown-attributes \ + ${CFLAGS:-} + +make depend +make all +make install_sw + +if [[ ! -f "${OPENSSL_DIR}/lib/libssl.so" ]]; then + echo "Failed to build ${OPENSSL_DIR}/lib/libssl.so" + exit 1 +fi + diff --git a/support/magicleap/toolchain.cmake b/support/magicleap/toolchain.cmake new file mode 100644 index 00000000000..99c23014a7a --- /dev/null +++ b/support/magicleap/toolchain.cmake @@ -0,0 +1 @@ +set(CMAKE_SYSTEM_NAME Linux) |