Problems with OpenGL states

Am I crazy or is this a bug in jogl? I’m unable to enable/disable lighting in a method external to init() or display().

For example, I tried to put the following code into my keyPressed() method:


public void keyPressed(KeyEvent e)
{
switch (e.getKeyCode())
{
  case KeyEvent.VK_L:
    this.light = !this.light;
    if (light)
      gl.glEnable(GL.GL_LIGHTING);
    else
      gl.glDisable(GL.GL_LIGHTING);
    break;
}
}

(Sorry for the crazy indending, but that isn’t working right for me now, either.)

This did not function correctly. Lighting could not be toggled. But if I move the test condition into display, everything works as it should.

It’s been some years since I did OpenGL coding under C++, but I’m reasonably sure that setting states should not be limited to certain functions. It doesn’t make sense to have to enable lighting each and every frame.

You can only use gl calls in init or display methods, that is how jogl works. If you need to toggle a light just have a if/else statement in your display method that checks a boolean if the light is on or off.

That’s adding unnecessary additional tests and possibly additional function calls in the most time critical portion of the code. If I set a state, that state should be in effect until I change that state. That’s the way OpenGL was designed. Hitting that code each frame is ridiculous.

I noticed GL4Java does not have this limitation.

If this was how it was intended, this is a really bad decision. It’s going to cause the display method to become bloated and a mass of if/else statements.

You can always set an event queue that you can check in the display method for state changes such as lighting.

[quote]It’s been some years since I did OpenGL coding under C++, but I’m reasonably sure that setting states should not be limited to certain functions.
[/quote]
Not functions, threads. Poking states at GL via multiple threads is just going to cause a world of problems, which is why you can’t toggle the lighting in the AWT event thread.

Nothing stopping you creating some wrapper objects around states to enable/disable - you don’t really want a big if/else structure in your display method :stuck_out_tongue:

If everything else that wasn’t thread safe behaved as jogl does, the world would be a horrible place. :wink:

I say just let the programmer worry about synchronisation, and plaster huge red “THIS IS NOT THREAD SAFE (THAT INCLUDES THE AWT DISPATCH THREAD(S))” stickers all over jogl.

[quote]I say just let the programmer worry about synchronisation, and plaster huge red “THIS IS NOT THREAD SAFE (THAT INCLUDES THE AWT DISPATCH THREAD(S))” stickers all over jogl.
[/quote]
I agree. OpenGL is not threadsafe. It was never intended to be. In win32 for example, if you wanted to work with multiple threads you had to request the rendering context.

I really dislike the idea that yet again I don’t really have access to OpenGL via Java. I’ve got Sun’s idea of how OpenGL should behave with Java. What other surprises await me? What else can I only do in certain methods? And yes, I mean methods. From the statements above, it doesn’t appear to me that adding my own synchronization blocks will help the situation. If I’m wrong, please point me to an example.

Maybe I’m just not seeing it. It was too late last night when I started this thread and it’s too early this morning to be continuing it.

[quote] I really dislike the idea that yet again I don’t really have access to OpenGL via Java.
[/quote]
You can try LWJGL, you just won’t have AWT/Swing elements at your desposal. But it might be more in line of what you want.

What is the problem? There exists a GL rendering thread, which is the only valid thread for operating on the GL state. This thread has callbacks which it triggers, the Animator methods like .display being prime examples.

You can’t just chuck extra syncronisation blocks in and expect it to magically work, because as you metion under the hood you need the calls to makeCurrent to set the thread which is valid for GL. As far as i know, the make current calls have been deliberatly not exposed to make the rendering play nice with AWT & Swing.

You seem intent on making a mountain out of a molehill, you dont need (or indeed want) to tinker with GL state from more than one thread.

What can I say? I’m a short guy. Mole hills look rather large from my level. ;D

I’d still like to see an example of the jogl way. Is there one someone can point to?

