Skip to content

Commit

Permalink
Windows: fix some cases of stuttering in windowed mode.
Browse files Browse the repository at this point in the history
Use DwmFlush instead of OpenGL vsync, when specific conditions are met. Fixes #1628.
  • Loading branch information
slime73 committed Apr 17, 2022
1 parent b3b1317 commit 5175b0d
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 0 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1755,6 +1755,7 @@ if(MSVC)
set(LOVE_LINK_LIBRARIES ${LOVE_LINK_LIBRARIES}
ws2_32.lib
winmm.lib
dwmapi.lib
)

set(LOVE_RC
Expand Down
52 changes: 52 additions & 0 deletions src/modules/window/sdl/Window.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@

#if defined(LOVE_WINDOWS)
#include <windows.h>
#include <dwmapi.h>
#include <VersionHelpers.h>
#elif defined(LOVE_MACOSX)
#include "common/macosx.h"
#endif
Expand Down Expand Up @@ -1015,7 +1017,57 @@ bool Window::isMinimized() const

void Window::swapBuffers()
{
#ifdef LOVE_WINDOWS
bool useDwmFlush = false;
int swapInterval = getVSync();

// https://github.com/love2d/love/issues/1628
// VSync can interact badly with Windows desktop composition (DWM) in windowed mode. DwmFlush can be used instead
// of vsync, but it's much less flexible so we're very conservative here with where it's used:
// - It won't work with exclusive or desktop fullscreen.
// - DWM refreshes don't always match the refresh rate of the monitor the window is in (or the requested swap
// interval), so we only use it when they do match.
// - The user may force GL vsync, and DwmFlush shouldn't be used together with GL vsync.
if (context != nullptr && !settings.fullscreen && swapInterval == 1)
{
// Desktop composition is always enabled in Windows 8+. But DwmIsCompositionEnabled won't always return true...
// (see DwmIsCompositionEnabled docs).
BOOL compositionEnabled = IsWindows8OrGreater();
if (compositionEnabled || (SUCCEEDED(DwmIsCompositionEnabled(&compositionEnabled)) && compositionEnabled))
{
DWM_TIMING_INFO info = {};
info.cbSize = sizeof(DWM_TIMING_INFO);
double dwmRefreshRate = 0;
if (SUCCEEDED(DwmGetCompositionTimingInfo(nullptr, &info)))
dwmRefreshRate = (double)info.rateRefresh.uiNumerator / (double)info.rateRefresh.uiDenominator;

SDL_DisplayMode dmode = {};
int displayindex = SDL_GetWindowDisplayIndex(window);

if (displayindex >= 0)
SDL_GetCurrentDisplayMode(displayindex, &dmode);

if (dmode.refresh_rate > 0 && dwmRefreshRate > 0 && (fabs(dmode.refresh_rate - dwmRefreshRate) < 2))
{
SDL_GL_SetSwapInterval(0);
if (SDL_GL_GetSwapInterval() == 0)
useDwmFlush = true;
else
SDL_GL_SetSwapInterval(swapInterval);
}
}
}
#endif

SDL_GL_SwapWindow(window);

#ifdef LOVE_WINDOWS
if (useDwmFlush)
{
DwmFlush();
SDL_GL_SetSwapInterval(swapInterval);
}
#endif
}

bool Window::hasFocus() const
Expand Down

0 comments on commit 5175b0d

Please sign in to comment.