android: emu_window: Adapt for use with split presenter thread.
This commit is contained in:
parent
a240d4356b
commit
12dc8b4206
@ -110,7 +110,7 @@ void Config::ReadValues() {
|
|||||||
Settings::values.use_shader_jit = sdl2_config->GetBoolean("Renderer", "use_shader_jit", true);
|
Settings::values.use_shader_jit = sdl2_config->GetBoolean("Renderer", "use_shader_jit", true);
|
||||||
Settings::values.resolution_factor =
|
Settings::values.resolution_factor =
|
||||||
static_cast<u16>(sdl2_config->GetInteger("Renderer", "resolution_factor", 1));
|
static_cast<u16>(sdl2_config->GetInteger("Renderer", "resolution_factor", 1));
|
||||||
Settings::values.vsync_enabled = sdl2_config->GetBoolean("Renderer", "vsync_enabled", false);
|
Settings::values.use_vsync_new = sdl2_config->GetBoolean("Renderer", "use_vsync_new", true);
|
||||||
Settings::values.use_frame_limit = sdl2_config->GetBoolean("Renderer", "use_frame_limit", true);
|
Settings::values.use_frame_limit = sdl2_config->GetBoolean("Renderer", "use_frame_limit", true);
|
||||||
Settings::values.frame_limit =
|
Settings::values.frame_limit =
|
||||||
static_cast<u16>(sdl2_config->GetReal("Renderer", "frame_limit", 1.0) * 100.0);
|
static_cast<u16>(sdl2_config->GetReal("Renderer", "frame_limit", 1.0) * 100.0);
|
||||||
|
@ -17,9 +17,53 @@
|
|||||||
#include "jni/emu_window/emu_window.h"
|
#include "jni/emu_window/emu_window.h"
|
||||||
#include "jni/id_cache.h"
|
#include "jni/id_cache.h"
|
||||||
#include "network/network.h"
|
#include "network/network.h"
|
||||||
|
#include "video_core/renderer_base.h"
|
||||||
|
#include "video_core/video_core.h"
|
||||||
|
|
||||||
static void* EGL_GetFuncAddress(const char* name) {
|
static constexpr std::array<EGLint, 15> egl_attribs{EGL_SURFACE_TYPE,
|
||||||
return (void*)eglGetProcAddress(name);
|
EGL_WINDOW_BIT,
|
||||||
|
EGL_RENDERABLE_TYPE,
|
||||||
|
EGL_OPENGL_ES3_BIT_KHR,
|
||||||
|
EGL_BLUE_SIZE,
|
||||||
|
8,
|
||||||
|
EGL_GREEN_SIZE,
|
||||||
|
8,
|
||||||
|
EGL_RED_SIZE,
|
||||||
|
8,
|
||||||
|
EGL_DEPTH_SIZE,
|
||||||
|
0,
|
||||||
|
EGL_STENCIL_SIZE,
|
||||||
|
0,
|
||||||
|
EGL_NONE};
|
||||||
|
static constexpr std::array<EGLint, 5> egl_empty_attribs{EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE};
|
||||||
|
static constexpr std::array<EGLint, 4> egl_context_attribs{EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE};
|
||||||
|
|
||||||
|
SharedContext_Android::SharedContext_Android(EGLDisplay egl_display, EGLConfig egl_config,
|
||||||
|
EGLContext egl_share_context)
|
||||||
|
: egl_display{egl_display}, egl_surface{eglCreatePbufferSurface(egl_display, egl_config,
|
||||||
|
egl_empty_attribs.data())},
|
||||||
|
egl_context{eglCreateContext(egl_display, egl_config, egl_share_context,
|
||||||
|
egl_context_attribs.data())} {
|
||||||
|
ASSERT_MSG(egl_surface, "eglCreatePbufferSurface() failed!");
|
||||||
|
ASSERT_MSG(egl_context, "eglCreateContext() failed!");
|
||||||
|
}
|
||||||
|
|
||||||
|
SharedContext_Android::~SharedContext_Android() {
|
||||||
|
if (!eglDestroySurface(egl_display, egl_surface)) {
|
||||||
|
LOG_CRITICAL(Frontend, "eglDestroySurface() failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!eglDestroyContext(egl_display, egl_context)) {
|
||||||
|
LOG_CRITICAL(Frontend, "eglDestroySurface() failed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SharedContext_Android::MakeCurrent() {
|
||||||
|
eglMakeCurrent(egl_display, egl_surface, egl_surface, egl_context);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SharedContext_Android::DoneCurrent() {
|
||||||
|
eglMakeCurrent(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool IsPortraitMode() {
|
static bool IsPortraitMode() {
|
||||||
@ -55,65 +99,61 @@ void EmuWindow_Android::OnFramebufferSizeChanged() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
EmuWindow_Android::EmuWindow_Android(ANativeWindow* surface) {
|
EmuWindow_Android::EmuWindow_Android(ANativeWindow* surface) {
|
||||||
LOG_DEBUG(Frontend, "Initializing Emuwindow");
|
LOG_DEBUG(Frontend, "Initializing EmuWindow_Android");
|
||||||
|
|
||||||
|
if (!surface) {
|
||||||
|
LOG_CRITICAL(Frontend, "surface is nullptr");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Network::Init();
|
Network::Init();
|
||||||
|
|
||||||
host_window = surface;
|
host_window = surface;
|
||||||
egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
|
|
||||||
|
|
||||||
EGLint num_configs{}, egl_major{}, egl_minor{};
|
if (egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY); egl_display == EGL_NO_DISPLAY) {
|
||||||
|
|
||||||
if (!egl_display) {
|
|
||||||
LOG_CRITICAL(Frontend, "eglGetDisplay() failed");
|
LOG_CRITICAL(Frontend, "eglGetDisplay() failed");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (eglInitialize(egl_display, 0, 0) != EGL_TRUE) {
|
||||||
if (!eglInitialize(egl_display, &egl_major, &egl_minor)) {
|
|
||||||
LOG_CRITICAL(Frontend, "eglInitialize() failed");
|
LOG_CRITICAL(Frontend, "eglInitialize() failed");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (EGLint egl_num_configs{}; eglChooseConfig(egl_display, egl_attribs.data(), &egl_config, 1,
|
||||||
constexpr std::array<int, 11> attribs{EGL_RENDERABLE_TYPE,
|
&egl_num_configs) != EGL_TRUE) {
|
||||||
EGL_OPENGL_ES3_BIT_KHR,
|
|
||||||
EGL_RED_SIZE,
|
|
||||||
8,
|
|
||||||
EGL_GREEN_SIZE,
|
|
||||||
8,
|
|
||||||
EGL_BLUE_SIZE,
|
|
||||||
8,
|
|
||||||
EGL_SURFACE_TYPE,
|
|
||||||
EGL_WINDOW_BIT,
|
|
||||||
EGL_NONE};
|
|
||||||
|
|
||||||
if (!eglChooseConfig(egl_display, attribs.data(), &config, 1, &num_configs)) {
|
|
||||||
LOG_CRITICAL(Frontend, "eglChooseConfig() failed");
|
LOG_CRITICAL(Frontend, "eglChooseConfig() failed");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
eglBindAPI(EGL_OPENGL_ES_API);
|
CreateWindowSurface();
|
||||||
|
|
||||||
if (!egl_context) {
|
if (egl_context = eglCreateContext(egl_display, egl_config, 0, egl_context_attribs.data());
|
||||||
std::vector<EGLint> ctx_attribs{EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE};
|
egl_context == EGL_NO_CONTEXT) {
|
||||||
egl_context = eglCreateContext(egl_display, config, EGL_NO_CONTEXT, &ctx_attribs[0]);
|
LOG_CRITICAL(Frontend, "eglCreateContext() failed");
|
||||||
shared_attribs = std::move(ctx_attribs);
|
return;
|
||||||
|
|
||||||
if (!egl_context) {
|
|
||||||
LOG_CRITICAL(Frontend, "eglCreateContext() failed");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if (eglSurfaceAttrib(egl_display, egl_surface, EGL_SWAP_BEHAVIOR, EGL_BUFFER_DESTROYED) !=
|
||||||
if (!CreateWindowSurface()) {
|
EGL_TRUE) {
|
||||||
LOG_CRITICAL(Frontend, "CreateWindowSurface() failed");
|
LOG_CRITICAL(Frontend, "eglSurfaceAttrib() failed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (core_context = CreateSharedContext(); !core_context) {
|
||||||
|
LOG_CRITICAL(Frontend, "CreateSharedContext() failed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (eglMakeCurrent(egl_display, egl_surface, egl_surface, egl_context) != EGL_TRUE) {
|
||||||
|
LOG_CRITICAL(Frontend, "eglMakeCurrent() failed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!gladLoadGLES2Loader((GLADloadproc)eglGetProcAddress)) {
|
||||||
|
LOG_CRITICAL(Frontend, "gladLoadGLES2Loader() failed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!eglSwapInterval(egl_display, Settings::values.use_vsync_new ? 1 : 0)) {
|
||||||
|
LOG_CRITICAL(Frontend, "eglSwapInterval() failed");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
MakeCurrent();
|
|
||||||
|
|
||||||
OnFramebufferSizeChanged();
|
OnFramebufferSizeChanged();
|
||||||
|
|
||||||
gladLoadGLES2Loader(EGL_GetFuncAddress);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EmuWindow_Android::CreateWindowSurface() {
|
bool EmuWindow_Android::CreateWindowSurface() {
|
||||||
@ -122,32 +162,30 @@ bool EmuWindow_Android::CreateWindowSurface() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
EGLint format{};
|
EGLint format{};
|
||||||
eglGetConfigAttrib(egl_display, config, EGL_NATIVE_VISUAL_ID, &format);
|
eglGetConfigAttrib(egl_display, egl_config, EGL_NATIVE_VISUAL_ID, &format);
|
||||||
ANativeWindow_setBuffersGeometry(host_window, 0, 0, format);
|
ANativeWindow_setBuffersGeometry(host_window, 0, 0, format);
|
||||||
window_width = ANativeWindow_getWidth(host_window);
|
window_width = ANativeWindow_getWidth(host_window);
|
||||||
window_height = ANativeWindow_getHeight(host_window);
|
window_height = ANativeWindow_getHeight(host_window);
|
||||||
UpdateCurrentFramebufferLayout(window_width, window_height);
|
UpdateCurrentFramebufferLayout(window_width, window_height);
|
||||||
NotifyClientAreaSizeChanged(std::make_pair(window_width, window_height));
|
|
||||||
|
|
||||||
egl_surface = eglCreateWindowSurface(egl_display, config,
|
if (egl_surface = eglCreateWindowSurface(egl_display, egl_config, host_window, 0);
|
||||||
static_cast<EGLNativeWindowType>(host_window), nullptr);
|
egl_surface == EGL_NO_SURFACE) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
return !!egl_surface;
|
return !!egl_surface;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmuWindow_Android::DestroyWindowSurface() {
|
void EmuWindow_Android::DestroyWindowSurface() {
|
||||||
if (egl_surface == EGL_NO_SURFACE) {
|
if (!egl_surface) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (eglGetCurrentSurface(EGL_DRAW) == egl_surface) {
|
if (eglGetCurrentSurface(EGL_DRAW) == egl_surface) {
|
||||||
eglMakeCurrent(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
eglMakeCurrent(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!eglDestroySurface(egl_display, egl_surface)) {
|
if (!eglDestroySurface(egl_display, egl_surface)) {
|
||||||
LOG_CRITICAL(Frontend, "eglDestroySurface() failed");
|
LOG_CRITICAL(Frontend, "eglDestroySurface() failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
egl_surface = EGL_NO_SURFACE;
|
egl_surface = EGL_NO_SURFACE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -155,30 +193,57 @@ void EmuWindow_Android::DestroyContext() {
|
|||||||
if (!egl_context) {
|
if (!egl_context) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (eglGetCurrentContext() == egl_context) {
|
if (eglGetCurrentContext() == egl_context) {
|
||||||
eglMakeCurrent(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
eglMakeCurrent(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!eglDestroyContext(egl_display, egl_context)) {
|
if (!eglDestroyContext(egl_display, egl_context)) {
|
||||||
LOG_CRITICAL(Frontend, "eglDestroySurface() failed");
|
LOG_CRITICAL(Frontend, "eglDestroySurface() failed");
|
||||||
}
|
}
|
||||||
|
if (!eglTerminate(egl_display)) {
|
||||||
if (!is_shared && !eglTerminate(egl_display)) {
|
|
||||||
LOG_CRITICAL(Frontend, "eglTerminate() failed");
|
LOG_CRITICAL(Frontend, "eglTerminate() failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
egl_context = EGL_NO_CONTEXT;
|
egl_context = EGL_NO_CONTEXT;
|
||||||
egl_display = EGL_NO_DISPLAY;
|
egl_display = EGL_NO_DISPLAY;
|
||||||
}
|
}
|
||||||
|
|
||||||
EmuWindow_Android::~EmuWindow_Android() {
|
EmuWindow_Android::~EmuWindow_Android() {
|
||||||
|
StopPresenting();
|
||||||
DestroyWindowSurface();
|
DestroyWindowSurface();
|
||||||
DestroyContext();
|
DestroyContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmuWindow_Android::SwapBuffers() {
|
std::unique_ptr<Frontend::GraphicsContext> EmuWindow_Android::CreateSharedContext() const {
|
||||||
eglSwapBuffers(egl_display, egl_surface);
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
eglSwapInterval(egl_display, Settings::values.use_vsync_new ? 1 : 0);
|
||||||
|
while (IsPresenting()) {
|
||||||
|
VideoCore::g_renderer->TryPresent(100);
|
||||||
|
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() {
|
||||||
@ -188,17 +253,21 @@ void EmuWindow_Android::PollEvents() {
|
|||||||
|
|
||||||
host_window = render_window;
|
host_window = render_window;
|
||||||
render_window = nullptr;
|
render_window = nullptr;
|
||||||
DoneCurrent();
|
|
||||||
|
if (IsPresenting()) {
|
||||||
|
StopPresenting();
|
||||||
|
}
|
||||||
|
|
||||||
DestroyWindowSurface();
|
DestroyWindowSurface();
|
||||||
CreateWindowSurface();
|
CreateWindowSurface();
|
||||||
MakeCurrent();
|
|
||||||
OnFramebufferSizeChanged();
|
OnFramebufferSizeChanged();
|
||||||
|
StartPresenting();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmuWindow_Android::MakeCurrent() {
|
void EmuWindow_Android::MakeCurrent() {
|
||||||
eglMakeCurrent(egl_display, egl_surface, egl_surface, egl_context);
|
core_context->MakeCurrent();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmuWindow_Android::DoneCurrent() {
|
void EmuWindow_Android::DoneCurrent() {
|
||||||
eglMakeCurrent(egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
core_context->DoneCurrent();
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <thread>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <EGL/egl.h>
|
#include <EGL/egl.h>
|
||||||
@ -13,11 +14,30 @@
|
|||||||
|
|
||||||
struct ANativeWindow;
|
struct ANativeWindow;
|
||||||
|
|
||||||
|
class SharedContext_Android : public Frontend::GraphicsContext {
|
||||||
|
public:
|
||||||
|
SharedContext_Android(EGLDisplay egl_display, EGLConfig egl_config,
|
||||||
|
EGLContext egl_share_context);
|
||||||
|
|
||||||
|
~SharedContext_Android() override;
|
||||||
|
|
||||||
|
void MakeCurrent() override;
|
||||||
|
|
||||||
|
void DoneCurrent() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
EGLSurface egl_surface{};
|
||||||
|
EGLContext egl_context{};
|
||||||
|
EGLDisplay egl_display{};
|
||||||
|
};
|
||||||
|
|
||||||
class EmuWindow_Android : public Frontend::EmuWindow {
|
class EmuWindow_Android : public Frontend::EmuWindow {
|
||||||
public:
|
public:
|
||||||
EmuWindow_Android(ANativeWindow* surface);
|
EmuWindow_Android(ANativeWindow* surface);
|
||||||
~EmuWindow_Android();
|
~EmuWindow_Android();
|
||||||
|
|
||||||
|
void Present();
|
||||||
|
|
||||||
/// Called by the onSurfaceChanges() method to change the surface
|
/// Called by the onSurfaceChanges() method to change the surface
|
||||||
void OnSurfaceChanged(ANativeWindow* surface);
|
void OnSurfaceChanged(ANativeWindow* surface);
|
||||||
|
|
||||||
@ -27,11 +47,16 @@ public:
|
|||||||
/// Handles movement of touch pointer
|
/// Handles movement of touch pointer
|
||||||
void OnTouchMoved(int x, int y);
|
void OnTouchMoved(int x, int y);
|
||||||
|
|
||||||
void SwapBuffers() override;
|
|
||||||
void PollEvents() override;
|
void PollEvents() override;
|
||||||
void MakeCurrent() override;
|
void MakeCurrent() override;
|
||||||
void DoneCurrent() override;
|
void DoneCurrent() override;
|
||||||
|
|
||||||
|
void StartPresenting();
|
||||||
|
void StopPresenting();
|
||||||
|
bool IsPresenting() const;
|
||||||
|
|
||||||
|
std::unique_ptr<GraphicsContext> CreateSharedContext() const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void OnFramebufferSizeChanged();
|
void OnFramebufferSizeChanged();
|
||||||
bool CreateWindowSurface();
|
bool CreateWindowSurface();
|
||||||
@ -41,13 +66,17 @@ private:
|
|||||||
ANativeWindow* render_window{};
|
ANativeWindow* render_window{};
|
||||||
ANativeWindow* host_window{};
|
ANativeWindow* host_window{};
|
||||||
|
|
||||||
bool is_shared{};
|
|
||||||
int window_width{};
|
int window_width{};
|
||||||
int window_height{};
|
int window_height{};
|
||||||
std::vector<int> shared_attribs;
|
|
||||||
|
|
||||||
EGLConfig config;
|
EGLConfig egl_config;
|
||||||
EGLSurface egl_surface{};
|
EGLSurface egl_surface{};
|
||||||
EGLContext egl_context{};
|
EGLContext egl_context{};
|
||||||
EGLDisplay egl_display{};
|
EGLDisplay egl_display{};
|
||||||
|
|
||||||
|
std::unique_ptr<Frontend::GraphicsContext> core_context;
|
||||||
|
|
||||||
|
std::unique_ptr<std::thread> presentation_thread;
|
||||||
|
|
||||||
|
bool is_presenting{};
|
||||||
};
|
};
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
#include "core/file_sys/cia_container.h"
|
#include "core/file_sys/cia_container.h"
|
||||||
#include "core/frontend/applets/default_applets.h"
|
#include "core/frontend/applets/default_applets.h"
|
||||||
|
#include "core/frontend/scope_acquire_context.h"
|
||||||
#include "core/gdbstub/gdbstub.h"
|
#include "core/gdbstub/gdbstub.h"
|
||||||
#include "core/hle/service/am/am.h"
|
#include "core/hle/service/am/am.h"
|
||||||
#include "core/loader/loader.h"
|
#include "core/loader/loader.h"
|
||||||
@ -142,6 +143,7 @@ static Core::System::ResultStatus RunCitra(const std::string& filepath) {
|
|||||||
InputManager::Init();
|
InputManager::Init();
|
||||||
SCOPE_EXIT({ InputManager::Shutdown(); });
|
SCOPE_EXIT({ InputManager::Shutdown(); });
|
||||||
|
|
||||||
|
Frontend::ScopeAcquireContext scope(*window);
|
||||||
const Core::System::ResultStatus load_result{system.Load(*window, filepath)};
|
const Core::System::ResultStatus load_result{system.Load(*window, filepath)};
|
||||||
if (load_result != Core::System::ResultStatus::Success) {
|
if (load_result != Core::System::ResultStatus::Success) {
|
||||||
return load_result;
|
return load_result;
|
||||||
@ -153,6 +155,7 @@ static Core::System::ResultStatus RunCitra(const std::string& filepath) {
|
|||||||
is_running = true;
|
is_running = true;
|
||||||
pause_emulation = false;
|
pause_emulation = false;
|
||||||
|
|
||||||
|
window->StartPresenting();
|
||||||
while (is_running) {
|
while (is_running) {
|
||||||
if (!pause_emulation) {
|
if (!pause_emulation) {
|
||||||
system.RunLoop();
|
system.RunLoop();
|
||||||
@ -166,6 +169,7 @@ static Core::System::ResultStatus RunCitra(const std::string& filepath) {
|
|||||||
running_cv.wait(lock, [] { return !pause_emulation || !is_running; });
|
running_cv.wait(lock, [] { return !pause_emulation || !is_running; });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
window->StopPresenting();
|
||||||
|
|
||||||
return Core::System::ResultStatus::Success;
|
return Core::System::ResultStatus::Success;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user