First of all, previous knowledge:
The device context HDC and the render context HGLRC are created on the message thread.
→ juce_opengl\native\juce_OpenGL_win32.h : OpenGLContext::NativeContext
Then a threadpool with one job acquires the MessageManager lock, per frame, and renders the components. → juce_opengl\opengl\juce_OpenGLContext.cpp : OpenGLContext::CachedImage::renderFrame()
So at least two threads are involved. It was abstracted this way because Android (and iOS?) require an extra render thread.
Now, I could have sworn, last time I checked it was necessary to call both wglMakeCurrent(dc, renderContext) and wglMakeCurrent(nullptr, nullptr) per frame.
But looking at it now with some debug messages:
static void deactivateCurrentContext()
{
DBG("Thread ID " + String((intptr_t)Thread::getCurrentThreadId()) + " : wglMakeCurrent (nullptr, nullptr)");
wglMakeCurrent (nullptr, nullptr);
}
bool makeActive() const noexcept
{
DBG("Thread ID " + String((intptr_t)Thread::getCurrentThreadId()) + " : wglMakeCurrent (dc, renderContext)");
return isActive() || wglMakeCurrent (dc, renderContext) != FALSE;
}
The output is this:
25448 = Message Thread
29580 = GL Render Thread
Thread ID 25448 : wglMakeCurrent (dc, renderContext)
Thread ID 25448 : wglMakeCurrent (nullptr, nullptr)
Thread ID 29580 : wglMakeCurrent (dc, renderContext)
Thread ID 29580 : wglMakeCurrent (nullptr, nullptr)
Thread ID 29580 : wglMakeCurrent (dc, renderContext)
Thread ID 29580 : wglMakeCurrent (nullptr, nullptr)
Thread ID 29580 : wglMakeCurrent (dc, renderContext)
Thread ID 29580 : wglMakeCurrent (nullptr, nullptr)
Thread ID 29580 : wglMakeCurrent (dc, renderContext)
Thread ID 29580 : wglMakeCurrent (nullptr, nullptr)
...
Even on window resize or close, after the initial setup of 25448, it’s only used by 29580. Which means all the acquisition is unnecessary, right? At least it seems that way, or are there cases where the message thread could/must suddenly intervene without waiting?
Now, one could argue: “But what about multiple windows!?”
Well, you can only attach one OpenGLContext to one Component at a time. And it’s mostly the TopLevelWindow. If multiple windows are used, and no sharing is required, each root component can and should use its own OpenGLContext.
The question is, when can multiple threads call wglMakeCurrent with the same render context? Is this really possible right now? Is it only done this way for the rare case of sharing context resources?
@reuk