From ed3607599de53aeed61c3e64c36adad3f8faee44 Mon Sep 17 00:00:00 2001 From: cobaltgit Date: Wed, 15 Jul 2026 09:31:20 +0100 Subject: [PATCH 1/3] android: use Glad --- CMakeLists.txt | 10 +++++++--- src/android/main.c | 19 ++++++++++++++++++- src/gl/gl_renderer.c | 6 +++--- src/gl/gl_renderer.h | 2 +- src/gl_common/gl_common.h | 9 +++++---- src/gl_common/gl_wrappers.h | 2 +- 6 files changed, 35 insertions(+), 13 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 924d470fa..880afd346 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -388,7 +388,11 @@ elseif(PLATFORM STREQUAL "android") target_include_directories(butterscotch PRIVATE ${CMAKE_SOURCE_DIR}/src/gl) target_include_directories(butterscotch PRIVATE ${CMAKE_SOURCE_DIR}/src/gl_common) target_include_directories(butterscotch PRIVATE ${CMAKE_SOURCE_DIR}/src/image) - add_compile_definitions(ENABLE_GLES PLATFORM_ANDROID) + add_compile_definitions(PLATFORM_ANDROID) + + # GLAD + add_library(glad STATIC vendor/glad/src/glad.c) + target_include_directories(glad PUBLIC vendor/glad/include) # Butterscotch VM/interpreter profiler option(ENABLE_VM_GML_PROFILER "Enable Butterscotch VM/interpreter profiler" ON) @@ -429,9 +433,9 @@ elseif(PLATFORM STREQUAL "android") # Android NDK system libraries: # - log: __android_log_* - # - GLESv3: OpenGL ES 3.0 functions + # - EGL: eglGetProcAddress used by the Glad GLES2 loader # - OpenSLES: miniaudio's OpenSL ES backend (it dlopen's libaaudio.so at runtime when available, so no link-time aaudio dep) - target_link_libraries(butterscotch PRIVATE log GLESv3 OpenSLES bzip2 stb_ds sha1 stb_vorbis) + target_link_libraries(butterscotch PRIVATE glad log EGL OpenSLES bzip2 stb_ds sha1 stb_vorbis) elseif(PLATFORM STREQUAL "ps2") file(GLOB DEBUG_FONT_SOURCES src/debug_font/*.c) target_sources(butterscotch PRIVATE ${DEBUG_FONT_SOURCES}) diff --git a/src/android/main.c b/src/android/main.c index 741eb4df9..b19036778 100644 --- a/src/android/main.c +++ b/src/android/main.c @@ -5,7 +5,9 @@ #include #include #include -#include +#include +#include +#include #include "common.h" #include "data_win.h" @@ -400,12 +402,27 @@ static void teardownRunner() { DataWin_free(dataWin); } +static void* androidGlLoader(const char* name) { + void* ptr = eglGetProcAddress(name); + if (ptr == NULL) { + ptr = dlsym(RTLD_DEFAULT, name); + } + return ptr; +} + JNIEXPORT jboolean JNICALL JNI_FN(startRunner)(JNIEnv* env, MAYBE_UNUSED jclass cls, jstring jDataWinPath, jstring jSavesPath, jint jOsType, jint jHostFramebuffer) { if (gRunner != nullptr) { LOGW("startRunner called while a runner is already alive; ignoring"); return JNI_FALSE; } gHostFramebuffer = (GLuint) jHostFramebuffer; + + if (!gladLoadGLES2Loader(androidGlLoader)) { + LOGE("Failed to load OpenGL ES via Glad"); + return JNI_FALSE; + } + LOGI("GL Version: %s", glGetString(GL_VERSION)); + const char* dataWinPath = (*env)->GetStringUTFChars(env, jDataWinPath, nullptr); const char* savesPath = (*env)->GetStringUTFChars(env, jSavesPath, nullptr); char** gameArgs = nullptr; diff --git a/src/gl/gl_renderer.c b/src/gl/gl_renderer.c index 60a42ca9f..a43394b4f 100644 --- a/src/gl/gl_renderer.c +++ b/src/gl/gl_renderer.c @@ -2,7 +2,7 @@ #include "matrix_math.h" #include "text_utils.h" -#if defined(__EMSCRIPTEN__) || defined(__ANDROID__) +#if defined(__EMSCRIPTEN__) #include #else #include @@ -51,7 +51,7 @@ static const char* baseFragmentShader = // ===[ Runtime OpenGL extension checks ]=== static bool hasFBO() { -#if !defined(__EMSCRIPTEN__) && !defined(__ANDROID__) +#if !defined(__EMSCRIPTEN__) return (glGenFramebuffers || glGenFramebuffersEXT); #else return true; @@ -59,7 +59,7 @@ static bool hasFBO() { } static bool hasVAO() { -#if !defined(__EMSCRIPTEN__) && !defined(__ANDROID__) +#if !defined(__EMSCRIPTEN__) return (glGenVertexArrays || glGenVertexArraysOES); #else return true; diff --git a/src/gl/gl_renderer.h b/src/gl/gl_renderer.h index 6ca2e97b7..19aff776b 100644 --- a/src/gl/gl_renderer.h +++ b/src/gl/gl_renderer.h @@ -4,7 +4,7 @@ #include "common.h" #include "renderer.h" #include "runner.h" -#if defined(__EMSCRIPTEN__) || defined(__ANDROID__) +#if defined(__EMSCRIPTEN__) #include #else #include diff --git a/src/gl_common/gl_common.h b/src/gl_common/gl_common.h index 5a66b86f9..0ba12664c 100644 --- a/src/gl_common/gl_common.h +++ b/src/gl_common/gl_common.h @@ -4,13 +4,14 @@ #include "common.h" #include -#if defined(__EMSCRIPTEN__) || defined(__ANDROID__) +#if defined(__EMSCRIPTEN__) #include -#elif PLATFORM_PS3 +#elif defined(__ANDROID__) || !defined(PLATFORM_PS3) +#include +#endif +#if PLATFORM_PS3 #include "ps3gl.h" #include "rsxutil.h" -#else -#include #endif // ===[ Letterbox blit ]=== diff --git a/src/gl_common/gl_wrappers.h b/src/gl_common/gl_wrappers.h index b9d6b3e75..4727e50d8 100644 --- a/src/gl_common/gl_wrappers.h +++ b/src/gl_common/gl_wrappers.h @@ -1,4 +1,4 @@ -#if !defined(_BS_GL_WRAPPERS_H_) && !defined(__EMSCRIPTEN__) && !defined(PLATFORM_PS3) && !defined(__ANDROID__) +#if !defined(_BS_GL_WRAPPERS_H_) && !defined(__EMSCRIPTEN__) && !defined(PLATFORM_PS3) #define _BS_GL_WRAPPERS_H_ static inline void rt_glBindVertexArray(GLuint vao) { From 3ede3378c83dfb3c49082961063b4a3301be4afa Mon Sep 17 00:00:00 2001 From: cobaltgit Date: Wed, 15 Jul 2026 09:54:12 +0100 Subject: [PATCH 2/3] use eglGetProcAddress --- src/android/main.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/android/main.c b/src/android/main.c index b19036778..43b1c3d85 100644 --- a/src/android/main.c +++ b/src/android/main.c @@ -402,14 +402,6 @@ static void teardownRunner() { DataWin_free(dataWin); } -static void* androidGlLoader(const char* name) { - void* ptr = eglGetProcAddress(name); - if (ptr == NULL) { - ptr = dlsym(RTLD_DEFAULT, name); - } - return ptr; -} - JNIEXPORT jboolean JNICALL JNI_FN(startRunner)(JNIEnv* env, MAYBE_UNUSED jclass cls, jstring jDataWinPath, jstring jSavesPath, jint jOsType, jint jHostFramebuffer) { if (gRunner != nullptr) { LOGW("startRunner called while a runner is already alive; ignoring"); @@ -417,7 +409,7 @@ JNIEXPORT jboolean JNICALL JNI_FN(startRunner)(JNIEnv* env, MAYBE_UNUSED jclass } gHostFramebuffer = (GLuint) jHostFramebuffer; - if (!gladLoadGLES2Loader(androidGlLoader)) { + if (!gladLoadGLES2Loader((GLADloadproc)eglGetProcAddress))) { LOGE("Failed to load OpenGL ES via Glad"); return JNI_FALSE; } From 5b813aef04b60cf878dda92b26613c7f677da0df Mon Sep 17 00:00:00 2001 From: cobaltgit Date: Wed, 15 Jul 2026 12:43:52 +0100 Subject: [PATCH 3/3] fix --- src/android/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/android/main.c b/src/android/main.c index 43b1c3d85..672dbc285 100644 --- a/src/android/main.c +++ b/src/android/main.c @@ -409,7 +409,7 @@ JNIEXPORT jboolean JNICALL JNI_FN(startRunner)(JNIEnv* env, MAYBE_UNUSED jclass } gHostFramebuffer = (GLuint) jHostFramebuffer; - if (!gladLoadGLES2Loader((GLADloadproc)eglGetProcAddress))) { + if (!gladLoadGLES2Loader((GLADloadproc)eglGetProcAddress)) { LOGE("Failed to load OpenGL ES via Glad"); return JNI_FALSE; }