diff options
| author | crueter <crueter@eden-emu.dev> | 2026-05-20 04:49:16 +0200 |
|---|---|---|
| committer | crueter <crueter@eden-emu.dev> | 2026-05-20 04:49:16 +0200 |
| commit | feb8c5f88eae046c1b76f46e4fa103a844fb0f23 (patch) | |
| tree | 70f71937a8930c1a5b562f69047e35491d6156b4 /src/qt_common/qt_common.cpp | |
| parent | 300a646a34b6729879e3fb71d53e625a09683bb2 (diff) | |
[desktop] More qt_common reorganization (#3916)
Ported from QML branch.
Main "big" change is that EmuThread is now a shared state in QtCommon,
not individually managed/passed around by GRenderWindow and MainWindow.
Signed-off-by: crueter <crueter@eden-emu.dev>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3916
Reviewed-by: Lizzie <lizzie@eden-emu.dev>
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Diffstat (limited to 'src/qt_common/qt_common.cpp')
| -rw-r--r-- | src/qt_common/qt_common.cpp | 216 |
1 files changed, 180 insertions, 36 deletions
diff --git a/src/qt_common/qt_common.cpp b/src/qt_common/qt_common.cpp index 3091171df8..0a134d5047 100644 --- a/src/qt_common/qt_common.cpp +++ b/src/qt_common/qt_common.cpp @@ -1,25 +1,52 @@ // SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later -#include "common/fs/fs.h" +#include "common/literals.h" + +#include "common/memory_detect.h" +#include "core/hle/service/filesystem/filesystem.h" +#include "hid_core/hid_core.h" +#include "network/network.h" #include "qt_common.h" +#include "common/fs/fs.h" +#include "common/fs/path_util.h" +#include "common/logging.h" +#include "common/scm_rev.h" +#include "core/memory.h" + +#ifdef ARCHITECTURE_x86_64 +#include "common/x64/cpu_detect.h" +#endif + #include <QGuiApplication> #include <QStringLiteral> -#include "common/logging.h" #include "core/frontend/emu_window.h" +#include "qt_common/util/meta.h" #include <QFile> +#include <QMessageBox> + +#include <thread> #include <JlCompress.h> #if !defined(WIN32) && !defined(__APPLE__) #include <qpa/qplatformnativeinterface.h> #elif defined(__APPLE__) #include <objc/message.h> -#include <objc/runtime.h> #endif +#ifdef _WIN32 +#include <QApplication> +#include <QSettings> +#include <windows.h> +#include "common/windows/timer_resolution.h" +#include "core/core_timing.h" +#endif + +using namespace Common::Literals; + namespace QtCommon { QWidget* rootObject = nullptr; @@ -27,6 +54,11 @@ QWidget* rootObject = nullptr; std::unique_ptr<Core::System> system = nullptr; std::shared_ptr<FileSys::RealVfsFilesystem> vfs = nullptr; std::unique_ptr<FileSys::ManualContentProvider> provider = nullptr; +std::unique_ptr<EmuThread> emu_thread = nullptr; + +const QStringList supported_file_extensions = {QStringLiteral("nro"), QStringLiteral("nso"), + QStringLiteral("nca"), QStringLiteral("xci"), + QStringLiteral("nsp"), QStringLiteral("kip")}; Core::Frontend::WindowSystemType GetWindowSystemType() { // Determine WSI type based on Qt platform. @@ -58,37 +90,8 @@ Core::Frontend::EmuWindow::WindowSystemInfo GetWindowSystemInfo(QWindow* window) // Our Win32 Qt external doesn't have the private API. wsi.render_surface = reinterpret_cast<void*>(window->winId()); #elif defined(__APPLE__) - id layer = reinterpret_cast<id (*)(id, SEL)>(objc_msgSend)( + wsi.render_surface = reinterpret_cast<void* (*)(id, SEL)>(objc_msgSend)( reinterpret_cast<id>(window->winId()), sel_registerName("layer")); - - // In Qt 6, the layer of the NSView might be a QContainerLayer. - // MoltenVK needs a CAMetalLayer. We search for it in sublayers. - Class metal_layer_class = objc_getClass("CAMetalLayer"); - id metal_layer = nullptr; - - if (layer) { - if (reinterpret_cast<bool (*)(id, SEL, Class)>(objc_msgSend)( - layer, sel_registerName("isKindOfClass:"), metal_layer_class)) { - metal_layer = layer; - } else { - id sublayers = reinterpret_cast<id (*)(id, SEL)>(objc_msgSend)( - layer, sel_registerName("sublayers")); - if (sublayers) { - unsigned long count = reinterpret_cast<unsigned long (*)(id, SEL)>(objc_msgSend)( - sublayers, sel_registerName("count")); - for (unsigned long i = 0; i < count; ++i) { - id sublayer = reinterpret_cast<id (*)(id, SEL, unsigned long)>(objc_msgSend)( - sublayers, sel_registerName("objectAtIndex:"), i); - if (reinterpret_cast<bool (*)(id, SEL, Class)>(objc_msgSend)( - sublayer, sel_registerName("isKindOfClass:"), metal_layer_class)) { - metal_layer = sublayer; - break; - } - } - } - } - } - wsi.render_surface = reinterpret_cast<void*>(metal_layer ? metal_layer : layer); #else QPlatformNativeInterface* pni = QGuiApplication::platformNativeInterface(); wsi.display_connection = pni->nativeResourceForWindow("display", window); @@ -103,18 +106,148 @@ Core::Frontend::EmuWindow::WindowSystemInfo GetWindowSystemInfo(QWindow* window) } const QString tr(const char* str) { - return QGuiApplication::tr(str); + return rootObject->tr(str); } const QString tr(const std::string& str) { - return QGuiApplication::tr(str.c_str()); + return rootObject->tr(str.c_str()); +} + +static void LogRuntimes() { +#ifdef _MSC_VER + // It is possible that the name of the dll will change. + // vcruntime140.dll is for 2015 and onwards + static constexpr char runtime_dll_name[] = "vcruntime140.dll"; + UINT sz = GetFileVersionInfoSizeA(runtime_dll_name, nullptr); + bool runtime_version_inspection_worked = false; + if (sz > 0) { + std::vector<u8> buf(sz); + if (GetFileVersionInfoA(runtime_dll_name, 0, sz, buf.data())) { + VS_FIXEDFILEINFO* pvi; + sz = sizeof(VS_FIXEDFILEINFO); + if (VerQueryValueA(buf.data(), "\\", reinterpret_cast<LPVOID*>(&pvi), &sz)) { + if (pvi->dwSignature == VS_FFI_SIGNATURE) { + runtime_version_inspection_worked = true; + LOG_INFO(Frontend, "MSVC Compiler: {} Runtime: {}.{}.{}.{}", _MSC_VER, + pvi->dwProductVersionMS >> 16, pvi->dwProductVersionMS & 0xFFFF, + pvi->dwProductVersionLS >> 16, pvi->dwProductVersionLS & 0xFFFF); + } + } + } + } + if (!runtime_version_inspection_worked) { + LOG_INFO(Frontend, "Unable to inspect {}", runtime_dll_name); + } +#endif + LOG_INFO(Frontend, "Qt Compile: {} Runtime: {}", QT_VERSION_STR, qVersion()); +} + +static QString PrettyProductName() { +#ifdef _WIN32 + // After Windows 10 Version 2004, Microsoft decided to switch to a different notation: 20H2 + // With that notation change they changed the registry key used to denote the current version + QSettings windows_registry( + QStringLiteral("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"), + QSettings::NativeFormat); + const QString release_id = windows_registry.value(QStringLiteral("ReleaseId")).toString(); + if (release_id == QStringLiteral("2009")) { + const u32 current_build = windows_registry.value(QStringLiteral("CurrentBuild")).toUInt(); + const QString display_version = + windows_registry.value(QStringLiteral("DisplayVersion")).toString(); + const u32 ubr = windows_registry.value(QStringLiteral("UBR")).toUInt(); + u32 version = 10; + if (current_build >= 22000) { + version = 11; + } + return QStringLiteral("Windows %1 Version %2 (Build %3.%4)") + .arg(QString::number(version), display_version, QString::number(current_build), + QString::number(ubr)); + } +#endif + return QSysInfo::prettyProductName(); +} + +static void RemoveCachedContents() { + const auto cache_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::CacheDir); + const auto offline_fonts = cache_dir / "fonts"; + const auto offline_manual = cache_dir / "offline_web_applet_manual"; + const auto offline_legal_information = cache_dir / "offline_web_applet_legal_information"; + const auto offline_system_data = cache_dir / "offline_web_applet_system_data"; + + Common::FS::RemoveDirRecursively(offline_fonts); + Common::FS::RemoveDirRecursively(offline_manual); + Common::FS::RemoveDirRecursively(offline_legal_information); + Common::FS::RemoveDirRecursively(offline_system_data); } void Init(QWidget* root) { - system = std::make_unique<Core::System>(); rootObject = root; + + system = std::make_unique<Core::System>(); vfs = std::make_unique<FileSys::RealVfsFilesystem>(); provider = std::make_unique<FileSys::ManualContentProvider>(); + + // initialization stuff + Common::FS::CreateEdenPaths(); + + system->Initialize(); + + Common::Log::Initialize(); + Common::Log::Start(); + + Network::Init(); + + QtCommon::Meta::RegisterMetaTypes(); + + // build version + const auto branch_name = std::string(Common::g_scm_branch); + const auto description = std::string(Common::g_scm_desc); + const auto build_id = std::string(Common::g_build_id); + + const auto yuzu_build = fmt::format("Eden Development Build | {}-{}", branch_name, description); + const auto override_build = + fmt::format(fmt::runtime(std::string(Common::g_title_bar_format_idle)), build_id); + const auto yuzu_build_version = override_build.empty() ? yuzu_build : override_build; + const auto processor_count = std::thread::hardware_concurrency(); + + // info logging + LOG_INFO(Frontend, "Eden Version: {}", yuzu_build_version); + LogRuntimes(); +#ifdef ARCHITECTURE_x86_64 + const auto& caps = Common::GetCPUCaps(); + std::string cpu_string = caps.cpu_string; + if (caps.avx || caps.avx2 || caps.avx512f) { + cpu_string += " | AVX"; + if (caps.avx512f) { + cpu_string += "512"; + } else if (caps.avx2) { + cpu_string += '2'; + } + if (caps.fma || caps.fma4) { + cpu_string += " | FMA"; + } + } + LOG_INFO(Frontend, "Host CPU: {}", cpu_string); + if (std::optional<int> processor_core = Common::GetProcessorCount()) { + LOG_INFO(Frontend, "Host CPU Cores: {}", *processor_core); + } +#endif + LOG_INFO(Frontend, "Host CPU Threads: {}", processor_count); + LOG_INFO(Frontend, "Host OS: {}", PrettyProductName().toStdString()); + LOG_INFO(Frontend, "Host RAM: {:.2f} GiB", + Common::GetMemInfo().TotalPhysicalMemory / f64{1_GiB}); + LOG_INFO(Frontend, "Host Swap: {:.2f} GiB", Common::GetMemInfo().TotalSwapMemory / f64{1_GiB}); +#ifdef _WIN32 + LOG_INFO(Frontend, "Host Timer Resolution: {:.4f} ms", + std::chrono::duration_cast<std::chrono::duration<f64, std::milli>>( + Common::Windows::SetCurrentTimerResolutionToMaximum()) + .count()); + QtCommon::system->CoreTiming().SetTimerResolutionNs( + Common::Windows::GetCurrentTimerResolution()); +#endif + + // Remove cached contents generated during the previous session + RemoveCachedContents(); } std::filesystem::path GetEdenCommand() { @@ -137,4 +270,15 @@ std::filesystem::path GetEdenCommand() { return command; } +void SetupContentProviders() { + system->SetContentProvider(std::make_unique<FileSys::ContentProviderUnion>()); + system->RegisterContentProvider(FileSys::ContentProviderUnionSlot::FrontendManual, + provider.get()); + system->GetFileSystemController().CreateFactories(*vfs); +} + +void SetupHID() { + system->HIDCore().ReloadInputDevices(); +} + } // namespace QtCommon |
