Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use the EGL API with Android #417

Merged
merged 1 commit into from
May 1, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ fn main() {

if target.contains("android") {
let mut file = File::create(&dest.join("egl_bindings.rs")).unwrap();
gl_generator::generate_bindings(gl_generator::StaticGenerator,
gl_generator::generate_bindings(gl_generator::StaticStructGenerator,
gl_generator::registry::Ns::Egl,
gl_generator::Fallbacks::All,
khronos_api::EGL_XML, vec![],
Expand Down
23 changes: 0 additions & 23 deletions src/api/android/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,29 +5,6 @@

use libc;

pub mod egl {
pub type khronos_utime_nanoseconds_t = super::khronos_utime_nanoseconds_t;
pub type khronos_uint64_t = super::khronos_uint64_t;
pub type khronos_ssize_t = super::khronos_ssize_t;
pub type EGLNativeDisplayType = super::EGLNativeDisplayType;
pub type EGLNativePixmapType = super::EGLNativePixmapType;
pub type EGLNativeWindowType = super::EGLNativeWindowType;
pub type EGLint = super::EGLint;
pub type NativeDisplayType = super::EGLNativeDisplayType;
pub type NativePixmapType = super::EGLNativePixmapType;
pub type NativeWindowType = super::EGLNativeWindowType;

include!(concat!(env!("OUT_DIR"), "/egl_bindings.rs"));
}

pub type khronos_utime_nanoseconds_t = khronos_uint64_t;
pub type khronos_uint64_t = libc::uint64_t;
pub type khronos_ssize_t = libc::c_long;
pub type EGLint = libc::int32_t;
pub type EGLNativeDisplayType = *const libc::c_void;
pub type EGLNativePixmapType = *const libc::c_void; // FIXME: egl_native_pixmap_t instead
pub type EGLNativeWindowType = *const ANativeWindow;

#[link(name = "android")]
#[link(name = "EGL")]
#[link(name = "GLESv2")]
Expand Down
226 changes: 35 additions & 191 deletions src/api/android/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,24 @@ use std::collections::VecDeque;
use Api;
use BuilderAttribs;
use CursorState;
use GlContext;
use GlRequest;
use PixelFormat;
use native_monitor::NativeMonitorId;

use api::egl;
use api::egl::Context as EglContext;

pub struct Window {
display: ffi::egl::types::EGLDisplay,
context: ffi::egl::types::EGLContext,
surface: ffi::egl::types::EGLSurface,
context: EglContext,
event_rx: Receiver<android_glue::Event>,
}

pub struct MonitorID;

mod ffi;

pub fn get_available_monitors() -> VecDeque <MonitorID> {
pub fn get_available_monitors() -> VecDeque<MonitorID> {
let mut rb = VecDeque::new();
rb.push_back(MonitorID);
rb
Expand All @@ -55,41 +57,6 @@ impl MonitorID {
}
}

#[cfg(feature = "headless")]
pub struct HeadlessContext(i32);

#[cfg(feature = "headless")]
impl HeadlessContext {
/// See the docs in the crate root file.
pub fn new(_builder: BuilderAttribs) -> Result<HeadlessContext, CreationError> {
unimplemented!()
}

/// See the docs in the crate root file.
pub unsafe fn make_current(&self) {
unimplemented!()
}

/// See the docs in the crate root file.
pub fn is_current(&self) -> bool {
unimplemented!()
}

/// See the docs in the crate root file.
pub fn get_proc_address(&self, _addr: &str) -> *const () {
unimplemented!()
}

pub fn get_api(&self) -> ::Api {
::Api::OpenGlEs
}
}

#[cfg(feature = "headless")]
unsafe impl Send for HeadlessContext {}
#[cfg(feature = "headless")]
unsafe impl Sync for HeadlessContext {}

pub struct PollEventsIterator<'a> {
window: &'a Window,
}
Expand Down Expand Up @@ -138,125 +105,19 @@ impl Window {
pub fn new(builder: BuilderAttribs) -> Result<Window, CreationError> {
use std::{mem, ptr};

if builder.sharing.is_some() {
unimplemented!()
}

let native_window = unsafe { android_glue::get_native_window() };
if native_window.is_null() {
return Err(OsError(format!("Android's native window is null")));
}

let display = unsafe {
let display = ffi::egl::GetDisplay(mem::transmute(ffi::egl::DEFAULT_DISPLAY));
if display.is_null() {
return Err(OsError("No EGL display connection available".to_string()));
}
display
};

android_glue::write_log("eglGetDisplay succeeded");

let (_major, _minor) = unsafe {
let mut major: ffi::egl::types::EGLint = mem::uninitialized();
let mut minor: ffi::egl::types::EGLint = mem::uninitialized();

if ffi::egl::Initialize(display, &mut major, &mut minor) == 0 {
return Err(OsError(format!("eglInitialize failed")))
}

(major, minor)
};

android_glue::write_log("eglInitialize succeeded");

let use_gles2 = match builder.gl_version {
GlRequest::Specific(Api::OpenGlEs, (2, _)) => true,
GlRequest::Specific(Api::OpenGlEs, _) => false,
GlRequest::Specific(_, _) => panic!("Only OpenGL ES is supported"), // FIXME: return a result
GlRequest::GlThenGles { opengles_version: (2, _), .. } => true,
_ => false,
};

let mut attribute_list = vec!();

if use_gles2 {
attribute_list.push(ffi::egl::RENDERABLE_TYPE as i32);
attribute_list.push(ffi::egl::OPENGL_ES2_BIT as i32);
}

{
let (red, green, blue) = match builder.color_bits.unwrap_or(24) {
24 => (8, 8, 8),
16 => (6, 5, 6),
_ => panic!("Bad color_bits"),
};
attribute_list.push(ffi::egl::RED_SIZE as i32);
attribute_list.push(red);
attribute_list.push(ffi::egl::GREEN_SIZE as i32);
attribute_list.push(green);
attribute_list.push(ffi::egl::BLUE_SIZE as i32);
attribute_list.push(blue);
}

attribute_list.push(ffi::egl::DEPTH_SIZE as i32);
attribute_list.push(builder.depth_bits.unwrap_or(8) as i32);

attribute_list.push(ffi::egl::NONE as i32);

let config = unsafe {
let mut num_config: ffi::egl::types::EGLint = mem::uninitialized();
let mut config: ffi::egl::types::EGLConfig = mem::uninitialized();
if ffi::egl::ChooseConfig(display, attribute_list.as_ptr(), &mut config, 1,
&mut num_config) == 0
{
return Err(OsError(format!("eglChooseConfig failed")))
}

if num_config <= 0 {
return Err(OsError(format!("eglChooseConfig returned no available config")))
}

config
};

android_glue::write_log("eglChooseConfig succeeded");

let context = unsafe {
let mut context_attributes = vec!();
if use_gles2 {
context_attributes.push(ffi::egl::CONTEXT_CLIENT_VERSION as i32);
context_attributes.push(2);
}
context_attributes.push(ffi::egl::NONE as i32);

let context = ffi::egl::CreateContext(display, config, ptr::null(),
context_attributes.as_ptr());
if context.is_null() {
return Err(OsError(format!("eglCreateContext failed")))
}
context
};

android_glue::write_log("eglCreateContext succeeded");

let surface = unsafe {
let surface = ffi::egl::CreateWindowSurface(display, config, native_window, ptr::null());
if surface.is_null() {
return Err(OsError(format!("eglCreateWindowSurface failed")))
}
surface
};

android_glue::write_log("eglCreateWindowSurface succeeded");
let context = try!(EglContext::new(egl::ffi::egl::Egl, builder, None,
native_window as *const _));

let (tx, rx) = channel();
android_glue::add_sender(tx);

Ok(Window {
display: display,
context: context,
surface: surface,
event_rx: rx,
})
}
Expand Down Expand Up @@ -317,42 +178,14 @@ impl Window {
}
}

pub fn make_current(&self) {
unsafe {
ffi::egl::MakeCurrent(self.display, self.surface, self.surface, self.context);
}
}

pub fn is_current(&self) -> bool {
unsafe { ffi::egl::GetCurrentContext() == self.context }
}

pub fn get_proc_address(&self, addr: &str) -> *const () {
let addr = CString::new(addr.as_bytes()).unwrap();
let addr = addr.as_ptr();
unsafe {
ffi::egl::GetProcAddress(addr) as *const ()
}
}

pub fn swap_buffers(&self) {
unsafe {
ffi::egl::SwapBuffers(self.display, self.surface);
}
}

pub fn platform_display(&self) -> *mut libc::c_void {
self.display as *mut libc::c_void
unimplemented!();
}

pub fn platform_window(&self) -> *mut libc::c_void {
unimplemented!()
}

pub fn get_api(&self) -> ::Api {
::Api::OpenGlEs
}

pub fn get_pixel_format(&self) -> PixelFormat {
unimplemented!();
}
Expand All @@ -379,6 +212,32 @@ impl Window {
unsafe impl Send for Window {}
unsafe impl Sync for Window {}

impl GlContext for Window {
unsafe fn make_current(&self) {
self.context.make_current()
}

fn is_current(&self) -> bool {
self.context.is_current()
}

fn get_proc_address(&self, addr: &str) -> *const libc::c_void {
self.context.get_proc_address(addr)
}

fn swap_buffers(&self) {
self.context.swap_buffers()
}

fn get_api(&self) -> Api {
self.context.get_api()
}

fn get_pixel_format(&self) -> PixelFormat {
self.context.get_pixel_format()
}
}

#[cfg(feature = "window")]
#[derive(Clone)]
pub struct WindowProxy;
Expand All @@ -388,18 +247,3 @@ impl WindowProxy {
unimplemented!()
}
}

impl Drop for Window {
fn drop(&mut self) {
use std::ptr;

unsafe {
// we don't call MakeCurrent(0, 0) because we are not sure that the context
// is still the current one
android_glue::write_log("Destroying gl-init window");
ffi::egl::DestroySurface(self.display, self.surface);
ffi::egl::DestroyContext(self.display, self.context);
ffi::egl::Terminate(self.display);
}
}
}
4 changes: 1 addition & 3 deletions src/api/egl/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ use libc;

#[cfg(target_os = "windows")]
extern crate winapi;
#[cfg(target_os = "android")]
use api::android::ffi;

pub mod egl {
pub type khronos_utime_nanoseconds_t = super::khronos_utime_nanoseconds_t;
Expand Down Expand Up @@ -32,4 +30,4 @@ pub type EGLNativeWindowType = winapi::HWND;
#[cfg(target_os = "linux")]
pub type EGLNativeWindowType = *const libc::c_void;
#[cfg(target_os = "android")]
pub type EGLNativeWindowType = *const ffi::ANativeWindow;
pub type EGLNativeWindowType = *const libc::c_void;
2 changes: 1 addition & 1 deletion src/api/egl/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#![cfg(target_os = "linux")]
#![cfg(any(target_os = "linux", target_os = "android"))]

use BuilderAttribs;
use CreationError;
Expand Down
35 changes: 35 additions & 0 deletions src/platform/android/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,38 @@
#![cfg(target_os = "android")]

pub use api::android::*;

#[cfg(feature = "headless")]
pub struct HeadlessContext(i32);

#[cfg(feature = "headless")]
impl HeadlessContext {
/// See the docs in the crate root file.
pub fn new(_builder: BuilderAttribs) -> Result<HeadlessContext, CreationError> {
unimplemented!()
}

/// See the docs in the crate root file.
pub unsafe fn make_current(&self) {
unimplemented!()
}

/// See the docs in the crate root file.
pub fn is_current(&self) -> bool {
unimplemented!()
}

/// See the docs in the crate root file.
pub fn get_proc_address(&self, _addr: &str) -> *const () {
unimplemented!()
}

pub fn get_api(&self) -> ::Api {
::Api::OpenGlEs
}
}

#[cfg(feature = "headless")]
unsafe impl Send for HeadlessContext {}
#[cfg(feature = "headless")]
unsafe impl Sync for HeadlessContext {}