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