/* 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 http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::Bindings::VRFrameDataBinding; use dom::bindings::codegen::Bindings::VRFrameDataBinding::VRFrameDataMethods; use dom::bindings::error::Fallible; use dom::bindings::nonnull::NonNullJSObjectPtr; use dom::bindings::num::Finite; use dom::bindings::reflector::{DomObject, Reflector, reflect_dom_object}; use dom::bindings::root::{Dom, DomRoot}; use dom::globalscope::GlobalScope; use dom::vrpose::VRPose; use dom::window::Window; use dom_struct::dom_struct; use js::jsapi::{Heap, JSContext, JSObject}; use js::typedarray::{Float32Array, CreateWith}; use std::cell::Cell; use std::ptr; use webvr_traits::WebVRFrameData; #[dom_struct] pub struct VRFrameData { reflector_: Reflector, left_proj: Heap<*mut JSObject>, left_view: Heap<*mut JSObject>, right_proj: Heap<*mut JSObject>, right_view: Heap<*mut JSObject>, pose: Dom, timestamp: Cell, first_timestamp: Cell } impl VRFrameData { fn new_inherited(pose: &VRPose) -> VRFrameData { VRFrameData { reflector_: Reflector::new(), left_proj: Heap::default(), left_view: Heap::default(), right_proj: Heap::default(), right_view: Heap::default(), pose: Dom::from_ref(&*pose), timestamp: Cell::new(0.0), first_timestamp: Cell::new(0.0) } } #[allow(unsafe_code)] fn new(global: &GlobalScope) -> DomRoot { let matrix = [1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0f32]; let pose = VRPose::new(&global, &Default::default()); let root = reflect_dom_object(Box::new(VRFrameData::new_inherited(&pose)), global, VRFrameDataBinding::Wrap); let cx = global.get_cx(); create_typed_array(cx, &matrix, &root.left_proj); create_typed_array(cx, &matrix, &root.left_view); create_typed_array(cx, &matrix, &root.right_proj); create_typed_array(cx, &matrix, &root.right_view); root } pub fn Constructor(window: &Window) -> Fallible> { Ok(VRFrameData::new(&window.global())) } } #[allow(unsafe_code)] fn create_typed_array(cx: *mut JSContext, src: &[f32], dst: &Heap<*mut JSObject>) { rooted!(in (cx) let mut array = ptr::null_mut()); unsafe { let _ = Float32Array::create(cx, CreateWith::Slice(src), array.handle_mut()); } (*dst).set(array.get()); } impl VRFrameData { #[allow(unsafe_code)] pub fn update(&self, data: &WebVRFrameData) { unsafe { let cx = self.global().get_cx(); typedarray!(in(cx) let left_proj_array: Float32Array = self.left_proj.get()); if let Ok(mut array) = left_proj_array { array.update(&data.left_projection_matrix); } typedarray!(in(cx) let left_view_array: Float32Array = self.left_view.get()); if let Ok(mut array) = left_view_array { array.update(&data.left_view_matrix); } typedarray!(in(cx) let right_proj_array: Float32Array = self.right_proj.get()); if let Ok(mut array) = right_proj_array { array.update(&data.right_projection_matrix); } typedarray!(in(cx) let right_view_array: Float32Array = self.right_view.get()); if let Ok(mut array) = right_view_array { array.update(&data.right_view_matrix); } } self.pose.update(&data.pose); self.timestamp.set(data.timestamp); if self.first_timestamp.get() == 0.0 { self.first_timestamp.set(data.timestamp); } } } impl VRFrameDataMethods for VRFrameData { // https://w3c.github.io/webvr/#dom-vrframedata-timestamp fn Timestamp(&self) -> Finite { Finite::wrap(self.timestamp.get() - self.first_timestamp.get()) } #[allow(unsafe_code)] // https://w3c.github.io/webvr/#dom-vrframedata-leftprojectionmatrix unsafe fn LeftProjectionMatrix(&self, _cx: *mut JSContext) -> NonNullJSObjectPtr { NonNullJSObjectPtr::new_unchecked(self.left_proj.get()) } #[allow(unsafe_code)] // https://w3c.github.io/webvr/#dom-vrframedata-leftviewmatrix unsafe fn LeftViewMatrix(&self, _cx: *mut JSContext) -> NonNullJSObjectPtr { NonNullJSObjectPtr::new_unchecked(self.left_view.get()) } #[allow(unsafe_code)] // https://w3c.github.io/webvr/#dom-vrframedata-rightprojectionmatrix unsafe fn RightProjectionMatrix(&self, _cx: *mut JSContext) -> NonNullJSObjectPtr { NonNullJSObjectPtr::new_unchecked(self.right_proj.get()) } #[allow(unsafe_code)] // https://w3c.github.io/webvr/#dom-vrframedata-rightviewmatrix unsafe fn RightViewMatrix(&self, _cx: *mut JSContext) -> NonNullJSObjectPtr { NonNullJSObjectPtr::new_unchecked(self.right_view.get()) } // https://w3c.github.io/webvr/#dom-vrframedata-pose fn Pose(&self) -> DomRoot { DomRoot::from_ref(&*self.pose) } }