Allow webvr thread consumers to request input data

This commit is contained in:
Manish Goregaokar 2019-04-23 10:16:56 -07:00
parent 623507187b
commit c1a8605c3d
4 changed files with 39 additions and 11 deletions

View file

@ -12,7 +12,7 @@ use std::fmt;
use std::num::NonZeroU32; use std::num::NonZeroU32;
use std::ops::Deref; use std::ops::Deref;
use webrender_api::{DocumentId, ImageKey, PipelineId}; use webrender_api::{DocumentId, ImageKey, PipelineId};
use webvr_traits::WebVRFutureFrameData; use webvr_traits::WebVRPoseInformation;
/// Helper function that creates a WebGL channel (WebGLSender, WebGLReceiver) to be used in WebGLCommands. /// Helper function that creates a WebGL channel (WebGLSender, WebGLReceiver) to be used in WebGLCommands.
pub use crate::webgl_channel::webgl_channel; pub use crate::webgl_channel::webgl_channel;
@ -508,9 +508,13 @@ pub enum WebVRCommand {
/// Synchronize the pose information to be used in the frame. /// Synchronize the pose information to be used in the frame.
SyncPoses( SyncPoses(
WebVRDeviceId, WebVRDeviceId,
// near
f64, f64,
// far
f64, f64,
WebGLSender<Result<WebVRFutureFrameData, ()>>, // sync gamepads too
bool,
WebGLSender<Result<WebVRPoseInformation, ()>>,
), ),
/// Submit the frame to a VR device using the specified texture coordinates. /// Submit the frame to a VR device using the specified texture coordinates.
SubmitFrame(WebVRDeviceId, [f32; 4], [f32; 4]), SubmitFrame(WebVRDeviceId, [f32; 4], [f32; 4]),

View file

@ -51,7 +51,7 @@ use std::mem;
use std::ops::Deref; use std::ops::Deref;
use std::rc::Rc; use std::rc::Rc;
use std::thread; use std::thread;
use webvr_traits::{WebVRDisplayData, WebVRDisplayEvent, WebVRFrameData, WebVRFutureFrameData}; use webvr_traits::{WebVRDisplayData, WebVRDisplayEvent, WebVRFrameData, WebVRPoseInformation};
use webvr_traits::{WebVRLayer, WebVRMsg}; use webvr_traits::{WebVRLayer, WebVRMsg};
#[dom_struct] #[dom_struct]
@ -86,7 +86,7 @@ pub struct VRDisplay {
// Compositor VRFrameData synchonization // Compositor VRFrameData synchonization
frame_data_status: Cell<VRFrameDataStatus>, frame_data_status: Cell<VRFrameDataStatus>,
#[ignore_malloc_size_of = "closures are hard"] #[ignore_malloc_size_of = "closures are hard"]
frame_data_receiver: DomRefCell<Option<WebGLReceiver<Result<WebVRFutureFrameData, ()>>>>, frame_data_receiver: DomRefCell<Option<WebGLReceiver<Result<WebVRPoseInformation, ()>>>>,
running_display_raf: Cell<bool>, running_display_raf: Cell<bool>,
paused: Cell<bool>, paused: Cell<bool>,
stopped_on_pause: Cell<bool>, stopped_on_pause: Cell<bool>,
@ -726,8 +726,13 @@ impl VRDisplay {
.unwrap(); .unwrap();
// Run Sync Poses in parallell on Render thread // Run Sync Poses in parallell on Render thread
let msg = let msg = WebVRCommand::SyncPoses(
WebVRCommand::SyncPoses(display_id, near, far, sync_sender.clone()); display_id,
near,
far,
false,
sync_sender.clone(),
);
api_sender.send_vr(msg).unwrap(); api_sender.send_vr(msg).unwrap();
} else { } else {
let _ = wakeup_receiver.recv(); let _ = wakeup_receiver.recv();
@ -808,8 +813,8 @@ impl VRDisplay {
fn sync_frame_data(&self) { fn sync_frame_data(&self) {
let status = if let Some(receiver) = self.frame_data_receiver.borrow().as_ref() { let status = if let Some(receiver) = self.frame_data_receiver.borrow().as_ref() {
match receiver.recv().unwrap() { match receiver.recv().unwrap() {
Ok(future_data) => { Ok(pose) => {
*self.frame_data.borrow_mut() = future_data.block(); *self.frame_data.borrow_mut() = pose.frame.block();
VRFrameDataStatus::Synced VRFrameDataStatus::Synced
}, },
Err(()) => VRFrameDataStatus::Exit, Err(()) => VRFrameDataStatus::Exit,

View file

@ -16,7 +16,7 @@ use std::collections::hash_map::Entry;
use std::collections::{HashMap, HashSet}; use std::collections::{HashMap, HashSet};
use std::{thread, time}; use std::{thread, time};
use webvr_traits::webvr::*; use webvr_traits::webvr::*;
use webvr_traits::{WebVRMsg, WebVRResult}; use webvr_traits::{WebVRMsg, WebVRPoseInformation, WebVRResult};
/// WebVRThread owns native VRDisplays, handles their life cycle inside Servo and /// WebVRThread owns native VRDisplays, handles their life cycle inside Servo and
/// acts a doorman for untrusted VR requests from DOM Objects. These are the key components /// acts a doorman for untrusted VR requests from DOM Objects. These are the key components
@ -386,10 +386,23 @@ impl webgl::WebVRRenderHandler for WebVRCompositorHandler {
unsafe { (*compositor.0).start_present(None) }; unsafe { (*compositor.0).start_present(None) };
} }
}, },
webgl::WebVRCommand::SyncPoses(compositor_id, near, far, sender) => { webgl::WebVRCommand::SyncPoses(compositor_id, near, far, get_gamepads, sender) => {
if let Some(compositor) = self.compositors.get(&compositor_id) { if let Some(compositor) = self.compositors.get(&compositor_id) {
let pose = unsafe { (*compositor.0).future_frame_data(near, far) }; let pose = unsafe { (*compositor.0).future_frame_data(near, far) };
let _ = sender.send(Ok(pose)); let mut pose_information = WebVRPoseInformation {
frame: pose,
gamepads: vec![],
};
if get_gamepads {
let gamepads = unsafe { (*compositor.0).fetch_gamepads() };
if let Ok(gamepads) = gamepads {
for gamepad in gamepads {
let g = gamepad.borrow();
pose_information.gamepads.push((g.id(), g.state()));
}
}
}
let _ = sender.send(Ok(pose_information));
} else { } else {
let _ = sender.send(Err(())); let _ = sender.send(Err(()));
} }

View file

@ -30,3 +30,9 @@ pub use rust_webvr_api::VRLayer as WebVRLayer;
pub use rust_webvr_api::VRMainThreadHeartbeat as WebVRMainThreadHeartbeat; pub use rust_webvr_api::VRMainThreadHeartbeat as WebVRMainThreadHeartbeat;
pub use rust_webvr_api::VRPose as WebVRPose; pub use rust_webvr_api::VRPose as WebVRPose;
pub use rust_webvr_api::VRStageParameters as WebVRStageParameters; pub use rust_webvr_api::VRStageParameters as WebVRStageParameters;
#[derive(Deserialize, Serialize)]
pub struct WebVRPoseInformation {
pub frame: WebVRFutureFrameData,
pub gamepads: Vec<(u32, WebVRGamepadState)>,
}