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