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)
parent
39733dc6b9
commit
04b50f6c6b
|
@ -36,11 +36,6 @@ struct SDL_GLDriverData
|
||||||
@interface SDLOpenGLContext : NSOpenGLContext {
|
@interface SDLOpenGLContext : NSOpenGLContext {
|
||||||
SDL_atomic_t dirty;
|
SDL_atomic_t dirty;
|
||||||
SDL_Window *window;
|
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
|
- (id)initWithFormat:(NSOpenGLPixelFormat *)format
|
||||||
|
@ -48,7 +43,7 @@ struct SDL_GLDriverData
|
||||||
- (void)scheduleUpdate;
|
- (void)scheduleUpdate;
|
||||||
- (void)updateIfNeeded;
|
- (void)updateIfNeeded;
|
||||||
- (void)setWindow:(SDL_Window *)window;
|
- (void)setWindow:(SDL_Window *)window;
|
||||||
- (void)dealloc;
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -36,23 +36,6 @@
|
||||||
|
|
||||||
#define DEFAULT_OPENGL "/System/Library/Frameworks/OpenGL.framework/Libraries/libGL.dylib"
|
#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
|
@implementation SDLOpenGLContext : NSOpenGLContext
|
||||||
|
|
||||||
- (id)initWithFormat:(NSOpenGLPixelFormat *)format
|
- (id)initWithFormat:(NSOpenGLPixelFormat *)format
|
||||||
|
@ -62,20 +45,6 @@ DisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeStamp* now, const
|
||||||
if (self) {
|
if (self) {
|
||||||
SDL_AtomicSet(&self->dirty, 0);
|
SDL_AtomicSet(&self->dirty, 0);
|
||||||
self->window = NULL;
|
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;
|
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
|
@end
|
||||||
|
|
||||||
|
|
||||||
|
@ -208,7 +164,6 @@ Cocoa_GL_CreateContext(_THIS, SDL_Window * window)
|
||||||
const char *glversion;
|
const char *glversion;
|
||||||
int glversion_major;
|
int glversion_major;
|
||||||
int glversion_minor;
|
int glversion_minor;
|
||||||
int interval;
|
|
||||||
|
|
||||||
if (_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES) {
|
if (_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES) {
|
||||||
#if SDL_VIDEO_OPENGL_EGL
|
#if SDL_VIDEO_OPENGL_EGL
|
||||||
|
@ -320,10 +275,6 @@ Cocoa_GL_CreateContext(_THIS, SDL_Window * window)
|
||||||
return NULL;
|
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 ) {
|
if ( Cocoa_GL_MakeCurrent(_this, window, context) < 0 ) {
|
||||||
Cocoa_GL_DeleteContext(_this, context);
|
Cocoa_GL_DeleteContext(_this, context);
|
||||||
SDL_SetError("Failed making OpenGL context current");
|
SDL_SetError("Failed making OpenGL context current");
|
||||||
|
@ -417,17 +368,21 @@ int
|
||||||
Cocoa_GL_SetSwapInterval(_THIS, int interval)
|
Cocoa_GL_SetSwapInterval(_THIS, int interval)
|
||||||
{ @autoreleasepool
|
{ @autoreleasepool
|
||||||
{
|
{
|
||||||
SDLOpenGLContext *nscontext = (SDLOpenGLContext *) SDL_GL_GetCurrentContext();
|
NSOpenGLContext *nscontext;
|
||||||
|
GLint value;
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
if (nscontext == nil) {
|
if (interval < 0) { /* no extension for this on Mac OS X at the moment. */
|
||||||
status = SDL_SetError("No current OpenGL context");
|
return SDL_SetError("Late swap tearing currently unsupported");
|
||||||
} else {
|
}
|
||||||
SDL_LockMutex(nscontext->swapIntervalMutex);
|
|
||||||
SDL_AtomicSet(&nscontext->swapIntervalsPassed, 0);
|
nscontext = (NSOpenGLContext*)SDL_GL_GetCurrentContext();
|
||||||
SDL_AtomicSet(&nscontext->swapIntervalSetting, interval);
|
if (nscontext != nil) {
|
||||||
SDL_UnlockMutex(nscontext->swapIntervalMutex);
|
value = interval;
|
||||||
|
[nscontext setValues:&value forParameter:NSOpenGLCPSwapInterval];
|
||||||
status = 0;
|
status = 0;
|
||||||
|
} else {
|
||||||
|
status = SDL_SetError("No current OpenGL context");
|
||||||
}
|
}
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
|
@ -437,8 +392,17 @@ int
|
||||||
Cocoa_GL_GetSwapInterval(_THIS)
|
Cocoa_GL_GetSwapInterval(_THIS)
|
||||||
{ @autoreleasepool
|
{ @autoreleasepool
|
||||||
{
|
{
|
||||||
SDLOpenGLContext *nscontext = (SDLOpenGLContext *) SDL_GL_GetCurrentContext();
|
NSOpenGLContext *nscontext;
|
||||||
return nscontext ? SDL_AtomicGet(&nscontext->swapIntervalSetting) : 0;
|
GLint value;
|
||||||
|
int status = 0;
|
||||||
|
|
||||||
|
nscontext = (NSOpenGLContext*)SDL_GL_GetCurrentContext();
|
||||||
|
if (nscontext != nil) {
|
||||||
|
[nscontext getValues:&value forParameter:NSOpenGLCPSwapInterval];
|
||||||
|
status = (int)value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
}}
|
}}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -447,25 +411,6 @@ Cocoa_GL_SwapWindow(_THIS, SDL_Window * window)
|
||||||
{
|
{
|
||||||
SDLOpenGLContext* nscontext = (SDLOpenGLContext*)SDL_GL_GetCurrentContext();
|
SDLOpenGLContext* nscontext = (SDLOpenGLContext*)SDL_GL_GetCurrentContext();
|
||||||
SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
|
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
|
/* 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. */
|
threads try to swap at the same time, so put a mutex around it. */
|
||||||
|
|
Loading…
Reference in New Issue