From 1fa052987bebbfe58ea3b7ec28f6b8581fa340fb Mon Sep 17 00:00:00 2001 From: Flyinghead Date: Tue, 9 Apr 2019 10:39:29 +0200 Subject: [PATCH] android: run renderer in a separate native thread fixes simultaneous gamepad button presses not being registered on some platforms --- .../java/com/reicast/emulator/emu/JNIdc.java | 3 +- .../reicast/emulator/emu/NativeGLView.java | 24 +------ .../reicast/src/main/jni/src/Android.cpp | 71 ++++++++++++------- 3 files changed, 49 insertions(+), 49 deletions(-) diff --git a/shell/android-studio/reicast/src/main/java/com/reicast/emulator/emu/JNIdc.java b/shell/android-studio/reicast/src/main/java/com/reicast/emulator/emu/JNIdc.java index 6262fb27a..fef8b9dfa 100644 --- a/shell/android-studio/reicast/src/main/java/com/reicast/emulator/emu/JNIdc.java +++ b/shell/android-studio/reicast/src/main/java/com/reicast/emulator/emu/JNIdc.java @@ -21,8 +21,7 @@ public final class JNIdc public static native int send(int cmd, int opt); public static native int data(int cmd, byte[] data); - public static native void rendinitNative(Surface surface, int w, int h); - public static native boolean rendframeNative(); + public static native void rendinitNative(Surface surface); public static native void rendinitJava(int w, int h); public static native boolean rendframeJava(); public static native void rendtermJava(); diff --git a/shell/android-studio/reicast/src/main/java/com/reicast/emulator/emu/NativeGLView.java b/shell/android-studio/reicast/src/main/java/com/reicast/emulator/emu/NativeGLView.java index 3a7268401..383a8684a 100644 --- a/shell/android-studio/reicast/src/main/java/com/reicast/emulator/emu/NativeGLView.java +++ b/shell/android-studio/reicast/src/main/java/com/reicast/emulator/emu/NativeGLView.java @@ -19,8 +19,6 @@ import com.reicast.emulator.NativeGLActivity; import com.reicast.emulator.config.Config; public class NativeGLView extends SurfaceView implements SurfaceHolder.Callback { - private Handler handler = new Handler(); - private boolean surfaceReady = false; private boolean paused = false; VirtualJoystickDelegate vjoyDelegate; @@ -66,23 +64,6 @@ public class NativeGLView extends SurfaceView implements SurfaceHolder.Callback if (NativeGLActivity.syms != null) JNIdc.data(1, NativeGLActivity.syms); - - startRendering(); - } - - private void startRendering() { - // Continuously render frames - handler.removeCallbacksAndMessages(null); - handler.postAtTime(new Runnable() { - @Override - public void run() { - if (!paused) - { - JNIdc.rendframeNative(); - handler.post(this); - } - } - }, SystemClock.uptimeMillis() + 500); } @Override @@ -111,7 +92,7 @@ public class NativeGLView extends SurfaceView implements SurfaceHolder.Callback public void surfaceChanged(SurfaceHolder surfaceHolder, int format, int w, int h) { //Log.i("reicast", "NativeGLView.surfaceChanged: " + w + "x" + h); surfaceReady = true; - JNIdc.rendinitNative(surfaceHolder.getSurface(), w, h); + JNIdc.rendinitNative(surfaceHolder.getSurface()); Emulator.getCurrentActivity().handleStateChange(false); } @@ -119,7 +100,7 @@ public class NativeGLView extends SurfaceView implements SurfaceHolder.Callback public void surfaceDestroyed(SurfaceHolder surfaceHolder) { //Log.i("reicast", "NativeGLView.surfaceDestroyed"); surfaceReady = false; - JNIdc.rendinitNative(null, 0, 0); + JNIdc.rendinitNative(null); Emulator.getCurrentActivity().handleStateChange(true); } @@ -142,7 +123,6 @@ public class NativeGLView extends SurfaceView implements SurfaceHolder.Callback requestFocus(); JNIdc.resume(); } - startRendering(); } @TargetApi(19) diff --git a/shell/android-studio/reicast/src/main/jni/src/Android.cpp b/shell/android-studio/reicast/src/main/jni/src/Android.cpp index 3ab96e5dd..ced2f366d 100644 --- a/shell/android-studio/reicast/src/main/jni/src/Android.cpp +++ b/shell/android-studio/reicast/src/main/jni/src/Android.cpp @@ -91,8 +91,7 @@ JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_destroy(JNIEnv *env,j JNIEXPORT jint JNICALL Java_com_reicast_emulator_emu_JNIdc_send(JNIEnv *env,jobject obj,jint id, jint v) __attribute__((visibility("default"))); JNIEXPORT jint JNICALL Java_com_reicast_emulator_emu_JNIdc_data(JNIEnv *env,jobject obj,jint id, jbyteArray d) __attribute__((visibility("default"))); -JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_rendinitNative(JNIEnv *env, jobject obj, jobject surface, jint w, jint h) __attribute__((visibility("default"))); -JNIEXPORT jboolean JNICALL Java_com_reicast_emulator_emu_JNIdc_rendframeNative(JNIEnv *env,jobject obj) __attribute__((visibility("default"))); +JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_rendinitNative(JNIEnv *env, jobject obj, jobject surface) __attribute__((visibility("default"))); JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_rendinitJava(JNIEnv *env, jobject obj, jint w, jint h) __attribute__((visibility("default"))); JNIEXPORT jboolean JNICALL Java_com_reicast_emulator_emu_JNIdc_rendframeJava(JNIEnv *env, jobject obj) __attribute__((visibility("default"))); JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_rendtermJava(JNIEnv *env, jobject obj) __attribute__((visibility("default"))); @@ -404,35 +403,57 @@ JNIEXPORT jint JNICALL Java_com_reicast_emulator_emu_JNIdc_data(JNIEnv *env, job extern void gl_swap(); extern void egl_stealcntx(); +volatile static bool render_running; +volatile static bool render_reinit; -JNIEXPORT jboolean JNICALL Java_com_reicast_emulator_emu_JNIdc_rendframeNative(JNIEnv *env,jobject obj) +void *render_thread_func(void *) { - if (g_window == NULL) - return false; - if (!egl_makecurrent()) - return false; - jboolean ret = (jboolean)rend_single_frame(); - if (ret) - gl_swap(); - return ret; + render_running = true; + + rend_init_renderer(); + + while (render_running) { + if (render_reinit) + { + render_reinit = false; + rend_init_renderer(); + } + else + if (!egl_makecurrent()) + break;; + + bool ret = rend_single_frame(); + if (ret) + gl_swap(); + } + egl_makecurrent(); + rend_term_renderer(); + ANativeWindow_release(g_window); + g_window = NULL; + render_running = false; + + return NULL; } -JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_rendinitNative(JNIEnv * env, jobject obj, jobject surface, jint width, jint height) +static cThread render_thread(render_thread_func, NULL); + +JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_rendinitNative(JNIEnv * env, jobject obj, jobject surface) { - if (g_window != NULL) - { - egl_makecurrent(); - rend_term_renderer(); - ANativeWindow_release(g_window); - g_window = NULL; - } - if (surface != NULL) - { + if (render_thread.hThread != NULL) + { + if (surface == NULL) + { + render_running = false; + render_thread.WaitToEnd(); + } + else + render_reinit = true; + } + else if (surface != NULL) + { g_window = ANativeWindow_fromSurface(env, surface); - rend_init_renderer(); - screen_width = width; - screen_height = height; - } + render_thread.Start(); + } } JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_rendinitJava(JNIEnv * env, jobject obj, jint width, jint height)