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

Android support #70

Open
icefoxen opened this issue May 9, 2017 · 33 comments

Comments

@icefoxen
Copy link
Contributor

commented May 9, 2017

Should happen eventually!

@icefoxen

This comment has been minimized.

Copy link
Contributor Author

commented Jun 9, 2017

Reference for how to make it go, maybe: https://github.com/tanis2000/minigame-rust

@icefoxen

This comment has been minimized.

Copy link
Contributor Author

commented Jul 23, 2017

Apparently getting glium to work on Android is not actually that hard: https://twitter.com/ozkriff/status/889014729884172289

@icefoxen icefoxen added *HARD* and removed *GOOD FIRST ISSUE* labels Jul 31, 2017

@TatriX

This comment has been minimized.

Copy link

commented Oct 9, 2017

I'm trying to build a 0.3.3 for android, without success yet though.

@icefoxen

This comment has been minimized.

Copy link
Contributor Author

commented Oct 9, 2017

Good luck! Let me know if you get it to work! I will help with anything I can but I really know nothing about Android programming. Trying out the glium fork of 0.3.3 might be worth a go.

@TatriX

This comment has been minimized.

Copy link

commented Oct 9, 2017

I compiled the code. Sigh. Current error:

thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: UnknownError("Application didn\'t initialize properly, did you include SDL_main.h in the file containing your main() function?")', /checkout/src/libcore/result.rs:860:4
@TatriX

This comment has been minimized.

Copy link

commented Oct 9, 2017

It seems that add_dirs doesn't support android:

FilesystemError("App data directories not supported")
@TatriX

This comment has been minimized.

Copy link

commented Oct 9, 2017

@icefoxen

This comment has been minimized.

Copy link
Contributor Author

commented Oct 9, 2017

Copied from the above app-dirs-rs issue:

https://developer.android.com/guide/topics/data/data-storage.html seems like the place to start

SDL2's filesystem path code does a sort of similar task so I thought it might be helpful, but doesn't look super hopeful: https://hg.libsdl.org/SDL/file/8df7a59b5528/src/filesystem/android/SDL_sysfilesystem.c  

https://hg.libsdl.org/SDL/file/8df7a59b5528/docs/README-android.md has some useful information under "loading assets".

Looks like Android has some special functionality for static data in addition to normal filesystem paths, so it's not entirely trivial.

Basically, Android has its own thoughts about where data should be stored and supporting that looks like it might take adding another VFS type to src/vfs.rs. Fortunately that shouldn't be TOO hard? If you want to give it a go, try hacking a minimal type in, implementing VFS on it that just returns file-doesn't-exist or something, and shove it rudely into the filesystem context in place of what's normally there. You won't be able to load assets but if everything else works you should be able to at least draw meshes and stuff.

I predict the next error will be sound initialization, since rodio uses cpal which doesn't support Android (yet). :-P That should be fairly easy to disable; we need the option to detect and optionally ignore sound errors in ggez anyway. After that you'll probably need to tell it to init the right version of OpenGL.

Thennnnnnn... maybe it will work?

@TatriX

This comment has been minimized.

Copy link

commented Oct 9, 2017

I hacked the code, a bit, and managed to bypass filesystem module.
The actual problem now is I need to call SDL_Android_Init(env, cls);.
I hope I could manage this before I go insane.

@icefoxen

This comment has been minimized.

Copy link
Contributor Author

commented Oct 9, 2017

Don't go insane, we need your brain intact! 😁

It does occur to me that this would be easier if ggez had a more modular structure like Love2D does, where you can enable or disable individual modules. Then you could just start with everything disabled, get that working, and turn things on one piece at a time as you make them work. That sort of structure wouldn't be HARD to do but would require extra indirection and error-checking, which is why I didn't do it in the first place. Hmmmm.

@TatriX

This comment has been minimized.

Copy link

commented Oct 10, 2017

Current state of the art:
sdl2+rust compiles and runs on my arm8 phone.

Currently I'm trying to figure out how can I break decency cycle.

@TatriX

This comment has been minimized.

Copy link

commented Oct 10, 2017

Basically now I need a ggez to be updated to use latest gfx_window_sdl and sdl2

@icefoxen

This comment has been minimized.

Copy link
Contributor Author

commented Oct 10, 2017

Woohoo!

What do you need the latest sdl2 for? I am not aware of any huge changes in it for mobile support. Maybe there are though?

We're on the latest published version of gfx_window_sdl, 0.6, which uses sdl2 0.29. sdl2 0.30 brings some cool API changes... to parts of the API that ggez ddoesn't use, so I didn't really consider it a priority. gfx_window_sdl 0.7 is being made but it will be for gfx 0.17, which might bring big changes in how gfx works; it's not done yet and will probably take a while to get there (my guess is 6 months before it works really well, but that's just a guess).

So. If you need sdl2 0.30 we can hack together an experimental version of gfx_window_sdl that uses it, it shouldn't be hard. If it can be made to work with sdl2 0.29 then that's ideal.

@TatriX

This comment has been minimized.

Copy link

commented Oct 10, 2017

To make sdl work on android I have to use

sdl2 = { default-features = false, features = ["unsafe_textures"], git = "https://github.com/Rust-SDL2/rust-sdl2.git", branch = "unsafe-textures-feature" }

It's the only way now.

@tanis2000

This comment has been minimized.

Copy link

commented Oct 10, 2017

@TatriX I haven't yet had a chance of looking at the code of ggez, but if you're not using the TextureCreator to manage textures you don't need the unsafe_textures feature of sdl2.

Even the code of my minigame would work without that now as I'm loading the textures in memory through stb_image and then I'm sending them to the GPU through direct GL calls.

What's ggez using to manage textures? Would you ever need to keep a copy of the textures in memory instead of spooling them off to the GPU?

@TatriX

This comment has been minimized.

Copy link

commented Oct 10, 2017

I think I've tried stripped version of the minigame without actual code, just sdl init, and it also failed with sdl_image not beeing resolved. Probably I should try again.

@icefoxen

This comment has been minimized.

Copy link
Contributor Author

commented Oct 10, 2017

ggez doesn't use SDL for drawing or image loading, so you should be able to cut those out if possible.

@TatriX

This comment has been minimized.

Copy link

commented Oct 10, 2017

@tanis2000 could you please take a simple example like this and try to run it on your mobile?

@tanis2000

This comment has been minimized.

Copy link

commented Oct 10, 2017

@icefoxen @TatriX what's the plan for mobile support? Would you like to have ggez do all the packaging or would you prefer to let the game project take care of that?

They're two completely different approaches, both with pro and cons and I guess it's better to have a clear idea before attempting to do anything.

@TatriX

This comment has been minimized.

Copy link

commented Oct 10, 2017

I'm okay with minigame approach. Call required stuff like SDL_Android_Init yourself and then simply call engine::run(). This way end user can decide how we want to package the app.
I think that currently the simplest (to implement) is the best.

@icefoxen

This comment has been minimized.

Copy link
Contributor Author

commented Oct 12, 2017

@tanis2000 I honestly have no idea because I don't know what the pros and cons of each are. :-/

My reflex is to make the game project take care of that so that we have to include a minimum of platform-specific scaffolding in ggez itself, and then have very good documentation/demo projects for people to use to get started.

What's ggez using to manage textures? Would you ever need to keep a copy of the textures in memory instead of spooling them off to the GPU?

Sorry, I missed this question. ggez manages textures via letting gfx-rs's OpenGL backend manage them, which basically means they end up as an Arc'ed texture handle (ie, a u32). So no, we never really store anything in CPU memory unless we're creating it (loading an image, rendering a font to bitmap, etc). If we ever do end up with CPU-memory image data it will be a different type, similar to SDL2's Texture vs. Surface.

@TatriX

This comment has been minimized.

Copy link

commented Oct 20, 2017

Ok, so I

  1. Removed app-dirs
  2. Removed rodio
  3. Updated GlBackendSpec
pub struct GlBackendSpec {
    #[default = r#"2"#]
    major: u8,
    #[default = r#"0"#]
    minor: u8,
}
  1. Found a crazy way to catch panics and write them to the android log with sdl 0.29:
use std::ffi::CString;

fn log(msg: &str) {
    let message = CString::new(msg).unwrap();
    unsafe {
        SDL_Log(message.into_raw());
    };
}

#[no_mangle]
#[allow(non_snake_case)]
pub extern "C" fn SDL_main() -> i32 {
    log("rust start");
    use std::panic;
    panic::set_hook(Box::new(|pi| {
        log(&format!("Custom panic hook {:?}", pi.location()));
    }));
    let result = panic::catch_unwind(|| ggez_test::run());
    if let Err(e) = result {
        let ref msg = if let Some(e) = e.downcast_ref::<&'static str>() {
            format!("Got an error: {}", e)
        } else if let Some(e) = e.downcast_ref::<String>()   {
            format!("Got an error: {}", e)
        } else {
            format!("Got an unknown error: {:?}", e)
        };
        log(msg);
    } else {
        log("rust clear exit")
    }
    0
}
#[cfg(target_os="android")]
extern "C" {
    fn SDL_Log(fmt: *const ::std::os::raw::c_char, ...);
}

