From e1b2c88c83897f7aa9194bac6debb699ceaf02b3 Mon Sep 17 00:00:00 2001 From: Drakulix Date: Sat, 9 Dec 2017 17:32:22 +0100 Subject: [PATCH] Use global gl_generator generator --- Cargo.toml | 1 + build.rs | 3 +- src/backend/graphics/egl.rs | 124 ++++++++++++++++++------------------ src/lib.rs | 3 + 4 files changed, 68 insertions(+), 63 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index b50c13d..0c850db 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,6 +25,7 @@ rental = "0.4.11" wayland-protocols = { version = "0.12.0", features = ["unstable_protocols", "server"] } image = "0.17.0" error-chain = "0.11.0" +lazy_static = "1.0.0" [build-dependencies] gl_generator = "0.5" diff --git a/build.rs b/build.rs index 4692ccd..7b556f9 100644 --- a/build.rs +++ b/build.rs @@ -29,7 +29,8 @@ fn main() { "EGL_MESA_platform_gbm", "EGL_EXT_platform_wayland", "EGL_EXT_platform_device", + "EGL_KHR_image_base", ], - ).write_bindings(gl_generator::StructGenerator, &mut file) + ).write_bindings(gl_generator::GlobalGenerator, &mut file) .unwrap(); } diff --git a/src/backend/graphics/egl.rs b/src/backend/graphics/egl.rs index 296422b..42f59e8 100644 --- a/src/backend/graphics/egl.rs +++ b/src/backend/graphics/egl.rs @@ -8,7 +8,6 @@ use super::GraphicsBackend; #[cfg(feature = "backend_drm")] use gbm::{AsRaw, Device as GbmDevice, Surface as GbmSurface}; -use libloading::Library; use nix::libc::{c_int, c_void}; use rental::TryNewError; use slog; @@ -26,7 +25,7 @@ use winit::Window as WinitWindow; #[cfg(feature = "backend_winit")] use winit::os::unix::WindowExt; -#[allow(non_camel_case_types, dead_code)] +#[allow(non_camel_case_types, dead_code, unused_mut)] mod ffi { use nix::libc::{c_long, c_void, int32_t, uint64_t}; @@ -43,6 +42,16 @@ mod ffi { pub mod egl { use super::*; + use libloading::Library; + use std::sync::{Once, ONCE_INIT}; + + lazy_static! { + pub static ref LIB: Library = { + Library::new("libEGL.so.1").expect("Failed to load LibEGL") + }; + } + + pub static LOAD: Once = ONCE_INIT; include!(concat!(env!("OUT_DIR"), "/egl_bindings.rs")); } @@ -222,10 +231,8 @@ unsafe impl NativeSurface for () { /// EGL context for rendering pub struct EGLContext<'a, T: NativeSurface> { - _lib: Library, context: ffi::egl::types::EGLContext, display: ffi::egl::types::EGLDisplay, - egl: ffi::egl::Egl, config_id: ffi::egl::types::EGLConfig, surface_attributes: Vec, pixel_format: PixelFormat, @@ -329,20 +336,20 @@ impl<'a, T: NativeSurface> EGLContext<'a, T> { } }; - trace!(log, "Loading libEGL"); - let lib = Library::new("libEGL.so.1").chain_err(|| ErrorKind::LoadingEGLFailed)?; - let egl = ffi::egl::Egl::load_with(|sym| { - let name = CString::new(sym).unwrap(); - let symbol = lib.get::<*mut c_void>(name.as_bytes()); - match symbol { - Ok(x) => *x as *const _, - Err(_) => ptr::null(), - } + ffi::egl::LOAD.call_once(|| { + ffi::egl::load_with(|sym| { + let name = CString::new(sym).unwrap(); + let symbol = ffi::egl::LIB.get::<*mut c_void>(name.as_bytes()); + match symbol { + Ok(x) => *x as *const _, + Err(_) => ptr::null(), + } + }); }); // the first step is to query the list of extensions without any display, if supported let dp_extensions = { - let p = egl.QueryString(ffi::egl::NO_DISPLAY, ffi::egl::EXTENSIONS as i32); + let p = ffi::egl::QueryString(ffi::egl::NO_DISPLAY, ffi::egl::EXTENSIONS as i32); // this possibility is available only with EGL 1.5 or EGL_EXT_platform_base, otherwise // `eglQueryString` returns an error @@ -361,48 +368,48 @@ impl<'a, T: NativeSurface> EGLContext<'a, T> { let display = match native { NativeDisplayPtr::X11(display) - if has_dp_extension("EGL_KHR_platform_x11") && egl.GetPlatformDisplay.is_loaded() => + if has_dp_extension("EGL_KHR_platform_x11") && ffi::egl::GetPlatformDisplay::is_loaded() => { trace!(log, "EGL Display Initialization via EGL_KHR_platform_x11"); - egl.GetPlatformDisplay(ffi::egl::PLATFORM_X11_KHR, display as *mut _, ptr::null()) + ffi::egl::GetPlatformDisplay(ffi::egl::PLATFORM_X11_KHR, display as *mut _, ptr::null()) } NativeDisplayPtr::X11(display) - if has_dp_extension("EGL_EXT_platform_x11") && egl.GetPlatformDisplayEXT.is_loaded() => + if has_dp_extension("EGL_EXT_platform_x11") && ffi::egl::GetPlatformDisplayEXT::is_loaded() => { trace!(log, "EGL Display Initialization via EGL_EXT_platform_x11"); - egl.GetPlatformDisplayEXT(ffi::egl::PLATFORM_X11_EXT, display as *mut _, ptr::null()) + ffi::egl::GetPlatformDisplayEXT(ffi::egl::PLATFORM_X11_EXT, display as *mut _, ptr::null()) } NativeDisplayPtr::Gbm(display) - if has_dp_extension("EGL_KHR_platform_gbm") && egl.GetPlatformDisplay.is_loaded() => + if has_dp_extension("EGL_KHR_platform_gbm") && ffi::egl::GetPlatformDisplay::is_loaded() => { trace!(log, "EGL Display Initialization via EGL_KHR_platform_gbm"); - egl.GetPlatformDisplay(ffi::egl::PLATFORM_GBM_KHR, display as *mut _, ptr::null()) + ffi::egl::GetPlatformDisplay(ffi::egl::PLATFORM_GBM_KHR, display as *mut _, ptr::null()) } NativeDisplayPtr::Gbm(display) - if has_dp_extension("EGL_MESA_platform_gbm") && egl.GetPlatformDisplayEXT.is_loaded() => + if has_dp_extension("EGL_MESA_platform_gbm") && ffi::egl::GetPlatformDisplayEXT::is_loaded() => { trace!(log, "EGL Display Initialization via EGL_MESA_platform_gbm"); - egl.GetPlatformDisplayEXT(ffi::egl::PLATFORM_GBM_MESA, display as *mut _, ptr::null()) + ffi::egl::GetPlatformDisplayEXT(ffi::egl::PLATFORM_GBM_MESA, display as *mut _, ptr::null()) } NativeDisplayPtr::Gbm(display) - if has_dp_extension("EGL_MESA_platform_gbm") && egl.GetPlatformDisplay.is_loaded() => + if has_dp_extension("EGL_MESA_platform_gbm") && ffi::egl::GetPlatformDisplay::is_loaded() => { trace!(log, "EGL Display Initialization via EGL_MESA_platform_gbm"); - egl.GetPlatformDisplay(ffi::egl::PLATFORM_GBM_MESA, display as *mut _, ptr::null()) + ffi::egl::GetPlatformDisplay(ffi::egl::PLATFORM_GBM_MESA, display as *mut _, ptr::null()) } NativeDisplayPtr::Wayland(display) - if has_dp_extension("EGL_KHR_platform_wayland") && egl.GetPlatformDisplay.is_loaded() => + if has_dp_extension("EGL_KHR_platform_wayland") && ffi::egl::GetPlatformDisplay::is_loaded() => { trace!( log, "EGL Display Initialization via EGL_KHR_platform_wayland" ); - egl.GetPlatformDisplay( + ffi::egl::GetPlatformDisplay( ffi::egl::PLATFORM_WAYLAND_KHR, display as *mut _, ptr::null(), @@ -410,13 +417,13 @@ impl<'a, T: NativeSurface> EGLContext<'a, T> { } NativeDisplayPtr::Wayland(display) - if has_dp_extension("EGL_EXT_platform_wayland") && egl.GetPlatformDisplayEXT.is_loaded() => + if has_dp_extension("EGL_EXT_platform_wayland") && ffi::egl::GetPlatformDisplayEXT::is_loaded() => { trace!( log, "EGL Display Initialization via EGL_EXT_platform_wayland" ); - egl.GetPlatformDisplayEXT( + ffi::egl::GetPlatformDisplayEXT( ffi::egl::PLATFORM_WAYLAND_EXT, display as *mut _, ptr::null(), @@ -427,7 +434,7 @@ impl<'a, T: NativeSurface> EGLContext<'a, T> { | NativeDisplayPtr::Gbm(display) | NativeDisplayPtr::Wayland(display) => { trace!(log, "Default EGL Display Initialization via GetDisplay"); - egl.GetDisplay(display as *mut _) + ffi::egl::GetDisplay(display as *mut _) } }; @@ -440,7 +447,7 @@ impl<'a, T: NativeSurface> EGLContext<'a, T> { let mut major: ffi::egl::types::EGLint = mem::uninitialized(); let mut minor: ffi::egl::types::EGLint = mem::uninitialized(); - if egl.Initialize(display, &mut major, &mut minor) == 0 { + if ffi::egl::Initialize(display, &mut major, &mut minor) == 0 { bail!(ErrorKind::InitFailed); } @@ -453,7 +460,7 @@ impl<'a, T: NativeSurface> EGLContext<'a, T> { // the list of extensions supported by the client once initialized is different from the // list of extensions obtained earlier let extensions = if egl_version >= (1, 2) { - let p = CStr::from_ptr(egl.QueryString(display, ffi::egl::EXTENSIONS as i32)); + let p = CStr::from_ptr(ffi::egl::QueryString(display, ffi::egl::EXTENSIONS as i32)); let list = String::from_utf8(p.to_bytes().to_vec()).unwrap_or_else(|_| String::new()); list.split(' ').map(|e| e.to_string()).collect::>() } else { @@ -462,7 +469,7 @@ impl<'a, T: NativeSurface> EGLContext<'a, T> { info!(log, "EGL Extensions: {:?}", extensions); - if egl_version >= (1, 2) && egl.BindAPI(ffi::egl::OPENGL_ES_API) == 0 { + if egl_version >= (1, 2) && ffi::egl::BindAPI(ffi::egl::OPENGL_ES_API) == 0 { error!( log, "OpenGLES not supported by the underlying EGL implementation" @@ -587,7 +594,7 @@ impl<'a, T: NativeSurface> EGLContext<'a, T> { // calling `eglChooseConfig` let mut config_id = mem::uninitialized(); let mut num_configs = mem::uninitialized(); - if egl.ChooseConfig( + if ffi::egl::ChooseConfig( display, descriptor.as_ptr(), &mut config_id, @@ -604,10 +611,10 @@ impl<'a, T: NativeSurface> EGLContext<'a, T> { // analyzing each config macro_rules! attrib { - ($egl:expr, $display:expr, $config:expr, $attr:expr) => ( + ($display:expr, $config:expr, $attr:expr) => ( { let mut value = mem::uninitialized(); - let res = $egl.GetConfigAttrib($display, $config, + let res = ffi::egl::GetConfigAttrib($display, $config, $attr as ffi::egl::types::EGLint, &mut value); if res == 0 { bail!(ErrorKind::ConfigFailed); @@ -618,17 +625,17 @@ impl<'a, T: NativeSurface> EGLContext<'a, T> { }; let desc = PixelFormat { - hardware_accelerated: attrib!(egl, display, config_id, ffi::egl::CONFIG_CAVEAT) + hardware_accelerated: attrib!(display, config_id, ffi::egl::CONFIG_CAVEAT) != ffi::egl::SLOW_CONFIG as i32, - color_bits: attrib!(egl, display, config_id, ffi::egl::RED_SIZE) as u8 - + attrib!(egl, display, config_id, ffi::egl::BLUE_SIZE) as u8 - + attrib!(egl, display, config_id, ffi::egl::GREEN_SIZE) as u8, - alpha_bits: attrib!(egl, display, config_id, ffi::egl::ALPHA_SIZE) as u8, - depth_bits: attrib!(egl, display, config_id, ffi::egl::DEPTH_SIZE) as u8, - stencil_bits: attrib!(egl, display, config_id, ffi::egl::STENCIL_SIZE) as u8, + color_bits: attrib!(display, config_id, ffi::egl::RED_SIZE) as u8 + + attrib!(display, config_id, ffi::egl::BLUE_SIZE) as u8 + + attrib!(display, config_id, ffi::egl::GREEN_SIZE) as u8, + alpha_bits: attrib!(display, config_id, ffi::egl::ALPHA_SIZE) as u8, + depth_bits: attrib!(display, config_id, ffi::egl::DEPTH_SIZE) as u8, + stencil_bits: attrib!(display, config_id, ffi::egl::STENCIL_SIZE) as u8, stereoscopy: false, double_buffer: true, - multisampling: match attrib!(egl, display, config_id, ffi::egl::SAMPLES) { + multisampling: match attrib!(display, config_id, ffi::egl::SAMPLES) { 0 | 1 => None, a => Some(a as u16), }, @@ -664,10 +671,10 @@ impl<'a, T: NativeSurface> EGLContext<'a, T> { context_attributes.push(ffi::egl::NONE as i32); trace!(log, "Creating EGL context..."); - let context = egl.CreateContext(display, config_id, ptr::null(), context_attributes.as_ptr()); + let context = ffi::egl::CreateContext(display, config_id, ptr::null(), context_attributes.as_ptr()); if context.is_null() { - match egl.GetError() as u32 { + match ffi::egl::GetError() as u32 { ffi::egl::BAD_ATTRIBUTE => bail!(ErrorKind::CreationFailed), err_no => bail!(ErrorKind::Unknown(err_no)), } @@ -698,10 +705,8 @@ impl<'a, T: NativeSurface> EGLContext<'a, T> { info!(log, "EGL context created"); Ok(EGLContext { - _lib: lib, context: context as *const _, display: display as *const _, - egl: egl, config_id: config_id, surface_attributes: surface_attributes, pixel_format: desc, @@ -723,7 +728,7 @@ impl<'a, T: NativeSurface> EGLContext<'a, T> { let (surface, keep) = native.surface(self.backend_type)?; let egl_surface = unsafe { - self.egl.CreateWindowSurface( + ffi::egl::CreateWindowSurface( self.display, self.config_id, match surface { @@ -755,12 +760,12 @@ impl<'a, T: NativeSurface> EGLContext<'a, T> { pub unsafe fn get_proc_address(&self, symbol: &str) -> *const c_void { let addr = CString::new(symbol.as_bytes()).unwrap(); let addr = addr.as_ptr(); - self.egl.GetProcAddress(addr) as *const _ + ffi::egl::GetProcAddress(addr) as *const _ } /// Returns true if the OpenGL context is the current one in the thread. pub fn is_current(&self) -> bool { - unsafe { self.egl.GetCurrentContext() == self.context as *const _ } + unsafe { ffi::egl::GetCurrentContext() == self.context as *const _ } } /// Returns the pixel format of the main framebuffer of the context. @@ -777,9 +782,8 @@ impl<'a, T: NativeSurface> Drop for EGLContext<'a, T> { unsafe { // we don't call MakeCurrent(0, 0) because we are not sure that the context // is still the current one - self.egl - .DestroyContext(self.display as *const _, self.context as *const _); - self.egl.Terminate(self.display as *const _); + ffi::egl::DestroyContext(self.display as *const _, self.context as *const _); + ffi::egl::Terminate(self.display as *const _); } } } @@ -809,13 +813,11 @@ impl<'context, 'surface, T: NativeSurface> EGLSurface<'context, 'surface, T> { /// Swaps buffers at the end of a frame. pub fn swap_buffers(&self) -> ::std::result::Result<(), SwapBuffersError> { let ret = unsafe { - self.context - .egl - .SwapBuffers(self.context.display as *const _, self.surface as *const _) + ffi::egl::SwapBuffers(self.context.display as *const _, self.surface as *const _) }; if ret == 0 { - match unsafe { self.context.egl.GetError() } as u32 { + match unsafe { ffi::egl::GetError() } as u32 { ffi::egl::CONTEXT_LOST => Err(SwapBuffersError::ContextLost), err => Err(SwapBuffersError::Unknown(err)), } @@ -831,7 +833,7 @@ impl<'context, 'surface, T: NativeSurface> EGLSurface<'context, 'surface, T> { /// This function is marked unsafe, because the context cannot be made current /// on multiple threads. pub unsafe fn make_current(&self) -> ::std::result::Result<(), SwapBuffersError> { - let ret = self.context.egl.MakeCurrent( + let ret = ffi::egl::MakeCurrent( self.context.display as *const _, self.surface as *const _, self.surface as *const _, @@ -839,7 +841,7 @@ impl<'context, 'surface, T: NativeSurface> EGLSurface<'context, 'surface, T> { ); if ret == 0 { - match self.context.egl.GetError() as u32 { + match ffi::egl::GetError() as u32 { ffi::egl::CONTEXT_LOST => Err(SwapBuffersError::ContextLost), err => panic!("eglMakeCurrent failed (eglGetError returned 0x{:x})", err), } @@ -863,9 +865,7 @@ unsafe impl<'a, 'b, T: NativeSurface> Sync for EGLSurface<'a, 'b, T> {} impl<'a, 'b, T: NativeSurface> Drop for EGLSurface<'a, 'b, T> { fn drop(&mut self) { unsafe { - self.context - .egl - .DestroySurface(self.context.display as *const _, self.surface as *const _); + ffi::egl::DestroySurface(self.context.display as *const _, self.surface as *const _); } } } diff --git a/src/lib.rs b/src/lib.rs index a69d09f..2e1efeb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -48,6 +48,9 @@ extern crate slog_stdlog; #[macro_use] extern crate error_chain; +#[macro_use] +extern crate lazy_static; + pub mod backend; pub mod wayland; pub mod utils;