diff options
| author | Mike <7153163+hackbar@users.noreply.github.com> | 2017-10-25 12:45:03 -0700 |
|---|---|---|
| committer | Mike <7153163+hackbar@users.noreply.github.com> | 2017-11-01 23:39:56 -0700 |
| commit | 18cb68eb3cfe656a4eb22229a5441c665a54bf3d (patch) | |
| tree | 8f5ed8376c8e878e4025f1a3457053c48eddb574 /Source/Android/app/src/main/java | |
| parent | 987d24fe87c5679d055576b8458ee5d2263fc7ab (diff) | |
Android: Destroy the surface in EmulationFragment onStop.
Emulation needs to be running when the surface is destroyed, but we want
to pause in onStop. So call the surfaceDestroyed callback, as this
accomplished both.
Diffstat (limited to 'Source/Android/app/src/main/java')
2 files changed, 137 insertions, 102 deletions
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/EmulationActivity.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/EmulationActivity.java index 27ec8cd794..8e59d07cca 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/EmulationActivity.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/EmulationActivity.java @@ -275,8 +275,6 @@ public final class EmulationActivity extends AppCompatActivity mImageView.setVisibility(View.GONE); } }); - - mEmulationFragment.startEmulation(); } else { 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 393790cf14..263cd597c1 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 @@ -25,14 +25,9 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C private SharedPreferences mPreferences; - private Surface mSurface; - private InputOverlay mInputOverlay; - private Thread mEmulationThread; - - private String mGamePath; - private final EmulationState mEmulationState = new EmulationState(); + private EmulationState mEmulationState; public static EmulationFragment newInstance(String gamePath) { @@ -73,7 +68,8 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C mPreferences = PreferenceManager.getDefaultSharedPreferences(getActivity()); - mGamePath = getArguments().getString(KEY_GAMEPATH); + String gamePath = getArguments().getString(KEY_GAMEPATH); + mEmulationState = new EmulationState(gamePath); } /** @@ -116,10 +112,17 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C } @Override - public void onStop() + public void onResume() { - pauseEmulation(); - super.onStop(); + super.onResume(); + mEmulationState.run(); + } + + @Override + public void onPause() + { + mEmulationState.pause(); + super.onPause(); } @Override @@ -158,101 +161,28 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C @Override public void surfaceCreated(SurfaceHolder holder) { - Log.debug("[EmulationFragment] Surface created."); + // We purposely don't do anything here. + // All work is done in surfaceChanged, which we are guaranteed to get even for surface creation. } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { Log.debug("[EmulationFragment] Surface changed. Resolution: " + width + "x" + height); - - if (mEmulationState.isPaused()) - { - NativeLibrary.UnPauseEmulation(); - } - - mSurface = holder.getSurface(); - NativeLibrary.SurfaceChanged(mSurface); + mEmulationState.newSurface(holder.getSurface()); } @Override public void surfaceDestroyed(SurfaceHolder holder) { - Log.debug("[EmulationFragment] Surface destroyed."); - NativeLibrary.SurfaceDestroyed(); - - if (mEmulationState.isRunning()) - { - pauseEmulation(); - } + mEmulationState.clearSurface(); } - public void startEmulation() + public void stopEmulation() { - synchronized (mEmulationState) - { - if (mEmulationState.isStopped()) - { - Log.debug("[EmulationFragment] Starting emulation thread."); - - mEmulationThread = new Thread(mEmulationRunner, "NativeEmulation"); - mEmulationThread.start(); - // The thread will call mEmulationState.run() - } - else if (mEmulationState.isPaused()) - { - Log.debug("[EmulationFragment] Resuming emulation."); - NativeLibrary.UnPauseEmulation(); - mEmulationState.run(); - } - else - { - Log.debug("[EmulationFragment] Bug, startEmulation called while running."); - } - } + mEmulationState.stop(); } - public void stopEmulation() { - synchronized (mEmulationState) - { - if (!mEmulationState.isStopped()) - { - NativeLibrary.StopEmulation(); - mEmulationState.stop(); - } - } - } - - private void pauseEmulation() - { - synchronized (mEmulationState) - { - Log.debug("[EmulationFragment] Pausing emulation."); - - NativeLibrary.PauseEmulation(); - mEmulationState.pause(); - } - } - - private Runnable mEmulationRunner = new Runnable() - { - @Override - public void run() - { - // Busy-wait for surface to be set - while (mSurface == null) {} - - synchronized (mEmulationState) - { - Log.info("[EmulationFragment] Starting emulation: " + mSurface); - - mEmulationState.run(); - } - // Start emulation using the provided Surface. - NativeLibrary.Run(mGamePath); - } - }; - public void startConfiguringControls() { getView().findViewById(R.id.done_control_config).setVisibility(View.VISIBLE); @@ -277,42 +207,149 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C STOPPED, RUNNING, PAUSED } + private final String mGamePath; + private Thread mEmulationThread; private State state; + private Surface mSurface; + private boolean mRunWhenSurfaceIsValid; - EmulationState() + EmulationState(String gamePath) { + mGamePath = gamePath; // Starting state is stopped. state = State.STOPPED; } - public boolean isStopped() + // Getters for the current state + + public synchronized boolean isStopped() { return state == State.STOPPED; } - public boolean isRunning() + public synchronized boolean isPaused() + { + return state == State.PAUSED; + } + + public synchronized boolean isRunning() { return state == State.RUNNING; } - public boolean isPaused() + // State changing methods + + public synchronized void stop() { - return state == State.PAUSED; + if (state != State.STOPPED) + { + state = State.STOPPED; + NativeLibrary.StopEmulation(); + } + else + { + Log.warning("[EmulationFragment] Stop called while already stopped."); + } } - public void run() + public synchronized void pause() { - state = State.RUNNING; + if (state != State.PAUSED) + { + state = State.PAUSED; + Log.debug("[EmulationFragment] Pausing emulation."); + + // Release the surface before pausing, since emulation has to be running for that. + mSurface = null; + NativeLibrary.SurfaceDestroyed(); + NativeLibrary.PauseEmulation(); + } + else + { + Log.warning("[EmulationFragment] Pause called while already paused."); + } } - public void pause() + public synchronized void run() { - state = State.PAUSED; + // If the surface is set, run now. Otherwise, wait for it to get set. + if (mSurface != null) + { + runWithValidSurface(); + } + else + { + mRunWhenSurfaceIsValid = true; + } } - public void stop() + // Surface callbacks + public synchronized void newSurface(Surface surface) { - state = State.STOPPED; + 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."); + + if (state == State.RUNNING) + { + NativeLibrary.SurfaceDestroyed(); + state = State.PAUSED; + } + else if (state == State.PAUSED) + { + Log.warning("[EmulationFragment] Surface cleared while emulation paused."); + } + else + { + Log.warning("[EmulationFragment] Surface cleared while emulation stopped."); + } + } + } + + private void runWithValidSurface() + { + mRunWhenSurfaceIsValid = false; + if (state == State.STOPPED) + { + Log.debug("[EmulationFragment] Starting emulation thread."); + + mEmulationThread = new Thread(new Runnable() + { + @Override + public void run() + { + NativeLibrary.SurfaceChanged(mSurface); + NativeLibrary.Run(mGamePath); + }}, + "NativeEmulation"); + mEmulationThread.start(); + + } + else if (state == State.PAUSED) + { + Log.debug("[EmulationFragment] Resuming emulation."); + NativeLibrary.UnPauseEmulation(); + NativeLibrary.SurfaceChanged(mSurface); + } + else + { + Log.debug("[EmulationFragment] Bug, run called while already running."); + } + state = State.RUNNING; } } } |