The JOGL demos (http://jogl-demos.dev.java.net/) contain some examples of proper mouse and keyboard interaction.

As it’s stated in chapter one of The OpenGL Programming Guide (the red book), OpenGL is a state machine. You put it into various states (or modes) that then remain in effect until you change them.

I’m not seeing anything in the examples that describes the situation I’m looking to solve. There is quite a bit of mouse and keyboard interaction, but there isn’t anything that illustrates switching a state variable without cluttering the display method.

For example, infiniteShadowVolumes.java, line #305 in the Sept. 5th code shows toggling a state. There is a lot of test code around the state changes to avoid making the call to gl if it’s not necessary – that’s good. That the display method is performing this test to begin with – that’s bad.

So, I see this method as a possible solution, but a messy one. To accomodate multithreading, I have to create two watcher variables and add additional test logic per state I wish to change. :-/

Full circle again eh? If contexts are exposed you will be able to set a state where ever you want possible incurring a hefty onetime penalty for context switching. The penalty of checking a few bools every frame is incredibly small compared to the time it actually takes to draw the frame. I implemented lesson07 with an eventqueue and I got the same fps. I noticed in you lesson07 port that you are not tracking whether a button is held down or not. That seems to be a sticky point for newbs.

An eventqueue seems the only really nice solution to the multithreading problem. And it is nothing new to Swing developers … :smiley:

But I have a question about it. When I implement an eventqueue that gets emptied and executed in the display-method this access (dispatch) has to be synchronized with the method that is adding the elements (invokeLater). the problem is: when invokeLater is called from AWTEvent-Thread it freezes the gui because the ‘dispatch’-Method gets the lock more often.

I already tried to start a new thread inside invokeLater that does the actual adding operation to the queue and minimized locking operations in the display method by using a volatile boolean that is set by invokeLater after an element is added. The situation got better but not good enough.

Is there a good solution to this problem?

[quote]I noticed in you lesson07 port that you are not tracking whether a button is held down or not. That seems to be a sticky point for newbs.
[/quote]
That’s correct. I chose not to because someone was getting different behavior under Linux. I’ve since found out that they were running an older version of the JDK and after they upgraded to 1.4.2, the issue went away. By then, however, I’d already posted my code with changes.

And I agree that the test for the booleans isn’t very significant. If the state changes often, it’s far less of an impact to test a boolean than it is to make a function call. Or, for that matter, lock and unlock the thread. But if the state changes rarely, which is more optimal? I’m not sure.

You should be doing as little as possible in the event dispatch thread. Basically generating a small message, pregenerated if possible. Your main display thread should do most of the work that will minimize gui stalling. I am not sure if I am understanding this right but you are in the event dispatch thread and calling invokelater to create a new thread? That will be very slow.

Maybe it was a bit unclear: The invokeLater I mentioned is my own implementation. It stores a Runnable in a list to get executed inside the display method.

I didn’t use a runnable. Here are the event classes I used for the lesson7 example. I didn’t use any runnable. I just sync the event queue whilst adding in the keylistener methods and in the display loop. Even without syncing I can usually hold down a couple keys for 10 seconds or so before I get a concurrent modification exception.


abstract class GLEvent extends EventObject {
            
            public GLEvent( Object source ) {
                  super( source );
            }
            
            abstract public void stateChange( GL gl );
      }
      
      class GLLightEvent extends GLEvent {
            
            private boolean light = false;
            
            public GLLightEvent( Object source ) {
                  super( source );
            }
            
            public void stateChange( GL gl ) {
                  if( light ) {
                        gl.glEnable( GL.GL_LIGHTING );
                  } else {
                        gl.glDisable( GL.GL_LIGHTING );
                  }
            }
            
            public void toggleLight() {
                  light = !light;
            }
            
            public void lightOn( boolean b ) {
                  light = b;
            }
            
            public boolean lightOn() {
                  return( light );
            }
      }
      
      class GLFilterEvent extends GLEvent {
            
            private int filter = 0;
            private int texture = 0;
            
            public GLFilterEvent( Object source ) {
                  super( source );
            }
            
            public void stateChange( GL gl ) {
                  gl.glBindTexture( GL.GL_TEXTURE_2D, texture );
            }
            
            public void setFilter( int f ) {
                  filter = f;
            }
            
            public void setTexture( int t ) {
                  texture = t;
            }
      }

Sorry, just catching up with this thread as I am new to this site.

I thought GL4Java DID have the same limitation. While testing it, I found the to be true between both JOGL and GL4Java.

My information was based on looking at the GL4Java NeHe ports and specific to my problem with changing a state. Jeff Kirby’s code did not get the current context before changing a state. At best, that’ll produce unknown results and possibly a ConcurrentModificationException. Or worse yet, an exception outside of the VM because the context was current. In my own case, I was finding the state to be immutable.