I’m trying to port a program from Java3D to JOGL, and I believe I’m running into a threading issue. I’m running JOGL 1.1 beta 5 under MacOS X 10.3.5 with Java 1.4.2_05 and an ATI Radeon 9000 Pro graphics card.
As it stands, my program dies with a bus error in glClear(), according to Apple’s crash reporter, as follows:
Thread 13 Crashed:
0 libGL.dylib 0x90c30f88 glClear + 0x54
1 libjogl.jnilib 0x09f9dce0 Java_net_java_games_jogl_impl_macosx_MacOSXGLImpl_glClear + 0x28
2 <<00000000>> 0x03f33580 0 + 0x3f33580
3 <<00000000>> 0x03f2d310 0 + 0x3f2d310
4 <<00000000>> 0x03f2cfb0 0 + 0x3f2cfb0
5 <<00000000>> 0x03f2cfb0 0 + 0x3f2cfb0
6 <<00000000>> 0x03f2d310 0 + 0x3f2d310
7 <<00000000>> 0x03f2a16c 0 + 0x3f2a16c
8 libclient.dylib 0x9473dff8 JVM_GetCPMethodClassNameUTF + 0xb38
9 libclient.dylib 0x9475f448 JVM_GetCPClassNameUTF + 0x998
10 libclient.dylib 0x9479c0a8 JVM_Close + 0x4b8
11 libclient.dylib 0x947ac970 JVM_Interrupt + 0x2e0
12 libclient.dylib 0x9485170c JVM_UnloadLibrary + 0xcdec
13 libclient.dylib 0x94797e04 JVM_FindClassFromClass + 0xc14
14 libclient.dylib 0x948f590c JVM_UnloadLibrary + 0xb0fec
15 libSystem.B.dylib 0x900246e8 _pthread_body + 0x28
My guess is that glClear() works perfectly fine and that the real problem lies in the particular architecture of my program, which is somehow incompatible with JOGL. I have two threads, the main thread and a rendering thread. The main thread is the registered GLEventListener, but it delegates all rendering to the rendering thread. However, this delegation happens indirectly and asynchronously, in that the main thread simply notifies the rendering thread that a certain action (e.g., refreshing the display) must be taken. When notified of an action to perform, the rendering thread obtains the GL context from the GLCanvas it has a reference to and begins issuing OpenGL commands. The above bus error is simply occurring in one of the first few (if not the first) OpenGL command issued by the rendering thread. Note that the rendering thread never renders into the GL context until notified by the GLEventListener.
My question is, why doesn’t this work? Must any rendering be done with the exact GLDrawable passed to the GLEventListener? Is there no way to do the rendering in another thread outside of GLEventListener.display()? I really don’t want to have to restructure the architecture so that all rendering is done in a single call to display(), since a single frame may take 30 seconds or more to render (think visualization rather than gaming). The Java3D version uses a rendering thread separate from the UI (mouse & menu handling) thread to progressively draw the display while maintaining full interactivity; that is, the user can change the viewpoint or make other adjustments to the visualization at any time while a frame is being rendered (rendering happens initially on the back buffer, but if the frame is taking too long to draw, I swap buffers and continue rendering into the front buffer, so that the user can see the display building up incrementally). Basically, I want the rendering thread running continuously while being responsive to user requests.
I saw someone once suggest never returning from GLEventListener.display(), but doesn’t that block the “system” thread that called display() and thus prevent the issuance of other JOGL events like reshape() in the future? (Here, I’m thinking of how the current AWT event dispatch works.) Using the Animator class doesn’t seem to be the solution, since all it does is repeatedly call display() (or am I missing something?), which means that while display() is executing, no further JOGL events are issued.
I did try calling GLCanvas.setAutoSwapBufferMode(false) and setNoAutoRedrawMode(true) during program initialization, to no avail.
Could someone shed some light on what JOGL permits as far as threading is concerned?