From f4530066552a4e9f05d80881e792cb05587a8e23 Mon Sep 17 00:00:00 2001 From: ecoal95 Date: Sun, 7 Jun 2015 04:00:36 +0200 Subject: [PATCH] Preliminary android support Blocked on https://github.com/servo/rust-egl/pull/16 --- Cargo.toml | 3 + src/lib.rs | 2 + src/platform/mod.rs | 5 +- src/platform/with_egl/mod.rs | 13 +--- src/platform/with_egl/native_gl_context.rs | 86 ++++++++++------------ src/platform/with_egl/utils.rs | 49 +++++++----- 6 files changed, 79 insertions(+), 79 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 9537b0d..432a958 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -46,3 +46,6 @@ features = ["xlib"] [target.arm-unknown-linux-gnueabihf.dependencies.x11] version = "*" features = ["xlib"] + +[target.arm-linux-androideabi.dependencies.egl] +git = "https://github.com/servo/rust-egl" diff --git a/src/lib.rs b/src/lib.rs index 994ebae..f8b111c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -10,6 +10,8 @@ extern crate glx; extern crate cgl; #[cfg(target_os="macos")] extern crate core_foundation; +#[cfg(target_os="android")] +extern crate egl; mod platform; pub use platform::{NativeGLContext, NativeGLContextMethods}; diff --git a/src/platform/mod.rs b/src/platform/mod.rs index 220b46f..0ef5d69 100644 --- a/src/platform/mod.rs +++ b/src/platform/mod.rs @@ -34,12 +34,11 @@ pub mod with_cgl; #[cfg(target_os="macos")] pub use self::with_cgl::NativeGLContext; - #[cfg(target_os="android")] -pub mod not_implemented; +pub mod with_egl; #[cfg(target_os="android")] -pub use self::not_implemented::NativeGLContext; +pub use self::with_egl::NativeGLContext; // TODO(ecoal95): Get a machine to test with mac and // get android building: diff --git a/src/platform/with_egl/mod.rs b/src/platform/with_egl/mod.rs index 4809bba..fac4744 100644 --- a/src/platform/with_egl/mod.rs +++ b/src/platform/with_egl/mod.rs @@ -2,12 +2,7 @@ mod native_gl_context; mod utils; pub use self::native_gl_context::NativeGLContext; -// The last three zeros arw for workaround buggy implementations -macro_rules! egl_end_workarounding_bugs { - () => {{ - egl::NONE, 0, 0, 0, - }} -} - - - +// NB: The last three zeros in egl attributes after the egl::EGL_NONE +// are a workaround for workaround buggy implementations. +// Also, when we compare a createxx call with zero, it's equivalent to +// compare it with egl::EGL_NO_XX diff --git a/src/platform/with_egl/native_gl_context.rs b/src/platform/with_egl/native_gl_context.rs index ac8adc0..89579c1 100644 --- a/src/platform/with_egl/native_gl_context.rs +++ b/src/platform/with_egl/native_gl_context.rs @@ -1,48 +1,46 @@ -use std::ffi::CString; use geom::Size2D; -use NativeGLContextMethods; +use platform::NativeGLContextMethods; use platform::with_egl::utils::{create_pixel_buffer_backed_offscreen_context}; +use egl::egl::{self, EGLint, EGLDisplay, EGLSurface, EGLConfig, EGLContext}; pub struct NativeGLContext { + native_display: EGLDisplay, native_surface: EGLSurface, - native_config: EGLConfig, native_context: EGLContext, - is_offscreen: bool } impl NativeGLContext { pub fn new(share_context: Option<&NativeGLContext>, - is_offscreen: bool, - surface: EGLSurface, - config: EGLConfig) + display: EGLDisplay, + surface: EGLSurface, + config: EGLConfig) -> Result { + let shared = match share_context { Some(ctx) => ctx.as_native_egl_context(), - None => egl::NO_CONTEXT + None => egl::EGL_NO_CONTEXT as EGLContext, }; - let mut attributes = [ - egl::CONTEXT_CLIENT_VERSION, 2, - egl_end_workarounding_bugs!() + let attributes = [ + egl::EGL_CONTEXT_CLIENT_VERSION as EGLint, 2, + egl::EGL_NONE as EGLint, 0, 0, 0, // see mod.rs ]; + let ctx = egl::CreateContext(display, config, shared, attributes.as_ptr()); - unsafe { - let native = egl::CreateContext(egl::Display(), config, shared, attributes.as_mut_ptr()); - - if native == 0 { - egl::DestroySurface(surface); - return Err("Error creating native EGL Context"); - } - - Ok(NativeGLContext { - native_surface: surface, - native_config: config, - native_context: native, - is_offscreen: is_offscreen - }) + // TODO: Check for every type of error possible, not just client error? + // Note if we do it we must do it too on egl::CreatePBufferSurface, etc... + if ctx == (egl::EGL_NO_CONTEXT as EGLContext) { + egl::DestroySurface(display, surface); + return Err("Error creating an EGL context"); } + + Ok(NativeGLContext { + native_display: display, + native_surface: surface, + native_context: ctx, + }) } #[inline(always)] @@ -53,12 +51,11 @@ impl NativeGLContext { impl NativeGLContextMethods for NativeGLContext { - fn get_proc_address(addr: &str) -> *const () { - let addr = CString::new(s.as_bytes()).unwrap(); - let addr = addr.as_ptr(); - unsafe { - egl::GetProcAddress(addr as *const _) as *const () - } + fn get_proc_address(_addr: &str) -> *const () { + // TODO: add eglGetProcAddress to rust-egl? + // let addr = CString::new(addr.as_bytes()).unwrap().as_ptr(); + // egl::GetProcAddress(addr as *const _) as *const () + 0 as *const () } fn create_headless() -> Result { @@ -67,25 +64,20 @@ impl NativeGLContextMethods for NativeGLContext { create_pixel_buffer_backed_offscreen_context(Size2D(16, 16)) } - fn create_offscreen(size: Size2D) -> Result { - let context = try!(create_headless(size)); - - try!(context.init_offscreen(size)); - - Ok(()) + #[inline(always)] + fn is_current(&self) -> bool { + egl::GetCurrentContext() == self.native_context } fn make_current(&self) -> Result<(), &'static str> { - unsafe { - if egl::GetCurrentContext() != self.native_context && - egl::MakeCurrent(self.native_display, - self.native_surface, - self.native_surface, - self.native_context) == egl::FALSE { - Err("egl::MakeCurrent") - } else { - Ok(()) - } + if !self.is_current() && + egl::MakeCurrent(self.native_display, + self.native_surface, + self.native_surface, + self.native_context) == egl::EGL_FALSE { + Err("egl::MakeCurrent") + } else { + Ok(()) } } } diff --git a/src/platform/with_egl/utils.rs b/src/platform/with_egl/utils.rs index 1824da0..d80cd79 100644 --- a/src/platform/with_egl/utils.rs +++ b/src/platform/with_egl/utils.rs @@ -1,38 +1,47 @@ -use egl; +use egl::egl::{self, EGLNativeDisplayType, EGLDisplay, EGLConfig, EGLSurface, EGLint}; use std::mem; use geom::Size2D; +use super::NativeGLContext; -fn create_pbuffer_surface(config: EGLConfig, size: Size2D) -> Result { +fn create_pbuffer_surface(display: EGLDisplay, config: EGLConfig, size: Size2D) -> Result { let mut attrs = [ - egl::WIDTH, size.width as EGLInt, - egl::HEIGHT, size.heigh as EGLInt, - egl_end_workarounding_bugs!() + egl::EGL_WIDTH as EGLint, size.width as EGLint, + egl::EGL_HEIGHT as EGLint, size.height as EGLint, + egl::EGL_NONE as EGLint, 0, 0, 0, // see mod.rs ]; - let surface = unsafe { egl::CreatePBufferSurface(egl::Display(), config, attrs.as_mut_ptr()) }; + let surface = unsafe { egl::CreatePbufferSurface(display, config, &mut *attrs.as_mut_ptr()) }; - if surface == 0 { + if surface == (egl::EGL_NO_SURFACE as EGLSurface) { return Err("egl::CreatePBufferSurface"); } Ok(surface) } -fn create_pixel_buffer_backed_offscreen_context(size: Size2D) -> Result { - let mut attributes = [ - egl::SURFACE_TYPE, egl::PBUFFER_BIT, - egl::RENDERABLE_TYPE, egl::OPENGL_ES2_BIT, - egl::RED_SIZE, 8, - egl::GREEN_SIZE, 8, - egl::BLUE_SIZE, 8, - egl::ALPHA_SIZE, 0, - egl_end_workarounding_bugs!() +pub fn create_pixel_buffer_backed_offscreen_context(size: Size2D) -> Result { + let attributes = [ + egl::EGL_SURFACE_TYPE as EGLint, egl::EGL_PBUFFER_BIT as EGLint, + egl::EGL_RENDERABLE_TYPE as EGLint, egl::EGL_OPENGL_ES2_BIT as EGLint, + egl::EGL_RED_SIZE as EGLint, 8, + egl::EGL_GREEN_SIZE as EGLint, 8, + egl::EGL_BLUE_SIZE as EGLint, 8, + egl::EGL_ALPHA_SIZE as EGLint, 0, + egl::EGL_NONE as EGLint, 0, 0, 0, // see mod.rs ]; - let config : EGLConfig = unsafe { mem::uninitialized() }; + // TODO: Check if we should use `egl::GetCurrentDisplay` instead + let display = egl::GetDisplay(egl::EGL_DEFAULT_DISPLAY as EGLNativeDisplayType); + + if display == (egl::EGL_NO_DISPLAY as EGLDisplay) { + return Err("egl::GetDisplay"); + } + + + let mut config : EGLConfig = unsafe { mem::uninitialized() }; let mut found_configs : EGLint = 0; - if egl::ChooseConfig(egl::Display(), attributes.as_mut_ptr(), &mut config, 1, &mut found_configs) == 0 { + if egl::ChooseConfig(display, attributes.as_ptr(), &mut config, 1, &mut found_configs) == 0 { return Err("egl::ChooseConfig"); } @@ -40,7 +49,7 @@ fn create_pixel_buffer_backed_offscreen_context(size: Size2D) -> Result