Move viewports to being per-session, not per-frame

This commit is contained in:
Manish Goregaokar 2020-05-14 11:18:34 -07:00
parent eaad692c0b
commit 794624b42b
5 changed files with 44 additions and 23 deletions

4
Cargo.lock generated
View file

@ -6471,7 +6471,7 @@ dependencies = [
[[package]] [[package]]
name = "webxr" name = "webxr"
version = "0.0.1" version = "0.0.1"
source = "git+https://github.com/servo/webxr#133663f06f9f0fdffeb046b03ce12205b8515847" source = "git+https://github.com/servo/webxr#a73b150f1e1a946fd90bd1ccf0056e35c3eef0d2"
dependencies = [ dependencies = [
"android_injected_glue", "android_injected_glue",
"bindgen", "bindgen",
@ -6494,7 +6494,7 @@ dependencies = [
[[package]] [[package]]
name = "webxr-api" name = "webxr-api"
version = "0.0.1" version = "0.0.1"
source = "git+https://github.com/servo/webxr#133663f06f9f0fdffeb046b03ce12205b8515847" source = "git+https://github.com/servo/webxr#a73b150f1e1a946fd90bd1ccf0056e35c3eef0d2"
dependencies = [ dependencies = [
"euclid", "euclid",
"ipc-channel", "ipc-channel",

View file

@ -40,7 +40,7 @@ use crate::dom::xrspace::XRSpace;
use crate::realms::InRealm; use crate::realms::InRealm;
use crate::task_source::TaskSource; use crate::task_source::TaskSource;
use dom_struct::dom_struct; use dom_struct::dom_struct;
use euclid::{Rect, RigidTransform3D, Transform3D, Vector3D}; use euclid::{RigidTransform3D, Transform3D, Vector3D};
use ipc_channel::ipc::IpcReceiver; use ipc_channel::ipc::IpcReceiver;
use ipc_channel::router::ROUTER; use ipc_channel::router::ROUTER;
use metrics::ToMs; use metrics::ToMs;
@ -463,17 +463,10 @@ impl XRSession {
/// Constructs a View suitable for inline sessions using the inlineVerticalFieldOfView and canvas size /// Constructs a View suitable for inline sessions using the inlineVerticalFieldOfView and canvas size
pub fn inline_view(&self) -> View<Viewer> { pub fn inline_view(&self) -> View<Viewer> {
debug_assert!(!self.is_immersive()); debug_assert!(!self.is_immersive());
let size = self
.active_render_state
.get()
.GetBaseLayer()
.expect("Must never construct views when base layer is not set")
.size();
View { View {
// Inline views have no offset // Inline views have no offset
transform: RigidTransform3D::identity(), transform: RigidTransform3D::identity(),
projection: *self.inline_projection_matrix.borrow(), projection: *self.inline_projection_matrix.borrow(),
viewport: Rect::from_size(size.to_i32()),
} }
} }

View file

@ -21,6 +21,7 @@ pub struct XRView {
reflector_: Reflector, reflector_: Reflector,
session: Dom<XRSession>, session: Dom<XRSession>,
eye: XREye, eye: XREye,
viewport_index: usize,
#[ignore_malloc_size_of = "mozjs"] #[ignore_malloc_size_of = "mozjs"]
proj: Heap<*mut JSObject>, proj: Heap<*mut JSObject>,
#[ignore_malloc_size_of = "defined in rust-webxr"] #[ignore_malloc_size_of = "defined in rust-webxr"]
@ -33,27 +34,26 @@ impl XRView {
session: &XRSession, session: &XRSession,
transform: &XRRigidTransform, transform: &XRRigidTransform,
eye: XREye, eye: XREye,
viewport_index: usize,
view: View<ApiSpace>, view: View<ApiSpace>,
) -> XRView { ) -> XRView {
XRView { XRView {
reflector_: Reflector::new(), reflector_: Reflector::new(),
session: Dom::from_ref(session), session: Dom::from_ref(session),
eye, eye,
viewport_index,
proj: Heap::default(), proj: Heap::default(),
view, view,
transform: Dom::from_ref(transform), transform: Dom::from_ref(transform),
} }
} }
pub fn view(&self) -> &View<ApiSpace> {
&self.view
}
pub fn new<V: Copy>( pub fn new<V: Copy>(
global: &GlobalScope, global: &GlobalScope,
session: &XRSession, session: &XRSession,
view: &View<V>, view: &View<V>,
eye: XREye, eye: XREye,
viewport_index: usize,
pose: &ApiViewerPose, pose: &ApiViewerPose,
) -> DomRoot<XRView> { ) -> DomRoot<XRView> {
// XXXManishearth compute and cache projection matrices on the Display // XXXManishearth compute and cache projection matrices on the Display
@ -70,6 +70,7 @@ impl XRView {
session, session,
&transform, &transform,
eye, eye,
viewport_index,
view.cast_unit(), view.cast_unit(),
)), )),
global, global,
@ -79,6 +80,10 @@ impl XRView {
pub fn session(&self) -> &XRSession { pub fn session(&self) -> &XRSession {
&self.session &self.session
} }
pub fn viewport_index(&self) -> usize {
self.viewport_index
}
} }
impl XRViewMethods for XRView { impl XRViewMethods for XRView {

View file

@ -49,19 +49,27 @@ impl XRViewerPose {
session, session,
&session.inline_view(), &session.inline_view(),
XREye::None, XREye::None,
0,
&pose, &pose,
)), )),
Views::Mono(view) => { Views::Mono(view) => {
views.push(XRView::new(global, session, &view, XREye::None, &pose)) views.push(XRView::new(global, session, &view, XREye::None, 0, &pose))
}, },
Views::Stereo(left, right) => { Views::Stereo(left, right) => {
views.push(XRView::new(global, session, &left, XREye::Left, &pose)); views.push(XRView::new(global, session, &left, XREye::Left, 0, &pose));
views.push(XRView::new(global, session, &right, XREye::Right, &pose)); views.push(XRView::new(global, session, &right, XREye::Right, 1, &pose));
}, },
Views::StereoCapture(left, right, third_eye) => { Views::StereoCapture(left, right, third_eye) => {
views.push(XRView::new(global, session, &left, XREye::Left, &pose)); views.push(XRView::new(global, session, &left, XREye::Left, 0, &pose));
views.push(XRView::new(global, session, &right, XREye::Right, &pose)); views.push(XRView::new(global, session, &right, XREye::Right, 1, &pose));
views.push(XRView::new(global, session, &third_eye, XREye::None, &pose)); views.push(XRView::new(
global,
session,
&third_eye,
XREye::None,
2,
&pose,
));
}, },
}; };
let transform = XRRigidTransform::new(global, cast_transform(pose)); let transform = XRRigidTransform::new(global, cast_transform(pose));

View file

@ -21,7 +21,7 @@ use crate::dom::xrview::XRView;
use crate::dom::xrviewport::XRViewport; use crate::dom::xrviewport::XRViewport;
use canvas_traits::webgl::WebGLFramebufferId; use canvas_traits::webgl::WebGLFramebufferId;
use dom_struct::dom_struct; use dom_struct::dom_struct;
use euclid::Size2D; use euclid::{Rect, Size2D};
use std::convert::TryInto; use std::convert::TryInto;
use webxr_api::SwapChainId as WebXRSwapChainId; use webxr_api::SwapChainId as WebXRSwapChainId;
use webxr_api::Viewport; use webxr_api::Viewport;
@ -114,7 +114,11 @@ impl XRWebGLLayer {
// Step 9.2. "Initialize layers framebuffer to a new opaque framebuffer created with context." // Step 9.2. "Initialize layers framebuffer to a new opaque framebuffer created with context."
let (swap_chain_id, framebuffer) = if session.is_immersive() { let (swap_chain_id, framebuffer) = if session.is_immersive() {
let size = session.with_session(|session| session.recommended_framebuffer_resolution()); let size = session.with_session(|session| {
session
.recommended_framebuffer_resolution()
.expect("immersive session must have viewports")
});
let (swap_chain_id, fb) = WebGLFramebuffer::maybe_new_webxr(session, &context, size) let (swap_chain_id, fb) = WebGLFramebuffer::maybe_new_webxr(session, &context, size)
.ok_or(Error::Operation)?; .ok_or(Error::Operation)?;
framebuffer = fb; framebuffer = fb;
@ -240,6 +244,17 @@ impl XRWebGLLayerMethods for XRWebGLLayer {
return None; return None;
} }
Some(XRViewport::new(&self.global(), view.view().viewport)) let index = view.viewport_index();
let viewport = self.session.with_session(|s| {
// Inline sssions
if s.viewports().is_empty() {
Rect::from_size(self.size().to_i32())
} else {
s.viewports()[index]
}
});
Some(XRViewport::new(&self.global(), viewport))
} }
} }