0
0
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:
Ishan09811 2024-12-19 22:06:43 +05:30 committed by GitHub
parent dd574b73d2
commit 4cc4981d08
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 38 additions and 6 deletions

View File

@ -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)

View File

@ -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};

View File

@ -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

View File

@ -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
}