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)
This commit is contained in:
Ryan C. Gordon 2019-06-11 16:19:01 -04:00
parent 39733dc6b9
commit 04b50f6c6b
2 changed files with 24 additions and 84 deletions

View File

@ -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

View File

@ -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. */