Skip to content
Permalink
Browse files

Use a test VRDisplay that renders to a GL window

  • Loading branch information...
asajeffrey committed Feb 15, 2019
1 parent de3d2f7 commit cc2d20315149887ee1f125deac1a1807722a50ee

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

Oops, something went wrong.
@@ -39,6 +39,7 @@ style_traits = {path = "../style_traits"}
time = "0.1.17"
webrender = {git = "https://github.com/servo/webrender", features = ["capture"]}
webrender_api = {git = "https://github.com/servo/webrender", features = ["ipc"]}
webvr_traits = {path = "../webvr_traits"}
webvr = {path = "../webvr"}

[build-dependencies]
@@ -43,6 +43,7 @@ use style_traits::{CSSPixel, DevicePixel, PinchZoomFactor};
use time::{now, precise_time_ns, precise_time_s};
use webrender_api::{self, DeviceIntPoint, DevicePoint, HitTestFlags, HitTestResult};
use webrender_api::{LayoutVector2D, ScrollLocation};
use webvr_traits::WebVRMainThreadHeartbeat;

#[derive(Debug, PartialEq)]
enum UnableToComposite {
@@ -176,6 +177,9 @@ pub struct IOCompositor<Window: WindowMethods> {
/// The webrender interface, if enabled.
webrender_api: webrender_api::RenderApi,

/// Some VR displays want to be sent a heartbeat from the main thread.
webvr_heartbeats: Vec<Box<dyn WebVRMainThreadHeartbeat>>,

/// Map of the pending paint metrics per layout thread.
/// The layout thread for each specific pipeline expects the compositor to
/// paint frames with specific given IDs (epoch). Once the compositor paints
@@ -283,6 +287,7 @@ impl<Window: WindowMethods> IOCompositor<Window> {
webrender: state.webrender,
webrender_document: state.webrender_document,
webrender_api: state.webrender_api,
webvr_heartbeats: state.webvr_heartbeats,
pending_paint_metrics: HashMap::new(),
}
}
@@ -919,7 +924,7 @@ impl<Window: WindowMethods> IOCompositor<Window> {
pipeline_ids.push(*pipeline_id);
}
}
let animation_state = if pipeline_ids.is_empty() {
let animation_state = if pipeline_ids.is_empty() && !self.webvr_heartbeats_racing() {
windowing::AnimationState::Idle
} else {
windowing::AnimationState::Animating
@@ -930,6 +935,10 @@ impl<Window: WindowMethods> IOCompositor<Window> {
}
}

fn webvr_heartbeats_racing(&self) -> bool {
self.webvr_heartbeats.iter().any(|hb| hb.heart_racing())
}

fn tick_animations_for_pipeline(&mut self, pipeline_id: PipelineId) {
let animation_callbacks_running = self
.pipeline_details(pipeline_id)
@@ -1345,6 +1354,11 @@ impl<Window: WindowMethods> IOCompositor<Window> {
CompositionRequest::CompositeNow(_) => self.composite(),
}

// Send every VR display that wants one a main-thread heartbeat
for webvr_heartbeat in &mut self.webvr_heartbeats {
webvr_heartbeat.heartbeat();
}

if !self.pending_scroll_zoom_events.is_empty() && !self.waiting_for_results_of_scroll {
self.process_pending_scroll_events()
}
@@ -18,6 +18,7 @@ use script_traits::{AnimationState, ConstellationMsg, EventResult};
use std::fmt::{Debug, Error, Formatter};
use style_traits::viewport::ViewportConstraints;
use webrender_api::{self, DeviceIntPoint, DeviceIntSize};
use webvr_traits::WebVRMainThreadHeartbeat;

/// Sends messages to the compositor.
pub struct CompositorProxy {
@@ -153,4 +154,5 @@ pub struct InitialCompositorState {
pub webrender: webrender::Renderer,
pub webrender_document: webrender_api::DocumentId,
pub webrender_api: webrender_api::RenderApi,
pub webvr_heartbeats: Vec<Box<WebVRMainThreadHeartbeat>>,
}
@@ -19,6 +19,7 @@ use std::rc::Rc;
use style_traits::DevicePixel;
use webrender_api::{DeviceIntPoint, DeviceIntRect, DeviceIntSize, DevicePoint, ScrollLocation};
use webvr::VRServiceManager;
use webvr_traits::WebVRMainThreadHeartbeat;

#[derive(Clone)]
pub enum MouseWindowEvent {
@@ -147,7 +148,12 @@ pub trait WindowMethods {
/// run the event loop at the vsync interval.
fn set_animation_state(&self, _state: AnimationState);
/// Register services with a VRServiceManager.
fn register_vr_services(&self, _: &mut VRServiceManager) {}
fn register_vr_services(
&self,
_: &mut VRServiceManager,
_: &mut Vec<Box<WebVRMainThreadHeartbeat>>,
) {
}
}

#[derive(Clone, Copy, Debug)]
@@ -257,10 +257,11 @@ where
// can't defer it after `create_constellation` has started.
script::init();

let mut webvr_heartbeats = Vec::new();
let webvr_services = if PREFS.is_webvr_enabled() {
let mut services = VRServiceManager::new();
services.register_defaults();
window.register_vr_services(&mut services);
window.register_vr_services(&mut services, &mut webvr_heartbeats);
Some(services)
} else {
None
@@ -307,6 +308,7 @@ where
webrender,
webrender_document,
webrender_api,
webvr_heartbeats,
},
);

@@ -22,7 +22,7 @@ gleam = "0.6"
ipc-channel = "0.11"
log = "0.4"
msg = {path = "../msg"}
rust-webvr = {version = "0.10", features = ["openvr", "vrexternal"]}
rust-webvr = {version = "0.10.2", features = ["openvr", "vrexternal"]}
script_traits = {path = "../script_traits"}
servo_config = {path = "../config"}
webvr_traits = {path = "../webvr_traits" }
@@ -10,4 +10,5 @@ extern crate log;
mod webvr_thread;
pub use crate::webvr_thread::{WebVRCompositorHandler, WebVRThread};
pub use rust_webvr::api::VRExternalShmemPtr;
pub use rust_webvr::VRMainThreadHeartbeat;
pub use rust_webvr::VRServiceManager;
@@ -27,5 +27,6 @@ pub use rust_webvr_api::VRGamepadEvent as WebVRGamepadEvent;
pub use rust_webvr_api::VRGamepadHand as WebVRGamepadHand;
pub use rust_webvr_api::VRGamepadState as WebVRGamepadState;
pub use rust_webvr_api::VRLayer as WebVRLayer;
pub use rust_webvr_api::VRMainThreadHeartbeat as WebVRMainThreadHeartbeat;
pub use rust_webvr_api::VRPose as WebVRPose;
pub use rust_webvr_api::VRStageParameters as WebVRStageParameters;
@@ -18,7 +18,7 @@ use servo::script_traits::{MouseButton, TouchEventType, TouchId};
use servo::servo_config::opts;
use servo::servo_config::prefs::{PrefValue, PREFS};
use servo::servo_url::ServoUrl;
use servo::webvr::{VRExternalShmemPtr, VRServiceManager};
use servo::webvr::{VRExternalShmemPtr, VRMainThreadHeartbeat, VRServiceManager};
use servo::{self, gl, webrender_api, BrowserId, Servo};
use std::cell::{Cell, RefCell};
use std::mem;
@@ -536,7 +536,11 @@ impl WindowMethods for ServoCallbacks {
}
}

fn register_vr_services(&self, services: &mut VRServiceManager) {
fn register_vr_services(
&self,
services: &mut VRServiceManager,
_: &mut Vec<Box<VRMainThreadHeartbeat>>,
) {
if let Some(ptr) = self.vr_pointer {
services.register_vrexternal(VRExternalShmemPtr::new(ptr));
}
@@ -51,6 +51,7 @@ lazy_static = "1"
libservo = {path = "../../components/servo"}
libc = "0.2"
log = "0.4"
rust-webvr = { version = "0.10.2", features = ["glwindow"] }
tinyfiledialogs = "3.0"
winit = {version = "0.18", features = ["icon_loading"]}

@@ -8,14 +8,18 @@ use euclid::{TypedPoint2D, TypedVector2D, TypedScale, TypedSize2D};
use gleam::gl;
use glutin::{Api, ContextBuilder, GlContext, GlRequest, GlWindow};
use keyboard_types::{Key, KeyboardEvent, KeyState};
use rust_webvr::GlWindowVRService;
use servo::compositing::windowing::{AnimationState, MouseWindowEvent, WindowEvent};
use servo::compositing::windowing::{EmbedderCoordinates, WindowMethods};
use servo::embedder_traits::{Cursor, EventLoopWaker};
use servo::script_traits::TouchEventType;
use servo::servo_config::opts;
use servo::servo_config::prefs::PREFS;
use servo::servo_geometry::DeviceIndependentPixel;
use servo::style_traits::DevicePixel;
use servo::webrender_api::{DeviceIntPoint, DeviceIntRect, DeviceIntSize, ScrollLocation};
use servo::webvr::VRServiceManager;
use servo::webvr_traits::WebVRMainThreadHeartbeat;
use std::cell::{Cell, RefCell};
#[cfg(any(target_os = "linux", target_os = "macos"))]
use std::ffi::CString;
@@ -440,6 +444,13 @@ impl Window {
}

fn winit_event_to_servo_event(&self, event: winit::Event) {
if let WindowKind::Window(ref window, _) = self.kind {
if let Event::WindowEvent { window_id, .. } = event {
if window.id() != window_id {
return;
}
}
}
match event {
Event::WindowEvent {
event: winit::WindowEvent::ReceivedCharacter(ch),
@@ -775,6 +786,39 @@ impl WindowMethods for Window {
};
true
}

fn register_vr_services(
&self,
services: &mut VRServiceManager,
heartbeats: &mut Vec<Box<WebVRMainThreadHeartbeat>>
) {
if PREFS.get("dom.webvr.test").as_boolean().unwrap_or(false) {
warn!("Creating test VR display");
// TODO: support dom.webvr.test in headless environments
if let WindowKind::Window(_, ref events_loop) = self.kind {
// This is safe, because register_vr_services is called from the main thread.
let name = String::from("Test VR Display");
let size = self.inner_size.get().to_f64();
let size = LogicalSize::new(size.width, size.height);
let mut window_builder = winit::WindowBuilder::new()
.with_title(name.clone())
.with_dimensions(size)
.with_visibility(false)
.with_multitouch();
window_builder = builder_with_platform_options(window_builder);
let context_builder = ContextBuilder::new()
.with_gl(Window::gl_version())
.with_vsync(false); // Assume the browser vsync is the same as the test VR window vsync
let gl_window = GlWindow::new(window_builder, context_builder, &*events_loop.borrow())
.expect("Failed to create window.");
let gl = self.gl.clone();
let (service, heartbeat) = GlWindowVRService::new(name, gl_window, gl);

services.register(Box::new(service));
heartbeats.push(Box::new(heartbeat));
}
}
}
}

fn winit_phase_to_touch_event_type(phase: TouchPhase) -> TouchEventType {

0 comments on commit cc2d203

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