From 8309e0ecb09fe5cf670dff5df1e7ca71821c27bd Mon Sep 17 00:00:00 2001 From: Camilla Berglund Date: Thu, 21 May 2015 14:48:11 +0200 Subject: [PATCH] Use DwmFlush when DWM is enabled. Use DwmFlush instead of WGL_EXT_swap_control when desktop compositing is enabled, to avoid the jitter of DWM and WGL vsync fighting. Fixes #516. --- CMakeLists.txt | 4 ---- README.md | 2 ++ docs/compile.dox | 5 ----- docs/window.dox | 4 +--- src/glfw_config.h.in | 2 -- src/wgl_context.c | 20 ++++++++++++++------ src/wgl_context.h | 1 + src/win32_init.c | 2 ++ src/win32_platform.h | 3 +++ src/win32_window.c | 15 ++++++--------- 10 files changed, 29 insertions(+), 29 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 048d1ee2..1b7ed1a9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,7 +26,6 @@ option(GLFW_INSTALL "Generate installation target" ON) option(GLFW_DOCUMENT_INTERNALS "Include internals in documentation" OFF) if (WIN32) - option(GLFW_USE_DWM_SWAP_INTERVAL "Set swap interval even when DWM compositing is enabled" OFF) option(GLFW_USE_OPTIMUS_HPG "Force use of high-performance GPU on Optimus systems" OFF) endif() @@ -236,9 +235,6 @@ if (_GLFW_WIN32) list(APPEND glfw_PKG_LIBS "-lgdi32") - if (GLFW_USE_DWM_SWAP_INTERVAL) - set(_GLFW_USE_DWM_SWAP_INTERVAL 1) - endif() if (GLFW_USE_OPTIMUS_HPG) set(_GLFW_USE_OPTIMUS_HPG 1) endif() diff --git a/README.md b/README.md index 8cc1909e..185aa280 100644 --- a/README.md +++ b/README.md @@ -65,6 +65,8 @@ GLFW bundles a number of dependencies in the `deps/` directory. - Minimum required CMake version updated to 2.8.12 - Bugfix: Initialization failed on headless systems - Bugfix: The cached current context could get out of sync + - [Win32] Removed `GLFW_USE_DWM_SWAP_INTERVAL` compile-time option + - [Win32] Bugfix: Swap interval was ignored when DWM was enabled - [Cocoa] Bugfix: The cached `NSScreen` for a monitor could get out of sync - [Cocoa] Bugfix: The `GLFW_AUTO_ICONIFY` window hint was ignored - [Cocoa] Bugfix: Resizing a window to its minimum size would segfault diff --git a/docs/compile.dox b/docs/compile.dox index b67a1346..e1828162 100644 --- a/docs/compile.dox +++ b/docs/compile.dox @@ -221,11 +221,6 @@ DLL version of the Visual C++ library is used. It is recommended to set this to `ON`, as this keeps the executable smaller and benefits from security and bug fix updates of the Visual C++ runtime. -`GLFW_USE_DWM_SWAP_INTERVAL` determines whether the swap interval is set even -when DWM compositing is enabled. If this is `ON`, the swap interval is set even -if DWM is enabled. It is recommended to set this to `OFF`, as doing otherwise -can lead to severe jitter. - `GLFW_USE_OPTIMUS_HPG` determines whether to export the `NvOptimusEnablement` symbol, which forces the use of the high-performance GPU on Nvidia Optimus systems. This symbol needs to be exported by the EXE to be detected by the diff --git a/docs/window.dox b/docs/window.dox index cc98ba09..f395c6fa 100644 --- a/docs/window.dox +++ b/docs/window.dox @@ -825,8 +825,6 @@ interval of one lets you avoid tearing. Note that this may not work on all machines, as some drivers have user-controlled settings that override any swap interval the application -requests. It is also by default disabled on Windows Vista and later when using -DWM (Aero), as using it there sometimes leads to severe jitter. You can -forcibly enable it for machines using DWM using @ref compile_options_win32. +requests. */ diff --git a/src/glfw_config.h.in b/src/glfw_config.h.in index 296c96de..13d5c783 100644 --- a/src/glfw_config.h.in +++ b/src/glfw_config.h.in @@ -57,8 +57,6 @@ // Define this to 1 if building as a shared library / dynamic library / DLL #cmakedefine _GLFW_BUILD_DLL -// Define this to 1 if glfwSwapInterval should ignore DWM compositing status -#cmakedefine _GLFW_USE_DWM_SWAP_INTERVAL // Define this to 1 to force use of high-performance GPU on Optimus systems #cmakedefine _GLFW_USE_OPTIMUS_HPG diff --git a/src/wgl_context.c b/src/wgl_context.c index b43cc193..c7293e08 100644 --- a/src/wgl_context.c +++ b/src/wgl_context.c @@ -570,6 +570,14 @@ void _glfwPlatformMakeContextCurrent(_GLFWwindow* window) void _glfwPlatformSwapBuffers(_GLFWwindow* window) { + // HACK: Use DwmFlush when desktop composition is enabled + if (_glfwIsCompositionEnabled()) + { + int count = window->wgl.interval; + while (count--) + _glfw_DwmFlush(); + } + SwapBuffers(window->wgl.dc); } @@ -577,12 +585,12 @@ void _glfwPlatformSwapInterval(int interval) { _GLFWwindow* window = _glfwPlatformGetCurrentContext(); -#if !defined(_GLFW_USE_DWM_SWAP_INTERVAL) - // HACK: Don't enabled vsync when desktop compositing is enabled, as it - // leads to severe frame jitter on some cards - if (_glfwIsCompositionEnabled() && interval) - return; -#endif + window->wgl.interval = interval; + + // HACK: Disable WGL swap interval when desktop composition is enabled to + // avoid interfering with DWM vsync + if (_glfwIsCompositionEnabled()) + interval = 0; if (window->wgl.EXT_swap_control) window->wgl.SwapIntervalEXT(interval); diff --git a/src/wgl_context.h b/src/wgl_context.h index 3fc29e72..59542203 100644 --- a/src/wgl_context.h +++ b/src/wgl_context.h @@ -44,6 +44,7 @@ typedef struct _GLFWcontextWGL { HDC dc; // Private GDI device context HGLRC context; // Permanent rendering context + int interval; // WGL extensions (context specific) PFNWGLSWAPINTERVALEXTPROC SwapIntervalEXT; diff --git a/src/win32_init.c b/src/win32_init.c index bf049a70..068a82ac 100644 --- a/src/win32_init.c +++ b/src/win32_init.c @@ -96,6 +96,8 @@ static GLboolean initLibraries(void) { _glfw.win32.dwmapi.DwmIsCompositionEnabled = (DWMISCOMPOSITIONENABLED_T) GetProcAddress(_glfw.win32.dwmapi.instance, "DwmIsCompositionEnabled"); + _glfw.win32.dwmapi.DwmFlush = (DWMFLUSH_T) + GetProcAddress(_glfw.win32.dwmapi.instance, "DwmFlush"); } return GL_TRUE; diff --git a/src/win32_platform.h b/src/win32_platform.h index 861d2bc3..37145f45 100644 --- a/src/win32_platform.h +++ b/src/win32_platform.h @@ -121,7 +121,9 @@ typedef BOOL (WINAPI * CHANGEWINDOWMESSAGEFILTEREX_T)(HWND,UINT,DWORD,PCHANGEFIL // dwmapi.dll function pointer typedefs typedef HRESULT (WINAPI * DWMISCOMPOSITIONENABLED_T)(BOOL*); +typedef HRESULT (WINAPI * DWMFLUSH_T)(VOID); #define _glfw_DwmIsCompositionEnabled _glfw.win32.dwmapi.DwmIsCompositionEnabled +#define _glfw_DwmFlush _glfw.win32.dwmapi.DwmFlush #define _GLFW_RECREATION_NOT_NEEDED 0 @@ -195,6 +197,7 @@ typedef struct _GLFWlibraryWin32 struct { HINSTANCE instance; DWMISCOMPOSITIONENABLED_T DwmIsCompositionEnabled; + DWMFLUSH_T DwmFlush; } dwmapi; } _GLFWlibraryWin32; diff --git a/src/win32_window.c b/src/win32_window.c index da652e8a..0fdcd7ad 100644 --- a/src/win32_window.c +++ b/src/win32_window.c @@ -565,15 +565,12 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, case WM_DWMCOMPOSITIONCHANGED: { - if (_glfwIsCompositionEnabled()) - { - _GLFWwindow* previous = _glfwPlatformGetCurrentContext(); - _glfwPlatformMakeContextCurrent(window); - _glfwPlatformSwapInterval(0); - _glfwPlatformMakeContextCurrent(previous); - } - - // TODO: Restore vsync if compositing was disabled + // HACK: Re-apply interval when desktop composition is toggled to + // ensure WGL swap interval is disabled when necessary + _GLFWwindow* previous = _glfwPlatformGetCurrentContext(); + _glfwPlatformMakeContextCurrent(window); + _glfwPlatformSwapInterval(window->wgl.interval); + _glfwPlatformMakeContextCurrent(previous); break; }