From 04b50f6c6bef67b744b192c78775771b51ff2141 Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Tue, 11 Jun 2019 16:19:01 -0400 Subject: [PATCH] cocoa: Backed out CVDisplayLink code for macOS vsync. This was to deal with broken vsync support in macOS 10.14, which we assumed would remain broken indefinitely, but a later 10.14 released fixed it. This is a loss of late-swap support, but there are several subtle problems in our CVDiplayLink code that are also evaporating, to be fair. Fixes Bugzilla #4575. (Backed out changeset 8760fed23001) --- src/video/cocoa/SDL_cocoaopengl.h | 7 +-- src/video/cocoa/SDL_cocoaopengl.m | 101 +++++++----------------------- 2 files changed, 24 insertions(+), 84 deletions(-) diff --git a/src/video/cocoa/SDL_cocoaopengl.h b/src/video/cocoa/SDL_cocoaopengl.h index 69186596f..9377d8052 100644 --- a/src/video/cocoa/SDL_cocoaopengl.h +++ b/src/video/cocoa/SDL_cocoaopengl.h @@ -36,11 +36,6 @@ struct SDL_GLDriverData @interface SDLOpenGLContext : NSOpenGLContext { SDL_atomic_t dirty; SDL_Window *window; - CVDisplayLinkRef displayLink; - @public SDL_mutex *swapIntervalMutex; - @public SDL_cond *swapIntervalCond; - @public SDL_atomic_t swapIntervalSetting; - @public SDL_atomic_t swapIntervalsPassed; } - (id)initWithFormat:(NSOpenGLPixelFormat *)format @@ -48,7 +43,7 @@ struct SDL_GLDriverData - (void)scheduleUpdate; - (void)updateIfNeeded; - (void)setWindow:(SDL_Window *)window; -- (void)dealloc; + @end diff --git a/src/video/cocoa/SDL_cocoaopengl.m b/src/video/cocoa/SDL_cocoaopengl.m index c014308d3..680c4ccf8 100644 --- a/src/video/cocoa/SDL_cocoaopengl.m +++ b/src/video/cocoa/SDL_cocoaopengl.m @@ -36,23 +36,6 @@ #define DEFAULT_OPENGL "/System/Library/Frameworks/OpenGL.framework/Libraries/libGL.dylib" -static CVReturn -DisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeStamp* now, const CVTimeStamp* outputTime, CVOptionFlags flagsIn, CVOptionFlags* flagsOut, void* displayLinkContext) -{ - SDLOpenGLContext *nscontext = (SDLOpenGLContext *) displayLinkContext; - - /*printf("DISPLAY LINK! %u\n", (unsigned int) SDL_GetTicks()); */ - const int setting = SDL_AtomicGet(&nscontext->swapIntervalSetting); - if (setting != 0) { /* nothing to do if vsync is disabled, don't even lock */ - SDL_LockMutex(nscontext->swapIntervalMutex); - SDL_AtomicAdd(&nscontext->swapIntervalsPassed, 1); - SDL_CondSignal(nscontext->swapIntervalCond); - SDL_UnlockMutex(nscontext->swapIntervalMutex); - } - - return kCVReturnSuccess; -} - @implementation SDLOpenGLContext : NSOpenGLContext - (id)initWithFormat:(NSOpenGLPixelFormat *)format @@ -62,20 +45,6 @@ DisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeStamp* now, const if (self) { SDL_AtomicSet(&self->dirty, 0); self->window = NULL; - SDL_AtomicSet(&self->swapIntervalSetting, 0); - SDL_AtomicSet(&self->swapIntervalsPassed, 0); - self->swapIntervalCond = SDL_CreateCond(); - self->swapIntervalMutex = SDL_CreateMutex(); - if (!self->swapIntervalCond || !self->swapIntervalMutex) { - [self release]; - return nil; - } - - /* !!! FIXME: check return values. */ - CVDisplayLinkCreateWithActiveCGDisplays(&self->displayLink); - CVDisplayLinkSetOutputCallback(self->displayLink, &DisplayLinkCallback, self); - CVDisplayLinkSetCurrentCGDisplayFromOpenGLContext(self->displayLink, [self CGLContextObj], [format CGLPixelFormatObj]); - CVDisplayLinkStart(displayLink); } return self; } @@ -145,19 +114,6 @@ DisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeStamp* now, const } } -- (void)dealloc -{ - if (self->displayLink) { - CVDisplayLinkRelease(self->displayLink); - } - if (self->swapIntervalCond) { - SDL_DestroyCond(self->swapIntervalCond); - } - if (self->swapIntervalMutex) { - SDL_DestroyMutex(self->swapIntervalMutex); - } - [super dealloc]; -} @end @@ -208,7 +164,6 @@ Cocoa_GL_CreateContext(_THIS, SDL_Window * window) const char *glversion; int glversion_major; int glversion_minor; - int interval; if (_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES) { #if SDL_VIDEO_OPENGL_EGL @@ -320,10 +275,6 @@ Cocoa_GL_CreateContext(_THIS, SDL_Window * window) return NULL; } - /* vsync is handled separately by synchronizing with a display link. */ - interval = 0; - [context setValues:&interval forParameter:NSOpenGLCPSwapInterval]; - if ( Cocoa_GL_MakeCurrent(_this, window, context) < 0 ) { Cocoa_GL_DeleteContext(_this, context); SDL_SetError("Failed making OpenGL context current"); @@ -417,17 +368,21 @@ int Cocoa_GL_SetSwapInterval(_THIS, int interval) { @autoreleasepool { - SDLOpenGLContext *nscontext = (SDLOpenGLContext *) SDL_GL_GetCurrentContext(); + NSOpenGLContext *nscontext; + GLint value; int status; - if (nscontext == nil) { - status = SDL_SetError("No current OpenGL context"); - } else { - SDL_LockMutex(nscontext->swapIntervalMutex); - SDL_AtomicSet(&nscontext->swapIntervalsPassed, 0); - SDL_AtomicSet(&nscontext->swapIntervalSetting, interval); - SDL_UnlockMutex(nscontext->swapIntervalMutex); + if (interval < 0) { /* no extension for this on Mac OS X at the moment. */ + return SDL_SetError("Late swap tearing currently unsupported"); + } + + nscontext = (NSOpenGLContext*)SDL_GL_GetCurrentContext(); + if (nscontext != nil) { + value = interval; + [nscontext setValues:&value forParameter:NSOpenGLCPSwapInterval]; status = 0; + } else { + status = SDL_SetError("No current OpenGL context"); } return status; @@ -437,8 +392,17 @@ int Cocoa_GL_GetSwapInterval(_THIS) { @autoreleasepool { - SDLOpenGLContext *nscontext = (SDLOpenGLContext *) SDL_GL_GetCurrentContext(); - return nscontext ? SDL_AtomicGet(&nscontext->swapIntervalSetting) : 0; + NSOpenGLContext *nscontext; + GLint value; + int status = 0; + + nscontext = (NSOpenGLContext*)SDL_GL_GetCurrentContext(); + if (nscontext != nil) { + [nscontext getValues:&value forParameter:NSOpenGLCPSwapInterval]; + status = (int)value; + } + + return status; }} int @@ -447,25 +411,6 @@ Cocoa_GL_SwapWindow(_THIS, SDL_Window * window) { SDLOpenGLContext* nscontext = (SDLOpenGLContext*)SDL_GL_GetCurrentContext(); SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata; - const int setting = SDL_AtomicGet(&nscontext->swapIntervalSetting); - - if (setting == 0) { - /* nothing to do if vsync is disabled, don't even lock */ - } else if (setting < 0) { /* late swap tearing */ - SDL_LockMutex(nscontext->swapIntervalMutex); - while (SDL_AtomicGet(&nscontext->swapIntervalsPassed) == 0) { - SDL_CondWait(nscontext->swapIntervalCond, nscontext->swapIntervalMutex); - } - SDL_AtomicSet(&nscontext->swapIntervalsPassed, 0); - SDL_UnlockMutex(nscontext->swapIntervalMutex); - } else { - SDL_LockMutex(nscontext->swapIntervalMutex); - do { /* always wait here so we know we just hit a swap interval. */ - SDL_CondWait(nscontext->swapIntervalCond, nscontext->swapIntervalMutex); - } while ((SDL_AtomicGet(&nscontext->swapIntervalsPassed) % setting) != 0); - SDL_AtomicSet(&nscontext->swapIntervalsPassed, 0); - SDL_UnlockMutex(nscontext->swapIntervalMutex); - } /* on 10.14 ("Mojave") and later, this deadlocks if two contexts in two threads try to swap at the same time, so put a mutex around it. */