Browse Source

Merge branch 'main' into 12.0-development

Alex Szpakowski 3 years ago
parent
commit
2149457c72
2 changed files with 55 additions and 0 deletions
  1. 1 0
      CMakeLists.txt
  2. 54 0
      src/modules/window/sdl/Window.cpp

+ 1 - 0
CMakeLists.txt

@@ -1779,6 +1779,7 @@ if(MSVC)
 	set(LOVE_LINK_LIBRARIES ${LOVE_LINK_LIBRARIES}
 	set(LOVE_LINK_LIBRARIES ${LOVE_LINK_LIBRARIES}
 		ws2_32.lib
 		ws2_32.lib
 		winmm.lib
 		winmm.lib
+		dwmapi.lib
 	)
 	)
 
 
 	set(LOVE_RC
 	set(LOVE_RC

+ 54 - 0
src/modules/window/sdl/Window.cpp

@@ -44,6 +44,8 @@
 
 
 #if defined(LOVE_WINDOWS)
 #if defined(LOVE_WINDOWS)
 #include <windows.h>
 #include <windows.h>
+#include <dwmapi.h>
+#include <VersionHelpers.h>
 #elif defined(LOVE_MACOS)
 #elif defined(LOVE_MACOS)
 #include "common/macos.h"
 #include "common/macos.h"
 #endif
 #endif
@@ -1176,7 +1178,59 @@ bool Window::isMinimized() const
 void Window::swapBuffers()
 void Window::swapBuffers()
 {
 {
 	if (glcontext)
 	if (glcontext)
+	{
+#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);
 		SDL_GL_SwapWindow(window);
+
+#ifdef LOVE_WINDOWS
+		if (useDwmFlush)
+		{
+			DwmFlush();
+			SDL_GL_SetSwapInterval(swapInterval);
+		}
+#endif
+	}
 }
 }
 
 
 bool Window::hasFocus() const
 bool Window::hasFocus() const