mirror of
https://github.com/servo/servo.git
synced 2025-06-17 04:44:28 +00:00
Add Servo3D immersive demo for magicleap
This commit is contained in:
parent
e381cebeb6
commit
0b48ff496f
20 changed files with 454 additions and 77 deletions
18
Cargo.lock
generated
18
Cargo.lock
generated
|
@ -2470,6 +2470,7 @@ dependencies = [
|
||||||
"libc 0.2.53 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.53 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"libservo 0.0.1",
|
"libservo 0.0.1",
|
||||||
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"rust-webvr 0.11.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"servo-egl 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"servo-egl 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"simpleservo 0.0.1",
|
"simpleservo 0.0.1",
|
||||||
"smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -3673,7 +3674,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rust-webvr"
|
name = "rust-webvr"
|
||||||
version = "0.11.3"
|
version = "0.11.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bindgen 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bindgen 0.49.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -3686,12 +3687,12 @@ dependencies = [
|
||||||
"libloading 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libloading 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"ovr-mobile-sys 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"ovr-mobile-sys 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rust-webvr-api 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rust-webvr-api 0.11.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rust-webvr-api"
|
name = "rust-webvr-api"
|
||||||
version = "0.11.1"
|
version = "0.11.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"android_injected_glue 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"android_injected_glue 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -4030,7 +4031,7 @@ dependencies = [
|
||||||
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"osmesa-src 0.1.0 (git+https://github.com/servo/osmesa-src)",
|
"osmesa-src 0.1.0 (git+https://github.com/servo/osmesa-src)",
|
||||||
"osmesa-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"osmesa-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"rust-webvr 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rust-webvr 0.11.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"sig 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"sig 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"tinyfiledialogs 3.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"tinyfiledialogs 3.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -5359,7 +5360,8 @@ dependencies = [
|
||||||
"ipc-channel 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"ipc-channel 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"msg 0.0.1",
|
"msg 0.0.1",
|
||||||
"rust-webvr 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rust-webvr 0.11.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"rust-webvr-api 0.11.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"script_traits 0.0.1",
|
"script_traits 0.0.1",
|
||||||
"servo_config 0.0.1",
|
"servo_config 0.0.1",
|
||||||
"webvr_traits 0.0.1",
|
"webvr_traits 0.0.1",
|
||||||
|
@ -5371,7 +5373,7 @@ version = "0.0.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ipc-channel 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"ipc-channel 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"msg 0.0.1",
|
"msg 0.0.1",
|
||||||
"rust-webvr-api 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rust-webvr-api 0.11.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -5881,8 +5883,8 @@ dependencies = [
|
||||||
"checksum regex-syntax 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "dcfd8681eebe297b81d98498869d4aae052137651ad7b96822f09ceb690d0a96"
|
"checksum regex-syntax 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "dcfd8681eebe297b81d98498869d4aae052137651ad7b96822f09ceb690d0a96"
|
||||||
"checksum remove_dir_all 0.5.1 (git+https://github.com/XAMPPRocky/remove_dir_all)" = "<none>"
|
"checksum remove_dir_all 0.5.1 (git+https://github.com/XAMPPRocky/remove_dir_all)" = "<none>"
|
||||||
"checksum ron 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "da06feaa07f69125ab9ddc769b11de29090122170b402547f64b86fe16ebc399"
|
"checksum ron 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "da06feaa07f69125ab9ddc769b11de29090122170b402547f64b86fe16ebc399"
|
||||||
"checksum rust-webvr 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7a171c39fdd52c5b461f2384a04e2d75555c7ed657c057c45ea9d69d68b5f9fb"
|
"checksum rust-webvr 0.11.4 (registry+https://github.com/rust-lang/crates.io-index)" = "829a995f41b762524b124f45ef2d9ec0391d63b362df6f7627ec391a6b579eaa"
|
||||||
"checksum rust-webvr-api 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c5611b60f8a26ad5af2b8d6ac072f9e1b396305e8eb19efd5a6df84c588b1429"
|
"checksum rust-webvr-api 0.11.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c8eb1d528c0d05ebf44126775b38eb3ec543f35a24275bb0360e45e3e3e8da73"
|
||||||
"checksum rustc-demangle 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3058a43ada2c2d0b92b3ae38007a2d0fa5e9db971be260e0171408a4ff471c95"
|
"checksum rustc-demangle 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3058a43ada2c2d0b92b3ae38007a2d0fa5e9db971be260e0171408a4ff471c95"
|
||||||
"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
|
"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
|
||||||
"checksum rusttype 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b8eb11f5b0a98c8eca2fb1483f42646d8c340e83e46ab416f8a063a0fd0eeb20"
|
"checksum rusttype 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b8eb11f5b0a98c8eca2fb1483f42646d8c340e83e46ab416f8a063a0fd0eeb20"
|
||||||
|
|
|
@ -161,10 +161,10 @@ pub trait WindowMethods {
|
||||||
|
|
||||||
pub trait EmbedderMethods {
|
pub trait EmbedderMethods {
|
||||||
/// Returns a thread-safe object to wake up the window's event loop.
|
/// Returns a thread-safe object to wake up the window's event loop.
|
||||||
fn create_event_loop_waker(&self) -> Box<dyn EventLoopWaker>;
|
fn create_event_loop_waker(&mut self) -> Box<dyn EventLoopWaker>;
|
||||||
/// Register services with a VRServiceManager.
|
/// Register services with a VRServiceManager.
|
||||||
fn register_vr_services(
|
fn register_vr_services(
|
||||||
&self,
|
&mut self,
|
||||||
_: &mut VRServiceManager,
|
_: &mut VRServiceManager,
|
||||||
_: &mut Vec<Box<WebVRMainThreadHeartbeat>>,
|
_: &mut Vec<Box<WebVRMainThreadHeartbeat>>,
|
||||||
) {
|
) {
|
||||||
|
|
|
@ -1436,7 +1436,7 @@ impl Window {
|
||||||
|
|
||||||
let complete = match join_port.try_recv() {
|
let complete = match join_port.try_recv() {
|
||||||
Err(TryRecvError::Empty) => {
|
Err(TryRecvError::Empty) => {
|
||||||
info!("script: waiting on layout");
|
debug!("script: waiting on layout");
|
||||||
join_port.recv().unwrap()
|
join_port.recv().unwrap()
|
||||||
},
|
},
|
||||||
Ok(reflow_complete) => reflow_complete,
|
Ok(reflow_complete) => reflow_complete,
|
||||||
|
|
|
@ -199,7 +199,7 @@ impl<Window> Servo<Window>
|
||||||
where
|
where
|
||||||
Window: WindowMethods + 'static + ?Sized,
|
Window: WindowMethods + 'static + ?Sized,
|
||||||
{
|
{
|
||||||
pub fn new(embedder: Box<EmbedderMethods>, window: Rc<Window>) -> Servo<Window> {
|
pub fn new(mut embedder: Box<EmbedderMethods>, window: Rc<Window>) -> Servo<Window> {
|
||||||
// Global configuration options, parsed from the command line.
|
// Global configuration options, parsed from the command line.
|
||||||
let opts = opts::get();
|
let opts = opts::get();
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,8 @@ gleam = "0.6"
|
||||||
ipc-channel = "0.11.2"
|
ipc-channel = "0.11.2"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
msg = {path = "../msg"}
|
msg = {path = "../msg"}
|
||||||
rust-webvr = {version = "0.11.3", features = ["mock", "openvr", "vrexternal"]}
|
rust-webvr = {version = "0.11.4", features = ["mock", "openvr", "vrexternal"]}
|
||||||
|
rust-webvr-api = "0.11.4"
|
||||||
script_traits = {path = "../script_traits"}
|
script_traits = {path = "../script_traits"}
|
||||||
servo_config = {path = "../config"}
|
servo_config = {path = "../config"}
|
||||||
webvr_traits = {path = "../webvr_traits" }
|
webvr_traits = {path = "../webvr_traits" }
|
||||||
|
|
|
@ -12,3 +12,4 @@ pub use crate::webvr_thread::{WebVRCompositorHandler, WebVRThread};
|
||||||
pub use rust_webvr::api::VRExternalShmemPtr;
|
pub use rust_webvr::api::VRExternalShmemPtr;
|
||||||
pub use rust_webvr::VRMainThreadHeartbeat;
|
pub use rust_webvr::VRMainThreadHeartbeat;
|
||||||
pub use rust_webvr::VRServiceManager;
|
pub use rust_webvr::VRServiceManager;
|
||||||
|
pub use rust_webvr_api::VRService;
|
||||||
|
|
|
@ -13,5 +13,5 @@ path = "lib.rs"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
ipc-channel = "0.11"
|
ipc-channel = "0.11"
|
||||||
msg = {path = "../msg"}
|
msg = {path = "../msg"}
|
||||||
rust-webvr-api = {version = "0.11.1", features = ["ipc"]}
|
rust-webvr-api = {version = "0.11.4", features = ["ipc"]}
|
||||||
serde = "1.0"
|
serde = "1.0"
|
||||||
|
|
|
@ -30,12 +30,12 @@ impl EmbedderCallbacks {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EmbedderMethods for EmbedderCallbacks {
|
impl EmbedderMethods for EmbedderCallbacks {
|
||||||
fn create_event_loop_waker(&self) -> Box<dyn EventLoopWaker> {
|
fn create_event_loop_waker(&mut self) -> Box<dyn EventLoopWaker> {
|
||||||
self.events_loop.borrow().create_event_loop_waker()
|
self.events_loop.borrow().create_event_loop_waker()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn register_vr_services(
|
fn register_vr_services(
|
||||||
&self,
|
&mut self,
|
||||||
services: &mut VRServiceManager,
|
services: &mut VRServiceManager,
|
||||||
heartbeats: &mut Vec<Box<WebVRMainThreadHeartbeat>>,
|
heartbeats: &mut Vec<Box<WebVRMainThreadHeartbeat>>,
|
||||||
) {
|
) {
|
||||||
|
|
|
@ -19,6 +19,7 @@ raqote_backend = ["simpleservo/raqote_backend"]
|
||||||
[dependencies]
|
[dependencies]
|
||||||
libservo = { path = "../../components/servo", features = ["no_static_freetype"] }
|
libservo = { path = "../../components/servo", features = ["no_static_freetype"] }
|
||||||
simpleservo = { path = "../libsimpleservo/api", features = ["no_static_freetype"] }
|
simpleservo = { path = "../libsimpleservo/api", features = ["no_static_freetype"] }
|
||||||
|
rust-webvr = { version = "0.11", features = ["magicleap"] }
|
||||||
libc = "0.2"
|
libc = "0.2"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
servo-egl = "0.2"
|
servo-egl = "0.2"
|
||||||
|
|
|
@ -10,16 +10,15 @@ use egl::egl::SwapBuffers;
|
||||||
use libc::{dup2, pipe, read};
|
use libc::{dup2, pipe, read};
|
||||||
use log::info;
|
use log::info;
|
||||||
use log::warn;
|
use log::warn;
|
||||||
|
use rust_webvr::api::MagicLeapVRService;
|
||||||
use servo::euclid::TypedScale;
|
use servo::euclid::TypedScale;
|
||||||
use servo::keyboard_types::Key;
|
use servo::keyboard_types::Key;
|
||||||
use servo::servo_url::ServoUrl;
|
use servo::servo_url::ServoUrl;
|
||||||
use servo::webrender_api::DevicePixel;
|
use servo::webrender_api::DevicePixel;
|
||||||
use servo::webrender_api::DevicePoint;
|
use servo::webrender_api::DevicePoint;
|
||||||
use servo::webrender_api::LayoutPixel;
|
use servo::webrender_api::LayoutPixel;
|
||||||
use simpleservo::{
|
use simpleservo::{self, deinit, gl_glue, MouseButton, ServoGlue, SERVO};
|
||||||
self, deinit, gl_glue, Coordinates, EventLoopWaker, HostTrait, InitOptions, MouseButton,
|
use simpleservo::{Coordinates, EventLoopWaker, HostTrait, InitOptions, VRInitOptions};
|
||||||
ServoGlue, SERVO,
|
|
||||||
};
|
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use std::ffi::CStr;
|
use std::ffi::CStr;
|
||||||
|
@ -70,16 +69,16 @@ pub enum MLKeyType {
|
||||||
|
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub struct MLLogger(extern "C" fn(MLLogLevel, *const c_char));
|
pub struct MLLogger(Option<extern "C" fn(MLLogLevel, *const c_char)>);
|
||||||
|
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
pub struct MLHistoryUpdate(extern "C" fn(MLApp, bool, bool));
|
pub struct MLHistoryUpdate(Option<extern "C" fn(MLApp, bool, bool)>);
|
||||||
|
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
pub struct MLURLUpdate(extern "C" fn(MLApp, *const c_char));
|
pub struct MLURLUpdate(Option<extern "C" fn(MLApp, *const c_char)>);
|
||||||
|
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
pub struct MLKeyboard(extern "C" fn(MLApp, bool));
|
pub struct MLKeyboard(Option<extern "C" fn(MLApp, bool)>);
|
||||||
|
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
|
@ -102,6 +101,7 @@ pub unsafe extern "C" fn init_servo(
|
||||||
ctxt: EGLContext,
|
ctxt: EGLContext,
|
||||||
surf: EGLSurface,
|
surf: EGLSurface,
|
||||||
disp: EGLDisplay,
|
disp: EGLDisplay,
|
||||||
|
landscape: bool,
|
||||||
app: MLApp,
|
app: MLApp,
|
||||||
logger: MLLogger,
|
logger: MLLogger,
|
||||||
history_update: MLHistoryUpdate,
|
history_update: MLHistoryUpdate,
|
||||||
|
@ -140,12 +140,17 @@ pub unsafe extern "C" fn init_servo(
|
||||||
};
|
};
|
||||||
info!("got args: {:?}", args);
|
info!("got args: {:?}", args);
|
||||||
|
|
||||||
|
let name = String::from("Magic Leap VR Display");
|
||||||
|
let (service, heartbeat) =
|
||||||
|
MagicLeapVRService::new(name, ctxt, gl.clone()).expect("Failed to create VR service");
|
||||||
|
let service = Box::new(service);
|
||||||
|
let heartbeat = Box::new(heartbeat);
|
||||||
let opts = InitOptions {
|
let opts = InitOptions {
|
||||||
args,
|
args,
|
||||||
url: Some(url.to_string()),
|
url: Some(url.to_string()),
|
||||||
density: hidpi,
|
density: hidpi,
|
||||||
enable_subpixel_text_antialiasing: false,
|
enable_subpixel_text_antialiasing: false,
|
||||||
vr_pointer: None,
|
vr_init: VRInitOptions::VRService(service, heartbeat),
|
||||||
coordinates,
|
coordinates,
|
||||||
};
|
};
|
||||||
let wakeup = Box::new(EventLoopWakerInstance);
|
let wakeup = Box::new(EventLoopWakerInstance);
|
||||||
|
@ -155,6 +160,7 @@ pub unsafe extern "C" fn init_servo(
|
||||||
ctxt,
|
ctxt,
|
||||||
surf,
|
surf,
|
||||||
disp,
|
disp,
|
||||||
|
landscape,
|
||||||
shut_down_complete: shut_down_complete.clone(),
|
shut_down_complete: shut_down_complete.clone(),
|
||||||
history_update,
|
history_update,
|
||||||
url_update,
|
url_update,
|
||||||
|
@ -316,6 +322,7 @@ struct HostCallbacks {
|
||||||
ctxt: EGLContext,
|
ctxt: EGLContext,
|
||||||
surf: EGLSurface,
|
surf: EGLSurface,
|
||||||
disp: EGLDisplay,
|
disp: EGLDisplay,
|
||||||
|
landscape: bool,
|
||||||
shut_down_complete: Rc<Cell<bool>>,
|
shut_down_complete: Rc<Cell<bool>>,
|
||||||
history_update: MLHistoryUpdate,
|
history_update: MLHistoryUpdate,
|
||||||
url_update: MLURLUpdate,
|
url_update: MLURLUpdate,
|
||||||
|
@ -325,7 +332,10 @@ struct HostCallbacks {
|
||||||
|
|
||||||
impl HostTrait for HostCallbacks {
|
impl HostTrait for HostCallbacks {
|
||||||
fn flush(&self) {
|
fn flush(&self) {
|
||||||
SwapBuffers(self.disp, self.surf);
|
// Immersive and landscape apps have different requirements for who calls SwapBuffers.
|
||||||
|
if self.landscape {
|
||||||
|
SwapBuffers(self.disp, self.surf);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_current(&self) {
|
fn make_current(&self) {
|
||||||
|
@ -337,12 +347,16 @@ impl HostTrait for HostCallbacks {
|
||||||
fn on_title_changed(&self, _title: String) {}
|
fn on_title_changed(&self, _title: String) {}
|
||||||
fn on_url_changed(&self, url: String) {
|
fn on_url_changed(&self, url: String) {
|
||||||
if let Ok(cstr) = CString::new(url.as_str()) {
|
if let Ok(cstr) = CString::new(url.as_str()) {
|
||||||
(self.url_update.0)(self.app, cstr.as_ptr());
|
if let Some(url_update) = self.url_update.0 {
|
||||||
|
url_update(self.app, cstr.as_ptr());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_history_changed(&self, can_go_back: bool, can_go_forward: bool) {
|
fn on_history_changed(&self, can_go_back: bool, can_go_forward: bool) {
|
||||||
(self.history_update.0)(self.app, can_go_back, can_go_forward);
|
if let Some(history_update) = self.history_update.0 {
|
||||||
|
history_update(self.app, can_go_back, can_go_forward);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_animating_changed(&self, _animating: bool) {}
|
fn on_animating_changed(&self, _animating: bool) {}
|
||||||
|
@ -352,7 +366,9 @@ impl HostTrait for HostCallbacks {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_ime_state_changed(&self, show: bool) {
|
fn on_ime_state_changed(&self, show: bool) {
|
||||||
(self.keyboard.0)(self.app, show)
|
if let Some(keyboard) = self.keyboard.0 {
|
||||||
|
keyboard(self.app, show)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -385,22 +401,29 @@ impl log::Log for MLLogger {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn log(&self, record: &log::Record) {
|
fn log(&self, record: &log::Record) {
|
||||||
let lvl = match record.level() {
|
if let Some(log) = self.0 {
|
||||||
log::Level::Error => MLLogLevel::Error,
|
let lvl = match record.level() {
|
||||||
log::Level::Warn => MLLogLevel::Warning,
|
log::Level::Error => MLLogLevel::Error,
|
||||||
log::Level::Info => MLLogLevel::Info,
|
log::Level::Warn => MLLogLevel::Warning,
|
||||||
log::Level::Debug => MLLogLevel::Debug,
|
log::Level::Info => MLLogLevel::Info,
|
||||||
log::Level::Trace => MLLogLevel::Verbose,
|
log::Level::Debug => MLLogLevel::Debug,
|
||||||
};
|
log::Level::Trace => MLLogLevel::Verbose,
|
||||||
let mut msg = SmallVec::<[u8; 128]>::new();
|
};
|
||||||
write!(msg, "{}\0", record.args()).unwrap();
|
let mut msg = SmallVec::<[u8; 128]>::new();
|
||||||
(self.0)(lvl, &msg[0] as *const _ as *const _);
|
write!(msg, "{}\0", record.args()).unwrap();
|
||||||
|
log(lvl, &msg[0] as *const _ as *const _);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn flush(&self) {}
|
fn flush(&self) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn redirect_stdout_to_log(logger: MLLogger) {
|
fn redirect_stdout_to_log(logger: MLLogger) {
|
||||||
|
let log = match logger.0 {
|
||||||
|
None => return,
|
||||||
|
Some(log) => log,
|
||||||
|
};
|
||||||
|
|
||||||
// The first step is to redirect stdout and stderr to the logs.
|
// The first step is to redirect stdout and stderr to the logs.
|
||||||
// We redirect stdout and stderr to a custom descriptor.
|
// We redirect stdout and stderr to a custom descriptor.
|
||||||
let mut pfd: [c_int; 2] = [0, 0];
|
let mut pfd: [c_int; 2] = [0, 0];
|
||||||
|
@ -439,7 +462,7 @@ fn redirect_stdout_to_log(logger: MLLogger) {
|
||||||
let end = if result == 0 {
|
let end = if result == 0 {
|
||||||
return;
|
return;
|
||||||
} else if result < 0 {
|
} else if result < 0 {
|
||||||
(logger.0)(
|
log(
|
||||||
MLLogLevel::Error,
|
MLLogLevel::Error,
|
||||||
b"error in log thread; closing\0".as_ptr() as *const _,
|
b"error in log thread; closing\0".as_ptr() as *const _,
|
||||||
);
|
);
|
||||||
|
@ -453,7 +476,7 @@ fn redirect_stdout_to_log(logger: MLLogger) {
|
||||||
|
|
||||||
if let Some(last_newline_pos) = buf.iter().rposition(|&c| c == b'\n' as c_char) {
|
if let Some(last_newline_pos) = buf.iter().rposition(|&c| c == b'\n' as c_char) {
|
||||||
buf[last_newline_pos] = b'\0' as c_char;
|
buf[last_newline_pos] = b'\0' as c_char;
|
||||||
(logger.0)(MLLogLevel::Info, buf.as_ptr());
|
log(MLLogLevel::Info, buf.as_ptr());
|
||||||
if last_newline_pos < buf.len() - 1 {
|
if last_newline_pos < buf.len() - 1 {
|
||||||
let pos_after_newline = last_newline_pos + 1;
|
let pos_after_newline = last_newline_pos + 1;
|
||||||
let len_not_logged_yet = buf[pos_after_newline..].len();
|
let len_not_logged_yet = buf[pos_after_newline..].len();
|
||||||
|
@ -467,7 +490,7 @@ fn redirect_stdout_to_log(logger: MLLogger) {
|
||||||
} else if end == BUF_AVAILABLE {
|
} else if end == BUF_AVAILABLE {
|
||||||
// No newline found but the buffer is full, flush it anyway.
|
// No newline found but the buffer is full, flush it anyway.
|
||||||
// `buf.as_ptr()` is null-terminated by BUF_LENGTH being 1 less than BUF_AVAILABLE.
|
// `buf.as_ptr()` is null-terminated by BUF_LENGTH being 1 less than BUF_AVAILABLE.
|
||||||
(logger.0)(MLLogLevel::Info, buf.as_ptr());
|
log(MLLogLevel::Info, buf.as_ptr());
|
||||||
cursor = 0;
|
cursor = 0;
|
||||||
} else {
|
} else {
|
||||||
cursor = end;
|
cursor = end;
|
||||||
|
|
|
@ -23,7 +23,7 @@ use servo::servo_config::opts;
|
||||||
use servo::servo_config::{pref, set_pref};
|
use servo::servo_config::{pref, set_pref};
|
||||||
use servo::servo_url::ServoUrl;
|
use servo::servo_url::ServoUrl;
|
||||||
use servo::webrender_api::{DevicePixel, FramebufferPixel, ScrollLocation};
|
use servo::webrender_api::{DevicePixel, FramebufferPixel, ScrollLocation};
|
||||||
use servo::webvr::{VRExternalShmemPtr, VRMainThreadHeartbeat, VRServiceManager};
|
use servo::webvr::{VRExternalShmemPtr, VRMainThreadHeartbeat, VRService, VRServiceManager};
|
||||||
use servo::{self, gl, BrowserId, Servo};
|
use servo::{self, gl, BrowserId, Servo};
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
@ -45,10 +45,16 @@ pub struct InitOptions {
|
||||||
pub url: Option<String>,
|
pub url: Option<String>,
|
||||||
pub coordinates: Coordinates,
|
pub coordinates: Coordinates,
|
||||||
pub density: f32,
|
pub density: f32,
|
||||||
pub vr_pointer: Option<*mut c_void>,
|
pub vr_init: VRInitOptions,
|
||||||
pub enable_subpixel_text_antialiasing: bool,
|
pub enable_subpixel_text_antialiasing: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub enum VRInitOptions {
|
||||||
|
None,
|
||||||
|
VRExternal(*mut c_void),
|
||||||
|
VRService(Box<VRService>, Box<VRMainThreadHeartbeat>),
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Coordinates {
|
pub struct Coordinates {
|
||||||
pub viewport: TypedRect<i32, DevicePixel>,
|
pub viewport: TypedRect<i32, DevicePixel>,
|
||||||
|
@ -177,7 +183,7 @@ pub fn init(
|
||||||
});
|
});
|
||||||
|
|
||||||
let embedder_callbacks = Box::new(ServoEmbedderCallbacks {
|
let embedder_callbacks = Box::new(ServoEmbedderCallbacks {
|
||||||
vr_pointer: init_opts.vr_pointer,
|
vr_init: init_opts.vr_init,
|
||||||
waker,
|
waker,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -551,7 +557,7 @@ impl ServoGlue {
|
||||||
|
|
||||||
struct ServoEmbedderCallbacks {
|
struct ServoEmbedderCallbacks {
|
||||||
waker: Box<dyn EventLoopWaker>,
|
waker: Box<dyn EventLoopWaker>,
|
||||||
vr_pointer: Option<*mut c_void>,
|
vr_init: VRInitOptions,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ServoWindowCallbacks {
|
struct ServoWindowCallbacks {
|
||||||
|
@ -563,17 +569,24 @@ struct ServoWindowCallbacks {
|
||||||
|
|
||||||
impl EmbedderMethods for ServoEmbedderCallbacks {
|
impl EmbedderMethods for ServoEmbedderCallbacks {
|
||||||
fn register_vr_services(
|
fn register_vr_services(
|
||||||
&self,
|
&mut self,
|
||||||
services: &mut VRServiceManager,
|
services: &mut VRServiceManager,
|
||||||
_: &mut Vec<Box<VRMainThreadHeartbeat>>,
|
heartbeats: &mut Vec<Box<VRMainThreadHeartbeat>>,
|
||||||
) {
|
) {
|
||||||
debug!("EmbedderMethods::register_vrexternal");
|
debug!("EmbedderMethods::register_vrexternal");
|
||||||
if let Some(ptr) = self.vr_pointer {
|
match mem::replace(&mut self.vr_init, VRInitOptions::None) {
|
||||||
services.register_vrexternal(VRExternalShmemPtr::new(ptr));
|
VRInitOptions::None => {},
|
||||||
|
VRInitOptions::VRExternal(ptr) => {
|
||||||
|
services.register_vrexternal(VRExternalShmemPtr::new(ptr));
|
||||||
|
},
|
||||||
|
VRInitOptions::VRService(service, heartbeat) => {
|
||||||
|
services.register(service);
|
||||||
|
heartbeats.push(heartbeat);
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_event_loop_waker(&self) -> Box<dyn EventLoopWaker> {
|
fn create_event_loop_waker(&mut self) -> Box<dyn EventLoopWaker> {
|
||||||
debug!("EmbedderMethods::create_event_loop_waker");
|
debug!("EmbedderMethods::create_event_loop_waker");
|
||||||
self.waker.clone()
|
self.waker.clone()
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,9 +6,8 @@
|
||||||
extern crate log;
|
extern crate log;
|
||||||
|
|
||||||
use env_logger;
|
use env_logger;
|
||||||
use simpleservo::{
|
use simpleservo::{self, gl_glue, ServoGlue, SERVO};
|
||||||
self, gl_glue, Coordinates, EventLoopWaker, HostTrait, InitOptions, ServoGlue, SERVO,
|
use simpleservo::{Coordinates, EventLoopWaker, HostTrait, InitOptions, VRInitOptions};
|
||||||
};
|
|
||||||
use std::ffi::{CStr, CString};
|
use std::ffi::{CStr, CString};
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::os::raw::{c_char, c_void};
|
use std::os::raw::{c_char, c_void};
|
||||||
|
@ -96,10 +95,10 @@ fn init(
|
||||||
url,
|
url,
|
||||||
coordinates,
|
coordinates,
|
||||||
density: opts.density,
|
density: opts.density,
|
||||||
vr_pointer: if opts.vr_pointer.is_null() {
|
vr_init: if opts.vr_pointer.is_null() {
|
||||||
None
|
VRInitOptions::None
|
||||||
} else {
|
} else {
|
||||||
Some(opts.vr_pointer)
|
VRInitOptions::VRExternal(opts.vr_pointer)
|
||||||
},
|
},
|
||||||
enable_subpixel_text_antialiasing: opts.enable_subpixel_text_antialiasing,
|
enable_subpixel_text_antialiasing: opts.enable_subpixel_text_antialiasing,
|
||||||
};
|
};
|
||||||
|
|
|
@ -13,9 +13,8 @@ use jni::sys::{jboolean, jfloat, jint, jstring, JNI_TRUE};
|
||||||
use jni::{errors, JNIEnv, JavaVM};
|
use jni::{errors, JNIEnv, JavaVM};
|
||||||
use libc::{dup2, pipe, read};
|
use libc::{dup2, pipe, read};
|
||||||
use log::Level;
|
use log::Level;
|
||||||
use simpleservo::{
|
use simpleservo::{self, gl_glue, ServoGlue, SERVO};
|
||||||
self, gl_glue, Coordinates, EventLoopWaker, HostTrait, InitOptions, ServoGlue, SERVO,
|
use simpleservo::{Coordinates, EventLoopWaker, HostTrait, InitOptions, VRInitOptions};
|
||||||
};
|
|
||||||
use std::os::raw::{c_char, c_int, c_void};
|
use std::os::raw::{c_char, c_int, c_void};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::thread;
|
use std::thread;
|
||||||
|
@ -696,10 +695,10 @@ fn get_options(env: &JNIEnv, opts: JObject) -> Result<(InitOptions, bool, Option
|
||||||
coordinates,
|
coordinates,
|
||||||
density,
|
density,
|
||||||
enable_subpixel_text_antialiasing,
|
enable_subpixel_text_antialiasing,
|
||||||
vr_pointer: if vr_pointer.is_null() {
|
vr_init: if vr_pointer.is_null() {
|
||||||
None
|
VRInitOptions::None
|
||||||
} else {
|
} else {
|
||||||
Some(vr_pointer)
|
VRInitOptions::VRExternal(vr_pointer)
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
Ok((opts, log, log_str))
|
Ok((opts, log, log_str))
|
||||||
|
|
|
@ -58,6 +58,7 @@ PACKAGES = {
|
||||||
],
|
],
|
||||||
'magicleap': [
|
'magicleap': [
|
||||||
'target/magicleap/aarch64-linux-android/release/Servo2D.mpk',
|
'target/magicleap/aarch64-linux-android/release/Servo2D.mpk',
|
||||||
|
'target/magicleap/aarch64-linux-android/release/Servo3D.mpk',
|
||||||
],
|
],
|
||||||
'maven': [
|
'maven': [
|
||||||
'target/android/gradle/servoview/maven/org/mozilla/servoview/servoview-armv7/',
|
'target/android/gradle/servoview/maven/org/mozilla/servoview/servoview-armv7/',
|
||||||
|
@ -230,22 +231,26 @@ class PackageCommands(CommandBase):
|
||||||
if not env.get("MLCERT"):
|
if not env.get("MLCERT"):
|
||||||
raise Exception("Magic Leap builds need the MLCERT environment variable")
|
raise Exception("Magic Leap builds need the MLCERT environment variable")
|
||||||
mabu = path.join(env.get("MAGICLEAP_SDK"), "mabu")
|
mabu = path.join(env.get("MAGICLEAP_SDK"), "mabu")
|
||||||
package = "./support/magicleap/Servo2D/Servo2D.package"
|
packages = [
|
||||||
|
"./support/magicleap/Servo3D/Servo3D.package",
|
||||||
|
"./support/magicleap/Servo2D/Servo2D.package",
|
||||||
|
]
|
||||||
if dev:
|
if dev:
|
||||||
build_type = "lumin_debug"
|
build_type = "lumin_debug"
|
||||||
else:
|
else:
|
||||||
build_type = "lumin_release"
|
build_type = "lumin_release"
|
||||||
argv = [
|
for package in packages:
|
||||||
mabu,
|
argv = [
|
||||||
"-o", target_dir,
|
mabu,
|
||||||
"-t", build_type,
|
"-o", target_dir,
|
||||||
package
|
"-t", build_type,
|
||||||
]
|
package
|
||||||
try:
|
]
|
||||||
subprocess.check_call(argv, env=env)
|
try:
|
||||||
except subprocess.CalledProcessError as e:
|
subprocess.check_call(argv, env=env)
|
||||||
print("Packaging Magic Leap exited with return value %d" % e.returncode)
|
except subprocess.CalledProcessError as e:
|
||||||
return e.returncode
|
print("Packaging Magic Leap exited with return value %d" % e.returncode)
|
||||||
|
return e.returncode
|
||||||
elif android:
|
elif android:
|
||||||
android_target = self.config["android"]["target"]
|
android_target = self.config["android"]["target"]
|
||||||
if "aarch64" in android_target:
|
if "aarch64" in android_target:
|
||||||
|
|
|
@ -66,7 +66,7 @@ void keyboard(Servo2D* app, bool visible) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// The functions Servo provides for hooking up to the ML.
|
// 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,
|
Servo2D*, MLLogger, MLHistoryUpdate, MLURLUpdate, MLKeyboard,
|
||||||
const char* url, const char* args, int width, int height, float hidpi);
|
const char* url, const char* args, int width, int height, float hidpi);
|
||||||
extern "C" void heartbeat_servo(ServoInstance*);
|
extern "C" void heartbeat_servo(ServoInstance*);
|
||||||
|
@ -174,7 +174,9 @@ int Servo2D::init() {
|
||||||
EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
|
EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
|
||||||
|
|
||||||
// Hook into servo
|
// 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_) {
|
if (!servo_) {
|
||||||
ML_LOG(Error, "Servo2D Failed to init servo instance");
|
ML_LOG(Error, "Servo2D Failed to init servo instance");
|
||||||
abort();
|
abort();
|
||||||
|
|
257
support/magicleap/Servo3D/Servo3D.cpp
Normal file
257
support/magicleap/Servo3D/Servo3D.cpp
Normal file
|
@ -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;
|
||||||
|
}
|
24
support/magicleap/Servo3D/Servo3D.mabu
Normal file
24
support/magicleap/Servo3D/Servo3D.mabu
Normal file
|
@ -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
|
8
support/magicleap/Servo3D/Servo3D.package
Normal file
8
support/magicleap/Servo3D/Servo3D.package
Normal file
|
@ -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
|
19
support/magicleap/Servo3D/fonts.xml
Normal file
19
support/magicleap/Servo3D/fonts.xml
Normal file
|
@ -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>
|
23
support/magicleap/Servo3D/manifest.xml
Normal file
23
support/magicleap/Servo3D/manifest.xml
Normal file
|
@ -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>
|
Loading…
Add table
Add a link
Reference in a new issue