cocoa: Put a mutex around GL_SwapBuffers. Prevents deadlock when swapping two different GL contexts on two different threads at the same time on macOS 10.14 ("Mojave"). Fixes Bugzilla #4278.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
diff --git a/src/video/cocoa/SDL_cocoaopengl.m b/src/video/cocoa/SDL_cocoaopengl.m
index c7d0c60..9539c17 100644
--- a/src/video/cocoa/SDL_cocoaopengl.m
+++ b/src/video/cocoa/SDL_cocoaopengl.m
@@ -410,8 +410,14 @@ Cocoa_GL_SwapWindow(_THIS, SDL_Window * window)
{ @autoreleasepool
{
SDLOpenGLContext* nscontext = (SDLOpenGLContext*)SDL_GL_GetCurrentContext();
+ SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
+
+ /* 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. */
+ SDL_LockMutex(videodata->swaplock);
[nscontext flushBuffer];
[nscontext updateIfNeeded];
+ SDL_UnlockMutex(videodata->swaplock);
return 0;
}}
diff --git a/src/video/cocoa/SDL_cocoavideo.h b/src/video/cocoa/SDL_cocoavideo.h
index 05bbd34..b1c26fa 100644
--- a/src/video/cocoa/SDL_cocoavideo.h
+++ b/src/video/cocoa/SDL_cocoavideo.h
@@ -107,7 +107,7 @@ typedef struct SDL_VideoData
Uint32 screensaver_activity;
BOOL screensaver_use_iopm;
IOPMAssertionID screensaver_assertion;
-
+ SDL_mutex *swaplock;
} SDL_VideoData;
/* Utility functions */
diff --git a/src/video/cocoa/SDL_cocoavideo.m b/src/video/cocoa/SDL_cocoavideo.m
index 9770224..20bdfa7 100644
--- a/src/video/cocoa/SDL_cocoavideo.m
+++ b/src/video/cocoa/SDL_cocoavideo.m
@@ -175,15 +175,23 @@ Cocoa_VideoInit(_THIS)
/* The IOPM assertion API can disable the screensaver as of 10.7. */
data->screensaver_use_iopm = floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_6;
+ data->swaplock = SDL_CreateMutex();
+ if (!data->swaplock) {
+ return -1;
+ }
+
return 0;
}
void
Cocoa_VideoQuit(_THIS)
{
+ SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
Cocoa_QuitModes(_this);
Cocoa_QuitKeyboard(_this);
Cocoa_QuitMouse(_this);
+ SDL_DestroyMutex(data->swaplock);
+ data->swaplock = NULL;
}
/* This function assumes that it's called from within an autorelease pool */