presenting in the ui thread
This commit is contained in:
parent
0945c9d5e9
commit
8ebc94d899
@ -172,6 +172,8 @@ public final class NativeLibrary {
|
||||
|
||||
public static native void SurfaceDestroyed();
|
||||
|
||||
public static native void DoFrame();
|
||||
|
||||
/**
|
||||
* Unpauses emulation from a paused state.
|
||||
*/
|
||||
|
@ -6,6 +6,7 @@ import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.view.Choreographer;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Surface;
|
||||
import android.view.SurfaceHolder;
|
||||
@ -30,7 +31,7 @@ import org.citra.citra_emu.utils.DirectoryStateReceiver;
|
||||
import org.citra.citra_emu.utils.EmulationMenuSettings;
|
||||
import org.citra.citra_emu.utils.Log;
|
||||
|
||||
public final class EmulationFragment extends Fragment implements SurfaceHolder.Callback {
|
||||
public final class EmulationFragment extends Fragment implements SurfaceHolder.Callback, Choreographer.FrameCallback {
|
||||
private static final String KEY_GAMEPATH = "gamepath";
|
||||
|
||||
private static final Handler perfStatsUpdateHandler = new Handler();
|
||||
@ -114,6 +115,7 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
Choreographer.getInstance().postFrameCallback(this);
|
||||
if (DirectoryInitialization.areCitraDirectoriesReady()) {
|
||||
mEmulationState.run(activity.isActivityRecreated());
|
||||
} else {
|
||||
@ -128,8 +130,11 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C
|
||||
directoryStateReceiver = null;
|
||||
}
|
||||
|
||||
if (mEmulationState.isRunning())
|
||||
if (mEmulationState.isRunning()) {
|
||||
mEmulationState.pause();
|
||||
}
|
||||
|
||||
Choreographer.getInstance().removeFrameCallback(this);
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
@ -227,6 +232,12 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C
|
||||
mEmulationState.clearSurface();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doFrame(long frameTimeNanos) {
|
||||
Choreographer.getInstance().postFrameCallback(this);
|
||||
NativeLibrary.DoFrame();
|
||||
}
|
||||
|
||||
public void stopEmulation() {
|
||||
mEmulationState.stop();
|
||||
}
|
||||
@ -342,9 +353,9 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C
|
||||
private void runWithValidSurface() {
|
||||
mRunWhenSurfaceIsValid = false;
|
||||
if (state == State.STOPPED) {
|
||||
NativeLibrary.SurfaceChanged(mSurface);
|
||||
Thread mEmulationThread = new Thread(() ->
|
||||
{
|
||||
NativeLibrary.SurfaceChanged(mSurface);
|
||||
Log.debug("[EmulationFragment] Starting emulation thread.");
|
||||
NativeLibrary.Run(mGamePath);
|
||||
}, "NativeEmulation");
|
||||
|
@ -79,6 +79,7 @@ static void UpdateLandscapeScreenLayout() {
|
||||
|
||||
void EmuWindow_Android::OnSurfaceChanged(ANativeWindow* surface) {
|
||||
render_window = surface;
|
||||
StopPresenting();
|
||||
}
|
||||
|
||||
bool EmuWindow_Android::OnTouchEvent(int x, int y, bool pressed) {
|
||||
@ -219,7 +220,6 @@ void EmuWindow_Android::DestroyContext() {
|
||||
}
|
||||
|
||||
EmuWindow_Android::~EmuWindow_Android() {
|
||||
StopPresenting();
|
||||
DestroyWindowSurface();
|
||||
DestroyContext();
|
||||
}
|
||||
@ -228,34 +228,27 @@ std::unique_ptr<Frontend::GraphicsContext> EmuWindow_Android::CreateSharedContex
|
||||
return std::make_unique<SharedContext_Android>(egl_display, egl_config, egl_context);
|
||||
}
|
||||
|
||||
void EmuWindow_Android::StartPresenting() {
|
||||
ASSERT(!presentation_thread);
|
||||
is_presenting = true;
|
||||
presentation_thread =
|
||||
std::make_unique<std::thread>([emu_window{this}] { emu_window->Present(); });
|
||||
}
|
||||
|
||||
void EmuWindow_Android::StopPresenting() {
|
||||
is_presenting = false;
|
||||
if (presentation_thread) {
|
||||
presentation_thread->join();
|
||||
presentation_thread.reset();
|
||||
if (presenting_state == PresentingState::Running) {
|
||||
eglMakeCurrent(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
}
|
||||
presenting_state = PresentingState::Stopped;
|
||||
}
|
||||
|
||||
bool EmuWindow_Android::IsPresenting() const {
|
||||
return is_presenting;
|
||||
}
|
||||
|
||||
void EmuWindow_Android::Present() {
|
||||
eglMakeCurrent(egl_display, egl_surface, egl_surface, egl_context);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||
void EmuWindow_Android::TryPresenting() {
|
||||
if (presenting_state != PresentingState::Running) {
|
||||
if (presenting_state == PresentingState::Initial) {
|
||||
eglMakeCurrent(egl_display, egl_surface, egl_surface, egl_context);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||
presenting_state = PresentingState::Running;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
eglSwapInterval(egl_display, Settings::values.use_vsync_new ? 1 : 0);
|
||||
while (IsPresenting()) {
|
||||
VideoCore::g_renderer->TryPresent(100);
|
||||
if (VideoCore::g_renderer->TryPresent()) {
|
||||
eglSwapBuffers(egl_display, egl_surface);
|
||||
}
|
||||
eglMakeCurrent(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
}
|
||||
|
||||
void EmuWindow_Android::PollEvents() {
|
||||
@ -266,14 +259,10 @@ void EmuWindow_Android::PollEvents() {
|
||||
host_window = render_window;
|
||||
render_window = nullptr;
|
||||
|
||||
if (IsPresenting()) {
|
||||
StopPresenting();
|
||||
}
|
||||
|
||||
DestroyWindowSurface();
|
||||
CreateWindowSurface();
|
||||
OnFramebufferSizeChanged();
|
||||
StartPresenting();
|
||||
presenting_state = PresentingState::Initial;
|
||||
}
|
||||
|
||||
void EmuWindow_Android::MakeCurrent() {
|
||||
|
@ -4,7 +4,6 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
#include <EGL/egl.h>
|
||||
@ -51,9 +50,8 @@ public:
|
||||
void MakeCurrent() override;
|
||||
void DoneCurrent() override;
|
||||
|
||||
void StartPresenting();
|
||||
void TryPresenting();
|
||||
void StopPresenting();
|
||||
bool IsPresenting() const;
|
||||
|
||||
std::unique_ptr<GraphicsContext> CreateSharedContext() const override;
|
||||
|
||||
@ -76,7 +74,10 @@ private:
|
||||
|
||||
std::unique_ptr<Frontend::GraphicsContext> core_context;
|
||||
|
||||
std::unique_ptr<std::thread> presentation_thread;
|
||||
|
||||
bool is_presenting{};
|
||||
enum class PresentingState {
|
||||
Initial,
|
||||
Running,
|
||||
Stopped,
|
||||
};
|
||||
PresentingState presenting_state{};
|
||||
};
|
||||
|
@ -102,7 +102,6 @@ static void TryShutdown() {
|
||||
return;
|
||||
}
|
||||
|
||||
window->StopPresenting();
|
||||
window->DoneCurrent();
|
||||
Core::System::GetInstance().Shutdown();
|
||||
window.reset();
|
||||
@ -167,8 +166,6 @@ static Core::System::ResultStatus RunCitra(const std::string& filepath) {
|
||||
is_running = true;
|
||||
pause_emulation = false;
|
||||
|
||||
window->StartPresenting();
|
||||
|
||||
SCOPE_EXIT({ TryShutdown(); });
|
||||
|
||||
// Audio stretching on Android is only useful with lower framerates, disable it when fullspeed
|
||||
@ -196,6 +193,7 @@ static Core::System::ResultStatus RunCitra(const std::string& filepath) {
|
||||
|
||||
std::unique_lock<std::mutex> pause_lock(paused_mutex);
|
||||
running_cv.wait(pause_lock, [] { return !pause_emulation || !is_running; });
|
||||
window->PollEvents();
|
||||
}
|
||||
}
|
||||
|
||||
@ -225,6 +223,13 @@ void Java_org_citra_citra_1emu_NativeLibrary_SurfaceDestroyed(JNIEnv* env,
|
||||
}
|
||||
}
|
||||
|
||||
void Java_org_citra_citra_1emu_NativeLibrary_DoFrame(JNIEnv* env, [[maybe_unused]] jclass clazz) {
|
||||
if (!is_running || pause_emulation) {
|
||||
return;
|
||||
}
|
||||
window->TryPresenting();
|
||||
}
|
||||
|
||||
void Java_org_citra_citra_1emu_NativeLibrary_NotifyOrientationChange(JNIEnv* env,
|
||||
[[maybe_unused]] jclass clazz,
|
||||
jint layout_option,
|
||||
@ -302,6 +307,7 @@ void Java_org_citra_citra_1emu_NativeLibrary_StopEmulation(JNIEnv* env,
|
||||
[[maybe_unused]] jclass clazz) {
|
||||
is_running = false;
|
||||
pause_emulation = false;
|
||||
window->StopPresenting();
|
||||
running_cv.notify_all();
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user