diff options
Diffstat (limited to 'platform/osx/os_osx.mm')
-rw-r--r-- | platform/osx/os_osx.mm | 68 |
1 files changed, 55 insertions, 13 deletions
diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm index 760858b2e5..6b65c1a529 100644 --- a/platform/osx/os_osx.mm +++ b/platform/osx/os_osx.mm @@ -117,6 +117,21 @@ static Vector2 get_mouse_pos(NSPoint locationInWindow, CGFloat backingScaleFacto return Vector2(mouse_x, mouse_y); } +// DisplayLinkCallback is called from our DisplayLink OS thread informing us right before +// a screen update is required. We can use it to work around the broken vsync. +static CVReturn DisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeStamp *now, const CVTimeStamp *outputTime, CVOptionFlags flagsIn, CVOptionFlags *flagsOut, void *displayLinkContext) { + OS_OSX *os = (OS_OSX *)displayLinkContext; + + // Set flag so we know we can output our next frame and signal our conditional lock + // if we're not doing vsync this will be ignored + [os->vsync_condition lock]; + os->waiting_for_vsync = false; + [os->vsync_condition signal]; + [os->vsync_condition unlock]; + + return kCVReturnSuccess; +} + @interface GodotApplication : NSApplication @end @@ -267,7 +282,9 @@ static Vector2 get_mouse_pos(NSPoint locationInWindow, CGFloat backingScaleFacto NSWindow *window = (NSWindow *)[notification object]; CGFloat newBackingScaleFactor = [window backingScaleFactor]; CGFloat oldBackingScaleFactor = [[[notification userInfo] objectForKey:@"NSBackingPropertyOldScaleFactorKey"] doubleValue]; - [OS_OSX::singleton->window_view setWantsBestResolutionOpenGLSurface:YES]; + if (OS_OSX::singleton->is_hidpi_allowed()) { + [OS_OSX::singleton->window_view setWantsBestResolutionOpenGLSurface:YES]; + } if (newBackingScaleFactor != oldBackingScaleFactor) { //Set new display scale and window size @@ -1366,6 +1383,15 @@ Error OS_OSX::initialize(const VideoMode &p_desired, int p_video_driver, int p_a [context makeCurrentContext]; + // setup our display link, this will inform us when a refresh is needed + CVDisplayLinkCreateWithActiveCGDisplays(&displayLink); + CVDisplayLinkSetOutputCallback(displayLink, &DisplayLinkCallback, this); + CVDisplayLinkSetCurrentCGDisplayFromOpenGLContext(displayLink, context.CGLContextObj, pixelFormat.CGLPixelFormatObj); + CVDisplayLinkStart(displayLink); + + // initialise a conditional lock object + vsync_condition = [[NSCondition alloc] init]; + set_use_vsync(p_desired.use_vsync); [NSApp activateIgnoringOtherApps:YES]; @@ -1453,6 +1479,11 @@ void OS_OSX::finalize() { midi_driver.close(); #endif + if (displayLink) { + CVDisplayLinkRelease(displayLink); + } + [vsync_condition release]; + CFNotificationCenterRemoveObserver(CFNotificationCenterGetDistributedCenter(), NULL, kTISNotifySelectedKeyboardInputSourceChanged, NULL); CGDisplayRemoveReconfigurationCallback(displays_arrangement_changed, NULL); @@ -1967,6 +1998,17 @@ String OS_OSX::get_locale() const { } void OS_OSX::swap_buffers() { + if (is_vsync_enabled()) { + // Wait until our DisplayLink callback unsets our flag... + [vsync_condition lock]; + while (waiting_for_vsync) + [vsync_condition wait]; + + // Make sure we wait again next frame around + waiting_for_vsync = true; + + [vsync_condition unlock]; + } [context flushBuffer]; } @@ -2633,22 +2675,22 @@ Error OS_OSX::move_to_trash(const String &p_path) { } void OS_OSX::_set_use_vsync(bool p_enable) { - CGLContextObj ctx = CGLGetCurrentContext(); + // CGLCPSwapInterval broke in OSX 10.14 and it seems Apple is not interested in fixing + // it as OpenGL is now deprecated and Metal solves this differently. + // Following SDLs example we're working around this using DisplayLink + // When vsync is enabled we set a flag "waiting_for_vsync" to true. + // This flag is set to false when DisplayLink informs us our display is about to refresh. + + /* CGLContextObj ctx = CGLGetCurrentContext(); if (ctx) { GLint swapInterval = p_enable ? 1 : 0; CGLSetParameter(ctx, kCGLCPSwapInterval, &swapInterval); - } -} -/* -bool OS_OSX::is_vsync_enabled() const { - GLint swapInterval = 0; - CGLContextObj ctx = CGLGetCurrentContext(); - if (ctx) { - CGLGetParameter(ctx, kCGLCPSwapInterval, &swapInterval); - } - return swapInterval ? true : false; + }*/ + + ///TODO Maybe pause/unpause display link? + waiting_for_vsync = p_enable; } -*/ + OS_OSX *OS_OSX::singleton = NULL; OS_OSX::OS_OSX() { |