From 08a6d70ad408d5699cae92e7d7542b5064746c83 Mon Sep 17 00:00:00 2001 From: Daniel Adams <70986246+msub2@users.noreply.github.com> Date: Thu, 15 Aug 2024 21:23:12 -1000 Subject: [PATCH] Surface framerate info/functionality in openxr (#239) Signed-off-by: Daniel Adams --- webxr-api/device.rs | 8 ++++++++ webxr-api/session.rs | 16 ++++++++++++++++ webxr/openxr/mod.rs | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+) diff --git a/webxr-api/device.rs b/webxr-api/device.rs index f583b5d5..f6bcf326 100644 --- a/webxr-api/device.rs +++ b/webxr-api/device.rs @@ -84,6 +84,14 @@ pub trait DeviceAPI: 'static { fn cancel_hit_test(&mut self, _id: HitTestId) { panic!("This device does not support hit tests"); } + + fn update_frame_rate(&mut self, rate: f32) -> f32 { + rate + } + + fn supported_frame_rates(&self) -> Vec { + Vec::new() + } } impl DiscoveryAPI for Box> { diff --git a/webxr-api/session.rs b/webxr-api/session.rs index fda075c7..65415718 100644 --- a/webxr-api/session.rs +++ b/webxr-api/session.rs @@ -117,6 +117,7 @@ enum SessionMsg { RenderAnimationFrame, RequestHitTest(HitTestSource), CancelHitTest(HitTestId), + UpdateFrameRate(f32, Sender), Quit, } @@ -144,6 +145,7 @@ pub struct Session { initial_inputs: Vec, granted_features: Vec, id: SessionId, + supported_frame_rates: Vec, } #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] @@ -242,6 +244,14 @@ impl Session { pub fn cancel_hit_test(&self, id: HitTestId) { let _ = self.sender.send(SessionMsg::CancelHitTest(id)); } + + pub fn update_frame_rate(&mut self, rate: f32, sender: Sender) { + let _ = self.sender.send(SessionMsg::UpdateFrameRate(rate, sender)); + } + + pub fn supported_frame_rates(&self) -> &[f32] { + &self.supported_frame_rates + } } #[derive(PartialEq)] @@ -303,6 +313,7 @@ where let initial_inputs = self.device.initial_inputs(); let environment_blend_mode = self.device.environment_blend_mode(); let granted_features = self.device.granted_features().into(); + let supported_frame_rates = self.device.supported_frame_rates(); Session { floor_transform, viewports, @@ -311,6 +322,7 @@ where environment_blend_mode, granted_features, id: self.id, + supported_frame_rates, } } @@ -389,6 +401,10 @@ where let _ = self.frame_sender.send(frame); } + SessionMsg::UpdateFrameRate(rate, sender) => { + let new_framerate = self.device.update_frame_rate(rate); + let _ = sender.send(new_framerate); + } SessionMsg::Quit => { if self.render_state == RenderState::NotInRenderLoop { self.quit(); diff --git a/webxr/openxr/mod.rs b/webxr/openxr/mod.rs index 8a805746..da4dcb29 100644 --- a/webxr/openxr/mod.rs +++ b/webxr/openxr/mod.rs @@ -222,6 +222,7 @@ pub struct CreatedInstance { supports_mutable_fov: bool, supported_interaction_profiles: Vec<&'static str>, supports_passthrough: bool, + supports_updating_framerate: bool, } pub fn create_instance( @@ -240,6 +241,8 @@ pub fn create_instance( let supports_secondary = needs_secondary && supported.msft_secondary_view_configuration && supported.msft_first_person_observer; + let supports_updating_framerate = supported.fb_display_refresh_rate; + let app_info = ApplicationInfo { application_name: &app_info.application_name, application_version: app_info.application_version, @@ -263,6 +266,10 @@ pub fn create_instance( exts.fb_passthrough = true; } + if supports_updating_framerate { + exts.fb_display_refresh_rate = true; + } + let supported_interaction_profiles = get_supported_interaction_profiles(&supported, &mut exts); let instance = entry @@ -293,6 +300,7 @@ pub fn create_instance( supports_mutable_fov, supported_interaction_profiles, supports_passthrough, + supports_updating_framerate, }) } @@ -439,6 +447,7 @@ struct OpenXrDevice { clip_planes: ClipPlanes, supports_secondary: bool, supports_mutable_fov: bool, + supports_updating_framerate: bool, // input action_set: ActionSet, @@ -948,6 +957,7 @@ impl OpenXrDevice { supports_mutable_fov, supported_interaction_profiles, supports_passthrough, + supports_updating_framerate, } = instance; let (init_tx, init_rx) = crossbeam_channel::unbounded(); @@ -1153,6 +1163,7 @@ impl OpenXrDevice { clip_planes: Default::default(), supports_secondary, supports_mutable_fov, + supports_updating_framerate, layer_manager, shared_data, @@ -1585,6 +1596,29 @@ impl DeviceAPI for OpenXrDevice { fn granted_features(&self) -> &[String] { &self.granted_features } + + fn update_frame_rate(&mut self, rate: f32) -> f32 { + if self.supports_updating_framerate { + self.session + .request_display_refresh_rate(rate) + .expect("Failed to request display refresh rate"); + self.session + .get_display_refresh_rate() + .expect("Failed to get display refresh rate") + } else { + -1.0 + } + } + + fn supported_frame_rates(&self) -> Vec { + if self.supports_updating_framerate { + self.session + .enumerate_display_refresh_rates() + .expect("Failed to enumerate display refresh rates") + } else { + vec![] + } + } } fn transform(pose: &Posef) -> RigidTransform3D {