khronos_egl/
lib.rs

1//! This crate provides a binding for the Khronos EGL 1.5 API.
2//! It was originally a fork of the [egl](https://crates.io/crates/egl) crate,
3//! which is left unmaintained.
4//!
5//! ## Usage
6//!
7//! You can access the EGL API using an [`Instance`]
8//! object defined by either statically linking with `libEGL.so.1` at compile time,
9//! or dynamically loading the EGL library at runtime.
10//!
11//! ### Static linking
12//!
13//! You must enable static linking using the `static` feature in your `Cargo.toml`:
14//! ```toml
15//! khronos-egl = { version = ..., features = ["static"] }
16//! ```
17//!
18//! This will add a dependency to the [`pkg-config`](https://crates.io/crates/pkg-config) crate,
19//! necessary to find the EGL library at compile time.
20//! Here is a simple example showing how to use this library to create an EGL context when static linking is enabled.
21//!
22//! ```rust
23//! extern crate khronos_egl as egl;
24//!
25//! fn main() -> Result<(), egl::Error> {
26//! 	// Create an EGL API instance.
27//! 	// The `egl::Static` API implementation is only available when the `static` feature is enabled.
28//! 	let egl = egl::Instance::new(egl::Static);
29//!
30//! 	let wayland_display = wayland_client::Display::connect_to_env().expect("unable to connect to the wayland server");
31//! 	let display = egl.get_display(wayland_display.get_display_ptr() as *mut std::ffi::c_void).unwrap();
32//! 	egl.initialize(display)?;
33//!
34//! 	let attributes = [
35//! 		egl::RED_SIZE, 8,
36//! 		egl::GREEN_SIZE, 8,
37//! 		egl::BLUE_SIZE, 8,
38//! 		egl::NONE
39//! 	];
40//!
41//! 	let config = egl.choose_first_config(display, &attributes)?.expect("unable to find an appropriate ELG configuration");
42//!
43//! 	let context_attributes = [
44//! 		egl::CONTEXT_MAJOR_VERSION, 4,
45//! 		egl::CONTEXT_MINOR_VERSION, 0,
46//! 		egl::CONTEXT_OPENGL_PROFILE_MASK, egl::CONTEXT_OPENGL_CORE_PROFILE_BIT,
47//! 		egl::NONE
48//! 	];
49//!
50//! 	egl.create_context(display, config, None, &context_attributes);
51//!
52//! 	Ok(())
53//! }
54//! ```
55//!
56//! The creation of a `Display` instance is not detailed here since it depends on your display server.
57//! It is created using the `get_display` function with a pointer to the display server connection handle.
58//! For instance, if you are using the [wayland-client](https://crates.io/crates/wayland-client) crate,
59//! you can get this pointer using the `Display::get_display_ptr` method.
60//!
61//! #### Static API Instance
62//!
63//! It may be bothering in some applications to pass the `Instance` to every fonction that needs to call the EGL API.
64//! One workaround would be to define a static `Instance`,
65//! which should be possible to define at compile time using static linking.
66//! However this is not yet supported by the stable `rustc` compiler.
67//! With the nightly compiler,
68//! you can combine the `nightly` and `static` features so that this crate
69//! can provide a static `Instance`, called `API` that can then be accessed everywhere.
70//!
71//! ```
72//! # extern crate khronos_egl as egl;
73//! use egl::API as egl;
74//! ```
75//!
76//! ### Dynamic Linking
77//!
78//! Dynamic linking allows your application to accept multiple versions of EGL and be more flexible.
79//! You must enable dynamic linking using the `dynamic` feature in your `Cargo.toml`:
80//! ```toml
81//! khronos-egl = { version = ..., features = ["dynamic"] }
82//! ```
83//!
84//! This will add a dependency to the [`libloading`](https://crates.io/crates/libloading) crate,
85//! necessary to find the EGL library at runtime.
86//! You can then load the EGL API into a `Instance<Dynamic<libloading::Library>>` as follows:
87//!
88//! ```
89//! # extern crate khronos_egl as egl;
90//! let lib = libloading::Library::new("libEGL.so.1").expect("unable to find libEGL.so.1");
91//! let egl = unsafe { egl::DynamicInstance::<egl::EGL1_4>::load_required_from(lib).expect("unable to load libEGL.so.1") };
92//! ```
93//!
94//! Here, `egl::EGL1_4` is used to specify what is the minimum required version of EGL that must be provided by `libEGL.so.1`.
95//! This will return a `DynamicInstance<egl::EGL1_4>`, however in that case where `libEGL.so.1` provides a more recent version of EGL,
96//! you can still upcast ths instance to provide version specific features:
97//! ```
98//! # extern crate khronos_egl as egl;
99//! # let lib = libloading::Library::new("libEGL.so.1").expect("unable to find libEGL.so.1");
100//! # let egl = unsafe { egl::DynamicInstance::<egl::EGL1_4>::load_required_from(lib).expect("unable to load libEGL.so.1") };
101//! match egl.upcast::<egl::EGL1_5>() {
102//! 	Some(egl1_5) => {
103//! 		// do something with EGL 1.5
104//! 	}
105//! 	None => {
106//! 		// do something with EGL 1.4 instead.
107//! 	}
108//! };
109//! ```
110//!
111//! ## Troubleshooting
112//!
113//! ### Static Linking with OpenGL ES
114//!
115//! When using OpenGL ES with `khronos-egl` with the `static` feature,
116//! it is necessary to place a dummy extern at the top of your application which links libEGL first, then GLESv1/2.
117//! This is because libEGL provides symbols required by GLESv1/2.
118//! Here's how to work around this:
119//!
120//! ```
121//! ##[link(name = "EGL")]
122//! ##[link(name = "GLESv2")]
123//! extern {}
124//! ```
125#![allow(non_upper_case_globals)]
126#![allow(non_snake_case)]
127
128extern crate libc;
129
130use std::convert::{TryFrom, TryInto};
131use std::ffi::CStr;
132use std::ffi::CString;
133use std::fmt;
134use std::ptr;
135
136use libc::{c_uint, c_char, c_void};
137
138/// EGL API provider.
139pub trait Api {
140	/// Version of the provided EGL API.
141	fn version(&self) -> Version;
142}
143
144pub trait Downcast<V> {
145	fn downcast(&self) -> &V;
146}
147
148impl<T> Downcast<T> for T {
149	fn downcast(&self) -> &T {
150		self
151	}
152}
153
154pub trait Upcast<V> {
155	fn upcast(&self) -> Option<&V>;
156}
157
158impl<T> Upcast<T> for T {
159	fn upcast(&self) -> Option<&T> {
160		Some(self)
161	}
162}
163
164/// EGL API instance.
165///
166/// An instance wraps an interface to the EGL API and provide
167/// rust-friendly access to it.
168pub struct Instance<T> {
169	api: T
170}
171
172impl<T> Instance<T> {
173	/// Cast the API.
174	#[inline(always)]
175	pub fn cast_into<U: From<T>>(self) -> Instance<U> {
176		Instance {
177			api: self.api.into()
178		}
179	}
180
181	/// Try to cast the API.
182	#[inline(always)]
183	pub fn try_cast_into<U: TryFrom<T>>(self) -> Result<Instance<U>, Instance<U::Error>> {
184		match self.api.try_into() {
185			Ok(t) => Ok(Instance {
186				api: t
187			}),
188			Err(e) => Err(Instance {
189				api: e
190			})
191		}
192	}
193
194	/// Returns the version of the provided EGL API.
195	#[inline(always)]
196	pub fn version(&self) -> Version where T: Api {
197		self.api.version()
198	}
199}
200
201impl<T> Instance<T> {
202	#[inline(always)]
203	pub const fn new(api: T) -> Instance<T> {
204		Instance {
205			api
206		}
207	}
208}
209
210impl<T: fmt::Debug> fmt::Debug for Instance<T> {
211	#[inline(always)]
212	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
213		write!(f, "Instance({:?})", self.api)
214	}
215}
216
217impl<T> From<T> for Instance<T> {
218	#[inline(always)]
219	fn from(t: T) -> Instance<T> {
220		Instance::new(t)
221	}
222}
223
224// ------------------------------------------------------------------------------------------------
225// EGL 1.0
226// ------------------------------------------------------------------------------------------------
227
228#[cfg(feature = "1_0")]
229mod egl1_0 {
230	use super::*;
231
232	pub type Boolean = c_uint;
233	pub type Int = i32;
234	pub type Attrib = usize;
235	pub type EGLDisplay = *mut c_void;
236	pub type EGLConfig = *mut c_void;
237	pub type EGLContext = *mut c_void;
238	pub type EGLSurface = *mut c_void;
239	pub type NativeDisplayType = *mut c_void;
240
241	#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
242	pub struct Display(pub(crate) EGLDisplay);
243
244	impl Display {
245		#[inline]
246		pub unsafe fn from_ptr(ptr: EGLDisplay) -> Display {
247			Display(ptr)
248		}
249
250		#[inline]
251		pub fn as_ptr(&self) -> EGLDisplay {
252			self.0
253		}
254	}
255
256	#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
257	pub struct Config(pub(crate) EGLConfig);
258
259	impl Config {
260		#[inline]
261		pub unsafe fn from_ptr(ptr: EGLConfig) -> Config {
262			Config(ptr)
263		}
264
265		#[inline]
266		pub fn as_ptr(&self) -> EGLConfig {
267			self.0
268		}
269	}
270
271	#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
272	pub struct Context(pub(crate) EGLContext);
273
274	impl Context {
275		#[inline]
276		pub unsafe fn from_ptr(ptr: EGLContext) -> Context {
277			Context(ptr)
278		}
279
280		#[inline]
281		pub fn as_ptr(&self) -> EGLContext {
282			self.0
283		}
284	}
285
286	#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
287	pub struct Surface(pub(crate) EGLSurface);
288
289	impl Surface {
290		#[inline]
291		pub unsafe fn from_ptr(ptr: EGLSurface) -> Surface {
292			Surface(ptr)
293		}
294
295		#[inline]
296		pub fn as_ptr(&self) -> EGLSurface {
297			self.0
298		}
299	}
300
301	#[cfg(not(android))]
302	pub type NativePixmapType = *mut c_void;
303
304	#[cfg(not(android))]
305	pub type NativeWindowType = *mut c_void;
306
307	#[repr(C)]
308	#[cfg(android)]
309	struct android_native_window_t;
310
311	#[repr(C)]
312	#[cfg(android)]
313	struct egl_native_pixmap_t;
314
315	#[cfg(android)]
316	pub type NativePixmapType = *mut egl_native_pixmap_t;
317
318	#[cfg(android)]
319	pub type NativeWindowType = *mut android_native_window_t;
320
321	pub const ALPHA_SIZE: Int = 0x3021;
322	pub const BAD_ACCESS: Int = 0x3002;
323	pub const BAD_ALLOC: Int = 0x3003;
324	pub const BAD_ATTRIBUTE: Int = 0x3004;
325	pub const BAD_CONFIG: Int = 0x3005;
326	pub const BAD_CONTEXT: Int = 0x3006;
327	pub const BAD_CURRENT_SURFACE: Int = 0x3007;
328	pub const BAD_DISPLAY: Int = 0x3008;
329	pub const BAD_MATCH: Int = 0x3009;
330	pub const BAD_NATIVE_PIXMAP: Int = 0x300A;
331	pub const BAD_NATIVE_WINDOW: Int = 0x300B;
332	pub const BAD_PARAMETER: Int = 0x300C;
333	pub const BAD_SURFACE: Int = 0x300D;
334	pub const BLUE_SIZE: Int = 0x3022;
335	pub const BUFFER_SIZE: Int = 0x3020;
336	pub const CONFIG_CAVEAT: Int = 0x3027;
337	pub const CONFIG_ID: Int = 0x3028;
338	pub const CORE_NATIVE_ENGINE: Int = 0x305B;
339	pub const DEPTH_SIZE: Int = 0x3025;
340	pub const DONT_CARE: Int = -1;
341	pub const DRAW: Int = 0x3059;
342	pub const EXTENSIONS: Int = 0x3055;
343	pub const FALSE: Boolean = 0;
344	pub const GREEN_SIZE: Int = 0x3023;
345	pub const HEIGHT: Int = 0x3056;
346	pub const LARGEST_PBUFFER: Int = 0x3058;
347	pub const LEVEL: Int = 0x3029;
348	pub const MAX_PBUFFER_HEIGHT: Int = 0x302A;
349	pub const MAX_PBUFFER_PIXELS: Int = 0x302B;
350	pub const MAX_PBUFFER_WIDTH: Int = 0x302C;
351	pub const NATIVE_RENDERABLE: Int = 0x302D;
352	pub const NATIVE_VISUAL_ID: Int = 0x302E;
353	pub const NATIVE_VISUAL_TYPE: Int = 0x302F;
354	pub const NONE: Int = 0x3038;
355	pub const ATTRIB_NONE: Attrib = 0x3038;
356	pub const NON_CONFORMANT_CONFIG: Int = 0x3051;
357	pub const NOT_INITIALIZED: Int = 0x3001;
358	pub const NO_CONTEXT: EGLContext = 0 as EGLContext;
359	pub const NO_DISPLAY: EGLDisplay = 0 as EGLDisplay;
360	pub const NO_SURFACE: EGLSurface = 0 as EGLSurface;
361	pub const PBUFFER_BIT: Int = 0x0001;
362	pub const PIXMAP_BIT: Int = 0x0002;
363	pub const READ: Int = 0x305A;
364	pub const RED_SIZE: Int = 0x3024;
365	pub const SAMPLES: Int = 0x3031;
366	pub const SAMPLE_BUFFERS: Int = 0x3032;
367	pub const SLOW_CONFIG: Int = 0x3050;
368	pub const STENCIL_SIZE: Int = 0x3026;
369	pub const SUCCESS: Int = 0x3000;
370	pub const SURFACE_TYPE: Int = 0x3033;
371	pub const TRANSPARENT_BLUE_VALUE: Int = 0x3035;
372	pub const TRANSPARENT_GREEN_VALUE: Int = 0x3036;
373	pub const TRANSPARENT_RED_VALUE: Int = 0x3037;
374	pub const TRANSPARENT_RGB: Int = 0x3052;
375	pub const TRANSPARENT_TYPE: Int = 0x3034;
376	pub const TRUE: Boolean = 1;
377	pub const VENDOR: Int = 0x3053;
378	pub const VERSION: Int = 0x3054;
379	pub const WIDTH: Int = 0x3057;
380	pub const WINDOW_BIT: Int = 0x0004;
381
382	/// EGL errors.
383	#[derive(Clone, Copy, PartialEq, Eq, Debug)]
384	pub enum Error {
385		/// EGL is not initialized, or could not be initialized, for the specified
386		/// EGL display connection.
387		NotInitialized,
388
389		/// EGL cannot access a requested resource (for example a context is bound
390		/// in another thread).
391		BadAccess,
392
393		/// EGL failed to allocate resources for the requested operation.
394		BadAlloc,
395
396		/// An unrecognized attribute or attribute value was passed in the attribute
397		/// list.
398		BadAttribute,
399
400		/// An Context argument does not name a valid EGL rendering context.
401		BadContext,
402
403		/// An Config argument does not name a valid EGL frame buffer configuration.
404		BadConfig,
405
406		/// The current surface of the calling thread is a window, pixel buffer or
407		/// pixmap that is no longer valid.
408		BadCurrentSurface,
409
410		/// An Display argument does not name a valid EGL display connection.
411		BadDisplay,
412
413		/// An Surface argument does not name a valid surface (window, pixel buffer
414		/// or pixmap) configured for GL rendering.
415		BadSurface,
416
417		/// Arguments are inconsistent (for example, a valid context requires
418		/// buffers not supplied by a valid surface).
419		BadMatch,
420
421		/// One or more argument values are invalid.
422		BadParameter,
423
424		/// A NativePixmapType argument does not refer to a valid native pixmap.
425		BadNativePixmap,
426
427		/// A NativeWindowType argument does not refer to a valid native window.
428		BadNativeWindow,
429
430		/// A power management event has occurred. The application must destroy all
431		/// contexts and reinitialise OpenGL ES state and objects to continue
432		/// rendering.
433		ContextLost,
434	}
435
436	impl std::error::Error for Error {
437		fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
438			None
439		}
440	}
441
442	impl Error {
443		pub fn native(&self) -> Int {
444			use Error::*;
445			match self {
446				NotInitialized => NOT_INITIALIZED,
447				BadAccess => BAD_ACCESS,
448				BadAlloc => BAD_ALLOC,
449				BadAttribute => BAD_ATTRIBUTE,
450				BadContext => BAD_CONTEXT,
451				BadConfig => BAD_CONFIG,
452				BadCurrentSurface => BAD_CURRENT_SURFACE,
453				BadDisplay => BAD_DISPLAY,
454				BadSurface => BAD_SURFACE,
455				BadMatch => BAD_MATCH,
456				BadParameter => BAD_PARAMETER,
457				BadNativePixmap => BAD_NATIVE_PIXMAP,
458				BadNativeWindow => BAD_NATIVE_WINDOW,
459				ContextLost => CONTEXT_LOST,
460			}
461		}
462
463		fn message(&self) -> &'static str {
464			use Error::*;
465			match self {
466				NotInitialized => "EGL is not initialized, or could not be initialized, for the specified EGL display connection.",
467				BadAccess => "EGL cannot access a requested resource (for example a context is bound in another thread.",
468				BadAlloc => "EGL failed to allocate resources for the requested operation.",
469				BadAttribute => "An unrecognized attribute or attribute value was passed in the attribute list.",
470				BadContext => "An Context argument does not name a valid EGL rendering context.",
471				BadConfig => "An Config argument does not name a valid EGL frame buffer configuration.",
472				BadCurrentSurface => "The current surface of the calling thread is a window, pixel buffer or pixmap that is no longer valid.",
473				BadDisplay => "An Display argument does not name a valid EGL display connection.",
474				BadSurface => "An Surface argument does not name a valid surface (window, pixel buffer or pixmap) configured for GL rendering.",
475				BadMatch => "Arguments are inconsistent (for example, a valid context requires buffers not supplied by a valid surface.",
476				BadParameter => "One or more argument values are invalid.",
477				BadNativePixmap => "A NativePixmapType argument does not refer to a valid native pixmap.",
478				BadNativeWindow => "A NativeWindowType argument does not refer to a valid native window.",
479				ContextLost => "A power management event has occurred. The application must destroy all contexts and reinitialise OpenGL ES state and objects to continue rendering."
480			}
481		}
482	}
483
484	impl From<Error> for Int {
485		fn from(e: Error) -> Int {
486			e.native()
487		}
488	}
489
490	impl TryFrom<Int> for Error {
491		type Error = Int;
492
493		fn try_from(e: Int) -> Result<Error, Int> {
494			use Error::*;
495			match e {
496				NOT_INITIALIZED => Ok(NotInitialized),
497				BAD_ACCESS => Ok(BadAccess),
498				BAD_ALLOC => Ok(BadAlloc),
499				BAD_ATTRIBUTE => Ok(BadAttribute),
500				BAD_CONTEXT => Ok(BadContext),
501				BAD_CONFIG => Ok(BadConfig),
502				BAD_CURRENT_SURFACE => Ok(BadCurrentSurface),
503				BAD_DISPLAY => Ok(BadDisplay),
504				BAD_SURFACE => Ok(BadSurface),
505				BAD_MATCH => Ok(BadMatch),
506				BAD_PARAMETER => Ok(BadParameter),
507				BAD_NATIVE_PIXMAP => Ok(BadNativePixmap),
508				BAD_NATIVE_WINDOW => Ok(BadNativeWindow),
509				CONTEXT_LOST => Ok(ContextLost),
510				_ => Err(e),
511			}
512		}
513	}
514
515	impl fmt::Display for Error {
516		fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
517			self.message().fmt(f)
518		}
519	}
520
521	pub fn check_int_list(attrib_list: &[Int]) -> Result<(), Error> {
522		if attrib_list.last() == Some(&NONE) {
523			Ok(())
524		} else {
525			Err(Error::BadParameter)
526		}
527	}
528
529	pub fn check_attrib_list(attrib_list: &[Attrib]) -> Result<(), Error> {
530		if attrib_list.last() == Some(&ATTRIB_NONE) {
531			Ok(())
532		} else {
533			Err(Error::BadParameter)
534		}
535	}
536
537	impl<T: api::EGL1_0> Instance<T> {
538		/// Return the number of EGL frame buffer configurations that atch specified
539		/// attributes.
540		///
541		/// This will call `eglChooseConfig` without `null` as `configs` to get the
542		/// number of matching configurations.
543		///
544		/// This will return a `BadParameter` error if `attrib_list` is not a valid
545		/// attributes list (if it does not terminate with `NONE`).
546		pub fn matching_config_count(&self, display: Display, attrib_list: &[Int]) -> Result<usize, Error> {
547			check_int_list(attrib_list)?;
548			unsafe {
549				let mut count = 0;
550
551				if self.api.eglChooseConfig(
552					display.as_ptr(),
553					attrib_list.as_ptr(),
554					ptr::null_mut(),
555					0,
556					&mut count,
557				) == TRUE
558				{
559					Ok(count as usize)
560				} else {
561					Err(self.get_error().unwrap())
562				}
563			}
564		}
565
566		/// Return a list of EGL frame buffer configurations that match specified
567		/// attributes.
568		///
569		/// This will write as many matching configurations in `configs` up to its
570		/// capacity. You can use the function [`matching_config_count`](Self::matching_config_count) to get the
571		/// exact number of configurations matching the specified attributes.
572		///
573		/// ## Example
574		///
575		/// ```
576		/// # extern crate khronos_egl as egl;
577		/// # extern crate wayland_client;
578		/// # fn main() -> Result<(), egl::Error> {
579		/// # let egl = egl::Instance::new(egl::Static);
580		/// # let wayland_display = wayland_client::Display::connect_to_env().expect("unable to connect to the wayland server");
581		/// # let display = egl.get_display(wayland_display.get_display_ptr() as *mut std::ffi::c_void).unwrap();
582		/// # egl.initialize(display)?;
583		/// # let attrib_list = [egl::RED_SIZE, 8, egl::GREEN_SIZE, 8, egl::BLUE_SIZE, 8, egl::NONE];
584		/// // Get the number of matching configurations.
585		/// let count = egl.matching_config_count(display, &attrib_list)?;
586		///
587		/// // Get the matching configurations.
588		/// let mut configs = Vec::with_capacity(count);
589		/// egl.choose_config(display, &attrib_list, &mut configs)?;
590		/// # Ok(())
591		/// # }
592		/// ```
593		///
594		/// This will return a `BadParameter` error if `attrib_list` is not a valid
595		/// attributes list (if it does not terminate with `NONE`).
596		pub fn choose_config(&self, display: Display, attrib_list: &[Int], configs: &mut Vec<Config>) -> Result<(), Error> {
597			check_int_list(attrib_list)?;
598			unsafe {
599				let capacity = configs.capacity();
600				let mut count = 0;
601
602				if self.api.eglChooseConfig(
603					display.as_ptr(),
604					attrib_list.as_ptr(),
605					configs.as_mut_ptr() as *mut EGLConfig,
606					capacity.try_into().unwrap(),
607					&mut count,
608				) == TRUE
609				{
610					configs.set_len(count as usize);
611					Ok(())
612				} else {
613					Err(self.get_error().unwrap())
614				}
615			}
616		}
617
618		/// Return the first EGL frame buffer configuration that match specified
619		/// attributes.
620		///
621		/// This is an helper function that will call `choose_config` with a buffer of
622		/// size 1, which is equivalent to:
623		/// ```
624		/// # extern crate khronos_egl as egl;
625		/// # extern crate wayland_client;
626		/// # fn main() -> Result<(), egl::Error> {
627		/// # let egl = egl::Instance::new(egl::Static);
628		/// # let wayland_display = wayland_client::Display::connect_to_env().expect("unable to connect to the wayland server");
629		/// # let display = egl.get_display(wayland_display.get_display_ptr() as *mut std::ffi::c_void).unwrap();
630		/// # egl.initialize(display)?;
631		/// # let attrib_list = [egl::RED_SIZE, 8, egl::GREEN_SIZE, 8, egl::BLUE_SIZE, 8, egl::NONE];
632		/// let mut configs = Vec::with_capacity(1);
633		/// egl.choose_config(display, &attrib_list, &mut configs)?;
634		/// configs.first();
635		/// # Ok(())
636		/// # }
637		/// ```
638		pub fn choose_first_config(&self, display: Display, attrib_list: &[Int]) -> Result<Option<Config>, Error> {
639			let mut configs = Vec::with_capacity(1);
640			self.choose_config(display, attrib_list, &mut configs)?;
641			Ok(configs.first().map(|config| *config))
642		}
643
644		/// Copy EGL surface color buffer to a native pixmap.
645		pub fn copy_buffers(&self, display: Display, surface: Surface, target: NativePixmapType) -> Result<(), Error> {
646			unsafe {
647				if self.api.eglCopyBuffers(display.as_ptr(), surface.as_ptr(), target) == TRUE {
648					Ok(())
649				} else {
650					Err(self.get_error().unwrap())
651				}
652			}
653		}
654
655		/// Create a new EGL rendering context.
656		///
657		/// This will return a `BadParameter` error if `attrib_list` is not a valid
658		/// attributes list (if it does not terminate with `NONE`).
659		pub fn create_context(&self, display: Display, config: Config, share_context: Option<Context>, attrib_list: &[Int]) -> Result<Context, Error> {
660			check_int_list(attrib_list)?;
661			unsafe {
662				let share_context = match share_context {
663					Some(share_context) => share_context.as_ptr(),
664					None => NO_CONTEXT,
665				};
666
667				let context = self.api.eglCreateContext(
668					display.as_ptr(),
669					config.as_ptr(),
670					share_context,
671					attrib_list.as_ptr(),
672				);
673
674				if context != NO_CONTEXT {
675					Ok(Context(context))
676				} else {
677					Err(self.get_error().unwrap())
678				}
679			}
680		}
681
682		/// Create a new EGL pixel buffer surface.
683		///
684		/// This will return a `BadParameter` error if `attrib_list` is not a valid
685		/// attributes list (if it does not terminate with `NONE`).
686		pub fn create_pbuffer_surface(&self, display: Display, config: Config, attrib_list: &[Int]) -> Result<Surface, Error> {
687			check_int_list(attrib_list)?;
688			unsafe {
689				let surface =
690					self.api.eglCreatePbufferSurface(display.as_ptr(), config.as_ptr(), attrib_list.as_ptr());
691
692				if surface != NO_SURFACE {
693					Ok(Surface(surface))
694				} else {
695					Err(self.get_error().unwrap())
696				}
697			}
698		}
699
700		/// Create a new EGL offscreen surface.
701		///
702		/// This will return a `BadParameter` error if `attrib_list` is not a valid
703		/// attributes list (if it does not terminate with `NONE`).
704		///
705		/// Since this function may raise undefined behavior if the display and native
706		/// pixmap do not belong to the same platform, it is inherently unsafe.
707		pub unsafe fn create_pixmap_surface(&self, display: Display, config: Config, pixmap: NativePixmapType, attrib_list: &[Int]) -> Result<Surface, Error> {
708			check_int_list(attrib_list)?;
709			let surface = self.api.eglCreatePixmapSurface(
710				display.as_ptr(),
711				config.as_ptr(),
712				pixmap,
713				attrib_list.as_ptr(),
714			);
715
716			if surface != NO_SURFACE {
717				Ok(Surface(surface))
718			} else {
719				Err(self.get_error().unwrap())
720			}
721		}
722
723		/// Create a new EGL window surface.
724		///
725		/// This will return a `BadParameter` error if `attrib_list` is not a valid
726		/// attributes list (if it does not terminate with `NONE`).
727		///
728		/// Since this function may raise undefined behavior if the display and native
729		/// window do not belong to the same platform, it is inherently unsafe.
730		pub unsafe fn create_window_surface(&self, display: Display, config: Config, window: NativeWindowType, attrib_list: Option<&[Int]>) -> Result<Surface, Error> {
731			let attrib_list = match attrib_list {
732				Some(attrib_list) => {
733					check_int_list(attrib_list)?;
734					attrib_list.as_ptr()
735				}
736				None => ptr::null(),
737			};
738
739			let surface =
740				self.api.eglCreateWindowSurface(display.as_ptr(), config.as_ptr(), window, attrib_list);
741
742			if surface != NO_SURFACE {
743				Ok(Surface(surface))
744			} else {
745				Err(self.get_error().unwrap())
746			}
747		}
748
749		/// Destroy an EGL rendering context.
750		pub fn destroy_context(&self, display: Display, ctx: Context) -> Result<(), Error> {
751			unsafe {
752				if self.api.eglDestroyContext(display.as_ptr(), ctx.as_ptr()) == TRUE {
753					Ok(())
754				} else {
755					Err(self.get_error().unwrap())
756				}
757			}
758		}
759
760		/// Destroy an EGL surface.
761		pub fn destroy_surface(&self, display: Display, surface: Surface) -> Result<(), Error> {
762			unsafe {
763				if self.api.eglDestroySurface(display.as_ptr(), surface.as_ptr()) == TRUE {
764					Ok(())
765				} else {
766					Err(self.get_error().unwrap())
767				}
768			}
769		}
770
771		/// Return information about an EGL frame buffer configuration.
772		pub fn get_config_attrib(&self, display: Display, config: Config, attribute: Int) -> Result<Int, Error> {
773			unsafe {
774				let mut value: Int = 0;
775				if self.api.eglGetConfigAttrib(display.as_ptr(), config.as_ptr(), attribute, &mut value) == TRUE
776				{
777					Ok(value)
778				} else {
779					Err(self.get_error().unwrap())
780				}
781			}
782		}
783
784		/// Return the number of all frame buffer configurations.
785		///
786		/// You can use it to setup the correct capacity for the configurations buffer in [`get_configs`](Self::get_configs).
787		///
788		/// ## Example
789		/// ```
790		/// # extern crate khronos_egl as egl;
791		/// # extern crate wayland_client;
792		/// # fn main() -> Result<(), egl::Error> {
793		/// # let egl = egl::Instance::new(egl::Static);
794		/// # let wayland_display = wayland_client::Display::connect_to_env().expect("unable to connect to the wayland server");
795		/// # let display = egl.get_display(wayland_display.get_display_ptr() as *mut std::ffi::c_void).unwrap();
796		/// # egl.initialize(display)?;
797		/// let mut configs = Vec::with_capacity(egl.get_config_count(display)?);
798		/// egl.get_configs(display, &mut configs);
799		/// assert!(configs.len() > 0);
800		/// # Ok(())
801		/// # }
802		/// ```
803		pub fn get_config_count(&self, display: Display) -> Result<usize, Error> {
804			unsafe {
805				let mut count = 0;
806
807				if self.api.eglGetConfigs(display.as_ptr(), std::ptr::null_mut(), 0, &mut count) == TRUE {
808					Ok(count as usize)
809				} else {
810					Err(self.get_error().unwrap())
811				}
812			}
813		}
814
815		/// Get the list of all EGL frame buffer configurations for a display.
816		///
817		/// The configurations are added to the `configs` buffer, up to the buffer's capacity.
818		/// You can use [`get_config_count`](Self::get_config_count) to get the total number of available frame buffer configurations,
819		/// and setup the buffer's capacity accordingly.
820		///
821		/// ## Example
822		/// ```
823		/// # extern crate khronos_egl as egl;
824		/// # extern crate wayland_client;
825		/// # fn main() -> Result<(), egl::Error> {
826		/// # let egl = egl::Instance::new(egl::Static);
827		/// # let wayland_display = wayland_client::Display::connect_to_env().expect("unable to connect to the wayland server");
828		/// # let display = egl.get_display(wayland_display.get_display_ptr() as *mut std::ffi::c_void).unwrap();
829		/// # egl.initialize(display)?;
830		/// let mut configs = Vec::with_capacity(egl.get_config_count(display)?);
831		/// egl.get_configs(display, &mut configs);
832		/// # Ok(())
833		/// # }
834		/// ```
835		pub fn get_configs(&self, display: Display, configs: &mut Vec<Config>) -> Result<(), Error> {
836			unsafe {
837				let capacity = configs.capacity();
838				let mut count = 0;
839
840				if self.api.eglGetConfigs(
841					display.as_ptr(),
842					configs.as_mut_ptr() as *mut EGLConfig,
843					capacity.try_into().unwrap(),
844					&mut count,
845				) == TRUE
846				{
847					configs.set_len(count as usize);
848					Ok(())
849				} else {
850					Err(self.get_error().unwrap())
851				}
852			}
853		}
854
855		/// Return the display for the current EGL rendering context.
856		pub fn get_current_display(&self) -> Option<Display> {
857			unsafe {
858				let display = self.api.eglGetCurrentDisplay();
859
860				if display != NO_DISPLAY {
861					Some(Display(display))
862				} else {
863					None
864				}
865			}
866		}
867
868		/// Return the read or draw surface for the current EGL rendering context.
869		pub fn get_current_surface(&self, readdraw: Int) -> Option<Surface> {
870			unsafe {
871				let surface = self.api.eglGetCurrentSurface(readdraw);
872
873				if surface != NO_SURFACE {
874					Some(Surface(surface))
875				} else {
876					None
877				}
878			}
879		}
880
881		/// Return an EGL display connection.
882		pub fn get_display(&self, display_id: NativeDisplayType) -> Option<Display> {
883			unsafe {
884				let display = self.api.eglGetDisplay(display_id);
885
886				if display != NO_DISPLAY {
887					Some(Display(display))
888				} else {
889					None
890				}
891			}
892		}
893
894		/// Return error information.
895		///
896		/// Return the error of the last called EGL function in the current thread, or
897		/// `None` if the error is set to `SUCCESS`.
898		///
899		/// Note that since a call to `eglGetError` sets the error to `SUCCESS`, and
900		/// since this function is automatically called by any wrapper function
901		/// returning a `Result` when necessary, this function may only return `None`
902		/// from the point of view of a user.
903		pub fn get_error(&self) -> Option<Error> {
904			unsafe {
905				let e = self.api.eglGetError();
906				if e == SUCCESS {
907					None
908				} else {
909					Some(e.try_into().unwrap())
910				}
911			}
912		}
913
914		/// Return a GL or an EGL extension function.
915		pub fn get_proc_address(&self, procname: &str) -> Option<extern "C" fn()> {
916			unsafe {
917				let string = CString::new(procname).unwrap();
918
919				let addr = self.api.eglGetProcAddress(string.as_ptr());
920				if !(addr as *const ()).is_null() {
921					Some(addr)
922				} else {
923					None
924				}
925			}
926		}
927
928		/// Initialize an EGL display connection.
929		pub fn initialize(&self, display: Display) -> Result<(Int, Int), Error> {
930			unsafe {
931				let mut major = 0;
932				let mut minor = 0;
933
934				if self.api.eglInitialize(display.as_ptr(), &mut major, &mut minor) == TRUE {
935					Ok((major, minor))
936				} else {
937					Err(self.get_error().unwrap())
938				}
939			}
940		}
941
942		/// Attach an EGL rendering context to EGL surfaces.
943		pub fn make_current(&self, display: Display, draw: Option<Surface>, read: Option<Surface>, ctx: Option<Context>) -> Result<(), Error> {
944			unsafe {
945				let draw = match draw {
946					Some(draw) => draw.as_ptr(),
947					None => NO_SURFACE,
948				};
949				let read = match read {
950					Some(read) => read.as_ptr(),
951					None => NO_SURFACE,
952				};
953				let ctx = match ctx {
954					Some(ctx) => ctx.as_ptr(),
955					None => NO_CONTEXT,
956				};
957
958				if self.api.eglMakeCurrent(display.as_ptr(), draw, read, ctx) == TRUE {
959					Ok(())
960				} else {
961					Err(self.get_error().unwrap())
962				}
963			}
964		}
965
966		/// Return EGL rendering context information.
967		pub fn query_context(&self, display: Display, ctx: Context, attribute: Int) -> Result<Int, Error> {
968			unsafe {
969				let mut value = 0;
970				if self.api.eglQueryContext(display.as_ptr(), ctx.as_ptr(), attribute, &mut value) == TRUE {
971					Ok(value)
972				} else {
973					Err(self.get_error().unwrap())
974				}
975			}
976		}
977
978		/// Return a string describing properties of the EGL client or of an EGL display
979		/// connection.
980		pub fn query_string(&self, display: Option<Display>, name: Int) -> Result<&'static CStr, Error> {
981			unsafe {
982				let display_ptr = match display {
983					Some(display) => display.as_ptr(),
984					None => NO_DISPLAY
985				};
986
987				let c_str = self.api.eglQueryString(display_ptr, name);
988
989				if !c_str.is_null() {
990					Ok(CStr::from_ptr(c_str))
991				} else {
992					Err(self.get_error().unwrap())
993				}
994			}
995		}
996
997		/// Return EGL surface information.
998		pub fn query_surface(&self, display: Display, surface: Surface, attribute: Int) -> Result<Int, Error> {
999			unsafe {
1000				let mut value = 0;
1001				if self.api.eglQuerySurface(display.as_ptr(), surface.as_ptr(), attribute, &mut value) == TRUE {
1002					Ok(value)
1003				} else {
1004					Err(self.get_error().unwrap())
1005				}
1006			}
1007		}
1008
1009		/// Post EGL surface color buffer to a native window.
1010		pub fn swap_buffers(&self, display: Display, surface: Surface) -> Result<(), Error> {
1011			unsafe {
1012				if self.api.eglSwapBuffers(display.as_ptr(), surface.as_ptr()) == TRUE {
1013					Ok(())
1014				} else {
1015					Err(self.get_error().unwrap())
1016				}
1017			}
1018		}
1019
1020		/// Terminate an EGL display connection.
1021		pub fn terminate(&self, display: Display) -> Result<(), Error> {
1022			unsafe {
1023				if self.api.eglTerminate(display.as_ptr()) == TRUE {
1024					Ok(())
1025				} else {
1026					Err(self.get_error().unwrap())
1027				}
1028			}
1029		}
1030
1031		/// Complete GL execution prior to subsequent native rendering calls.
1032		pub fn wait_gl(&self) -> Result<(), Error> {
1033			unsafe {
1034				if self.api.eglWaitGL() == TRUE {
1035					Ok(())
1036				} else {
1037					Err(self.get_error().unwrap())
1038				}
1039			}
1040		}
1041
1042		/// Complete native execution prior to subsequent GL rendering calls.
1043		pub fn wait_native(&self, engine: Int) -> Result<(), Error> {
1044			unsafe {
1045				if self.api.eglWaitNative(engine) == TRUE {
1046					Ok(())
1047				} else {
1048					Err(self.get_error().unwrap())
1049				}
1050			}
1051		}
1052	}
1053}
1054
1055#[cfg(feature = "1_0")]
1056pub use egl1_0::*;
1057
1058// ------------------------------------------------------------------------------------------------
1059// EGL 1.1
1060// ------------------------------------------------------------------------------------------------
1061
1062#[cfg(feature = "1_1")]
1063mod egl1_1 {
1064	use super::*;
1065
1066	pub const BACK_BUFFER: Int = 0x3084;
1067	pub const BIND_TO_TEXTURE_RGB: Int = 0x3039;
1068	pub const BIND_TO_TEXTURE_RGBA: Int = 0x303A;
1069	pub const CONTEXT_LOST: Int = 0x300E;
1070	pub const MIN_SWAP_INTERVAL: Int = 0x303B;
1071	pub const MAX_SWAP_INTERVAL: Int = 0x303C;
1072	pub const MIPMAP_TEXTURE: Int = 0x3082;
1073	pub const MIPMAP_LEVEL: Int = 0x3083;
1074	pub const NO_TEXTURE: Int = 0x305C;
1075	pub const TEXTURE_2D: Int = 0x305F;
1076	pub const TEXTURE_FORMAT: Int = 0x3080;
1077	pub const TEXTURE_RGB: Int = 0x305D;
1078	pub const TEXTURE_RGBA: Int = 0x305E;
1079	pub const TEXTURE_TARGET: Int = 0x3081;
1080
1081	impl<T: api::EGL1_1> Instance<T> {
1082		/// Defines a two-dimensional texture image.
1083		pub fn bind_tex_image(&self, display: Display, surface: Surface, buffer: Int) -> Result<(), Error> {
1084			unsafe {
1085				if self.api.eglBindTexImage(display.as_ptr(), surface.as_ptr(), buffer) == TRUE {
1086					Ok(())
1087				} else {
1088					Err(self.get_error().unwrap())
1089				}
1090			}
1091		}
1092
1093		///  Releases a color buffer that is being used as a texture.
1094		pub fn release_tex_image(&self, display: Display, surface: Surface, buffer: Int) -> Result<(), Error> {
1095			unsafe {
1096				if self.api.eglReleaseTexImage(display.as_ptr(), surface.as_ptr(), buffer) == TRUE {
1097					Ok(())
1098				} else {
1099					Err(self.get_error().unwrap())
1100				}
1101			}
1102		}
1103
1104		/// Set an EGL surface attribute.
1105		pub fn surface_attrib(&self, display: Display, surface: Surface, attribute: Int, value: Int) -> Result<(), Error> {
1106			unsafe {
1107				if self.api.eglSurfaceAttrib(display.as_ptr(), surface.as_ptr(), attribute, value) == TRUE {
1108					Ok(())
1109				} else {
1110					Err(self.get_error().unwrap())
1111				}
1112			}
1113		}
1114
1115		/// Specifies the minimum number of video frame periods per buffer swap for the
1116		/// window associated with the current context.
1117		pub fn swap_interval(&self, display: Display, interval: Int) -> Result<(), Error> {
1118			unsafe {
1119				if self.api.eglSwapInterval(display.as_ptr(), interval) == TRUE {
1120					Ok(())
1121				} else {
1122					Err(self.get_error().unwrap())
1123				}
1124			}
1125		}
1126	}
1127}
1128
1129#[cfg(feature = "1_1")]
1130pub use egl1_1::*;
1131
1132// ------------------------------------------------------------------------------------------------
1133// EGL 1.2
1134// ------------------------------------------------------------------------------------------------
1135
1136#[cfg(feature = "1_2")]
1137mod egl1_2 {
1138	use super::*;
1139
1140	pub type Enum = c_uint;
1141	pub type EGLClientBuffer = *mut c_void;
1142
1143	#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
1144	pub struct ClientBuffer(EGLClientBuffer);
1145
1146	impl ClientBuffer {
1147		#[inline]
1148		pub unsafe fn from_ptr(ptr: EGLClientBuffer) -> ClientBuffer {
1149			ClientBuffer(ptr)
1150		}
1151
1152		#[inline]
1153		pub fn as_ptr(&self) -> EGLClientBuffer {
1154			self.0
1155		}
1156	}
1157
1158	pub const ALPHA_FORMAT: Int = 0x3088;
1159	pub const ALPHA_FORMAT_NONPRE: Int = 0x308B;
1160	pub const ALPHA_FORMAT_PRE: Int = 0x308C;
1161	pub const ALPHA_MASK_SIZE: Int = 0x303E;
1162	pub const BUFFER_PRESERVED: Int = 0x3094;
1163	pub const BUFFER_DESTROYED: Int = 0x3095;
1164	pub const CLIENT_APIS: Int = 0x308D;
1165	pub const COLORSPACE: Int = 0x3087;
1166	pub const COLORSPACE_sRGB: Int = 0x3089;
1167	pub const COLORSPACE_LINEAR: Int = 0x308A;
1168	pub const COLOR_BUFFER_TYPE: Int = 0x303F;
1169	pub const CONTEXT_CLIENT_TYPE: Int = 0x3097;
1170	pub const DISPLAY_SCALING: Int = 10000;
1171	pub const HORIZONTAL_RESOLUTION: Int = 0x3090;
1172	pub const LUMINANCE_BUFFER: Int = 0x308F;
1173	pub const LUMINANCE_SIZE: Int = 0x303D;
1174	pub const OPENGL_ES_BIT: Int = 0x0001;
1175	pub const OPENVG_BIT: Int = 0x0002;
1176	pub const OPENGL_ES_API: Enum = 0x30A0;
1177	pub const OPENVG_API: Enum = 0x30A1;
1178	pub const OPENVG_IMAGE: Int = 0x3096;
1179	pub const PIXEL_ASPECT_RATIO: Int = 0x3092;
1180	pub const RENDERABLE_TYPE: Int = 0x3040;
1181	pub const RENDER_BUFFER: Int = 0x3086;
1182	pub const RGB_BUFFER: Int = 0x308E;
1183	pub const SINGLE_BUFFER: Int = 0x3085;
1184	pub const SWAP_BEHAVIOR: Int = 0x3093;
1185	pub const UNKNOWN: Int = -1;
1186	pub const VERTICAL_RESOLUTION: Int = 0x3091;
1187
1188	impl<T: api::EGL1_2> Instance<T> {
1189		/// Set the current rendering API.
1190		pub fn bind_api(&self, api: Enum) -> Result<(), Error> {
1191			unsafe {
1192				if self.api.eglBindAPI(api) == TRUE {
1193					Ok(())
1194				} else {
1195					Err(self.get_error().unwrap())
1196				}
1197			}
1198		}
1199
1200		/// Query the current rendering API.
1201		pub fn query_api(&self) -> Enum {
1202			unsafe { self.api.eglQueryAPI() }
1203		}
1204
1205		/// Create a new EGL pixel buffer surface bound to an OpenVG image.
1206		///
1207		/// This will return a `BadParameter` error if `attrib_list` is not a valid
1208		/// attributes list (if it does not terminate with `NONE`).
1209		pub fn create_pbuffer_from_client_buffer(&self, display: Display, buffer_type: Enum, buffer: ClientBuffer, config: Config, attrib_list: &[Int]) -> Result<Surface, Error> {
1210			check_int_list(attrib_list)?;
1211			unsafe {
1212				let surface = self.api.eglCreatePbufferFromClientBuffer(
1213					display.as_ptr(),
1214					buffer_type,
1215					buffer.as_ptr(),
1216					config.as_ptr(),
1217					attrib_list.as_ptr(),
1218				);
1219
1220				if surface != NO_SURFACE {
1221					Ok(Surface(surface))
1222				} else {
1223					Err(self.get_error().unwrap())
1224				}
1225			}
1226		}
1227
1228		/// Release EGL per-thread state.
1229		pub fn release_thread(&self) -> Result<(), Error> {
1230			unsafe {
1231				if self.api.eglReleaseThread() == TRUE {
1232					Ok(())
1233				} else {
1234					Err(self.get_error().unwrap())
1235				}
1236			}
1237		}
1238
1239		/// Complete client API execution prior to subsequent native rendering calls.
1240		pub fn wait_client(&self) -> Result<(), Error> {
1241			unsafe {
1242				if self.api.eglWaitClient() == TRUE {
1243					Ok(())
1244				} else {
1245					Err(self.get_error().unwrap())
1246				}
1247			}
1248		}
1249	}
1250}
1251
1252#[cfg(feature = "1_2")]
1253pub use egl1_2::*;
1254
1255// ------------------------------------------------------------------------------------------------
1256// EGL 1.3
1257// ------------------------------------------------------------------------------------------------
1258
1259#[cfg(feature = "1_3")]
1260mod egl1_3 {
1261	use super::*;
1262
1263	pub const CONFORMANT: Int = 0x3042;
1264	pub const CONTEXT_CLIENT_VERSION: Int = 0x3098;
1265	pub const MATCH_NATIVE_PIXMAP: Int = 0x3041;
1266	pub const OPENGL_ES2_BIT: Int = 0x0004;
1267	pub const VG_ALPHA_FORMAT: Int = 0x3088;
1268	pub const VG_ALPHA_FORMAT_NONPRE: Int = 0x308B;
1269	pub const VG_ALPHA_FORMAT_PRE: Int = 0x308C;
1270	pub const VG_ALPHA_FORMAT_PRE_BIT: Int = 0x0040;
1271	pub const VG_COLORSPACE: Int = 0x3087;
1272	pub const VG_COLORSPACE_sRGB: Int = 0x3089;
1273	pub const VG_COLORSPACE_LINEAR: Int = 0x308A;
1274	pub const VG_COLORSPACE_LINEAR_BIT: Int = 0x0020;
1275}
1276
1277#[cfg(feature = "1_3")]
1278pub use egl1_3::*;
1279
1280// ------------------------------------------------------------------------------------------------
1281// EGL 1.4
1282// ------------------------------------------------------------------------------------------------
1283
1284#[cfg(feature = "1_4")]
1285mod egl1_4 {
1286	use super::*;
1287
1288	pub const DEFAULT_DISPLAY: NativeDisplayType = 0 as NativeDisplayType;
1289	pub const MULTISAMPLE_RESOLVE_BOX_BIT: Int = 0x0200;
1290	pub const MULTISAMPLE_RESOLVE: Int = 0x3099;
1291	pub const MULTISAMPLE_RESOLVE_DEFAULT: Int = 0x309A;
1292	pub const MULTISAMPLE_RESOLVE_BOX: Int = 0x309B;
1293	pub const OPENGL_API: Enum = 0x30A2;
1294	pub const OPENGL_BIT: Int = 0x0008;
1295	pub const SWAP_BEHAVIOR_PRESERVED_BIT: Int = 0x0400;
1296
1297	impl<T: api::EGL1_4> Instance<T> {
1298		/// Return the current EGL rendering context.
1299		pub fn get_current_context(&self) -> Option<Context> {
1300			unsafe {
1301				let context = self.api.eglGetCurrentContext();
1302
1303				if context != NO_CONTEXT {
1304					Some(Context(context))
1305				} else {
1306					None
1307				}
1308			}
1309		}
1310	}
1311}
1312
1313#[cfg(feature = "1_4")]
1314pub use egl1_4::*;
1315
1316// ------------------------------------------------------------------------------------------------
1317// EGL 1.5
1318// ------------------------------------------------------------------------------------------------
1319
1320#[cfg(feature = "1_5")]
1321mod egl1_5 {
1322	use super::*;
1323
1324	pub type Time = u64;
1325	pub type EGLSync = *mut c_void;
1326	pub type EGLImage = *mut c_void;
1327
1328	#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
1329	pub struct Sync(EGLSync);
1330
1331	impl Sync {
1332		#[inline]
1333		pub unsafe fn from_ptr(ptr: EGLSync) -> Sync {
1334			Sync(ptr)
1335		}
1336
1337		#[inline]
1338		pub fn as_ptr(&self) -> EGLSync {
1339			self.0
1340		}
1341	}
1342
1343	#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
1344	pub struct Image(EGLImage);
1345
1346	impl Image {
1347		#[inline]
1348		pub unsafe fn from_ptr(ptr: EGLImage) -> Image {
1349			Image(ptr)
1350		}
1351
1352		#[inline]
1353		pub fn as_ptr(&self) -> EGLImage {
1354			self.0
1355		}
1356	}
1357
1358	pub const CONTEXT_MAJOR_VERSION: Int = 0x3098;
1359	pub const CONTEXT_MINOR_VERSION: Int = 0x30FB;
1360	pub const CONTEXT_OPENGL_PROFILE_MASK: Int = 0x30FD;
1361	pub const CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY: Int = 0x31BD;
1362	pub const NO_RESET_NOTIFICATION: Int = 0x31BE;
1363	pub const LOSE_CONTEXT_ON_RESET: Int = 0x31BF;
1364	pub const CONTEXT_OPENGL_CORE_PROFILE_BIT: Int = 0x00000001;
1365	pub const CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT: Int = 0x00000002;
1366	pub const CONTEXT_OPENGL_DEBUG: Int = 0x31B0;
1367	pub const CONTEXT_OPENGL_FORWARD_COMPATIBLE: Int = 0x31B1;
1368	pub const CONTEXT_OPENGL_ROBUST_ACCESS: Int = 0x31B2;
1369	pub const OPENGL_ES3_BIT: Int = 0x00000040;
1370	pub const CL_EVENT_HANDLE: Int = 0x309C;
1371	pub const SYNC_CL_EVENT: Int = 0x30FE;
1372	pub const SYNC_CL_EVENT_COMPLETE: Int = 0x30FF;
1373	pub const SYNC_PRIOR_COMMANDS_COMPLETE: Int = 0x30F0;
1374	pub const SYNC_TYPE: Int = 0x30F7;
1375	pub const SYNC_STATUS: Int = 0x30F1;
1376	pub const SYNC_CONDITION: Int = 0x30F8;
1377	pub const SIGNALED: Int = 0x30F2;
1378	pub const UNSIGNALED: Int = 0x30F3;
1379	pub const SYNC_FLUSH_COMMANDS_BIT: Int = 0x0001;
1380	pub const FOREVER: u64 = 0xFFFFFFFFFFFFFFFFu64;
1381	pub const TIMEOUT_EXPIRED: Int = 0x30F5;
1382	pub const CONDITION_SATISFIED: Int = 0x30F6;
1383	pub const NO_SYNC: EGLSync = 0 as EGLSync;
1384	pub const SYNC_FENCE: Int = 0x30F9;
1385	pub const GL_COLORSPACE: Int = 0x309D;
1386	pub const GL_COLORSPACE_SRGB: Int = 0x3089;
1387	pub const GL_COLORSPACE_LINEAR: Int = 0x308A;
1388	pub const GL_RENDERBUFFER: Int = 0x30B9;
1389	pub const GL_TEXTURE_2D: Int = 0x30B1;
1390	pub const GL_TEXTURE_LEVEL: Int = 0x30BC;
1391	pub const GL_TEXTURE_3D: Int = 0x30B2;
1392	pub const GL_TEXTURE_ZOFFSET: Int = 0x30BD;
1393	pub const GL_TEXTURE_CUBE_MAP_POSITIVE_X: Int = 0x30B3;
1394	pub const GL_TEXTURE_CUBE_MAP_NEGATIVE_X: Int = 0x30B4;
1395	pub const GL_TEXTURE_CUBE_MAP_POSITIVE_Y: Int = 0x30B5;
1396	pub const GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: Int = 0x30B6;
1397	pub const GL_TEXTURE_CUBE_MAP_POSITIVE_Z: Int = 0x30B7;
1398	pub const GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: Int = 0x30B8;
1399	pub const IMAGE_PRESERVED: Int = 0x30D2;
1400	pub const NO_IMAGE: EGLImage = 0 as EGLImage;
1401
1402	impl<T: api::EGL1_5> Instance<T> {
1403		/// Create a new EGL sync object.
1404		///
1405		/// Note that the constant `ATTRIB_NONE` which has the type `Attrib` can be used
1406		/// instead of `NONE` to terminate the attribute list.
1407		///
1408		/// This will return a `BadParameter` error if `attrib_list` is not a valid
1409		/// attributes list (if it does not terminate with `ATTRIB_NONE`).
1410		///
1411		/// This function is unsafe: when creating an OpenCL Event Sync Object, passing an invalid event
1412		/// handle in `attrib_list` may result in undefined behavior up to and including program
1413		/// termination.
1414		pub unsafe fn create_sync(&self, display: Display, ty: Enum, attrib_list: &[Attrib]) -> Result<Sync, Error> {
1415			check_attrib_list(attrib_list)?;
1416			let sync = self.api.eglCreateSync(display.as_ptr(), ty, attrib_list.as_ptr());
1417			if sync != NO_SYNC {
1418				Ok(Sync(sync))
1419			} else {
1420				Err(self.get_error().unwrap())
1421			}
1422		}
1423
1424		/// Destroy a sync object.
1425		///
1426		/// This function is unsafe: if display does not match the display passed to eglCreateSync when
1427		/// sync was created, the behaviour is undefined.
1428		pub unsafe fn destroy_sync(&self, display: Display, sync: Sync) -> Result<(), Error> {
1429			if self.api.eglDestroySync(display.as_ptr(), sync.as_ptr()) == TRUE {
1430				Ok(())
1431			} else {
1432				Err(self.get_error().unwrap())
1433			}
1434		}
1435
1436		/// Wait in the client for a sync object to be signalled.
1437		///
1438		/// This function is unsafe: if `display` does not match the [`Display`] passed to [`create_sync`](Self::create_sync)
1439		/// when `sync` was created, the behaviour is undefined.
1440		pub unsafe fn client_wait_sync(&self, display: Display, sync: Sync, flags: Int, timeout: Time) -> Result<Int, Error> {
1441			let status = self.api.eglClientWaitSync(display.as_ptr(), sync.as_ptr(), flags, timeout);
1442			if status != FALSE as Int {
1443				Ok(status)
1444			} else {
1445				Err(self.get_error().unwrap())
1446			}
1447		}
1448
1449		/// Return an attribute of a sync object.
1450		///
1451		/// This function is unsafe: If `display` does not match the [`Display`] passed to [`create_sync`](Self::create_sync)
1452		/// when `sync` was created, behaviour is undefined.
1453		pub unsafe fn get_sync_attrib(&self, display: Display, sync: Sync, attribute: Int) -> Result<Attrib, Error> {
1454			let mut value = 0;
1455			if self.api.eglGetSyncAttrib(
1456				display.as_ptr(),
1457				sync.as_ptr(),
1458				attribute,
1459				&mut value as *mut Attrib,
1460			) == TRUE
1461			{
1462				Ok(value)
1463			} else {
1464				Err(self.get_error().unwrap())
1465			}
1466		}
1467
1468		/// Create a new Image object.
1469		///
1470		/// Note that the constant `ATTRIB_NONE` which has the type `Attrib` can be used
1471		/// instead of `NONE` to terminate the attribute list.
1472		///
1473		/// This will return a `BadParameter` error if `attrib_list` is not a valid
1474		/// attributes list (if it does not terminate with `ATTRIB_NONE`).
1475		pub fn create_image(&self, display: Display, ctx: Context, target: Enum, buffer: ClientBuffer, attrib_list: &[Attrib]) -> Result<Image, Error> {
1476			check_attrib_list(attrib_list)?;
1477			unsafe {
1478				let image = self.api.eglCreateImage(
1479					display.as_ptr(),
1480					ctx.as_ptr(),
1481					target,
1482					buffer.as_ptr(),
1483					attrib_list.as_ptr(),
1484				);
1485				if image != NO_IMAGE {
1486					Ok(Image(image))
1487				} else {
1488					Err(self.get_error().unwrap())
1489				}
1490			}
1491		}
1492
1493		/// Destroy an Image object.
1494		pub fn destroy_image(&self, display: Display, image: Image) -> Result<(), Error> {
1495			unsafe {
1496				if self.api.eglDestroyImage(display.as_ptr(), image.as_ptr()) == TRUE {
1497					Ok(())
1498				} else {
1499					Err(self.get_error().unwrap())
1500				}
1501			}
1502		}
1503
1504		/// Return an EGL display connection.
1505		///
1506		/// Note that the constant `ATTRIB_NONE` which has the type `Attrib` can be used
1507		/// instead of `NONE` to terminate the attribute list.
1508		///
1509		/// This will return a `BadParameter` error if `attrib_list` is not a valid
1510		/// attributes list (if it does not terminate with `ATTRIB_NONE`).
1511		pub fn get_platform_display(&self, platform: Enum, native_display: *mut c_void, attrib_list: &[Attrib]) -> Result<Display, Error> {
1512			check_attrib_list(attrib_list)?;
1513			unsafe {
1514				let display = self.api.eglGetPlatformDisplay(platform, native_display, attrib_list.as_ptr());
1515				if display != NO_DISPLAY {
1516					Ok(Display(display))
1517				} else {
1518					Err(self.get_error().unwrap())
1519				}
1520			}
1521		}
1522
1523		/// Create a new EGL on-screen rendering surface.
1524		///
1525		/// Note that the constant `ATTRIB_NONE` which has the type `Attrib` can be used
1526		/// instead of `NONE` to terminate the attribute list.
1527		///
1528		/// This will return a `BadParameter` error if `attrib_list` is not a valid
1529		/// attributes list (if it does not terminate with `ATTRIB_NONE`).
1530		pub fn create_platform_window_surface(&self, display: Display, config: Config, native_window: *mut c_void, attrib_list: &[Attrib]) -> Result<Surface, Error> {
1531			check_attrib_list(attrib_list)?;
1532			unsafe {
1533				let surface = self.api.eglCreatePlatformWindowSurface(
1534					display.as_ptr(),
1535					config.as_ptr(),
1536					native_window,
1537					attrib_list.as_ptr(),
1538				);
1539				if surface != NO_SURFACE {
1540					Ok(Surface(surface))
1541				} else {
1542					Err(self.get_error().unwrap())
1543				}
1544			}
1545		}
1546
1547		/// Create a new EGL offscreen surface.
1548		///
1549		/// Note that the constant `ATTRIB_NONE` which has the type `Attrib` can be used
1550		/// instead of `NONE` to terminate the attribute list.
1551		///
1552		/// This will return a `BadParameter` error if `attrib_list` is not a valid
1553		/// attributes list (if it does not terminate with `ATTRIB_NONE`).
1554		pub fn create_platform_pixmap_surface(&self, display: Display, config: Config, native_pixmap: *mut c_void, attrib_list: &[Attrib]) -> Result<Surface, Error> {
1555			check_attrib_list(attrib_list)?;
1556			unsafe {
1557				let surface = self.api.eglCreatePlatformPixmapSurface(
1558					display.as_ptr(),
1559					config.as_ptr(),
1560					native_pixmap,
1561					attrib_list.as_ptr(),
1562				);
1563				if surface != NO_SURFACE {
1564					Ok(Surface(surface))
1565				} else {
1566					Err(self.get_error().unwrap())
1567				}
1568			}
1569		}
1570
1571		/// Wait in the server for a sync object to be signalled.
1572		///
1573		/// This function is unsafe: if `display` does not match the [`Display`] passed to [`create_sync`](Self::create_sync)
1574		/// when `sync` was created, the behavior is undefined.
1575		pub fn wait_sync(&self, display: Display, sync: Sync, flags: Int) -> Result<(), Error> {
1576			unsafe {
1577				if self.api.eglWaitSync(display.as_ptr(), sync.as_ptr(), flags) == TRUE {
1578					Ok(())
1579				} else {
1580					Err(self.get_error().unwrap())
1581				}
1582			}
1583		}
1584	}
1585}
1586
1587#[cfg(feature = "1_5")]
1588pub use egl1_5::*;
1589
1590// -------------------------------------------------------------------------------------------------
1591// FFI
1592// -------------------------------------------------------------------------------------------------
1593
1594macro_rules! api {
1595	($($id:ident : $version:literal { $(fn $name:ident ($($arg:ident : $atype:ty ),* ) -> $rtype:ty ;)* }),*) => {
1596		#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
1597		pub enum Version {
1598			$(
1599				#[cfg(feature=$version)]
1600				$id,
1601			)*
1602		}
1603
1604		impl std::fmt::Display for Version {
1605			fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1606				match self {
1607					$(
1608						#[cfg(feature=$version)]
1609						Version::$id => write!(f, $version),
1610					)*
1611				}
1612			}
1613		}
1614
1615		pub mod api {
1616			use super::*;
1617
1618			api!(@api_traits () () $($id : $version { $(fn $name ($($arg : $atype ),* ) -> $rtype ;)* })*);
1619		}
1620
1621		#[cfg(feature="static")]
1622		mod ffi {
1623			use libc::{c_char, c_void};
1624
1625			use super::{
1626				Attrib, Boolean, EGLClientBuffer, EGLConfig, EGLContext, EGLDisplay, EGLImage, EGLSurface,
1627				EGLSync, Enum, Int, NativeDisplayType, NativePixmapType, NativeWindowType, Time,
1628			};
1629
1630			$(
1631				extern "C" {
1632					$(
1633						#[cfg(feature=$version)]
1634						pub fn $name ($($arg : $atype ),* ) -> $rtype ;
1635					)*
1636				}
1637			)*
1638		}
1639
1640		#[cfg(feature="static")]
1641		/// Static EGL API interface.
1642		///
1643		/// This type is only available when the `static` feature is enabled,
1644		/// by statically linking the EGL library at compile time.
1645		#[derive(Copy, Clone, Debug)]
1646		pub struct Static;
1647
1648		#[cfg(feature="static")]
1649		impl Api for Static {
1650			#[inline(always)]
1651			fn version(&self) -> Version {
1652				LATEST
1653			}
1654		}
1655
1656		#[cfg(feature="static")]
1657		pub static API: Instance<Static> = Instance::new(Static);
1658
1659		#[cfg(feature="dynamic")]
1660		extern crate libloading;
1661
1662		api!(@dynamic_struct $($id : $version { $(fn $name ($($arg : $atype ),* ) -> $rtype ;)* })*);
1663		api!(@api_types () $($id : $version { $(fn $name ($($arg : $atype ),* ) -> $rtype ;)* })*);
1664	};
1665	(@dynamic_struct $($id:ident : $version:literal { $(fn $name:ident ($($arg:ident : $atype:ty ),* ) -> $rtype:ty ;)* })*) => {
1666		#[cfg(feature="dynamic")]
1667		#[derive(Debug)]
1668		pub enum LoadError<L> {
1669			/// Something wrong happend while loading the library.
1670			Library(L),
1671
1672			/// The provided version does not meet the requirements.
1673			InvalidVersion {
1674				provided: Version,
1675				required: Version
1676			}
1677		}
1678
1679		#[cfg(feature="dynamic")]
1680		impl<L: std::error::Error + 'static> std::error::Error for LoadError<L> {
1681			fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
1682				match self {
1683					LoadError::Library(l) => Some(l),
1684					_ => None
1685				}
1686			}
1687		}
1688
1689		#[cfg(feature="dynamic")]
1690		impl<L: std::fmt::Display> std::fmt::Display for LoadError<L> {
1691			fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1692				match self {
1693					LoadError::Library(l) => write!(f, "Load error: {}", l),
1694					LoadError::InvalidVersion { provided, required } => write!(f, "Invalid EGL API version (required {}, provided {})", required, provided)
1695				}
1696			}
1697		}
1698
1699		#[cfg(feature="dynamic")]
1700		struct RawDynamic<L> {
1701			lib: L,
1702			version: Version,
1703			$(
1704				$(
1705					#[cfg(feature=$version)]
1706					$name : std::mem::MaybeUninit<unsafe extern "C" fn($($atype ),*) -> $rtype>,
1707				)*
1708			)*
1709		}
1710
1711		#[cfg(feature="dynamic")]
1712		impl<L> RawDynamic<L> {
1713			#[inline(always)]
1714			/// Returns the underlying EGL library.
1715			pub fn library(&self) -> &L {
1716				&self.lib
1717			}
1718
1719			#[inline(always)]
1720			/// Returns the EGL version.
1721			pub fn version(&self) -> Version {
1722				self.version
1723			}
1724
1725			#[inline(always)]
1726			/// Sets the EGL version.
1727			pub unsafe fn set_version(&mut self, version: Version) {
1728				self.version = version
1729			}
1730
1731			/// Wraps the given library but does not load the symbols.
1732			pub unsafe fn unloaded(lib: L, version: Version) -> Self {
1733				RawDynamic {
1734					lib,
1735					version,
1736					$(
1737						$(
1738							#[cfg(feature=$version)]
1739							$name : std::mem::MaybeUninit::uninit(),
1740						)*
1741					)*
1742				}
1743			}
1744		}
1745
1746		#[cfg(feature="dynamic")]
1747		/// Dynamic EGL API interface.
1748		///
1749		/// The first type parameter is the type of the underlying library handle.
1750		/// The second `Dynamic` type parameter gives the EGL API version provided by the library.
1751		///
1752		/// This type is only available when the `dynamic` feature is enabled.
1753		/// In most cases, you may prefer to directly use the `DynamicInstance` type.
1754		pub struct Dynamic<L, A> {
1755			raw: RawDynamic<L>,
1756			_api_version: std::marker::PhantomData<A>
1757		}
1758
1759		#[cfg(feature="dynamic")]
1760		impl<L, A> Dynamic<L, A> {
1761			#[inline(always)]
1762			/// Return the underlying EGL library.
1763			pub fn library(&self) -> &L {
1764				self.raw.library()
1765			}
1766
1767			/// Returns the provided EGL version.
1768			pub fn version(&self) -> Version {
1769				self.raw.version()
1770			}
1771
1772			/// Wraps the given library but does not load the symbols.
1773			pub(crate) unsafe fn unloaded(lib: L, version: Version) -> Self {
1774				Dynamic {
1775					raw: RawDynamic::unloaded(lib, version),
1776					_api_version: std::marker::PhantomData
1777				}
1778			}
1779		}
1780
1781		#[cfg(feature="dynamic")]
1782		impl<L, A> Api for Dynamic<L, A> {
1783			/// Returns the provided EGL version.
1784			#[inline(always)]
1785			fn version(&self) -> Version {
1786				self.version()
1787			}
1788		}
1789
1790		#[cfg(feature="dynamic")]
1791		#[cfg(feature="1_0")]
1792		impl<L: std::borrow::Borrow<libloading::Library>> Dynamic<L, EGL1_0> {
1793			#[inline]
1794			/// Load the EGL API symbols from the given library.
1795			///
1796			/// This will load the most recent API provided by the library,
1797			/// which is at least EGL 1.0.
1798			/// You can check what version has actually been loaded using [`Dynamic::version`],
1799			/// and/or convert to a more recent version using [`try_into`](TryInto::try_into).
1800			///
1801			/// ## Safety
1802			/// This is fundamentally unsafe since there are no guaranties the input library complies to the EGL API.
1803			pub unsafe fn load_from(lib: L) -> Result<Dynamic<L, EGL1_0>, libloading::Error> {
1804				let mut result = Dynamic::unloaded(lib, Version::EGL1_0);
1805
1806				$(
1807					match $id::load_from(&mut result.raw) {
1808						Ok(()) => result.raw.set_version(Version::$id),
1809						Err(libloading::Error::DlSymUnknown) => {
1810							if Version::$id == Version::EGL1_0 {
1811								return Err(libloading::Error::DlSymUnknown) // we require at least EGL 1.0.
1812							} else {
1813								return Ok(result)
1814							}
1815						},
1816						Err(libloading::Error::DlSym { desc }) => {
1817							if Version::$id == Version::EGL1_0 {
1818								return Err(libloading::Error::DlSym { desc }) // we require at least EGL 1.0.
1819							} else {
1820								return Ok(result)
1821							}
1822						},
1823						Err(e) => return Err(e)
1824					}
1825				)*
1826
1827				Ok(result)
1828			}
1829		}
1830
1831		#[cfg(feature="dynamic")]
1832		#[cfg(feature="1_0")]
1833		impl<L: std::borrow::Borrow<libloading::Library>> Instance<Dynamic<L, EGL1_0>> {
1834			#[inline(always)]
1835			/// Create an EGL instance using the symbols provided by the given library.
1836			///
1837			/// The most recent version of EGL provided by the given library is loaded.
1838			/// You can check what version has actually been loaded using [`Instance::version`],
1839			/// and/or convert to a more recent version using [`try_into`](TryInto::try_into).
1840			///
1841			/// ## Safety
1842			/// This is fundamentally unsafe since there are no guaranties the input library complies to the EGL API.
1843			pub unsafe fn load_from(lib: L) -> Result<Instance<Dynamic<L, EGL1_0>>, libloading::Error> {
1844				Ok(Instance::new(Dynamic::<L, EGL1_0>::load_from(lib)?))
1845			}
1846		}
1847
1848		#[cfg(feature="dynamic")]
1849		impl<L, V> Instance<Dynamic<L, V>> {
1850			/// Cast the API.
1851			#[inline(always)]
1852			pub fn downcast<W>(&self) -> &Instance<Dynamic<L, W>> where Instance<Dynamic<L, V>>: Downcast<Instance<Dynamic<L, W>>> {
1853				Downcast::downcast(self)
1854			}
1855
1856			/// Cast the API.
1857			#[inline(always)]
1858			pub fn upcast<W>(&self) -> Option<&Instance<Dynamic<L, W>>> where Instance<Dynamic<L, V>>: Upcast<Instance<Dynamic<L, W>>> {
1859				Upcast::upcast(self)
1860			}
1861		}
1862
1863		#[cfg(feature="dynamic")]
1864		unsafe impl<L: std::borrow::Borrow<libloading::Library> + Send, A: Send> Send for Dynamic<L, A> {}
1865
1866		#[cfg(feature="dynamic")]
1867		unsafe impl<L: std::borrow::Borrow<libloading::Library> + std::marker::Sync, A: std::marker::Sync> std::marker::Sync for Dynamic<L, A> {}
1868
1869		#[cfg(feature="dynamic")]
1870		impl<L: std::borrow::Borrow<libloading::Library> + fmt::Debug, A> fmt::Debug for Dynamic<L, A> {
1871			fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1872				write!(f, "Dynamic({:?})", self.library())
1873			}
1874		}
1875	};
1876	(@api_traits ( ) ( ) $id:ident : $version:literal { $(fn $name:ident ($($arg:ident : $atype:ty ),* ) -> $rtype:ty ;)* } $($t_id:ident : $t_version:literal { $(fn $t_name:ident ($($t_arg:ident : $t_atype:ty ),* ) -> $t_rtype:ty ;)* })*) => {
1877		api!(@api_trait ( ) ( ) $id : $version { $(fn $name ($($arg : $atype ),* ) -> $rtype ;)* });
1878		api!(@api_traits ( $id : $version ) ( : $id ) $($t_id : $t_version { $(fn $t_name ($($t_arg : $t_atype ),* ) -> $t_rtype ;)* })*);
1879	};
1880	(@api_traits ( $($pred:ident : $p_version:literal)+ ) ( $($deps:tt)+ ) $id:ident : $version:literal { $(fn $name:ident ($($arg:ident : $atype:ty ),* ) -> $rtype:ty ;)* } $($t_id:ident : $t_version:literal { $(fn $t_name:ident ($($t_arg:ident : $t_atype:ty ),* ) -> $t_rtype:ty ;)* })*) => {
1881		api!(@api_trait ( $($pred : $p_version)* ) ( $($deps)* ) $id : $version { $(fn $name ($($arg : $atype ),* ) -> $rtype ;)* });
1882		api!(@api_traits ( $($pred : $version)* $id : $version ) ( $($deps)* + $id ) $($t_id : $t_version { $(fn $t_name ($($t_arg : $t_atype ),* ) -> $t_rtype ;)* })*);
1883	};
1884	(@api_traits ( $($pred:ident : $p_version:literal)* ) ( $($deps:tt)* )) => {
1885		// nothing
1886	};
1887	(@api_trait ( $($pred:ident : $p_version:literal)* ) ( $($deps:tt)* ) $id:ident : $version:literal { $(fn $name:ident ($($arg:ident : $atype:ty ),* ) -> $rtype:ty ;)* }) => {
1888		/// EGL API interface.
1889		///
1890		/// An implementation of this trait can be used to create an [`Instance`].
1891		///
1892		/// This crate provides two implemntation of this trait:
1893		///  - [`Static`] which is available with the `static` feature enabled,
1894		///    defined by statically linking to the EGL library at compile time.
1895		///  - [`Dynamic`] which is available with the `dynamic` feature enabled,
1896		///    defined by dynamically linking to the EGL library at runtime.
1897		///    In this case, you may prefer to directly use the `DynamicInstance` type.
1898		#[cfg(feature=$version)]
1899		pub unsafe trait $id $($deps)* {
1900			$(
1901				unsafe fn $name (&self, $($arg : $atype ),* ) -> $rtype ;
1902			)*
1903		}
1904	};
1905	(@api_types ( ) $id:ident : $version:literal { $(fn $name:ident ($($arg:ident : $atype:ty ),* ) -> $rtype:ty ;)* } $($t_id:ident : $t_version:literal { $(fn $t_name:ident ($($t_arg:ident : $t_atype:ty ),* ) -> $t_rtype:ty ;)* })*) => {
1906		#[cfg(feature="dynamic")]
1907		$(
1908			#[cfg(not(feature=$t_version))]
1909		)*
1910		#[cfg(feature=$version)]
1911		/// Latest available EGL version.
1912		pub type Latest = $id;
1913
1914		$(
1915			#[cfg(not(feature=$t_version))]
1916		)*
1917		#[cfg(feature=$version)]
1918		/// Latest available EGL version.
1919		pub const LATEST: Version = Version::$id;
1920
1921		api!(@api_type ( ) $id : $version { $(fn $name ($($arg : $atype ),* ) -> $rtype ;)* });
1922		api!(@api_types ( $id : $version { $(fn $name ($($arg : $atype ),* ) -> $rtype ;)* } ) $($t_id : $t_version { $(fn $t_name ($($t_arg : $t_atype ),* ) -> $t_rtype ;)* })*);
1923	};
1924	(@api_types ( $($pred:ident : $p_version:literal { $(fn $p_name:ident ($($p_arg:ident : $p_atype:ty ),* ) -> $p_rtype:ty ;)* })+ ) $id:ident : $version:literal { $(fn $name:ident ($($arg:ident : $atype:ty ),* ) -> $rtype:ty ;)* } $($t_id:ident : $t_version:literal { $(fn $t_name:ident ($($t_arg:ident : $t_atype:ty ),* ) -> $t_rtype:ty ;)* })*) => {
1925		#[cfg(feature="dynamic")]
1926		$(
1927			#[cfg(not(feature=$t_version))]
1928		)*
1929		#[cfg(feature=$version)]
1930		/// Latest available EGL version.
1931		pub type Latest = $id;
1932
1933		$(
1934			#[cfg(not(feature=$t_version))]
1935		)*
1936		#[cfg(feature=$version)]
1937		/// Latest available EGL version.
1938		pub const LATEST: Version = Version::$id;
1939
1940		api!(@api_type ( $($pred : $p_version { $(fn $p_name ($($p_arg : $p_atype ),* ) -> $p_rtype ;)* })* ) $id : $version { $(fn $name ($($arg : $atype ),* ) -> $rtype ;)* });
1941		api!(@api_types ( $($pred : $p_version { $(fn $p_name ($($p_arg : $p_atype ),* ) -> $p_rtype ;)* })* $id : $version { $(fn $name ($($arg : $atype ),* ) -> $rtype ;)* } ) $($t_id : $t_version { $(fn $t_name ($($t_arg : $t_atype ),* ) -> $t_rtype ;)* })*);
1942	};
1943	(@api_types ( $($pred:ident : $p_version:literal { $(fn $p_name:ident ($($p_arg:ident : $p_atype:ty ),* ) -> $p_rtype:ty ;)* })+ ) ) => {
1944		#[cfg(feature="dynamic")]
1945		#[cfg(feature="1_0")]
1946		/// Alias for dynamically linked instances with the latest handled version of EGL.
1947		pub type DynamicInstance<V = Latest> = Instance<Dynamic<libloading::Library, V>>;
1948
1949		#[cfg(feature="dynamic")]
1950		#[cfg(feature="1_0")]
1951		impl DynamicInstance<EGL1_0> {
1952			#[inline(always)]
1953			/// Create an EGL instance by finding and loading a dynamic library with the given filename.
1954			///
1955			/// See [`Library::new`](libloading::Library::new)
1956			/// for more details on how the `filename` argument is used.
1957			///
1958			/// On Linux plateforms, the library is loaded with the `RTLD_NODELETE` flag.
1959			/// See [#14](https://github.com/timothee-haudebourg/khronos-egl/issues/14) for more details.
1960			///
1961			/// ## Safety
1962			/// This is fundamentally unsafe since there are no guaranties the input library complies to the EGL API.
1963			pub unsafe fn load_from_filename<P: AsRef<std::ffi::OsStr>>(filename: P) -> Result<DynamicInstance<EGL1_0>, libloading::Error> {
1964				#[cfg(target_os = "linux")]
1965				let lib: libloading::Library = {
1966					// On Linux, load library with `RTLD_NOW | RTLD_NODELETE` to fix a SIGSEGV
1967					// See https://github.com/timothee-haudebourg/khronos-egl/issues/14 for more details.
1968					libloading::os::unix::Library::open(Some(filename), 0x2 | 0x1000)?.into()
1969				};
1970				#[cfg(not(target_os = "linux"))]
1971				let lib = libloading::Library::new(filename)?;
1972				Self::load_from(lib)
1973			}
1974
1975			#[inline(always)]
1976			/// Create an EGL instance by finding and loading the `libEGL.so.1` or `libEGL.so` library.
1977			///
1978			/// This is equivalent to `DynamicInstance::load_from_filename("libEGL.so.1")`.
1979			///
1980			/// ## Safety
1981			/// This is fundamentally unsafe since there are no guaranties the found library complies to the EGL API.
1982			pub unsafe fn load() -> Result<DynamicInstance<EGL1_0>, libloading::Error> {
1983				Self::load_from_filename("libEGL.so.1").or(Self::load_from_filename("libEGL.so"))
1984			}
1985		}
1986	};
1987	(@api_type ( $($pred:ident : $p_version:literal { $(fn $p_name:ident ($($p_arg:ident : $p_atype:ty ),* ) -> $p_rtype:ty ;)* })* ) $id:ident : $version:literal { $(fn $name:ident ($($arg:ident : $atype:ty ),* ) -> $rtype:ty ;)* }) => {
1988		#[cfg(feature="static")]
1989		#[cfg(feature=$version)]
1990		unsafe impl api::$id for Static {
1991			$(
1992				#[inline(always)]
1993				unsafe fn $name(&self, $($arg : $atype),*) -> $rtype {
1994					ffi::$name($($arg),*)
1995				}
1996			)*
1997		}
1998
1999		#[cfg(feature="dynamic")]
2000		#[cfg(feature=$version)]
2001		/// EGL version type.
2002		///
2003		/// Used by [`Dynamic`] to statically know the EGL API version provided by the library.
2004		pub struct $id;
2005
2006		#[cfg(feature="dynamic")]
2007		#[cfg(feature=$version)]
2008		impl $id {
2009			#[allow(unused_variables)]
2010			unsafe fn load_from<L: std::borrow::Borrow<libloading::Library>>(raw: &mut RawDynamic<L>) -> Result<(), libloading::Error> {
2011				let lib = raw.lib.borrow();
2012
2013				$(
2014					let name = stringify!($name).as_bytes();
2015					let symbol = lib.get::<unsafe extern "C" fn($($atype ),*) -> $rtype>(name)?;
2016					let ptr = (&symbol.into_raw().into_raw()) as *const *mut _ as *const unsafe extern "C" fn($($atype ),*) -> $rtype;
2017					assert!(!ptr.is_null());
2018					raw.$name = std::mem::MaybeUninit::new(*ptr);
2019				)*
2020
2021				Ok(())
2022			}
2023		}
2024
2025		$(
2026			#[cfg(feature="dynamic")]
2027			#[cfg(feature=$version)]
2028			unsafe impl<L: std::borrow::Borrow<libloading::Library>> api::$pred for Dynamic<L, $id> {
2029				$(
2030					#[inline(always)]
2031					unsafe fn $p_name(&self, $($p_arg : $p_atype),*) -> $p_rtype {
2032						(self.raw.$p_name.assume_init())($($p_arg),*)
2033					}
2034				)*
2035			}
2036		)*
2037
2038		#[cfg(feature="dynamic")]
2039		#[cfg(feature=$version)]
2040		unsafe impl<L: std::borrow::Borrow<libloading::Library>> api::$id for Dynamic<L, $id> {
2041			$(
2042				#[inline(always)]
2043				unsafe fn $name(&self, $($arg : $atype),*) -> $rtype {
2044					(self.raw.$name.assume_init())($($arg),*)
2045				}
2046			)*
2047		}
2048
2049		$(
2050			#[cfg(feature="dynamic")]
2051			#[cfg(feature=$version)]
2052			impl<L: std::borrow::Borrow<libloading::Library>> TryFrom<Dynamic<L, $pred>> for Dynamic<L, $id> {
2053				type Error = Dynamic<L, $pred>;
2054
2055				fn try_from(other: Dynamic<L, $pred>) -> Result<Self, Dynamic<L, $pred>> {
2056					if other.version() >= Version::$id {
2057						Ok(Dynamic {
2058							raw: other.raw,
2059							_api_version: std::marker::PhantomData
2060						})
2061					} else {
2062						Err(other)
2063					}
2064				}
2065			}
2066
2067			#[cfg(feature="dynamic")]
2068			#[cfg(feature=$version)]
2069			impl<L: std::borrow::Borrow<libloading::Library>> From<Dynamic<L, $id>> for Dynamic<L, $pred> {
2070				fn from(other: Dynamic<L, $id>) -> Self {
2071					Dynamic {
2072						raw: other.raw,
2073						_api_version: std::marker::PhantomData
2074					}
2075				}
2076			}
2077
2078			#[cfg(feature="dynamic")]
2079			#[cfg(feature=$version)]
2080			impl<L: std::borrow::Borrow<libloading::Library>> AsRef<Dynamic<L, $pred>> for Dynamic<L, $id> {
2081				fn as_ref(&self) -> &Dynamic<L, $pred> {
2082					unsafe { std::mem::transmute(self) } // this is safe because both types have the same repr.
2083				}
2084			}
2085
2086			#[cfg(feature="dynamic")]
2087			#[cfg(feature=$version)]
2088			impl<L: std::borrow::Borrow<libloading::Library>> Downcast<Dynamic<L, $pred>> for Dynamic<L, $id> {
2089				fn downcast(&self) -> &Dynamic<L, $pred> {
2090					unsafe { std::mem::transmute(self) } // this is safe because both types have the same repr.
2091				}
2092			}
2093
2094			#[cfg(feature="dynamic")]
2095			#[cfg(feature=$version)]
2096			impl<L: std::borrow::Borrow<libloading::Library>> Downcast<Instance<Dynamic<L, $pred>>> for Instance<Dynamic<L, $id>> {
2097				fn downcast(&self) -> &Instance<Dynamic<L, $pred>> {
2098					unsafe { std::mem::transmute(self) } // this is safe because both types have the same repr.
2099				}
2100			}
2101
2102			#[cfg(feature="dynamic")]
2103			#[cfg(feature=$version)]
2104			impl<L: std::borrow::Borrow<libloading::Library>> Upcast<Dynamic<L, $id>> for Dynamic<L, $pred> {
2105				fn upcast(&self) -> Option<&Dynamic<L, $id>> {
2106					if self.version() >= Version::$id {
2107						Some(unsafe { std::mem::transmute(self) }) // this is safe because both types have the same repr.
2108					} else {
2109						None
2110					}
2111				}
2112			}
2113
2114			#[cfg(feature="dynamic")]
2115			#[cfg(feature=$version)]
2116			impl<L: std::borrow::Borrow<libloading::Library>> Upcast<Instance<Dynamic<L, $id>>> for Instance<Dynamic<L, $pred>> {
2117				fn upcast(&self) -> Option<&Instance<Dynamic<L, $id>>> {
2118					if self.version() >= Version::$id {
2119						Some(unsafe { std::mem::transmute(self) }) // this is safe because both types have the same repr.
2120					} else {
2121						None
2122					}
2123				}
2124			}
2125		)*
2126
2127		#[cfg(feature="dynamic")]
2128		#[cfg(feature=$version)]
2129		impl<L: std::borrow::Borrow<libloading::Library>> Dynamic<L, $id> {
2130			#[inline]
2131			/// Load the EGL API symbols from the given library.
2132			///
2133			/// The second `Dynamic` type parameter gives the EGL API version expected to be provided by the library.
2134			///
2135			/// ## Safety
2136			/// This is fundamentally unsafe since there are no guaranties the input library complies to the EGL API.
2137			pub unsafe fn load_required(lib: L) -> Result<Dynamic<L, $id>, LoadError<libloading::Error>> {
2138				match Dynamic::<L, EGL1_0>::load_from(lib) {
2139					Ok(dynamic) => {
2140						let provided = dynamic.version();
2141						match dynamic.try_into() {
2142							Ok(t) => Ok(t),
2143							Err(_) => Err(LoadError::InvalidVersion {
2144								provided,
2145								required: Version::$id
2146							})
2147						}
2148					},
2149					Err(e) => Err(LoadError::Library(e))
2150				}
2151			}
2152		}
2153
2154		#[cfg(feature="dynamic")]
2155		#[cfg(feature=$version)]
2156		impl<L: std::borrow::Borrow<libloading::Library>> Instance<Dynamic<L, $id>> {
2157			#[inline(always)]
2158			/// Create an EGL instance using the symbols provided by the given library.
2159			/// This function fails if the EGL library does not provide the minimum required version given by the type parameter.
2160			///
2161			/// ## Safety
2162			/// This is fundamentally unsafe since there are no guaranties the input library complies to the EGL API.
2163			pub unsafe fn load_required_from(lib: L) -> Result<Instance<Dynamic<L, $id>>, LoadError<libloading::Error>> {
2164				Ok(Instance::new(Dynamic::<L, $id>::load_required(lib)?))
2165			}
2166		}
2167
2168		#[cfg(feature="dynamic")]
2169		#[cfg(feature=$version)]
2170		impl DynamicInstance<$id> {
2171			#[inline(always)]
2172			/// Create an EGL instance by finding and loading a dynamic library with the given filename.
2173			/// This function fails if the EGL library does not provide the minimum required version given by the type parameter.
2174			///
2175			/// See [`Library::new`](libloading::Library::new)
2176			/// for more details on how the `filename` argument is used.
2177			///
2178			/// On Linux plateforms, the library is loaded with the `RTLD_NODELETE` flag.
2179			/// See [#14](https://github.com/timothee-haudebourg/khronos-egl/issues/14) for more details.
2180			///
2181			/// ## Safety
2182			/// This is fundamentally unsafe since there are no guaranties the input library complies to the EGL API.
2183			pub unsafe fn load_required_from_filename<P: AsRef<std::ffi::OsStr>>(filename: P) -> Result<DynamicInstance<$id>, LoadError<libloading::Error>> {
2184				#[cfg(target_os = "linux")]
2185				let lib: libloading::Library = {
2186					// On Linux, load library with `RTLD_NOW | RTLD_NODELETE` to fix a SIGSEGV
2187					// See https://github.com/timothee-haudebourg/khronos-egl/issues/14 for more details.
2188					libloading::os::unix::Library::open(Some(filename), 0x2 | 0x1000).map_err(LoadError::Library)?.into()
2189				};
2190				#[cfg(not(target_os = "linux"))]
2191				let lib = libloading::Library::new(filename).map_err(LoadError::Library)?;
2192				Self::load_required_from(lib)
2193			}
2194
2195			#[inline(always)]
2196			/// Create an EGL instance by finding and loading the `libEGL.so.1` or `libEGL.so` library.
2197			/// This function fails if the EGL library does not provide the minimum required version given by the type parameter.
2198			///
2199			/// This is equivalent to `DynamicInstance::load_required_from_filename("libEGL.so.1")`.
2200			///
2201			/// ## Safety
2202			/// This is fundamentally unsafe since there are no guaranties the found library complies to the EGL API.
2203			pub unsafe fn load_required() -> Result<DynamicInstance<$id>, LoadError<libloading::Error>> {
2204			    Self::load_required_from_filename("libEGL.so.1").or(Self::load_required_from_filename("libEGL.so"))
2205			}
2206		}
2207	}
2208}
2209
2210api! {
2211	EGL1_0 : "1_0" {
2212		fn eglChooseConfig(
2213			display: EGLDisplay,
2214			attrib_list: *const Int,
2215			configs: *mut EGLConfig,
2216			config_size: Int,
2217			num_config: *mut Int
2218		) -> Boolean;
2219		fn eglCopyBuffers(
2220			display: EGLDisplay,
2221			surface: EGLSurface,
2222			target: NativePixmapType
2223		) -> Boolean;
2224		fn eglCreateContext(
2225			display: EGLDisplay,
2226			config: EGLConfig,
2227			share_context: EGLContext,
2228			attrib_list: *const Int
2229		) -> EGLContext;
2230		fn eglCreatePbufferSurface(
2231			display: EGLDisplay,
2232			config: EGLConfig,
2233			attrib_list: *const Int
2234		) -> EGLSurface;
2235		fn eglCreatePixmapSurface(
2236			display: EGLDisplay,
2237			config: EGLConfig,
2238			pixmap: NativePixmapType,
2239			attrib_list: *const Int
2240		) -> EGLSurface;
2241		fn eglCreateWindowSurface(
2242			display: EGLDisplay,
2243			config: EGLConfig,
2244			win: NativeWindowType,
2245			attrib_list: *const Int
2246		) -> EGLSurface;
2247		fn eglDestroyContext(display: EGLDisplay, ctx: EGLContext) -> Boolean;
2248		fn eglDestroySurface(display: EGLDisplay, surface: EGLSurface) -> Boolean;
2249		fn eglGetConfigAttrib(
2250			display: EGLDisplay,
2251			config: EGLConfig,
2252			attribute: Int,
2253			value: *mut Int
2254		) -> Boolean;
2255		fn eglGetConfigs(
2256			display: EGLDisplay,
2257			configs: *mut EGLConfig,
2258			config_size: Int,
2259			num_config: *mut Int
2260		) -> Boolean;
2261		fn eglGetCurrentDisplay() -> EGLDisplay;
2262		fn eglGetCurrentSurface(readdraw: Int) -> EGLSurface;
2263		fn eglGetDisplay(display_id: NativeDisplayType) -> EGLDisplay;
2264		fn eglGetError() -> Int;
2265		fn eglGetProcAddress(procname: *const c_char) -> extern "C" fn();
2266		fn eglInitialize(display: EGLDisplay, major: *mut Int, minor: *mut Int) -> Boolean;
2267		fn eglMakeCurrent(
2268			display: EGLDisplay,
2269			draw: EGLSurface,
2270			read: EGLSurface,
2271			ctx: EGLContext
2272		) -> Boolean;
2273		fn eglQueryContext(
2274			display: EGLDisplay,
2275			ctx: EGLContext,
2276			attribute: Int,
2277			value: *mut Int
2278		) -> Boolean;
2279		fn eglQueryString(display: EGLDisplay, name: Int) -> *const c_char;
2280		fn eglQuerySurface(
2281			display: EGLDisplay,
2282			surface: EGLSurface,
2283			attribute: Int,
2284			value: *mut Int
2285		) -> Boolean;
2286		fn eglSwapBuffers(display: EGLDisplay, surface: EGLSurface) -> Boolean;
2287		fn eglTerminate(display: EGLDisplay) -> Boolean;
2288		fn eglWaitGL() -> Boolean;
2289		fn eglWaitNative(engine: Int) -> Boolean;
2290	},
2291
2292	EGL1_1 : "1_1" {
2293		fn eglBindTexImage(display: EGLDisplay, surface: EGLSurface, buffer: Int) -> Boolean;
2294		fn eglReleaseTexImage(display: EGLDisplay, surface: EGLSurface, buffer: Int) -> Boolean;
2295		fn eglSurfaceAttrib(
2296			display: EGLDisplay,
2297			surface: EGLSurface,
2298			attribute: Int,
2299			value: Int
2300		) -> Boolean;
2301		fn eglSwapInterval(display: EGLDisplay, interval: Int) -> Boolean;
2302	},
2303
2304	EGL1_2 : "1_2" {
2305		fn eglBindAPI(api: Enum) -> Boolean;
2306		fn eglQueryAPI() -> Enum;
2307		fn eglCreatePbufferFromClientBuffer(
2308			display: EGLDisplay,
2309			buftype: Enum,
2310			buffer: EGLClientBuffer,
2311			config: EGLConfig,
2312			attrib_list: *const Int
2313		) -> EGLSurface;
2314		fn eglReleaseThread() -> Boolean;
2315		fn eglWaitClient() -> Boolean;
2316	},
2317
2318	EGL1_3 : "1_3" {
2319		// nothing.
2320	},
2321
2322	EGL1_4 : "1_4" {
2323		fn eglGetCurrentContext() -> EGLContext;
2324	},
2325
2326	EGL1_5 : "1_5" {
2327		fn eglCreateSync(display: EGLDisplay, type_: Enum, attrib_list: *const Attrib) -> EGLSync;
2328		fn eglDestroySync(display: EGLDisplay, sync: EGLSync) -> Boolean;
2329		fn eglClientWaitSync(display: EGLDisplay, sync: EGLSync, flags: Int, timeout: Time) -> Int;
2330		fn eglGetSyncAttrib(
2331			display: EGLDisplay,
2332			sync: EGLSync,
2333			attribute: Int,
2334			value: *mut Attrib
2335		) -> Boolean;
2336		fn eglCreateImage(
2337			display: EGLDisplay,
2338			ctx: EGLContext,
2339			target: Enum,
2340			buffer: EGLClientBuffer,
2341			attrib_list: *const Attrib
2342		) -> EGLImage;
2343		fn eglDestroyImage(display: EGLDisplay, image: EGLImage) -> Boolean;
2344		fn eglGetPlatformDisplay(
2345			platform: Enum,
2346			native_display: *mut c_void,
2347			attrib_list: *const Attrib
2348		) -> EGLDisplay;
2349		fn eglCreatePlatformWindowSurface(
2350			display: EGLDisplay,
2351			config: EGLConfig,
2352			native_window: *mut c_void,
2353			attrib_list: *const Attrib
2354		) -> EGLSurface;
2355		fn eglCreatePlatformPixmapSurface(
2356			display: EGLDisplay,
2357			config: EGLConfig,
2358			native_pixmap: *mut c_void,
2359			attrib_list: *const Attrib
2360		) -> EGLSurface;
2361		fn eglWaitSync(display: EGLDisplay, sync: EGLSync, flags: Int) -> Boolean;
2362	}
2363}