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.
From: Grazvydas Ignotas notasas@gmail.com
--- 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);
From: Grazvydas Ignotas notasas@gmail.com
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..e13838e644d 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; + } + InterlockedCompareExchange(&last_time, target, last); + Sleep(target - now);
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(); }
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=146862
Your paranoid android.
=== debian11b (64 bit WoW report) ===
kernel32: comm.c:1574: Test failed: AbortWaitCts hComPortEvent failed comm.c:1586: Test failed: Unexpected time 1001, expected around 500
user32: win.c:4037: Test failed: Expected active window 0000000003E10180, got 00000000030B0182. win.c:4038: Test failed: Expected focus window 0000000003E10180, got 00000000030B0182.