How to add OpenGL ES rendering support for SDL3 to build for Android?

Hello,

I try to rewrite the sdl3-sample example to OpenGL ES:

#include <SDL_opengles2.h>

// ...

    // draw a color
    auto time = SDL_GetTicks() / 1000.f;
    auto red = (std::sin(time) + 1) / 2.0;
    auto green = (std::sin(time / 2) + 1) / 2.0;
    auto blue = (std::sin(time) * 2 + 1) / 2.0;
    glClearColor(red, green, blue, 1.f);
    glColor(GL_COLOR_BUFFER_BIT);

    SDL_GL_SwapWindow(window);

// ...

But I have these errors:

C/C++: E:/_Projects/SDL3/sdl3-sample/src/main.cpp:38: error: undefined reference to 'glClearColor'
C/C++: E:/_Projects/SDL3/sdl3-sample/src/main.cpp:39: error: undefined reference to 'glClear'

All examples that I found in SDL for Android included this:

#include <SDL_opengles2.h>

But I don’t understand why it doesn’t work in this example. Maybe I should add something in config files. Please, help me to run this example.

main.cpp

#include <iostream>
#include <SDL.h>
#include <cmath>
#include <SDL_opengles2.h>
#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP)
//On UWP, we need to not have SDL_main otherwise we'll get a linker error
#define SDL_MAIN_HANDLED
#endif
#include <SDL_main.h>
#if __EMSCRIPTEN__
#include <emscripten.h>
#endif

void SDL_Fail(){
    SDL_LogError(SDL_LOG_CATEGORY_CUSTOM, "Error %s", SDL_GetError());
    exit(1);
}

static bool app_quit = false;
SDL_Window* window = nullptr;

void main_loop() {
    // Get events. If you are making a game, you probably want SDL_PollEvent instead of SDL_WaitEvent.
    // you cannot use WaitEvent on Emscripten, because you cannot block the main thread there.

    SDL_Event event;
    while (SDL_PollEvent(&event)) {
        if (event.type == SDL_EVENT_QUIT)
            app_quit = true;
        break;
    }

    // draw a color
    auto time = SDL_GetTicks() / 1000.f;
    auto red = (std::sin(time) + 1) / 2.0;
    auto green = (std::sin(time / 2) + 1) / 2.0;
    auto blue = (std::sin(time) * 2 + 1) / 2.0;
    glClearColor(red, green, blue, 1.f);
    glClear(GL_COLOR_BUFFER_BIT);

    SDL_GL_SwapWindow(window);
}

// Note: your main function __must__ take this form, otherwise on nonstandard platforms (iOS, etc), your app will not launch.
int main(int argc, char* argv[]){
    
    // init the library, here we make a window so we only need the Video capabilities.
    if (SDL_Init(SDL_INIT_VIDEO)){
        SDL_Fail();
    }
    
    // create a window
    SDL_Window* window = SDL_CreateWindow("Window", 352, 430, SDL_WINDOW_OPENGL);
    if (!window){
        SDL_Fail();
    }

    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
    SDL_GLContext glContext = SDL_GL_CreateContext(window);
    if (!glContext)
    {
        SDL_Fail();
    }

    // print some information about the window
    SDL_ShowWindow(window);
    {
        int width, height, bbwidth, bbheight;
        SDL_GetWindowSize(window, &width, &height);
        SDL_GetWindowSizeInPixels(window, &bbwidth, &bbheight);
        SDL_Log("Window size: %ix%i", width, height);
        SDL_Log("Backbuffer size: %ix%i", bbwidth, bbheight);
        if (width != bbwidth){
            SDL_Log("This is a highdpi environment.");
        }
    }
    
    SDL_Log("Application started successfully!");
    
#if __EMSCRIPTEN__
    // on Emscripten, we cannot have an infinite loop in main. Instead, we must
    // tell emscripten to call our main loop.
    emscripten_set_main_loop(main_loop, 0, 1);
#else
    while (!app_quit) {
        main_loop();
    }
#endif

    // cleanup everything at the end
#if !__EMSCRIPTEN__
    // SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(window);
    SDL_Quit();
    SDL_Log("Application quit successfully!");
#endif
    return 0;
}

Cross-ref:

I thought that the errors are relative to #include but it seams like #inlcude works and undefined reference glClearColor is a problem with linker. The linker doesn’t see the OpenGL library. But how to add OpenGL to Gradle to build for Android?

It seams like OpenGL ES was added in AndroidManifest. But why undefined reference glClearColor occurs?

Log:

E:\_Projects\SDL3\sdl3-sample\SDL\android-project>gradlew assembleDebug

> Configure project :app
[CXX5202] This app only has 32-bit [armeabi-v7a] native libraries. Beginning August 1, 2019 Google Play store requires that all apps that include native libraries must provide 64-bit versions. For more information, visit https://g.co/64-bit-requirement
[CXX5202] This app only has 32-bit [armeabi-v7a] native libraries. Beginning August 1, 2019 Google Play store requires that all apps that include native libraries must provide 64-bit versions. For more information, visit https://g.co/64-bit-requirement
WARNING:[CXX5202] This app only has 32-bit [armeabi-v7a] native libraries. Beginning August 1, 2019 Google Play store requires that all apps that include native libraries must provide 64-bit versions. For more information, visit https://g.co/64-bit-requirement
[CXX5202] This app only has 32-bit [armeabi-v7a] native libraries. Beginning August 1, 2019 Google Play store requires that all apps that include native libraries must provide 64-bit versions. For more information, visit https://g.co/64-bit-requirement
WARNING:[CXX5202] This app only has 32-bit [armeabi-v7a] native libraries. Beginning August 1, 2019 Google Play store requires that all apps that include native libraries must provide 64-bit versions. For more information, visit https://g.co/64-bit-requirement
[CXX5202] This app only has 32-bit [armeabi-v7a] native libraries. Beginning August 1, 2019 Google Play store requires that all apps that include native libraries must provide 64-bit versions. For more information, visit https://g.co/64-bit-requirement
Warning: unexpected element (uri:"", local:"base-extension"). Expected elements are <{}codename>,<{}layoutlib>,<{}api-level>

