From 546238663c2560270b0f082fc088fd264e5a5031 Mon Sep 17 00:00:00 2001 From: Maksim Belov <45949002+artdeell@users.noreply.github.com> Date: Fri, 15 Nov 2024 22:49:19 +0300 Subject: [PATCH] Feat[pojavexec]: better renderer symbol loading (#6220) --- app_pojavlauncher/src/main/jni/Android.mk | 1 + .../src/main/jni/ctxbridges/egl_loader.c | 52 +++++++++++-------- .../src/main/jni/ctxbridges/egl_loader.h | 4 +- .../src/main/jni/ctxbridges/gl_bridge.c | 2 +- .../src/main/jni/ctxbridges/loader_dlopen.c | 24 +++++++++ .../src/main/jni/ctxbridges/loader_dlopen.h | 10 ++++ .../src/main/jni/ctxbridges/osm_bridge.c | 4 +- .../src/main/jni/ctxbridges/osmesa_loader.c | 40 +++++++------- .../src/main/jni/ctxbridges/osmesa_loader.h | 5 +- 9 files changed, 94 insertions(+), 48 deletions(-) create mode 100644 app_pojavlauncher/src/main/jni/ctxbridges/loader_dlopen.c create mode 100644 app_pojavlauncher/src/main/jni/ctxbridges/loader_dlopen.h diff --git a/app_pojavlauncher/src/main/jni/Android.mk b/app_pojavlauncher/src/main/jni/Android.mk index 3ac7a1f727..f0948a8026 100644 --- a/app_pojavlauncher/src/main/jni/Android.mk +++ b/app_pojavlauncher/src/main/jni/Android.mk @@ -34,6 +34,7 @@ LOCAL_SHARED_LIBRARIES := bytehook LOCAL_SRC_FILES := \ bigcoreaffinity.c \ egl_bridge.c \ + ctxbridges/loader_dlopen.c \ ctxbridges/gl_bridge.c \ ctxbridges/osm_bridge.c \ ctxbridges/egl_loader.c \ diff --git a/app_pojavlauncher/src/main/jni/ctxbridges/egl_loader.c b/app_pojavlauncher/src/main/jni/ctxbridges/egl_loader.c index ca53001e28..dcd998a796 100644 --- a/app_pojavlauncher/src/main/jni/ctxbridges/egl_loader.c +++ b/app_pojavlauncher/src/main/jni/ctxbridges/egl_loader.c @@ -5,6 +5,7 @@ #include #include #include "egl_loader.h" +#include "loader_dlopen.h" EGLBoolean (*eglMakeCurrent_p) (EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx); EGLBoolean (*eglDestroyContext_p) (EGLDisplay dpy, EGLContext ctx); @@ -24,28 +25,33 @@ EGLint (*eglGetError_p) (void); EGLContext (*eglCreateContext_p) (EGLDisplay dpy, EGLConfig config, EGLContext share_list, const EGLint *attrib_list); EGLBoolean (*eglSwapInterval_p) (EGLDisplay dpy, EGLint interval); EGLSurface (*eglGetCurrentSurface_p) (EGLint readdraw); +__eglMustCastToProperFunctionPointerType (*eglGetProcAddress_p) (const char *procname); -void dlsym_EGL() { - void* dl_handle = NULL; - if(getenv("POJAVEXEC_EGL")) dl_handle = dlopen(getenv("POJAVEXEC_EGL"), RTLD_LAZY); - if(dl_handle == NULL) dl_handle = dlopen("libEGL.so", RTLD_LAZY); - if(dl_handle == NULL) abort(); - eglBindAPI_p = dlsym(dl_handle,"eglBindAPI"); - eglChooseConfig_p = dlsym(dl_handle, "eglChooseConfig"); - eglCreateContext_p = dlsym(dl_handle, "eglCreateContext"); - eglCreatePbufferSurface_p = dlsym(dl_handle, "eglCreatePbufferSurface"); - eglCreateWindowSurface_p = dlsym(dl_handle, "eglCreateWindowSurface"); - eglDestroyContext_p = dlsym(dl_handle, "eglDestroyContext"); - eglDestroySurface_p = dlsym(dl_handle, "eglDestroySurface"); - eglGetConfigAttrib_p = dlsym(dl_handle, "eglGetConfigAttrib"); - eglGetCurrentContext_p = dlsym(dl_handle, "eglGetCurrentContext"); - eglGetDisplay_p = dlsym(dl_handle, "eglGetDisplay"); - eglGetError_p = dlsym(dl_handle, "eglGetError"); - eglInitialize_p = dlsym(dl_handle, "eglInitialize"); - eglMakeCurrent_p = dlsym(dl_handle, "eglMakeCurrent"); - eglSwapBuffers_p = dlsym(dl_handle, "eglSwapBuffers"); - eglReleaseThread_p = dlsym(dl_handle, "eglReleaseThread"); - eglSwapInterval_p = dlsym(dl_handle, "eglSwapInterval"); - eglTerminate_p = dlsym(dl_handle, "eglTerminate"); - eglGetCurrentSurface_p = dlsym(dl_handle,"eglGetCurrentSurface"); +bool dlsym_EGL() { + void* dl_handle = loader_dlopen(getenv("POJAVEXEC_EGL"),"libEGL.so", RTLD_LOCAL|RTLD_LAZY); + if(dl_handle == NULL) return false; + eglGetProcAddress_p = dlsym(dl_handle, "eglGetProcAddress"); + if(eglGetProcAddress_p == NULL) { + printf("%s\n", dlerror()); + return false; + } + eglBindAPI_p = (void*) eglGetProcAddress_p("eglBindAPI"); + eglChooseConfig_p = (void*) eglGetProcAddress_p("eglChooseConfig"); + eglCreateContext_p = (void*) eglGetProcAddress_p("eglCreateContext"); + eglCreatePbufferSurface_p = (void*) eglGetProcAddress_p("eglCreatePbufferSurface"); + eglCreateWindowSurface_p = (void*) eglGetProcAddress_p("eglCreateWindowSurface"); + eglDestroyContext_p = (void*) eglGetProcAddress_p("eglDestroyContext"); + eglDestroySurface_p = (void*) eglGetProcAddress_p("eglDestroySurface"); + eglGetConfigAttrib_p = (void*) eglGetProcAddress_p("eglGetConfigAttrib"); + eglGetCurrentContext_p = (void*) eglGetProcAddress_p("eglGetCurrentContext"); + eglGetDisplay_p = (void*) eglGetProcAddress_p("eglGetDisplay"); + eglGetError_p = (void*) eglGetProcAddress_p("eglGetError"); + eglInitialize_p = (void*) eglGetProcAddress_p("eglInitialize"); + eglMakeCurrent_p = (void*) eglGetProcAddress_p("eglMakeCurrent"); + eglSwapBuffers_p = (void*) eglGetProcAddress_p("eglSwapBuffers"); + eglReleaseThread_p = (void*) eglGetProcAddress_p("eglReleaseThread"); + eglSwapInterval_p = (void*) eglGetProcAddress_p("eglSwapInterval"); + eglTerminate_p = (void*) eglGetProcAddress_p("eglTerminate"); + eglGetCurrentSurface_p = (void*) eglGetProcAddress_p("eglGetCurrentSurface"); + return true; } diff --git a/app_pojavlauncher/src/main/jni/ctxbridges/egl_loader.h b/app_pojavlauncher/src/main/jni/ctxbridges/egl_loader.h index 5c761d2621..65b34dae95 100644 --- a/app_pojavlauncher/src/main/jni/ctxbridges/egl_loader.h +++ b/app_pojavlauncher/src/main/jni/ctxbridges/egl_loader.h @@ -2,6 +2,7 @@ // Created by maks on 21.09.2022. // #include +#include #ifndef POJAVLAUNCHER_EGL_LOADER_H #define POJAVLAUNCHER_EGL_LOADER_H @@ -23,7 +24,8 @@ extern EGLint (*eglGetError_p) (void); extern EGLContext (*eglCreateContext_p) (EGLDisplay dpy, EGLConfig config, EGLContext share_list, const EGLint *attrib_list); extern EGLBoolean (*eglSwapInterval_p) (EGLDisplay dpy, EGLint interval); extern EGLSurface (*eglGetCurrentSurface_p) (EGLint readdraw); +extern __eglMustCastToProperFunctionPointerType (*eglGetProcAddress_p) (const char *procname); -void dlsym_EGL(); +bool dlsym_EGL(); #endif //POJAVLAUNCHER_EGL_LOADER_H diff --git a/app_pojavlauncher/src/main/jni/ctxbridges/gl_bridge.c b/app_pojavlauncher/src/main/jni/ctxbridges/gl_bridge.c index a0efdd9414..d4ca7f18a8 100644 --- a/app_pojavlauncher/src/main/jni/ctxbridges/gl_bridge.c +++ b/app_pojavlauncher/src/main/jni/ctxbridges/gl_bridge.c @@ -20,7 +20,7 @@ static __thread gl_render_window_t* currentBundle; static EGLDisplay g_EglDisplay; bool gl_init() { - dlsym_EGL(); + if(!dlsym_EGL()) return false; g_EglDisplay = eglGetDisplay_p(EGL_DEFAULT_DISPLAY); if (g_EglDisplay == EGL_NO_DISPLAY) { __android_log_print(ANDROID_LOG_ERROR, g_LogTag, "%s", diff --git a/app_pojavlauncher/src/main/jni/ctxbridges/loader_dlopen.c b/app_pojavlauncher/src/main/jni/ctxbridges/loader_dlopen.c new file mode 100644 index 0000000000..cc8ff70dad --- /dev/null +++ b/app_pojavlauncher/src/main/jni/ctxbridges/loader_dlopen.c @@ -0,0 +1,24 @@ +// +// Created by maks on 26.10.2024. +// +#include +#include +#include +#include +void* loader_dlopen(char* primaryName, char* secondaryName, int flags) { + void* dl_handle; + if(primaryName == NULL) goto secondary; + + dl_handle = dlopen(primaryName, flags); + if(dl_handle != NULL) return dl_handle; + if(secondaryName == NULL) goto dl_error; + + secondary: + dl_handle = dlopen(secondaryName, flags); + if(dl_handle == NULL) goto dl_error; + return dl_handle; + + dl_error: + printf("%s", dlerror()); + return NULL; +} \ No newline at end of file diff --git a/app_pojavlauncher/src/main/jni/ctxbridges/loader_dlopen.h b/app_pojavlauncher/src/main/jni/ctxbridges/loader_dlopen.h new file mode 100644 index 0000000000..0e23e448ac --- /dev/null +++ b/app_pojavlauncher/src/main/jni/ctxbridges/loader_dlopen.h @@ -0,0 +1,10 @@ +// +// Created by maks on 26.10.2024. +// + +#ifndef POJAVLAUNCHER_LOADER_DLOPEN_H +#define POJAVLAUNCHER_LOADER_DLOPEN_H + +void* loader_dlopen(char* primaryName, char* secondaryName, int flags); + +#endif //POJAVLAUNCHER_LOADER_DLOPEN_H diff --git a/app_pojavlauncher/src/main/jni/ctxbridges/osm_bridge.c b/app_pojavlauncher/src/main/jni/ctxbridges/osm_bridge.c index 9f6e5c6137..814f2e86db 100644 --- a/app_pojavlauncher/src/main/jni/ctxbridges/osm_bridge.c +++ b/app_pojavlauncher/src/main/jni/ctxbridges/osm_bridge.c @@ -16,8 +16,8 @@ static char no_render_buffer[4]; void setNativeWindowSwapInterval(struct ANativeWindow* nativeWindow, int swapInterval); bool osm_init() { - dlsym_OSMesa(); - return true; // no more specific initialization required + if(!dlsym_OSMesa()) return false; + return true; } osm_render_window_t* osm_get_current() { diff --git a/app_pojavlauncher/src/main/jni/ctxbridges/osmesa_loader.c b/app_pojavlauncher/src/main/jni/ctxbridges/osmesa_loader.c index 331e3c9a2d..43cc3a5790 100644 --- a/app_pojavlauncher/src/main/jni/ctxbridges/osmesa_loader.c +++ b/app_pojavlauncher/src/main/jni/ctxbridges/osmesa_loader.c @@ -4,6 +4,7 @@ #include #include #include +#include "loader_dlopen.h" #include "osmesa_loader.h" GLboolean (*OSMesaMakeCurrent_p) (OSMesaContext ctx, void *buffer, GLenum type, @@ -17,26 +18,25 @@ void (*glFinish_p) (void); void (*glClearColor_p) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); void (*glClear_p) (GLbitfield mask); void (*glReadPixels_p) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void * data); +void* (*OSMesaGetProcAddress_p)(const char* funcName); -void dlsym_OSMesa() { - char* main_path = NULL; - char* alt_path = NULL; - if(asprintf(&main_path, "%s/libOSMesa.so", getenv("POJAV_NATIVEDIR")) == -1 || - asprintf(&alt_path, "%s/libOSMesa.so.8", getenv("POJAV_NATIVEDIR")) == -1) { - abort(); +bool dlsym_OSMesa() { + void* dl_handle = loader_dlopen("libOSMesa.so.8", "libOSMesa.so", RTLD_LOCAL | RTLD_LAZY); + if(dl_handle == NULL) return false; + OSMesaGetProcAddress_p = dlsym(dl_handle, "OSMesaGetProcAddress"); + if(OSMesaGetProcAddress_p == NULL) { + printf("%s\n", dlerror()); + return false; } - void* dl_handle = NULL; - dl_handle = dlopen(alt_path, RTLD_GLOBAL); - if(dl_handle == NULL) dl_handle = dlopen(main_path, RTLD_GLOBAL); - if(dl_handle == NULL) abort(); - OSMesaMakeCurrent_p = dlsym(dl_handle, "OSMesaMakeCurrent"); - OSMesaGetCurrentContext_p = dlsym(dl_handle,"OSMesaGetCurrentContext"); - OSMesaCreateContext_p = dlsym(dl_handle, "OSMesaCreateContext"); - OSMesaDestroyContext_p = dlsym(dl_handle, "OSMesaDestroyContext"); - OSMesaPixelStore_p = dlsym(dl_handle,"OSMesaPixelStore"); - glGetString_p = dlsym(dl_handle,"glGetString"); - glClearColor_p = dlsym(dl_handle, "glClearColor"); - glClear_p = dlsym(dl_handle,"glClear"); - glFinish_p = dlsym(dl_handle,"glFinish"); - glReadPixels_p = dlsym(dl_handle,"glReadPixels"); + OSMesaMakeCurrent_p = OSMesaGetProcAddress_p("OSMesaMakeCurrent"); + OSMesaGetCurrentContext_p = OSMesaGetProcAddress_p("OSMesaGetCurrentContext"); + OSMesaCreateContext_p = OSMesaGetProcAddress_p("OSMesaCreateContext"); + OSMesaDestroyContext_p = OSMesaGetProcAddress_p("OSMesaDestroyContext"); + OSMesaPixelStore_p = OSMesaGetProcAddress_p("OSMesaPixelStore"); + glGetString_p = OSMesaGetProcAddress_p("glGetString"); + glClearColor_p = OSMesaGetProcAddress_p("glClearColor"); + glClear_p = OSMesaGetProcAddress_p("glClear"); + glFinish_p = OSMesaGetProcAddress_p("glFinish"); + glReadPixels_p = OSMesaGetProcAddress_p("glReadPixels"); + return true; } \ No newline at end of file diff --git a/app_pojavlauncher/src/main/jni/ctxbridges/osmesa_loader.h b/app_pojavlauncher/src/main/jni/ctxbridges/osmesa_loader.h index 6cb76d25cc..9a876563be 100644 --- a/app_pojavlauncher/src/main/jni/ctxbridges/osmesa_loader.h +++ b/app_pojavlauncher/src/main/jni/ctxbridges/osmesa_loader.h @@ -6,6 +6,7 @@ #define POJAVLAUNCHER_OSMESA_LOADER_H #include +#include extern GLboolean (*OSMesaMakeCurrent_p) (OSMesaContext ctx, void *buffer, GLenum type, GLsizei width, GLsizei height); @@ -18,5 +19,7 @@ extern void (*glFinish_p) (void); extern void (*glClearColor_p) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); extern void (*glClear_p) (GLbitfield mask); extern void (*glReadPixels_p) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void * data); -void dlsym_OSMesa(); +extern void* (*OSMesaGetProcAddress_p)(const char* funcName); + +bool dlsym_OSMesa(); #endif //POJAVLAUNCHER_OSMESA_LOADER_H