From 0417f7003f133fbef63e8e9d98d305368b1eed47 Mon Sep 17 00:00:00 2001 From: Pierre Krieger Date: Sat, 25 Apr 2015 22:14:30 +0200 Subject: [PATCH] Allow using EGL with X11 --- build.rs | 8 ++++++++ src/api/dlopen.rs | 14 ++++++++++++++ src/api/egl/ffi.rs | 8 +------- src/api/egl/mod.rs | 2 +- src/api/mod.rs | 1 + src/api/x11/mod.rs | 29 ++++++++++++++++++++--------- 6 files changed, 45 insertions(+), 17 deletions(-) create mode 100644 src/api/dlopen.rs diff --git a/build.rs b/build.rs index ca955743..4f96710a 100644 --- a/build.rs +++ b/build.rs @@ -58,6 +58,14 @@ fn main() { "GLX_SGI_swap_control".to_string() ], "1.4", "core", &mut file).unwrap(); + + let mut file = File::create(&dest.join("egl_bindings.rs")).unwrap(); + gl_generator::generate_bindings(gl_generator::StructGenerator, + gl_generator::registry::Ns::Egl, + gl_generator::Fallbacks::All, + khronos_api::EGL_XML, + vec![], + "1.5", "core", &mut file).unwrap(); } if target.contains("android") { diff --git a/src/api/dlopen.rs b/src/api/dlopen.rs new file mode 100644 index 00000000..63f690af --- /dev/null +++ b/src/api/dlopen.rs @@ -0,0 +1,14 @@ +#![cfg(target_os = "linux")] + +use libc; + +pub const RTLD_LAZY: libc::c_int = 0x001; +pub const RTLD_NOW: libc::c_int = 0x002; + +#[link="dl"] +extern { + pub fn dlopen(filename: *const libc::c_char, flag: libc::c_int) -> *mut libc::c_void; + pub fn dlerror() -> *mut libc::c_char; + pub fn dlsym(handle: *mut libc::c_void, symbol: *const libc::c_char) -> *mut libc::c_void; + pub fn dlclose(handle: *mut libc::c_void) -> libc::c_int; +} diff --git a/src/api/egl/ffi.rs b/src/api/egl/ffi.rs index e3cf32ed..8e2528dc 100644 --- a/src/api/egl/ffi.rs +++ b/src/api/egl/ffi.rs @@ -2,8 +2,6 @@ use libc; #[cfg(target_os = "windows")] extern crate winapi; -#[cfg(target_os = "linux")] -use api::x11::ffi; #[cfg(target_os = "android")] use api::android::ffi; @@ -32,10 +30,6 @@ pub type EGLNativePixmapType = *const libc::c_void; // FIXME: egl_native_pix #[cfg(target_os = "windows")] pub type EGLNativeWindowType = winapi::HWND; #[cfg(target_os = "linux")] -pub type EGLNativeWindowType = ffi::Window; +pub type EGLNativeWindowType = *const libc::c_void; #[cfg(target_os = "android")] pub type EGLNativeWindowType = *const ffi::ANativeWindow; - -#[cfg(not(target_os = "windows"))] -#[link(name = "EGL")] -extern {} diff --git a/src/api/egl/mod.rs b/src/api/egl/mod.rs index d9ac313c..fdea2cd3 100644 --- a/src/api/egl/mod.rs +++ b/src/api/egl/mod.rs @@ -1,4 +1,4 @@ -#![cfg(all(target_os = "windows", target_os = "linux"))] // always false of the moment +#![cfg(target_os = "linux")] use BuilderAttribs; use CreationError; diff --git a/src/api/mod.rs b/src/api/mod.rs index c71c2397..34ef01dc 100644 --- a/src/api/mod.rs +++ b/src/api/mod.rs @@ -1,5 +1,6 @@ pub mod android; pub mod cocoa; +pub mod dlopen; pub mod egl; pub mod glx; pub mod osmesa; diff --git a/src/api/x11/mod.rs b/src/api/x11/mod.rs index 0bb5c881..3dd90d3c 100644 --- a/src/api/x11/mod.rs +++ b/src/api/x11/mod.rs @@ -6,6 +6,7 @@ use CreationError::OsError; use libc; use std::{mem, ptr}; use std::cell::Cell; +use std::ffi::CString; use std::sync::atomic::AtomicBool; use std::collections::VecDeque; use std::sync::{Arc, Mutex, Once, ONCE_INIT}; @@ -15,7 +16,9 @@ use CursorState; use GlRequest; use PixelFormat; +use api::dlopen; use api::glx::Context as GlxContext; +use api::egl::Context as EglContext; pub use self::monitor::{MonitorID, get_available_monitors, get_primary_monitor}; @@ -64,6 +67,7 @@ pub struct XWindow { pub enum Context { Glx(GlxContext), + Egl(EglContext), None, } @@ -543,10 +547,17 @@ impl Window { Context::Glx(try!(GlxContext::new(builder, display, window, fb_config, visual_infos))) }, - /*GlRequest::Specific(Api::OpenGlEs, _) => { - let egl = ::egl::ffi::egl::Egl; - Context::Egl(try!(EglContext::new(egl, builder, Some(display as *const _), window))) - },*/ + GlRequest::Specific(Api::OpenGlEs, _) => { + let libegl = unsafe { dlopen::dlopen(b"libEGL.so\0".as_ptr() as *const _, dlopen::RTLD_NOW) }; + if libegl.is_null() { + return Err(CreationError::NotSupported); + } + let egl = ::api::egl::ffi::egl::Egl::load_with(|sym| { + let sym = CString::new(sym).unwrap(); + unsafe { dlopen::dlsym(libegl, sym.as_ptr()) } + }); + Context::Egl(try!(EglContext::new(egl, builder, Some(display as *const _), unsafe { mem::transmute(window) }))) + }, GlRequest::Specific(_, _) => { return Err(CreationError::NotSupported); }, @@ -666,7 +677,7 @@ impl Window { pub unsafe fn make_current(&self) { match self.x.context { Context::Glx(ref ctxt) => ctxt.make_current(), - //Context::Egl(ref ctxt) => ctxt.make_current(), + Context::Egl(ref ctxt) => ctxt.make_current(), Context::None => {} } } @@ -674,7 +685,7 @@ impl Window { pub fn is_current(&self) -> bool { match self.x.context { Context::Glx(ref ctxt) => ctxt.is_current(), - //Context::Egl(ref ctxt) => ctxt.is_current(), + Context::Egl(ref ctxt) => ctxt.is_current(), Context::None => panic!() } } @@ -682,7 +693,7 @@ impl Window { pub fn get_proc_address(&self, addr: &str) -> *const () { match self.x.context { Context::Glx(ref ctxt) => ctxt.get_proc_address(addr), - //Context::Egl(ref ctxt) => ctxt.get_proc_address(addr), + Context::Egl(ref ctxt) => ctxt.get_proc_address(addr), Context::None => ptr::null() } } @@ -690,7 +701,7 @@ impl Window { pub fn swap_buffers(&self) { match self.x.context { Context::Glx(ref ctxt) => ctxt.swap_buffers(), - //Context::Egl(ref ctxt) => ctxt.swap_buffers(), + Context::Egl(ref ctxt) => ctxt.swap_buffers(), Context::None => {} } } @@ -707,7 +718,7 @@ impl Window { pub fn get_api(&self) -> ::Api { match self.x.context { Context::Glx(ref ctxt) => ctxt.get_api(), - //Context::Egl(ref ctxt) => ctxt.get_api(), + Context::Egl(ref ctxt) => ctxt.get_api(), Context::None => panic!() } }