> Task :app:buildCMakeDebug FAILED
C/C++: ninja: Entering directory `E:\_Projects\SDL3\sdl3-sample\SDL\android-project\app\.cxx\Debug\3oy3nw31\armeabi-v7a'
C/C++: E:/_Projects/SDL3/sdl3-sample/src/main.cpp:44: error: undefined reference to 'glClearColor'
C/C++: E:/_Projects/SDL3/sdl3-sample/src/main.cpp:45: error: undefined reference to 'glClear'
C/C++: clang++: error: linker command failed with exit code 1 (use -v to see invocation)

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':app:buildCMakeDebug'.
> Build command failed.
  Error while executing process ninja.exe with arguments {-C E:\_Projects\SDL3\sdl3-sample\SDL\android-project\app\.cxx\Debug\3oy3nw31\armeabi-v7a SDL3-shared main}
  ninja: Entering directory `E:\_Projects\SDL3\sdl3-sample\SDL\android-project\app\.cxx\Debug\3oy3nw31\armeabi-v7a'
  [1/1] Linking CXX shared library Debug\libmain.so
  FAILED: Debug/libmain.so
  C:\Windows\system32\cmd.exe /C "cd . && E:\AppData\Android\SDK\ndk\21.4.7075529\toolchains\llvm\prebuilt\windows-x86_64\bin\clang++.exe --target=armv7-none-linux-androideabi16 --gcc-toolchain=E:/AppData/Android/SDK/ndk/21.4.7075529/toolchains/llvm/prebuilt/windows-x86_64 --sysroot=E:/AppData/Android/SDK/ndk/21.4.7075529/toolchains/llvm/prebuilt/windows-x86_64/sysroot -fPIC -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -march=armv7-a -mthumb -Wformat -Werror=format-security   -O0 -fno-limit-debug-info  -Wl,--exclude-libs,libgcc.a -Wl,--exclude-libs,libgcc_real.a -Wl,--exclude-libs,libatomic.a -static-libstdc++ -Wl,--build-id -Wl,--fatal-warnings -Wl,--exclude-libs,libunwind.a -Wl,--no-undefined -Qunused-arguments -shared -Wl,-soname,libmain.so -o Debug\libmain.so CMakeFiles/main.dir/src/main.cpp.o  Debug/libSDL3.so  -latomic -lm && cd ."
  E:/_Projects/SDL3/sdl3-sample/src/main.cpp:44: error: undefined reference to 'glClearColor'
  E:/_Projects/SDL3/sdl3-sample/src/main.cpp:45: error: undefined reference to 'glClear'
  clang++: error: linker command failed with exit code 1 (use -v to see invocation)
  ninja: build stopped: subcommand failed.



* Try:
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.

* Get more help at https://help.gradle.org

BUILD FAILED in 5s
14 actionable tasks: 2 executed, 12 up-to-date

I don’t know the Android build system(s). However, here are a few links to posts by others that have had the same problem you’ve got and have resolved it, and a few that mention the library name that you’re not linking with.

Seems the key is to get the GLESv2 library added to the link line (i.e. libGLESv2.so), using whatever build system and NDK install you’ve got there:

1 Like

Thank you very much for links! I will study the info.

SDL3 builds without problems. I have a problem with linking with GLESv2. I am not familiar with CMake. I tried to add GLESv2 like this:

target_link_libraries(${EXECUTABLE_NAME} PUBLIC SDL3::SDL3 GLESv2)

But I have this error: ld.exe: cannot find -lGLESv2

[ 98%] Built target SDL3-shared
[ 98%] Building CXX object CMakeFiles/sdl-min.dir/src/main.cpp.obj
[100%] Linking CXX executable sdl-min.exe
C:/Qt/Tools/mingw1120_64/bin/../lib/gcc/x86_64-w64-mingw32/11.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: cannot find -lGLESv2

My mistake above was that I tried to build with Android flag GLESv2 using MinGW. MinGW is for Windows only. I should to use gredlew after adding these flags android EGL GLESv2 to CMakeLists.txt:

target_link_libraries(${EXECUTABLE_NAME} PUBLIC SDL3::SDL3 android EGL GLESv2)
  • I moved to SDL/android-project and typed this commad: gradlew assembleDebug. It was completed successfully. The APK file was generated. But when I run the example on physical device the background color is green but I set it to red:
    auto red = 1.f;
    auto green = 0.f;
    auto blue = 0.f;
    glClearColor(red, green, blue, 1.f);
    glClear(GL_COLOR_BUFFER_BIT);
    SDL_GL_SwapWindow(window);

I tried to run the example on emulator but the screen is black.