diff --git a/README.md b/README.md index a41d8f2b..fa177f43 100644 --- a/README.md +++ b/README.md @@ -425,6 +425,7 @@ Parameters that are enabled by default have to be explicitly disabled. These (cu | `width=`
`height=` | Customizeable HUD dimensions (in pixels) | | `wine_color` | Change color of the wine/proton text | | `wine` | Show current Wine or Proton version in use | +| `winesync` | Show wine sync method in use | Example: `MANGOHUD_CONFIG=cpu_temp,gpu_temp,position=top-right,height=500,font_size=32` Because comma is also used as option delimiter and needs to be escaped for values with a backslash, you can use `+` like `MANGOHUD_CONFIG=fps_limit=60+30+0` instead. diff --git a/data/MangoHud.conf b/data/MangoHud.conf index 490a1945..c081332e 100644 --- a/data/MangoHud.conf +++ b/data/MangoHud.conf @@ -151,6 +151,7 @@ throttling_status # vulkan_driver # wine # exec_name +# winesync ### Display loaded MangoHud architecture # arch diff --git a/src/hud_elements.cpp b/src/hud_elements.cpp index 11c4d2ff..0be2bab2 100644 --- a/src/hud_elements.cpp +++ b/src/hud_elements.cpp @@ -1414,6 +1414,18 @@ void HudElements::refresh_rate() { } } +void HudElements::winesync() { + if (!HUDElements.winesync_ptr) + HUDElements.winesync_ptr = std::make_unique(); + + if (HUDElements.winesync_ptr->valid()) { + ImguiNextColumnFirstItem(); + HUDElements.TextColored(HUDElements.colors.engine, "%s", "WSYNC"); + ImguiNextColumnOrNewRow(); + right_aligned_text(HUDElements.colors.text, HUDElements.ralign_width, "%s", HUDElements.winesync_ptr->get_method().c_str()); + } +} + void HudElements::sort_elements(const std::pair& option) { const auto& param = option.first; const auto& value = option.second; @@ -1458,7 +1470,8 @@ void HudElements::sort_elements(const std::pair& optio {"graphs", {graphs}}, {"fps_metrics", {fps_metrics}}, {"hdr", {hdr}}, - {"refresh_rate", {refresh_rate}} + {"refresh_rate", {refresh_rate}}, + {"winesync", {winesync}} }; auto check_param = display_params.find(param); @@ -1579,6 +1592,8 @@ void HudElements::legacy_elements(){ ordered_functions.push_back({exec_name, "exec_name", value}); if (params->enabled[OVERLAY_PARAM_ENABLED_duration]) ordered_functions.push_back({duration, "duration", value}); + if (params->enabled[OVERLAY_PARAM_ENABLED_winesync]) + ordered_functions.push_back({winesync, "winesync", value}); } void HudElements::update_exec(){ diff --git a/src/hud_elements.h b/src/hud_elements.h index e2338277..69cc8383 100644 --- a/src/hud_elements.h +++ b/src/hud_elements.h @@ -5,6 +5,7 @@ #include #include "timing.hpp" #include +#include "winesync.h" struct Function { std::function run; // Using std::function instead of a raw function pointer for more flexibility @@ -46,6 +47,7 @@ class HudElements{ uint32_t vendorID; int hdr_status = 0; int refresh = 0; + std::unique_ptr winesync_ptr = nullptr; void sort_elements(const std::pair& option); void legacy_elements(); @@ -89,6 +91,7 @@ class HudElements{ static void fps_metrics(); static void hdr(); static void refresh_rate(); + static void winesync(); void convert_colors(const struct overlay_params& params); void convert_colors(bool do_conv, const struct overlay_params& params); diff --git a/src/overlay_params.h b/src/overlay_params.h index 26ecb947..3a301117 100644 --- a/src/overlay_params.h +++ b/src/overlay_params.h @@ -109,6 +109,7 @@ typedef unsigned long KeySym; OVERLAY_PARAM_BOOL(hdr) \ OVERLAY_PARAM_BOOL(refresh_rate) \ OVERLAY_PARAM_BOOL(frame_timing_detailed) \ + OVERLAY_PARAM_BOOL(winesync) \ OVERLAY_PARAM_CUSTOM(fps_sampling_period) \ OVERLAY_PARAM_CUSTOM(output_folder) \ OVERLAY_PARAM_CUSTOM(output_file) \ diff --git a/src/winesync.h b/src/winesync.h new file mode 100644 index 00000000..9feca6bc --- /dev/null +++ b/src/winesync.h @@ -0,0 +1,81 @@ +#include "file_utils.h" +#include +#include + +namespace fs = ghc::filesystem; + +class WineSync { + private: + enum syncMethods { + NONE, + WINESERVER, + ESYNC, + FSYNC, + NTSYNC + }; + + int method = 0; + bool inside_wine = true; + + const char* methods[5] = { + "NONE", + "Wserver", + "Esync", + "Fsync", + "NTsync" + }; + + public: + WineSync() { +#ifdef __linux__ + // check that's were inside wine + std::string wineProcess = get_exe_path(); + auto n = wineProcess.find_last_of('/'); + std::string preloader = wineProcess.substr(n + 1); + if (preloader != "wine-preloader" && preloader != "wine64-preloader"){ + inside_wine = false; + return; + } + + const char* paths[2] { + "/proc/self/map_files", + "/proc/self/fd" + }; + + // check which sync wine is using, if any. + fs::path path; + for (size_t i = 0; i < sizeof(paths) / sizeof(paths[0]); i++) { + path = paths[i]; + for (auto& p : fs::directory_iterator(path)) { + auto filename = p.path().string().c_str(); + auto sym = read_symlink(filename); + if (sym.find("winesync") != std::string::npos) + method = syncMethods::NTSYNC; + else if (sym.find("fsync") != std::string::npos) + method = syncMethods::FSYNC; + else if (sym.find("ntsync") != std::string::npos) + method = syncMethods::NTSYNC; + else if (sym.find("esync") != std::string::npos) + method = syncMethods::ESYNC; + + if (method) + break; + + } + if (method) + break; + } +#endif + }; + + bool valid() { + return inside_wine; + } + + // return sync method as display name + std::string get_method() { + return methods[method]; + } +}; + +extern std::unique_ptr winesync_ptr; \ No newline at end of file