Skip to content
Permalink
Browse files

Add Servo3D immersive demo for magicleap

  • Loading branch information...
asajeffrey committed Apr 25, 2019
1 parent 4c776f3 commit 456f50c9d6deee3706c2f64fdfff653808edd28e

Some generated files are not rendered by default. Learn more.

@@ -22,7 +22,8 @@ gleam = "0.6"
ipc-channel = "0.11.2"
log = "0.4"
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"}
servo_config = {path = "../config"}
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::VRMainThreadHeartbeat;
pub use rust_webvr::VRServiceManager;
pub use rust_webvr_api::VRService;
@@ -13,5 +13,5 @@ path = "lib.rs"
[dependencies]
ipc-channel = "0.11"
msg = {path = "../msg"}
rust-webvr-api = {version = "0.11.1", features = ["ipc"]}
rust-webvr-api = {version = "0.11.4", features = ["ipc"]}
serde = "1.0"
@@ -19,6 +19,7 @@ raqote_backend = ["simpleservo/raqote_backend"]
[dependencies]
libservo = { path = "../../components/servo", features = ["no_static_freetype"] }
simpleservo = { path = "../libsimpleservo/api", features = ["no_static_freetype"] }
rust-webvr = { version = "0.11", features = ["magicleap"] }
libc = "0.2"
log = "0.4"
servo-egl = "0.2"
@@ -10,12 +10,17 @@ use egl::egl::SwapBuffers;
use libc::{dup2, pipe, read};
use log::info;
use log::warn;
use rust_webvr::api::MagicLeapVRService;
use servo::compositing::windowing::EmbedderMethods;
use servo::euclid::TypedScale;
use servo::gl::Gl;
use servo::keyboard_types::Key;
use servo::servo_url::ServoUrl;
use servo::webrender_api::DevicePixel;
use servo::webrender_api::DevicePoint;
use servo::webrender_api::LayoutPixel;
use servo::webvr::VRMainThreadHeartbeat;
use servo::webvr::VRServiceManager;
use simpleservo::{
self, deinit, gl_glue, Coordinates, EventLoopWaker, HostTrait, InitOptions, MouseButton,
ServoGlue, SERVO,
@@ -70,16 +75,16 @@ pub enum MLKeyType {

#[repr(transparent)]
#[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)]
pub struct MLHistoryUpdate(extern "C" fn(MLApp, bool, bool));
pub struct MLHistoryUpdate(Option<extern "C" fn(MLApp, bool, bool)>);

#[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)]
pub struct MLKeyboard(extern "C" fn(MLApp, bool));
pub struct MLKeyboard(Option<extern "C" fn(MLApp, bool)>);

#[repr(transparent)]
#[derive(Clone, Copy)]
@@ -102,6 +107,7 @@ pub unsafe extern "C" fn init_servo(
ctxt: EGLContext,
surf: EGLSurface,
disp: EGLDisplay,
landscape: bool,
app: MLApp,
logger: MLLogger,
history_update: MLHistoryUpdate,
@@ -140,28 +146,33 @@ pub unsafe extern "C" fn init_servo(
};
info!("got args: {:?}", args);

let embedder_callbacks = Box::new(MLEmbedderMethods {
vr_display_name: String::from("Magic Leap VR Display"),
egl_context: ctxt,
gl: gl.clone(),
});
let opts = InitOptions {
args,
url: Some(url.to_string()),
density: hidpi,
enable_subpixel_text_antialiasing: false,
vr_pointer: None,
embedder_callbacks,
coordinates,
};
let wakeup = Box::new(EventLoopWakerInstance);
let shut_down_complete = Rc::new(Cell::new(false));
let callbacks = Box::new(HostCallbacks {
app,
ctxt,
surf,
disp,
landscape,
shut_down_complete: shut_down_complete.clone(),
history_update,
url_update,
keyboard,
});
info!("Starting servo");
simpleservo::init(opts, gl, wakeup, callbacks).expect("error initializing Servo");
simpleservo::init(opts, gl, callbacks).expect("error initializing Servo");

let result = Box::new(ServoInstance {
scroll_state: ScrollState::TriggerUp,
@@ -316,6 +327,7 @@ struct HostCallbacks {
ctxt: EGLContext,
surf: EGLSurface,
disp: EGLDisplay,
landscape: bool,
shut_down_complete: Rc<Cell<bool>>,
history_update: MLHistoryUpdate,
url_update: MLURLUpdate,
@@ -325,7 +337,10 @@ struct HostCallbacks {

impl HostTrait for HostCallbacks {
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) {
@@ -337,12 +352,16 @@ impl HostTrait for HostCallbacks {
fn on_title_changed(&self, _title: String) {}
fn on_url_changed(&self, url: String) {
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) {
(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) {}
@@ -352,7 +371,9 @@ impl HostTrait for HostCallbacks {
}

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)
}
}
}

@@ -369,11 +390,39 @@ enum ScrollState {
TriggerDragging(DevicePoint, DevicePoint),
}

struct EventLoopWakerInstance;
struct MLEmbedderMethods {
vr_display_name: String,
egl_context: EGLContext,
gl: Rc<Gl>,
}

impl EmbedderMethods for MLEmbedderMethods {
fn create_event_loop_waker(&self) -> Box<dyn EventLoopWaker> {
Box::new(MLEventLoopWaker)
}

impl EventLoopWaker for EventLoopWakerInstance {
fn register_vr_services(
&self,
services: &mut VRServiceManager,
heartbeats: &mut Vec<Box<VRMainThreadHeartbeat>>,
) {
if let Ok((service, heartbeat)) = MagicLeapVRService::new(
self.vr_display_name.clone(),
self.egl_context,
self.gl.clone(),
) {
info!("Registering VR services");
services.register(Box::new(service));
heartbeats.push(Box::new(heartbeat));
}
}
}

struct MLEventLoopWaker;

impl EventLoopWaker for MLEventLoopWaker {
fn clone(&self) -> Box<EventLoopWaker + Send> {
Box::new(EventLoopWakerInstance)
Box::new(MLEventLoopWaker)
}

fn wake(&self) {}
@@ -385,22 +434,29 @@ impl log::Log for MLLogger {
}

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::<[u8; 128]>::new();
write!(msg, "{}\0", record.args()).unwrap();
(self.0)(lvl, &msg[0] as *const _ as *const _);
if let Some(log) = self.0 {
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::<[u8; 128]>::new();
write!(msg, "{}\0", record.args()).unwrap();
log(lvl, &msg[0] as *const _ as *const _);
}
}

fn flush(&self) {}
}

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.
// We redirect stdout and stderr to a custom descriptor.
let mut pfd: [c_int; 2] = [0, 0];
@@ -439,7 +495,7 @@ fn redirect_stdout_to_log(logger: MLLogger) {
let end = if result == 0 {
return;
} else if result < 0 {
(logger.0)(
log(
MLLogLevel::Error,
b"error in log thread; closing\0".as_ptr() as *const _,
);
@@ -453,7 +509,7 @@ fn redirect_stdout_to_log(logger: MLLogger) {

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;
(logger.0)(MLLogLevel::Info, buf.as_ptr());
log(MLLogLevel::Info, buf.as_ptr());
if last_newline_pos < buf.len() - 1 {
let pos_after_newline = last_newline_pos + 1;
let len_not_logged_yet = buf[pos_after_newline..].len();
@@ -467,7 +523,7 @@ fn redirect_stdout_to_log(logger: MLLogger) {
} else if end == BUF_AVAILABLE {
// 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.
(logger.0)(MLLogLevel::Info, buf.as_ptr());
log(MLLogLevel::Info, buf.as_ptr());
cursor = 0;
} else {
cursor = end;

0 comments on commit 456f50c

Please sign in to comment.
You can’t perform that action at this time.