JDK-6503420 : Swing/Jogl Interopability: Exception in paint-Method causes Crash
  • Type: Bug
  • Component: client-libs
  • Sub-Component: javax.swing
  • Affected Version: 6
  • Priority: P4
  • Status: Closed
  • Resolution: Not an Issue
  • OS: windows_xp
  • CPU: x86
  • Submitted: 2006-12-12
  • Updated: 2011-02-16
  • Resolved: 2006-12-21
Description
FULL PRODUCT VERSION :
java version "1.6.0-rc"
Java(TM) SE Runtime Environment (build 1.6.0-rc-b104)
Java HotSpot(TM) Client VM (build 1.6.0-rc-b104, mixed mode, sharing)

ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows XP [Version 5.1.2600]

A DESCRIPTION OF THE PROBLEM :
I use the GLJpanel in connection with the GlassPane. The GlassPane holds some kind of HUD.

If any exception is thrown within the HUD's paint-method. The animator causes never ending GLExceptions.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Just throw an Exception within a paint-Method. (Maybe of an Component in the GlassPane). The GLJPanel ist located in the ContentPane of the JFrame.

Here's my Test-Case. Just run it and you'll see the problem. Never Ending
Exceptions "Caused by: javax.media.opengl.GLException: Error making context
current: 6"

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
It should print a Stack-Trace or something but not such unrecoverable Exceptions.

ERROR MESSAGES/STACK TRACES THAT OCCUR :
java.lang.reflect.InvocationTargetException
	at java.awt.EventQueue.invokeAndWait(EventQueue.java:997)
	at javax.swing.SwingUtilities.invokeAndWait(SwingUtilities.java:1323)
	at com.sun.opengl.util.Animator.display(Animator.java:158)
	at com.sun.opengl.util.Animator$MainLoop.run(Animator.java:181)
	at java.lang.Thread.run(Thread.java:619)
Caused by: javax.media.opengl.GLException: Error making context current: 6
	at com.sun.opengl.impl.windows.WindowsGLContext.makeCurrentImpl(WindowsGLContext.java:169)
	at com.sun.opengl.impl.windows.WindowsPbufferGLContext.makeCurrentImpl(WindowsPbufferGLContext.java:102)
	at com.sun.opengl.impl.GLContextImpl.makeCurrent(GLContextImpl.java:127)
	at com.sun.opengl.impl.GLDrawableHelper.invokeGL(GLDrawableHelper.java:182)
	at com.sun.opengl.impl.GLPbufferImpl.maybeDoSingleThreadedWorkaround(GLPbufferImpl.java:201)
	at com.sun.opengl.impl.GLPbufferImpl.display(GLPbufferImpl.java:88)
	at javax.media.opengl.GLJPanel.paintComponent(GLJPanel.java:605)
	at javax.swing.JComponent.paint(JComponent.java:1022)
	at javax.swing.JComponent.paintChildren(JComponent.java:859)
	at javax.swing.JComponent.paint(JComponent.java:1031)
	at javax.swing.JComponent.paintChildren(JComponent.java:859)
	at javax.swing.JComponent.paint(JComponent.java:1031)
	at javax.swing.JLayeredPane.paint(JLayeredPane.java:564)
	at javax.swing.JComponent.paintChildren(JComponent.java:859)
	at javax.swing.JComponent.paint(JComponent.java:1031)
	at javax.swing.JComponent.paintToOffscreen(JComponent.java:5104)
	at 
REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.awt.Color;
import java.awt.FlowLayout;

import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLJPanel;
import javax.swing.JFrame;
import javax.swing.JPanel;

import com.sun.opengl.util.Animator;

public class TestCase implements GLEventListener {

    private JFrame frame;
    private JPanel panel;

    public TestCase() {
        frame = new JFrame();
        frame.setSize(300, 300);

        panel = new JPanel(new FlowLayout(FlowLayout.LEFT));

        JPanel exceptionThrower = new JPanel() {

            private boolean first = true;

            public void paint(java.awt.Graphics g) {

                super.paint(g);

                if (first) {
                    first = false;
                    throw new IllegalArgumentException();
                }
            }
        };

        exceptionThrower.setBackground(Color.RED);
        exceptionThrower.setSize(100, 300);

        GLJPanel glPanel = new GLJPanel();
        glPanel.setSize(200, 300);
        glPanel.addGLEventListener(this);

        Animator animator = new Animator(glPanel);

        panel.add(exceptionThrower);
        panel.add(glPanel);

        frame.getContentPane().add(panel);

        frame.setVisible(true);

        animator.start();
    }

    /**
     * @param args
     */
    public static void main(String[] args) {

        new TestCase();
    }

    public void init(GLAutoDrawable arg0) {
        // do some init stuff
    }

    public void display(GLAutoDrawable arg0) {
        // do the display stuff
    }

    public void reshape(GLAutoDrawable arg0, int arg1, int arg2, int arg3,
int arg4) {
    }

    public void displayChanged(GLAutoDrawable arg0, boolean arg1, boolean
arg2) {
    }

}

---------- END SOURCE ----------

Comments
EVALUATION The problem in the submitter's test case is reproducible with slightly older NVidia drivers on Windows. At first glance it is unclear why the problem occurs. The JPanel throwing the IllegalArgumentException is a completely different component than the GLJPanel and it is puzzling why aborting a repaint of one of them should have any effect on the other. However, after discussion with ###@###.### from the AWT team, it is clear what is happening. During its first repaint (which succeeds) the GLJPanel creates an OpenGL pbuffer and associated context. It makes the context current on the AWT Event Dispatch Thread and later releases the context. The exception throwing JPanel then raises an IllegalArgumentException. It turns out that this actually causes the AWT Event Dispatch Thread to exit and another thread to be started to act as the new EDT. At some point in the near future, OpenGL context-related operations against the pbuffer start failing on the new EDT. This is happening because of poor quality of the OpenGL drivers when using a pbuffer and context from more than one thread, even when those accesses are being done correctly according to the OpenGL specification. This has been proven to be the problem by using an undocumented system property to avoid aborting the EDT, which causes the test case to work as expected. I was able to reproduce this with NVidia's 81.85 drivers on a Windows XP machine with a Quadro FX Go700 graphics chip. However, on a desktop machine with a GeForce FX 5800 Ultra and NVidia's latest 93.71 drivers, the problem no longer occurs. Because recent OpenGL driver bug fixes have eliminated the need for more workarounds for this issue in the JOGL code, I'm closing this as "not a bug" and not opening an associated bug with the JOGL issue tracker (http://jogl.dev.java.net/ -- where further JOGL-related issues should be opened). The submitter should contact his or her graphics card vendor and report this as a bug against their OpenGL drivers, if the latest version of those drivers hasn't solved the problem. The specific issue that should be reported is that using a pbuffer and its associated OpenGL context from more than one thread (when the OpenGL context management in the application is correct) results in context-related operations on the second thread to soon fail.
21-12-2006