diff --git a/Cargo.lock b/Cargo.lock index ad6ac5e8268..02dab6a7194 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3965,6 +3965,7 @@ dependencies = [ "core-foundation 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "gl_generator 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libloading 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "libservo 0.0.1", "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/ports/libsimpleservo/api/Cargo.toml b/ports/libsimpleservo/api/Cargo.toml index 031dc1fca19..11e6f03ee5f 100644 --- a/ports/libsimpleservo/api/Cargo.toml +++ b/ports/libsimpleservo/api/Cargo.toml @@ -20,6 +20,9 @@ core-foundation = "0.6" [target.'cfg(target_os = "windows")'.dependencies] winapi = "0.3.2" +[target.'cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd"))'.dependencies] +libloading = "0.5" + [build-dependencies] gl_generator = "0.10" diff --git a/ports/libsimpleservo/api/build.rs b/ports/libsimpleservo/api/build.rs index 711cf1a96d0..de216c650d1 100644 --- a/ports/libsimpleservo/api/build.rs +++ b/ports/libsimpleservo/api/build.rs @@ -5,15 +5,16 @@ use gl_generator::{Api, Fallbacks, Profile, Registry}; use std::env; use std::fs::File; -use std::path::Path; +use std::path::PathBuf; fn main() { let target = env::var("TARGET").unwrap(); + let dest = PathBuf::from(&env::var("OUT_DIR").unwrap()); + // Generate GL bindings // For now, we only support EGL, and only on Windows and Android. if target.contains("android") || target.contains("windows") { - let dest = env::var("OUT_DIR").unwrap(); - let mut file = File::create(&Path::new(&dest).join("egl_bindings.rs")).unwrap(); + let mut file = File::create(&dest.join("egl_bindings.rs")).unwrap(); if target.contains("android") { Registry::new(Api::Egl, (1, 5), Profile::Core, Fallbacks::All, []) .write_bindings(gl_generator::StaticStructGenerator, &mut file) @@ -25,4 +26,15 @@ fn main() { .unwrap(); }; } + + if target.contains("linux") || + target.contains("dragonfly") || + target.contains("freebsd") || + target.contains("openbsd") + { + let mut file = File::create(&dest.join("glx_bindings.rs")).unwrap(); + Registry::new(Api::Glx, (1, 4), Profile::Core, Fallbacks::All, []) + .write_bindings(gl_generator::StructGenerator, &mut file) + .unwrap(); + } } diff --git a/ports/libsimpleservo/api/src/gl_glue.rs b/ports/libsimpleservo/api/src/gl_glue.rs index bc8c3ddb1b7..945cad97636 100644 --- a/ports/libsimpleservo/api/src/gl_glue.rs +++ b/ports/libsimpleservo/api/src/gl_glue.rs @@ -75,7 +75,7 @@ pub mod egl { } } -#[cfg(any(target_os = "windows", target_os = "linux"))] +#[cfg(target_os = "windows")] pub mod gl { pub fn init() -> Result { unimplemented!(); @@ -110,3 +110,45 @@ pub mod gl { Ok(gl) } } + +#[cfg(any( + target_os = "linux", + target_os = "dragonfly", + target_os = "freebsd", + target_os = "openbsd" +))] +pub mod gl { + use libloading::{Library, Symbol}; + use servo::gl::GlFns; + use std::ffi::CString; + use std::os::raw::c_void; + + pub fn init() -> Result { + info!("Loading OpenGL"); + + pub mod glx { + include!(concat!(env!("OUT_DIR"), "/glx_bindings.rs")); + } + + let lib = match Library::new("libGL.so.1").or_else(|_| Library::new("libGL.so")) { + Ok(lib) => lib, + Err(_) => return Err("Can't find libGL.so, OpenGL isn't configured/installed"), + }; + + let glx = glx::Glx::load_with(|sym| unsafe { + let symbol: Symbol<*const c_void> = lib.get(sym.as_bytes()).unwrap(); + *symbol.into_raw() + }); + + let gl = unsafe { + GlFns::load_with(|addr| { + let addr = CString::new(addr.as_bytes()).unwrap(); + glx.GetProcAddress(addr.as_ptr() as *const _) as *const _ + }) + }; + + info!("OpenGL is loaded"); + + Ok(gl) + } +}