cocoa: Backed out CVDisplayLink code for macOS vsync.
authorRyan C. Gordon <icculus@icculus.org>
Tue, 11 Jun 2019 16:19:01 -0400
changeset 128401b6f67e84802
parent 12839 1b94a9e6746e
child 12841 8a0e446a4cf9
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 73f3ca85ac0e)
src/video/cocoa/SDL_cocoaopengl.h
src/video/cocoa/SDL_cocoaopengl.m
     1.1 --- a/src/video/cocoa/SDL_cocoaopengl.h	Tue Jun 11 19:58:10 2019 -0700
     1.2 +++ b/src/video/cocoa/SDL_cocoaopengl.h	Tue Jun 11 16:19:01 2019 -0400
     1.3 @@ -36,11 +36,6 @@
     1.4  @interface SDLOpenGLContext : NSOpenGLContext {
     1.5      SDL_atomic_t dirty;
     1.6      SDL_Window *window;
     1.7 -    CVDisplayLinkRef displayLink;
     1.8 -    @public SDL_mutex *swapIntervalMutex;
     1.9 -    @public SDL_cond *swapIntervalCond;
    1.10 -    @public SDL_atomic_t swapIntervalSetting;
    1.11 -    @public SDL_atomic_t swapIntervalsPassed;
    1.12  }
    1.13  
    1.14  - (id)initWithFormat:(NSOpenGLPixelFormat *)format
    1.15 @@ -48,7 +43,7 @@
    1.16  - (void)scheduleUpdate;
    1.17  - (void)updateIfNeeded;
    1.18  - (void)setWindow:(SDL_Window *)window;
    1.19 -- (void)dealloc;
    1.20 +
    1.21  @end
    1.22  
    1.23  
     2.1 --- a/src/video/cocoa/SDL_cocoaopengl.m	Tue Jun 11 19:58:10 2019 -0700
     2.2 +++ b/src/video/cocoa/SDL_cocoaopengl.m	Tue Jun 11 16:19:01 2019 -0400
     2.3 @@ -36,23 +36,6 @@
     2.4  
     2.5  #define DEFAULT_OPENGL  "/System/Library/Frameworks/OpenGL.framework/Libraries/libGL.dylib"
     2.6  
     2.7 -static CVReturn
     2.8 -DisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeStamp* now, const CVTimeStamp* outputTime, CVOptionFlags flagsIn, CVOptionFlags* flagsOut, void* displayLinkContext)
     2.9 -{
    2.10 -    SDLOpenGLContext *nscontext = (SDLOpenGLContext *) displayLinkContext;
    2.11 -
    2.12 -    /*printf("DISPLAY LINK! %u\n", (unsigned int) SDL_GetTicks()); */
    2.13 -    const int setting = SDL_AtomicGet(&nscontext->swapIntervalSetting);
    2.14 -    if (setting != 0) { /* nothing to do if vsync is disabled, don't even lock */
    2.15 -        SDL_LockMutex(nscontext->swapIntervalMutex);
    2.16 -        SDL_AtomicAdd(&nscontext->swapIntervalsPassed, 1);
    2.17 -        SDL_CondSignal(nscontext->swapIntervalCond);
    2.18 -        SDL_UnlockMutex(nscontext->swapIntervalMutex);
    2.19 -    }
    2.20 -
    2.21 -    return kCVReturnSuccess;
    2.22 -}
    2.23 -
    2.24  @implementation SDLOpenGLContext : NSOpenGLContext
    2.25  
    2.26  - (id)initWithFormat:(NSOpenGLPixelFormat *)format
    2.27 @@ -62,20 +45,6 @@
    2.28      if (self) {
    2.29          SDL_AtomicSet(&self->dirty, 0);
    2.30          self->window = NULL;
    2.31 -        SDL_AtomicSet(&self->swapIntervalSetting, 0);
    2.32 -        SDL_AtomicSet(&self->swapIntervalsPassed, 0);
    2.33 -        self->swapIntervalCond = SDL_CreateCond();
    2.34 -        self->swapIntervalMutex = SDL_CreateMutex();
    2.35 -        if (!self->swapIntervalCond || !self->swapIntervalMutex) {
    2.36 -            [self release];
    2.37 -            return nil;
    2.38 -        }
    2.39 -
    2.40 -        /* !!! FIXME: check return values. */
    2.41 -        CVDisplayLinkCreateWithActiveCGDisplays(&self->displayLink);
    2.42 -        CVDisplayLinkSetOutputCallback(self->displayLink, &DisplayLinkCallback, self);
    2.43 -        CVDisplayLinkSetCurrentCGDisplayFromOpenGLContext(self->displayLink, [self CGLContextObj], [format CGLPixelFormatObj]);
    2.44 -        CVDisplayLinkStart(displayLink);
    2.45      }
    2.46      return self;
    2.47  }
    2.48 @@ -145,19 +114,6 @@
    2.49      }
    2.50  }
    2.51  
    2.52 -- (void)dealloc
    2.53 -{
    2.54 -    if (self->displayLink) {
    2.55 -        CVDisplayLinkRelease(self->displayLink);
    2.56 -    }
    2.57 -    if (self->swapIntervalCond) {
    2.58 -        SDL_DestroyCond(self->swapIntervalCond);
    2.59 -    }
    2.60 -    if (self->swapIntervalMutex) {
    2.61 -        SDL_DestroyMutex(self->swapIntervalMutex);
    2.62 -    }
    2.63 -    [super dealloc];
    2.64 -}
    2.65  @end
    2.66  
    2.67  
    2.68 @@ -208,7 +164,6 @@
    2.69      const char *glversion;
    2.70      int glversion_major;
    2.71      int glversion_minor;
    2.72 -    int interval;
    2.73  
    2.74      if (_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES) {
    2.75  #if SDL_VIDEO_OPENGL_EGL
    2.76 @@ -320,10 +275,6 @@
    2.77          return NULL;
    2.78      }
    2.79  
    2.80 -    /* vsync is handled separately by synchronizing with a display link. */
    2.81 -    interval = 0;
    2.82 -    [context setValues:&interval forParameter:NSOpenGLCPSwapInterval];
    2.83 -
    2.84      if ( Cocoa_GL_MakeCurrent(_this, window, context) < 0 ) {
    2.85          Cocoa_GL_DeleteContext(_this, context);
    2.86          SDL_SetError("Failed making OpenGL context current");
    2.87 @@ -417,17 +368,21 @@
    2.88  Cocoa_GL_SetSwapInterval(_THIS, int interval)
    2.89  { @autoreleasepool
    2.90  {
    2.91 -    SDLOpenGLContext *nscontext = (SDLOpenGLContext *) SDL_GL_GetCurrentContext();
    2.92 +    NSOpenGLContext *nscontext;
    2.93 +    GLint value;
    2.94      int status;
    2.95  
    2.96 -    if (nscontext == nil) {
    2.97 +    if (interval < 0) {  /* no extension for this on Mac OS X at the moment. */
    2.98 +        return SDL_SetError("Late swap tearing currently unsupported");
    2.99 +    }
   2.100 +
   2.101 +    nscontext = (NSOpenGLContext*)SDL_GL_GetCurrentContext();
   2.102 +    if (nscontext != nil) {
   2.103 +        value = interval;
   2.104 +        [nscontext setValues:&value forParameter:NSOpenGLCPSwapInterval];
   2.105 +        status = 0;
   2.106 +    } else {
   2.107          status = SDL_SetError("No current OpenGL context");
   2.108 -    } else {
   2.109 -        SDL_LockMutex(nscontext->swapIntervalMutex);
   2.110 -        SDL_AtomicSet(&nscontext->swapIntervalsPassed, 0);
   2.111 -        SDL_AtomicSet(&nscontext->swapIntervalSetting, interval);
   2.112 -        SDL_UnlockMutex(nscontext->swapIntervalMutex);
   2.113 -        status = 0;
   2.114      }
   2.115  
   2.116      return status;
   2.117 @@ -437,8 +392,17 @@
   2.118  Cocoa_GL_GetSwapInterval(_THIS)
   2.119  { @autoreleasepool
   2.120  {
   2.121 -    SDLOpenGLContext *nscontext = (SDLOpenGLContext *) SDL_GL_GetCurrentContext();
   2.122 -    return nscontext ? SDL_AtomicGet(&nscontext->swapIntervalSetting) : 0;
   2.123 +    NSOpenGLContext *nscontext;
   2.124 +    GLint value;
   2.125 +    int status = 0;
   2.126 +
   2.127 +    nscontext = (NSOpenGLContext*)SDL_GL_GetCurrentContext();
   2.128 +    if (nscontext != nil) {
   2.129 +        [nscontext getValues:&value forParameter:NSOpenGLCPSwapInterval];
   2.130 +        status = (int)value;
   2.131 +    }
   2.132 +
   2.133 +    return status;
   2.134  }}
   2.135  
   2.136  int
   2.137 @@ -447,25 +411,6 @@
   2.138  {
   2.139      SDLOpenGLContext* nscontext = (SDLOpenGLContext*)SDL_GL_GetCurrentContext();
   2.140      SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
   2.141 -    const int setting = SDL_AtomicGet(&nscontext->swapIntervalSetting);
   2.142 -
   2.143 -    if (setting == 0) {
   2.144 -        /* nothing to do if vsync is disabled, don't even lock */
   2.145 -    } else if (setting < 0) {  /* late swap tearing */
   2.146 -        SDL_LockMutex(nscontext->swapIntervalMutex);
   2.147 -        while (SDL_AtomicGet(&nscontext->swapIntervalsPassed) == 0) {
   2.148 -            SDL_CondWait(nscontext->swapIntervalCond, nscontext->swapIntervalMutex);
   2.149 -        }
   2.150 -        SDL_AtomicSet(&nscontext->swapIntervalsPassed, 0);
   2.151 -        SDL_UnlockMutex(nscontext->swapIntervalMutex);
   2.152 -    } else {
   2.153 -        SDL_LockMutex(nscontext->swapIntervalMutex);
   2.154 -        do {  /* always wait here so we know we just hit a swap interval. */
   2.155 -            SDL_CondWait(nscontext->swapIntervalCond, nscontext->swapIntervalMutex);
   2.156 -        } while ((SDL_AtomicGet(&nscontext->swapIntervalsPassed) % setting) != 0);
   2.157 -        SDL_AtomicSet(&nscontext->swapIntervalsPassed, 0);
   2.158 -        SDL_UnlockMutex(nscontext->swapIntervalMutex);
   2.159 -    }
   2.160  
   2.161      /* on 10.14 ("Mojave") and later, this deadlocks if two contexts in two
   2.162         threads try to swap at the same time, so put a mutex around it. */