Skip to main content

edgefirst_egl/
lib.rs

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