trying to patch yabridge

This commit is contained in:
Matt Nish-Lapidus 2025-06-20 15:55:34 -04:00
parent 80598a1ff1
commit 8f34589f02
5 changed files with 12 additions and 11 deletions

View file

@ -0,0 +1,41 @@
diff --git a/overlays/meson.build b/overlays/meson.build
index 12ecb97..a6e39ff 100644
--- a/overlays/meson.build
+++ b/overlays/meson.build
@@ -218,7 +218,7 @@ if is_64bit_system
xcb_64bit_dep = dependency('xcb')
endif
if with_bitbridge
- xcb_32bit_dep = winegcc.find_library('xcb')
+ xcb_32bit_dep = winegcc.find_library('xcb', dirs: ['@libxcb32@/lib'])
endif
# These are all headers-only libraries, and thus won't require separate 32-bit
diff --git a/src/common/notifications.cpp b/src/common/notifications.cpp
index 654b6c83..78ba2fe7 100644
--- a/src/common/notifications.cpp
+++ b/src/common/notifications.cpp
@@ -29,8 +29,8 @@
#include "process.h"
#include "utils.h"
-constexpr char libdbus_library_name[] = "libdbus-1.so.3";
-constexpr char libdbus_library_fallback_name[] = "libdbus-1.so";
+constexpr char libdbus_library_name[] = "@libdbus@/lib/libdbus-1.so.3";
+constexpr char libdbus_library_fallback_name[] = "@libdbus@/lib/libdbus-1.so";
std::atomic<void*> libdbus_handle = nullptr;
std::mutex libdbus_mutex;
diff --git a/src/plugin/utils.cpp b/src/plugin/utils.cpp
index 441345c6..f3e51cff 100644
--- a/src/plugin/utils.cpp
+++ b/src/plugin/utils.cpp
@@ -103,7 +103,7 @@ std::string PluginInfo::wine_version() const {
// The '*.exe' scripts generated by winegcc allow you to override the binary
// used to run Wine, so will will handle this in the same way for our Wine
// version detection. We'll be using `execvpe`
- std::string wine_path = "wine";
+ std::string wine_path = "@wine@/bin/wine";
// NOLINTNEXTLINE(concurrency-mt-unsafe)
if (const char* wineloader_path = getenv("WINELOADER");
wineloader_path && access(wineloader_path, X_OK) == 0) {

View file

@ -0,0 +1,71 @@
diff --git a/src/chainloader/utils.cpp b/src/chainloader/utils.cpp
index fa90b8f7..bd44d0ea 100644
--- a/src/chainloader/utils.cpp
+++ b/src/chainloader/utils.cpp
@@ -29,8 +29,10 @@
namespace fs = ghc::filesystem;
void* find_plugin_library(const std::string& name) {
+ Logger logger = Logger::create_exception_logger();
+
// Just using a goto for this would probably be cleaner, but yeah...
- const auto impl = [&name]() -> void* {
+ const auto impl = [&name, &logger]() -> void* {
// If `name` exists right next to the Wine plugin host binary, then
// we'll try loading that. Otherwise we'll fall back to regular
// `dlopen()` for distro packaged versions of yabridge
@@ -52,27 +54,28 @@ void* find_plugin_library(const std::string& name) {
}
}
- if (void* handle = dlopen(name.c_str(), RTLD_LAZY | RTLD_LOCAL)) {
- return handle;
+ auto nix_profiles = getenv("NIX_PROFILES");
+ if (!nix_profiles || nix_profiles[0] == '\0') {
+ logger.log("");
+ logger.log("ERROR: 'NIX_PROFILES' environment variable is not set");
+ logger.log("");
+ return nullptr;
}
- // One last Hail Mary, in case ldconfig was not set up correctly. This
- // might be relevant for some of the `/usr/local/*` locations (although
- // you really, really shouldn't install yabridge there, please, thank
- // you). Yabridgectl searches through these same directories.
- for (const auto& lib_dir : {
- "/usr/lib",
- "/usr/lib/x86_64-linux-gnu",
- "/usr/lib64",
- "/usr/local/lib",
- "/usr/local/lib/x86_64-linux-gnu",
- "/usr/local/lib64",
- }) {
- const fs::path candidate = fs::path(lib_dir) / name;
- if (void* handle =
- dlopen(candidate.c_str(), RTLD_LAZY | RTLD_LOCAL)) {
+ // NIX_PROFILES is iterated in reverse from the most specific (the
+ // user profile) to the least specific (the system profile).
+ const std::string_view nix_profiles_view = nix_profiles;
+ auto segment_end = nix_profiles_view.size();
+ while (segment_end != std::string::npos) {
+ const auto next_segment_end = nix_profiles_view.rfind(' ', segment_end - 1);
+ const auto segment_begin = next_segment_end + 1;
+ const auto profile = nix_profiles_view.substr(segment_begin, segment_end - segment_begin);
+ const auto candidate = fs::path(profile) / "lib" / name;
+ if (auto handle = dlopen(candidate.c_str(), RTLD_LAZY | RTLD_LOCAL)) {
return handle;
}
+
+ segment_end = next_segment_end;
}
return nullptr;
@@ -82,8 +85,6 @@ void* find_plugin_library(const std::string& name) {
if (!handle) {
const fs::path this_plugin_path = get_this_file_location();
- Logger logger = Logger::create_exception_logger();
-
logger.log("");
logger.log("Could not find '" + name + "'");
logger.log("");

173
patches/wine-6006.patch Normal file
View file

@ -0,0 +1,173 @@
From 23a6646d697ddfc51e3deab018853a22376dacdf Mon Sep 17 00:00:00 2001
From: Grazvydas Ignotas <notasas@gmail.com>
Date: Sun, 7 Jul 2024 00:11:26 +0300
Subject: [PATCH 1/2] dwmapi: Drop unnecessary static, improve variable names.
---
dlls/dwmapi/dwmapi_main.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/dlls/dwmapi/dwmapi_main.c b/dlls/dwmapi/dwmapi_main.c
index adc02552ba7..8d4ccbb1fc4 100644
--- a/dlls/dwmapi/dwmapi_main.c
+++ b/dlls/dwmapi/dwmapi_main.c
@@ -184,9 +184,9 @@ HRESULT WINAPI DwmEnableBlurBehindWindow(HWND hWnd, const DWM_BLURBEHIND *pBlurB
*/
BOOL WINAPI DwmDefWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, LRESULT *plResult)
{
- static int i;
+ static BOOL once;
- if (!i++) FIXME("stub\n");
+ if (!once++) FIXME("stub\n");
return FALSE;
}
@@ -273,7 +273,8 @@ static int get_display_frequency(void)
HRESULT WINAPI DwmGetCompositionTimingInfo(HWND hwnd, DWM_TIMING_INFO *info)
{
LARGE_INTEGER performance_frequency, qpc;
- static int i, display_frequency;
+ int display_frequency;
+ static BOOL once;
if (!info)
return E_INVALIDARG;
@@ -281,7 +282,7 @@ HRESULT WINAPI DwmGetCompositionTimingInfo(HWND hwnd, DWM_TIMING_INFO *info)
if (info->cbSize != sizeof(DWM_TIMING_INFO))
return MILERR_MISMATCHED_SIZE;
- if(!i++) FIXME("(%p %p)\n", hwnd, info);
+ if (!once++) FIXME("(%p %p)\n", hwnd, info);
memset(info, 0, info->cbSize);
info->cbSize = sizeof(DWM_TIMING_INFO);
--
GitLab
From 9bd6b35aa8d9b92593db1722ce533e0e4d8985ad Mon Sep 17 00:00:00 2001
From: Grazvydas Ignotas <notasas@gmail.com>
Date: Sun, 7 Jul 2024 00:18:40 +0300
Subject: [PATCH 2/2] dwmapi: Simulate DwmFlush blocking behavior.
The documentation states it's a blocking call. There are reports of it
being used for WaitForVBlank-like purposes [1]. Without blocking Softube
VST plugin logic breaks and they never update their UIs.
[1] https://news.ycombinator.com/item?id=34501612
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=56935
---
dlls/dwmapi/dwmapi_main.c | 23 +++++++++++++++++++--
dlls/dwmapi/tests/dwmapi.c | 41 ++++++++++++++++++++++++++++++++++++++
2 files changed, 62 insertions(+), 2 deletions(-)
diff --git a/dlls/dwmapi/dwmapi_main.c b/dlls/dwmapi/dwmapi_main.c
index 8d4ccbb1fc4..419216534aa 100644
--- a/dlls/dwmapi/dwmapi_main.c
+++ b/dlls/dwmapi/dwmapi_main.c
@@ -32,6 +32,7 @@
WINE_DEFAULT_DEBUG_CHANNEL(dwmapi);
+static int get_display_frequency(void);
/**********************************************************************
* DwmIsCompositionEnabled (DWMAPI.@)
@@ -88,9 +89,26 @@ HRESULT WINAPI DwmGetColorizationColor(DWORD *colorization, BOOL *opaque_blend)
*/
HRESULT WINAPI DwmFlush(void)
{
+ static volatile LONG last_time;
static BOOL once;
+ DWORD now, interval, last = last_time, target;
+ int freq;
- if (!once++) FIXME("() stub\n");
+ if (!once++) FIXME("() semi-stub\n");
+
+ // simulate the WaitForVBlank-like blocking behavior
+ freq = get_display_frequency();
+ interval = 1000 / freq;
+ now = GetTickCount();
+ if (now - last < interval)
+ target = last + interval;
+ else
+ {
+ // act as if we were called midway between 2 vsyncs
+ target = now + interval / 2;
+ }
+ Sleep(target - now);
+ InterlockedCompareExchange(&last_time, target, last);
return S_OK;
}
@@ -262,7 +280,8 @@ static int get_display_frequency(void)
}
else
{
- WARN("Failed to query display frequency, returning a fallback value.\n");
+ static BOOL once;
+ if (!once++) WARN("Failed to query display frequency, returning a fallback value.\n");
return 60;
}
}
diff --git a/dlls/dwmapi/tests/dwmapi.c b/dlls/dwmapi/tests/dwmapi.c
index a89a1fd705b..20628578f41 100644
--- a/dlls/dwmapi/tests/dwmapi.c
+++ b/dlls/dwmapi/tests/dwmapi.c
@@ -140,9 +140,50 @@ cleanup:
DestroyWindow(hwnd);
}
+static void test_DwmFlush(void)
+{
+ LARGE_INTEGER frequency, ts[2];
+ int i, result, ms;
+ DEVMODEA mode;
+ BOOL enabled;
+ HRESULT hr;
+
+ enabled = FALSE;
+ hr = DwmIsCompositionEnabled(&enabled);
+ ok(hr == S_OK, "Got hr %#lx.\n", hr);
+ if (!enabled)
+ {
+ skip("DWM is disabled.\n");
+ return;
+ }
+
+ memset(&mode, 0, sizeof(mode));
+ mode.dmSize = sizeof(mode);
+ result = EnumDisplaySettingsA(NULL, ENUM_CURRENT_SETTINGS, &mode);
+ ok(result, "Failed to get display mode %#lx.\n", GetLastError());
+ ok(mode.dmDisplayFrequency != 0, "dmDisplayFrequency is 0.\n");
+
+ result = QueryPerformanceFrequency(&frequency);
+ ok(result, "Failed to get performance counter frequency.\n");
+
+ result = QueryPerformanceCounter(&ts[0]);
+ ok(result, "Failed to read performance counter.\n");
+ for (i = 0; i < 2; i++)
+ {
+ hr = DwmFlush();
+ ok(hr == S_OK, "Got hr %#lx.\n", hr);
+ }
+ result = QueryPerformanceCounter(&ts[1]);
+ ok(result, "Failed to read performance counter.\n");
+ ms = (ts[1].QuadPart - ts[0].QuadPart) * 1000 / frequency.QuadPart;
+ ok(ms >= 1000 / mode.dmDisplayFrequency,
+ "DwmFlush() took %dms with dmDisplayFrequency %ld.\n", ms, mode.dmDisplayFrequency);
+}
+
START_TEST(dwmapi)
{
test_DwmIsCompositionEnabled();
test_DwmGetCompositionTimingInfo();
test_DWMWA_EXTENDED_FRAME_BOUNDS();
+ test_DwmFlush();
}
--
GitLab