glViewport() crashing with invalid value

I’m having a problem with glViewport() crashing when invalid values are sent to it. This is being caused by having the GLPanel inside of a JSplitPane(). The main window on the application is split into 2 split panes, each with 2 split panes in them. The top split pane is the GLCanvas, the other panes are panels with tables, buttons, fields, etc. I can resize the panes and everything is fine until the GLPanel gets down to a height of 0 then glViewport() throws a GLExcpeption and the DebugGL reports “glGetError() returned the following error codes after a call to glViewport(): GL_INVALID_VALUE”.

The code for my reshape method is as follows:


   public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height)
   {
      GL gl = drawable.getGL();
      
      System.out.println("width: " + width + " height: " + height);
      if (width == 0)
      {
         width = 1;
      }
      
      if (height == 0)
      {
         height = 1;
      }
      
      System.out.println("height: " + height);
      super.setBounds(x, y, width, height);
      gl.glViewport(x, y, width, height);
      
      gl.glMatrixMode(GL.GL_PROJECTION);
      gl.glLoadIdentity();
      
      gl.glOrtho(0.0, width, 0.0, height, -1.0, 1.0);
      
      gl.glMatrixMode(GL.GL_MODELVIEW);
      gl.glLoadIdentity();
      
      // Store the width and height for use in calculations in display().
      this.width = width;
      this.height = height;
   }


As you can see I’m checking for height to be 0 and setting it to 1. But glViewport() is throwing the exception anyway. Does glViewport() get called automatically before I can reset the value of height? (I thought I read somewhere that glViewport() gets called even if you don’t explicitly call it.)

Here is some output from when the crash occurs. Height is definitely being set to 1 before glViewport() is called.


...
...
...
width: 1264 height: 4
height: 4
width: 1264 height: 3
height: 3
width: 1264 height: 2
height: 2
width: 1264 height: 1
height: 1
width: 1264 height: 0
height: 1
javax.media.opengl.GLException: glGetError() returned the following error codes after a call to glViewport(): GL_INVALID_VALUE 
	at javax.media.opengl.DebugGL.checkGLGetError(DebugGL.java:11724)
	at javax.media.opengl.DebugGL.glViewport(DebugGL.java:11040)
	at javax.media.opengl.GLCanvas$DisplayAction.run(GLCanvas.java:276)
	at com.sun.opengl.impl.GLDrawableHelper.invokeGL(GLDrawableHelper.java:194)
	at javax.media.opengl.GLCanvas.maybeDoSingleThreadedWorkaround(GLCanvas.java:258)
	at javax.media.opengl.GLCanvas.display(GLCanvas.java:130)
	at view.GraphicsPanel.paint(GraphicsPanel.java:155)

Is there something I’m doing wrong in the reshape() method?

I also noticed in the JavaDoc for reshape() that it says “Subclasses which override this method must call super.reshape() in their reshape() method in order to function properly.” But in Java 5 the JPanel reshape method is deprecated. So I am calling super.setBounds(x, y, width, height). (The JavaDoc should be updated to note this change also.)

The problem is occuring on Windows 2000, with a Intel Extreme Graphics 2 graphics card, using JOGL JSR-231 beta 04. (I have not tried the nightly builds to see if it would fix the problem). I have the following properties set: “-Dsun.java2d.nodraw=true -Dsun.awt.noerasebackground=true -Djogl.debug”.

Any help would be appreciated.

david.

Yes. If you read the docs on the event listener, reshape has glViewport called before the user code is called on the listener.

I knew I had read that somewhere.

So how do you handle the problem of the height going to zero if you can’t check the value before it is called by the listener?

Are you inside a widget that you’re calling pack() on? That’s about the only way I know that a GLCanvas can go to zero dimensions before the end user gets hold of it.

No. As mentioned in the code from the first posting the GLCanvas is in a horizontal JSplitPane. As I move the divider up the pane eventually has 0 height and that is when glViewport() throws the exception.

Why is glViewport() called automatically? If I implement the reshape() method there might be other things I want to do before setting the viewport.

thanks again,
david.

That’s just part of the convenience of the listener interface. Mostly the GLEventListener interface is implemented purely for the display() method, which is where you do your normal rendering. By calling glViewport() automatically, that just means one less method you have to worry about writing code for. You can leave it blank and everything will work as expected.

As for the splitpane code setting the size to zero, then I think the only way you can deal with this is use a ComponentListener and look for the resize events. As soon as you see its size go to zero, halt the rendering thread. This is good practice anyway as it would save you CPU cycles when nothing is shown in that pane.

I added a ComponentListener and am capturing the resize events. When the height is <= 0 I set it to 1, but the exception is still being thrown from glViewport().

In your response you mentioned that I should “halt the rendering thread”. How do I do that? Is that the AWT event dispatch thread?

david.