I've just run some more tests and there is a slight inaccuracy in my previous post; the OpenGL "Invalid operation (1282)" error occurs any time after I try to switch the context in the new thread.
Here is the code where I save the current context in the main thread:
1
| OpenGL.setContext(Display.getContext()); |
Where this 'OpenGL' context just basically holds an Object and returns it when it's asked; this is the object that grabs hold of the context and passes it between threads.
When the new thread begins, here is the code that restores the context:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public void run() { try { GLContext.useContext(OpenGL.getContext()); } catch(LWJGLException ex) { finished = true; return; } Util.checkGLError(); |
Calling Util.checkGLError() immediately before starting the new thread produces no OpenGL errors. After the thread is created, no OpenGL or Display-modifying functions are called in the main thread, so this is not the source of the errors (I've checked thoroughly with Util.checkGLError()). However, as soon as I set the OpenGL context with the above code, this is where the OpenGL error starts appearing.
[EDIT]
I'm very sorry to keep messing around like this, but I seem to be more awake than I was at 4:30 last night when I came up with the idea of what was going wrong. I have just been experimenting even more and discovered this:
1) The Display -is- accessible through all Threads, so sorry about the subject of this thread. I hadn't tested it correctly.
2) I've discovered exactly which part of the program is going wrong: here is more info...
From the stack trace, the origin of the null pointer exception is in GL11.java on line 1839:
1
| long function_pointer = GLContext.getCapabilities().GL11_glGetError_pointer; |
So to test out the exception and get things clear, I have changed my thread entry point code to this:
1 2 3 4 5 6 7 8 9
| public void run() { try { Keyboard.create(); } catch(LWJGLException ex) { ex.printStackTrace(); } if(GLContext.getCapabilities() == null) System.out.println("it was null."); Util.checkGLError(); |
Display.create() was called in a different thread (the Display -has- been created upon entering the thread with the code shown above). Inside the thread where Display.create() was called, GLContext.getCapabilities()
is not null.
Now, I think I have discovered exactly what I am trying to do (so sorry once again for changing my mind about the problem so many times): I need to be able to access the same GL context throughout all of my threads, rather than each Thread keeping its own copy. If my understanding is correct, the GLContext object is thread local, so each time a new Thread accesses the GLContext.getCapabilities() method, the capabilities created inside that thread are returned. In my case, I'm calling GLContext.getCapabilities (implicitly through Util.checkGLError()) inside a thread which has -not- (and cannot) call Display.create().
So, now I believe the clear question that I am asking is this: how can I maintain the same GLContext throughout all Threads? I have a feeling that doing something similar to this is an incorrect way of going about it:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public void run() { try { GLContext.useContext(Display.getContext()); } catch(LWJGLException ex) { ex.printStackTrace(); } if(GLContext.getCapabilities() == null) System.out.println("it was null."); Util.checkGLError(); |
While using this line of code, it
does stop the null pointer exceptions (and the test for GLContext.getCapabilities() is now -not- null), I end up receiving this error when calling Util.checkGLError(): "
Exception in thread "Thread-0" org.lwjgl.opengl.OpenGLException: Invalid operation (1282) at org.lwjgl.opengl.Util.checkGLError(Util.java:56)".
Hopefully I've now got my question clear; once again, sorry for the lack of clarity in my previous posts.
[/EDIT]