Browse Source

OpenGL: Ensure flushBuffer can't be called simultaneously from multiple threads on macOS 10.13 or earlier

On these platforms, calling flushBuffer from multiple threads
simultaneously will lead to deadlocks.
v7.0.9
reuk 2 years ago
parent
commit
c08a1827b5
No known key found for this signature in database GPG Key ID: FCB43929F012EE5C
1 changed files with 64 additions and 31 deletions
  1. +64
    -31
      modules/juce_opengl/opengl/juce_OpenGLContext.cpp

+ 64
- 31
modules/juce_opengl/opengl/juce_OpenGLContext.cpp View File

@@ -186,12 +186,22 @@ public:
{
renderThread->remove (this);
if ((state.fetch_and (~StateFlags::initialised) & StateFlags::initialised) != 0)
{
context.makeActive();
shutdownOnThread();
OpenGLContext::deactivateCurrentContext();
}
if ((state.fetch_and (~StateFlags::initialised) & StateFlags::initialised) == 0)
return;
ScopedContextActivator activator;
activator.activate (context);
if (context.renderer != nullptr)
context.renderer->openGLContextClosing();
if (vertexArrayObject != 0)
context.extensions.glDeleteVertexArrays (1, &vertexArrayObject);
associatedObjectNames.clear();
associatedObjects.clear();
cachedImageFrameBuffer.release();
nativeContext->shutdownOnRenderThread();
}
void resume()
@@ -375,12 +385,12 @@ public:
abortScope = true;
}
if (! contextActivator.activate (context))
return RenderStatus::noWork;
{
NativeContext::Locker locker (*nativeContext);
if (! contextActivator.activate (context))
return RenderStatus::noWork;
JUCE_CHECK_OPENGL_ERROR
doWorkWhileWaitingForLock (contextActivator);
@@ -416,7 +426,7 @@ public:
}
}
nativeContext->swapBuffers();
bufferSwapper.swap();
return RenderStatus::nominal;
}
@@ -520,9 +530,6 @@ public:
paintOwner (*g);
JUCE_CHECK_OPENGL_ERROR
}
if (! context.isActive())
context.makeActive();
}
JUCE_CHECK_OPENGL_ERROR
@@ -667,20 +674,6 @@ public:
return InitResult::success;
}
void shutdownOnThread()
{
if (context.renderer != nullptr)
context.renderer->openGLContextClosing();
if (vertexArrayObject != 0)
context.extensions.glDeleteVertexArrays (1, &vertexArrayObject);
associatedObjectNames.clear();
associatedObjects.clear();
cachedImageFrameBuffer.release();
nativeContext->shutdownOnRenderThread();
}
/* Returns true if the context requires a non-zero vertex array object (VAO) to be bound.
If the context is a compatibility context, we can just pretend that VAOs don't exist,
@@ -840,7 +833,6 @@ public:
case RenderStatus::nominal: result = RenderStatus::nominal; break;
case RenderStatus::messageThreadAborted: return RenderStatus::messageThreadAborted;
}
}
return result;
@@ -950,6 +942,49 @@ public:
#endif
}
//==============================================================================
class BufferSwapper : private AsyncUpdater
{
public:
explicit BufferSwapper (CachedImage& img)
: image (img) {}
~BufferSwapper() override
{
cancelPendingUpdate();
}
void swap()
{
static const auto swapBuffersOnMainThread = []
{
const auto os = SystemStats::getOperatingSystemType();
if ((os & SystemStats::MacOSX) != 0)
return (os != SystemStats::MacOSX && os < SystemStats::MacOSX_10_14);
return false;
}();
if (swapBuffersOnMainThread && ! MessageManager::getInstance()->isThisTheMessageThread())
triggerAsyncUpdate();
else
image.nativeContext->swapBuffers();
}
private:
void handleAsyncUpdate() override
{
ScopedContextActivator activator;
activator.activate (image.context);
NativeContext::Locker locker (*image.nativeContext);
image.nativeContext->swapBuffers();
}
CachedImage& image;
};
//==============================================================================
friend class NativeContext;
std::unique_ptr<NativeContext> nativeContext;
@@ -977,6 +1012,7 @@ public:
#endif
bool textureNpotSupported = false;
std::chrono::steady_clock::time_point lastMMLockReleaseTime{};
BufferSwapper bufferSwapper { *this };
#if JUCE_MAC
NSView* getCurrentView() const
@@ -1055,9 +1091,6 @@ public:
pendingDestruction = 1 << 2,
initialised = 1 << 3,
// Flags that may change state after each frame
transient = pendingRender | paintComponents,
// Flags that should retain their state after each frame
persistent = initialised | pendingDestruction
};


Loading…
Cancel
Save