diff --git a/Cargo.toml b/Cargo.toml index 1d92f4f0..48a82c26 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "offscreen_gl_context" license = "MIT / Apache-2.0" -version = "0.8.4" +version = "0.8.5" authors = ["Emilio Cobos Álvarez ", "The Servo Project Developers"] description = "Creation and manipulation of HW accelerated offscreen rendering contexts in multiple platforms. Originally intended for the Servo project's WebGL implementation." repository = "https://github.com/emilio/rust-offscreen-rendering-context" @@ -14,7 +14,7 @@ gl_generator = "0.5" default = ["x11"] osmesa = ["osmesa-sys"] # NOTE: Just for testing use, there are no other changes -test_egl_in_linux = [] +test_egl_in_linux = ["libloading", "lazy_static"] [dependencies] log = "0.3" @@ -22,6 +22,8 @@ gleam = "0.4" euclid = "0.11" serde = { version = "0.9", optional = true } osmesa-sys = { version = "0.1", optional = true } +libloading = { version = "0.3", optional = true } +lazy_static = { version = "0.2", optional = true } [target.x86_64-apple-darwin.dependencies] core-foundation = "0.3.0" @@ -38,5 +40,8 @@ gdi32-sys = "0.2" user32-sys = "0.2" kernel32-sys = "0.2" -[target.'cfg(any(target_os="macos", target_os="windows"))'.dependencies] +[target.'cfg(any(target_os="macos", target_os="windows", target_os="android"))'.dependencies] lazy_static = "0.2" + +[target.'cfg(target_os = "android")'.dependencies] +libloading = "0.3" \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 3ec44227..b368cafa 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -23,9 +23,11 @@ extern crate kernel32; extern crate gdi32; #[cfg(target_os = "windows")] extern crate user32; -#[cfg(any(target_os="macos", target_os="windows"))] +#[cfg(any(target_os="macos", target_os="windows", target_os="android", feature="test_egl_in_linux"))] #[macro_use] extern crate lazy_static; +#[cfg(any(target_os="android", feature="test_egl_in_linux"))] +extern crate libloading; mod platform; pub use platform::{NativeGLContext, NativeGLContextMethods, NativeGLContextHandle}; diff --git a/src/platform/with_egl/native_gl_context.rs b/src/platform/with_egl/native_gl_context.rs index 698ed5c9..9e85fdea 100644 --- a/src/platform/with_egl/native_gl_context.rs +++ b/src/platform/with_egl/native_gl_context.rs @@ -2,9 +2,20 @@ use euclid::Size2D; use platform::NativeGLContextMethods; use platform::with_egl::utils::{create_pixel_buffer_backed_offscreen_context}; use std::ffi::CString; +use std::ops::Deref; use egl; use egl::types::{EGLint, EGLBoolean, EGLDisplay, EGLSurface, EGLConfig, EGLContext}; +use libloading as lib; +lazy_static! { + static ref GL_LIB: Option = { + if cfg!(target_os = "android") { + lib::Library::new("libGLESv2.so").ok() + } else { + lib::Library::new("libGL.so").ok() + } + }; +} pub struct NativeGLContextHandle(pub EGLDisplay, pub EGLSurface); unsafe impl Send for NativeGLContextHandle {} @@ -69,10 +80,21 @@ impl Drop for NativeGLContext { impl NativeGLContextMethods for NativeGLContext { type Handle = NativeGLContextHandle; + // According to the EGL spec <= 1.4, eglGetProcAddress should only be used to + // retrieve extension functions. Some implementatios return NULL for core OpenGL functions. + // Other implementations may return non-NULL values even for invalid core or extension symbols. + // This is very dangerous, so we use dlsym function before calling eglGetProcAddress + // in order to avoid possible garbage pointers. fn get_proc_address(addr: &str) -> *const () { unsafe { - let addr = CString::new(addr.as_bytes()).unwrap().as_ptr(); - egl::GetProcAddress(addr as *const _) as *const () + if let Some(ref lib) = *GL_LIB { + let symbol: lib::Symbol = lib.get(addr.as_bytes()).unwrap(); + return *symbol.deref() as *const(); + } + + let addr = CString::new(addr.as_bytes()); + let addr = addr.unwrap().as_ptr(); + egl::GetProcAddress(addr) as *const () } }