As for the explanation
There are several multithreading constraints while communicating with OpenGL. For one there has to be a so called OpenGL “context” in a state that allows to call OpenGL functions.
JOGL handles this constraints by providing the GLEventListener callbacks. The JOGL framework ensures, that the given GL object can successfully call the native OpenGL functions for the time the GLEventListener interface methods are executed. This is the very reason why the GLAutoDrawable object is passed as the methods argument instead of providing a gobal “getGL()” method or something.
If you store the GL object you get in the GLEventListener method, there is a good chance, that the OpenGL context is not in the right state the next time you call a method on the GL object, so your call will fail. Best practice is, not to store the GL object and implement some kind of action queue to defer OpenGL calls to the display() method. I use a simple GLAction interface for that:
public interface GLAction
{
public void execute(GL target);
}
and store instances of them in a GLQueue singleton:
public class GLQueue
{
private static GLQueue instance = null;
private final ArrayList queue= new ArrayList(16);
protected GLQueue(){}
public static synchronized GLQueue getInstance()
{
if(instance==null) instance= new GLQueue();
return instance;
}
public void add(GLAction action)
{
synchronized (queue) { queue.add(action); }
}
public void execute(GL gl)
{
// make a copy of the queue to allow thread safe iteration
ArrayList temp = null;
synchronized (queue)
{
// Only make a copy, if the queue has entries
if( queue.size() != 0 )
{
temp = new ArrayList(queue);
queue.clear();
}
}
// iterate outside of the synchronization to avoid blocking the queue
if( temp!=null )
{
for (int i=0; i < temp.size();i++)
{
((GLAction) temp.get(i)).execute(gl);
}
}
}
}
so each time, I have to react to a button-press or something I add it to the queue:
public void actionPerformed(ActionEvent event)
{
GLQueue.getInstance().add(
new GLAction()
{
public void execute(GL target)
{
// do something gl related
}
}
)
}
and execute the queue in my display-method:
public void display(GLAutoDrawable drawable)
{
GLQueue.getInstance().execute(drawable.getGL());
}
There are mechanisms in the new JSR version of JOGL to allow for more control over context and threading behaviour, but I suggest only to touch them, if you reach expert level or really have to for some reasons 