Compare commits
1 Commits
camera-ite
...
openxr
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0ae20b23c5 |
@@ -14,6 +14,7 @@ path = "src/main.rs"
|
||||
|
||||
[features]
|
||||
default = ["wayland", "xwayland"]
|
||||
openxr_runtime = []
|
||||
wayland = ["dep:smithay", "dep:xkbcommon"]
|
||||
xwayland = ["smithay/xwayland"]
|
||||
profile_tokio = ["dep:console-subscriber", "tokio/tracing"]
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
use super::scenegraph::Scenegraph;
|
||||
#[cfg(feature = "oxr_runtime")]
|
||||
use crate::openxr;
|
||||
use crate::{
|
||||
core::{registry::OwnedRegistry, task},
|
||||
nodes::{
|
||||
@@ -108,6 +110,8 @@ impl Client {
|
||||
items::create_interface(&client)?;
|
||||
input::create_interface(&client)?;
|
||||
startup::create_interface(&client)?;
|
||||
#[cfg(feature = "openxr_runtime")]
|
||||
openxr::create_interface(&client);
|
||||
|
||||
let pid_printable = pid
|
||||
.map(|pid| pid.to_string())
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
mod core;
|
||||
mod nodes;
|
||||
mod objects;
|
||||
#[cfg(feature = "openxr_runtime")]
|
||||
mod openxr;
|
||||
#[cfg(feature = "wayland")]
|
||||
mod wayland;
|
||||
|
||||
@@ -31,6 +33,8 @@ use tracing::metadata::LevelFilter;
|
||||
use tracing::{debug_span, error, info};
|
||||
use tracing_subscriber::{fmt, prelude::*, EnvFilter};
|
||||
|
||||
pub static SK_INFO: OnceCell<SystemInfo> = OnceCell::new();
|
||||
|
||||
#[derive(Parser)]
|
||||
#[clap(author, version, about, long_about = None)]
|
||||
struct CliArgs {
|
||||
@@ -114,6 +118,8 @@ fn main() {
|
||||
let _ = SK_MULTITHREAD.set(sk.multithreaded());
|
||||
info!("Init StereoKit");
|
||||
|
||||
SK_INFO.set(stereokit.system_info()).unwrap();
|
||||
|
||||
sk.material_set_shader(
|
||||
sk.material_find("default/material_pbr").unwrap(),
|
||||
sk.shader_find("default/shader_pbr_clip").unwrap(),
|
||||
|
||||
@@ -29,6 +29,8 @@ use tracing::{debug_span, instrument};
|
||||
|
||||
use crate::core::client::Client;
|
||||
use crate::core::registry::Registry;
|
||||
#[cfg(feature = "openxr_runtime")]
|
||||
use crate::openxr;
|
||||
|
||||
use self::alias::Alias;
|
||||
use self::audio::Sound;
|
||||
@@ -101,6 +103,10 @@ pub struct Node {
|
||||
|
||||
// Startup
|
||||
pub startup_settings: OnceCell<Mutex<StartupSettings>>,
|
||||
|
||||
// OpenXR
|
||||
#[cfg(feature = "openxr_runtime")]
|
||||
pub openxr_object: OnceCell<openxr::Object>,
|
||||
}
|
||||
|
||||
impl Node {
|
||||
@@ -144,6 +150,8 @@ impl Node {
|
||||
item_acceptor: OnceCell::new(),
|
||||
item_ui: OnceCell::new(),
|
||||
sound: OnceCell::new(),
|
||||
#[cfg(feature = "openxr_runtime")]
|
||||
openxr_object: OnceCell::new(),
|
||||
startup_settings: OnceCell::new(),
|
||||
};
|
||||
node.add_local_signal("set_enabled", Node::set_enabled_flex);
|
||||
|
||||
76
src/openxr/action.rs
Normal file
76
src/openxr/action.rs
Normal file
@@ -0,0 +1,76 @@
|
||||
use super::Object;
|
||||
use crate::{core::client::Client, nodes::Node};
|
||||
use color_eyre::eyre::{bail, Result};
|
||||
use parking_lot::Mutex;
|
||||
use rustc_hash::FxHashMap;
|
||||
use serde::Deserialize;
|
||||
use stardust_xr::schemas::flex::deserialize;
|
||||
use std::sync::Arc;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Action {
|
||||
// _info: InstanceInfo,
|
||||
_localized_name: String,
|
||||
suggested_bindings: Mutex<FxHashMap<String, String>>,
|
||||
}
|
||||
impl Action {
|
||||
pub fn create_action_flex(
|
||||
node: &Node,
|
||||
_calling_client: Arc<Client>,
|
||||
data: &[u8],
|
||||
) -> Result<()> {
|
||||
let Object::ActionSet(action_set) = node.get_aspect("OpenXR interface", "Instance", |n| &n.openxr_object)? else {
|
||||
bail!("Object not an instance")
|
||||
};
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct CreateActionInfo {
|
||||
name: String,
|
||||
localized_name: String,
|
||||
}
|
||||
let info: CreateActionInfo = dbg!(deserialize(data)?);
|
||||
|
||||
let node = Node::create(
|
||||
&node.get_client().unwrap(),
|
||||
node.get_path(),
|
||||
&info.name,
|
||||
true,
|
||||
)
|
||||
.add_to_scenegraph();
|
||||
node.add_local_signal("suggest_binding", Self::suggest_binding_flex);
|
||||
|
||||
let action = Arc::new(Action {
|
||||
_localized_name: info.localized_name,
|
||||
suggested_bindings: Mutex::new(FxHashMap::default()),
|
||||
});
|
||||
action_set
|
||||
.actions
|
||||
.lock()
|
||||
.insert(info.name, Arc::downgrade(&action));
|
||||
node.openxr_object.set(Object::Action(action)).unwrap();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
pub fn suggest_binding_flex(
|
||||
node: &Node,
|
||||
_calling_client: Arc<Client>,
|
||||
data: &[u8],
|
||||
) -> Result<()> {
|
||||
let Object::Action(action) = node.get_aspect("OpenXR interface", "Action", |n| &n.openxr_object)? else {
|
||||
bail!("Object not an action")
|
||||
};
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct SuggestBindingArgs {
|
||||
interaction_profile: String,
|
||||
binding: String,
|
||||
}
|
||||
let args: SuggestBindingArgs = dbg!(deserialize(data)?);
|
||||
action
|
||||
.suggested_bindings
|
||||
.lock()
|
||||
.insert(args.interaction_profile, args.binding);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
60
src/openxr/action_set.rs
Normal file
60
src/openxr/action_set.rs
Normal file
@@ -0,0 +1,60 @@
|
||||
use super::{action::Action, Object};
|
||||
use crate::{core::client::Client, nodes::Node};
|
||||
use color_eyre::eyre::{bail, Result};
|
||||
use parking_lot::Mutex;
|
||||
use rustc_hash::FxHashMap;
|
||||
use serde::Deserialize;
|
||||
use stardust_xr::schemas::flex::deserialize;
|
||||
use std::sync::{Arc, Weak};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ActionSet {
|
||||
// _info: InstanceInfo,
|
||||
_localized_name: String,
|
||||
_priority: u32,
|
||||
pub actions: Mutex<FxHashMap<String, Weak<Action>>>,
|
||||
}
|
||||
impl ActionSet {
|
||||
pub fn create_action_set_flex(
|
||||
node: &Node,
|
||||
_calling_client: Arc<Client>,
|
||||
data: &[u8],
|
||||
) -> Result<()> {
|
||||
let Object::Instance(instance) = node.get_aspect("OpenXR interface", "Instance", |n| &n.openxr_object)? else {
|
||||
bail!("Object not an instance")
|
||||
};
|
||||
let Some(instance) = instance.get() else { bail!("Instance not initialized") };
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct CreateActionSetInfo {
|
||||
name: String,
|
||||
localized_name: String,
|
||||
priority: u32,
|
||||
}
|
||||
let info: CreateActionSetInfo = deserialize(data)?;
|
||||
|
||||
let node = Node::create(
|
||||
&node.get_client().unwrap(),
|
||||
"/openxr/action_set",
|
||||
&info.name,
|
||||
true,
|
||||
)
|
||||
.add_to_scenegraph();
|
||||
node.add_local_signal("create_action", Action::create_action_flex);
|
||||
|
||||
let action_set = Arc::new(ActionSet {
|
||||
_localized_name: info.localized_name,
|
||||
_priority: info.priority,
|
||||
actions: Mutex::new(FxHashMap::default()),
|
||||
});
|
||||
instance
|
||||
.action_sets
|
||||
.lock()
|
||||
.insert(info.name, Arc::downgrade(&action_set));
|
||||
node.openxr_object
|
||||
.set(Object::ActionSet(action_set))
|
||||
.unwrap();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
47
src/openxr/instance.rs
Normal file
47
src/openxr/instance.rs
Normal file
@@ -0,0 +1,47 @@
|
||||
use super::{action_set::ActionSet, Object};
|
||||
use crate::{core::client::Client, nodes::Node};
|
||||
use color_eyre::eyre::{bail, eyre, Result};
|
||||
use parking_lot::Mutex;
|
||||
use rustc_hash::FxHashMap;
|
||||
use serde::Deserialize;
|
||||
use stardust_xr::schemas::flex::deserialize;
|
||||
use std::sync::{Arc, Weak};
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct InstanceInfo {
|
||||
_app_info: ApplicationInfo,
|
||||
_extension_names: Vec<String>,
|
||||
}
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct ApplicationInfo {
|
||||
_app_name: String,
|
||||
_app_version: u32,
|
||||
_engine_name: String,
|
||||
_engine_version: u32,
|
||||
_api_version: u64,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Instance {
|
||||
_info: InstanceInfo,
|
||||
pub action_sets: Mutex<FxHashMap<String, Weak<ActionSet>>>,
|
||||
}
|
||||
impl Instance {
|
||||
pub fn setup_instance_flex(
|
||||
node: &Node,
|
||||
_calling_client: Arc<Client>,
|
||||
data: &[u8],
|
||||
) -> Result<()> {
|
||||
let Object::Instance(instance) = node.get_aspect("OpenXR interface", "Instance", |n| &n.openxr_object)? else {
|
||||
bail!("Object not an instance")
|
||||
};
|
||||
let instance_info = Instance {
|
||||
_info: deserialize(data)?,
|
||||
action_sets: Mutex::new(FxHashMap::default()),
|
||||
};
|
||||
dbg!(&instance_info);
|
||||
instance
|
||||
.set(Arc::new(instance_info))
|
||||
.map_err(|_| eyre!("Instance already set up"))
|
||||
}
|
||||
}
|
||||
34
src/openxr/mod.rs
Normal file
34
src/openxr/mod.rs
Normal file
@@ -0,0 +1,34 @@
|
||||
mod action;
|
||||
mod action_set;
|
||||
mod instance;
|
||||
mod session;
|
||||
mod system;
|
||||
|
||||
use self::{
|
||||
action::Action, action_set::ActionSet, instance::Instance, session::Session, system::System,
|
||||
};
|
||||
use crate::{core::client::Client, nodes::Node};
|
||||
use once_cell::sync::OnceCell;
|
||||
use std::sync::Arc;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Object {
|
||||
Instance(OnceCell<Arc<Instance>>),
|
||||
System(System),
|
||||
Session(Session),
|
||||
ActionSet(Arc<ActionSet>),
|
||||
Action(Arc<Action>),
|
||||
}
|
||||
|
||||
pub fn create_interface(client: &Arc<Client>) {
|
||||
let node = Node::create(client, "", "openxr", false);
|
||||
node.add_local_signal("setup_instance", Instance::setup_instance_flex);
|
||||
node.add_local_method("get_system", System::get_system_flex);
|
||||
node.add_local_signal("create_action_set", ActionSet::create_action_set_flex);
|
||||
|
||||
node.openxr_object
|
||||
.set(Object::Instance(OnceCell::new()))
|
||||
.unwrap();
|
||||
|
||||
node.add_to_scenegraph();
|
||||
}
|
||||
34
src/openxr/session.rs
Normal file
34
src/openxr/session.rs
Normal file
@@ -0,0 +1,34 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use color_eyre::eyre::{bail, Result};
|
||||
use stardust_xr::schemas::flex::deserialize;
|
||||
|
||||
use super::Object;
|
||||
use crate::{core::client::Client, nodes::Node};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Session {
|
||||
// _info: InstanceInfo,
|
||||
}
|
||||
impl Session {
|
||||
pub fn create_session_flex(
|
||||
node: &Node,
|
||||
_calling_client: Arc<Client>,
|
||||
data: &[u8],
|
||||
) -> Result<()> {
|
||||
let Object::System(_system) = node.get_aspect("OpenXR interface", "Instance", |n| &n.openxr_object)? else {
|
||||
bail!("Object not a system")
|
||||
};
|
||||
let node = Node::create(
|
||||
&node.get_client().unwrap(),
|
||||
node.get_path(),
|
||||
deserialize(data)?,
|
||||
true,
|
||||
)
|
||||
.add_to_scenegraph();
|
||||
let session = Session {};
|
||||
node.openxr_object.set(Object::Session(session)).unwrap();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
76
src/openxr/system.rs
Normal file
76
src/openxr/system.rs
Normal file
@@ -0,0 +1,76 @@
|
||||
use super::{session::Session, Object};
|
||||
use crate::{core::client::Client, nodes::Node, SK_INFO};
|
||||
use color_eyre::eyre::{bail, eyre, Result};
|
||||
use serde::Serialize;
|
||||
use stardust_xr::schemas::flex::{deserialize, serialize};
|
||||
use std::sync::Arc;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum System {
|
||||
Handheld,
|
||||
HeadMounted,
|
||||
}
|
||||
impl System {
|
||||
pub fn from_raw(raw: u32) -> Option<Self> {
|
||||
match raw {
|
||||
1 => Some(System::Handheld),
|
||||
2 => Some(System::HeadMounted),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_system_flex(
|
||||
node: &Node,
|
||||
_calling_client: Arc<Client>,
|
||||
data: &[u8],
|
||||
) -> Result<Vec<u8>> {
|
||||
// let Object::Instance(instance) = node.get_aspect("OpenXR interface", "Instance", |n| &n.openxr_object)? else {
|
||||
// bail!("Object not an instance")
|
||||
// };
|
||||
let system_type: u32 = deserialize(data)?;
|
||||
let system = System::from_raw(system_type).ok_or_else(|| eyre!("No system exists!"))?;
|
||||
let node = Node::create(
|
||||
&node.get_client().unwrap(),
|
||||
node.get_path(),
|
||||
&format!("system{}", system_type),
|
||||
true,
|
||||
)
|
||||
.add_to_scenegraph();
|
||||
node.add_local_method("views", System::views_flex);
|
||||
node.add_local_signal("create_session", Session::create_session_flex);
|
||||
node.openxr_object.set(Object::System(system)).unwrap();
|
||||
|
||||
Ok(serialize(system_type)?)
|
||||
}
|
||||
|
||||
fn views_flex(_node: &Node, _calling_client: Arc<Client>, data: &[u8]) -> Result<Vec<u8>> {
|
||||
let view_configuration_type: u64 = deserialize(data)?;
|
||||
let view_count: u32 = match view_configuration_type {
|
||||
1 => 1,
|
||||
2 => 2,
|
||||
1000037000 => 4,
|
||||
1000054000 => 1,
|
||||
_ => bail!("Invalid view config type"),
|
||||
};
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
struct View {
|
||||
recommended_image_rect_width: u32,
|
||||
max_image_rect_width: u32,
|
||||
recommended_image_rect_height: u32,
|
||||
max_image_rect_height: u32,
|
||||
}
|
||||
let sk_info = SK_INFO.get().unwrap();
|
||||
|
||||
Ok(serialize(
|
||||
(0..view_count)
|
||||
.map(|_| View {
|
||||
recommended_image_rect_width: sk_info.display_width,
|
||||
max_image_rect_width: sk_info.display_width,
|
||||
recommended_image_rect_height: sk_info.display_height,
|
||||
max_image_rect_height: sk_info.display_height,
|
||||
})
|
||||
.collect::<Vec<_>>(),
|
||||
)?)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user