diff --git a/libswirl/android/Android.cpp b/libswirl/android/Android.cpp index 5f6bc00e71..992f10c9ce 100644 --- a/libswirl/android/Android.cpp +++ b/libswirl/android/Android.cpp @@ -158,7 +158,7 @@ extern bool print_stats; jobject g_emulator; jmethodID saveAndroidSettingsMid; jmethodID launchFromUrlMid; -static ANativeWindow *g_window = 0; +static std::atomic g_window(0); void os_DoEvents() { @@ -310,14 +310,15 @@ JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_setupMic(JNIEnv *env, JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_pause(JNIEnv *env,jobject obj) { - if (game_started && sh4_cpu->IsRunning()) - virtualDreamcast->Stop([] {}); -} + static atomic isPausing(false); -JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_resume(JNIEnv *env,jobject obj) -{ - if (game_started && !sh4_cpu->IsRunning() && gui_state == Closed) - virtualDreamcast->Resume(); + if (!isPausing) { + isPausing = true; + + g_GUI->OpenSettings([] { + isPausing = false; + }); + } } JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_stop(JNIEnv *env,jobject obj) @@ -392,19 +393,27 @@ 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 (surface == NULL) { - verify(render_thread.hThread != NULL); - - g_GUIRenderer->Stop(); - render_thread.WaitToEnd(); - render_thread.hThread = NULL; - verify(g_window != NULL); - ANativeWindow_release(g_window); - g_window = NULL; + g_GUI->OpenSettings([] { + g_GUIRenderer->Stop(); + verify(render_thread.hThread != NULL); + render_thread.WaitToEnd(); + + render_thread.hThread = NULL; + + + ANativeWindow_release(g_window); + verify(g_window != NULL); + g_window = NULL; + }); + + do {} while (g_window != NULL); } else { + do {} while (g_window != NULL); + verify(g_window == NULL); verify(render_thread.hThread == NULL); g_window = ANativeWindow_fromSurface(env, surface); @@ -448,7 +457,14 @@ JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_getControllers(JNIEnv JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_guiOpenSettings(JNIEnv *env, jobject obj) { - g_GUI->OpenSettings(); + static atomic setttingsOpening(false); + if (setttingsOpening == false) + { + setttingsOpening = true; + g_GUI->OpenSettings([] { + setttingsOpening = false; + }); + } } JNIEXPORT jboolean JNICALL Java_com_reicast_emulator_emu_JNIdc_guiIsOpen(JNIEnv *env, jobject obj) diff --git a/libswirl/gui/gui.cpp b/libswirl/gui/gui.cpp index 642aba3a0d..147170834b 100644 --- a/libswirl/gui/gui.cpp +++ b/libswirl/gui/gui.cpp @@ -314,23 +314,32 @@ struct ReicastUI_impl : GUI { printf("Screen DPI is %d, size %d x %d. Scaling by %.2f\n", screen_dpi, screen_width, screen_height, scaling); } - void OpenSettings() + void OpenSettings(function cb) { if (gui_state == Closed) { // FIXME: This feels like a hack // avoids assert if OpenSettings is called twice, before the core actually stops if (sh4_cpu->IsRunning()) { - virtualDreamcast->Stop([this] { + virtualDreamcast->Stop([this, cb] { gui_state = Commands; settings_opening = true; HideOSD(); + cb(); }); } + else { + cb(); + } } else if (gui_state == VJoyEdit) { gui_state = VJoyEditCommands; + cb(); + } + else + { + cb(); } } diff --git a/libswirl/gui/gui.h b/libswirl/gui/gui.h index f9a96bc912..f57d0125b1 100644 --- a/libswirl/gui/gui.h +++ b/libswirl/gui/gui.h @@ -18,10 +18,11 @@ */ #pragma once #include +#include struct GUI { virtual void Init() = 0; - virtual void OpenSettings() = 0; + virtual void OpenSettings(std::function cb) = 0; virtual void RenderUI() = 0; virtual void DisplayNotification(const char* msg, int duration) = 0; virtual void RenderOSD() = 0; diff --git a/libswirl/gui/gui_renderer.cpp b/libswirl/gui/gui_renderer.cpp index d65f5ba12f..f48ef89122 100644 --- a/libswirl/gui/gui_renderer.cpp +++ b/libswirl/gui/gui_renderer.cpp @@ -88,6 +88,7 @@ static void findGLVersion() struct GUIRenderer_impl : GUIRenderer { std::atomic keepRunning; + std::atomic frameDone; cMutex callback_mutex; cResetEvent pendingCallback; @@ -116,8 +117,11 @@ struct GUIRenderer_impl : GUIRenderer { callback_mutex.Lock(); { cb = callback; + callback = nullptr; + frameDone = cb == nullptr; } callback_mutex.Unlock(); + if (cb) { if (cb()) { @@ -126,9 +130,6 @@ struct GUIRenderer_impl : GUIRenderer { rv = false; } } - callback_mutex.Lock(); - callback = nullptr; - callback_mutex.Unlock(); } else if (g_GUI->IsOpen() || g_GUI->IsVJoyEdit()) { @@ -192,6 +193,7 @@ struct GUIRenderer_impl : GUIRenderer { virtual void QueueEmulatorFrame(std::function cb) { callback_mutex.Lock(); + frameDone = false; callback = cb; callback_mutex.Unlock(); } @@ -205,7 +207,7 @@ struct GUIRenderer_impl : GUIRenderer { cb = callback; } callback_mutex.Unlock(); - } while (callback); + } while (callback || !frameDone); } }; diff --git a/libswirl/hw/pvr/Renderer_if.cpp b/libswirl/hw/pvr/Renderer_if.cpp index 2ea8f7cf4a..ce60721165 100644 --- a/libswirl/hw/pvr/Renderer_if.cpp +++ b/libswirl/hw/pvr/Renderer_if.cpp @@ -14,6 +14,7 @@ #include "scripting/lua_bindings.h" #include +#include #if FEAT_HAS_NIXPROF #include "profiler/profiler.h" @@ -88,6 +89,7 @@ static unique_ptr fallback_renderer; //bool renderer_enabled = true; // Signals the renderer thread to exit bool renderer_changed = false; // Signals the renderer thread to switch renderer +static atomic pend_rend(false); static cResetEvent rs, re; int max_idx,max_mvo,max_op,max_pt,max_tr,max_vtx,max_modt, ovrn; @@ -100,7 +102,6 @@ void killtex(); bool render_output_framebuffer(); bool dump_frame_switch = false; -bool pend_rend = false; // auto or slug @@ -198,9 +199,11 @@ static bool rend_frame(u8* vram, TA_context* ctx, bool draw_osd) { bool proc = renderer->Process(ctx); - if (!proc || !ctx->rend.isRTT) - // If rendering to texture, continue locking until the frame is rendered - re.Set(); + if (!proc || !ctx->rend.isRTT) { + // If rendering to texture, continue locking until the frame is rendered + pend_rend = false; + re.Set(); + } bool do_swp = proc && renderer->RenderPVR(); @@ -414,8 +417,10 @@ void rend_start_render(u8* vram) bool do_swp = rend_frame(vram, _pvrrc, true); - if (_pvrrc->rend.isRTT) + if (_pvrrc->rend.isRTT) { + pend_rend = false; re.Set(); + } //clear up & free data .. FinishRender(_pvrrc); @@ -424,9 +429,9 @@ void rend_start_render(u8* vram) return do_swp; }); + pend_rend = true; rs.Set(); - pend_rend = true; } } else diff --git a/libswirl/input/gamepad_device.cpp b/libswirl/input/gamepad_device.cpp index 4ffb08b022..11116bb9d0 100644 --- a/libswirl/input/gamepad_device.cpp +++ b/libswirl/input/gamepad_device.cpp @@ -96,8 +96,12 @@ bool GamepadDevice::gamepad_btn_input(u32 code, bool pressed) virtualDreamcast->Stop([] { }); break; case EMU_BTN_MENU: - if (pressed) - g_GUI->OpenSettings(); + if (pressed && !settingsOpenning) { + settingsOpenning = true; + g_GUI->OpenSettings([this] { + settingsOpenning = false; + }); + } break; case EMU_BTN_TRIGGER_LEFT: lt[_maple_port] = pressed ? 255 : 0; diff --git a/libswirl/input/gamepad_device.h b/libswirl/input/gamepad_device.h index add7507d3e..930374f56a 100644 --- a/libswirl/input/gamepad_device.h +++ b/libswirl/input/gamepad_device.h @@ -19,7 +19,7 @@ #pragma once #include -#include +#include #include "types.h" #include "mapping.h" #include "oslib/threading.h" @@ -27,6 +27,8 @@ class GamepadDevice { typedef void (*input_detected_cb)(u32 code); + atomic settingsOpenning; + public: const std::string& api_name() { return _api_name; } const std::string& name() { return _name; } @@ -35,6 +37,7 @@ class GamepadDevice const std::string& unique_id() { return _unique_id; } virtual bool gamepad_btn_input(u32 code, bool pressed); bool gamepad_axis_input(u32 code, int value); + GamepadDevice() : settingsOpenning(false) { } virtual ~GamepadDevice() {} void detect_btn_input(input_detected_cb button_pressed); diff --git a/libswirl/serialize.cpp b/libswirl/serialize.cpp index a706fda95f..6cb9a8e14e 100644 --- a/libswirl/serialize.cpp +++ b/libswirl/serialize.cpp @@ -733,8 +733,7 @@ bool dc_serialize(void **data, unsigned int *total_size) mcfg_SerializeDevices(data, total_size); REICAST_S(FrameCount); - REICAST_S(pend_rend); - + REICAST_SA(YUV_tempdata,512/4); REICAST_S(YUV_dest); @@ -948,8 +947,6 @@ bool dc_unserialize(void **data, unsigned int *total_size) mcfg_UnserializeDevices(data, total_size); REICAST_US(FrameCount); - REICAST_US(pend_rend); - REICAST_USA(YUV_tempdata,512/4); REICAST_US(YUV_dest); diff --git a/reicast/android-studio/reicast/src/main/java/com/reicast/emulator/emu/JNIdc.java b/reicast/android-studio/reicast/src/main/java/com/reicast/emulator/emu/JNIdc.java index 97ff44a817..9eaad54c32 100644 --- a/reicast/android-studio/reicast/src/main/java/com/reicast/emulator/emu/JNIdc.java +++ b/reicast/android-studio/reicast/src/main/java/com/reicast/emulator/emu/JNIdc.java @@ -14,7 +14,7 @@ public final class JNIdc public static native void setExternalStorageDirectories(Object[] pathList); public static native void setGameUri(String fileName); public static native void pause(); - public static native void resume(); + public static native void stop(); public static native void destroy(); diff --git a/reicast/android-studio/reicast/src/main/java/com/reicast/emulator/emu/NativeGLView.java b/reicast/android-studio/reicast/src/main/java/com/reicast/emulator/emu/NativeGLView.java index aa878f7abb..0c30338e8a 100644 --- a/reicast/android-studio/reicast/src/main/java/com/reicast/emulator/emu/NativeGLView.java +++ b/reicast/android-studio/reicast/src/main/java/com/reicast/emulator/emu/NativeGLView.java @@ -117,7 +117,6 @@ public void resume() { setFocusable(true); setFocusableInTouchMode(true); requestFocus(); - JNIdc.resume(); } }