cocoa: OpenGL setView and update must be used on main thread (thanks, Tim!).
authorRyan C. Gordon
Tue, 07 Apr 2020 14:01:25 -0400
changeset 1370319c4516de68d
parent 13702 1463104b6302
child 13704 25edf3df6e51
cocoa: OpenGL setView and update must be used on main thread (thanks, Tim!).

If called from background threads, use Grand Central Dispatch to use the
main thread instead. On the main thread, just call them directly.

Fixes Bugzilla #4932.
src/video/cocoa/SDL_cocoaopengl.h
src/video/cocoa/SDL_cocoaopengl.m
     1.1 --- a/src/video/cocoa/SDL_cocoaopengl.h	Tue Apr 07 13:49:19 2020 -0400
     1.2 +++ b/src/video/cocoa/SDL_cocoaopengl.h	Tue Apr 07 14:01:25 2020 -0400
     1.3 @@ -49,6 +49,8 @@
     1.4  - (void)scheduleUpdate;
     1.5  - (void)updateIfNeeded;
     1.6  - (void)setWindow:(SDL_Window *)window;
     1.7 +- (SDL_Window*)window;
     1.8 +- (void)explicitUpdate;
     1.9  
    1.10  @end
    1.11  
     2.1 --- a/src/video/cocoa/SDL_cocoaopengl.m	Tue Apr 07 13:49:19 2020 -0400
     2.2 +++ b/src/video/cocoa/SDL_cocoaopengl.m	Tue Apr 07 14:01:25 2020 -0400
     2.3 @@ -63,14 +63,10 @@
     2.4  /* This should only be called on the thread on which a user is using the context. */
     2.5  - (void)updateIfNeeded
     2.6  {
     2.7 -    int value = SDL_AtomicSet(&self->dirty, 0);
     2.8 +    const int value = SDL_AtomicSet(&self->dirty, 0);
     2.9      if (value > 0) {
    2.10          /* We call the real underlying update here, since -[SDLOpenGLContext update] just calls us. */
    2.11 -        if ([NSThread isMainThread]) {
    2.12 -            [super update];
    2.13 -        } else {
    2.14 -            [super performSelectorOnMainThread:@selector(update) withObject:nil waitUntilDone:NO];
    2.15 -        }
    2.16 +        [self explicitUpdate];
    2.17      }
    2.18  }
    2.19  
    2.20 @@ -119,9 +115,13 @@
    2.21          }
    2.22  
    2.23          if ([self view] != contentview) {
    2.24 -            [self setView:contentview];
    2.25 +            if ([NSThread isMainThread]) {
    2.26 +                [self setView:contentview];
    2.27 +            } else {
    2.28 +                dispatch_sync(dispatch_get_main_queue(), ^{ [self setView:contentview]; });
    2.29 +            }
    2.30              if (self == [NSOpenGLContext currentContext]) {
    2.31 -                [self update];
    2.32 +                [self explicitUpdate];
    2.33              } else {
    2.34                  [self scheduleUpdate];
    2.35              }
    2.36 @@ -129,13 +129,27 @@
    2.37      } else {
    2.38          [self clearDrawable];
    2.39          if (self == [NSOpenGLContext currentContext]) {
    2.40 -            [self update];
    2.41 +            [self explicitUpdate];
    2.42          } else {
    2.43              [self scheduleUpdate];
    2.44          }
    2.45      }
    2.46  }
    2.47  
    2.48 +- (SDL_Window*)window
    2.49 +{
    2.50 +    return self->window;
    2.51 +}
    2.52 +
    2.53 +- (void)explicitUpdate
    2.54 +{
    2.55 +    if ([NSThread isMainThread]) {
    2.56 +        [super update];
    2.57 +    } else {
    2.58 +        dispatch_sync(dispatch_get_main_queue(), ^{ [super update]; });
    2.59 +    }
    2.60 +}
    2.61 +
    2.62  @end
    2.63  
    2.64  
    2.65 @@ -352,8 +366,10 @@
    2.66  {
    2.67      if (context) {
    2.68          SDLOpenGLContext *nscontext = (SDLOpenGLContext *)context;
    2.69 -        [nscontext setWindow:window];
    2.70 -        [nscontext updateIfNeeded];
    2.71 +        if ([nscontext window] != window) {
    2.72 +            [nscontext setWindow:window];
    2.73 +            [nscontext updateIfNeeded];
    2.74 +        }
    2.75          [nscontext makeCurrentContext];
    2.76      } else {
    2.77          [NSOpenGLContext clearCurrentContext];