Revert "Presenting in ui thread (#92)"

This reverts commit d1c2e8fb88873bf8642d07ca7e386cc1bac19692.
This commit is contained in:
bunnei 2020-06-01 16:34:40 -04:00
parent fe4ff50d5b
commit 1d083cc7db
8 changed files with 86 additions and 51 deletions

View File

@ -0,0 +1,26 @@
package org.citra.citra_emu;
import android.content.Context;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
/**
* Instrumented test, which will execute on an Android device.
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
@Test
public void useAppContext() {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getTargetContext();
assertEquals("org.citra.citra_emu", appContext.getPackageName());
}
}

View File

@ -172,8 +172,6 @@ public final class NativeLibrary {
public static native void SurfaceDestroyed(); public static native void SurfaceDestroyed();
public static native void DoFrame();
/** /**
* Unpauses emulation from a paused state. * Unpauses emulation from a paused state.
*/ */

View File

@ -6,7 +6,6 @@ import android.content.SharedPreferences;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.view.Choreographer;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.Surface; import android.view.Surface;
import android.view.SurfaceHolder; import android.view.SurfaceHolder;
@ -31,7 +30,7 @@ import org.citra.citra_emu.utils.DirectoryStateReceiver;
import org.citra.citra_emu.utils.EmulationMenuSettings; import org.citra.citra_emu.utils.EmulationMenuSettings;
import org.citra.citra_emu.utils.Log; import org.citra.citra_emu.utils.Log;
public final class EmulationFragment extends Fragment implements SurfaceHolder.Callback, Choreographer.FrameCallback { public final class EmulationFragment extends Fragment implements SurfaceHolder.Callback {
private static final String KEY_GAMEPATH = "gamepath"; private static final String KEY_GAMEPATH = "gamepath";
private static final Handler perfStatsUpdateHandler = new Handler(); private static final Handler perfStatsUpdateHandler = new Handler();
@ -115,7 +114,6 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C
@Override @Override
public void onResume() { public void onResume() {
super.onResume(); super.onResume();
Choreographer.getInstance().postFrameCallback(this);
if (DirectoryInitialization.areCitraDirectoriesReady()) { if (DirectoryInitialization.areCitraDirectoriesReady()) {
mEmulationState.run(activity.isActivityRecreated()); mEmulationState.run(activity.isActivityRecreated());
} else { } else {
@ -130,11 +128,8 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C
directoryStateReceiver = null; directoryStateReceiver = null;
} }
if (mEmulationState.isRunning()) { if (mEmulationState.isRunning())
mEmulationState.pause(); mEmulationState.pause();
}
Choreographer.getInstance().removeFrameCallback(this);
super.onPause(); super.onPause();
} }
@ -232,12 +227,6 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C
mEmulationState.clearSurface(); mEmulationState.clearSurface();
} }
@Override
public void doFrame(long frameTimeNanos) {
Choreographer.getInstance().postFrameCallback(this);
NativeLibrary.DoFrame();
}
public void stopEmulation() { public void stopEmulation() {
mEmulationState.stop(); mEmulationState.stop();
} }
@ -353,9 +342,9 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C
private void runWithValidSurface() { private void runWithValidSurface() {
mRunWhenSurfaceIsValid = false; mRunWhenSurfaceIsValid = false;
if (state == State.STOPPED) { if (state == State.STOPPED) {
NativeLibrary.SurfaceChanged(mSurface);
Thread mEmulationThread = new Thread(() -> Thread mEmulationThread = new Thread(() ->
{ {
NativeLibrary.SurfaceChanged(mSurface);
Log.debug("[EmulationFragment] Starting emulation thread."); Log.debug("[EmulationFragment] Starting emulation thread.");
NativeLibrary.Run(mGamePath); NativeLibrary.Run(mGamePath);
}, "NativeEmulation"); }, "NativeEmulation");

View File

@ -79,7 +79,6 @@ static void UpdateLandscapeScreenLayout() {
void EmuWindow_Android::OnSurfaceChanged(ANativeWindow* surface) { void EmuWindow_Android::OnSurfaceChanged(ANativeWindow* surface) {
render_window = surface; render_window = surface;
StopPresenting();
} }
bool EmuWindow_Android::OnTouchEvent(int x, int y, bool pressed) { bool EmuWindow_Android::OnTouchEvent(int x, int y, bool pressed) {
@ -220,6 +219,7 @@ void EmuWindow_Android::DestroyContext() {
} }
EmuWindow_Android::~EmuWindow_Android() { EmuWindow_Android::~EmuWindow_Android() {
StopPresenting();
DestroyWindowSurface(); DestroyWindowSurface();
DestroyContext(); DestroyContext();
} }
@ -228,26 +228,34 @@ std::unique_ptr<Frontend::GraphicsContext> EmuWindow_Android::CreateSharedContex
return std::make_unique<SharedContext_Android>(egl_display, egl_config, egl_context); return std::make_unique<SharedContext_Android>(egl_display, egl_config, egl_context);
} }
void EmuWindow_Android::StopPresenting() { void EmuWindow_Android::StartPresenting() {
if (presenting_state == PresentingState::Running) { ASSERT(!presentation_thread);
eglMakeCurrent(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); is_presenting = true;
} presentation_thread =
presenting_state = PresentingState::Stopped; std::make_unique<std::thread>([emu_window{this}] { emu_window->Present(); });
} }
void EmuWindow_Android::TryPresenting() { void EmuWindow_Android::StopPresenting() {
if (presenting_state != PresentingState::Running) { is_presenting = false;
if (presenting_state == PresentingState::Initial) { if (presentation_thread) {
presentation_thread->join();
presentation_thread.reset();
}
}
bool EmuWindow_Android::IsPresenting() const {
return is_presenting;
}
void EmuWindow_Android::Present() {
eglMakeCurrent(egl_display, egl_surface, egl_surface, egl_context); eglMakeCurrent(egl_display, egl_surface, egl_surface, egl_context);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
presenting_state = PresentingState::Running;
} else {
return;
}
}
eglSwapInterval(egl_display, Settings::values.use_vsync_new ? 1 : 0); eglSwapInterval(egl_display, Settings::values.use_vsync_new ? 1 : 0);
while (IsPresenting()) {
VideoCore::g_renderer->TryPresent(100); VideoCore::g_renderer->TryPresent(100);
eglSwapBuffers(egl_display, egl_surface); eglSwapBuffers(egl_display, egl_surface);
}
eglMakeCurrent(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
} }
void EmuWindow_Android::PollEvents() { void EmuWindow_Android::PollEvents() {
@ -258,10 +266,14 @@ void EmuWindow_Android::PollEvents() {
host_window = render_window; host_window = render_window;
render_window = nullptr; render_window = nullptr;
if (IsPresenting()) {
StopPresenting();
}
DestroyWindowSurface(); DestroyWindowSurface();
CreateWindowSurface(); CreateWindowSurface();
OnFramebufferSizeChanged(); OnFramebufferSizeChanged();
presenting_state = PresentingState::Initial; StartPresenting();
} }
void EmuWindow_Android::MakeCurrent() { void EmuWindow_Android::MakeCurrent() {

View File

@ -4,6 +4,7 @@
#pragma once #pragma once
#include <thread>
#include <vector> #include <vector>
#include <EGL/egl.h> #include <EGL/egl.h>
@ -50,8 +51,9 @@ public:
void MakeCurrent() override; void MakeCurrent() override;
void DoneCurrent() override; void DoneCurrent() override;
void TryPresenting(); void StartPresenting();
void StopPresenting(); void StopPresenting();
bool IsPresenting() const;
std::unique_ptr<GraphicsContext> CreateSharedContext() const override; std::unique_ptr<GraphicsContext> CreateSharedContext() const override;
@ -74,10 +76,7 @@ private:
std::unique_ptr<Frontend::GraphicsContext> core_context; std::unique_ptr<Frontend::GraphicsContext> core_context;
enum class PresentingState { std::unique_ptr<std::thread> presentation_thread;
Initial,
Running, bool is_presenting{};
Stopped,
};
PresentingState presenting_state{};
}; };

View File

@ -102,6 +102,7 @@ static void TryShutdown() {
return; return;
} }
window->StopPresenting();
window->DoneCurrent(); window->DoneCurrent();
Core::System::GetInstance().Shutdown(); Core::System::GetInstance().Shutdown();
window.reset(); window.reset();
@ -166,6 +167,8 @@ static Core::System::ResultStatus RunCitra(const std::string& filepath) {
is_running = true; is_running = true;
pause_emulation = false; pause_emulation = false;
window->StartPresenting();
SCOPE_EXIT({ TryShutdown(); }); SCOPE_EXIT({ TryShutdown(); });
// Audio stretching on Android is only useful with lower framerates, disable it when fullspeed // Audio stretching on Android is only useful with lower framerates, disable it when fullspeed
@ -193,7 +196,6 @@ static Core::System::ResultStatus RunCitra(const std::string& filepath) {
std::unique_lock<std::mutex> pause_lock(paused_mutex); std::unique_lock<std::mutex> pause_lock(paused_mutex);
running_cv.wait(pause_lock, [] { return !pause_emulation || !is_running; }); running_cv.wait(pause_lock, [] { return !pause_emulation || !is_running; });
window->PollEvents();
} }
} }
@ -223,13 +225,6 @@ 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, void Java_org_citra_citra_1emu_NativeLibrary_NotifyOrientationChange(JNIEnv* env,
[[maybe_unused]] jclass clazz, [[maybe_unused]] jclass clazz,
jint layout_option, jint layout_option,
@ -307,7 +302,6 @@ void Java_org_citra_citra_1emu_NativeLibrary_StopEmulation(JNIEnv* env,
[[maybe_unused]] jclass clazz) { [[maybe_unused]] jclass clazz) {
is_running = false; is_running = false;
pause_emulation = false; pause_emulation = false;
window->StopPresenting();
running_cv.notify_all(); running_cv.notify_all();
} }

View File

@ -0,0 +1,17 @@
package org.citra.citra_emu;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* Example local unit test, which will execute on the development machine (host).
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
public class ExampleUnitTest {
@Test
public void addition_isCorrect() {
assertEquals(4, 2 + 2);
}
}

View File

@ -7,7 +7,7 @@ buildscript {
jcenter() jcenter()
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:3.6.3' classpath 'com.android.tools.build:gradle:3.6.1'
// NOTE: Do not place your application dependencies here; they belong // NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files // in the individual module build.gradle files