surfman/platform/generic/egl/
device.rs1use crate::egl::Egl;
6
7#[cfg(not(target_os = "windows"))]
8use libc::{dlopen, dlsym, RTLD_LAZY};
9use std::ffi::{CStr, CString};
10use std::mem;
11use std::os::raw::c_void;
12use std::sync::LazyLock;
13#[cfg(target_os = "windows")]
14use winapi::shared::minwindef::HMODULE;
15#[cfg(target_os = "windows")]
16use winapi::um::libloaderapi;
17
18thread_local! {
19 pub static EGL_FUNCTIONS: Egl = Egl::load_with(get_proc_address);
20}
21
22#[cfg(target_os = "windows")]
23static EGL_LIBRARY: LazyLock<EGLLibraryWrapper> = LazyLock::new(|| unsafe {
24 let module = libloaderapi::LoadLibraryA(c"libEGL.dll".as_ptr());
25 EGLLibraryWrapper(module)
26});
27
28#[cfg(target_env = "ohos")]
29static EGL_POTENTIAL_SO_NAMES: [&CStr; 1] = [c"libEGL.so"];
30
31#[cfg(not(any(target_os = "windows", target_os = "macos", target_env = "ohos")))]
32static EGL_POTENTIAL_SO_NAMES: [&CStr; 2] = [c"libEGL.so.1", c"libEGL.so"];
33
34#[cfg(not(any(target_os = "windows", target_os = "macos")))]
35static EGL_LIBRARY: LazyLock<EGLLibraryWrapper> = LazyLock::new(|| {
36 for soname in EGL_POTENTIAL_SO_NAMES {
37 unsafe {
38 let handle = dlopen(soname.as_ptr(), RTLD_LAZY);
39 if !handle.is_null() {
40 return EGLLibraryWrapper(handle);
41 }
42 }
43 }
44 panic!("Unable to load the libEGL shared object");
45});
46
47#[cfg(target_os = "windows")]
48struct EGLLibraryWrapper(HMODULE);
49#[cfg(not(target_os = "windows"))]
50struct EGLLibraryWrapper(*mut c_void);
51
52unsafe impl Send for EGLLibraryWrapper {}
53unsafe impl Sync for EGLLibraryWrapper {}
54
55#[cfg(target_os = "windows")]
56fn get_proc_address(symbol_name: &str) -> *const c_void {
57 unsafe {
58 let symbol_name: CString = CString::new(symbol_name).unwrap();
59 let symbol_ptr = symbol_name.as_ptr();
60 libloaderapi::GetProcAddress(EGL_LIBRARY.0, symbol_ptr).cast()
61 }
62}
63
64#[cfg(not(target_os = "windows"))]
65fn get_proc_address(symbol_name: &str) -> *const c_void {
66 unsafe {
67 let symbol_name: CString = CString::new(symbol_name).unwrap();
68 let symbol_ptr = symbol_name.as_ptr();
69 dlsym(EGL_LIBRARY.0, symbol_ptr).cast_const()
70 }
71}
72
73pub(crate) unsafe fn lookup_egl_extension(name: &CStr) -> *mut c_void {
74 EGL_FUNCTIONS.with(|egl| mem::transmute(egl.GetProcAddress(name.as_ptr())))
75}