//! This crate provides a binding for the Khronos EGL 1.5 API. //! It was originally a fork of the [egl](https://crates.io/crates/egl) crate, //! which is left unmaintained. //! //! ## Usage //! //! You can access the EGL API using an [`Instance`] //! object defined by either statically linking with `libEGL.so.1` at compile time, //! or dynamically loading the EGL library at runtime. //! //! ### Static linking //! //! You must enable static linking using the `static` feature in your `Cargo.toml`: //! ```toml //! khronos-egl = { version = ..., features = ["static"] } //! ``` //! //! This will add a dependency to the [`pkg-config`](https://crates.io/crates/pkg-config) crate, //! necessary to find the EGL library at compile time. //! Here is a simple example showing how to use this library to create an EGL context when static linking is enabled. //! //! ```rust //! extern crate khronos_egl as egl; //! //! fn main() -> Result<(), egl::Error> { //! // Create an EGL API instance. //! // The `egl::Static` API implementation is only available when the `static` feature is enabled. //! let egl = egl::Instance::new(egl::Static); //! //! let wayland_display = wayland_client::Display::connect_to_env().expect("unable to connect to the wayland server"); //! let display = unsafe { egl.get_display(wayland_display.get_display_ptr() as *mut std::ffi::c_void) }.unwrap(); //! egl.initialize(display)?; //! //! let attributes = [ //! egl::RED_SIZE, 8, //! egl::GREEN_SIZE, 8, //! egl::BLUE_SIZE, 8, //! egl::NONE //! ]; //! //! let config = egl.choose_first_config(display, &attributes)?.expect("unable to find an appropriate ELG configuration"); //! //! let context_attributes = [ //! egl::CONTEXT_MAJOR_VERSION, 4, //! egl::CONTEXT_MINOR_VERSION, 0, //! egl::CONTEXT_OPENGL_PROFILE_MASK, egl::CONTEXT_OPENGL_CORE_PROFILE_BIT, //! egl::NONE //! ]; //! //! egl.create_context(display, config, None, &context_attributes); //! //! Ok(()) //! } //! ``` //! //! The creation of a `Display` instance is not detailed here since it depends on your display server. //! It is created using the `get_display` function with a pointer to the display server connection handle. //! For instance, if you are using the [wayland-client](https://crates.io/crates/wayland-client) crate, //! you can get this pointer using the `Display::get_display_ptr` method. //! //! #### Static API Instance //! //! It may be bothering in some applications to pass the `Instance` to every fonction that needs to call the EGL API. //! One workaround would be to define a static `Instance`, //! which should be possible to define at compile time using static linking. //! However this is not yet supported by the stable `rustc` compiler. //! With the nightly compiler, //! you can combine the `nightly` and `static` features so that this crate //! can provide a static `Instance`, called `API` that can then be accessed everywhere. //! //! ``` //! # extern crate khronos_egl as egl; //! use egl::API as egl; //! ``` //! //! ### Dynamic Linking //! //! Dynamic linking allows your application to accept multiple versions of EGL and be more flexible. //! You must enable dynamic linking using the `dynamic` feature in your `Cargo.toml`: //! ```toml //! khronos-egl = { version = ..., features = ["dynamic"] } //! ``` //! //! This will add a dependency to the [`libloading`](https://crates.io/crates/libloading) crate, //! necessary to find the EGL library at runtime. //! You can then load the EGL API into a `Instance<Dynamic<libloading::Library>>` as follows: //! //! ``` //! # extern crate khronos_egl as egl; //! let lib = unsafe { libloading::Library::new("libEGL.so.1") }.expect("unable to find libEGL.so.1"); //! let egl = unsafe { egl::DynamicInstance::<egl::EGL1_4>::load_required_from(lib) }.expect("unable to load libEGL.so.1"); //! ``` //! //! Here, `egl::EGL1_4` is used to specify what is the minimum required version of EGL that must be provided by `libEGL.so.1`. //! This will return a `DynamicInstance<egl::EGL1_4>`, however in that case where `libEGL.so.1` provides a more recent version of EGL, //! you can still upcast ths instance to provide version specific features: //! ``` //! # extern crate khronos_egl as egl; //! # let lib = unsafe { libloading::Library::new("libEGL.so.1") }.expect("unable to find libEGL.so.1"); //! # let egl = unsafe { egl::DynamicInstance::<egl::EGL1_4>::load_required_from(lib) }.expect("unable to load libEGL.so.1"); //! match egl.upcast::<egl::EGL1_5>() { //! Some(egl1_5) => { //! // do something with EGL 1.5 //! } //! None => { //! // do something with EGL 1.4 instead. //! } //! }; //! ``` //! //! ## Troubleshooting //! //! ### Static Linking with OpenGL ES //! //! When using OpenGL ES with `khronos-egl` with the `static` feature, //! it is necessary to place a dummy extern at the top of your application which links libEGL first, then GLESv1/2. //! This is because libEGL provides symbols required by GLESv1/2. //! Here's how to work around this: //! //! ``` //! ##[link(name = "EGL")] //! ##[link(name = "GLESv2")] //! extern {} //! ``` #![allow(non_upper_case_globals)] #![allow(non_snake_case)]
externcrate libc;
use std::convert::{TryFrom, TryInto}; use std::ffi::CStr; use std::ffi::CString; use std::fmt; use std::ptr;
use libc::{c_char, c_uint, c_void};
/// EGL API provider. pubtrait Api { /// Version of the provided EGL API. fn version(&self) -> Version;
}
impl<T> Upcast<T> for T { fn upcast(&self) -> Option<&T> {
Some(self)
}
}
/// EGL API instance. /// /// An instance wraps an interface to the EGL API and provide /// rust-friendly access to it. pubstruct Instance<T> {
api: T,
}
impl Display { /// Creates a new display from its EGL pointer. /// /// # Safety /// /// `ptr` must be a valid `EGLDisplay` pointer. #[inline] pubunsafefn from_ptr(ptr: EGLDisplay) -> Display {
Display(ptr)
}
impl Config { /// Creates a new configuration form its EGL pointer. /// /// # Safety /// /// `ptr` must be a valid `EGLConfig` pointer. #[inline] pubunsafefn from_ptr(ptr: EGLConfig) -> Config {
Config(ptr)
}
impl Context { /// Creates a new context form its EGL pointer. /// /// # Safety /// /// `ptr` must be a valid `EGLContext` pointer. #[inline] pubunsafefn from_ptr(ptr: EGLContext) -> Context {
Context(ptr)
}
impl Surface { /// Creates a new surface form its EGL pointer. /// /// # Safety /// /// `ptr` must be a valid `EGLSurface` pointer. #[inline] pubunsafefn from_ptr(ptr: EGLSurface) -> Surface {
Surface(ptr)
}
pubconst ALPHA_SIZE: Int = 0x3021; pubconst BAD_ACCESS: Int = 0x3002; pubconst BAD_ALLOC: Int = 0x3003; pubconst BAD_ATTRIBUTE: Int = 0x3004; pubconst BAD_CONFIG: Int = 0x3005; pubconst BAD_CONTEXT: Int = 0x3006; pubconst BAD_CURRENT_SURFACE: Int = 0x3007; pubconst BAD_DISPLAY: Int = 0x3008; pubconst BAD_MATCH: Int = 0x3009; pubconst BAD_NATIVE_PIXMAP: Int = 0x300A; pubconst BAD_NATIVE_WINDOW: Int = 0x300B; pubconst BAD_PARAMETER: Int = 0x300C; pubconst BAD_SURFACE: Int = 0x300D; pubconst BLUE_SIZE: Int = 0x3022; pubconst BUFFER_SIZE: Int = 0x3020; pubconst CONFIG_CAVEAT: Int = 0x3027; pubconst CONFIG_ID: Int = 0x3028; pubconst CORE_NATIVE_ENGINE: Int = 0x305B; pubconst DEPTH_SIZE: Int = 0x3025; pubconst DONT_CARE: Int = -1; pubconst DRAW: Int = 0x3059; pubconst EXTENSIONS: Int = 0x3055; pubconstFALSE: Boolean = 0; pubconst GREEN_SIZE: Int = 0x3023; pubconst HEIGHT: Int = 0x3056; pubconst LARGEST_PBUFFER: Int = 0x3058; pubconst LEVEL: Int = 0x3029; pubconst MAX_PBUFFER_HEIGHT: Int = 0x302A; pubconst MAX_PBUFFER_PIXELS: Int = 0x302B; pubconst MAX_PBUFFER_WIDTH: Int = 0x302C; pubconst NATIVE_RENDERABLE: Int = 0x302D; pubconst NATIVE_VISUAL_ID: Int = 0x302E; pubconst NATIVE_VISUAL_TYPE: Int = 0x302F; pubconst NONE: Int = 0x3038; pubconst ATTRIB_NONE: Attrib = 0x3038; pubconst NON_CONFORMANT_CONFIG: Int = 0x3051; pubconst NOT_INITIALIZED: Int = 0x3001; pubconst NO_CONTEXT: EGLContext = 0as EGLContext; pubconst NO_DISPLAY: EGLDisplay = 0as EGLDisplay; pubconst NO_SURFACE: EGLSurface = 0as EGLSurface; pubconst PBUFFER_BIT: Int = 0x0001; pubconst PIXMAP_BIT: Int = 0x0002; pubconst READ: Int = 0x305A; pubconst RED_SIZE: Int = 0x3024; pubconst SAMPLES: Int = 0x3031; pubconst SAMPLE_BUFFERS: Int = 0x3032; pubconst SLOW_CONFIG: Int = 0x3050; pubconst STENCIL_SIZE: Int = 0x3026; pubconst SUCCESS: Int = 0x3000; pubconst SURFACE_TYPE: Int = 0x3033; pubconst TRANSPARENT_BLUE_VALUE: Int = 0x3035; pubconst TRANSPARENT_GREEN_VALUE: Int = 0x3036; pubconst TRANSPARENT_RED_VALUE: Int = 0x3037; pubconst TRANSPARENT_RGB: Int = 0x3052; pubconst TRANSPARENT_TYPE: Int = 0x3034; pubconstTRUE: Boolean = 1; pubconst VENDOR: Int = 0x3053; pubconst VERSION: Int = 0x3054; pubconst WIDTH: Int = 0x3057; pubconst WINDOW_BIT: Int = 0x0004;
/// EGL errors. #[derive(Clone, Copy, PartialEq, Eq, Debug)] pubenum Error { /// EGL is not initialized, or could not be initialized, for the specified /// EGL display connection.
NotInitialized,
/// EGL cannot access a requested resource (for example a context is bound /// in another thread).
BadAccess,
/// EGL failed to allocate resources for the requested operation.
BadAlloc,
/// An unrecognized attribute or attribute value was passed in the attribute /// list.
BadAttribute,
/// An Context argument does not name a valid EGL rendering context.
BadContext,
/// An Config argument does not name a valid EGL frame buffer configuration.
BadConfig,
/// The current surface of the calling thread is a window, pixel buffer or /// pixmap that is no longer valid.
BadCurrentSurface,
/// An Display argument does not name a valid EGL display connection.
BadDisplay,
/// An Surface argument does not name a valid surface (window, pixel buffer /// or pixmap) configured for GL rendering.
BadSurface,
/// Arguments are inconsistent (for example, a valid context requires /// buffers not supplied by a valid surface).
BadMatch,
/// One or more argument values are invalid.
BadParameter,
/// A NativePixmapType argument does not refer to a valid native pixmap.
BadNativePixmap,
/// A NativeWindowType argument does not refer to a valid native window.
BadNativeWindow,
/// A power management event has occurred. The application must destroy all /// contexts and reinitialise OpenGL ES state and objects to continue /// rendering.
ContextLost,
}
fn message(&self) -> &'static str { use Error::*; matchself {
NotInitialized => "EGL is not initialized, or could not be initialized, for the specified EGL display connection.",
BadAccess => "EGL cannot access a requested resource (for example a context is bound in another thread.",
BadAlloc => "EGL failed to allocate resources for the requested operation.",
BadAttribute => "An unrecognized attribute or attribute value was passed in the attribute list.",
BadContext => "An Context argument does not name a valid EGL rendering context.",
BadConfig => "An Config argument does not name a valid EGL frame buffer configuration.",
BadCurrentSurface => "The current surface of the calling thread is a window, pixel buffer or pixmap that is no longer valid.",
BadDisplay => "An Display argument does not name a valid EGL display connection.",
BadSurface => "An Surface argument does not name a valid surface (window, pixel buffer or pixmap) configured for GL rendering.",
BadMatch => "Arguments are inconsistent (for example, a valid context requires buffers not supplied by a valid surface.",
BadParameter => "One or more argument values are invalid.",
BadNativePixmap => "A NativePixmapType argument does not refer to a valid native pixmap.",
BadNativeWindow => "A NativeWindowType argument does not refer to a valid native window.",
ContextLost => "A power management event has occurred. The application must destroy all contexts and reinitialise OpenGL ES state and objects to continue rendering."
}
}
}
impl From<Error> for Int { fn from(e: Error) -> Int {
e.native()
}
}
impl<T: api::EGL1_0> Instance<T> { /// Return the number of EGL frame buffer configurations that atch specified /// attributes. /// /// This will call `eglChooseConfig` without `null` as `configs` to get the /// number of matching configurations. /// /// This will return a `BadParameter` error if `attrib_list` is not a valid /// attributes list (if it does not terminate with `NONE`). pubfn matching_config_count(
&self,
display: Display,
attrib_list: &[Int],
) -> Result<usize, Error> {
check_int_list(attrib_list)?; unsafe { letmut count = 0;
/// Return a list of EGL frame buffer configurations that match specified /// attributes. /// /// This will write as many matching configurations in `configs` up to its /// capacity. You can use the function [`matching_config_count`](Self::matching_config_count) to get the /// exact number of configurations matching the specified attributes. /// /// ## Example /// /// ``` /// # extern crate khronos_egl as egl; /// # extern crate wayland_client; /// # fn main() -> Result<(), egl::Error> { /// # let egl = egl::Instance::new(egl::Static); /// # let wayland_display = wayland_client::Display::connect_to_env().expect("unable to connect to the wayland server"); /// # let display = unsafe { egl.get_display(wayland_display.get_display_ptr() as *mut std::ffi::c_void) }.unwrap(); /// # egl.initialize(display)?; /// # let attrib_list = [egl::RED_SIZE, 8, egl::GREEN_SIZE, 8, egl::BLUE_SIZE, 8, egl::NONE]; /// // Get the number of matching configurations. /// let count = egl.matching_config_count(display, &attrib_list)?; /// /// // Get the matching configurations. /// let mut configs = Vec::with_capacity(count); /// egl.choose_config(display, &attrib_list, &mut configs)?; /// # Ok(()) /// # } /// ``` /// /// This will return a `BadParameter` error if `attrib_list` is not a valid /// attributes list (if it does not terminate with `NONE`). pubfn choose_config(
&self,
display: Display,
attrib_list: &[Int],
configs: &mut Vec<Config>,
) -> Result<(), Error> {
check_int_list(attrib_list)?;
let capacity = configs.capacity(); if capacity == 0 { // When the input ptr is null (when capacity is 0), // eglChooseConfig behaves differently and returns the number // of configurations.
Ok(())
} else { unsafe { letmut count = 0;
/// Return the first EGL frame buffer configuration that match specified /// attributes. /// /// This is an helper function that will call `choose_config` with a buffer of /// size 1, which is equivalent to: /// ``` /// # extern crate khronos_egl as egl; /// # extern crate wayland_client; /// # fn main() -> Result<(), egl::Error> { /// # let egl = egl::Instance::new(egl::Static); /// # let wayland_display = wayland_client::Display::connect_to_env().expect("unable to connect to the wayland server"); /// # let display = unsafe { egl.get_display(wayland_display.get_display_ptr() as *mut std::ffi::c_void) }.unwrap(); /// # egl.initialize(display)?; /// # let attrib_list = [egl::RED_SIZE, 8, egl::GREEN_SIZE, 8, egl::BLUE_SIZE, 8, egl::NONE]; /// let mut configs = Vec::with_capacity(1); /// egl.choose_config(display, &attrib_list, &mut configs)?; /// configs.first(); /// # Ok(()) /// # } /// ``` pubfn choose_first_config(
&self,
display: Display,
attrib_list: &[Int],
) -> Result<Option<Config>, Error> { letmut configs = Vec::with_capacity(1); self.choose_config(display, attrib_list, &mut configs)?;
Ok(configs.first().copied())
}
/// Copy EGL surface color buffer to a native pixmap. /// /// # Safety /// /// `target` must be a valid pointer to a native pixmap that belongs /// to the same platform as `display` and `surface`. pubunsafefn copy_buffers(
&self,
display: Display,
surface: Surface,
target: NativePixmapType,
) -> Result<(), Error> { unsafe { ifself
.api
.eglCopyBuffers(display.as_ptr(), surface.as_ptr(), target)
== TRUE
{
Ok(())
} else {
Err(self.get_error().unwrap())
}
}
}
/// Create a new EGL rendering context. /// /// This will return a `BadParameter` error if `attrib_list` is not a valid /// attributes list (if it does not terminate with `NONE`). pubfn create_context(
&self,
display: Display,
config: Config,
share_context: Option<Context>,
attrib_list: &[Int],
) -> Result<Context, Error> {
check_int_list(attrib_list)?; unsafe { let share_context = match share_context {
Some(share_context) => share_context.as_ptr(),
None => NO_CONTEXT,
};
let context = self.api.eglCreateContext(
display.as_ptr(),
config.as_ptr(),
share_context,
attrib_list.as_ptr(),
);
/// Create a new EGL pixel buffer surface. /// /// This will return a `BadParameter` error if `attrib_list` is not a valid /// attributes list (if it does not terminate with `NONE`). pubfn create_pbuffer_surface(
&self,
display: Display,
config: Config,
attrib_list: &[Int],
) -> Result<Surface, Error> {
check_int_list(attrib_list)?; unsafe { let surface = self.api.eglCreatePbufferSurface(
display.as_ptr(),
config.as_ptr(),
attrib_list.as_ptr(),
);
/// Create a new EGL offscreen surface. /// /// This will return a `BadParameter` error if `attrib_list` is not a valid /// attributes list (if it does not terminate with `NONE`). /// /// # Safety /// /// This function may raise undefined behavior if the display and native /// pixmap do not belong to the same platform. pubunsafefn create_pixmap_surface(
&self,
display: Display,
config: Config,
pixmap: NativePixmapType,
attrib_list: &[Int],
) -> Result<Surface, Error> {
check_int_list(attrib_list)?; let surface = self.api.eglCreatePixmapSurface(
display.as_ptr(),
config.as_ptr(),
pixmap,
attrib_list.as_ptr(),
);
/// Create a new EGL window surface. /// /// This will return a `BadParameter` error if `attrib_list` is not a valid /// attributes list (if it does not terminate with `NONE`). /// /// # Safety /// /// This function may raise undefined behavior if the display and native /// window do not belong to the same platform. pubunsafefn create_window_surface(
&self,
display: Display,
config: Config,
window: NativeWindowType,
attrib_list: Option<&[Int]>,
) -> Result<Surface, Error> { let attrib_list = match attrib_list {
Some(attrib_list) => {
check_int_list(attrib_list)?;
attrib_list.as_ptr()
}
None => ptr::null(),
};
let surface = self.api.eglCreateWindowSurface(
display.as_ptr(),
config.as_ptr(),
window,
attrib_list,
);
/// Get the list of all EGL frame buffer configurations for a display. /// /// The configurations are added to the `configs` buffer, up to the buffer's capacity. /// You can use [`get_config_count`](Self::get_config_count) to get the total number of available frame buffer configurations, /// and setup the buffer's capacity accordingly. /// /// ## Example /// ``` /// # extern crate khronos_egl as egl; /// # extern crate wayland_client; /// # fn main() -> Result<(), egl::Error> { /// # let egl = egl::Instance::new(egl::Static); /// # let wayland_display = wayland_client::Display::connect_to_env().expect("unable to connect to the wayland server"); /// # let display = unsafe { egl.get_display(wayland_display.get_display_ptr() as *mut std::ffi::c_void) }.unwrap(); /// # egl.initialize(display)?; /// let mut configs = Vec::with_capacity(egl.get_config_count(display)?); /// egl.get_configs(display, &mut configs); /// # Ok(()) /// # } /// ``` pubfn get_configs(
&self,
display: Display,
configs: &mut Vec<Config>,
) -> Result<(), Error> { let capacity = configs.capacity(); if capacity == 0 { // When the input ptr is null (when capacity is 0), // eglGetConfig behaves differently and returns the number // of configurations.
Ok(())
} else { unsafe { letmut count = 0;
/// Return the display for the current EGL rendering context. pubfn get_current_display(&self) -> Option<Display> { unsafe { let display = self.api.eglGetCurrentDisplay();
/// Return the read or draw surface for the current EGL rendering context. pubfn get_current_surface(&self, readdraw: Int) -> Option<Surface> { unsafe { let surface = self.api.eglGetCurrentSurface(readdraw);
/// Return an EGL display connection. /// /// # Safety /// /// The `native_display` must be a valid pointer to the native display. /// Valid values for platform are defined by EGL extensions, as are /// requirements for native_display. For example, an extension /// specification that defines support for the X11 platform may require /// that native_display be a pointer to an X11 Display, and an extension /// specification that defines support for the Microsoft Windows /// platform may require that native_display be a pointer to a Windows /// Device Context. pubunsafefn get_display(&self, display_id: NativeDisplayType) -> Option<Display> { let display = self.api.eglGetDisplay(display_id);
/// Return error information. /// /// Return the error of the last called EGL function in the current thread, or /// `None` if the error is set to `SUCCESS`. /// /// Note that since a call to `eglGetError` sets the error to `SUCCESS`, and /// since this function is automatically called by any wrapper function /// returning a `Result` when necessary, this function may only return `None` /// from the point of view of a user. pubfn get_error(&self) -> Option<Error> { unsafe { let e = self.api.eglGetError(); if e == SUCCESS {
None
} else {
Some(e.try_into().unwrap())
}
}
}
/// Return a GL or an EGL extension function. pubfn get_proc_address(&self, procname: &str) -> Option<extern"system"fn()> { unsafe { let string = CString::new(procname).unwrap();
let addr = self.api.eglGetProcAddress(string.as_ptr()); if !(addr as *const ()).is_null() {
Some(addr)
} else {
None
}
}
}
/// Initialize an EGL display connection. pubfn initialize(&self, display: Display) -> Result<(Int, Int), Error> { unsafe { letmut major = 0; letmut minor = 0;
pubconst BACK_BUFFER: Int = 0x3084; pubconst BIND_TO_TEXTURE_RGB: Int = 0x3039; pubconst BIND_TO_TEXTURE_RGBA: Int = 0x303A; pubconst CONTEXT_LOST: Int = 0x300E; pubconst MIN_SWAP_INTERVAL: Int = 0x303B; pubconst MAX_SWAP_INTERVAL: Int = 0x303C; pubconst MIPMAP_TEXTURE: Int = 0x3082; pubconst MIPMAP_LEVEL: Int = 0x3083; pubconst NO_TEXTURE: Int = 0x305C; pubconst TEXTURE_2D: Int = 0x305F; pubconst TEXTURE_FORMAT: Int = 0x3080; pubconst TEXTURE_RGB: Int = 0x305D; pubconst TEXTURE_RGBA: Int = 0x305E; pubconst TEXTURE_TARGET: Int = 0x3081;
/// Specifies the minimum number of video frame periods per buffer swap for the /// window associated with the current context. pubfn swap_interval(&self, display: Display, interval: Int) -> Result<(), Error> { unsafe { ifself.api.eglSwapInterval(display.as_ptr(), interval) == TRUE {
Ok(())
} else {
Err(self.get_error().unwrap())
}
}
}
}
}
impl ClientBuffer { /// Creates a new client buffer form its EGL pointer. /// /// # Safety /// /// `ptr` must be a valid `EGLClientBuffer` pointer. #[inline] pubunsafefn from_ptr(ptr: EGLClientBuffer) -> ClientBuffer {
ClientBuffer(ptr)
}
/// Query the current rendering API. pubfn query_api(&self) -> Enum { unsafe { self.api.eglQueryAPI() }
}
/// Create a new EGL pixel buffer surface bound to an OpenVG image. /// /// This will return a `BadParameter` error if `attrib_list` is not a valid /// attributes list (if it does not terminate with `NONE`). pubfn create_pbuffer_from_client_buffer(
&self,
display: Display,
buffer_type: Enum,
buffer: ClientBuffer,
config: Config,
attrib_list: &[Int],
) -> Result<Surface, Error> {
check_int_list(attrib_list)?; unsafe { let surface = self.api.eglCreatePbufferFromClientBuffer(
display.as_ptr(),
buffer_type,
buffer.as_ptr(),
config.as_ptr(),
attrib_list.as_ptr(),
);
impl Sync { /// Creates a new sync form its EGL pointer. /// /// # Safety /// /// `ptr` must be a valid `EGLSync` pointer. #[inline] pubunsafefn from_ptr(ptr: EGLSync) -> Sync {
Sync(ptr)
}
impl Image { /// Creates a new image form its EGL pointer. /// /// # Safety /// /// `ptr` must be a valid `EGLImage` pointer. #[inline] pubunsafefn from_ptr(ptr: EGLImage) -> Image {
Image(ptr)
}
pubconst CONTEXT_MAJOR_VERSION: Int = 0x3098; pubconst CONTEXT_MINOR_VERSION: Int = 0x30FB; pubconst CONTEXT_OPENGL_PROFILE_MASK: Int = 0x30FD; pubconst CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY: Int = 0x31BD; pubconst NO_RESET_NOTIFICATION: Int = 0x31BE; pubconst LOSE_CONTEXT_ON_RESET: Int = 0x31BF; pubconst CONTEXT_OPENGL_CORE_PROFILE_BIT: Int = 0x00000001; pubconst CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT: Int = 0x00000002; pubconst CONTEXT_OPENGL_DEBUG: Int = 0x31B0; pubconst CONTEXT_OPENGL_FORWARD_COMPATIBLE: Int = 0x31B1; pubconst CONTEXT_OPENGL_ROBUST_ACCESS: Int = 0x31B2; pubconst OPENGL_ES3_BIT: Int = 0x00000040; pubconst CL_EVENT_HANDLE: Int = 0x309C; pubconst SYNC_CL_EVENT: Int = 0x30FE; pubconst SYNC_CL_EVENT_COMPLETE: Int = 0x30FF; pubconst SYNC_PRIOR_COMMANDS_COMPLETE: Int = 0x30F0; pubconst SYNC_TYPE: Int = 0x30F7; pubconst SYNC_STATUS: Int = 0x30F1; pubconst SYNC_CONDITION: Int = 0x30F8; pubconst SIGNALED: Int = 0x30F2; pubconst UNSIGNALED: Int = 0x30F3; pubconst SYNC_FLUSH_COMMANDS_BIT: Int = 0x0001; pubconst FOREVER: u64 = 0xFFFFFFFFFFFFFFFFu64; pubconst TIMEOUT_EXPIRED: Int = 0x30F5; pubconst CONDITION_SATISFIED: Int = 0x30F6; pubconst NO_SYNC: EGLSync = 0as EGLSync; pubconst SYNC_FENCE: Int = 0x30F9; pubconst GL_COLORSPACE: Int = 0x309D; pubconst GL_COLORSPACE_SRGB: Int = 0x3089; pubconst GL_COLORSPACE_LINEAR: Int = 0x308A; pubconst GL_RENDERBUFFER: Int = 0x30B9; pubconst GL_TEXTURE_2D: Int = 0x30B1; pubconst GL_TEXTURE_LEVEL: Int = 0x30BC; pubconst GL_TEXTURE_3D: Int = 0x30B2; pubconst GL_TEXTURE_ZOFFSET: Int = 0x30BD; pubconst GL_TEXTURE_CUBE_MAP_POSITIVE_X: Int = 0x30B3; pubconst GL_TEXTURE_CUBE_MAP_NEGATIVE_X: Int = 0x30B4; pubconst GL_TEXTURE_CUBE_MAP_POSITIVE_Y: Int = 0x30B5; pubconst GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: Int = 0x30B6; pubconst GL_TEXTURE_CUBE_MAP_POSITIVE_Z: Int = 0x30B7; pubconst GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: Int = 0x30B8; pubconst IMAGE_PRESERVED: Int = 0x30D2; pubconst NO_IMAGE: EGLImage = 0as EGLImage;
impl<T: api::EGL1_5> Instance<T> { /// Create a new EGL sync object. /// /// Note that the constant `ATTRIB_NONE` which has the type `Attrib` can be used /// instead of `NONE` to terminate the attribute list. /// /// This will return a `BadParameter` error if `attrib_list` is not a valid /// attributes list (if it does not terminate with `ATTRIB_NONE`). /// /// # Safety /// /// When creating an OpenCL Event Sync Object, passing an invalid event /// handle in `attrib_list` may result in undefined behavior up to and including program /// termination. pubunsafefn create_sync(
&self,
display: Display,
ty: Enum,
attrib_list: &[Attrib],
) -> Result<Sync, Error> {
check_attrib_list(attrib_list)?; let sync = self
.api
.eglCreateSync(display.as_ptr(), ty, attrib_list.as_ptr()); if sync != NO_SYNC {
Ok(Sync(sync))
} else {
Err(self.get_error().unwrap())
}
}
/// Destroy a sync object. /// /// # Safety /// /// If display does not match the display passed to eglCreateSync when /// sync was created, the behaviour is undefined. pubunsafefn destroy_sync(&self, display: Display, sync: Sync) -> Result<(), Error> { ifself.api.eglDestroySync(display.as_ptr(), sync.as_ptr()) == TRUE {
Ok(())
} else {
Err(self.get_error().unwrap())
}
}
/// Wait in the client for a sync object to be signalled. /// /// # Safety /// /// If `display` does not match the [`Display`] passed to [`create_sync`](Self::create_sync) /// when `sync` was created, the behaviour is undefined. pubunsafefn client_wait_sync(
&self,
display: Display,
sync: Sync,
flags: Int,
timeout: Time,
) -> Result<Int, Error> { let status = self.api
.eglClientWaitSync(display.as_ptr(), sync.as_ptr(), flags, timeout); if status != FALSEas Int {
Ok(status)
} else {
Err(self.get_error().unwrap())
}
}
/// Return an attribute of a sync object. /// /// # Safety /// /// If `display` does not match the [`Display`] passed to [`create_sync`](Self::create_sync) /// when `sync` was created, behavior is undefined. pubunsafefn get_sync_attrib(
&self,
display: Display,
sync: Sync,
attribute: Int,
) -> Result<Attrib, Error> { letmut value = 0; ifself.api.eglGetSyncAttrib(
display.as_ptr(),
sync.as_ptr(),
attribute,
&mut value as *mut Attrib,
) == TRUE
{
Ok(value)
} else {
Err(self.get_error().unwrap())
}
}
/// Create a new Image object. /// /// Note that the constant `ATTRIB_NONE` which has the type `Attrib` can be used /// instead of `NONE` to terminate the attribute list. /// /// This will return a `BadParameter` error if `attrib_list` is not a valid /// attributes list (if it does not terminate with `ATTRIB_NONE`). pubfn create_image(
&self,
display: Display,
ctx: Context,
target: Enum,
buffer: ClientBuffer,
attrib_list: &[Attrib],
) -> Result<Image, Error> {
check_attrib_list(attrib_list)?; unsafe { let image = self.api.eglCreateImage(
display.as_ptr(),
ctx.as_ptr(),
target,
buffer.as_ptr(),
attrib_list.as_ptr(),
); if image != NO_IMAGE {
Ok(Image(image))
} else {
Err(self.get_error().unwrap())
}
}
}
/// Return an EGL display connection. /// /// Note that the constant `ATTRIB_NONE` which has the type `Attrib` can be used /// instead of `NONE` to terminate the attribute list. /// /// This will return a `BadParameter` error if `attrib_list` is not a valid /// attributes list (if it does not terminate with `ATTRIB_NONE`). /// /// # Safety /// /// The `native_display` must be a valid pointer to the native display. /// Valid values for platform are defined by EGL extensions, as are /// requirements for native_display. For example, an extension /// specification that defines support for the X11 platform may require /// that native_display be a pointer to an X11 Display, and an extension /// specification that defines support for the Microsoft Windows /// platform may require that native_display be a pointer to a Windows /// Device Context. pubunsafefn get_platform_display(
&self,
platform: Enum,
native_display: NativeDisplayType,
attrib_list: &[Attrib],
) -> Result<Display, Error> {
check_attrib_list(attrib_list)?;
let display = self.api
.eglGetPlatformDisplay(platform, native_display, attrib_list.as_ptr()); if display != NO_DISPLAY {
Ok(Display::from_ptr(display))
} else {
Err(self.get_error().unwrap())
}
}
/// Create a new EGL on-screen rendering surface. /// /// Note that the constant `ATTRIB_NONE` which has the type `Attrib` can be used /// instead of `NONE` to terminate the attribute list. /// /// This will return a `BadParameter` error if `attrib_list` is not a valid /// attributes list (if it does not terminate with `ATTRIB_NONE`). /// /// # Safety /// /// The `native_window` must be a valid pointer to the native window /// and must belong to the same platform as `display`. /// EGL considers the returned EGLSurface as belonging to that same platform. /// The EGL extension that defines the platform to which display belongs /// also defines the requirements for the `native_window` parameter. pubunsafefn create_platform_window_surface(
&self,
display: Display,
config: Config,
native_window: NativeWindowType,
attrib_list: &[Attrib],
) -> Result<Surface, Error> {
check_attrib_list(attrib_list)?;
/// Create a new EGL offscreen surface. /// /// Note that the constant `ATTRIB_NONE` which has the type `Attrib` can be used /// instead of `NONE` to terminate the attribute list. /// /// This will return a `BadParameter` error if `attrib_list` is not a valid /// attributes list (if it does not terminate with `ATTRIB_NONE`). /// /// # Safety /// /// The `native_pixmap` must be a valid pointer to a native pixmap. /// and must belong to the same platform as `display`. /// EGL considers the returned EGLSurface as belonging to that same platform. /// The EGL extension that defines the platform to which display belongs /// also defines the requirements for the `native_pixmap` parameter. pubunsafefn create_platform_pixmap_surface(
&self,
display: Display,
config: Config,
native_pixmap: NativePixmapType,
attrib_list: &[Attrib],
) -> Result<Surface, Error> {
check_attrib_list(attrib_list)?;
/// Wait in the server for a sync object to be signalled. /// /// This function is unsafe: if `display` does not match the [`Display`] passed to [`create_sync`](Self::create_sync) /// when `sync` was created, the behavior is undefined. pubfn wait_sync(&self, display: Display, sync: Sync, flags: Int) -> Result<(), Error> { unsafe { ifself.api.eglWaitSync(display.as_ptr(), sync.as_ptr(), flags) == TRUE {
Ok(())
} else {
Err(self.get_error().unwrap())
}
}
}
}
}
#[cfg(feature="static")] /// Static EGL API interface. /// /// This type is only available when the `static` feature is enabled, /// by statically linking the EGL library at compile time. #[derive(Copy, Clone, Debug)] pubstructStatic;
#[cfg(feature="static")] impl Api forStatic { #[inline(always)] fn version(&self) -> Version {
LATEST
}
}
#[inline(always)] /// Returns the EGL version. pubfn version(&self) -> Version { self.version
}
#[inline(always)] /// Sets the EGL version. pubunsafefn set_version(&mutself, version: Version) { self.version = version
}
/// Wraps the given library but does not load the symbols. pubunsafefn unloaded(lib: L, version: Version) -> Self {
RawDynamic {
lib,
version,
$(
$( #[cfg(feature=$version)]
$name : std::mem::MaybeUninit::uninit(),
)*
)*
}
}
}
#[cfg(feature="dynamic")] /// Dynamic EGL API interface. /// /// The first type parameter is the type of the underlying library handle. /// The second `Dynamic` type parameter gives the EGL API version provided by the library. /// /// This type is only available when the `dynamic` feature is enabled. /// In most cases, you may prefer to directly use the `DynamicInstance` type. pubstruct Dynamic<L, A> {
raw: RawDynamic<L>,
_api_version: std::marker::PhantomData<A>
}
#[cfg(feature="dynamic")] impl<L, A> Dynamic<L, A> { #[inline(always)] /// Return the underlying EGL library. pubfn library(&self) -> &L { self.raw.library()
}
/// Returns the provided EGL version. pubfn version(&self) -> Version { self.raw.version()
}
/// Wraps the given library but does not load the symbols. pub(crate) unsafefn unloaded(lib: L, version: Version) -> Self {
Dynamic {
raw: RawDynamic::unloaded(lib, version),
_api_version: std::marker::PhantomData
}
}
}
#[cfg(feature="dynamic")] impl<L, A> Api for Dynamic<L, A> { /// Returns the provided EGL version. #[inline(always)] fn version(&self) -> Version { self.version()
}
}
#[cfg(feature="dynamic")] #[cfg(feature="1_0")] impl<L: std::borrow::Borrow<libloading::Library>> Dynamic<L, EGL1_0> { #[inline] /// Load the EGL API symbols from the given library. /// /// This will load the most recent API provided by the library, /// which is at least EGL 1.0. /// You can check what version has actually been loaded using [`Dynamic::version`], /// and/or convert to a more recent version using [`try_into`](TryInto::try_into). /// /// ## Safety /// This is fundamentally unsafe since there are no guaranties the input library complies to the EGL API. pubunsafefn load_from(lib: L) -> Result<Dynamic<L, EGL1_0>, libloading::Error> { letmut result = Dynamic::unloaded(lib, Version::EGL1_0);
$( match $id::load_from(&mut result.raw) {
Ok(()) => result.raw.set_version(Version::$id),
Err(libloading::Error::DlSymUnknown) => { if Version::$id == Version::EGL1_0 { return Err(libloading::Error::DlSymUnknown) // we require at least EGL 1.0.
} else { return Ok(result)
}
},
Err(libloading::Error::DlSym { desc }) => { if Version::$id == Version::EGL1_0 { return Err(libloading::Error::DlSym { desc }) // we require at least EGL 1.0.
} else { return Ok(result)
}
},
Err(e) => return Err(e)
}
)*
Ok(result)
}
}
#[cfg(feature="dynamic")] #[cfg(feature="1_0")] impl<L: std::borrow::Borrow<libloading::Library>> Instance<Dynamic<L, EGL1_0>> { #[inline(always)] /// Create an EGL instance using the symbols provided by the given library. /// /// The most recent version of EGL provided by the given library is loaded. /// You can check what version has actually been loaded using [`Instance::version`], /// and/or convert to a more recent version using [`try_into`](TryInto::try_into). /// /// ## Safety /// This is fundamentally unsafe since there are no guaranties the input library complies to the EGL API. pubunsafefn load_from(lib: L) -> Result<Instance<Dynamic<L, EGL1_0>>, libloading::Error> {
Ok(Instance::new(Dynamic::<L, EGL1_0>::load_from(lib)?))
}
}
#[cfg(feature="dynamic")] #[cfg(feature="1_0")] impl DynamicInstance<EGL1_0> { #[inline(always)] /// Create an EGL instance by finding and loading a dynamic library with the given filename. /// /// See [`Library::new`](libloading::Library::new) /// for more details on how the `filename` argument is used. /// /// On Linux plateforms, the library is loaded with the `RTLD_NODELETE` flag. /// See [#14](https://github.com/timothee-haudebourg/khronos-egl/issues/14) for more details. /// /// ## Safety /// This is fundamentally unsafe since there are no guaranties the input library complies to the EGL API. pubunsafefn load_from_filename<P: AsRef<std::ffi::OsStr>>(filename: P) -> Result<DynamicInstance<EGL1_0>, libloading::Error> { #[cfg(target_os = "linux")] let lib: libloading::Library = { // On Linux, load library with `RTLD_NOW | RTLD_NODELETE` to fix a SIGSEGV // See https://github.com/timothee-haudebourg/khronos-egl/issues/14 for more details.
libloading::os::unix::Library::open(Some(filename), 0x2 | 0x1000)?.into()
}; #[cfg(not(target_os = "linux"))] let lib = libloading::Library::new(filename)?; Self::load_from(lib)
}
#[inline(always)] /// Create an EGL instance by finding and loading the `libEGL.so.1` or `libEGL.so` library. /// /// This is equivalent to `DynamicInstance::load_from_filename("libEGL.so.1")`. /// /// ## Safety /// This is fundamentally unsafe since there are no guaranties the found library complies to the EGL API. pubunsafefn load() -> Result<DynamicInstance<EGL1_0>, libloading::Error> { Self::load_from_filename("libEGL.so.1").or(Self::load_from_filename("libEGL.so"))
}
}
};
(@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 ;)* }) => { #[cfg(feature="static")] #[cfg(feature=$version)] unsafeimpl api::$id forStatic {
$( #[inline(always)] unsafefn $name(&self, $($arg : $atype),*) -> $rtype {
ffi::$name($($arg),*)
}
)*
}
#[cfg(feature="dynamic")] #[cfg(feature=$version)] /// EGL version type. /// /// Used by [`Dynamic`] to statically know the EGL API version provided by the library. pubstruct $id;
$( let name = stringify!($name).as_bytes(); let symbol = lib.get::<unsafeextern"system"fn($($atype ),*) -> $rtype>(name)?; #[cfg(unix)] let ptr = (&symbol.into_raw().into_raw()) as *const *mut _ as *constunsafeextern"system"fn($($atype ),*) -> $rtype; #[cfg(windows)] let ptr = (&symbol.into_raw().into_raw()) as *const _ as *constunsafeextern"system"fn($($atype ),*) -> $rtype;
assert!(!ptr.is_null());
raw.$name = std::mem::MaybeUninit::new(*ptr);
)*
#[cfg(feature="dynamic")] #[cfg(feature=$version)] impl<L: std::borrow::Borrow<libloading::Library>> AsRef<Dynamic<L, $pred>> for Dynamic<L, $id> { fn as_ref(&self) -> &Dynamic<L, $pred> { unsafe { std::mem::transmute(self) } // this is safe because both types have the same repr.
}
}
#[cfg(feature="dynamic")] #[cfg(feature=$version)] impl<L: std::borrow::Borrow<libloading::Library>> Downcast<Dynamic<L, $pred>> for Dynamic<L, $id> { fn downcast(&self) -> &Dynamic<L, $pred> { unsafe { std::mem::transmute(self) } // this is safe because both types have the same repr.
}
}
#[cfg(feature="dynamic")] #[cfg(feature=$version)] impl<L: std::borrow::Borrow<libloading::Library>> Downcast<Instance<Dynamic<L, $pred>>> for Instance<Dynamic<L, $id>> { fn downcast(&self) -> &Instance<Dynamic<L, $pred>> { unsafe { std::mem::transmute(self) } // this is safe because both types have the same repr.
}
}
#[cfg(feature="dynamic")] #[cfg(feature=$version)] impl<L: std::borrow::Borrow<libloading::Library>> Upcast<Dynamic<L, $id>> for Dynamic<L, $pred> { fn upcast(&self) -> Option<&Dynamic<L, $id>> { ifself.version() >= Version::$id {
Some(unsafe { std::mem::transmute(self) }) // this is safe because both types have the same repr.
} else {
None
}
}
}
#[cfg(feature="dynamic")] #[cfg(feature=$version)] impl<L: std::borrow::Borrow<libloading::Library>> Upcast<Instance<Dynamic<L, $id>>> for Instance<Dynamic<L, $pred>> { fn upcast(&self) -> Option<&Instance<Dynamic<L, $id>>> { ifself.version() >= Version::$id {
Some(unsafe { std::mem::transmute(self) }) // this is safe because both types have the same repr.
} else {
None
}
}
}
)*
#[cfg(feature="dynamic")] #[cfg(feature=$version)] impl<L: std::borrow::Borrow<libloading::Library>> Dynamic<L, $id> { #[inline] /// Load the EGL API symbols from the given library. /// /// The second `Dynamic` type parameter gives the EGL API version expected to be provided by the library. /// /// ## Safety /// This is fundamentally unsafe since there are no guaranties the input library complies to the EGL API. pubunsafefn load_required(lib: L) -> Result<Dynamic<L, $id>, LoadError<libloading::Error>> { match Dynamic::<L, EGL1_0>::load_from(lib) {
Ok(dynamic) => { let provided = dynamic.version(); match dynamic.try_into() {
Ok(t) => Ok(t),
Err(_) => Err(LoadError::InvalidVersion {
provided,
required: Version::$id
})
}
},
Err(e) => Err(LoadError::Library(e))
}
}
}
#[cfg(feature="dynamic")] #[cfg(feature=$version)] impl<L: std::borrow::Borrow<libloading::Library>> Instance<Dynamic<L, $id>> { #[inline(always)] /// Create an EGL instance using the symbols provided by the given library. /// This function fails if the EGL library does not provide the minimum required version given by the type parameter. /// /// ## Safety /// This is fundamentally unsafe since there are no guaranties the input library complies to the EGL API. pubunsafefn load_required_from(lib: L) -> Result<Instance<Dynamic<L, $id>>, LoadError<libloading::Error>> {
Ok(Instance::new(Dynamic::<L, $id>::load_required(lib)?))
}
}
#[cfg(feature="dynamic")] #[cfg(feature=$version)] impl DynamicInstance<$id> { #[inline(always)] /// Create an EGL instance by finding and loading a dynamic library with the given filename. /// This function fails if the EGL library does not provide the minimum required version given by the type parameter. /// /// See [`Library::new`](libloading::Library::new) /// for more details on how the `filename` argument is used. /// /// On Linux plateforms, the library is loaded with the `RTLD_NODELETE` flag. /// See [#14](https://github.com/timothee-haudebourg/khronos-egl/issues/14) for more details. /// /// ## Safety /// This is fundamentally unsafe since there are no guaranties the input library complies to the EGL API. pubunsafefn load_required_from_filename<P: AsRef<std::ffi::OsStr>>(filename: P) -> Result<DynamicInstance<$id>, LoadError<libloading::Error>> { #[cfg(target_os = "linux")] let lib: libloading::Library = { // On Linux, load library with `RTLD_NOW | RTLD_NODELETE` to fix a SIGSEGV // See https://github.com/timothee-haudebourg/khronos-egl/issues/14 for more details.
libloading::os::unix::Library::open(Some(filename), 0x2 | 0x1000).map_err(LoadError::Library)?.into()
}; #[cfg(not(target_os = "linux"))] let lib = libloading::Library::new(filename).map_err(LoadError::Library)?; Self::load_required_from(lib)
}
#[inline(always)] /// Create an EGL instance by finding and loading the `libEGL.so.1` or `libEGL.so` library. /// This function fails if the EGL library does not provide the minimum required version given by the type parameter. /// /// This is equivalent to `DynamicInstance::load_required_from_filename("libEGL.so.1")`. /// /// ## Safety /// This is fundamentally unsafe since there are no guaranties the found library complies to the EGL API. pubunsafefn load_required() -> Result<DynamicInstance<$id>, LoadError<libloading::Error>> { Self::load_required_from_filename("libEGL.so.1").or(Self::load_required_from_filename("libEGL.so"))
}
}
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.