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