New thing: pojav_environ

Now, instead of using a lot of env vars, we have a global thing: the pojav_environ!
It provides a global storage between libraries that were loaded multiple times. Currently it is used to store config_renderer, the Pojav window and the main window bundle of gl bridge.
It finally swaps surfaces on my device!
This commit is contained in:
Boulay Mathias 2022-10-03 19:52:10 +02:00
parent 0e7d663974
commit 4841f6a4d3
6 changed files with 98 additions and 61 deletions

View File

@ -36,6 +36,7 @@ LOCAL_SRC_FILES := \
ctxbridges/gl_bridge.c \
ctxbridges/egl_loader.c \
ctxbridges/osmesa_loader.c \
environ/environ.c \
input_bridge_v3.c \
jre_launcher.c \
utils.c

View File

@ -7,6 +7,7 @@
#include <stdlib.h>
#include <dlfcn.h>
#include <stdbool.h>
#include <environ/environ.h>
#include "gl_bridge.h"
#include "egl_loader.h"
@ -17,9 +18,7 @@
#define STATE_RENDERER_ALIVE 0
#define STATE_RENDERER_NEW_WINDOW 1
static const char* g_LogTag = "GLBridge";
struct ANativeWindow* newWindow;
static __thread render_window_t* currentBundle;
static render_window_t* mainWindowBundle;
static EGLDisplay g_EglDisplay;
bool gl_init() {
@ -104,10 +103,10 @@ void gl_make_current(render_window_t* bundle) {
return;
}
bool hasSetMainWindow = false;
if(mainWindowBundle == NULL) {
mainWindowBundle = bundle;
__android_log_print(ANDROID_LOG_INFO, g_LogTag, "Main window bundle is now %p", mainWindowBundle);
mainWindowBundle->newNativeSurface = newWindow;
if(pojav_environ->mainWindowBundle == NULL) {
pojav_environ->mainWindowBundle = bundle;
__android_log_print(ANDROID_LOG_INFO, g_LogTag, "Main window bundle is now %p", pojav_environ->mainWindowBundle);
pojav_environ->mainWindowBundle->newNativeSurface = pojav_environ->pojavWindow;
hasSetMainWindow = true;
}
__android_log_print(ANDROID_LOG_INFO, g_LogTag, "Making current, surface=%p, nativeSurface=%p, newNativeSurface=%p", bundle->surface, bundle->nativeSurface, bundle->newNativeSurface);
@ -118,9 +117,9 @@ void gl_make_current(render_window_t* bundle) {
currentBundle = bundle;
}else {
if(hasSetMainWindow) {
mainWindowBundle->newNativeSurface = NULL;
gl_swap_surface(mainWindowBundle);
mainWindowBundle = NULL;
pojav_environ->mainWindowBundle->newNativeSurface = NULL;
gl_swap_surface(pojav_environ->mainWindowBundle);
pojav_environ->mainWindowBundle = NULL;
}
__android_log_print(ANDROID_LOG_ERROR, g_LogTag, "eglMakeCurrent returned with error: %04x", eglGetError_p());
}
@ -145,12 +144,11 @@ void gl_swap_buffers() {
}
void gl_setup_window(struct ANativeWindow* window) {
if(mainWindowBundle != NULL) {
mainWindowBundle->state = STATE_RENDERER_NEW_WINDOW;
mainWindowBundle->newNativeSurface = window;
}else{
newWindow = window;
void gl_setup_window() {
if(pojav_environ->mainWindowBundle != NULL) {
__android_log_print(ANDROID_LOG_INFO, g_LogTag, "Main window bundle is not NULL, changing state");
pojav_environ->mainWindowBundle->state = STATE_RENDERER_NEW_WINDOW;
pojav_environ->mainWindowBundle->newNativeSurface = pojav_environ->pojavWindow;
}
}

View File

@ -1,7 +1,8 @@
//
// Created by maks on 17.09.2022.
//
#include <EGL//egl.h>
#include <stdbool.h>
#ifndef POJAVLAUNCHER_GL_BRIDGE_H
#define POJAVLAUNCHER_GL_BRIDGE_H
@ -19,7 +20,7 @@ bool gl_init();
render_window_t* gl_init_context(render_window_t* share);
void gl_make_current(render_window_t* bundle);
void gl_swap_buffers();
void gl_setup_window(struct ANativeWindow* window);
void gl_setup_window();
void gl_swap_interval(int swapInterval);

View File

@ -20,6 +20,7 @@
#include <android/native_window_jni.h>
#include <android/rect.h>
#include <string.h>
#include <environ/environ.h>
#include "utils.h"
#include "ctxbridges/gl_bridge.h"
// region OSMESA internals
@ -580,7 +581,6 @@ typedef struct osmesa_context
};
// endregion OSMESA internals
struct PotatoBridge {
/*ANativeWindow */ void* androidWindow;
/* EGLContext */ void* eglContextOld;
/* EGLContext */ void* eglContext;
@ -603,7 +603,6 @@ void (*vtest_swap_buffers_p) (void);
#define RENDERER_VK_ZINK 2
#define RENDERER_VIRGL 3
int config_renderer;
void* gbuffer;
void* egl_make_current(void* window);
@ -617,7 +616,7 @@ void pojav_openGLOnUnload() {
void pojavTerminate() {
printf("EGLBridge: Terminating\n");
switch (config_renderer) {
switch (pojav_environ->config_renderer) {
case RENDERER_GL4ES: {
eglMakeCurrent_p(potatoBridge.eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
eglDestroySurface_p(potatoBridge.eglDisplay, potatoBridge.eglSurface);
@ -638,24 +637,20 @@ void pojavTerminate() {
}
JNIEXPORT void JNICALL Java_net_kdt_pojavlaunch_utils_JREUtils_setupBridgeWindow(JNIEnv* env, jclass clazz, jobject surface) {
potatoBridge.androidWindow = ANativeWindow_fromSurface(env, surface);
if(config_renderer == RENDERER_GL4ES) {
gl_setup_window(potatoBridge.androidWindow);
pojav_environ->pojavWindow = ANativeWindow_fromSurface(env, surface);
if(pojav_environ->config_renderer == RENDERER_GL4ES) {
gl_setup_window();
}
char *ptrStr;
asprintf(&ptrStr, "%ld", (long) potatoBridge.androidWindow);
setenv("POJAV_WINDOW_PTR", ptrStr, 1);
free(ptrStr);
}
JNIEXPORT void JNICALL
Java_net_kdt_pojavlaunch_utils_JREUtils_releaseBridgeWindow(JNIEnv *env, jclass clazz) {
ANativeWindow_release(potatoBridge.androidWindow);
ANativeWindow_release(pojav_environ->pojavWindow);
}
void* pojavGetCurrentContext() {
switch (config_renderer) {
switch (pojav_environ->config_renderer) {
case RENDERER_GL4ES:
return (void *)eglGetCurrentContext_p();
case RENDERER_VIRGL:
@ -701,7 +696,7 @@ void dlsym_OSMesa(void* dl_handle) {
}*/
bool loadSymbols() {
switch (config_renderer) {
switch (pojav_environ->config_renderer) {
case RENDERER_VIRGL:
dlsym_EGL();
case RENDERER_VK_ZINK:
@ -714,7 +709,7 @@ bool loadSymbols() {
}
bool loadSymbolsVirGL() {
config_renderer = RENDERER_VIRGL;
pojav_environ->config_renderer = RENDERER_VIRGL;
loadSymbols();
char* fileName = calloc(1, 1024);
@ -732,16 +727,15 @@ bool loadSymbolsVirGL() {
}
int pojavInit() {
potatoBridge.androidWindow = (void *)atol(getenv("POJAV_WINDOW_PTR"));
ANativeWindow_acquire(potatoBridge.androidWindow);
savedWidth = ANativeWindow_getWidth(potatoBridge.androidWindow);
savedHeight = ANativeWindow_getHeight(potatoBridge.androidWindow);
ANativeWindow_setBuffersGeometry(potatoBridge.androidWindow,savedWidth,savedHeight,AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM);
ANativeWindow_acquire(pojav_environ->pojavWindow);
savedWidth = ANativeWindow_getWidth(pojav_environ->pojavWindow);
savedHeight = ANativeWindow_getHeight(pojav_environ->pojavWindow);
ANativeWindow_setBuffersGeometry(pojav_environ->pojavWindow,savedWidth,savedHeight,AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM);
// NOTE: Override for now.
const char *renderer = getenv("POJAV_RENDERER");
if (strncmp("opengles3_virgl", renderer, 15) == 0) {
config_renderer = RENDERER_VIRGL;
pojav_environ->config_renderer = RENDERER_VIRGL;
setenv("GALLIUM_DRIVER","virpipe",1);
setenv("OSMESA_NO_FLUSH_FRONTBUFFER","1",false);
if(strcmp(getenv("OSMESA_NO_FLUSH_FRONTBUFFER"),"1") == 0) {
@ -749,21 +743,21 @@ int pojavInit() {
}
loadSymbolsVirGL();
} else if (strncmp("opengles", renderer, 8) == 0) {
config_renderer = RENDERER_GL4ES;
pojav_environ->config_renderer = RENDERER_GL4ES;
//loadSymbols();
} else if (strcmp(renderer, "vulkan_zink") == 0) {
config_renderer = RENDERER_VK_ZINK;
pojav_environ->config_renderer = RENDERER_VK_ZINK;
setenv("GALLIUM_DRIVER","zink",1);
loadSymbols();
}
if(config_renderer == RENDERER_GL4ES) {
if(pojav_environ->config_renderer == RENDERER_GL4ES) {
if(gl_init()) {
gl_setup_window(potatoBridge.androidWindow);
gl_setup_window(pojav_environ->pojavWindow);
return 1;
}
return 0;
}
if (config_renderer == RENDERER_VIRGL) {
if (pojav_environ->config_renderer == RENDERER_VIRGL) {
if (potatoBridge.eglDisplay == NULL || potatoBridge.eglDisplay == EGL_NO_DISPLAY) {
potatoBridge.eglDisplay = eglGetDisplay_p(EGL_DEFAULT_DISPLAY);
if (potatoBridge.eglDisplay == EGL_NO_DISPLAY) {
@ -773,7 +767,7 @@ int pojavInit() {
}
printf("EGLBridge: Initializing\n");
// printf("EGLBridge: ANativeWindow pointer = %p\n", potatoBridge.androidWindow);
// printf("EGLBridge: ANativeWindow pointer = %p\n", pojav_environ->pojavWindow);
//(*env)->ThrowNew(env,(*env)->FindClass(env,"java/lang/Exception"),"Trace exception");
if (!eglInitialize_p(potatoBridge.eglDisplay, NULL, NULL)) {
printf("EGLBridge: Error eglInitialize() failed: %s\n", eglGetError_p());
@ -807,11 +801,11 @@ int pojavInit() {
return 0;
}
ANativeWindow_setBuffersGeometry(potatoBridge.androidWindow, 0, 0, vid);
ANativeWindow_setBuffersGeometry(pojav_environ->pojavWindow, 0, 0, vid);
eglBindAPI_p(EGL_OPENGL_ES_API);
potatoBridge.eglSurface = eglCreateWindowSurface_p(potatoBridge.eglDisplay, config, potatoBridge.androidWindow, NULL);
potatoBridge.eglSurface = eglCreateWindowSurface_p(potatoBridge.eglDisplay, config, pojav_environ->pojavWindow, NULL);
if (!potatoBridge.eglSurface) {
printf("EGLBridge: Error eglCreateWindowSurface failed: %p\n", eglGetError_p());
@ -833,12 +827,12 @@ int pojavInit() {
potatoBridge.eglDisplay,
potatoBridge.eglSurface
);
if (config_renderer != RENDERER_VIRGL) {
if (pojav_environ->config_renderer != RENDERER_VIRGL) {
return 1;
}
}
if (config_renderer == RENDERER_VIRGL) {
if (pojav_environ->config_renderer == RENDERER_VIRGL) {
// Init EGL context and vtest server
const EGLint ctx_attribs[] = {
EGL_CONTEXT_CLIENT_VERSION, 3,
@ -852,7 +846,7 @@ int pojavInit() {
usleep(100*1000); // need enough time for the server to init
}
if (config_renderer == RENDERER_VK_ZINK || config_renderer == RENDERER_VIRGL) {
if (pojav_environ->config_renderer == RENDERER_VK_ZINK || pojav_environ->config_renderer == RENDERER_VIRGL) {
if(OSMesaCreateContext_p == NULL) {
printf("OSMDroid: %s\n",dlerror());
return 0;
@ -879,7 +873,7 @@ void pojavSwapBuffers() {
if (stopSwapBuffers) {
return;
}
switch (config_renderer) {
switch (pojav_environ->config_renderer) {
case RENDERER_GL4ES: {
gl_swap_buffers();
} break;
@ -897,9 +891,9 @@ void pojavSwapBuffers() {
}
OSMesaMakeCurrent_p(ctx,buf.bits,GL_UNSIGNED_BYTE,savedWidth,savedHeight);
glFinish_p();
ANativeWindow_unlockAndPost(potatoBridge.androidWindow);
ANativeWindow_unlockAndPost(pojav_environ->pojavWindow);
//OSMesaMakeCurrent_p(ctx,gbuffer,GL_UNSIGNED_BYTE,savedWidth,savedHeight);
ANativeWindow_lock(potatoBridge.androidWindow,&buf,NULL);
ANativeWindow_lock(pojav_environ->pojavWindow,&buf,NULL);
} break;
}
}
@ -918,7 +912,7 @@ void* egl_make_current(void* window) {
printf("EGLBridge: eglMakeCurrent() succeed!\n");
}
if (config_renderer == RENDERER_VIRGL) {
if (pojav_environ->config_renderer == RENDERER_VIRGL) {
printf("VirGL: vtest_main = %p\n", vtest_main_p);
printf("VirGL: Calling VTest server's main function\n");
vtest_main_p(3, (const char*[]){"vtest", "--no-loop-or-fork", "--use-gles", NULL, NULL});
@ -931,17 +925,17 @@ void pojavMakeCurrent(void* window) {
// printf("OSMDroid: skipped context reset\n");
// return JNI_TRUE;
//}
if(config_renderer == RENDERER_GL4ES) {
if(pojav_environ->config_renderer == RENDERER_GL4ES) {
gl_make_current((render_window_t*)window);
}
if (config_renderer == RENDERER_VK_ZINK || config_renderer == RENDERER_VIRGL) {
if (pojav_environ->config_renderer == RENDERER_VK_ZINK || pojav_environ->config_renderer == RENDERER_VIRGL) {
printf("OSMDroid: making current\n");
OSMesaMakeCurrent_p((OSMesaContext)window,gbuffer,GL_UNSIGNED_BYTE,savedWidth,savedHeight);
if (config_renderer == RENDERER_VK_ZINK) {
ANativeWindow_lock(potatoBridge.androidWindow,&buf,NULL);
if (pojav_environ->config_renderer == RENDERER_VK_ZINK) {
ANativeWindow_lock(pojav_environ->pojavWindow,&buf,NULL);
OSMesaPixelStore_p(OSMESA_ROW_LENGTH,buf.stride);
stride = buf.stride;
//ANativeWindow_unlockAndPost(potatoBridge.androidWindow);
//ANativeWindow_unlockAndPost(pojav_environ->pojavWindow);
OSMesaPixelStore_p(OSMESA_Y_UP,0);
}
@ -964,7 +958,7 @@ JNIEXPORT void JNICALL
Java_org_lwjgl_glfw_GLFW_nativeEglDetachOnCurrentThread(JNIEnv *env, jclass clazz) {
//Obstruct the context on the current thread
switch (config_renderer) {
switch (pojav_environ->config_renderer) {
case RENDERER_GL4ES: {
eglMakeCurrent_p(potatoBridge.eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
} break;
@ -978,7 +972,7 @@ Java_org_lwjgl_glfw_GLFW_nativeEglDetachOnCurrentThread(JNIEnv *env, jclass claz
*/
void* pojavCreateContext(void* contextSrc) {
if (config_renderer == RENDERER_GL4ES) {
if (pojav_environ->config_renderer == RENDERER_GL4ES) {
/*const EGLint ctx_attribs[] = {
EGL_CONTEXT_CLIENT_VERSION, atoi(getenv("LIBGL_ES")),
EGL_NONE
@ -991,7 +985,7 @@ void* pojavCreateContext(void* contextSrc) {
return gl_init_context(contextSrc);
}
if (config_renderer == RENDERER_VK_ZINK || config_renderer == RENDERER_VIRGL) {
if (pojav_environ->config_renderer == RENDERER_VK_ZINK || pojav_environ->config_renderer == RENDERER_VIRGL) {
printf("OSMDroid: generating context\n");
void* ctx = OSMesaCreateContext_p(OSMESA_RGBA,contextSrc);
printf("OSMDroid: context=%p\n",ctx);
@ -1020,7 +1014,7 @@ Java_org_lwjgl_opengl_GL_getNativeWidthHeight(JNIEnv *env, jobject thiz) {
return ret;
}
void pojavSwapInterval(int interval) {
switch (config_renderer) {
switch (pojav_environ->config_renderer) {
case RENDERER_GL4ES: {
gl_swap_interval(interval);
} break;

View File

@ -0,0 +1,26 @@
//
// Created by maks on 24.09.2022.
//
#include <stdlib.h>
#include <android/log.h>
#include <assert.h>
#include <string.h>
#include "environ.h"
struct pojav_environ_s *pojav_environ;
__attribute__((constructor)) void env_init() {
char* strptr_env = getenv("POJAV_ENVIRON");
if(strptr_env == NULL) {
__android_log_print(ANDROID_LOG_INFO, "Environ", "No environ found, creating...");
pojav_environ = malloc(sizeof(struct pojav_environ_s));
assert(pojav_environ);
memset(pojav_environ, 0 , sizeof(struct pojav_environ_s));
assert(asprintf(&strptr_env, "%p", pojav_environ) != -1);
setenv("POJAV_ENVIRON", strptr_env, 1);
free(strptr_env);
}else{
__android_log_print(ANDROID_LOG_INFO, "Environ", "Found existing environ: %s", strptr_env);
pojav_environ = (void*) strtoul(strptr_env, NULL, 0x10);
}
__android_log_print(ANDROID_LOG_INFO, "Environ", "%p", pojav_environ);
}

View File

@ -0,0 +1,17 @@
//
// Created by maks on 24.09.2022.
//
#ifndef POJAVLAUNCHER_ENVIRON_H
#define POJAVLAUNCHER_ENVIRON_H
#include <ctxbridges/gl_bridge.h>
struct pojav_environ_s {
struct ANativeWindow* pojavWindow;
render_window_t* mainWindowBundle;
int config_renderer;
};
extern struct pojav_environ_s *pojav_environ;
#endif //POJAVLAUNCHER_ENVIRON_H