mirror of
https://github.com/Ishan09811/pine.git
synced 2025-04-24 08:55:10 +00:00
Implement proper pause and resume logic (#34)
This commit is contained in:
parent
dd574b73d2
commit
4cc4981d08
@ -165,6 +165,14 @@ extern "C" JNIEXPORT jboolean Java_emu_skyline_EmulationActivity_setSurface(JNIE
|
||||
return true;
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void Java_emu_skyline_EmulationActivity_pauseEmulation(JNIEnv *, jobject, jboolean pause) {
|
||||
auto gpu = GpuWeak.lock();
|
||||
if (!gpu) return;
|
||||
if (pause) {
|
||||
gpu->presentation.Pause();
|
||||
} else gpu->presentation.Resume();
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void Java_emu_skyline_EmulationActivity_changeAudioStatus(JNIEnv *, jobject, jboolean play) {
|
||||
auto audio{AudioWeak.lock()};
|
||||
if (audio)
|
||||
|
@ -21,6 +21,8 @@ extern jfloat AverageFrametimeDeviationMs;
|
||||
namespace skyline::gpu {
|
||||
using namespace service::hosbinder;
|
||||
|
||||
std::atomic<bool> paused{false};
|
||||
|
||||
PresentationEngine::PresentationEngine(const DeviceState &state, GPU &gpu)
|
||||
: state{state},
|
||||
gpu{gpu},
|
||||
@ -76,7 +78,11 @@ namespace skyline::gpu {
|
||||
try {
|
||||
choreographerLooper = ALooper_prepare(0);
|
||||
AChoreographer_postFrameCallback64(AChoreographer_getInstance(), reinterpret_cast<AChoreographer_frameCallback64>(&ChoreographerCallback), this);
|
||||
while (ALooper_pollAll(-1, nullptr, nullptr, nullptr) == ALOOPER_POLL_WAKE && !choreographerStop); // Will block and process callbacks till ALooper_wake() is called with choreographerStop set
|
||||
while (ALooper_pollAll(-1, nullptr, nullptr, nullptr) == ALOOPER_POLL_WAKE && !choreographerStop) {
|
||||
while (paused.load(std::memory_order_acquire)) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||
}
|
||||
}
|
||||
} catch (const signal::SignalException &e) {
|
||||
LOGE("{}\nStack Trace:{}", e.what(), state.loader->GetStackTrace(e.frames));
|
||||
if (state.process)
|
||||
@ -235,6 +241,9 @@ namespace skyline::gpu {
|
||||
|
||||
try {
|
||||
presentQueue.Process([this](const PresentableFrame &frame) {
|
||||
while (paused.load(std::memory_order_acquire)) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||
}
|
||||
PresentFrame(frame);
|
||||
frame.presentCallback(); // We're calling the callback here as it's outside of all the locks in PresentFrame
|
||||
skipSignal = true;
|
||||
@ -412,6 +421,16 @@ namespace skyline::gpu {
|
||||
return nextFrameId++;
|
||||
}
|
||||
|
||||
void PresentationEngine::Pause() {
|
||||
paused.store(true, std::memory_order_release);
|
||||
LOGI("PresentationEngine paused.");
|
||||
}
|
||||
|
||||
void PresentationEngine::Resume() {
|
||||
paused.store(false, std::memory_order_release);
|
||||
LOGI("PresentationEngine resumed.");
|
||||
}
|
||||
|
||||
NativeWindowTransform PresentationEngine::GetTransformHint() {
|
||||
if (!vkSurface.has_value()) {
|
||||
std::unique_lock lock{mutex};
|
||||
|
@ -115,6 +115,9 @@ namespace skyline::gpu {
|
||||
*/
|
||||
void UpdateSurface(jobject newSurface);
|
||||
|
||||
void Pause();
|
||||
void Resume();
|
||||
|
||||
/**
|
||||
* @brief Queue the supplied texture to be presented to the screen
|
||||
* @param timestamp The earliest timestamp (relative to skyline::util::GetTickNs) at which the frame must be presented, it should be 0 when it doesn't matter
|
||||
|
@ -172,6 +172,8 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback, View.OnTo
|
||||
*/
|
||||
private external fun stopEmulation(join : Boolean) : Boolean
|
||||
|
||||
private external fun pauseEmulation(pause: Boolean)
|
||||
|
||||
/**
|
||||
* This sets the surface object in libskyline to the provided value, emulation is halted if set to null
|
||||
*
|
||||
@ -448,8 +450,8 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback, View.OnTo
|
||||
binding.inGameMenu.setNavigationItemSelectedListener {
|
||||
when (it.itemId) {
|
||||
R.id.menu_emulation_resume -> {
|
||||
if (!isEmulatorPaused) {
|
||||
pauseEmulator()
|
||||
if (isEmulatorPaused) {
|
||||
resumeEmulator()
|
||||
it.title = resources.getString(R.string.pause_emulation)
|
||||
it.icon = ResourcesCompat.getDrawable(
|
||||
resources,
|
||||
@ -457,7 +459,7 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback, View.OnTo
|
||||
this.theme
|
||||
)
|
||||
} else {
|
||||
resumeEmulator()
|
||||
pauseEmulator()
|
||||
it.title = resources.getString(R.string.resume_emulation)
|
||||
it.icon = ResourcesCompat.getDrawable(
|
||||
resources,
|
||||
@ -500,14 +502,14 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback, View.OnTo
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
fun pauseEmulator() {
|
||||
if (isEmulatorPaused) return
|
||||
setSurface(null)
|
||||
pauseEmulation(true)
|
||||
changeAudioStatus(false)
|
||||
isEmulatorPaused = true
|
||||
}
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
fun resumeEmulator() {
|
||||
gameSurface?.let { setSurface(it) }
|
||||
pauseEmulation(false)
|
||||
changeAudioStatus(true)
|
||||
isEmulatorPaused = false
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user