Skip to content

Commit

Permalink
Refactor: Unified egl_bridge implementation (#4816)
Browse files Browse the repository at this point in the history
* Start working on bridge unification

* Fin[bridge]: unified bridge structure

* Fix[egl_bridge]: remove legacy functions and make initialization more early

* Fix[bridge_tbl]: add forgotten gl_get_current

* Clean[jre_launcher]: remove stray adrsp_test() declaration
  • Loading branch information
artdeell authored Nov 6, 2023
1 parent 9a24cde commit 682fe04
Show file tree
Hide file tree
Showing 10 changed files with 274 additions and 142 deletions.
2 changes: 2 additions & 0 deletions app_pojavlauncher/src/main/jni/Android.mk
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,15 @@ LOCAL_SRC_FILES := \
bigcoreaffinity.c \
egl_bridge.c \
ctxbridges/gl_bridge.c \
ctxbridges/osm_bridge.c \
ctxbridges/egl_loader.c \
ctxbridges/osmesa_loader.c \
environ/environ.c \
input_bridge_v3.c \
jre_launcher.c \
utils.c \
driver_helper/nsbypass.c

ifeq ($(TARGET_ARCH_ABI),arm64-v8a)
LOCAL_CFLAGS += -DADRENO_POSSIBLE
LOCAL_LDLIBS += -lEGL -lGLESv2
Expand Down
45 changes: 45 additions & 0 deletions app_pojavlauncher/src/main/jni/ctxbridges/bridge_tbl.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
//
// Created by maks on 18.10.2023.
//

#ifndef POJAVLAUNCHER_BRIDGE_TBL_H
#define POJAVLAUNCHER_BRIDGE_TBL_H

#include <ctxbridges/common.h>
#include <ctxbridges/gl_bridge.h>
#include <ctxbridges/osm_bridge.h>

typedef basic_render_window_t* (*br_init_context_t)(basic_render_window_t* share);
typedef void (*br_make_current_t)(basic_render_window_t* bundle);
typedef basic_render_window_t* (*br_get_current_t)();

bool (*br_init)() = NULL;
br_init_context_t br_init_context = NULL;
br_make_current_t br_make_current = NULL;
br_get_current_t br_get_current = NULL;
void (*br_swap_buffers)() = NULL;
void (*br_setup_window)() = NULL;
void (*br_swap_interval)(int swapInterval) = NULL;


void set_osm_bridge_tbl() {
br_init = osm_init;
br_init_context = (br_init_context_t) osm_init_context;
br_make_current = (br_make_current_t) osm_make_current;
br_get_current = (br_get_current_t) osm_get_current;
br_swap_buffers = osm_swap_buffers;
br_setup_window = osm_setup_window;
br_swap_interval = osm_swap_interval;
}

void set_gl_bridge_tbl() {
br_init = gl_init;
br_init_context = (br_init_context_t) gl_init_context;
br_make_current = (br_make_current_t) gl_make_current;
br_get_current = (br_get_current_t) gl_get_current;
br_swap_buffers = gl_swap_buffers;
br_setup_window = gl_setup_window;
br_swap_interval = gl_swap_interval;
}

#endif //POJAVLAUNCHER_BRIDGE_TBL_H
17 changes: 17 additions & 0 deletions app_pojavlauncher/src/main/jni/ctxbridges/common.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//
// Created by maks on 18.10.2023.
//

#ifndef POJAVLAUNCHER_COMMON_H
#define POJAVLAUNCHER_COMMON_H

#define STATE_RENDERER_ALIVE 0
#define STATE_RENDERER_NEW_WINDOW 1

typedef struct {
char state;
struct ANativeWindow *nativeSurface;
struct ANativeWindow *newNativeSurface;
} basic_render_window_t;

#endif //POJAVLAUNCHER_COMMON_H
22 changes: 12 additions & 10 deletions app_pojavlauncher/src/main/jni/ctxbridges/gl_bridge.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,8 @@
// Created by maks on 17.09.2022.
//

#define STATE_RENDERER_ALIVE 0
#define STATE_RENDERER_NEW_WINDOW 1
static const char* g_LogTag = "GLBridge";
static __thread render_window_t* currentBundle;
static __thread gl_render_window_t* currentBundle;
static EGLDisplay g_EglDisplay;

bool gl_init() {
Expand All @@ -37,9 +35,13 @@ bool gl_init() {
return true;
}

render_window_t* gl_init_context(render_window_t *share) {
render_window_t* bundle = malloc(sizeof(render_window_t));
memset(bundle, 0, sizeof(render_window_t));
gl_render_window_t* gl_get_current() {
return currentBundle;
}

gl_render_window_t* gl_init_context(gl_render_window_t *share) {
gl_render_window_t* bundle = malloc(sizeof(gl_render_window_t));
memset(bundle, 0, sizeof(gl_render_window_t));
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_PBUFFER_BIT, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_NONE };
EGLint num_configs = 0;

Expand Down Expand Up @@ -86,7 +88,7 @@ render_window_t* gl_init_context(render_window_t *share) {
return bundle;
}

void gl_swap_surface(render_window_t* bundle) {
void gl_swap_surface(gl_render_window_t* bundle) {
if(bundle->nativeSurface != NULL) {
ANativeWindow_release(bundle->nativeSurface);
}
Expand All @@ -107,7 +109,7 @@ void gl_swap_surface(render_window_t* bundle) {
//eglMakeCurrent_p(g_EglDisplay, bundle->surface, bundle->surface, bundle->context);
}

void gl_make_current(render_window_t* bundle) {
void gl_make_current(gl_render_window_t* bundle) {
if(bundle == NULL) {
if(eglMakeCurrent_p(g_EglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)) {
currentBundle = NULL;
Expand All @@ -116,7 +118,7 @@ void gl_make_current(render_window_t* bundle) {
}
bool hasSetMainWindow = false;
if(pojav_environ->mainWindowBundle == NULL) {
pojav_environ->mainWindowBundle = bundle;
pojav_environ->mainWindowBundle = (basic_render_window_t*)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;
Expand All @@ -130,7 +132,7 @@ void gl_make_current(render_window_t* bundle) {
}else {
if(hasSetMainWindow) {
pojav_environ->mainWindowBundle->newNativeSurface = NULL;
gl_swap_surface(pojav_environ->mainWindowBundle);
gl_swap_surface((gl_render_window_t*)pojav_environ->mainWindowBundle);
pojav_environ->mainWindowBundle = NULL;
}
__android_log_print(ANDROID_LOG_ERROR, g_LogTag, "eglMakeCurrent returned with error: %04x", eglGetError_p());
Expand Down
11 changes: 6 additions & 5 deletions app_pojavlauncher/src/main/jni/ctxbridges/gl_bridge.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,18 @@

typedef struct {
char state;
struct ANativeWindow *nativeSurface;
struct ANativeWindow *newNativeSurface;
EGLConfig config;
EGLint format;
EGLContext context;
EGLSurface surface;
struct ANativeWindow *nativeSurface;
struct ANativeWindow *newNativeSurface;
} render_window_t;
} gl_render_window_t;

bool gl_init();
render_window_t* gl_init_context(render_window_t* share);
void gl_make_current(render_window_t* bundle);
gl_render_window_t* gl_get_current();
gl_render_window_t* gl_init_context(gl_render_window_t* share);
void gl_make_current(gl_render_window_t* bundle);
void gl_swap_buffers();
void gl_setup_window();
void gl_swap_interval(int swapInterval);
Expand Down
138 changes: 138 additions & 0 deletions app_pojavlauncher/src/main/jni/ctxbridges/osm_bridge.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
//
// Created by maks on 18.10.2023.
//
#include <malloc.h>
#include <string.h>
#include <environ/environ.h>
#include <android/log.h>
#include "osm_bridge.h"

static const char* g_LogTag = "GLBridge";
static __thread osm_render_window_t* currentBundle;
// a tiny buffer for rendering when there's nowhere t render
static char no_render_buffer[4];

bool osm_init() {
dlsym_OSMesa();
return true; // no more specific initialization required
}

osm_render_window_t* osm_get_current() {
return currentBundle;
}

osm_render_window_t* osm_init_context(osm_render_window_t* share) {
osm_render_window_t* render_window = malloc(sizeof(osm_render_window_t));
if(render_window == NULL) return NULL;
memset(render_window, 0, sizeof(osm_render_window_t));
OSMesaContext osmesa_share = NULL;
if(share != NULL) osmesa_share = share->context;
OSMesaContext context = OSMesaCreateContext_p(GL_RGBA, osmesa_share);
if(context == NULL) {
free(render_window);
return NULL;
}
render_window->context = context;
return render_window;
}

void osm_set_no_render_buffer(ANativeWindow_Buffer* buffer) {
buffer->bits = &no_render_buffer;
buffer->width = 1;
buffer->height = 1;
buffer->stride = 0;
}

void osm_swap_surfaces(osm_render_window_t* bundle) {
if(bundle->nativeSurface != NULL && bundle->newNativeSurface != bundle->nativeSurface) {
if(!bundle->disable_rendering) {
__android_log_print(ANDROID_LOG_INFO, g_LogTag, "Unlocking for cleanup...");
ANativeWindow_unlockAndPost(bundle->nativeSurface);
}
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;
bundle->newNativeSurface = NULL;
ANativeWindow_acquire(bundle->nativeSurface);
ANativeWindow_setBuffersGeometry(bundle->nativeSurface, 0, 0, WINDOW_FORMAT_RGBX_8888);
bundle->disable_rendering = false;
return;
}else {
__android_log_print(ANDROID_LOG_ERROR, g_LogTag,
"No new native surface, switching to dummy framebuffer");
bundle->nativeSurface = NULL;
osm_set_no_render_buffer(&bundle->buffer);
bundle->disable_rendering = true;
}

}

void osm_release_window() {
currentBundle->newNativeSurface = NULL;
osm_swap_surfaces(currentBundle);
}

void osm_apply_current_ll() {
ANativeWindow_Buffer* buffer = &currentBundle->buffer;
OSMesaMakeCurrent_p(currentBundle->context, buffer->bits, GL_UNSIGNED_BYTE, buffer->width, buffer->height);
if(buffer->stride != currentBundle->last_stride)
OSMesaPixelStore_p(OSMESA_ROW_LENGTH, buffer->stride);
currentBundle->last_stride = buffer->stride;
}

void osm_make_current(osm_render_window_t* bundle) {
if(bundle == NULL) {
//technically this does nothing as its not possible to unbind a context in OSMesa
OSMesaMakeCurrent_p(NULL, NULL, 0, 0, 0);
currentBundle = NULL;
return;
}
bool hasSetMainWindow = false;
currentBundle = bundle;
if(pojav_environ->mainWindowBundle == NULL) {
pojav_environ->mainWindowBundle = (basic_render_window_t*) 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;
}
if(bundle->nativeSurface == NULL) {
//prepare the buffer for our first render!
osm_swap_surfaces(bundle);
if(hasSetMainWindow) pojav_environ->mainWindowBundle->state = STATE_RENDERER_ALIVE;
}
osm_set_no_render_buffer(&bundle->buffer);
osm_apply_current_ll();
OSMesaPixelStore_p(OSMESA_Y_UP,0);
}

void osm_swap_buffers() {
if(currentBundle->state == STATE_RENDERER_NEW_WINDOW) {
osm_swap_surfaces(currentBundle);
currentBundle->state = STATE_RENDERER_ALIVE;
}

if(currentBundle->nativeSurface != NULL && !currentBundle->disable_rendering)
if(ANativeWindow_lock(currentBundle->nativeSurface, &currentBundle->buffer, NULL) != 0)
osm_release_window();

osm_apply_current_ll();
glFinish_p(); // this will force osmesa to write the last rendered image into the buffer

if(currentBundle->nativeSurface != NULL && !currentBundle->disable_rendering)
if(ANativeWindow_unlockAndPost(currentBundle->nativeSurface) != 0)
osm_release_window();
}

void osm_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;
}
}

void osm_swap_interval(int swapInterval) {
// nothing, as you can only set the swap interval with internal system APIs
}
29 changes: 29 additions & 0 deletions app_pojavlauncher/src/main/jni/ctxbridges/osm_bridge.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
//
// Created by maks on 18.10.2023.
//
#include <android/native_window.h>
#include <stdbool.h>
#ifndef POJAVLAUNCHER_OSM_BRIDGE_H
#define POJAVLAUNCHER_OSM_BRIDGE_H
#include "osmesa_loader.h"


typedef struct {
char state;
struct ANativeWindow *nativeSurface;
struct ANativeWindow *newNativeSurface;
ANativeWindow_Buffer buffer;
int32_t last_stride;
bool disable_rendering;
OSMesaContext context;
} osm_render_window_t;

bool osm_init();
osm_render_window_t* osm_get_current();
osm_render_window_t* osm_init_context(osm_render_window_t* share);
void osm_make_current(osm_render_window_t* bundle);
void osm_swap_buffers();
void osm_setup_window();
void osm_swap_interval(int swapInterval);

#endif //POJAVLAUNCHER_OSM_BRIDGE_H
Loading

0 comments on commit 682fe04

Please sign in to comment.