11use clap:: Parser ;
22use color_eyre:: { Result , eyre:: Context , owo_colors:: OwoColorize } ;
3- use tracing:: debug;
3+ use openxr:: {
4+ ApplicationInfo , ExtensionSet , FormFactor , FrameStream , FrameWaiter , Graphics ,
5+ Headless , Session , headless:: SessionCreateInfo as HeadlessSessionCreateInfo ,
6+ } ;
7+ use tracing:: { debug, error, info} ;
48
59#[ derive( Debug , Parser ) ]
610pub struct Args {
@@ -20,30 +24,120 @@ struct InfoArgs {}
2024
2125impl InfoArgs {
2226 fn run ( self , entry : :: openxr:: Entry ) -> Result < ( ) > {
23- println ! ( "{}" , "layers:" . bold( ) ) ;
24- for layer in entry
27+ let mut layers = entry
2528 . enumerate_layers ( )
26- . wrap_err ( "failed to enumerate layers" ) ?
27- {
28- println ! ( "layer: {layer:?}" ) ;
29+ . wrap_err ( "failed to enumerate layers" ) ?;
30+ layers. sort_by_key ( |l| l. layer_name . to_owned ( ) ) ;
31+ println ! ( "{}" , "layers:" . bold( ) ) ;
32+ for layer in layers {
33+ let name = & layer. layer_name ;
34+ println ! (
35+ "- {} v{}: spec version: {}, desc: {}" ,
36+ name, layer. layer_version, layer. spec_version, layer. description
37+ ) ;
38+
39+ let extensions =
40+ entry. enumerate_layer_extensions ( name) . wrap_err_with ( || {
41+ format ! ( "failed to enumerate layer extensions for layer {name}" )
42+ } ) ?;
43+ let mut extension_names: Vec < _ > = extensions
44+ . names ( )
45+ . into_iter ( )
46+ . map ( String :: from_utf8_lossy)
47+ . collect ( ) ;
48+ extension_names. sort ( ) ;
49+ for ext_name in extension_names {
50+ println ! ( " - {ext_name}" ) ;
51+ }
2952 }
3053
31- let extensions = entry
54+ let supported_extensions = entry
3255 . enumerate_extensions ( )
3356 . wrap_err ( "failed to enumerate extensions" ) ?;
57+ let mut names: Vec < _ > = supported_extensions
58+ . names ( )
59+ . into_iter ( )
60+ . map ( String :: from_utf8_lossy)
61+ . collect ( ) ;
62+ names. sort ( ) ;
3463 println ! ( "{}" , "extensions:" . bold( ) ) ;
35- for name in extensions. names ( ) {
36- let name = std:: ffi:: CStr :: from_bytes_with_nul ( name)
37- . wrap_err ( "encountered name that was not a CStr" ) ?;
38- let name = std:: str:: from_utf8 ( name. to_bytes ( ) )
39- . wrap_err ( "encountered name that was not UTF-8" ) ?;
40- println ! ( "{name}" ) ;
64+ for name in names {
65+ println ! ( "- {name}" ) ;
66+ }
67+
68+ let mut requested_extensions = ExtensionSet :: default ( ) ;
69+ requested_extensions. mnd_headless = supported_extensions. mnd_headless ;
70+ let mk_instance = move |ext| {
71+ entry
72+ . create_instance (
73+ & ApplicationInfo {
74+ application_name : "xr-tools" ,
75+ ..Default :: default ( )
76+ } ,
77+ & ext,
78+ & [ ] ,
79+ )
80+ . wrap_err ( "failed to create openxr instance" )
81+ } ;
82+
83+ let instance = match mk_instance ( requested_extensions. clone ( ) ) {
84+ Ok ( i) => i,
85+ Err ( err) => {
86+ error ! ( "failed to create instance with headless extension: {err}" ) ;
87+ info ! ( "attempting again but this time with no extensions" ) ;
88+ requested_extensions = ExtensionSet :: default ( ) ;
89+ mk_instance ( requested_extensions. clone ( ) ) ?
90+ }
91+ } ;
92+ debug ! ( "created openxr instance" ) ;
93+
94+ let runtime_properties = instance
95+ . properties ( )
96+ . wrap_err ( "failed to get runtime properties from instance" ) ?;
97+ println ! (
98+ "{} {}, {} {}" ,
99+ "runtime:" . bold( ) ,
100+ runtime_properties. runtime_name,
101+ "version:" . bold( ) ,
102+ runtime_properties. runtime_version
103+ ) ;
104+
105+ let hmd_system_id = instance
106+ . system ( FormFactor :: HEAD_MOUNTED_DISPLAY )
107+ . wrap_err ( "failed to get SystemID for HEAD_MOUNTED_DISPLAY form factor" ) ?;
108+ let hmd_properties = instance
109+ . system_properties ( hmd_system_id)
110+ . wrap_err ( "failed to get system properties for HMD" ) ?;
111+ println ! ( "{hmd_properties:#?}" ) ;
112+
113+ // SAFETY: Headless sessions have no special safety requirements
114+ if requested_extensions. mnd_headless {
115+ info ! ( "press enter key to open xr session with headless graphics..." ) ;
116+ std:: io:: stdin ( ) . read_line ( & mut String :: new ( ) ) . unwrap ( ) ;
117+ let ( session, frame_waiter, frame_stream) = unsafe {
118+ instance. create_session :: < Headless > (
119+ hmd_system_id,
120+ & HeadlessSessionCreateInfo { } ,
121+ )
122+ }
123+ . wrap_err ( "failed to create headless session" ) ?;
124+ debug ! ( "created headless session" ) ;
125+ do_session ( session, frame_waiter, frame_stream) ?;
41126 }
42127
43128 Ok ( ( ) )
44129 }
45130}
46131
132+ fn do_session < G : Graphics > (
133+ _session : Session < G > ,
134+ _frame_waiter : FrameWaiter ,
135+ _frame_stream : FrameStream < G > ,
136+ ) -> Result < ( ) > {
137+ // TODO: Query devices
138+ Ok ( ( ) )
139+ }
140+
47141impl Args {
48142 pub fn run ( self ) -> Result < ( ) > {
49143 let entry = if self . static_loader {
0 commit comments