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.
This commit is contained in:
Camilla Berglund 2015-05-21 14:48:11 +02:00
parent 22e9451192
commit 8309e0ecb0
10 changed files with 29 additions and 29 deletions

View File

@ -26,7 +26,6 @@ option(GLFW_INSTALL "Generate installation target" ON)
option(GLFW_DOCUMENT_INTERNALS "Include internals in documentation" OFF) option(GLFW_DOCUMENT_INTERNALS "Include internals in documentation" OFF)
if (WIN32) 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) option(GLFW_USE_OPTIMUS_HPG "Force use of high-performance GPU on Optimus systems" OFF)
endif() endif()
@ -236,9 +235,6 @@ if (_GLFW_WIN32)
list(APPEND glfw_PKG_LIBS "-lgdi32") 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) if (GLFW_USE_OPTIMUS_HPG)
set(_GLFW_USE_OPTIMUS_HPG 1) set(_GLFW_USE_OPTIMUS_HPG 1)
endif() endif()

View File

@ -65,6 +65,8 @@ GLFW bundles a number of dependencies in the `deps/` directory.
- Minimum required CMake version updated to 2.8.12 - Minimum required CMake version updated to 2.8.12
- Bugfix: Initialization failed on headless systems - Bugfix: Initialization failed on headless systems
- Bugfix: The cached current context could get out of sync - 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 cached `NSScreen` for a monitor could get out of sync
- [Cocoa] Bugfix: The `GLFW_AUTO_ICONIFY` window hint was ignored - [Cocoa] Bugfix: The `GLFW_AUTO_ICONIFY` window hint was ignored
- [Cocoa] Bugfix: Resizing a window to its minimum size would segfault - [Cocoa] Bugfix: Resizing a window to its minimum size would segfault

View File

@ -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 `ON`, as this keeps the executable smaller and benefits from security and bug
fix updates of the Visual C++ runtime. 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` `GLFW_USE_OPTIMUS_HPG` determines whether to export the `NvOptimusEnablement`
symbol, which forces the use of the high-performance GPU on Nvidia Optimus 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 systems. This symbol needs to be exported by the EXE to be detected by the

View File

@ -825,8 +825,6 @@ interval of one lets you avoid tearing.
Note that this may not work on all machines, as some drivers have Note that this may not work on all machines, as some drivers have
user-controlled settings that override any swap interval the application user-controlled settings that override any swap interval the application
requests. It is also by default disabled on Windows Vista and later when using requests.
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.
*/ */

View File

@ -57,8 +57,6 @@
// Define this to 1 if building as a shared library / dynamic library / DLL // Define this to 1 if building as a shared library / dynamic library / DLL
#cmakedefine _GLFW_BUILD_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 // Define this to 1 to force use of high-performance GPU on Optimus systems
#cmakedefine _GLFW_USE_OPTIMUS_HPG #cmakedefine _GLFW_USE_OPTIMUS_HPG

View File

@ -570,6 +570,14 @@ void _glfwPlatformMakeContextCurrent(_GLFWwindow* window)
void _glfwPlatformSwapBuffers(_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); SwapBuffers(window->wgl.dc);
} }
@ -577,12 +585,12 @@ void _glfwPlatformSwapInterval(int interval)
{ {
_GLFWwindow* window = _glfwPlatformGetCurrentContext(); _GLFWwindow* window = _glfwPlatformGetCurrentContext();
#if !defined(_GLFW_USE_DWM_SWAP_INTERVAL) window->wgl.interval = interval;
// HACK: Don't enabled vsync when desktop compositing is enabled, as it
// leads to severe frame jitter on some cards // HACK: Disable WGL swap interval when desktop composition is enabled to
if (_glfwIsCompositionEnabled() && interval) // avoid interfering with DWM vsync
return; if (_glfwIsCompositionEnabled())
#endif interval = 0;
if (window->wgl.EXT_swap_control) if (window->wgl.EXT_swap_control)
window->wgl.SwapIntervalEXT(interval); window->wgl.SwapIntervalEXT(interval);

View File

@ -44,6 +44,7 @@ typedef struct _GLFWcontextWGL
{ {
HDC dc; // Private GDI device context HDC dc; // Private GDI device context
HGLRC context; // Permanent rendering context HGLRC context; // Permanent rendering context
int interval;
// WGL extensions (context specific) // WGL extensions (context specific)
PFNWGLSWAPINTERVALEXTPROC SwapIntervalEXT; PFNWGLSWAPINTERVALEXTPROC SwapIntervalEXT;

View File

@ -96,6 +96,8 @@ static GLboolean initLibraries(void)
{ {
_glfw.win32.dwmapi.DwmIsCompositionEnabled = (DWMISCOMPOSITIONENABLED_T) _glfw.win32.dwmapi.DwmIsCompositionEnabled = (DWMISCOMPOSITIONENABLED_T)
GetProcAddress(_glfw.win32.dwmapi.instance, "DwmIsCompositionEnabled"); GetProcAddress(_glfw.win32.dwmapi.instance, "DwmIsCompositionEnabled");
_glfw.win32.dwmapi.DwmFlush = (DWMFLUSH_T)
GetProcAddress(_glfw.win32.dwmapi.instance, "DwmFlush");
} }
return GL_TRUE; return GL_TRUE;

View File

@ -121,7 +121,9 @@ typedef BOOL (WINAPI * CHANGEWINDOWMESSAGEFILTEREX_T)(HWND,UINT,DWORD,PCHANGEFIL
// dwmapi.dll function pointer typedefs // dwmapi.dll function pointer typedefs
typedef HRESULT (WINAPI * DWMISCOMPOSITIONENABLED_T)(BOOL*); typedef HRESULT (WINAPI * DWMISCOMPOSITIONENABLED_T)(BOOL*);
typedef HRESULT (WINAPI * DWMFLUSH_T)(VOID);
#define _glfw_DwmIsCompositionEnabled _glfw.win32.dwmapi.DwmIsCompositionEnabled #define _glfw_DwmIsCompositionEnabled _glfw.win32.dwmapi.DwmIsCompositionEnabled
#define _glfw_DwmFlush _glfw.win32.dwmapi.DwmFlush
#define _GLFW_RECREATION_NOT_NEEDED 0 #define _GLFW_RECREATION_NOT_NEEDED 0
@ -195,6 +197,7 @@ typedef struct _GLFWlibraryWin32
struct { struct {
HINSTANCE instance; HINSTANCE instance;
DWMISCOMPOSITIONENABLED_T DwmIsCompositionEnabled; DWMISCOMPOSITIONENABLED_T DwmIsCompositionEnabled;
DWMFLUSH_T DwmFlush;
} dwmapi; } dwmapi;
} _GLFWlibraryWin32; } _GLFWlibraryWin32;

View File

@ -565,15 +565,12 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
case WM_DWMCOMPOSITIONCHANGED: case WM_DWMCOMPOSITIONCHANGED:
{ {
if (_glfwIsCompositionEnabled()) // HACK: Re-apply interval when desktop composition is toggled to
{ // ensure WGL swap interval is disabled when necessary
_GLFWwindow* previous = _glfwPlatformGetCurrentContext(); _GLFWwindow* previous = _glfwPlatformGetCurrentContext();
_glfwPlatformMakeContextCurrent(window); _glfwPlatformMakeContextCurrent(window);
_glfwPlatformSwapInterval(0); _glfwPlatformSwapInterval(window->wgl.interval);
_glfwPlatformMakeContextCurrent(previous); _glfwPlatformMakeContextCurrent(previous);
}
// TODO: Restore vsync if compositing was disabled
break; break;
} }