1#![allow(non_camel_case_types, non_snake_case, dead_code)]
2
3pub type EGLNativeDisplayType = *mut ();
4pub type EGLNativePixmapType = ::std::os::raw::c_ulong;
5pub type EGLNativeWindowType = ::std::os::raw::c_ulong;
6
7pub use core::ptr::null_mut;
8
9pub const EGL_NO_CONTEXT: EGLContext = 0 as EGLContext;
10pub const EGL_NO_SURFACE: EGLSurface = 0 as EGLSurface;
11
12pub const EGL_WINDOW_BIT: u32 = 4;
13
14pub const EGL_OPENGL_ES2_BIT: u32 = 4;
15
16pub const EGL_SUCCESS: u32 = 12288;
17pub const EGL_ALPHA_SIZE: u32 = 12321;
18pub const EGL_BLUE_SIZE: u32 = 12322;
19pub const EGL_GREEN_SIZE: u32 = 12323;
20pub const EGL_RED_SIZE: u32 = 12324;
21pub const EGL_DEPTH_SIZE: u32 = 12325;
22pub const EGL_STENCIL_SIZE: u32 = 12326;
23pub const EGL_NATIVE_VISUAL_ID: u32 = 12334;
24pub const EGL_SURFACE_TYPE: u32 = 12339;
25pub const EGL_NONE: u32 = 12344;
26pub const EGL_RENDERABLE_TYPE: u32 = 12352;
27pub const EGL_HEIGHT: u32 = 12374;
28pub const EGL_WIDTH: u32 = 12375;
29pub const EGL_CONTEXT_CLIENT_VERSION: u32 = 12440;
30pub const EGL_OPENGL_ES_API: u32 = 12448;
31
32pub const EGL_GL_TEXTURE_2D_KHR: u32 = 12465;
33
34pub const EGL_PLATFORM_X11_EXT: u32 = 12757;
35pub const EGL_PLATFORM_GBM_KHR: u32 = 12759;
36
37pub const EGL_LINUX_DMA_BUF_EXT: u32 = 12912;
38pub const EGL_LINUX_DRM_FOURCC_EXT: u32 = 12913;
39pub const EGL_DMA_BUF_PLANE0_FD_EXT: u32 = 12914;
40pub const EGL_DMA_BUF_PLANE0_OFFSET_EXT: u32 = 12915;
41pub const EGL_DMA_BUF_PLANE0_PITCH_EXT: u32 = 12916;
42pub const EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT: u32 = 13379;
43pub const EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT: u32 = 13380;
44
45pub type NativeDisplayType = EGLNativeDisplayType;
46pub type NativePixmapType = EGLNativePixmapType;
47pub type NativeWindowType = EGLNativeWindowType;
48pub type EGLint = i32;
49pub type EGLuint64KHR = u64;
50pub type EGLenum = ::std::os::raw::c_uint;
51pub type EGLBoolean = ::std::os::raw::c_uint;
52pub type EGLDisplay = *mut ::std::os::raw::c_void;
53pub type EGLConfig = *mut ::std::os::raw::c_void;
54pub type EGLSurface = *mut ::std::os::raw::c_void;
55pub type EGLContext = *mut ::std::os::raw::c_void;
56pub type EGLClientBuffer = *mut ::std::os::raw::c_void;
57pub type EGLImageKHR = *mut ::std::os::raw::c_void;
58pub type __eglMustCastToProperFunctionPointerType = ::std::option::Option<unsafe extern "C" fn()>;
59pub type PFNEGLBINDAPIPROC = ::std::option::Option<unsafe extern "C" fn(api: EGLenum) -> EGLBoolean>;
60pub type PFNEGLCHOOSECONFIGPROC = ::std::option::Option<
61unsafe extern "C" fn(
62 dpy: EGLDisplay,
63 attrib_list: *const EGLint,
64 configs: *mut EGLConfig,
65 config_size: EGLint,
66 num_config: *mut EGLint,
67) -> EGLBoolean,
68>;
69pub type PFNEGLCOPYBUFFERSPROC = ::std::option::Option<
70unsafe extern "C" fn(
71 dpy: EGLDisplay,
72 surface: EGLSurface,
73 target: EGLNativePixmapType,
74) -> EGLBoolean,
75>;
76pub type PFNEGLCREATECONTEXTPROC = ::std::option::Option<
77unsafe extern "C" fn(
78 dpy: EGLDisplay,
79 config: EGLConfig,
80 share_context: EGLContext,
81 attrib_list: *const EGLint,
82) -> EGLContext,
83>;
84pub type PFNEGLCREATEIMAGEKHRPROC = ::std::option::Option<
85unsafe extern "C" fn(
86 dpy: EGLDisplay,
87 ctx: EGLContext,
88 target: EGLenum,
89 buffer: EGLClientBuffer,
90 attrib_list: *const EGLint,
91) -> EGLImageKHR,
92>;
93pub type PFNEGLDESTROYIMAGEKHRPROC = ::std::option::Option<
94unsafe extern "C" fn(
95 dpy: EGLDisplay,
96 image: EGLImageKHR,
97) -> EGLBoolean,
98>;
99pub type PFNEGLCREATEPBUFFERSURFACEPROC = ::std::option::Option<
100unsafe extern "C" fn(
101 dpy: EGLDisplay,
102 config: EGLConfig,
103 attrib_list: *const EGLint,
104) -> EGLSurface,
105>;
106pub type PFNEGLCREATEPIXMAPSURFACEPROC = ::std::option::Option<
107unsafe extern "C" fn(
108 dpy: EGLDisplay,
109 config: EGLConfig,
110 pixmap: EGLNativePixmapType,
111 attrib_list: *const EGLint,
112) -> EGLSurface,
113>;
114pub type PFNEGLCREATEWINDOWSURFACEPROC = ::std::option::Option<
115unsafe extern "C" fn(
116 dpy: EGLDisplay,
117 config: EGLConfig,
118 win: EGLNativeWindowType,
119 attrib_list: *const EGLint,
120) -> EGLSurface,
121>;
122pub type PFNEGLDESTROYCONTEXTPROC =
123::std::option::Option<unsafe extern "C" fn(dpy: EGLDisplay, ctx: EGLContext) -> EGLBoolean>;
124pub type PFNEGLDESTROYSURFACEPROC =
125::std::option::Option<unsafe extern "C" fn(dpy: EGLDisplay, surface: EGLSurface) -> EGLBoolean>;
126pub type PFNEGLGETCONFIGATTRIBPROC = ::std::option::Option<
127unsafe extern "C" fn(
128 dpy: EGLDisplay,
129 config: EGLConfig,
130 attribute: EGLint,
131 value: *mut EGLint,
132) -> EGLBoolean,
133>;
134pub type PFNEGLGETCONFIGSPROC = ::std::option::Option<
135unsafe extern "C" fn(
136 dpy: EGLDisplay,
137 configs: *mut EGLConfig,
138 config_size: EGLint,
139 num_config: *mut EGLint,
140) -> EGLBoolean,
141>;
142pub type PFNEGLGETCURRENTDISPLAYPROC = ::std::option::Option<unsafe extern "C" fn() -> EGLDisplay>;
143pub type PFNEGLGETCURRENTSURFACEPROC =
144::std::option::Option<unsafe extern "C" fn(readdraw: EGLint) -> EGLSurface>;
145pub type PFNEGLGETDISPLAYPROC =
146::std::option::Option<unsafe extern "C" fn(display_id: EGLNativeDisplayType) -> EGLDisplay>;
147pub type PFNEGLGETERRORPROC = ::std::option::Option<unsafe extern "C" fn() -> EGLint>;
148pub type PFNEGLGETPROCADDRESSPROC = ::std::option::Option<
149unsafe extern "C" fn(
150 procname: *const ::std::os::raw::c_char,
151) -> *mut ::std::os::raw::c_void,
152>;
153pub type PFNEGLINITIALIZEPROC = ::std::option::Option<
154unsafe extern "C" fn(dpy: EGLDisplay, major: *mut EGLint, minor: *mut EGLint) -> EGLBoolean,
155>;
156pub type PFNEGLMAKECURRENTPROC = ::std::option::Option<
157unsafe extern "C" fn(
158 dpy: EGLDisplay,
159 draw: EGLSurface,
160 read: EGLSurface,
161 ctx: EGLContext,
162) -> EGLBoolean,
163>;
164pub type PFNEGLQUERYCONTEXTPROC = ::std::option::Option<
165unsafe extern "C" fn(
166 dpy: EGLDisplay,
167 ctx: EGLContext,
168 attribute: EGLint,
169 value: *mut EGLint,
170) -> EGLBoolean,
171>;
172pub type PFNEGLQUERYSTRINGPROC = ::std::option::Option<
173unsafe extern "C" fn(dpy: EGLDisplay, name: EGLint) -> *const ::std::os::raw::c_char,
174>;
175pub type PFNEGLQUERYSURFACEPROC = ::std::option::Option<
176unsafe extern "C" fn(
177 dpy: EGLDisplay,
178 surface: EGLSurface,
179 attribute: EGLint,
180 value: *mut EGLint,
181) -> EGLBoolean,
182>;
183pub type PFNEGLSWAPBUFFERSPROC =
184::std::option::Option<unsafe extern "C" fn(dpy: EGLDisplay, surface: EGLSurface) -> EGLBoolean>;
185pub type PFNEGLTERMINATEPROC =
186::std::option::Option<unsafe extern "C" fn(dpy: EGLDisplay) -> EGLBoolean>;
187pub type PFNEGLWAITGLPROC = ::std::option::Option<unsafe extern "C" fn() -> EGLBoolean>;
188pub type PFNEGLWAITNATIVEPROC =
189::std::option::Option<unsafe extern "C" fn(engine: EGLint) -> EGLBoolean>;
190pub type PFNEGLBINDTEXIMAGEPROC = ::std::option::Option<
191unsafe extern "C" fn(dpy: EGLDisplay, surface: EGLSurface, buffer: EGLint) -> EGLBoolean,
192>;
193pub type PFNEGLRELEASETEXIMAGEPROC = ::std::option::Option<
194unsafe extern "C" fn(dpy: EGLDisplay, surface: EGLSurface, buffer: EGLint) -> EGLBoolean,
195>;
196pub type PFNEGLSURFACEATTRIBPROC = ::std::option::Option<
197unsafe extern "C" fn(
198 dpy: EGLDisplay,
199 surface: EGLSurface,
200 attribute: EGLint,
201 value: EGLint,
202) -> EGLBoolean,
203>;
204pub type PFNEGLSWAPINTERVALPROC =
205::std::option::Option<unsafe extern "C" fn(dpy: EGLDisplay, interval: EGLint) -> EGLBoolean>;
206
207pub type PFNEGLGETPLATFORMDISPLAYEXTPROC = ::std::option::Option<
208unsafe extern "C" fn(
209 platform: EGLenum,
210 native_display: *mut ::std::os::raw::c_void,
211 attrib_list: *const EGLint,
212) -> EGLDisplay,
213>;
214
215pub type PFNEGLEXPORTDMABUFIMAGEQUERYMESAPROC = ::std::option::Option<
216unsafe extern "C" fn(
217 dpy: EGLDisplay,
218 image: EGLImageKHR,
219 fourcc: *mut i32,
220 num_planes: *mut i32,
221 modifiers: *mut EGLuint64KHR,
222) -> EGLBoolean,
223>;
224pub type PFNEGLEXPORTDMABUFIMAGEMESAPROC = ::std::option::Option<
225unsafe extern "C" fn(
226 dpy: EGLDisplay,
227 image: EGLImageKHR,
228 fds: *mut i32,
229 strides: *mut EGLint,
230 offsets: *mut EGLint,
231) -> EGLBoolean,
232>;
233
234type PFNGLEGLIMAGETARGETTEXTURE2DOESPROC = ::std::option::Option<
236unsafe extern "C" fn(
237 super::gl_sys::GLenum,
238 EGLImageKHR,
239),
240>;
241
242struct Module(::std::ptr::NonNull<::std::os::raw::c_void>);
243
244pub struct LibEgl {
245 pub eglBindAPI: PFNEGLBINDAPIPROC,
246 pub eglChooseConfig: PFNEGLCHOOSECONFIGPROC,
247 pub eglCopyBuffers: PFNEGLCOPYBUFFERSPROC,
248 pub eglCreateContext: PFNEGLCREATECONTEXTPROC,
249 pub eglCreatePbufferSurface: PFNEGLCREATEPBUFFERSURFACEPROC,
250 pub eglCreatePixmapSurface: PFNEGLCREATEPIXMAPSURFACEPROC,
251 pub eglCreateWindowSurface: PFNEGLCREATEWINDOWSURFACEPROC,
252 pub eglDestroyContext: PFNEGLDESTROYCONTEXTPROC,
253 pub eglDestroySurface: PFNEGLDESTROYSURFACEPROC,
254 pub eglGetConfigAttrib: PFNEGLGETCONFIGATTRIBPROC,
255 pub eglGetConfigs: PFNEGLGETCONFIGSPROC,
256 pub eglGetCurrentDisplay: PFNEGLGETCURRENTDISPLAYPROC,
257 pub eglGetCurrentSurface: PFNEGLGETCURRENTSURFACEPROC,
258 pub eglGetDisplay: PFNEGLGETDISPLAYPROC,
259 pub eglGetError: PFNEGLGETERRORPROC,
260 pub eglGetProcAddress: PFNEGLGETPROCADDRESSPROC,
261 pub eglInitialize: PFNEGLINITIALIZEPROC,
262 pub eglMakeCurrent: PFNEGLMAKECURRENTPROC,
263 pub eglQueryContext: PFNEGLQUERYCONTEXTPROC,
264 pub eglQueryString: PFNEGLQUERYSTRINGPROC,
265 pub eglQuerySurface: PFNEGLQUERYSURFACEPROC,
266 pub eglSwapBuffers: PFNEGLSWAPBUFFERSPROC,
267 pub eglTerminate: PFNEGLTERMINATEPROC,
268 pub eglWaitGL: PFNEGLWAITGLPROC,
269 pub eglWaitNative: PFNEGLWAITNATIVEPROC,
270 pub eglBindTexImage: PFNEGLBINDTEXIMAGEPROC,
271 pub eglReleaseTexImage: PFNEGLRELEASETEXIMAGEPROC,
272 pub eglSurfaceAttrib: PFNEGLSURFACEATTRIBPROC,
273 pub eglSwapInterval: PFNEGLSWAPINTERVALPROC,
274
275 pub eglCreateImageKHR: PFNEGLCREATEIMAGEKHRPROC,
276 pub eglDestroyImageKHR: PFNEGLDESTROYIMAGEKHRPROC,
277 pub eglExportDMABUFImageQueryMESA: PFNEGLEXPORTDMABUFIMAGEQUERYMESAPROC,
278 pub eglExportDMABUFImageMESA: PFNEGLEXPORTDMABUFIMAGEMESAPROC,
279 pub eglGetPlatformDisplayEXT: PFNEGLGETPLATFORMDISPLAYEXTPROC,
280
281 pub glEGLImageTargetTexture2DOES: PFNGLEGLIMAGETARGETTEXTURE2DOESPROC,
283
284 _keep_module_alive: Module,
285}
286
287impl LibEgl {
288 pub fn try_load() -> Option<LibEgl> {
289 use self::super::libc_sys::{dlclose, dlopen, dlsym, RTLD_LAZY, RTLD_LOCAL};
290 use std::{
291 ffi::{CString, CStr},
292 ptr::NonNull,
293 };
294
295 impl Module {
296 pub fn load(path: &str) -> Result<Self,()> {
297 let path = CString::new(path).unwrap();
298
299 let module = unsafe {dlopen(path.as_ptr(), RTLD_LAZY | RTLD_LOCAL)};
300 if module.is_null() {
301 Err(())
302 } else {
303 Ok(Module(unsafe {NonNull::new_unchecked(module)}))
304 }
305 }
306
307 pub fn get_symbol<F: Sized>(&self, name: &str) -> Result<F, ()> {
308 let name = CString::new(name).unwrap();
309
310 let symbol = unsafe {dlsym(self.0.as_ptr(), name.as_ptr())};
311
312 if symbol.is_null() {
313 return Err(());
314 }
315
316 Ok(unsafe {std::mem::transmute_copy::<_, F>(&symbol)})
317 }
318 }
319
320 impl Drop for Module {
321 fn drop(&mut self) {
322 unsafe {dlclose(self.0.as_ptr())};
323 }
324 }
325
326 let module = Module::load("libEGL.so").or_else(|_| Module::load("libEGL.so.1")).ok()?;
327
328 let eglGetProcAddress: PFNEGLGETPROCADDRESSPROC = module.get_symbol("eglGetProcAddress").ok();
329 macro_rules! get_ext_fn {
330 ($name:literal) => {
331 eglGetProcAddress.and_then(|gpa| unsafe {
332 std::mem::transmute(gpa(CStr::from_bytes_with_nul(concat!($name, "\0").as_bytes()).unwrap().as_ptr()))
333 })
334 }
335 }
336
337 Some(LibEgl {
338 eglBindAPI: module.get_symbol("eglBindAPI").ok(),
339 eglChooseConfig: module.get_symbol("eglChooseConfig").ok(),
340 eglCopyBuffers: module.get_symbol("eglCopyBuffers").ok(),
341 eglCreateContext: module.get_symbol("eglCreateContext").ok(),
342 eglCreatePbufferSurface: module.get_symbol("eglCreatePbufferSurface").ok(),
343 eglCreatePixmapSurface: module.get_symbol("eglCreatePixmapSurface").ok(),
344 eglCreateWindowSurface: module.get_symbol("eglCreateWindowSurface").ok(),
345 eglDestroyContext: module.get_symbol("eglDestroyContext").ok(),
346 eglDestroySurface: module.get_symbol("eglDestroySurface").ok(),
347 eglGetConfigAttrib: module.get_symbol("eglGetConfigAttrib").ok(),
348 eglGetConfigs: module.get_symbol("eglGetConfigs").ok(),
349 eglGetCurrentDisplay: module.get_symbol("eglGetCurrentDisplay").ok(),
350 eglGetCurrentSurface: module.get_symbol("eglGetCurrentSurface").ok(),
351 eglGetDisplay: module.get_symbol("eglGetDisplay").ok(),
352 eglGetError: module.get_symbol("eglGetError").ok(),
353 eglGetProcAddress,
354 eglInitialize: module.get_symbol("eglInitialize").ok(),
355 eglMakeCurrent: module.get_symbol("eglMakeCurrent").ok(),
356 eglQueryContext: module.get_symbol("eglQueryContext").ok(),
357 eglQueryString: module.get_symbol("eglQueryString").ok(),
358 eglQuerySurface: module.get_symbol("eglQuerySurface").ok(),
359 eglSwapBuffers: module.get_symbol("eglSwapBuffers").ok(),
360 eglTerminate: module.get_symbol("eglTerminate").ok(),
361 eglWaitGL: module.get_symbol("eglWaitGL").ok(),
362 eglWaitNative: module.get_symbol("eglWaitNative").ok(),
363 eglBindTexImage: module.get_symbol("eglBindTexImage").ok(),
364 eglReleaseTexImage: module.get_symbol("eglReleaseTexImage").ok(),
365 eglSurfaceAttrib: module.get_symbol("eglSurfaceAttrib").ok(),
366 eglSwapInterval: module.get_symbol("eglSwapInterval").ok(),
367
368 eglCreateImageKHR: get_ext_fn!("eglCreateImageKHR"),
369 eglDestroyImageKHR: get_ext_fn!("eglDestroyImageKHR"),
370 eglExportDMABUFImageQueryMESA: get_ext_fn!("eglExportDMABUFImageQueryMESA"),
371 eglExportDMABUFImageMESA: get_ext_fn!("eglExportDMABUFImageMESA"),
372 eglGetPlatformDisplayEXT: get_ext_fn!("eglGetPlatformDisplayEXT"),
373
374 glEGLImageTargetTexture2DOES: get_ext_fn!("glEGLImageTargetTexture2DOES"),
375
376 _keep_module_alive: module,
377 })
378 }
379}
380
381#[derive(Debug)]
382pub enum EglError {
383 NoDisplay,
384 InitializeFailed,
385 CreateContextFailed,
386}
387
388pub struct Egl {}
389
390#[cfg(target_os="android")]
391pub unsafe fn create_egl_context(
392 egl: &mut LibEgl,
393 display: *mut std::ffi::c_void,
394 alpha: bool,
395) -> Result<(EGLContext, EGLConfig, EGLDisplay), EglError> {
396
397 let display = (egl.eglGetDisplay.unwrap())(display as _);
398 if display == null_mut() {
399 return Err(EglError::NoDisplay);
400 }
401
402 if (egl.eglInitialize.unwrap())(display, null_mut(), null_mut()) == 0 {
403 return Err(EglError::InitializeFailed);
404 }
405
406 let alpha_size = if alpha {8} else {0};
407 #[rustfmt::skip]
408 let cfg_attributes = vec![
409 EGL_SURFACE_TYPE,
410 EGL_WINDOW_BIT,
411 EGL_RED_SIZE,
412 8,
413 EGL_GREEN_SIZE,
414 8,
415 EGL_BLUE_SIZE,
416 8,
417 EGL_ALPHA_SIZE,
418 alpha_size,
419 EGL_DEPTH_SIZE,
420 24,
421 EGL_STENCIL_SIZE,
422 0,
423 EGL_NONE,
424 ];
425 let mut available_cfgs: Vec<EGLConfig> = vec![null_mut(); 32];
426 let mut cfg_count = 0;
427
428 (egl.eglChooseConfig.unwrap())(
429 display,
430 cfg_attributes.as_ptr() as _,
431 available_cfgs.as_ptr() as _,
432 32,
433 &mut cfg_count as *mut _ as *mut _,
434 );
435 assert!(cfg_count > 0);
436 assert!(cfg_count <= 32);
437
438 let mut config: EGLConfig = null_mut();
440 let mut exact_cfg_found = false;
441 for c in &mut available_cfgs[0..cfg_count] {
442 let mut r: i32 = 0;
443 let mut g: i32 = 0;
444 let mut b: i32 = 0;
445 let mut a: i32 = 0;
446 let mut d: i32 = 0;
447 if (egl.eglGetConfigAttrib.unwrap())(display, *c, EGL_RED_SIZE as _, &mut r) == 1
448 && (egl.eglGetConfigAttrib.unwrap())(display, *c, EGL_GREEN_SIZE as _, &mut g) == 1
449 && (egl.eglGetConfigAttrib.unwrap())(display, *c, EGL_BLUE_SIZE as _, &mut b) == 1
450 && (egl.eglGetConfigAttrib.unwrap())(display, *c, EGL_ALPHA_SIZE as _, &mut a) == 1
451 && (egl.eglGetConfigAttrib.unwrap())(display, *c, EGL_DEPTH_SIZE as _, &mut d) == 1
452 && r == 8
453 && g == 8
454 && b == 8
455 && (alpha_size == 0 || a == alpha_size as _)
456 && d == 16
457 {
458 exact_cfg_found = true;
459 config = *c;
460 break;
461 }
462 }
463 if !exact_cfg_found {
464 config = available_cfgs[0];
465 }
466 let ctx_attributes = vec![EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE];
467 let context = (egl.eglCreateContext.unwrap())(
468 display,
469 config,
470 null_mut(),
471 ctx_attributes.as_ptr() as _,
472 );
473 if context.is_null() {
474 return Err(EglError::CreateContextFailed);
475 }
476
477 return Ok((context, config, display));
478}