mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-05 14:31:24 +12:00
RSX/Qt: Reuse gs_frame if possible
This commit is contained in:
parent
99f1f4c22a
commit
1ab3a0bd73
18 changed files with 101 additions and 16 deletions
|
@ -498,6 +498,9 @@ void lv2_exitspawn(ppu_thread& ppu, std::vector<std::string>& argv, std::vector<
|
||||||
};
|
};
|
||||||
|
|
||||||
signal_system_cache_can_stay();
|
signal_system_cache_can_stay();
|
||||||
|
|
||||||
|
// Make sure we keep the game window opened
|
||||||
|
Emu.SetContinuousMode(true);
|
||||||
Emu.Kill(false);
|
Emu.Kill(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -52,6 +52,14 @@ GLGSRender::GLGSRender(utils::serial* ar) noexcept : GSRender(ar)
|
||||||
backend_config.supports_normalized_barycentrics = true;
|
backend_config.supports_normalized_barycentrics = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GLGSRender::~GLGSRender()
|
||||||
|
{
|
||||||
|
if (m_frame)
|
||||||
|
{
|
||||||
|
m_frame->reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
extern CellGcmContextData current_context;
|
extern CellGcmContextData current_context;
|
||||||
|
|
||||||
void GLGSRender::set_viewport()
|
void GLGSRender::set_viewport()
|
||||||
|
|
|
@ -159,6 +159,7 @@ public:
|
||||||
|
|
||||||
GLGSRender(utils::serial* ar) noexcept;
|
GLGSRender(utils::serial* ar) noexcept;
|
||||||
GLGSRender() noexcept : GLGSRender(nullptr) {}
|
GLGSRender() noexcept : GLGSRender(nullptr) {}
|
||||||
|
virtual ~GLGSRender();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@ public:
|
||||||
virtual ~GSFrameBase() = default;
|
virtual ~GSFrameBase() = default;
|
||||||
|
|
||||||
virtual void close() = 0;
|
virtual void close() = 0;
|
||||||
|
virtual void reset() = 0;
|
||||||
virtual bool shown() = 0;
|
virtual bool shown() = 0;
|
||||||
virtual void hide() = 0;
|
virtual void hide() = 0;
|
||||||
virtual void show() = 0;
|
virtual void show() = 0;
|
||||||
|
|
|
@ -18,7 +18,7 @@ GSRender::~GSRender()
|
||||||
{
|
{
|
||||||
m_context = nullptr;
|
m_context = nullptr;
|
||||||
|
|
||||||
if (m_frame)
|
if (m_frame && !m_continuous_mode)
|
||||||
{
|
{
|
||||||
m_frame->close();
|
m_frame->close();
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,10 @@ void GSRender::on_exit()
|
||||||
|
|
||||||
if (m_frame)
|
if (m_frame)
|
||||||
{
|
{
|
||||||
m_frame->hide();
|
if (!m_continuous_mode)
|
||||||
|
{
|
||||||
|
m_frame->hide();
|
||||||
|
}
|
||||||
m_frame->delete_context(m_context);
|
m_frame->delete_context(m_context);
|
||||||
m_context = nullptr;
|
m_context = nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,12 +21,15 @@ class GSRender : public rsx::thread
|
||||||
protected:
|
protected:
|
||||||
GSFrameBase* m_frame;
|
GSFrameBase* m_frame;
|
||||||
draw_context_t m_context = nullptr;
|
draw_context_t m_context = nullptr;
|
||||||
|
bool m_continuous_mode = false;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
~GSRender() override;
|
~GSRender() override;
|
||||||
|
|
||||||
GSRender(utils::serial* ar) noexcept;
|
GSRender(utils::serial* ar) noexcept;
|
||||||
|
|
||||||
|
void set_continuous_mode(bool continuous_mode) { m_continuous_mode = continuous_mode; }
|
||||||
|
|
||||||
void on_init_thread() override;
|
void on_init_thread() override;
|
||||||
void on_exit() override;
|
void on_exit() override;
|
||||||
|
|
||||||
|
|
|
@ -114,6 +114,7 @@ namespace rsx
|
||||||
|
|
||||||
Emu.CallFromMainThread([]()
|
Emu.CallFromMainThread([]()
|
||||||
{
|
{
|
||||||
|
Emu.SetContinuousMode(true);
|
||||||
Emu.Restart(false);
|
Emu.Restart(false);
|
||||||
});
|
});
|
||||||
return page_navigation::exit;
|
return page_navigation::exit;
|
||||||
|
|
|
@ -26,6 +26,7 @@ namespace rsx
|
||||||
if (!suspend_mode)
|
if (!suspend_mode)
|
||||||
{
|
{
|
||||||
Emu.after_kill_callback = []() { Emu.Restart(); };
|
Emu.after_kill_callback = []() { Emu.Restart(); };
|
||||||
|
Emu.SetContinuousMode(true);
|
||||||
}
|
}
|
||||||
Emu.Kill(false, true);
|
Emu.Kill(false, true);
|
||||||
});
|
});
|
||||||
|
|
|
@ -60,6 +60,8 @@
|
||||||
#include "Emu/RSX/VK/VulkanAPI.h"
|
#include "Emu/RSX/VK/VulkanAPI.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "Emu/RSX/GSRender.h"
|
||||||
|
|
||||||
LOG_CHANNEL(sys_log, "SYS");
|
LOG_CHANNEL(sys_log, "SYS");
|
||||||
|
|
||||||
// Preallocate 32 MiB
|
// Preallocate 32 MiB
|
||||||
|
@ -1005,6 +1007,16 @@ void Emulator::SetForceBoot(bool force_boot)
|
||||||
m_force_boot = force_boot;
|
m_force_boot = force_boot;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Emulator::SetContinuousMode(bool continuous_mode)
|
||||||
|
{
|
||||||
|
m_continuous_mode = continuous_mode;
|
||||||
|
|
||||||
|
if (GSRender* render = static_cast<GSRender*>(g_fxo->try_get<rsx::thread>()))
|
||||||
|
{
|
||||||
|
render->set_continuous_mode(continuous_mode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
game_boot_result Emulator::Load(const std::string& title_id, bool is_disc_patch, usz recursion_count)
|
game_boot_result Emulator::Load(const std::string& title_id, bool is_disc_patch, usz recursion_count)
|
||||||
{
|
{
|
||||||
if (recursion_count == 0 && m_restrict_emu_state_change)
|
if (recursion_count == 0 && m_restrict_emu_state_change)
|
||||||
|
@ -2897,6 +2909,9 @@ void qt_events_aware_op(int repeat_duration_ms, std::function<bool()> wrapped_op
|
||||||
|
|
||||||
void Emulator::GracefulShutdown(bool allow_autoexit, bool async_op, bool savestate)
|
void Emulator::GracefulShutdown(bool allow_autoexit, bool async_op, bool savestate)
|
||||||
{
|
{
|
||||||
|
// Make sure we close the game window
|
||||||
|
Emu.SetContinuousMode(false);
|
||||||
|
|
||||||
// Ensure no game has booted inbetween
|
// Ensure no game has booted inbetween
|
||||||
const auto guard = Emu.MakeEmulationStateGuard();
|
const auto guard = Emu.MakeEmulationStateGuard();
|
||||||
|
|
||||||
|
@ -3278,7 +3293,6 @@ void Emulator::Kill(bool allow_autoexit, bool savestate, savestate_stage* save_s
|
||||||
thread_ctrl::wait_for(5'000);
|
thread_ctrl::wait_for(5'000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
*closed_sucessfully = true;
|
*closed_sucessfully = true;
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
|
@ -154,6 +154,7 @@ class Emulator final
|
||||||
// 2. It signifies that we don't want to exit on Kill(), for example if we want to transition to another application.
|
// 2. It signifies that we don't want to exit on Kill(), for example if we want to transition to another application.
|
||||||
bool m_force_boot = false;
|
bool m_force_boot = false;
|
||||||
|
|
||||||
|
bool m_continuous_mode = false;
|
||||||
bool m_has_gui = true;
|
bool m_has_gui = true;
|
||||||
|
|
||||||
bool m_state_inspection_savestate = false;
|
bool m_state_inspection_savestate = false;
|
||||||
|
@ -346,6 +347,15 @@ public:
|
||||||
return m_config_mode == cfg_mode::continuous;
|
return m_config_mode == cfg_mode::continuous;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ContinuousModeEnabled(bool reset)
|
||||||
|
{
|
||||||
|
if (reset)
|
||||||
|
{
|
||||||
|
return std::exchange(m_continuous_mode, false);
|
||||||
|
}
|
||||||
|
return m_continuous_mode;
|
||||||
|
}
|
||||||
|
|
||||||
class emulation_state_guard_t
|
class emulation_state_guard_t
|
||||||
{
|
{
|
||||||
class Emulator* _this = nullptr;
|
class Emulator* _this = nullptr;
|
||||||
|
@ -385,6 +395,7 @@ public:
|
||||||
bool BootRsxCapture(const std::string& path);
|
bool BootRsxCapture(const std::string& path);
|
||||||
|
|
||||||
void SetForceBoot(bool force_boot);
|
void SetForceBoot(bool force_boot);
|
||||||
|
void SetContinuousMode(bool continuous_mode);
|
||||||
|
|
||||||
game_boot_result Load(const std::string& title_id = "", bool is_disc_patch = false, usz recursion_count = 0);
|
game_boot_result Load(const std::string& title_id = "", bool is_disc_patch = false, usz recursion_count = 0);
|
||||||
void Run(bool start_playtime);
|
void Run(bool start_playtime);
|
||||||
|
|
|
@ -133,7 +133,7 @@ EmuCallbacks main_application::CreateCallbacks()
|
||||||
basic_keyboard_handler* ret = g_fxo->init<KeyboardHandlerBase, basic_keyboard_handler>(Emu.DeserialManager());
|
basic_keyboard_handler* ret = g_fxo->init<KeyboardHandlerBase, basic_keyboard_handler>(Emu.DeserialManager());
|
||||||
ensure(ret);
|
ensure(ret);
|
||||||
ret->moveToThread(get_thread());
|
ret->moveToThread(get_thread());
|
||||||
ret->SetTargetWindow(m_game_window);
|
ret->SetTargetWindow(reinterpret_cast<QWindow*>(m_game_window));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -170,7 +170,7 @@ EmuCallbacks main_application::CreateCallbacks()
|
||||||
basic_mouse_handler* ret = g_fxo->init<MouseHandlerBase, basic_mouse_handler>(Emu.DeserialManager());
|
basic_mouse_handler* ret = g_fxo->init<MouseHandlerBase, basic_mouse_handler>(Emu.DeserialManager());
|
||||||
ensure(ret);
|
ensure(ret);
|
||||||
ret->moveToThread(get_thread());
|
ret->moveToThread(get_thread());
|
||||||
ret->SetTargetWindow(m_game_window);
|
ret->SetTargetWindow(reinterpret_cast<QWindow*>(m_game_window));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case mouse_handler::raw:
|
case mouse_handler::raw:
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <QWindow>
|
#include <QThread>
|
||||||
|
|
||||||
struct EmuCallbacks;
|
struct EmuCallbacks;
|
||||||
|
class gs_frame;
|
||||||
|
|
||||||
class main_application
|
class main_application
|
||||||
{
|
{
|
||||||
|
@ -25,5 +26,5 @@ protected:
|
||||||
EmuCallbacks CreateCallbacks();
|
EmuCallbacks CreateCallbacks();
|
||||||
|
|
||||||
std::string m_active_user;
|
std::string m_active_user;
|
||||||
QWindow* m_game_window = nullptr; // (Currently) only needed so that pad handlers have a valid target for event filtering.
|
gs_frame* m_game_window = nullptr;
|
||||||
};
|
};
|
||||||
|
|
|
@ -28,6 +28,11 @@ gl_gs_frame::gl_gs_frame(QScreen* screen, const QRect& geometry, const QIcon& ap
|
||||||
show();
|
show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void gl_gs_frame::reset()
|
||||||
|
{
|
||||||
|
m_primary_context = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
draw_context_t gl_gs_frame::make_context()
|
draw_context_t gl_gs_frame::make_context()
|
||||||
{
|
{
|
||||||
auto context = new GLContext();
|
auto context = new GLContext();
|
||||||
|
|
|
@ -20,6 +20,7 @@ private:
|
||||||
public:
|
public:
|
||||||
explicit gl_gs_frame(QScreen* screen, const QRect& geometry, const QIcon& appIcon, std::shared_ptr<gui_settings> gui_settings, bool force_fullscreen);
|
explicit gl_gs_frame(QScreen* screen, const QRect& geometry, const QIcon& appIcon, std::shared_ptr<gui_settings> gui_settings, bool force_fullscreen);
|
||||||
|
|
||||||
|
void reset() override;
|
||||||
draw_context_t make_context() override;
|
draw_context_t make_context() override;
|
||||||
void set_current(draw_context_t ctx) override;
|
void set_current(draw_context_t ctx) override;
|
||||||
void delete_context(draw_context_t ctx) override;
|
void delete_context(draw_context_t ctx) override;
|
||||||
|
|
|
@ -328,6 +328,7 @@ void gs_frame::handle_shortcut(gui::shortcuts::shortcut shortcut_key, const QKey
|
||||||
{
|
{
|
||||||
Emu.Restart();
|
Emu.Restart();
|
||||||
};
|
};
|
||||||
|
Emu.SetContinuousMode(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
Emu.Kill(false, true);
|
Emu.Kill(false, true);
|
||||||
|
@ -623,6 +624,10 @@ void gs_frame::close()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void gs_frame::reset()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
bool gs_frame::shown()
|
bool gs_frame::shown()
|
||||||
{
|
{
|
||||||
return QWindow::isVisible();
|
return QWindow::isVisible();
|
||||||
|
|
|
@ -80,6 +80,7 @@ protected:
|
||||||
void showEvent(QShowEvent *event) override;
|
void showEvent(QShowEvent *event) override;
|
||||||
|
|
||||||
void close() override;
|
void close() override;
|
||||||
|
void reset() override;
|
||||||
|
|
||||||
bool shown() override;
|
bool shown() override;
|
||||||
void hide() override;
|
void hide() override;
|
||||||
|
|
|
@ -348,6 +348,28 @@ void gui_application::InitializeConnects()
|
||||||
|
|
||||||
std::unique_ptr<gs_frame> gui_application::get_gs_frame()
|
std::unique_ptr<gs_frame> gui_application::get_gs_frame()
|
||||||
{
|
{
|
||||||
|
// Load AppIcon
|
||||||
|
const QIcon app_icon = m_main_window ? m_main_window->GetAppIcon() : gui::utils::get_app_icon_from_path(Emu.GetBoot(), Emu.GetTitleID());
|
||||||
|
|
||||||
|
if (m_game_window)
|
||||||
|
{
|
||||||
|
// Check if the continuous mode is enabled. We reset the mode after each use in order to ensure that it is only used when explicitly needed.
|
||||||
|
const bool continuous_mode_enabled = Emu.ContinuousModeEnabled(true);
|
||||||
|
|
||||||
|
if (Emu.IsChildProcess() || continuous_mode_enabled)
|
||||||
|
{
|
||||||
|
gui_log.notice("gui_application: Re-using old game window (IsChildProcess=%d, ContinuousModeEnabled=%d)", Emu.IsChildProcess(), continuous_mode_enabled);
|
||||||
|
|
||||||
|
if (!app_icon.isNull())
|
||||||
|
{
|
||||||
|
m_game_window->setIcon(app_icon);
|
||||||
|
}
|
||||||
|
return std::unique_ptr<gs_frame>(m_game_window);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gui_log.notice("gui_application: Creating new game window");
|
||||||
|
|
||||||
extern const std::unordered_map<video_resolution, std::pair<int, int>, value_hash<video_resolution>> g_video_out_resolution_map;
|
extern const std::unordered_map<video_resolution, std::pair<int, int>, value_hash<video_resolution>> g_video_out_resolution_map;
|
||||||
|
|
||||||
auto [w, h] = ::at32(g_video_out_resolution_map, g_cfg.video.resolution);
|
auto [w, h] = ::at32(g_video_out_resolution_map, g_cfg.video.resolution);
|
||||||
|
@ -424,9 +446,6 @@ std::unique_ptr<gs_frame> gui_application::get_gs_frame()
|
||||||
frame_geometry.setSize(QSize(w, h));
|
frame_geometry.setSize(QSize(w, h));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load AppIcon
|
|
||||||
const QIcon app_icon = m_main_window ? m_main_window->GetAppIcon() : gui::utils::get_app_icon_from_path(Emu.GetBoot(), Emu.GetTitleID());
|
|
||||||
|
|
||||||
gs_frame* frame = nullptr;
|
gs_frame* frame = nullptr;
|
||||||
|
|
||||||
switch (g_cfg.video.renderer.get())
|
switch (g_cfg.video.renderer.get())
|
||||||
|
@ -446,6 +465,12 @@ std::unique_ptr<gs_frame> gui_application::get_gs_frame()
|
||||||
|
|
||||||
m_game_window = frame;
|
m_game_window = frame;
|
||||||
|
|
||||||
|
connect(m_game_window, &gs_frame::destroyed, this, [this]()
|
||||||
|
{
|
||||||
|
gui_log.notice("gui_application: Deleting old game window");
|
||||||
|
m_game_window = nullptr;
|
||||||
|
});
|
||||||
|
|
||||||
return std::unique_ptr<gs_frame>(frame);
|
return std::unique_ptr<gs_frame>(frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -582,10 +607,10 @@ void gui_application::InitializeCallbacks()
|
||||||
{
|
{
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case 0: static_cast<gs_frame*>(m_game_window)->progress_reset(value); break;
|
case 0: m_game_window->progress_reset(value); break;
|
||||||
case 1: static_cast<gs_frame*>(m_game_window)->progress_increment(value); break;
|
case 1: m_game_window->progress_increment(value); break;
|
||||||
case 2: static_cast<gs_frame*>(m_game_window)->progress_set_limit(value); break;
|
case 2: m_game_window->progress_set_limit(value); break;
|
||||||
case 3: static_cast<gs_frame*>(m_game_window)->progress_set_value(value); break;
|
case 3: m_game_window->progress_set_value(value); break;
|
||||||
default: gui_log.fatal("Unknown type in handle_taskbar_progress(type=%d, value=%d)", type, value); break;
|
default: gui_log.fatal("Unknown type in handle_taskbar_progress(type=%d, value=%d)", type, value); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1045,7 +1070,7 @@ void gui_application::OnShortcutChange()
|
||||||
{
|
{
|
||||||
if (m_game_window)
|
if (m_game_window)
|
||||||
{
|
{
|
||||||
static_cast<gs_frame*>(m_game_window)->update_shortcuts();
|
m_game_window->update_shortcuts();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1074,7 +1099,7 @@ void gui_application::OnAppStateChanged(Qt::ApplicationState state)
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto emu_state = Emu.GetStatus();
|
const auto emu_state = Emu.GetStatus();
|
||||||
const bool is_active = state == Qt::ApplicationActive;
|
const bool is_active = state & Qt::ApplicationActive;
|
||||||
|
|
||||||
if (emu_state != system_state::paused && emu_state != system_state::running)
|
if (emu_state != system_state::paused && emu_state != system_state::running)
|
||||||
{
|
{
|
||||||
|
|
|
@ -2590,6 +2590,7 @@ void main_window::CreateConnects()
|
||||||
{
|
{
|
||||||
Emu.Restart();
|
Emu.Restart();
|
||||||
};
|
};
|
||||||
|
Emu.SetContinuousMode(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
Emu.Kill(false, true);
|
Emu.Kill(false, true);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue