11use khronos_egl:: { Context , Display , Instance } ;
22use std:: ffi:: CStr ;
3- use waynest:: server:: Error ;
4-
5- // Define function pointers for the missing EGL extension functions
6- type EglQueryDisplayAttribEXT = unsafe extern "C" fn (
7- egl_display : khronos_egl:: EGLDisplay ,
8- attribute : i32 ,
9- value : * mut * const std:: ffi:: c_void ,
10- ) -> khronos_egl:: Boolean ;
11-
12- type EglQueryDeviceStringEXT =
13- unsafe extern "C" fn ( device : * const std:: ffi:: c_void , name : i32 ) -> * const i8 ;
3+ use std:: io:: { self , Error } ;
144
155#[ derive( Debug ) ]
166pub struct GraphicsInfo {
17- pub egl_instance : Instance < khronos_egl:: Static > ,
7+ pub instance : Instance < khronos_egl:: Static > ,
188 pub display : Display ,
199 pub context : Context ,
2010}
2111unsafe impl Send for GraphicsInfo { }
2212unsafe impl Sync for GraphicsInfo { }
2313
2414impl GraphicsInfo {
15+ #[ allow( unused) ]
2516 pub fn get_drm_device_file_path ( & self ) -> Result < String , Error > {
17+ // Define function pointers for the missing EGL extension functions
18+ type EglQueryDisplayAttribEXT = unsafe extern "C" fn (
19+ egl_display : khronos_egl:: EGLDisplay ,
20+ attribute : i32 ,
21+ value : * mut * const std:: ffi:: c_void ,
22+ ) -> khronos_egl:: Boolean ;
23+
24+ type EglQueryDeviceStringEXT =
25+ unsafe extern "C" fn ( device : * const std:: ffi:: c_void , name : i32 ) -> * const i8 ;
26+
2627 // Load the missing EGL extension functions
2728 let egl_query_display_attrib_ext = {
28- let func = self
29- . egl_instance
30- . get_proc_address ( "eglQueryDisplayAttribEXT" ) ;
31- let func =
32- func. ok_or_else ( || Error :: Custom ( "eglQueryDisplayAttribEXT not available" . into ( ) ) ) ?;
29+ let func = self . instance . get_proc_address ( "eglQueryDisplayAttribEXT" ) ;
30+ let func = func. ok_or_else ( || {
31+ io:: Error :: new (
32+ io:: ErrorKind :: Other ,
33+ "eglQueryDisplayAttribEXT not available" ,
34+ )
35+ } ) ?;
3336 unsafe { std:: mem:: transmute :: < extern "system" fn ( ) , EglQueryDisplayAttribEXT > ( func) }
3437 } ;
3538
3639 let egl_query_device_string_ext = {
37- let func = self
38- . egl_instance
39- . get_proc_address ( "eglQueryDeviceStringEXT" ) ;
40- let func =
41- func. ok_or_else ( || Error :: Custom ( "eglQueryDeviceStringEXT not available" . into ( ) ) ) ?;
40+ let func = self . instance . get_proc_address ( "eglQueryDeviceStringEXT" ) ;
41+ let func = func. ok_or_else ( || {
42+ io:: Error :: new (
43+ io:: ErrorKind :: Other ,
44+ "eglQueryDeviceStringEXT not available" ,
45+ )
46+ } ) ?;
4247 unsafe { std:: mem:: transmute :: < extern "system" fn ( ) , EglQueryDeviceStringEXT > ( func) }
4348 } ;
4449
@@ -50,26 +55,119 @@ impl GraphicsInfo {
5055 let success = unsafe {
5156 egl_query_display_attrib_ext ( egl_display. as_ptr ( ) , egl_attributes, & mut device)
5257 } ;
58+ if device. is_null ( ) {
59+ return Err ( io:: Error :: new ( io:: ErrorKind :: Other , "egl_device is null" ) ) ;
60+ }
5361 if success == khronos_egl:: FALSE {
54- return Err ( Error :: Custom ( "Failed to query EGL device" . into ( ) ) ) ;
62+ let egl_error = self . instance . get_error ( ) ;
63+ return Err ( io:: Error :: new (
64+ io:: ErrorKind :: Other ,
65+ format ! ( "Failed to query EGL device: {:?}" , egl_error) ,
66+ ) ) ;
5567 }
5668 device
5769 } ;
5870
59- // Get the DRM device file path
71+ // Check supported attributes for the device
72+ const EGL_EXTENSIONS : i32 = 0x3055 ;
73+ let supported_attributes =
74+ unsafe { egl_query_device_string_ext ( egl_device, EGL_EXTENSIONS ) } ;
75+ if supported_attributes. is_null ( ) {
76+ return Err ( io:: Error :: new (
77+ io:: ErrorKind :: Other ,
78+ "Failed to query supported attributes" ,
79+ ) ) ;
80+ }
81+ let extensions = unsafe { CStr :: from_ptr ( supported_attributes) . to_str ( ) . unwrap_or ( "" ) } ;
82+ if !extensions. contains ( "EGL_DRM_DEVICE_FILE_EXT" ) {
83+ return Err ( io:: Error :: new (
84+ io:: ErrorKind :: Other ,
85+ "EGL_DRM_DEVICE_FILE_EXT not supported" ,
86+ ) ) ;
87+ }
88+
89+ // Ensure EGL context is current
90+ let previous_context = self . instance . get_current_context ( ) ;
91+ let previous_display = self . instance . get_current_display ( ) ;
92+ self . instance
93+ . make_current ( self . display , None , None , Some ( self . context ) )
94+ . map_err ( |_| {
95+ io:: Error :: new ( io:: ErrorKind :: Other , "Failed to make EGL context current" )
96+ } ) ?;
6097 let drm_device_file_path = unsafe {
6198 let cstr = egl_query_device_string_ext ( egl_device, 0x3376 ) ; // EGL_DRM_DEVICE_FILE_EXT
6299 if cstr. is_null ( ) {
63- return Err ( Error :: Custom ( "Failed to query DRM device file path" . into ( ) ) ) ;
100+ let egl_error = self . instance . get_error ( ) ;
101+ return Err ( io:: Error :: new (
102+ io:: ErrorKind :: Other ,
103+ format ! ( "Failed to query DRM device file path: {:?}" , egl_error) ,
104+ ) ) ;
64105 }
65106 CStr :: from_ptr ( cstr)
66107 . to_str ( )
67- . map_err ( |_| {
68- Error :: Custom ( "Failed to convert DRM device file path to string" . into ( ) )
108+ . map_err ( |e| {
109+ io:: Error :: new (
110+ io:: ErrorKind :: InvalidData ,
111+ format ! ( "Failed to convert DRM device file path to string: {}" , e) ,
112+ )
69113 } ) ?
70114 . to_string ( )
71115 } ;
72116
117+ // Restore previous EGL context state
118+ if let Some ( previous_display) = previous_display {
119+ self . instance
120+ . make_current ( previous_display, None , None , previous_context)
121+ . map_err ( |e| {
122+ let egl_error = self . instance . get_error ( ) ;
123+ io:: Error :: new (
124+ io:: ErrorKind :: Other ,
125+ format ! (
126+ "Failed to restore previous EGL context state: {:?}, EGL error: {:?}" ,
127+ e, egl_error
128+ ) ,
129+ )
130+ } ) ?;
131+ }
132+
73133 Ok ( drm_device_file_path)
74134 }
75135}
136+
137+ #[ test]
138+ fn test_get_drm_device_file_path ( ) {
139+ use std:: sync:: Arc ;
140+ use stereokit_rust:: sk:: AppMode ;
141+ use stereokit_rust:: sk:: SkSettings ;
142+ use stereokit_rust:: system:: BackendOpenGLESEGL ;
143+
144+ // Initialize StereoKit
145+ let sk = SkSettings :: default ( )
146+ . app_name ( "GraphicsInfo Test" )
147+ . mode ( if std:: env:: args ( ) . any ( |arg| arg == "-f" ) {
148+ AppMode :: Simulator
149+ } else {
150+ AppMode :: XR
151+ } )
152+ . init ( )
153+ . expect ( "StereoKit failed to initialize" ) ;
154+
155+ // Create GraphicsInfo instance
156+ let graphics_info = unsafe {
157+ Arc :: new ( GraphicsInfo {
158+ instance : khronos_egl:: Instance :: new ( khronos_egl:: Static ) ,
159+ display : khronos_egl:: Display :: from_ptr ( BackendOpenGLESEGL :: display ( ) ) ,
160+ context : khronos_egl:: Context :: from_ptr ( BackendOpenGLESEGL :: context ( ) ) ,
161+ } )
162+ } ;
163+
164+ sk. step ( ) ;
165+
166+ // Call get_drm_device_file_path and log the result
167+ match graphics_info. get_drm_device_file_path ( ) {
168+ Ok ( path) => println ! ( "DRM Device File Path: {}" , path) ,
169+ Err ( e) => eprintln ! ( "Error retrieving DRM Device File Path: {:?}" , e) ,
170+ }
171+
172+ std:: io:: Write :: flush ( & mut std:: io:: stdout ( ) ) . expect ( "Failed to flush stdout" ) ;
173+ }
0 commit comments