mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-08-04 08:22:32 +00:00
Devtools: Pause system
This commit is contained in:
parent
009f956d8d
commit
983cafb5f2
@ -458,6 +458,8 @@ set(CORE src/core/aerolib/stubs.cpp
|
|||||||
src/core/platform.h
|
src/core/platform.h
|
||||||
src/core/signals.cpp
|
src/core/signals.cpp
|
||||||
src/core/signals.h
|
src/core/signals.h
|
||||||
|
src/core/system.cpp
|
||||||
|
src/core/system.h
|
||||||
src/core/tls.cpp
|
src/core/tls.cpp
|
||||||
src/core/tls.h
|
src/core/tls.h
|
||||||
src/core/virtual_memory.cpp
|
src/core/virtual_memory.cpp
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
#include "core/libraries/kernel/threads/threads.h"
|
#include "core/libraries/kernel/threads/threads.h"
|
||||||
#include "core/libraries/libs.h"
|
#include "core/libraries/libs.h"
|
||||||
#include "core/linker.h"
|
#include "core/linker.h"
|
||||||
|
#include "core/system.h"
|
||||||
#include "core/tls.h"
|
#include "core/tls.h"
|
||||||
#ifdef _WIN64
|
#ifdef _WIN64
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
@ -988,6 +989,7 @@ static void cleanup_thread(void* arg) {
|
|||||||
}
|
}
|
||||||
Core::SetTcbBase(nullptr);
|
Core::SetTcbBase(nullptr);
|
||||||
thread->is_almost_done = true;
|
thread->is_almost_done = true;
|
||||||
|
Common::Singleton<SystemState>::Instance()->RemoveCurrentThreadFromGuestList();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void* run_thread(void* arg) {
|
static void* run_thread(void* arg) {
|
||||||
@ -998,6 +1000,7 @@ static void* run_thread(void* arg) {
|
|||||||
g_pthread_self = thread;
|
g_pthread_self = thread;
|
||||||
pthread_cleanup_push(cleanup_thread, thread);
|
pthread_cleanup_push(cleanup_thread, thread);
|
||||||
thread->is_started = true;
|
thread->is_started = true;
|
||||||
|
Common::Singleton<SystemState>::Instance()->AddCurrentThreadToGuestList();
|
||||||
ret = linker->ExecuteGuest(thread->entry, thread->arg);
|
ret = linker->ExecuteGuest(thread->entry, thread->arg);
|
||||||
pthread_cleanup_pop(1);
|
pthread_cleanup_pop(1);
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -247,6 +247,17 @@ int PS4_SYSV_ABI sceKernelConvertLocaltimeToUtc(time_t param_1, int64_t param_2,
|
|||||||
return SCE_OK;
|
return SCE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace Dev {
|
||||||
|
u64& GetInitialPtc() {
|
||||||
|
return initial_ptc;
|
||||||
|
}
|
||||||
|
|
||||||
|
Common::NativeClock* GetClock() {
|
||||||
|
return clock.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Dev
|
||||||
|
|
||||||
void timeSymbolsRegister(Core::Loader::SymbolsResolver* sym) {
|
void timeSymbolsRegister(Core::Loader::SymbolsResolver* sym) {
|
||||||
clock = std::make_unique<Common::NativeClock>();
|
clock = std::make_unique<Common::NativeClock>();
|
||||||
initial_ptc = clock->GetUptime();
|
initial_ptc = clock->GetUptime();
|
||||||
|
@ -7,6 +7,10 @@
|
|||||||
|
|
||||||
#include "common/types.h"
|
#include "common/types.h"
|
||||||
|
|
||||||
|
namespace Common {
|
||||||
|
class NativeClock;
|
||||||
|
}
|
||||||
|
|
||||||
namespace Core::Loader {
|
namespace Core::Loader {
|
||||||
class SymbolsResolver;
|
class SymbolsResolver;
|
||||||
}
|
}
|
||||||
@ -47,6 +51,12 @@ constexpr int ORBIS_CLOCK_EXT_DEBUG_NETWORK = 17;
|
|||||||
constexpr int ORBIS_CLOCK_EXT_AD_NETWORK = 18;
|
constexpr int ORBIS_CLOCK_EXT_AD_NETWORK = 18;
|
||||||
constexpr int ORBIS_CLOCK_EXT_RAW_NETWORK = 19;
|
constexpr int ORBIS_CLOCK_EXT_RAW_NETWORK = 19;
|
||||||
|
|
||||||
|
namespace Dev {
|
||||||
|
u64& GetInitialPtc();
|
||||||
|
|
||||||
|
Common::NativeClock* GetClock();
|
||||||
|
} // namespace Dev
|
||||||
|
|
||||||
u64 PS4_SYSV_ABI sceKernelGetTscFrequency();
|
u64 PS4_SYSV_ABI sceKernelGetTscFrequency();
|
||||||
u64 PS4_SYSV_ABI sceKernelGetProcessTime();
|
u64 PS4_SYSV_ABI sceKernelGetProcessTime();
|
||||||
u64 PS4_SYSV_ABI sceKernelGetProcessTimeCounter();
|
u64 PS4_SYSV_ABI sceKernelGetProcessTimeCounter();
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
#include <imgui.h>
|
#include <imgui.h>
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
@ -281,10 +282,15 @@ void MsgDialogUi::Draw() {
|
|||||||
first_render = false;
|
first_render = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
DialogResult Libraries::MsgDialog::ShowMsgDialog(MsgDialogState state, bool block) {
|
DialogResult Libraries::MsgDialog::ShowMsgDialog(MsgDialogState p_state, bool block) {
|
||||||
DialogResult result{};
|
static DialogResult result{};
|
||||||
Status status = Status::RUNNING;
|
static Status status;
|
||||||
MsgDialogUi dialog(&state, &status, &result);
|
static MsgDialogUi dialog;
|
||||||
|
static MsgDialogState state;
|
||||||
|
dialog = MsgDialogUi{};
|
||||||
|
status = Status::RUNNING;
|
||||||
|
state = std::move(p_state);
|
||||||
|
dialog = MsgDialogUi(&state, &status, &result);
|
||||||
if (block) {
|
if (block) {
|
||||||
while (status == Status::RUNNING) {
|
while (status == Status::RUNNING) {
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#include "core/libraries/kernel/time_management.h"
|
#include "core/libraries/kernel/time_management.h"
|
||||||
#include "core/libraries/videoout/driver.h"
|
#include "core/libraries/videoout/driver.h"
|
||||||
#include "core/platform.h"
|
#include "core/platform.h"
|
||||||
|
#include "core/system.h"
|
||||||
#include "video_core/renderer_vulkan/renderer_vulkan.h"
|
#include "video_core/renderer_vulkan/renderer_vulkan.h"
|
||||||
|
|
||||||
extern std::unique_ptr<Vulkan::RendererVulkan> renderer;
|
extern std::unique_ptr<Vulkan::RendererVulkan> renderer;
|
||||||
@ -265,6 +266,8 @@ void VideoOutDriver::PresentThread(std::stop_token token) {
|
|||||||
|
|
||||||
Common::AccurateTimer timer{vblank_period};
|
Common::AccurateTimer timer{vblank_period};
|
||||||
|
|
||||||
|
auto systemState = Common::Singleton<SystemState>::Instance();
|
||||||
|
|
||||||
const auto receive_request = [this] -> Request {
|
const auto receive_request = [this] -> Request {
|
||||||
std::scoped_lock lk{mutex};
|
std::scoped_lock lk{mutex};
|
||||||
if (!requests.empty()) {
|
if (!requests.empty()) {
|
||||||
@ -284,7 +287,7 @@ void VideoOutDriver::PresentThread(std::stop_token token) {
|
|||||||
if (vblank_status.count % (main_port.flip_rate + 1) == 0) {
|
if (vblank_status.count % (main_port.flip_rate + 1) == 0) {
|
||||||
const auto request = receive_request();
|
const auto request = receive_request();
|
||||||
if (!request) {
|
if (!request) {
|
||||||
if (!main_port.is_open) {
|
if (!main_port.is_open || systemState->IsGuestThreadsPaused()) {
|
||||||
DrawBlankFrame();
|
DrawBlankFrame();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
#include "core/memory.h"
|
#include "core/memory.h"
|
||||||
#include "core/tls.h"
|
#include "core/tls.h"
|
||||||
#include "core/virtual_memory.h"
|
#include "core/virtual_memory.h"
|
||||||
|
#include "system.h"
|
||||||
|
|
||||||
namespace Core {
|
namespace Core {
|
||||||
|
|
||||||
@ -88,6 +89,7 @@ void Linker::Execute() {
|
|||||||
|
|
||||||
// Init primary thread.
|
// Init primary thread.
|
||||||
Common::SetCurrentThreadName("GAME_MainThread");
|
Common::SetCurrentThreadName("GAME_MainThread");
|
||||||
|
Common::Singleton<SystemState>::Instance()->AddCurrentThreadToGuestList();
|
||||||
Libraries::Kernel::pthreadInitSelfMainThread();
|
Libraries::Kernel::pthreadInitSelfMainThread();
|
||||||
EnsureThreadInitialized(true);
|
EnsureThreadInitialized(true);
|
||||||
|
|
||||||
|
@ -83,6 +83,12 @@ static void SignalHandler(int sig, siginfo_t* info, void* raw_context) {
|
|||||||
fmt::ptr(code_address), DisassembleInstruction(code_address));
|
fmt::ptr(code_address), DisassembleInstruction(code_address));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case SIGUSR1: { // Sleep thread until signal is received
|
||||||
|
sigset_t sigset;
|
||||||
|
sigemptyset(&sigset);
|
||||||
|
sigaddset(&sigset, SIGUSR1);
|
||||||
|
sigwait(&sigset, &sig);
|
||||||
|
} break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -105,6 +111,8 @@ SignalDispatch::SignalDispatch() {
|
|||||||
"Failed to register access violation signal handler.");
|
"Failed to register access violation signal handler.");
|
||||||
ASSERT_MSG(sigaction(SIGILL, &action, nullptr) == 0,
|
ASSERT_MSG(sigaction(SIGILL, &action, nullptr) == 0,
|
||||||
"Failed to register illegal instruction signal handler.");
|
"Failed to register illegal instruction signal handler.");
|
||||||
|
ASSERT_MSG(sigaction(SIGUSR1, &action, nullptr) == 0,
|
||||||
|
"Failed to register sleep signal handler.");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
71
src/core/system.cpp
Normal file
71
src/core/system.cpp
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "common/assert.h"
|
||||||
|
#include "common/native_clock.h"
|
||||||
|
#include "libraries/kernel/event_queues.h"
|
||||||
|
#include "libraries/kernel/time_management.h"
|
||||||
|
#include "libraries/system/msgdialog.h"
|
||||||
|
#include "system.h"
|
||||||
|
|
||||||
|
void SystemState::AddCurrentThreadToGuestList() {
|
||||||
|
std::lock_guard lock{guest_threads_mutex};
|
||||||
|
ThreadID id;
|
||||||
|
#ifdef _WIN32
|
||||||
|
id = GetCurrentThreadId();
|
||||||
|
#else
|
||||||
|
id = pthread_self();
|
||||||
|
#endif
|
||||||
|
guest_threads.push_back(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemState::RemoveCurrentThreadFromGuestList() {
|
||||||
|
std::lock_guard lock{guest_threads_mutex};
|
||||||
|
ThreadID id;
|
||||||
|
#ifdef _WIN32
|
||||||
|
id = GetCurrentThreadId();
|
||||||
|
#else
|
||||||
|
id = pthread_self();
|
||||||
|
#endif
|
||||||
|
std::erase_if(guest_threads, [&](const ThreadID& v) { return v == id; });
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemState::PauseGuestThreads() {
|
||||||
|
using namespace Libraries::MsgDialog;
|
||||||
|
std::lock_guard lock{guest_threads_mutex};
|
||||||
|
if (is_guest_threads_paused) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& id : guest_threads) {
|
||||||
|
#ifdef _WIN32
|
||||||
|
const HANDLE hd = OpenThread(THREAD_SUSPEND_RESUME, FALSE, id);
|
||||||
|
SuspendThread(hd);
|
||||||
|
CloseHandle(hd);
|
||||||
|
#else
|
||||||
|
pthread_kill(id, SIGUSR1);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
pause_time = Libraries::Kernel::Dev::GetClock()->GetUptime();
|
||||||
|
is_guest_threads_paused = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemState::ResumeGuestThreads() {
|
||||||
|
std::lock_guard lock{guest_threads_mutex};
|
||||||
|
if (!is_guest_threads_paused) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 delta_time = Libraries::Kernel::Dev::GetClock()->GetUptime() - pause_time;
|
||||||
|
Libraries::Kernel::Dev::GetInitialPtc() += delta_time;
|
||||||
|
for (const auto& id : guest_threads) {
|
||||||
|
#ifdef _WIN32
|
||||||
|
const HANDLE hd = OpenThread(THREAD_SUSPEND_RESUME, FALSE, id);
|
||||||
|
ResumeThread(hd);
|
||||||
|
CloseHandle(hd);
|
||||||
|
#else
|
||||||
|
pthread_kill(id, SIGUSR1);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
is_guest_threads_paused = false;
|
||||||
|
}
|
39
src/core/system.h
Normal file
39
src/core/system.h
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <mutex>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#ifndef WIN32_LEAN_AND_MEAN
|
||||||
|
#define WIN32_LEAN_AND_MEAN 1
|
||||||
|
#endif
|
||||||
|
#include <Windows.h>
|
||||||
|
using ThreadID = DWORD;
|
||||||
|
#else
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <signal.h>
|
||||||
|
using ThreadID = pthread_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class SystemState {
|
||||||
|
std::mutex guest_threads_mutex{};
|
||||||
|
std::vector<ThreadID> guest_threads{};
|
||||||
|
bool is_guest_threads_paused = false;
|
||||||
|
u64 pause_time{};
|
||||||
|
|
||||||
|
public:
|
||||||
|
void AddCurrentThreadToGuestList();
|
||||||
|
|
||||||
|
void RemoveCurrentThreadFromGuestList();
|
||||||
|
|
||||||
|
void PauseGuestThreads();
|
||||||
|
|
||||||
|
void ResumeGuestThreads();
|
||||||
|
|
||||||
|
inline bool IsGuestThreadsPaused() const {
|
||||||
|
return is_guest_threads_paused;
|
||||||
|
}
|
||||||
|
};
|
@ -4,7 +4,9 @@
|
|||||||
#include <imgui.h>
|
#include <imgui.h>
|
||||||
|
|
||||||
#include "common/config.h"
|
#include "common/config.h"
|
||||||
|
#include "common/singleton.h"
|
||||||
#include "common/types.h"
|
#include "common/types.h"
|
||||||
|
#include "core/system.h"
|
||||||
#include "imgui_internal.h"
|
#include "imgui_internal.h"
|
||||||
#include "video_info.h"
|
#include "video_info.h"
|
||||||
|
|
||||||
@ -18,7 +20,11 @@ struct FrameInfo {
|
|||||||
static bool show = false;
|
static bool show = false;
|
||||||
static bool show_advanced = false;
|
static bool show_advanced = false;
|
||||||
|
|
||||||
|
static auto sysState = Common::Singleton<SystemState>::Instance();
|
||||||
static u32 current_frame = 0;
|
static u32 current_frame = 0;
|
||||||
|
|
||||||
|
namespace FrameGraph {
|
||||||
|
|
||||||
constexpr float TARGET_FPS = 60.0f;
|
constexpr float TARGET_FPS = 60.0f;
|
||||||
constexpr u32 FRAME_BUFFER_SIZE = 1024;
|
constexpr u32 FRAME_BUFFER_SIZE = 1024;
|
||||||
constexpr float BAR_WIDTH_MULT = 1.4f;
|
constexpr float BAR_WIDTH_MULT = 1.4f;
|
||||||
@ -27,22 +33,13 @@ constexpr float FRAME_GRAPH_PADDING_Y = 3.0f;
|
|||||||
static std::array<FrameInfo, FRAME_BUFFER_SIZE> frame_list;
|
static std::array<FrameInfo, FRAME_BUFFER_SIZE> frame_list;
|
||||||
static float frame_graph_height = 50.0f;
|
static float frame_graph_height = 50.0f;
|
||||||
|
|
||||||
static void DrawSimple() {
|
static void Draw() {
|
||||||
const auto io = GetIO();
|
const auto& ctx = *GImGui;
|
||||||
Text("FPS: %.1f (%.3f ms)", io.Framerate, 1000.0f / io.Framerate);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void DrawAdvanced() {
|
|
||||||
const auto& ctx = *GetCurrentContext();
|
|
||||||
const auto& io = ctx.IO;
|
|
||||||
const auto& window = *ctx.CurrentWindow;
|
const auto& window = *ctx.CurrentWindow;
|
||||||
auto& draw_list = *window.DrawList;
|
auto& draw_list = *window.DrawList;
|
||||||
|
|
||||||
Text("Frame time: %.3f ms (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate);
|
|
||||||
|
|
||||||
SeparatorText("Frame graph");
|
|
||||||
const float full_width = GetContentRegionAvail().x;
|
const float full_width = GetContentRegionAvail().x;
|
||||||
{ // Frame graph - inspired by
|
// Frame graph - inspired by
|
||||||
// https://asawicki.info/news_1758_an_idea_for_visualization_of_frame_times
|
// https://asawicki.info/news_1758_an_idea_for_visualization_of_frame_times
|
||||||
auto pos = GetCursorScreenPos();
|
auto pos = GetCursorScreenPos();
|
||||||
const ImVec2 size{full_width, frame_graph_height + FRAME_GRAPH_PADDING_Y * 2.0f};
|
const ImVec2 size{full_width, frame_graph_height + FRAME_GRAPH_PADDING_Y * 2.0f};
|
||||||
@ -80,8 +77,8 @@ static void DrawAdvanced() {
|
|||||||
int g = (int)(0xFF * t);
|
int g = (int)(0xFF * t);
|
||||||
color = IM_COL32(0xFF, g, 0, 0xFF);
|
color = IM_COL32(0xFF, g, 0, 0xFF);
|
||||||
}
|
}
|
||||||
draw_list.AddRectFilled({cur_pos_x - width, final_pos_y - height},
|
draw_list.AddRectFilled({cur_pos_x - width, final_pos_y - height}, {cur_pos_x, final_pos_y},
|
||||||
{cur_pos_x, final_pos_y}, color);
|
color);
|
||||||
cur_pos_x -= width;
|
cur_pos_x -= width;
|
||||||
if (cur_pos_x < width) {
|
if (cur_pos_x < width) {
|
||||||
break;
|
break;
|
||||||
@ -89,16 +86,58 @@ static void DrawAdvanced() {
|
|||||||
}
|
}
|
||||||
draw_list.PopClipRect();
|
draw_list.PopClipRect();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace FrameGraph
|
||||||
|
|
||||||
|
static void DrawSimple() {
|
||||||
|
const auto io = GetIO();
|
||||||
|
Text("FPS: %.1f (%.3f ms)", io.Framerate, 1000.0f / io.Framerate);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void DrawAdvanced() {
|
||||||
|
const auto& ctx = *GImGui;
|
||||||
|
const auto& io = ctx.IO;
|
||||||
|
const auto& window = *ctx.CurrentWindow;
|
||||||
|
auto& draw_list = *window.DrawList;
|
||||||
|
|
||||||
|
auto isSystemPaused = sysState->IsGuestThreadsPaused();
|
||||||
|
|
||||||
|
static float deltaTime;
|
||||||
|
static float frameRate;
|
||||||
|
|
||||||
|
if (!isSystemPaused) {
|
||||||
|
deltaTime = io.DeltaTime * 1000.0f;
|
||||||
|
frameRate = io.Framerate;
|
||||||
|
}
|
||||||
|
|
||||||
|
Text("Frame time: %.3f ms (%.1f FPS)", deltaTime, frameRate);
|
||||||
|
|
||||||
|
SeparatorText("Frame graph");
|
||||||
|
FrameGraph::Draw();
|
||||||
|
SeparatorText("System debug");
|
||||||
|
BeginDisabled(isSystemPaused);
|
||||||
|
if (Button("Pause")) {
|
||||||
|
sysState->PauseGuestThreads();
|
||||||
|
}
|
||||||
|
EndDisabled();
|
||||||
|
SameLine();
|
||||||
|
BeginDisabled(!isSystemPaused);
|
||||||
|
if (Button("Resume")) {
|
||||||
|
sysState->ResumeGuestThreads();
|
||||||
|
}
|
||||||
|
EndDisabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Layers::VideoInfo::Draw() {
|
void Layers::VideoInfo::Draw() {
|
||||||
const auto io = GetIO();
|
const auto io = GetIO();
|
||||||
|
|
||||||
|
if (!sysState->IsGuestThreadsPaused()) {
|
||||||
const FrameInfo frame_info{
|
const FrameInfo frame_info{
|
||||||
.num = ++current_frame,
|
.num = ++current_frame,
|
||||||
.delta = io.DeltaTime,
|
.delta = io.DeltaTime,
|
||||||
};
|
};
|
||||||
frame_list[current_frame % FRAME_BUFFER_SIZE] = frame_info;
|
FrameGraph::frame_list[current_frame % FrameGraph::FRAME_BUFFER_SIZE] = frame_info;
|
||||||
|
}
|
||||||
|
|
||||||
if (IsKeyPressed(ImGuiKey_F10, false)) {
|
if (IsKeyPressed(ImGuiKey_F10, false)) {
|
||||||
const bool changed_ctrl = io.KeyCtrl != show_advanced;
|
const bool changed_ctrl = io.KeyCtrl != show_advanced;
|
||||||
@ -108,11 +147,13 @@ void Layers::VideoInfo::Draw() {
|
|||||||
|
|
||||||
if (show) {
|
if (show) {
|
||||||
if (show_advanced) {
|
if (show_advanced) {
|
||||||
if (Begin("Video Debug Info", nullptr, ImGuiWindowFlags_NoDecoration)) {
|
if (Begin("Video Debug Info", &show, 0)) {
|
||||||
DrawAdvanced();
|
DrawAdvanced();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (Begin("Video Info", nullptr, ImGuiWindowFlags_NoDecoration)) {
|
if (Begin("Video Info", nullptr,
|
||||||
|
ImGuiWindowFlags_NoNav | ImGuiWindowFlags_NoDecoration |
|
||||||
|
ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||||
DrawSimple();
|
DrawSimple();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user