and now my error is:

Got an error: called `Result::unwrap()` on an `Err` value: WindowError(WindowBuildError(SdlError("Could not initialize OpenGL / GLES library")))
@TatriX

This comment has been minimized.

Copy link

commented Oct 20, 2017

Aslo my device reports that is supports GLES 3.2

@icefoxen

This comment has been minimized.

Copy link
Contributor Author

commented Oct 20, 2017

OpenGL and OpenGL ES are entirely separate beasts, as far as the spec and driver is concerned; the version numbers don't even line up nicely with each other, IIRC ES 2.0 is about equivalent to OpenGL 3.0, and ES 3.0 is most similar to OpenGL 4.2 or something. It's stupid.

You are going to have to tell SDL to request OpenGL ES specifically, try changing the Core in line https://github.com/ggez/ggez/blob/master/src/graphics/mod.rs#L254 with GLES (see https://docs.rs/sdl2/0.29.0/sdl2/video/enum.GLProfile.html and related SDL documentation for more info).

IIRC, ES 2.0 also doesn't support instancing, which will probably break pretty much all the rendering and shaders now that drawing a single object is basically implemented as drawing a single-item SpriteBatch. If you can get it to build the window at all, it might be useful try ES 3.2 and work your way back.

@TatriX

This comment has been minimized.

Copy link

commented Oct 20, 2017

Using GLES gives me

called `Result::unwrap()` on an `Err` value: UnknownError("That operation is not supported")
@TatriX

This comment has been minimized.

Copy link

commented Oct 20, 2017

Maybe it's somehow related to https://github.com/Rust-SDL2/rust-sdl2/tree/unsafe-textures-feature
Using this branch with minigame-rust worked for me.

@seivan

This comment has been minimized.

Copy link

commented Oct 2, 2018

I guess a lot of things has changed since switching to winit?
My question is, to launch on iOS the game needs(?) to be a static binary, and called on in main.h - so how would resources work in that scenario? Like images, fonts, etc?

@icefoxen

This comment has been minimized.

Copy link
Contributor Author

commented Oct 3, 2018

@seivan I know literally nothing about iOS but I'm actually working with someone who does on this off and on. Does indeed look like there's some resource-y things that need ironing out.

@icefoxen

This comment has been minimized.

Copy link
Contributor Author

commented Oct 4, 2018

...wait, that's you. Derp.

It really just depends on what iOS's limitations are. If we have access to specific directories via normal file system calls, we need to make sure ggez tries to read/write to only those directories. If we need to use a particular filesystem API to access things, we need to make it do that. (I THINK this is what Android does.) If things actually do need to be part of the same .exe file, then we need to implement the functionality to handle that, probably doing something along the lines of what #469 describes.

I don't know enough about iOS to say more. I should man up and do some research. :/

@icefoxen

This comment has been minimized.

Copy link
Contributor Author

commented Jan 14, 2019

Using cargo-apk to try to build for Android runs into this bug: rust-windowing/android-rs-glue#197

@icefoxen

This comment has been minimized.

Copy link
Contributor Author

commented Jan 14, 2019

A typical experience, like the third one this week:

