• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
128 extern crate libc;
129 
130 use std::convert::{TryFrom, TryInto};
131 use std::ffi::CStr;
132 use std::ffi::CString;
133 use std::fmt;
134 use std::ptr;
135 
136 use libc::{c_char, c_uint, c_void};
137 
138 /// EGL API provider.
139 pub trait Api {
140 	/// Version of the provided EGL API.
version(&self) -> Version141 	fn version(&self) -> Version;
142 }
143 
144 pub trait Downcast<V> {
downcast(&self) -> &V145 	fn downcast(&self) -> &V;
146 }
147 
148 impl<T> Downcast<T> for T {
downcast(&self) -> &T149 	fn downcast(&self) -> &T {
150 		self
151 	}
152 }
153 
154 pub trait Upcast<V> {
upcast(&self) -> Option<&V>155 	fn upcast(&self) -> Option<&V>;
156 }
157 
158 impl<T> Upcast<T> for T {
upcast(&self) -> Option<&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.
168 pub struct Instance<T> {
169 	api: T,
170 }
171 
172 impl<T> Instance<T> {
173 	/// Cast the API.
174 	#[inline(always)]
cast_into<U: From<T>>(self) -> Instance<U>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)]
try_cast_into<U: TryFrom<T>>(self) -> Result<Instance<U>, Instance<U::Error>>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)]
version(&self) -> Version where T: Api,192 	pub fn version(&self) -> Version
193 	where
194 		T: Api,
195 	{
196 		self.api.version()
197 	}
198 }
199 
200 impl<T> Instance<T> {
201 	#[inline(always)]
new(api: T) -> Instance<T>202 	pub const fn new(api: T) -> Instance<T> {
203 		Instance { api }
204 	}
205 }
206 
207 impl<T: fmt::Debug> fmt::Debug for Instance<T> {
208 	#[inline(always)]
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result209 	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
210 		write!(f, "Instance({:?})", self.api)
211 	}
212 }
213 
214 impl<T> From<T> for Instance<T> {
215 	#[inline(always)]
from(t: T) -> Instance<T>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")]
226 mod 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]
from_ptr(ptr: EGLDisplay) -> Display248 		pub unsafe fn from_ptr(ptr: EGLDisplay) -> Display {
249 			Display(ptr)
250 		}
251 
252 		#[inline]
as_ptr(&self) -> EGLDisplay253 		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]
from_ptr(ptr: EGLConfig) -> Config268 		pub unsafe fn from_ptr(ptr: EGLConfig) -> Config {
269 			Config(ptr)
270 		}
271 
272 		#[inline]
as_ptr(&self) -> EGLConfig273 		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]
from_ptr(ptr: EGLContext) -> Context288 		pub unsafe fn from_ptr(ptr: EGLContext) -> Context {
289 			Context(ptr)
290 		}
291 
292 		#[inline]
as_ptr(&self) -> EGLContext293 		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]
from_ptr(ptr: EGLSurface) -> Surface308 		pub unsafe fn from_ptr(ptr: EGLSurface) -> Surface {
309 			Surface(ptr)
310 		}
311 
312 		#[inline]
as_ptr(&self) -> EGLSurface313 		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 {
source(&self) -> Option<&(dyn std::error::Error + 'static)>454 		fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
455 			None
456 		}
457 	}
458 
459 	impl Error {
native(&self) -> Int460 		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 
message(&self) -> &'static str480 		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 {
from(e: Error) -> Int502 		fn from(e: Error) -> Int {
503 			e.native()
504 		}
505 	}
506 
507 	impl TryFrom<Int> for Error {
508 		type Error = Int;
509 
try_from(e: Int) -> Result<Error, Int>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 {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result533 		fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
534 			self.message().fmt(f)
535 		}
536 	}
537 
check_int_list(attrib_list: &[Int]) -> Result<(), Error>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 
check_attrib_list(attrib_list: &[Attrib]) -> Result<(), Error>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`).
matching_config_count( &self, display: Display, attrib_list: &[Int], ) -> Result<usize, Error>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`).
choose_config( &self, display: Display, attrib_list: &[Int], configs: &mut Vec<Config>, ) -> Result<(), Error>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 		/// ```
choose_first_config( &self, display: Display, attrib_list: &[Int], ) -> Result<Option<Config>, Error>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`.
copy_buffers( &self, display: Display, surface: Surface, target: NativePixmapType, ) -> Result<(), Error>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`).
create_context( &self, display: Display, config: Config, share_context: Option<Context>, attrib_list: &[Int], ) -> Result<Context, Error>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`).
create_pbuffer_surface( &self, display: Display, config: Config, attrib_list: &[Int], ) -> Result<Surface, Error>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.
create_pixmap_surface( &self, display: Display, config: Config, pixmap: NativePixmapType, attrib_list: &[Int], ) -> Result<Surface, Error>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.
create_window_surface( &self, display: Display, config: Config, window: NativeWindowType, attrib_list: Option<&[Int]>, ) -> Result<Surface, Error>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.
destroy_context(&self, display: Display, ctx: Context) -> Result<(), Error>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.
destroy_surface(&self, display: Display, surface: Surface) -> Result<(), Error>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.
get_config_attrib( &self, display: Display, config: Config, attribute: Int, ) -> Result<Int, Error>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 		/// ```
get_config_count(&self, display: Display) -> Result<usize, Error>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 		/// ```
get_configs( &self, display: Display, configs: &mut Vec<Config>, ) -> Result<(), Error>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.
get_current_display(&self) -> Option<Display>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.
get_current_surface(&self, readdraw: Int) -> Option<Surface>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.
get_display(&self, display_id: NativeDisplayType) -> Option<Display>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.
get_error(&self) -> Option<Error>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.
get_proc_address(&self, procname: &str) -> Option<extern "system" fn()>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.
initialize(&self, display: Display) -> Result<(Int, Int), Error>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.
make_current( &self, display: Display, draw: Option<Surface>, read: Option<Surface>, ctx: Option<Context>, ) -> Result<(), Error>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.
query_context( &self, display: Display, ctx: Context, attribute: Int, ) -> Result<Int, Error>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.
query_string( &self, display: Option<Display>, name: Int, ) -> Result<&'static CStr, Error>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.
query_surface( &self, display: Display, surface: Surface, attribute: Int, ) -> Result<Int, Error>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.
swap_buffers(&self, display: Display, surface: Surface) -> Result<(), Error>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.
terminate(&self, display: Display) -> Result<(), Error>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.
wait_gl(&self) -> Result<(), Error>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.
wait_native(&self, engine: Int) -> Result<(), Error>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")]
1214 pub use egl1_0::*;
1215 
1216 // ------------------------------------------------------------------------------------------------
1217 // EGL 1.1
1218 // ------------------------------------------------------------------------------------------------
1219 
1220 #[cfg(feature = "1_1")]
1221 mod 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.
bind_tex_image( &self, display: Display, surface: Surface, buffer: Int, ) -> Result<(), Error>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.
release_tex_image( &self, display: Display, surface: Surface, buffer: Int, ) -> Result<(), Error>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.
surface_attrib( &self, display: Display, surface: Surface, attribute: Int, value: Int, ) -> Result<(), Error>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.
swap_interval(&self, display: Display, interval: Int) -> Result<(), Error>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")]
1316 pub use egl1_1::*;
1317 
1318 // ------------------------------------------------------------------------------------------------
1319 // EGL 1.2
1320 // ------------------------------------------------------------------------------------------------
1321 
1322 #[cfg(feature = "1_2")]
1323 mod 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]
from_ptr(ptr: EGLClientBuffer) -> ClientBuffer1339 		pub unsafe fn from_ptr(ptr: EGLClientBuffer) -> ClientBuffer {
1340 			ClientBuffer(ptr)
1341 		}
1342 
1343 		#[inline]
as_ptr(&self) -> EGLClientBuffer1344 		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.
bind_api(&self, api: Enum) -> Result<(), Error>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.
query_api(&self) -> Enum1392 		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`).
create_pbuffer_from_client_buffer( &self, display: Display, buffer_type: Enum, buffer: ClientBuffer, config: Config, attrib_list: &[Int], ) -> Result<Surface, Error>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.
release_thread(&self) -> Result<(), Error>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.
wait_client(&self) -> Result<(), Error>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")]
1451 pub use egl1_2::*;
1452 
1453 // ------------------------------------------------------------------------------------------------
1454 // EGL 1.3
1455 // ------------------------------------------------------------------------------------------------
1456 
1457 #[cfg(feature = "1_3")]
1458 mod 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")]
1476 pub use egl1_3::*;
1477 
1478 // ------------------------------------------------------------------------------------------------
1479 // EGL 1.4
1480 // ------------------------------------------------------------------------------------------------
1481 
1482 #[cfg(feature = "1_4")]
1483 mod 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.
get_current_context(&self) -> Option<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")]
1512 pub use egl1_4::*;
1513 
1514 // ------------------------------------------------------------------------------------------------
1515 // EGL 1.5
1516 // ------------------------------------------------------------------------------------------------
1517 
1518 #[cfg(feature = "1_5")]
1519 mod 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]
from_ptr(ptr: EGLSync) -> Sync1536 		pub unsafe fn from_ptr(ptr: EGLSync) -> Sync {
1537 			Sync(ptr)
1538 		}
1539 
1540 		#[inline]
as_ptr(&self) -> EGLSync1541 		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]
from_ptr(ptr: EGLImage) -> Image1556 		pub unsafe fn from_ptr(ptr: EGLImage) -> Image {
1557 			Image(ptr)
1558 		}
1559 
1560 		#[inline]
as_ptr(&self) -> EGLImage1561 		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.
create_sync( &self, display: Display, ty: Enum, attrib_list: &[Attrib], ) -> Result<Sync, Error>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.
destroy_sync(&self, display: Display, sync: Sync) -> Result<(), Error>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.
client_wait_sync( &self, display: Display, sync: Sync, flags: Int, timeout: Time, ) -> Result<Int, Error>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.
get_sync_attrib( &self, display: Display, sync: Sync, attribute: Int, ) -> Result<Attrib, Error>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`).
create_image( &self, display: Display, ctx: Context, target: Enum, buffer: ClientBuffer, attrib_list: &[Attrib], ) -> Result<Image, Error>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.
destroy_image(&self, display: Display, image: Image) -> Result<(), Error>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.
get_platform_display( &self, platform: Enum, native_display: NativeDisplayType, attrib_list: &[Attrib], ) -> Result<Display, Error>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.
create_platform_window_surface( &self, display: Display, config: Config, native_window: NativeWindowType, attrib_list: &[Attrib], ) -> Result<Surface, Error>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.
create_platform_pixmap_surface( &self, display: Display, config: Config, native_pixmap: NativePixmapType, attrib_list: &[Attrib], ) -> Result<Surface, Error>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.
wait_sync(&self, display: Display, sync: Sync, flags: Int) -> Result<(), Error>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")]
1874 pub use egl1_5::*;
1875 
1876 // -------------------------------------------------------------------------------------------------
1877 // FFI
1878 // -------------------------------------------------------------------------------------------------
1879 
1880 macro_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 
2499 api! {
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 }
2653