Skip to content

Commit

Permalink
enhancement: make jni surface changeable indirectly from other thread
Browse files Browse the repository at this point in the history
  • Loading branch information
twaik committed Dec 31, 2024
1 parent 89c1fe4 commit 2f0aea9
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 14 deletions.
3 changes: 1 addition & 2 deletions app/src/main/cpp/lorie/cmdentrypoint.c
Original file line number Diff line number Diff line change
Expand Up @@ -205,8 +205,7 @@ Java_com_termux_x11_CmdEntryPoint_start(JNIEnv *env, __unused jclass cls, jobjec

JNIEXPORT void JNICALL
Java_com_termux_x11_CmdEntryPoint_windowChanged(JNIEnv *env, __unused jobject cls, jobject surface) {
QueueWorkProc(lorieChangeWindow, NULL, surface ? (*env)->NewGlobalRef(env, surface) : NULL);
lorieTriggerWorkingQueue();
renderer_set_window(env, surface ? (*env)->NewGlobalRef(env, surface) : NULL);
}

static Bool sendConfigureNotify(__unused ClientPtr pClient, void *closure) {
Expand Down
53 changes: 41 additions & 12 deletions app/src/main/cpp/lorie/renderer.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#pragma ide diagnostic ignored "UnreachableCode"
#pragma ide diagnostic ignored "OCUnusedMacroInspection"
#pragma ide diagnostic ignored "misc-no-recursion"
#pragma clang diagnostic ignored "-Wincompatible-pointer-types-discards-qualifiers"
#define EGL_EGLEXT_PROTOTYPES
#define GL_GLEXT_PROTOTYPES

Expand Down Expand Up @@ -142,9 +143,12 @@ static int renderedFrames = 0;
static jmethodID Surface_release = NULL;
static jmethodID Surface_destroy = NULL;

static pthread_mutex_t resLock = PTHREAD_MUTEX_INITIALIZER;
static volatile bool contextAvailable = false;
static volatile bool bufferChanged = false;
static volatile bool surfaceChanged = false;
static volatile LorieBuffer* pendingBuffer = NULL;
static volatile jobject pendingSurface = NULL;

struct lorie_shared_server_state* state = NULL;
static struct {
Expand Down Expand Up @@ -187,6 +191,8 @@ int renderer_init(JNIEnv* env, int* legacy_drawing, uint8_t* flip) {
if (ctx)
return 1;

pthread_mutex_init(&resLock, NULL);

jclass Surface = (*env)->FindClass(env, "android/view/Surface");
Surface_release = (*env)->GetMethodID(env, Surface, "release", "()V");
Surface_destroy = (*env)->GetMethodID(env, Surface, "destroy", "()V");
Expand Down Expand Up @@ -345,6 +351,24 @@ void renderer_set_buffer(JNIEnv* env, LorieBuffer* buf) {
LorieBuffer_acquire(pendingBuffer);
}

void renderer_set_window(JNIEnv* env, jobject new_surface) {
pthread_mutex_lock(&resLock);
if (pendingSurface && new_surface && pendingSurface != new_surface && (*env)->IsSameObject(env, pendingSurface, new_surface)) {
(*env)->DeleteGlobalRef(env, new_surface);
return;
}

if (pendingSurface && pendingSurface == new_surface)
return;

if (pendingSurface)
(*env)->DeleteGlobalRef(env, pendingSurface);

pendingSurface = new_surface;
surfaceChanged = TRUE;
pthread_mutex_unlock(&resLock);
}

static inline __always_inline void release_win_and_surface(JNIEnv *env, jobject* jsfc, ANativeWindow** anw, EGLSurface *esfc) {
if (esfc && *esfc) {
if (eglMakeCurrent(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT) != EGL_TRUE)
Expand All @@ -367,21 +391,20 @@ static inline __always_inline void release_win_and_surface(JNIEnv *env, jobject*
}
}

void renderer_set_window(JNIEnv* env, jobject new_surface) {
void renderer_refresh_context(JNIEnv* env) {
pthread_mutex_lock(&resLock);
uint32_t emptyData = {0};
ANativeWindow* window;
if (new_surface && surface && new_surface != surface && (*env)->IsSameObject(env, new_surface, surface)) {
(*env)->DeleteGlobalRef(env, new_surface);
new_surface = NULL;
ANativeWindow* window = pendingSurface ? ANativeWindow_fromSurface(env, pendingSurface) : NULL;
if ((pendingSurface && surface && pendingSurface != surface && (*env)->IsSameObject(env, pendingSurface, surface)) || (window && win == window)) {
(*env)->DeleteGlobalRef(env, pendingSurface);
pendingSurface = NULL;
surfaceChanged = FALSE;
return;
}

window = new_surface ? ANativeWindow_fromSurface(env, new_surface) : NULL;
int width = window ? ANativeWindow_getWidth(window) : 0;
int height = window ? ANativeWindow_getHeight(window) : 0;
log("renderer_set_window %p %d %d", window, width, height);
if (window && win == window)
return;

if (window)
ANativeWindow_acquire(window);
Expand All @@ -390,11 +413,15 @@ void renderer_set_window(JNIEnv* env, jobject new_surface) {

if (window && (width <= 0 || height <= 0)) {
log("Xlorie: We've got invalid surface. Probably it became invalid before we started working with it.\n");
release_win_and_surface(env, &new_surface, &window, NULL);
release_win_and_surface(env, &pendingSurface, &window, NULL);
}

win = window;
surface = new_surface;
surface = pendingSurface;
pendingSurface = NULL;
surfaceChanged = FALSE;

pthread_mutex_unlock(&resLock);

if (!win) {
eglMakeCurrent(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
Expand Down Expand Up @@ -459,7 +486,7 @@ static void draw(GLuint id, float x0, float y0, float x1, float y1, uint8_t flip
static void draw_cursor(void);

int renderer_should_redraw(void) {
return contextAvailable || bufferChanged || (state && state->cursor.updated);
return contextAvailable || surfaceChanged || bufferChanged || (state && state->cursor.updated);
}

static void renderer_renew_image(void) {
Expand Down Expand Up @@ -501,14 +528,16 @@ static void renderer_renew_image(void) {
int renderer_redraw(JNIEnv* env, uint8_t flip) {
int err = EGL_SUCCESS;

if (surfaceChanged)
renderer_refresh_context(env);

if (bufferChanged)
renderer_renew_image();

if (!contextAvailable)
return FALSE;

if (state && state->cursor.updated) {
uint32_t data = 0;
log("Xlorie: updating cursor\n");
pthread_mutex_lock(&state->cursor.lock);
state->cursor.updated = false;
Expand Down

0 comments on commit 2f0aea9

Please sign in to comment.