The only right way to initialize opengl contexts is when the rest of the gui init is done (ie it cannot be done in the component’s constructor). This is because of the aweful win32 opengl implementation that juce nicely trying to hide.
Anyway, while playing around with your code, I found some of the problems you were talking about, mainly due to Win32ComponentPeer being not thread safe when interacting with the gui, some of these may be fixed so that initialization can be done anytime.
However this is not a major problem, because if you do a serious opengl application, you surely want to control exactly when threads get started and stopped, and when the opengl contexts get created and destroyed, and it’s ok to be forced to do it outside of the constructor / desctrutor.
If jules doesn’t decide to change this behavior, the context must created after any makeVisible / addChildComponent / setSize / … that might have some undesirable effects on the component peer,
the best solution is to do all the gui operations you want to set it up, and then start your rendering thread, which will let the context be created on the first makeCurrentContextActive() call.
stopThread() must also be called before any attempt to remove the component from its parent.
I also did some tests for multiple contexts in multiple threads because I need this for my application, and the surprise is that you can’t initialize multiple opengl contexts in the same time, mainly because some global variables that are not intended to be used from multiple threads.
below is a patch that made it work on my machine, but I don’t think it’s complete, and I don’t know if it is the real solution … is it jules ?
If you want to make some crash-tests and have a chance to make your graphic card burn, just increase the number of created contexts by changing the number here :
//MainAppWindow.cpp:52
// This creates a 8x6 grid of OpenGLComponentWithFps
ComponentArray <OpenGLComponentWithFps> * content = new ComponentArray <OpenGLComponentWithFps> (8, 6);
you can get the modified version here
just extract it in juce’s ‘extra’ directory, I included a project file for visual studio 2005.
the patch for multiple context initialization :
[code]Index: src/juce_appframework/events/juce_MessageManager.h
— src/juce_appframework/events/juce_MessageManager.h (revision 338)
+++ src/juce_appframework/events/juce_MessageManager.h (working copy)
@@ -199,7 +199,7 @@
friend class ActionBroadcaster;
static MessageManager* instance;
- SortedSet<const MessageListener*> messageListeners;
-
SortedSet<const MessageListener*, CriticalSection> messageListeners;
ActionListenerList* broadcastListeners;
friend class JUCEApplication;
Index: src/juce_appframework/events/juce_Timer.cpp
===================================================================
— src/juce_appframework/events/juce_Timer.cpp (revision 338)
+++ src/juce_appframework/events/juce_Timer.cpp (working copy)
@@ -323,7 +323,8 @@
//==============================================================================
#ifdef JUCE_DEBUG
-static SortedSet <Timer*> activeTimers;
+static SortedSet <Timer*, CriticalSection> activeTimers; // add Critical section cause this code is called by
#endif
Timer::Timer() throw()
Index: src/juce_appframework/gui/components/special/juce_OpenGLComponent.cpp
— src/juce_appframework/gui/components/special/juce_OpenGLComponent.cpp (revision 338)
+++ src/juce_appframework/gui/components/special/juce_OpenGLComponent.cpp (working copy)
@@ -69,7 +69,7 @@
}
//==============================================================================
-static VoidArray knownContexts;
+static Array <void*, CriticalSection> knownContexts;
OpenGLContext::OpenGLContext() throw()
{
Index: src/juce_appframework/gui/components/windows/juce_ComponentPeer.cpp
— src/juce_appframework/gui/components/windows/juce_ComponentPeer.cpp (revision 338)
+++ src/juce_appframework/gui/components/windows/juce_ComponentPeer.cpp (working copy)
@@ -59,7 +59,8 @@
static const int fakeMouseMoveMessage = 0x7fff00ff;
-static VoidArray heavyweightPeers (4);
+static Array <void*, CriticalSection> heavyweightPeers (4); // add a critical section cause it is used by getPeer() which
//==============================================================================
[/code]