From 309d6137aee5cb406b9371d6bf6c80d8b09a41ca Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Tue, 7 Apr 2020 14:01:25 -0400 Subject: [PATCH] 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 | 2 ++ src/video/cocoa/SDL_cocoaopengl.m | 38 ++++++++++++++++++++++--------- 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/src/video/cocoa/SDL_cocoaopengl.h b/src/video/cocoa/SDL_cocoaopengl.h index 5debd2331..bae8ce48a 100644 --- a/src/video/cocoa/SDL_cocoaopengl.h +++ b/src/video/cocoa/SDL_cocoaopengl.h @@ -49,6 +49,8 @@ struct SDL_GLDriverData - (void)scheduleUpdate; - (void)updateIfNeeded; - (void)setWindow:(SDL_Window *)window; +- (SDL_Window*)window; +- (void)explicitUpdate; @end diff --git a/src/video/cocoa/SDL_cocoaopengl.m b/src/video/cocoa/SDL_cocoaopengl.m index c4db2565b..257f1a5c5 100644 --- a/src/video/cocoa/SDL_cocoaopengl.m +++ b/src/video/cocoa/SDL_cocoaopengl.m @@ -63,14 +63,10 @@ /* This should only be called on the thread on which a user is using the context. */ - (void)updateIfNeeded { - int value = SDL_AtomicSet(&self->dirty, 0); + const int value = SDL_AtomicSet(&self->dirty, 0); if (value > 0) { /* We call the real underlying update here, since -[SDLOpenGLContext update] just calls us. */ - if ([NSThread isMainThread]) { - [super update]; - } else { - [super performSelectorOnMainThread:@selector(update) withObject:nil waitUntilDone:NO]; - } + [self explicitUpdate]; } } @@ -119,9 +115,13 @@ } if ([self view] != contentview) { - [self setView:contentview]; + if ([NSThread isMainThread]) { + [self setView:contentview]; + } else { + dispatch_sync(dispatch_get_main_queue(), ^{ [self setView:contentview]; }); + } if (self == [NSOpenGLContext currentContext]) { - [self update]; + [self explicitUpdate]; } else { [self scheduleUpdate]; } @@ -129,13 +129,27 @@ } else { [self clearDrawable]; if (self == [NSOpenGLContext currentContext]) { - [self update]; + [self explicitUpdate]; } else { [self scheduleUpdate]; } } } +- (SDL_Window*)window +{ + return self->window; +} + +- (void)explicitUpdate +{ + if ([NSThread isMainThread]) { + [super update]; + } else { + dispatch_sync(dispatch_get_main_queue(), ^{ [super update]; }); + } +} + @end @@ -352,8 +366,10 @@ Cocoa_GL_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context) { if (context) { SDLOpenGLContext *nscontext = (SDLOpenGLContext *)context; - [nscontext setWindow:window]; - [nscontext updateIfNeeded]; + if ([nscontext window] != window) { + [nscontext setWindow:window]; + [nscontext updateIfNeeded]; + } [nscontext makeCurrentContext]; } else { [NSOpenGLContext clearCurrentContext];