macOS: Guard non-reentrant uses of NSOpenGLContext

NSOpenGLContext should be re-entrant, but is not in practice, resulting
in deadlocks when there are two render threads, eg:

 thread #23, name = 'QSGRenderThread'
    frame #0: 0x00007fff5c6dda4e libsystem_kernel.dylib`__psynch_mutexwait + 10
    frame #1: 0x00007fff5c8a5b9d libsystem_pthread.dylib`_pthread_mutex_lock_wait + 83
    frame #2: 0x00007fff5c8a34c8 libsystem_pthread.dylib`_pthread_mutex_lock_slow + 253
    frame #3: 0x00007fff31ebb52e AppKit`flush_notify + 110
    frame #4: 0x00007fff3e75ee2a GLEngine`glSwap_Exec + 186
    frame #5: 0x00007fff3e740797 OpenGL`CGLFlushDrawable + 59
    frame #6: 0x00007fff31ad43ac AppKit`-[NSOpenGLContext flushBuffer] + 27
    ...

Task-number: QTBUG-69040
Change-Id: I6f28b4cc5faf61ae93f66353ce2abdf8c223d994
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
This commit is contained in:
Tor Arne Vestbø 2018-06-27 16:59:57 +02:00
parent 4d73ab73c8
commit 9050ce4ff5

View File

@ -117,6 +117,9 @@ static void updateFormatFromContext(QSurfaceFormat *format)
format->setProfile(QSurfaceFormat::CompatibilityProfile);
}
// NSOpenGLContext is not re-entrant (https://openradar.appspot.com/37064579)
static QMutex s_contextMutex;
QCocoaGLContext::QCocoaGLContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share,
const QVariant &nativeHandle)
: m_context(nil),
@ -248,6 +251,7 @@ void QCocoaGLContext::swapBuffers(QPlatformSurface *surface)
QWindow *window = static_cast<QCocoaWindow *>(surface)->window();
setActiveWindow(window);
QMutexLocker locker(&s_contextMutex);
[m_context flushBuffer];
}
@ -400,6 +404,7 @@ QFunctionPointer QCocoaGLContext::getProcAddress(const char *procName)
void QCocoaGLContext::update()
{
QMutexLocker locker(&s_contextMutex);
[m_context update];
}