mirror of
https://github.com/AngelAuraMC/Amethyst-Android.git
synced 2025-09-14 07:05:40 -04:00
Changes
- Moved all gl4es+egl management into gl_bridge.c and gl_bridge.h - Also, reimplemented it from scratch with surface swapping support
This commit is contained in:
parent
424e6bb630
commit
1261e4a7ea
@ -143,7 +143,10 @@ public class MinecraftGLSurface extends View {
|
|||||||
private boolean isCalled = false;
|
private boolean isCalled = false;
|
||||||
@Override
|
@Override
|
||||||
public void surfaceCreated(@NonNull SurfaceHolder holder) {
|
public void surfaceCreated(@NonNull SurfaceHolder holder) {
|
||||||
if(isCalled) return;
|
if(isCalled) {
|
||||||
|
JREUtils.setupBridgeWindow(surfaceView.getHolder().getSurface());
|
||||||
|
return;
|
||||||
|
}
|
||||||
isCalled = true;
|
isCalled = true;
|
||||||
|
|
||||||
realStart(surfaceView.getHolder().getSurface());
|
realStart(surfaceView.getHolder().getSurface());
|
||||||
@ -168,7 +171,10 @@ public class MinecraftGLSurface extends View {
|
|||||||
private boolean isCalled = false;
|
private boolean isCalled = false;
|
||||||
@Override
|
@Override
|
||||||
public void onSurfaceTextureAvailable(@NonNull SurfaceTexture surface, int width, int height) {
|
public void onSurfaceTextureAvailable(@NonNull SurfaceTexture surface, int width, int height) {
|
||||||
if(isCalled) return;
|
if(isCalled) {
|
||||||
|
JREUtils.setupBridgeWindow(new Surface(surface));
|
||||||
|
return;
|
||||||
|
}
|
||||||
isCalled = true;
|
isCalled = true;
|
||||||
|
|
||||||
realStart(new Surface(textureView.getSurfaceTexture()));
|
realStart(new Surface(textureView.getSurfaceTexture()));
|
||||||
|
@ -33,6 +33,7 @@ LOCAL_MODULE := pojavexec
|
|||||||
# -DGLES_TEST
|
# -DGLES_TEST
|
||||||
LOCAL_SRC_FILES := \
|
LOCAL_SRC_FILES := \
|
||||||
egl_bridge.c \
|
egl_bridge.c \
|
||||||
|
gl_bridge.c \
|
||||||
input_bridge_v3.c \
|
input_bridge_v3.c \
|
||||||
jre_launcher.c \
|
jre_launcher.c \
|
||||||
utils.c
|
utils.c
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#include <android/rect.h>
|
#include <android/rect.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
#include "gl_bridge.h"
|
||||||
// region OSMESA internals
|
// region OSMESA internals
|
||||||
|
|
||||||
struct pipe_screen;
|
struct pipe_screen;
|
||||||
@ -668,6 +669,9 @@ void pojavTerminate() {
|
|||||||
|
|
||||||
JNIEXPORT void JNICALL Java_net_kdt_pojavlaunch_utils_JREUtils_setupBridgeWindow(JNIEnv* env, jclass clazz, jobject surface) {
|
JNIEXPORT void JNICALL Java_net_kdt_pojavlaunch_utils_JREUtils_setupBridgeWindow(JNIEnv* env, jclass clazz, jobject surface) {
|
||||||
potatoBridge.androidWindow = ANativeWindow_fromSurface(env, surface);
|
potatoBridge.androidWindow = ANativeWindow_fromSurface(env, surface);
|
||||||
|
if(config_renderer == RENDERER_GL4ES) {
|
||||||
|
gl_setup_window(potatoBridge.androidWindow);
|
||||||
|
}
|
||||||
char *ptrStr;
|
char *ptrStr;
|
||||||
asprintf(&ptrStr, "%ld", (long) potatoBridge.androidWindow);
|
asprintf(&ptrStr, "%ld", (long) potatoBridge.androidWindow);
|
||||||
setenv("POJAV_WINDOW_PTR", ptrStr, 1);
|
setenv("POJAV_WINDOW_PTR", ptrStr, 1);
|
||||||
@ -813,14 +817,20 @@ int pojavInit() {
|
|||||||
loadSymbolsVirGL();
|
loadSymbolsVirGL();
|
||||||
} else if (strncmp("opengles", renderer, 8) == 0) {
|
} else if (strncmp("opengles", renderer, 8) == 0) {
|
||||||
config_renderer = RENDERER_GL4ES;
|
config_renderer = RENDERER_GL4ES;
|
||||||
loadSymbols();
|
//loadSymbols();
|
||||||
} else if (strcmp(renderer, "vulkan_zink") == 0) {
|
} else if (strcmp(renderer, "vulkan_zink") == 0) {
|
||||||
config_renderer = RENDERER_VK_ZINK;
|
config_renderer = RENDERER_VK_ZINK;
|
||||||
setenv("GALLIUM_DRIVER","zink",1);
|
setenv("GALLIUM_DRIVER","zink",1);
|
||||||
loadSymbols();
|
loadSymbols();
|
||||||
}
|
}
|
||||||
|
if(config_renderer == RENDERER_GL4ES) {
|
||||||
if (config_renderer == RENDERER_GL4ES || config_renderer == RENDERER_VIRGL) {
|
if(gl_init()) {
|
||||||
|
gl_setup_window(potatoBridge.androidWindow);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (config_renderer == RENDERER_VIRGL) {
|
||||||
if (potatoBridge.eglDisplay == NULL || potatoBridge.eglDisplay == EGL_NO_DISPLAY) {
|
if (potatoBridge.eglDisplay == NULL || potatoBridge.eglDisplay == EGL_NO_DISPLAY) {
|
||||||
potatoBridge.eglDisplay = eglGetDisplay_p(EGL_DEFAULT_DISPLAY);
|
potatoBridge.eglDisplay = eglGetDisplay_p(EGL_DEFAULT_DISPLAY);
|
||||||
if (potatoBridge.eglDisplay == EGL_NO_DISPLAY) {
|
if (potatoBridge.eglDisplay == EGL_NO_DISPLAY) {
|
||||||
@ -938,12 +948,7 @@ void pojavSwapBuffers() {
|
|||||||
}
|
}
|
||||||
switch (config_renderer) {
|
switch (config_renderer) {
|
||||||
case RENDERER_GL4ES: {
|
case RENDERER_GL4ES: {
|
||||||
if (!eglSwapBuffers_p(potatoBridge.eglDisplay, eglGetCurrentSurface_p(EGL_DRAW))) {
|
gl_swap_buffers();
|
||||||
if (eglGetError_p() == EGL_BAD_SURFACE) {
|
|
||||||
stopSwapBuffers = true;
|
|
||||||
closeGLFWWindow();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case RENDERER_VIRGL: {
|
case RENDERER_VIRGL: {
|
||||||
@ -993,46 +998,9 @@ void pojavMakeCurrent(void* window) {
|
|||||||
// printf("OSMDroid: skipped context reset\n");
|
// printf("OSMDroid: skipped context reset\n");
|
||||||
// return JNI_TRUE;
|
// return JNI_TRUE;
|
||||||
//}
|
//}
|
||||||
|
if(config_renderer == RENDERER_GL4ES) {
|
||||||
if (config_renderer == RENDERER_GL4ES) {
|
gl_make_current((render_bundle_t*)window);
|
||||||
EGLContext *currCtx = eglGetCurrentContext_p();
|
|
||||||
printf("EGLBridge: Comparing: thr=%d, this=%p, curr=%p\n", gettid(), window, currCtx);
|
|
||||||
if (currCtx == NULL || window == 0) {
|
|
||||||
/*if (window != 0x0 && potatoBridge.eglContextOld != NULL && potatoBridge.eglContextOld != (void *) window) {
|
|
||||||
// Create new pbuffer per thread
|
|
||||||
// TODO get window size for 2nd+ window!
|
|
||||||
int surfaceWidth, surfaceHeight;
|
|
||||||
eglQuerySurface(potatoBridge.eglDisplay, potatoBridge.eglSurface, EGL_WIDTH, &surfaceWidth);
|
|
||||||
eglQuerySurface(potatoBridge.eglDisplay, potatoBridge.eglSurface, EGL_HEIGHT, &surfaceHeight);
|
|
||||||
int surfaceAttr[] = {
|
|
||||||
EGL_WIDTH, surfaceWidth,
|
|
||||||
EGL_HEIGHT, surfaceHeight,
|
|
||||||
EGL_NONE
|
|
||||||
};
|
|
||||||
potatoBridge.eglSurface = eglCreatePbufferSurface(potatoBridge.eglDisplay, config, surfaceAttr);
|
|
||||||
printf("EGLBridge: created pbuffer surface %p for context %p\n", potatoBridge.eglSurface, window);
|
|
||||||
}*/
|
|
||||||
//potatoBridge.eglContextOld = (void *) window;
|
|
||||||
// eglMakeCurrent(potatoBridge.eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
|
||||||
printf("EGLBridge: Making current on window %p on thread %d\n", window, gettid());
|
|
||||||
egl_make_current((void *)window);
|
|
||||||
|
|
||||||
// Test
|
|
||||||
#ifdef GLES_TEST
|
|
||||||
glClearColor(0.4f, 0.4f, 0.4f, 1.0f);
|
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
|
||||||
eglSwapBuffers(potatoBridge.eglDisplay, potatoBridge.eglSurface);
|
|
||||||
printf("First frame error: %p\n", eglGetError());
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// idk this should convert or just `return success;`...
|
|
||||||
return; //success == EGL_TRUE ? JNI_TRUE : JNI_FALSE;
|
|
||||||
} else {
|
|
||||||
// (*env)->ThrowNew(env,(*env)->FindClass(env,"java/lang/Exception"),"Trace exception");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config_renderer == RENDERER_VK_ZINK || config_renderer == RENDERER_VIRGL) {
|
if (config_renderer == RENDERER_VK_ZINK || config_renderer == RENDERER_VIRGL) {
|
||||||
printf("OSMDroid: making current\n");
|
printf("OSMDroid: making current\n");
|
||||||
OSMesaMakeCurrent_p((OSMesaContext)window,gbuffer,GL_UNSIGNED_BYTE,savedWidth,savedHeight);
|
OSMesaMakeCurrent_p((OSMesaContext)window,gbuffer,GL_UNSIGNED_BYTE,savedWidth,savedHeight);
|
||||||
@ -1078,7 +1046,7 @@ Java_org_lwjgl_glfw_GLFW_nativeEglDetachOnCurrentThread(JNIEnv *env, jclass claz
|
|||||||
|
|
||||||
void* pojavCreateContext(void* contextSrc) {
|
void* pojavCreateContext(void* contextSrc) {
|
||||||
if (config_renderer == RENDERER_GL4ES) {
|
if (config_renderer == RENDERER_GL4ES) {
|
||||||
const EGLint ctx_attribs[] = {
|
/*const EGLint ctx_attribs[] = {
|
||||||
EGL_CONTEXT_CLIENT_VERSION, atoi(getenv("LIBGL_ES")),
|
EGL_CONTEXT_CLIENT_VERSION, atoi(getenv("LIBGL_ES")),
|
||||||
EGL_NONE
|
EGL_NONE
|
||||||
};
|
};
|
||||||
@ -1086,7 +1054,8 @@ void* pojavCreateContext(void* contextSrc) {
|
|||||||
potatoBridge.eglContext = ctx;
|
potatoBridge.eglContext = ctx;
|
||||||
printf("EGLBridge: Created CTX pointer = %p\n",ctx);
|
printf("EGLBridge: Created CTX pointer = %p\n",ctx);
|
||||||
//(*env)->ThrowNew(env,(*env)->FindClass(env,"java/lang/Exception"),"Trace exception");
|
//(*env)->ThrowNew(env,(*env)->FindClass(env,"java/lang/Exception"),"Trace exception");
|
||||||
return (long)ctx;
|
return (long)ctx;*/
|
||||||
|
return gl_init_context(contextSrc);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config_renderer == RENDERER_VK_ZINK || config_renderer == RENDERER_VIRGL) {
|
if (config_renderer == RENDERER_VK_ZINK || config_renderer == RENDERER_VIRGL) {
|
||||||
@ -1119,7 +1088,9 @@ Java_org_lwjgl_opengl_GL_getNativeWidthHeight(JNIEnv *env, jobject thiz) {
|
|||||||
}
|
}
|
||||||
void pojavSwapInterval(int interval) {
|
void pojavSwapInterval(int interval) {
|
||||||
switch (config_renderer) {
|
switch (config_renderer) {
|
||||||
case RENDERER_GL4ES:
|
case RENDERER_GL4ES: {
|
||||||
|
gl_swap_interval(interval);
|
||||||
|
} break;
|
||||||
case RENDERER_VIRGL: {
|
case RENDERER_VIRGL: {
|
||||||
eglSwapInterval_p(potatoBridge.eglDisplay, interval);
|
eglSwapInterval_p(potatoBridge.eglDisplay, interval);
|
||||||
} break;
|
} break;
|
||||||
|
189
app_pojavlauncher/src/main/jni/gl_bridge.c
Normal file
189
app_pojavlauncher/src/main/jni/gl_bridge.c
Normal file
@ -0,0 +1,189 @@
|
|||||||
|
#include <EGL/egl.h>
|
||||||
|
#include <android/log.h>
|
||||||
|
#include <android/native_window.h>
|
||||||
|
#include <android/native_window_jni.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include "gl_bridge.h"
|
||||||
|
|
||||||
|
//
|
||||||
|
// Created by maks on 17.09.2022.
|
||||||
|
//
|
||||||
|
|
||||||
|
#define STATE_RENDERER_ALIVE 0
|
||||||
|
#define STATE_RENDERER_NEW_WINDOW 1
|
||||||
|
static char* g_LogTag = "GLBridge";
|
||||||
|
|
||||||
|
EGLBoolean (*eglMakeCurrent_p) (EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx);
|
||||||
|
EGLBoolean (*eglDestroyContext_p) (EGLDisplay dpy, EGLContext ctx);
|
||||||
|
EGLBoolean (*eglDestroySurface_p) (EGLDisplay dpy, EGLSurface surface);
|
||||||
|
EGLBoolean (*eglTerminate_p) (EGLDisplay dpy);
|
||||||
|
EGLBoolean (*eglReleaseThread_p) (void);
|
||||||
|
EGLContext (*eglGetCurrentContext_p) (void);
|
||||||
|
EGLDisplay (*eglGetDisplay_p) (NativeDisplayType display);
|
||||||
|
EGLBoolean (*eglInitialize_p) (EGLDisplay dpy, EGLint *major, EGLint *minor);
|
||||||
|
EGLBoolean (*eglChooseConfig_p) (EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config);
|
||||||
|
EGLBoolean (*eglGetConfigAttrib_p) (EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value);
|
||||||
|
EGLBoolean (*eglBindAPI_p) (EGLenum api);
|
||||||
|
EGLSurface (*eglCreatePbufferSurface_p) (EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list);
|
||||||
|
EGLSurface (*eglCreateWindowSurface_p) (EGLDisplay dpy, EGLConfig config, NativeWindowType window, const EGLint *attrib_list);
|
||||||
|
EGLBoolean (*eglSwapBuffers_p) (EGLDisplay dpy, EGLSurface draw);
|
||||||
|
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);
|
||||||
|
|
||||||
|
struct ANativeWindow* newWindow;
|
||||||
|
static __thread render_bundle_t* currentBundle;
|
||||||
|
static render_bundle_t* mainWindowBundle;
|
||||||
|
EGLDisplay g_EglDisplay;
|
||||||
|
|
||||||
|
void gl_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 gl_init() {
|
||||||
|
gl_dlsym_EGL();
|
||||||
|
g_EglDisplay = eglGetDisplay_p(EGL_DEFAULT_DISPLAY);
|
||||||
|
if (g_EglDisplay == EGL_NO_DISPLAY) {
|
||||||
|
__android_log_print(ANDROID_LOG_ERROR, g_LogTag, "%s",
|
||||||
|
"eglGetDisplay_p(EGL_DEFAULT_DISPLAY) returned EGL_NO_DISPLAY");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (eglInitialize_p(g_EglDisplay, 0, 0) != EGL_TRUE) {
|
||||||
|
__android_log_print(ANDROID_LOG_ERROR, g_LogTag, "eglInitialize_p() failed: %04x",
|
||||||
|
eglGetError_p());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
eglSwapInterval_p(g_EglDisplay, 1);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
render_bundle_t* gl_init_context(render_bundle_t *share) {
|
||||||
|
render_bundle_t* bundle = malloc(sizeof(render_bundle_t));
|
||||||
|
const EGLint egl_attributes[] = { EGL_BLUE_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_RED_SIZE, 8, EGL_ALPHA_SIZE, 8, EGL_DEPTH_SIZE, 24, EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_NONE };
|
||||||
|
EGLint num_configs = 0;
|
||||||
|
if (eglChooseConfig_p(g_EglDisplay, egl_attributes, NULL, 0, &num_configs) != EGL_TRUE) {
|
||||||
|
__android_log_print(ANDROID_LOG_ERROR, g_LogTag, "eglChooseConfig_p() failed: %04x",
|
||||||
|
eglGetError_p());
|
||||||
|
free(bundle);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (num_configs == 0) {
|
||||||
|
__android_log_print(ANDROID_LOG_ERROR, g_LogTag, "%s",
|
||||||
|
"eglChooseConfig_p() found no matching config");
|
||||||
|
free(bundle);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the first matching config
|
||||||
|
eglChooseConfig_p(g_EglDisplay, egl_attributes, &bundle->config, 1, &num_configs);
|
||||||
|
eglGetConfigAttrib_p(g_EglDisplay, bundle->config, EGL_NATIVE_VISUAL_ID, &bundle->format);
|
||||||
|
|
||||||
|
int libgl_es = strtol(getenv("LIBGL_ES"), NULL, 0);
|
||||||
|
if(libgl_es < 0 || libgl_es > INT16_MAX) libgl_es = 2;
|
||||||
|
const EGLint egl_context_attributes[] = { EGL_CONTEXT_CLIENT_VERSION, libgl_es, EGL_NONE };
|
||||||
|
bundle->context = eglCreateContext_p(g_EglDisplay, bundle->context, share == NULL ? EGL_NO_CONTEXT : share->context, egl_context_attributes);
|
||||||
|
|
||||||
|
if (bundle->context == EGL_NO_CONTEXT) {
|
||||||
|
__android_log_print(ANDROID_LOG_ERROR, g_LogTag, "eglCreateContext_p() finished with error: %04x",
|
||||||
|
eglGetError_p());
|
||||||
|
free(bundle);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return bundle;
|
||||||
|
}
|
||||||
|
|
||||||
|
void gl_set_android_surface(render_bundle_t* bundle) {
|
||||||
|
if(bundle->nativeSurface != NULL) {
|
||||||
|
ANativeWindow_release(bundle->nativeSurface);
|
||||||
|
}
|
||||||
|
if(bundle->newNativeSurface != NULL) {
|
||||||
|
__android_log_print(ANDROID_LOG_ERROR, g_LogTag, "Switching to new native surface");
|
||||||
|
bundle->nativeSurface = bundle->newNativeSurface;
|
||||||
|
ANativeWindow_acquire(bundle->nativeSurface);
|
||||||
|
ANativeWindow_setBuffersGeometry(bundle->nativeSurface, 0, 0, bundle->format);
|
||||||
|
bundle->surface = eglCreateWindowSurface_p(g_EglDisplay, bundle->config, bundle->nativeSurface, NULL);
|
||||||
|
}else{
|
||||||
|
__android_log_print(ANDROID_LOG_ERROR, g_LogTag, "No new native surface, disabling surfaces");
|
||||||
|
bundle->nativeSurface = NULL;
|
||||||
|
bundle->surface = NULL;
|
||||||
|
}
|
||||||
|
//eglMakeCurrent_p(g_EglDisplay, bundle->surface, bundle->surface, bundle->context);
|
||||||
|
}
|
||||||
|
|
||||||
|
void gl_make_current(render_bundle_t* bundle) {
|
||||||
|
if(bundle == NULL) {
|
||||||
|
__android_log_print(ANDROID_LOG_FATAL, g_LogTag, "Cannot make a NULL bundle current!");
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
__android_log_print(ANDROID_LOG_INFO, g_LogTag, "Making current, surface=%p, nativeSurface=%p, newNativeSurface=%p", bundle->surface, bundle->nativeSurface, bundle->newNativeSurface);
|
||||||
|
if(bundle->surface == NULL) { //it likely will be on the first run
|
||||||
|
if(bundle->nativeSurface || bundle->newNativeSurface) gl_set_android_surface(bundle);
|
||||||
|
}
|
||||||
|
if(eglMakeCurrent_p(g_EglDisplay, bundle->surface, bundle->surface, bundle->context)) {
|
||||||
|
currentBundle = bundle;
|
||||||
|
}else __android_log_print(ANDROID_LOG_ERROR, g_LogTag, "eglMakeCurrent returned with error: %04x", eglGetError_p());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void gl_swap_buffers() {
|
||||||
|
if(mainWindowBundle == NULL) {
|
||||||
|
mainWindowBundle = currentBundle;
|
||||||
|
__android_log_print(ANDROID_LOG_INFO, g_LogTag, "Main window bundle is now %p", mainWindowBundle);
|
||||||
|
mainWindowBundle->state = STATE_RENDERER_NEW_WINDOW;
|
||||||
|
mainWindowBundle->newNativeSurface = newWindow;
|
||||||
|
}
|
||||||
|
if(currentBundle->state == STATE_RENDERER_NEW_WINDOW) {
|
||||||
|
eglMakeCurrent_p(g_EglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); //detach everything to destroy the old EGLSurface
|
||||||
|
if(currentBundle->surface != NULL) eglDestroySurface_p(g_EglDisplay, currentBundle->surface);
|
||||||
|
gl_set_android_surface(currentBundle);
|
||||||
|
eglMakeCurrent_p(g_EglDisplay, currentBundle->surface, currentBundle->surface, currentBundle->context);
|
||||||
|
currentBundle->state = STATE_RENDERER_ALIVE;
|
||||||
|
}
|
||||||
|
if(currentBundle->surface != NULL)
|
||||||
|
if(!eglSwapBuffers_p(g_EglDisplay, currentBundle->surface) && eglGetError_p() == EGL_BAD_SURFACE) {
|
||||||
|
eglMakeCurrent_p(g_EglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||||
|
eglDestroySurface_p(g_EglDisplay, currentBundle->surface);
|
||||||
|
currentBundle->surface = NULL;
|
||||||
|
__android_log_print(ANDROID_LOG_INFO, g_LogTag, "The window has died, awaiting window change");
|
||||||
|
eglMakeCurrent_p(g_EglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, currentBundle->context);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void gl_setup_window(struct ANativeWindow* window) {
|
||||||
|
if(mainWindowBundle != NULL) {
|
||||||
|
mainWindowBundle->state = STATE_RENDERER_NEW_WINDOW;
|
||||||
|
mainWindowBundle->newNativeSurface = window;
|
||||||
|
}else{
|
||||||
|
newWindow = window;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void gl_swap_interval(int swapInterval) {
|
||||||
|
eglSwapInterval_p(g_EglDisplay, swapInterval);
|
||||||
|
}
|
26
app_pojavlauncher/src/main/jni/gl_bridge.h
Normal file
26
app_pojavlauncher/src/main/jni/gl_bridge.h
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
//
|
||||||
|
// Created by maks on 17.09.2022.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef POJAVLAUNCHER_GL_BRIDGE_H
|
||||||
|
#define POJAVLAUNCHER_GL_BRIDGE_H
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char state;
|
||||||
|
EGLConfig config;
|
||||||
|
EGLint format;
|
||||||
|
EGLContext context;
|
||||||
|
EGLSurface surface;
|
||||||
|
struct ANativeWindow *nativeSurface;
|
||||||
|
struct ANativeWindow *newNativeSurface;
|
||||||
|
} render_bundle_t;
|
||||||
|
|
||||||
|
bool gl_init();
|
||||||
|
render_bundle_t* gl_init_context(render_bundle_t* share);
|
||||||
|
void gl_make_current(render_bundle_t* bundle);
|
||||||
|
void gl_swap_buffers();
|
||||||
|
void gl_setup_window(struct ANativeWindow* window);
|
||||||
|
void gl_swap_interval(int swapInterval);
|
||||||
|
|
||||||
|
|
||||||
|
#endif //POJAVLAUNCHER_GL_BRIDGE_H
|
Loading…
x
Reference in New Issue
Block a user