mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-23 14:19:46 -06:00
Android: Replace emulation rotation crash workaround with proper fix
The workaround was added in0446a58
. The underlying problem is that we must not destroy the surface while the video backend is initializing, otherwise the video backend may reference nullptr. I've also cleaned up the logic for when to destroy the surface. Note that the comment in EmulationFragment.java about only being able to destroy the surface when emulation is running is not true anymore (due tode632fc
, it seems like).
This commit is contained in:
@ -400,6 +400,8 @@ public final class NativeLibrary
|
||||
*/
|
||||
public static native void StopEmulation();
|
||||
|
||||
public static native void WaitUntilDoneBooting();
|
||||
|
||||
/**
|
||||
* Returns true if emulation is running (or is paused).
|
||||
*/
|
||||
|
@ -235,10 +235,6 @@ public final class EmulationActivity extends AppCompatActivity
|
||||
{
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
// Find the EmulationFragment
|
||||
mEmulationFragment = (EmulationFragment) getSupportFragmentManager()
|
||||
.findFragmentById(R.id.frame_emulation_fragment);
|
||||
|
||||
if (savedInstanceState == null)
|
||||
{
|
||||
// Get params we were passed
|
||||
@ -251,9 +247,7 @@ public final class EmulationActivity extends AppCompatActivity
|
||||
}
|
||||
else
|
||||
{
|
||||
// Could have recreated the activity(rotate) before creating the fragment. If the fragment
|
||||
// doesn't exist, treat this as a new start.
|
||||
activityRecreated = mEmulationFragment != null;
|
||||
activityRecreated = true;
|
||||
restoreState(savedInstanceState);
|
||||
}
|
||||
|
||||
@ -311,9 +305,10 @@ public final class EmulationActivity extends AppCompatActivity
|
||||
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);
|
||||
}
|
||||
|
||||
if (!(mDeviceHasTouchScreen && lockLandscape &&
|
||||
getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) &&
|
||||
mEmulationFragment == null)
|
||||
// Find or create the EmulationFragment
|
||||
mEmulationFragment = (EmulationFragment) getSupportFragmentManager()
|
||||
.findFragmentById(R.id.frame_emulation_fragment);
|
||||
if (mEmulationFragment == null)
|
||||
{
|
||||
mEmulationFragment = EmulationFragment.newInstance(mPaths);
|
||||
getSupportFragmentManager().beginTransaction()
|
||||
|
@ -316,8 +316,6 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C
|
||||
state = State.PAUSED;
|
||||
Log.debug("[EmulationFragment] Pausing emulation.");
|
||||
|
||||
// Release the surface before pausing, since emulation has to be running for that.
|
||||
NativeLibrary.SurfaceDestroyed();
|
||||
NativeLibrary.PauseEmulation();
|
||||
}
|
||||
else
|
||||
@ -381,19 +379,17 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C
|
||||
mSurface = null;
|
||||
Log.debug("[EmulationFragment] Surface destroyed.");
|
||||
|
||||
if (state == State.RUNNING)
|
||||
if (state != State.STOPPED)
|
||||
{
|
||||
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.");
|
||||
// In order to avoid dereferencing nullptr, we must not destroy the surface while booting
|
||||
// the core, so wait here if necessary. An easy (but not 100% consistent) way to reach
|
||||
// this method while the core is booting is by having landscape orientation lock enabled
|
||||
// and starting emulation while the phone is in portrait mode, leading to the activity
|
||||
// being recreated very soon after NativeLibrary.Run has been called.
|
||||
NativeLibrary.WaitUntilDoneBooting();
|
||||
}
|
||||
|
||||
NativeLibrary.SurfaceDestroyed();
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user