Browse Source

metal: implement vsync toggle on macOS

Alex Szpakowski 4 years ago
parent
commit
0d94530374
3 changed files with 64 additions and 8 deletions
  1. 6 0
      src/common/macos.h
  2. 27 0
      src/common/macos.mm
  3. 31 8
      src/modules/window/sdl/Window.cpp

+ 6 - 0
src/common/macos.h

@@ -49,6 +49,12 @@ std::string checkDropEvents();
  **/
 void requestAttention(bool continuous);
 
+/**
+ * Sets whether vsync is enabled for the given CAMetalLayer
+ **/
+void setMetalLayerVSync(void *metallayer, bool vsync);
+bool getMetalLayerVSync(void *metallayer);
+
 } // macos
 } // love
 

+ 27 - 0
src/common/macos.mm

@@ -24,6 +24,7 @@
 
 #import <Foundation/Foundation.h>
 #import <Cocoa/Cocoa.h>
+#import <QuartzCore/CAMetalLayer.h>
 
 #ifdef LOVE_MACOSX_SDL_DIRECT_INCLUDE
 # include <SDL.h>
@@ -85,6 +86,32 @@ void requestAttention(bool continuous)
 	}
 }
 
+void setMetalLayerVSync(void *metallayer, bool vsync)
+{
+	@autoreleasepool
+	{
+		if (@available(macOS 10.13, *))
+		{
+			CAMetalLayer *layer = (__bridge CAMetalLayer *) metallayer;
+			layer.displaySyncEnabled = vsync;
+		}
+	}
+}
+
+bool getMetalLayerVSync(void *metallayer)
+{
+	@autoreleasepool
+	{
+		if (@available(macOS 10.13, *))
+		{
+			CAMetalLayer *layer = (__bridge CAMetalLayer *) metallayer;
+			return layer.displaySyncEnabled;
+		}
+	}
+
+	return true;
+}
+
 } // osx
 } // love
 

+ 31 - 8
src/modules/window/sdl/Window.cpp

@@ -1070,20 +1070,43 @@ love::image::ImageData *Window::getIcon()
 
 void Window::setVSync(int vsync)
 {
-	if (glcontext == nullptr)
-		return;
+	if (glcontext != nullptr)
+	{
+		SDL_GL_SetSwapInterval(vsync);
 
-	SDL_GL_SetSwapInterval(vsync);
+		// Check if adaptive vsync was requested but not supported, and fall
+		// back to regular vsync if so.
+		if (vsync == -1 && SDL_GL_GetSwapInterval() != -1)
+			SDL_GL_SetSwapInterval(1);
+	}
 
-	// Check if adaptive vsync was requested but not supported, and fall back
-	// to regular vsync if so.
-	if (vsync == -1 && SDL_GL_GetSwapInterval() != -1)
-		SDL_GL_SetSwapInterval(1);
+#if defined(LOVE_GRAPHICS_METAL) && defined(LOVE_MACOS)
+	if (metalView != nullptr)
+	{
+		void *metallayer = SDL_Metal_GetLayer(metalView);
+		love::macos::setMetalLayerVSync(metallayer, vsync != 0);
+	}
+#endif
 }
 
 int Window::getVSync() const
 {
-	return glcontext != nullptr ? SDL_GL_GetSwapInterval() : 0;
+	if (glcontext != nullptr)
+		return SDL_GL_GetSwapInterval();
+
+#if defined(LOVE_GRAPHICS_METAL)
+	if (metalView != nullptr)
+	{
+#ifdef LOVE_MACOS
+		void *metallayer = SDL_Metal_GetLayer(metalView);
+		return love::macos::getMetalLayerVSync(metallayer) ? 1 : 0;
+#else
+		return 1;
+#endif
+	}
+#endif
+
+	return 0;
 }
 
 void Window::setDisplaySleepEnabled(bool enable)