Closed jayzhen521 closed 6 months ago
Please note that the Android port is still in an experimental state. I just got the build script to successfully compile LLGL GLES3 for Android, but I actually haven't set up any deployment targets yet, i.e. no build script generates the APK package yet. Since the example projects include the android_main
function, I presume a standard setup with the NativeActivity
should be sufficient, i.e. one that doesn't require any Java code. For now I would have to refer you to the official Android NDK documentation and suggest you first manually link the *.so files from the Android example builds to a NativeActivity Android project.
The upper layer needs to make complex UI layouts and have others use java/kotlin for development, NativeActivity seems not fit for this.
I made some updates to the Android port and got a first example up and running in the Android emulator:
I used a modified version of the native-activity example from the android ndk-samples project and build LLGL as static lib for all known ABI versions via ./BuildAndroid.sh -s -d --abi=all
.
The modified CMakeLists.txt from the native-activity sample contains this:
#set(LLGL_ROOT ...)
set(LLGL_INCLUDE_DIR "${LLGL_ROOT}/include")
set(LLGL_LIB_DIR "${LLGL_ROOT}/build_android/${ANDROID_ABI}/build")
add_library(lib_llgl STATIC IMPORTED)
set_target_properties(lib_llgl PROPERTIES IMPORTED_LOCATION "${LLGL_LIB_DIR}/libLLGLD.a")
add_library(lib_llgl_gles3 STATIC IMPORTED)
set_target_properties(lib_llgl_gles3 PROPERTIES IMPORTED_LOCATION "${LLGL_LIB_DIR}/libLLGL_OpenGLES3D.a")
target_include_directories(native-activity PRIVATE
${ANDROID_NDK}/sources/android/native_app_glue
${LLGL_INCLUDE_DIR})
target_link_libraries(native-activity
android log native_app_glue EGL lib_llgl lib_llgl_gles3 GLESv3)
${ANDROID_ABI}
selects the build for the respective ABI, since Android Studio builds for multiple ABI versions at once, at least with the default settings in the ndk-samples project.
If you can't rely on the native-activity example and you have to provide your own EGL context. You would have to add something like this to your LLGL loading code:
#include <LLGL/Backend/OpenGL/NativeHande.h>
...
// Forward custom ::EGLContext object to LLGL
LLGL::OpenGL::RenderSystemNativeHandle nativeRendererHandle = {};
nativeRendererHandle.context = myEGLContext;
rendererDesc.nativeHandle = &nativeRendererHandle;
rendererDesc.nativeHandleSize = sizeof(nativeRendererHandle);
I suggest to reproduce the approach of hooking up LLGL to the native-activity sample and go from there. Just so you have something working and then you can modify it to use a different GL view.
UPDATE:
Forgot to point out that I'm linking against libLLGLD.a and libLLGL_OpenGLES3D.a since I built with -d
option to have debug symbols. Running in Android Studio with lldb provides a pretty decent debugging experience, i.e. the C++ integration works pretty good.
Thank you so much! I very much agree with your point of view, and I am getting familiar with the relevant code. I will try manual egl first.
I suggest to reproduce the approach of hooking up LLGL to the native-activity sample and go from there. Just so you have something working and then you can modify it to use a different GL view.
This is a good idea!
UPDATE: After a little modification, The native-activity does display correctly.
Would you mind sharing your modifications? And please keep me posted if you get LLGL hooked up to a separate GLView.
Would you mind sharing your modifications?
I've just implemented it with the help of your instructions, making only a few modifications for drawing triangle. If you need, I can paste the modifications here or create a demo.
I was wondering if I could take a bit of your time to help debug my project. Under the second commit at https://github.com/jayzhen521/SurfaceViewManual, I've constructed my own EGL environment at the native level and managed to draw a Triangle. However, after introducing LLGL and making some adjustments to it, it still doesn't display correctly. It might be due to my insufficient understanding of some EGL principles. The modifications I've made are available at https://github.com/jayzhen521/LLGL.git. I would greatly appreciate your help in reviewing my changes.
(In the SurfaceViewManual, I have just left "Clear" command, but it cannot work)
The ultimate goal of the project I'm building is to leverage the cross-platform capabilities of LLGL. This will enable higher-level developers to work on non-rendering related content, such as UI, using Java, Kotlin, Swift, and other languages.
It looks like you are trying to do the event handling yourself, so when you only want LLGL to draw in drawFrame()
, I wouldn't invoke exampleTexturing->Run()
and only forward that call via exampleTexturing->DrawFrame()
. Run()
will enter the main loop and in your case it seems your app only wants to draw a single frame, so this would hang your application.
Your OnDrawFrame
implementation is missing one important step. Calling Clear
outside a render pass in LLGL is undefined behavior:
commands->Begin();
commands->Clear(LLGL::ClearFlags::ColorDepth, backgroundColor);
commands->End();
The documentation says Clears the specified group of attachments of the active render target, but outside a render pass there are no active render targets. You have to call it inside a render pass like so:
commands->Begin();
commands->BeginRenderPass(*swapChain);
commands->Clear(LLGL::ClearFlags::ColorDepth, backgroundColor);
commands->EndRenderPass();
commands->End();
Having said that, this might not fix your problem, because GLES will probably be just fine calling Clear
directly, it simply doesn't follow the design pattern of LLGL and the debug layer should report an error (which is not enabled in your case).
But let me know if that changes anything before we dig deeper.
It looks like you are trying to do the event handling yourself, so when you only want LLGL to draw in drawFrame(), I wouldn't invoke exampleTexturing->Run() and only forward that call via exampleTexturing->DrawFrame(). Run() will enter the main loop and in your case it seems your app only wants to draw a single frame, so this would hang your application.
It works.
I will add rendering logic for testing later, which will be reflected at https://github.com/jayzhen521/SurfaceViewManual. If LLGL has some bugs related to Android, I will file a PR.
I think we can close this since you have a setup to build LLGL for Android now. Feel free to open this again or a new ticket if need you something else regarding that platform.
Can you give me some tips about how to run the examples in Android? I want to deploy the LLGL to android but didn't find any relevant content.
I also have two questions: