From 2c564a0b9d654d860dcc2832b2492f8e1b94813b Mon Sep 17 00:00:00 2001 From: JosJuice Date: Sun, 8 Aug 2021 12:10:03 +0200 Subject: Android: Remove mSurface from EmulationState --- .../org/dolphinemu/dolphinemu/NativeLibrary.java | 2 ++ .../dolphinemu/fragments/EmulationFragment.java | 30 +++++----------------- 2 files changed, 8 insertions(+), 24 deletions(-) (limited to 'Source/Android/app/src/main/java') diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/NativeLibrary.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/NativeLibrary.java index 0ac2463217..5ab4e15993 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/NativeLibrary.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/NativeLibrary.java @@ -393,6 +393,8 @@ public final class NativeLibrary public static native void SurfaceDestroyed(); + public static native boolean HasSurface(); + /** * Unpauses emulation from a paused state. */ diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/EmulationFragment.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/EmulationFragment.java index 7d18c47936..2ea106cb4a 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/EmulationFragment.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/EmulationFragment.java @@ -173,13 +173,15 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { Log.debug("[EmulationFragment] Surface changed. Resolution: " + width + "x" + height); - mEmulationState.newSurface(holder.getSurface()); + NativeLibrary.SurfaceChanged(holder.getSurface()); + mEmulationState.newSurface(); } @Override public void surfaceDestroyed(@NonNull SurfaceHolder holder) { - mEmulationState.clearSurface(); + Log.debug("[EmulationFragment] Surface destroyed."); + NativeLibrary.SurfaceDestroyed(); } public void stopEmulation() @@ -219,7 +221,6 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C private final String[] mGamePaths; private State state; - private Surface mSurface; private boolean mRunWhenSurfaceIsValid; private boolean loadPreviousTemporaryState; private final String temporaryStatePath; @@ -304,7 +305,7 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C } // If the surface is set, run now. Otherwise, wait for it to get set. - if (mSurface != null) + if (NativeLibrary.HasSurface()) { runWithValidSurface(); } @@ -314,31 +315,14 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C } } - // Surface callbacks - public synchronized void newSurface(Surface surface) + public synchronized void newSurface() { - mSurface = surface; if (mRunWhenSurfaceIsValid) { runWithValidSurface(); } } - public synchronized void clearSurface() - { - if (mSurface == null) - { - Log.warning("[EmulationFragment] clearSurface called, but surface already null."); - } - else - { - mSurface = null; - Log.debug("[EmulationFragment] Surface destroyed."); - - NativeLibrary.SurfaceDestroyed(); - } - } - private void runWithValidSurface() { mRunWhenSurfaceIsValid = false; @@ -346,7 +330,6 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C { Thread emulationThread = new Thread(() -> { - NativeLibrary.SurfaceChanged(mSurface); if (loadPreviousTemporaryState) { Log.debug("[EmulationFragment] Starting emulation thread from previous state."); @@ -363,7 +346,6 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C } else if (state == State.PAUSED) { - NativeLibrary.SurfaceChanged(mSurface); if (!EmulationActivity.getHasUserPausedEmulation() && !NativeLibrary.IsShowingAlertMessage()) { -- cgit v1.2.3 From 446e2d9119a3c4281e72feefca9bbcd2b1eb21e3 Mon Sep 17 00:00:00 2001 From: JosJuice Date: Sun, 8 Aug 2021 14:33:06 +0200 Subject: Android: Remove state from EmulationState --- .../org/dolphinemu/dolphinemu/NativeLibrary.java | 9 +++ .../dolphinemu/fragments/EmulationFragment.java | 79 ++++------------------ 2 files changed, 21 insertions(+), 67 deletions(-) (limited to 'Source/Android/app/src/main/java') diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/NativeLibrary.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/NativeLibrary.java index 5ab4e15993..123cd6c066 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/NativeLibrary.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/NativeLibrary.java @@ -410,6 +410,13 @@ public final class NativeLibrary */ public static native void StopEmulation(); + /** + * Ensures that IsRunning will return true from now on until emulation exits. + * (If this is not called, IsRunning will start returning true at some point + * after calling Run.) + */ + public static native void SetIsBooting(); + /** * Returns true if emulation is running (or is paused). */ @@ -417,6 +424,8 @@ public final class NativeLibrary public static native boolean IsRunningAndStarted(); + public static native boolean IsRunningAndUnpaused(); + /** * Enables or disables CPU block profiling * diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/EmulationFragment.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/EmulationFragment.java index 2ea106cb4a..ce35f1e98e 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/EmulationFragment.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/EmulationFragment.java @@ -123,8 +123,12 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C @Override public void onPause() { - if (mEmulationState.isRunning() && !NativeLibrary.IsShowingAlertMessage()) - mEmulationState.pause(); + if (NativeLibrary.IsRunningAndUnpaused() && !NativeLibrary.IsShowingAlertMessage()) + { + Log.debug("[EmulationFragment] Pausing emulation."); + NativeLibrary.PauseEmulation(); + } + super.onPause(); } @@ -186,7 +190,8 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C public void stopEmulation() { - mEmulationState.stop(); + Log.debug("[EmulationFragment] Stopping emulation."); + NativeLibrary.StopEmulation(); } public void startConfiguringControls() @@ -214,13 +219,7 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C private static class EmulationState { - private enum State - { - STOPPED, RUNNING, PAUSED - } - private final String[] mGamePaths; - private State state; private boolean mRunWhenSurfaceIsValid; private boolean loadPreviousTemporaryState; private final String temporaryStatePath; @@ -229,56 +228,6 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C { mGamePaths = gamePaths; this.temporaryStatePath = temporaryStatePath; - // Starting state is stopped. - state = State.STOPPED; - } - - // Getters for the current state - - public synchronized boolean isStopped() - { - return state == State.STOPPED; - } - - public synchronized boolean isPaused() - { - return state == State.PAUSED; - } - - public synchronized boolean isRunning() - { - return state == State.RUNNING; - } - - // State changing methods - - public synchronized void stop() - { - if (state != State.STOPPED) - { - Log.debug("[EmulationFragment] Stopping emulation."); - state = State.STOPPED; - NativeLibrary.StopEmulation(); - } - else - { - Log.warning("[EmulationFragment] Stop called while already stopped."); - } - } - - public synchronized void pause() - { - if (state != State.PAUSED) - { - state = State.PAUSED; - Log.debug("[EmulationFragment] Pausing emulation."); - - NativeLibrary.PauseEmulation(); - } - else - { - Log.warning("[EmulationFragment] Pause called while already paused."); - } } public synchronized void run(boolean isActivityRecreated) @@ -288,7 +237,6 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C if (NativeLibrary.IsRunning()) { loadPreviousTemporaryState = false; - state = State.PAUSED; deleteFile(temporaryStatePath); } else @@ -326,8 +274,10 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C private void runWithValidSurface() { mRunWhenSurfaceIsValid = false; - if (state == State.STOPPED) + if (!NativeLibrary.IsRunning()) { + NativeLibrary.SetIsBooting(); + Thread emulationThread = new Thread(() -> { if (loadPreviousTemporaryState) @@ -344,7 +294,7 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C }, "NativeEmulation"); emulationThread.start(); } - else if (state == State.PAUSED) + else { if (!EmulationActivity.getHasUserPausedEmulation() && !NativeLibrary.IsShowingAlertMessage()) @@ -353,11 +303,6 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C NativeLibrary.UnPauseEmulation(); } } - else - { - Log.debug("[EmulationFragment] Bug, run called while already running."); - } - state = State.RUNNING; } } -- cgit v1.2.3 From 3eb07e977269b6d2ddd126f78acd6d4b4a219e71 Mon Sep 17 00:00:00 2001 From: JosJuice Date: Sun, 8 Aug 2021 16:22:52 +0200 Subject: Android: Don't rely on onPause for pausing before destroying surface Fixes a crash which was uncovered (or just made more likely?) by the previous commit. --- .../main/java/org/dolphinemu/dolphinemu/fragments/EmulationFragment.java | 1 + 1 file changed, 1 insertion(+) (limited to 'Source/Android/app/src/main/java') diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/EmulationFragment.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/EmulationFragment.java index ce35f1e98e..d4780e9605 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/EmulationFragment.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/EmulationFragment.java @@ -186,6 +186,7 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C { Log.debug("[EmulationFragment] Surface destroyed."); NativeLibrary.SurfaceDestroyed(); + mRunWhenSurfaceIsValid = true; } public void stopEmulation() -- cgit v1.2.3 From 2cd09b8eb3bdc39f455f47c40ce165c7965b74e3 Mon Sep 17 00:00:00 2001 From: JosJuice Date: Sun, 8 Aug 2021 14:56:07 +0200 Subject: Android: Remove synchronized keywords from EmulationState These methods are only being called from the GUI thread anyway... --- .../java/org/dolphinemu/dolphinemu/fragments/EmulationFragment.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Source/Android/app/src/main/java') diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/EmulationFragment.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/EmulationFragment.java index d4780e9605..aecf2c8a83 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/EmulationFragment.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/EmulationFragment.java @@ -231,7 +231,7 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C this.temporaryStatePath = temporaryStatePath; } - public synchronized void run(boolean isActivityRecreated) + public void run(boolean isActivityRecreated) { if (isActivityRecreated) { @@ -264,7 +264,7 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C } } - public synchronized void newSurface() + public void newSurface() { if (mRunWhenSurfaceIsValid) { -- cgit v1.2.3 From 53d7d595e694eab21eae2e44f988242063518598 Mon Sep 17 00:00:00 2001 From: JosJuice Date: Sun, 8 Aug 2021 15:01:12 +0200 Subject: Android: Remove the EmulationState class The purpose of this class was to keep track of state which the emulation core was already keeping track of. This is rather risky - if we update the state of one of the two without updating the other, the two become out of sync, leading to some rather confusing problems. This duplicated state was removed from EmulationState in the previous commits, so now there isn't much left in the class. Might as well move its members directly into EmulationFragment. --- .../dolphinemu/fragments/EmulationFragment.java | 127 +++++++++------------ 1 file changed, 54 insertions(+), 73 deletions(-) (limited to 'Source/Android/app/src/main/java') diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/EmulationFragment.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/EmulationFragment.java index aecf2c8a83..4e9e864137 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/EmulationFragment.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/EmulationFragment.java @@ -32,7 +32,9 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C private InputOverlay mInputOverlay; - private EmulationState mEmulationState; + private String[] mGamePaths; + private boolean mRunWhenSurfaceIsValid; + private boolean mLoadPreviousTemporaryState; private EmulationActivity activity; @@ -73,8 +75,7 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C // So this fragment doesn't restart on configuration changes; i.e. rotation. setRetainInstance(true); - String[] gamePaths = getArguments().getStringArray(KEY_GAMEPATHS); - mEmulationState = new EmulationState(gamePaths, getTemporaryStateFilePath()); + mGamePaths = getArguments().getStringArray(KEY_GAMEPATHS); } /** @@ -117,7 +118,7 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C public void onResume() { super.onResume(); - mEmulationState.run(activity.isActivityRecreated()); + run(activity.isActivityRecreated()); } @Override @@ -178,7 +179,10 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C { Log.debug("[EmulationFragment] Surface changed. Resolution: " + width + "x" + height); NativeLibrary.SurfaceChanged(holder.getSurface()); - mEmulationState.newSurface(); + if (mRunWhenSurfaceIsValid) + { + runWithValidSurface(); + } } @Override @@ -218,91 +222,68 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C return mInputOverlay != null && mInputOverlay.isInEditMode(); } - private static class EmulationState + private void run(boolean isActivityRecreated) { - private final String[] mGamePaths; - private boolean mRunWhenSurfaceIsValid; - private boolean loadPreviousTemporaryState; - private final String temporaryStatePath; - - EmulationState(String[] gamePaths, String temporaryStatePath) - { - mGamePaths = gamePaths; - this.temporaryStatePath = temporaryStatePath; - } - - public void run(boolean isActivityRecreated) + if (isActivityRecreated) { - if (isActivityRecreated) + if (NativeLibrary.IsRunning()) { - if (NativeLibrary.IsRunning()) - { - loadPreviousTemporaryState = false; - deleteFile(temporaryStatePath); - } - else - { - loadPreviousTemporaryState = true; - } + mLoadPreviousTemporaryState = false; + deleteFile(getTemporaryStateFilePath()); } else { - Log.debug("[EmulationFragment] activity resumed or fresh start"); - loadPreviousTemporaryState = false; - // activity resumed without being killed or this is the first run - deleteFile(temporaryStatePath); - } - - // If the surface is set, run now. Otherwise, wait for it to get set. - if (NativeLibrary.HasSurface()) - { - runWithValidSurface(); - } - else - { - mRunWhenSurfaceIsValid = true; + mLoadPreviousTemporaryState = true; } } + else + { + Log.debug("[EmulationFragment] activity resumed or fresh start"); + mLoadPreviousTemporaryState = false; + // activity resumed without being killed or this is the first run + deleteFile(getTemporaryStateFilePath()); + } - public void newSurface() + // If the surface is set, run now. Otherwise, wait for it to get set. + if (NativeLibrary.HasSurface()) { - if (mRunWhenSurfaceIsValid) - { - runWithValidSurface(); - } + runWithValidSurface(); + } + else + { + mRunWhenSurfaceIsValid = true; } + } - private void runWithValidSurface() + private void runWithValidSurface() + { + mRunWhenSurfaceIsValid = false; + if (!NativeLibrary.IsRunning()) { - mRunWhenSurfaceIsValid = false; - if (!NativeLibrary.IsRunning()) - { - NativeLibrary.SetIsBooting(); + NativeLibrary.SetIsBooting(); - Thread emulationThread = new Thread(() -> - { - if (loadPreviousTemporaryState) - { - Log.debug("[EmulationFragment] Starting emulation thread from previous state."); - NativeLibrary.Run(mGamePaths, temporaryStatePath, true); - } - else - { - Log.debug("[EmulationFragment] Starting emulation thread."); - NativeLibrary.Run(mGamePaths); - } - EmulationActivity.stopIgnoringLaunchRequests(); - }, "NativeEmulation"); - emulationThread.start(); - } - else + Thread emulationThread = new Thread(() -> { - if (!EmulationActivity.getHasUserPausedEmulation() && - !NativeLibrary.IsShowingAlertMessage()) + if (mLoadPreviousTemporaryState) + { + Log.debug("[EmulationFragment] Starting emulation thread from previous state."); + NativeLibrary.Run(mGamePaths, getTemporaryStateFilePath(), true); + } + else { - Log.debug("[EmulationFragment] Resuming emulation."); - NativeLibrary.UnPauseEmulation(); + Log.debug("[EmulationFragment] Starting emulation thread."); + NativeLibrary.Run(mGamePaths); } + EmulationActivity.stopIgnoringLaunchRequests(); + }, "NativeEmulation"); + emulationThread.start(); + } + else + { + if (!EmulationActivity.getHasUserPausedEmulation() && !NativeLibrary.IsShowingAlertMessage()) + { + Log.debug("[EmulationFragment] Resuming emulation."); + NativeLibrary.UnPauseEmulation(); } } } -- cgit v1.2.3