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

Error compiling to Android with cargo apk #1307 #1385

Closed
wants to merge 6 commits into from
Closed
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
4 changes: 2 additions & 2 deletions glutin/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ default = ["x11", "wayland", "wayland-dlopen"]

[dependencies]
lazy_static = "1.3"
winit = { version = "0.26", default-features = false }
winit = { git = "https://github.com/Kaiser1989/winit", default-features = false }

[target.'cfg(target_os = "android")'.dependencies]
android_glue = "0.2"
ndk-glue = "0.5.0"
glutin_egl_sys = { version = "0.1.5", path = "../glutin_egl_sys" }
parking_lot = "0.11"

Expand Down
28 changes: 15 additions & 13 deletions glutin/src/api/android/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::api::egl::{Context as EglContext, NativeDisplay, SurfaceType as EglSu
use crate::CreationError::{self, OsError};
use crate::{Api, ContextError, GlAttributes, PixelFormat, PixelFormatRequirements, Rect};

use crate::platform::android::EventLoopExtAndroid;
//use crate::platform::android::EventLoopExtAndroid;
use glutin_egl_sys as ffi;
use parking_lot::Mutex;
use winit;
Expand All @@ -26,8 +26,8 @@ pub struct Context(Arc<AndroidContext>);
#[derive(Debug)]
struct AndroidSyncEventHandler(Arc<AndroidContext>);

impl android_glue::SyncEventHandler for AndroidSyncEventHandler {
fn handle(&mut self, event: &android_glue::Event) {
/*impl ndk_glue::SyncEventHandler for AndroidSyncEventHandler {
fn handle(&mut self, event: &ndk_glue::Event) {
match *event {
// 'on_surface_destroyed' Android event can arrive with some delay
// because multithreading communication. Because of
Expand All @@ -36,7 +36,7 @@ impl android_glue::SyncEventHandler for AndroidSyncEventHandler {
// surface already destroyed. EGL generates a BAD_SURFACE error in
// this situation. Set stop to true to prevent
// swap_buffer call race conditions.
android_glue::Event::TermWindow => {
ndk_glue::Event::TermWindow => {
let mut stopped = self.0.stopped.as_ref().unwrap().lock();
*stopped = true;
}
Expand All @@ -45,7 +45,7 @@ impl android_glue::SyncEventHandler for AndroidSyncEventHandler {
}
};
}
}
}*/

impl Context {
#[inline]
Expand All @@ -57,23 +57,25 @@ impl Context {
) -> Result<(winit::window::Window, Self), CreationError> {
let win = wb.build(el)?;
let gl_attr = gl_attr.clone().map_sharing(|c| &c.0.egl_context);
let nwin = unsafe { android_glue::get_native_window() };
if nwin.is_null() {
let nwin = ndk_glue::native_window();
if nwin.is_none() {
return Err(OsError("Android's native window is null".to_string()));
}
let native_display = NativeDisplay::Android;
let egl_context =
EglContext::new(pf_reqs, &gl_attr, native_display, EglSurfaceType::Window, |c, _| {
Ok(c[0])
})
.and_then(|p| p.finish(nwin as *const _))?;
.and_then(|p| p.finish(nwin.as_ref().unwrap().ptr().as_ptr() as *const _))?;
let ctx = Arc::new(AndroidContext { egl_context, stopped: Some(Mutex::new(false)) });

let handler = Box::new(AndroidSyncEventHandler(ctx.clone()));
android_glue::add_sync_event_handler(handler);
// TODO: With `ndk-glue` we cannot directly register handlers in such manner, so we want work around it in different way.

//let handler = Box::new(AndroidSyncEventHandler(ctx.clone()));
//android_glue::add_sync_event_handler(handler);
let context = Context(ctx.clone());

el.set_suspend_callback(Some(Box::new(move |suspended| {
/*el.set_suspend_callback(Some(Box::new(move |suspended| {
let mut stopped = ctx.stopped.as_ref().unwrap().lock();
*stopped = suspended;
if suspended {
Expand All @@ -86,11 +88,11 @@ impl Context {
// Android has started the activity or sent it to foreground.
// Restore the EGL surface and animation loop.
unsafe {
let nwin = android_glue::get_native_window();
let nwin = ndk_glue::native_window();
ctx.egl_context.on_surface_created(nwin as *const _);
}
}
})));
})));*/

Ok((win, context))
}
Expand Down
96 changes: 46 additions & 50 deletions glutin/src/api/egl/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,8 +176,8 @@ pub struct Context {
surface: Option<Mutex<ffi::egl::types::EGLSurface>>,
api: Api,
pixel_format: PixelFormat,
#[cfg(target_os = "android")]
config_id: ffi::egl::types::EGLConfig,
// #[cfg(target_os = "android")]
// config_id: ffi::egl::types::EGLConfig,
}

#[cfg(target_os = "android")]
Expand Down Expand Up @@ -541,47 +541,47 @@ impl Context {
// Android has started the activity or sent it to foreground.
// Create a new surface and attach it to the recreated ANativeWindow.
// Restore the EGLContext.
#[cfg(target_os = "android")]
pub unsafe fn on_surface_created(&self, nwin: ffi::EGLNativeWindowType) {
let egl = EGL.as_ref().unwrap();
let mut surface = self.surface.as_ref().unwrap().lock();
if *surface != ffi::egl::NO_SURFACE {
return;
}
*surface = egl.CreateWindowSurface(self.display, self.config_id, nwin, std::ptr::null());
if surface.is_null() {
panic!("on_surface_created: eglCreateWindowSurface failed with 0x{:x}", egl.GetError())
}
let ret = egl.MakeCurrent(self.display, *surface, *surface, self.context);
if ret == 0 {
panic!("on_surface_created: eglMakeCurrent failed with 0x{:x}", egl.GetError())
}
}
// #[cfg(target_os = "android")]
// pub unsafe fn on_surface_created(&self, nwin: ffi::EGLNativeWindowType) {
// let egl = EGL.as_ref().unwrap();
// let mut surface = self.surface.as_ref().unwrap().lock();
// if *surface != ffi::egl::NO_SURFACE {
// return;
// }
// *surface = egl.CreateWindowSurface(self.display, self.config_id, nwin, std::ptr::null());
// if surface.is_null() {
// panic!("on_surface_created: eglCreateWindowSurface failed with 0x{:x}", egl.GetError())
// }
// let ret = egl.MakeCurrent(self.display, *surface, *surface, self.context);
// if ret == 0 {
// panic!("on_surface_created: eglMakeCurrent failed with 0x{:x}", egl.GetError())
// }
// }

// Handle Android Life Cycle.
// Android has stopped the activity or sent it to background.
// Release the surface attached to the destroyed ANativeWindow.
// The EGLContext is not destroyed so it can be restored later.
#[cfg(target_os = "android")]
pub unsafe fn on_surface_destroyed(&self) {
let egl = EGL.as_ref().unwrap();
let mut surface = self.surface.as_ref().unwrap().lock();
if *surface == ffi::egl::NO_SURFACE {
return;
}
let ret = egl.MakeCurrent(
self.display,
ffi::egl::NO_SURFACE,
ffi::egl::NO_SURFACE,
ffi::egl::NO_CONTEXT,
);
if ret == 0 {
panic!("on_surface_destroyed: eglMakeCurrent failed with 0x{:x}", egl.GetError())
}

egl.DestroySurface(self.display, *surface);
*surface = ffi::egl::NO_SURFACE;
}
// #[cfg(target_os = "android")]
// pub unsafe fn on_surface_destroyed(&self) {
// let egl = EGL.as_ref().unwrap();
// let mut surface = self.surface.as_ref().unwrap().lock();
// if *surface == ffi::egl::NO_SURFACE {
// return;
// }
// let ret = egl.MakeCurrent(
// self.display,
// ffi::egl::NO_SURFACE,
// ffi::egl::NO_SURFACE,
// ffi::egl::NO_CONTEXT,
// );
// if ret == 0 {
// panic!("on_surface_destroyed: eglMakeCurrent failed with 0x{:x}", egl.GetError())
// }

// egl.DestroySurface(self.display, *surface);
// *surface = ffi::egl::NO_SURFACE;
// }

#[inline]
pub fn get_proc_address(&self, addr: &str) -> *const core::ffi::c_void {
Expand All @@ -602,12 +602,7 @@ impl Context {
let ret = unsafe { egl.SwapBuffers(self.display, *surface) };

if ret == 0 {
match unsafe { egl.GetError() } as u32 {
ffi::egl::CONTEXT_LOST => return Err(ContextError::ContextLost),
err => {
panic!("swap_buffers: eglSwapBuffers failed (eglGetError returned 0x{:x})", err)
}
}
Err(ContextError::ContextLost)
} else {
Ok(())
}
Expand All @@ -618,9 +613,9 @@ impl Context {
pub fn swap_buffers_with_damage(&self, rects: &[Rect]) -> Result<(), ContextError> {
let egl = EGL.as_ref().unwrap();

if !egl.SwapBuffersWithDamageKHR.is_loaded() {
/*if !egl.SwapBuffersWithDamageKHR.is_loaded() {
return Err(ContextError::FunctionUnavailable);
}
}*/

let surface = self.surface.as_ref().unwrap().lock();
if *surface == ffi::egl::NO_SURFACE {
Expand Down Expand Up @@ -660,8 +655,9 @@ impl Context {
#[inline]
#[cfg(not(target_os = "windows"))]
pub fn swap_buffers_with_damage_supported(&self) -> bool {
let egl = EGL.as_ref().unwrap();
egl.SwapBuffersWithDamageKHR.is_loaded()
//let egl = EGL.as_ref().unwrap();
//egl.SwapBuffersWithDamageKHR.is_loaded()
true
}

#[inline]
Expand Down Expand Up @@ -995,8 +991,8 @@ impl<'a> ContextPrototype<'a> {
surface: surface.map(|s| Mutex::new(s)),
api: self.api,
pixel_format: self.pixel_format,
#[cfg(target_os = "android")]
config_id: self.config_id,
// #[cfg(target_os = "android")]
// config_id: self.config_id,
})
}
}
Expand Down
4 changes: 4 additions & 0 deletions glutin_egl_sys/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ fn main() {
);

if target.contains("android") || target.contains("ios") {
// FIXME: Without it we have unresolved links on Android and also possibly on IOS but I don't tested.
if target.contains("android") {
println!("cargo:rustc-link-lib=EGL");
}
reg.write_bindings(gl_generator::StaticStructGenerator, &mut file)
} else {
reg.write_bindings(gl_generator::StructGenerator, &mut file)
Expand Down