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