diff --git a/inc/fps_limiter.h b/inc/fps_limiter.h index dcc413c..ec0f7bc 100644 --- a/inc/fps_limiter.h +++ b/inc/fps_limiter.h @@ -22,6 +22,8 @@ typedef struct _D3DKMT_CLOSEADAPTER { UINT hAdapter; } D3DKMT_CLOSEADAPTER; +typedef HRESULT(WINAPI* DWMFLUSHPROC)(VOID); +typedef HRESULT(WINAPI* DWMISCOMPOSITIONENABLEDPROC)(BOOL*); typedef NTSTATUS(WINAPI* D3DKMTWAITFORVERTICALBLANKEVENTPROC)(const D3DKMT_WAITFORVERTICALBLANKEVENT* Arg1); typedef NTSTATUS(WINAPI* D3DKMTOPENADAPTERFROMHDCPROC)(D3DKMT_OPENADAPTERFROMHDC* Arg1); typedef NTSTATUS(WINAPI* D3DKMTCLOSEADAPTERPROC)(D3DKMT_CLOSEADAPTER* Arg1); @@ -38,6 +40,9 @@ typedef struct FPSLIMITER D3DKMT_OPENADAPTERFROMHDC adapter; D3DKMT_CLOSEADAPTER close_adapter; HMODULE gdi32_dll; + HMODULE dwmapi_dll; + DWMFLUSHPROC DwmFlush; + DWMISCOMPOSITIONENABLEDPROC DwmIsCompositionEnabled; D3DKMTWAITFORVERTICALBLANKEVENTPROC D3DKMTWaitForVerticalBlankEvent; D3DKMTOPENADAPTERFROMHDCPROC D3DKMTOpenAdapterFromHdc; D3DKMTCLOSEADAPTERPROC D3DKMTCloseAdapter; @@ -51,6 +56,8 @@ extern FPSLIMITER g_fpsl; void fpsl_init(); BOOL fpsl_wait_for_vblank(); +BOOL fpsl_dwm_flush(); +BOOL fpsl_dwm_is_enabled(); void fpsl_frame_start(); void fpsl_frame_end(); diff --git a/src/dd.c b/src/dd.c index 65eed9b..d7018e0 100644 --- a/src/dd.c +++ b/src/dd.c @@ -1568,8 +1568,17 @@ HRESULT dd_WaitForVerticalBlank(DWORD dwFlags, HANDLE hEvent) { if (g_config.maxgameticks == -2 || g_ddraw.wait_for_real_vblank) { - if (fpsl_wait_for_vblank()) - return DD_OK; + /* Workaround for DwmFlush() freeze (e.g. slow alt+tab) issue on windows 7 SP1 */ + if (g_ddraw.renderer == ogl_render_main && !IsWine() && !IsWindows8OrGreater()) + { + if (fpsl_wait_for_vblank()) + return DD_OK; + } + else + { + if (fpsl_dwm_flush() || fpsl_wait_for_vblank()) + return DD_OK; + } } if (!g_ddraw.flip_limiter.tick_length) diff --git a/src/fps_limiter.c b/src/fps_limiter.c index 1300f8d..14c4394 100644 --- a/src/fps_limiter.c +++ b/src/fps_limiter.c @@ -49,6 +49,23 @@ void fpsl_init() g_fpsl.gdi32_dll = real_LoadLibraryA("gdi32.dll"); } + if (!g_fpsl.dwmapi_dll) + { + g_fpsl.dwmapi_dll = real_LoadLibraryA("dwmapi.dll"); + } + + if (!g_fpsl.DwmFlush) + { + g_fpsl.DwmFlush = + (DWMFLUSHPROC)real_GetProcAddress(g_fpsl.dwmapi_dll, "DwmFlush"); + } + + if (!g_fpsl.DwmIsCompositionEnabled) + { + g_fpsl.DwmIsCompositionEnabled = + (DWMISCOMPOSITIONENABLEDPROC)real_GetProcAddress(g_fpsl.dwmapi_dll, "DwmIsCompositionEnabled"); + } + if (!g_fpsl.D3DKMTWaitForVerticalBlankEvent) { g_fpsl.D3DKMTWaitForVerticalBlankEvent = @@ -101,6 +118,33 @@ BOOL fpsl_wait_for_vblank() return FALSE; } +BOOL fpsl_dwm_flush() +{ + if (g_fpsl.initialized && fpsl_dwm_is_enabled() && g_fpsl.DwmFlush) + { + HRESULT x = g_fpsl.DwmFlush(); + + if (!SUCCEEDED(x)) + { + //TRACE(" ERROR %s(result=%08X)\n", __FUNCTION__, x); + } + + return SUCCEEDED(x); + } + + return FALSE; +} + +BOOL fpsl_dwm_is_enabled() +{ + BOOL dwm_enabled = FALSE; + + if (g_fpsl.DwmIsCompositionEnabled) + g_fpsl.DwmIsCompositionEnabled(&dwm_enabled); + + return dwm_enabled; +} + void fpsl_frame_start() { if (g_fpsl.tick_length > 0) @@ -112,8 +156,17 @@ void fpsl_frame_end() if (g_config.maxfps < 0 || (g_config.vsync && (!g_config.maxfps || g_config.maxfps >= g_ddraw.mode.dmDisplayFrequency))) { - if (fpsl_wait_for_vblank()) - return; + /* Workaround for DwmFlush() freeze (e.g. slow alt+tab) issue on windows 7 SP1 */ + if (g_ddraw.renderer == ogl_render_main && !IsWine() && !IsWindows8OrGreater()) + { + if (fpsl_wait_for_vblank()) + return; + } + else + { + if (fpsl_dwm_flush() || fpsl_wait_for_vblank()) + return; + } } if (g_fpsl.tick_length > 0)