GLContext from other classes

I have a question regarding use of the glcontext. Basically, I have a scene class which has references to the GLRenderer (a class that implements GLEventListener) and an inner classe - FogTestKeyListener which extends CustomKeyListener.

All rendering works fine, but when i click a key, I need a state change to occur within the openGL context - for example - gl.glDisable(GL.GL_LIGHTING).

The way that I construct these input classes is to pass a handle of the scene plus the glContext from the renderer (obtained by previously calling canvas.getGL().).

Find below the code for one of my inner classes:


class FogTestKeyListener extends CustomKeyListener {

      FogTestScene scene;
      GL gl;
      
      public FogTestKeyListener(GLScene scene, GL gl) {
            this.scene = (FogTestScene)scene;
            this.gl = gl;
      }

      public void keyReleased(KeyEvent evt) {

                gl.glDisable(GL.GL_LIGHTING);
            System.out.println("GL error: " + gl.glGetError());
            System.out.println("Keyboard input '" + evt.getKeyChar() + "' from " + this.getClass().getName());
      }
}

An error ‘1282’ is returned when the key is released and nothing happens with regard to the lighting - it stays enabled.

Am i doing something which isn’t possible within JOGL?

[quote]The way that I construct these input classes is to pass a handle of the scene plus the glContext from the renderer (obtained by previously calling canvas.getGL().).
[/quote]
Only one thread is valid for making gl calls from at any one time, and in Jogl’s case this means whichever thread is driving the Animator object (and also includes GLEventListener methods like init). Your button events are almost certainly in an AWT event thread, so aren’t allowed to touch gl at all. (and this is why its generally a bad idea to pass around a canvas or GL object other than just for the context of a display call).

Log your button press or state change, then update GL on your next display cycle.

Thanks for the info Tang.

Whilst I go off to think about how to amend my application structure, can I quickly ask how one would go about logging java opengl calls for later processing on the next display call?

Would I keep calls in an array? How would I go about calling them?

Thanks Tang!

Theres two methods I’ve used before, I’m sure others have ways of dealing with this -

  1. Queue up all events (with a dummy action listener) then flush this queue during your update/redraw. Works nicely for mouse events ('cos you can convert to opengl units while you’re at it) but not so great for a GUI with loads of components.

  2. Switch to storing all your drawing state in some sort of scene data structure. When drawing, simple re-set all state (such as lighting on/off) every time. Your event handlers then just have to poke at the scene data. Usually you end up doing this anyway as you’ll want to save your scene data to file and recover it at some point.

Thanks for an explanation of possible solutions tang! I’m not 100% sure how I would go about implementing solution #1 and as I had unconsciously developed a scene class structure, I will work on implementing my application through solution #2.

One quick question though - what kind of impact will the following type of coding (this is part of my display() method) have on the rendering speed of the application?


            if(scene.lightingEnabled) {
                  gl.glEnable(GL.GL_LIGHTING);
            } else {
                  gl.glDisable(GL.GL_LIGHTING);
                  //System.out.println("Lighting disabled");
            }
            
            if(scene.fogEnabled) {
                  gl.glEnable(GL.GL_FOG);
                  gl.glFogi(GL.GL_FOG_MODE, scene.fogTypes[scene.fogFilter]);
            } else {
                  gl.glDisable(GL.GL_FOG);
                  //System.out.println("fog disabled");
            }

A few function calls is not going to slow down your renderer by any measurable amount.

Good to know - hopefully in two weeks time I’ll have my first beta of the application I’m currently developing.

Does anyone else have any other methods/structures for making sure calls from classes outside the scope of the glcontext are carried through?

Cheers,

ribot

This code would be an example of a event queue. Here are a couple example event classes.


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;
            }
      }


Then you would just drop this in your display loop.


synchronized( eventList ) {
        int i = eventList.size();
        if( i > 0 ) {
          if( i > numEvents ) {
            numEvents = i;
          }
          ListIterator iter = eventList.listIterator(0);
          while( iter.hasNext() ) {
            ((GLEvent)iter.next()).stateChange(gl);
          }
          eventList.clear();
        }
      }


Here is what you would put in your event listening code.


public void keyTyped(KeyEvent e) {
      
      char c = e.getKeyChar();
      System.err.println("KeyEvent: " + c );
      if( (c == 'l') || (c == 'L') ) {
        light = !light;
        GLLightEvent glle = new GLLightEvent( this );
        glle.lightOn( this.light );
        synchronized( eventList ) {
          eventList.add( glle );
        }
      }
      if( (c == 'f') || (c == 'F') ) {
        this.filter += 1;
        if (filter > 2)
          filter = 0;
        GLFilterEvent glfe = new GLFilterEvent( this );
        glfe.setFilter( filter );
        glfe.setTexture( texture[filter] );
        System.err.println( "Texture: " + texture[filter] );
        synchronized( eventList ) {
          eventList.add( glfe );
        }
      }
    }


YOu can obviously use any type of structure that you want for your queue. This one uses a linked list. An ArrayList would probably be better but what ever you do it will have to be synchronized.

GKW: Thank you for posting your event queuing code - is this what you use for all your jogl apps? What are the benefits of using this method compared to a scene-based data structure mentioned earlier (i.e. is is just a cleaner way of doing things? Better for when applications grow in size and complexity?)?

Many thanks.

If only I had the extra time to have lots of JOGL apps. A few months ago someone was complaining that the code for JOGL was different from a NeHe tutorial and didn’t want to have a bunch of if statements in their rendering loop checking if any states have changed. I made an event queue because if there are no events in the queue the app can go right to rendering. I can’t tell you if it is any better than anything else. You will have to find that out for yourself.

I would be really nice if there was a “standard” delegating GLContext class available for this purpose. So, that could be used by any thread and the GL events would be automagically queued withing the wrapper. Then, you would “flush” the updates with a single method call from the actual GL context thread…

That might work for simple calls, but it wouldn’t work for any call that returns data fetched from OpenGL. And you could get all sorts of crazy race conditions with changing vertex array pointers, bound textures etc.

I don’t think it would really be practical, you really do need a proper way of handling this at an app level.

hi there,
i have that same very problem. i need to control the drawing outside an animator, as i animate the objects by myself. not to mention that i upload textures when i need them - which is definitely not inside of display() or init().

i call tick() on all my objects, then draw() and finally i issue a glFlush() when i think my gl-calls are complete.
this is impossible with the current structure (as far as i can see).

is there any hook to get to that context and call a makeCurrent() or something equal when i need it?
or can i halt the gl-thread until i signaled all my objects to tick() and then have that thread display() once?
or - the best solution - can i just not detach a new thread for gl and keep all the calls in my own thread?

jogl looks like what i need, but this is a heavy drawback for me, as i can not rewrite all my code. i know that one should not fight the api but use it.
any ideas welcome!

the stupid questions of a newbie… when i hit the submit-button i found the answer:
i have to keep the canvas and just call display() on it after a tick() and everything works as i want - with the exception of uploading textures.

so the one question still is unanswered:
any way of talking to the context outside of display() to do some modifications to it?