11:34 < Icefoz> OKAY.  Let's try to build cargo apk from source.
11:34 < merina> : )
11:35 < merina> it would be amazing to just hit up cargo apk + container at one point and baaaam, cross compiled to all android targets
11:35 < Icefoz> That's the dream!
11:37 < Icefoz> For now though... I have to install the android NDK through android studio???
11:38 < sgift> I think yes. They've removed direct NDK install without studio a while back (iirc)
11:39 < Icefoz> Good thing I have fast internet.  z_z
11:54 < Icefoz> Exception in thread "main" java.lang.NoClassDefFoundError: javax/xml/bind/annotation/XmlSchema
11:54 < Icefoz> Off to a good start.
11:56 < Icefoz> ah, found where to try to do it through Android Studio.  Looks like it uses its own JVM
or such?  idk
11:57 < merina> android java and java are very different worlds
11:58 < ytain_> Android uses ART which is their own JVM,
11:59 < sgift> Yes. It is old. And shit.
11:59 < ytain_> but less optimal than the JVM on PC
11:59 < sgift> Its some weird JDK6+<a few things>
11:59 < Icefoz> Yes but I'm just trying to run `sdkmanager`
11:59 < Icefoz> oh nooooooo openssl
11:59 < sgift> :(
12:00 < ytain_> why you need to download the NDK via Android Studio?
12:00 < ytain_> you don't have to
12:00 < Icefoz> I can't find a link to do it any other place on the android website.
12:00 < ytain_> you just download the NDK from this web page
12:00 < ytain_> https://developer.android.com/ndk/downloads/
12:00 < sgift> damn :( I thought that one was killed
12:00 < sgift> my fault.
12:01 < Icefoz> lemme tilt at the windmill of openssl first.
12:01 < ytain_> and for cargo apk you just specify the path to ndk folder where it is installed
12:05 < Icefoz> "Unable to detect OpenSSL version", even when I explicitly tell it which version.
12:06 < Icefoz> why is the openssl crate such shit.  ;_;
12:06 < Icefoz> can we just use rustls for everything
12:07 < fkaa> external deps are the devil
12:09 < Icefoz> like I literally don't know what to do about this.  I'm looking at the line in the build
script as I write this.
12:11 < merina> ohh
12:11 < Icefoz> https://github.com/sfackler/rust-openssl/blob/0.9.x/openssl/build.rs#L4-L16
12:11 < Icefoz> `env DEP_OPENSSL_VERSION=110 cargo install cargo-apk`
12:12 < merina> wait look here: https://github.com/sfackler/rust-openssl/issues/994
12:12 < merina> we use this as workaround
12:12 < merina> openssl = { git = "https://github.com/ishitatsuyuki/rust-openssl", branch = "0.9.x" }
12:12 < merina> with [patch.crates-io] above
12:12 < merina> might solve it
12:13 < Icefoz> Use that in a git checkout of `cargo-apk`, you mean?
12:19 < Icefoz> ...building it from git doesn't have the ssl problem at all, it seems.
12:19 < Icefoz> wth
12:21 < merina> oh
12:26 < Icefoz> well, installing it from git also makes `cargo apk build` just say `expected build,
install, run or logcat`
12:26 < Icefoz> no matter what I do.
12:27 < Icefoz> So after 45 minutes, no dice.
12:27 < Icefoz> This is typical of my attempts to build ggez for android.
12:28 < Icefoz> crap tools and old documentation producing frustrating problems until I give up and go to do something useful.

@icefoxen

This comment has been minimized.

Copy link
Contributor Author

commented Jan 14, 2019

On iOS, this appears to be a blocking bug: RustAudio/cpal#224 There may be others, though.

@tanis2000

This comment has been minimized.

Copy link

commented Jan 17, 2019

@icefoxen yes, if you're using CPAL, you have to wait until they actually support iOS. They added macOS support and probably forgot that iOS is a completely different beast.

@icefoxen icefoxen changed the title iOS/Android support ~~iOS~~/Android support Apr 23, 2019

@icefoxen icefoxen changed the title ~~iOS~~/Android support Android support Apr 23, 2019

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
4 participants
You can’t perform that action at this time.