glutin/api/egl/
mod.rs
1use std::ffi::{self, CString};
10use std::ops::{Deref, DerefMut};
11
12use glutin_egl_sys::egl;
13
14use libloading::Library;
15use once_cell::sync::{Lazy, OnceCell};
16
17#[cfg(unix)]
18use libloading::os::unix as libloading_os;
19#[cfg(windows)]
20use libloading::os::windows as libloading_os;
21
22use crate::error::{Error, ErrorKind, Result};
23use crate::lib_loading::{SymLoading, SymWrapper};
24
25pub mod config;
26pub mod context;
27pub mod device;
28pub mod display;
29pub mod surface;
30
31pub(crate) static EGL: Lazy<Option<Egl>> = Lazy::new(|| {
35 #[cfg(windows)]
36 let paths = ["libEGL.dll", "atioglxx.dll"];
37
38 #[cfg(not(windows))]
39 let paths = ["libEGL.so.1", "libEGL.so"];
40
41 unsafe { SymWrapper::new(&paths).map(Egl).ok() }
42});
43
44type EglGetProcAddress = unsafe extern "system" fn(*const ffi::c_void) -> *const ffi::c_void;
45static EGL_GET_PROC_ADDRESS: OnceCell<libloading_os::Symbol<EglGetProcAddress>> = OnceCell::new();
46
47#[allow(missing_debug_implementations)]
49pub struct Egl(SymWrapper<egl::Egl>);
50
51unsafe impl Sync for Egl {}
52unsafe impl Send for Egl {}
53
54impl SymLoading for egl::Egl {
55 unsafe fn load_with(lib: &Library) -> Self {
56 let loader = move |sym_name: &'static str| -> *const ffi::c_void {
57 unsafe {
58 let sym_name = CString::new(sym_name.as_bytes()).unwrap();
59 if let Ok(sym) = lib.get(sym_name.as_bytes_with_nul()) {
60 return *sym;
61 }
62
63 let egl_proc_address = EGL_GET_PROC_ADDRESS.get_or_init(|| {
64 let sym: libloading::Symbol<'_, EglGetProcAddress> =
65 lib.get(b"eglGetProcAddress\0").unwrap();
66 sym.into_raw()
67 });
68
69 (egl_proc_address)(sym_name.as_bytes_with_nul().as_ptr() as *const ffi::c_void)
73 }
74 };
75
76 egl::BindWaylandDisplayWL::load_with(loader);
77 egl::UnbindWaylandDisplayWL::load_with(loader);
78 egl::QueryWaylandBufferWL::load_with(loader);
79 egl::CreateWaylandBufferFromImageWL::load_with(loader);
80
81 Self::load_with(loader)
82 }
83}
84
85impl Deref for Egl {
86 type Target = egl::Egl;
87
88 fn deref(&self) -> &Self::Target {
89 &self.0
90 }
91}
92
93impl DerefMut for Egl {
94 fn deref_mut(&mut self) -> &mut Self::Target {
95 &mut self.0
96 }
97}
98
99fn check_error() -> Result<()> {
101 let egl = EGL.as_ref().unwrap();
102 unsafe {
103 let raw_code = egl.GetError() as egl::types::EGLenum;
104 let kind = match raw_code {
105 egl::SUCCESS => return Ok(()),
106 egl::NOT_INITIALIZED => ErrorKind::InitializationFailed,
107 egl::BAD_ACCESS => ErrorKind::BadAccess,
108 egl::BAD_ALLOC => ErrorKind::OutOfMemory,
109 egl::BAD_ATTRIBUTE => ErrorKind::BadAttribute,
110 egl::BAD_CONTEXT => ErrorKind::BadContext,
111 egl::BAD_CONFIG => ErrorKind::BadConfig,
112 egl::BAD_CURRENT_SURFACE => ErrorKind::BadCurrentSurface,
113 egl::BAD_DISPLAY => ErrorKind::BadDisplay,
114 egl::BAD_SURFACE => ErrorKind::BadSurface,
115 egl::BAD_MATCH => ErrorKind::BadMatch,
116 egl::BAD_PARAMETER => ErrorKind::BadParameter,
117 egl::BAD_NATIVE_PIXMAP => ErrorKind::BadNativePixmap,
118 egl::BAD_NATIVE_WINDOW => ErrorKind::BadNativeWindow,
119 egl::CONTEXT_LOST => ErrorKind::ContextLost,
120 _ => ErrorKind::Misc,
121 };
122
123 Err(Error::new(Some(raw_code as i64), None, kind))
124 }
125}