Bug 30

Summary: Error Swapping Buffers with JInternalFrame
Product: [JogAmp] Jogl Reporter: Sven Gothel <sgothel>
Component: coreAssignee: Sven Gothel <sgothel>
Status: VERIFIED WORKSFORME    
Severity: normal    
Priority: P1    
Version: 1   
Hardware: All   
OS: windows   
Type: DEFECT SCM Refs:
Workaround: ---
Attachments: Test Case for generating Exception with JinternalFrame
Test Case for generating Exception with JinternalFrame
Jar File for reproducing error

Description Sven Gothel 2010-03-24 07:45:44 CET


---- Reported by moussaba 2003-08-07 13:31:39 ----

When GLcanvas added to a JInternalFrame, when frame is iconized and restored it 
crashes and generates the following exception:

net.java.games.jogl.GLException: Error swapping buffers
	at 
net.java.games.jogl.impl.windows.WindowsOnscreenGLContext.swapBuffers
(WindowsOnscreenGLContext.java:137)
	at net.java.games.jogl.impl.GLContext.invokeGL(GLContext.java:187)
	at net.java.games.jogl.GLCanvas.displayImpl(GLCanvas.java:179)
	at net.java.games.jogl.GLCanvas.display(GLCanvas.java:84)
	at net.java.games.jogl.Animator$1.run(Animator.java:104)
	at java.lang.Thread.run(Thread.java:534)

Below is example source code that generates the exception

*
 * Lesson06.java
 * Modified on August 07, 2003
 * Reproduces the GLException: Error Swapping Buffers when
 * Using JInternalFrame.  Iconize the Internal Frame, restore it and you will
 * get the above mentioned exception.  This does not occur when the main window
 * is iconized.
 * Created on July 16, 2003, 11:30 AM
 * Modified on August 97,2003
 */

import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import javax.swing.*;
import javax.swing.event.*;
import java.io.*;
import java.net.*;
import java.nio.*;
import javax.imageio.*;

import net.java.games.jogl.*;
import net.java.games.jogl.util.*;

/** Port of the NeHe OpenGL Tutorial (Lesson 6)
 * to Java using the Jogl interface to OpenGL.  Jogl can be obtained
 * at http://jogl.dev.java.net/
 *
 * @author Kevin Duling (jattier@hotmail.com)
 */
public class Lesson06
{
  static Animator animator = null;
  static class Renderer
    implements GLEventListener,
               KeyListener
  {
    private float	xrot;				// X Rotation ( NEW )
    private float	yrot;				// Y Rotation ( NEW )
    private float	zrot;				// Z Rotation ( NEW )
    private int[] texture= new int[2];

    /** Called by the drawable to initiate OpenGL rendering by the client.
     * After all GLEventListeners have been notified of a display event, the
     * drawable will swap its buffers if necessary.
     * @param gLDrawable The GLDrawable object.
     */
    public void display(GLDrawable gLDrawable)
    {
      final GL gl = gLDrawable.getGL();
      gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
      gl.glLoadIdentity();						
			// Reset The View
      gl.glTranslatef(0.0f,0.0f,-5.0f);

      gl.glRotatef(xrot,1.0f,0.0f,0.0f);
      gl.glRotatef(yrot,0.0f,1.0f,0.0f);
      gl.glRotatef(zrot,0.0f,0.0f,1.0f);

      gl.glColor3f(1.0f, 1.0f, 1.0f);
      gl.glBindTexture(GL.GL_TEXTURE_2D, texture[0]);
      gl.glBegin(GL.GL_QUADS);
      //Bottom of Cube
        gl.glTexCoord2f(1.0f, 1.0f); gl.glVertex3f(-1.0f, -0.25f, -1.0f);
        gl.glTexCoord2f(0.0f, 1.0f); gl.glVertex3f( 1.0f, -0.25f, -1.0f);
        gl.glTexCoord2f(0.0f, 0.0f); gl.glVertex3f( 1.0f, -0.25f,  1.0f);
        gl.glTexCoord2f(1.0f, 0.0f); gl.glVertex3f(-1.0f, -0.25f,  1.0f);
      gl.glEnd();

      gl.glBindTexture(GL.GL_TEXTURE_2D, texture[1]);
      gl.glBegin(GL.GL_QUADS);
  // Top Face
          gl.glTexCoord2f(0.0f, 1.0f); gl.glVertex3f(-1.0f,  0.0f, -1.0f);
          gl.glTexCoord2f(0.0f, 0.0f); gl.glVertex3f(-1.0f,  0.0f,  1.0f);
          gl.glTexCoord2f(1.0f, 0.0f); gl.glVertex3f( 1.0f,  0.0f,  1.0f);
          gl.glTexCoord2f(1.0f, 1.0f); gl.glVertex3f( 1.0f,  0.0f, -1.0f);



      gl.glBegin(GL.GL_QUADS);

        /*gl.glTexCoord2f(0.0f, 0.0f); gl.glVertex3f(-1.0f, -1.0f,  1.0f);
        gl.glTexCoord2f(1.0f, 0.0f); gl.glVertex3f( 1.0f, -1.0f,  1.0f);
        gl.glTexCoord2f(1.0f, 1.0f); gl.glVertex3f( 1.0f,  1.0f,  1.0f);
        gl.glTexCoord2f(0.0f, 1.0f); gl.glVertex3f(-1.0f,  1.0f,  1.0f);
       */
      // Back Face
      gl.glColor3f(0.0f, 0.4f, 0.0f); // Set The Color To Blue
      gl.glVertex3f(1.0f, -0.25f, -1.0f); // Top Right Of The Quad (Back)
      gl.glVertex3f( -1.0f, -0.25f, -1.0f); // Top Left Of The Quad (Back)
      gl.glVertex3f( -1.0f, 0.0f, -1.0f); // Bottom Left Of The Quad (Back)
      gl.glVertex3f(1.0f, 0.0f, -1.0f); // Bottom Right Of The Quad (Back)

      /*gl.glTexCoord2f(1.0f, 0.0f); gl.glVertex3f(-1.0f, -1.0f, -1.0f);
               gl.glTexCoord2f(1.0f, 1.0f); gl.glVertex3f(-1.0f,  1.0f, -1.0f);
               gl.glTexCoord2f(0.0f, 1.0f); gl.glVertex3f( 1.0f,  1.0f, -1.0f);
           gl.glTexCoord2f(0.0f, 0.0f); gl.glVertex3f( 1.0f, -1.0f, -1.0f);*/
      // Front Face
      //glColor3f (1.0f, 0.0f, 0.0f);	// Set The Color To Red
      gl.glColor3f(0.0f, 0.4f, 0.0f); // Set The Color To Blue
      gl.glVertex3f(1.0f, 0.0f, 1.0f); // Top Right Of The Quad (Front)
      gl.glVertex3f( -1.0f, 0.0f, 1.0f); // Top Left Of The Quad (Front)
      gl.glVertex3f( -1.0f, -0.25f, 1.0f); // Bottom Left Of The Quad (Front)
      gl.glVertex3f(1.0f, -0.25f, 1.0f); // Bottom Right Of The Quad (Front)


        // Right face
        gl.glColor3f (0.0f, 0.4f, 0.0f);	// Set The Color To Blue
        gl.glVertex3f (1.0f, 0.0f, -1.0f);	// Top Right Of The Quad (Right)
        gl.glVertex3f (1.0f, 0.0f, 1.0f);	// Top Left Of The Quad (Right)
        gl.glVertex3f (1.0f, -0.25f, 1.0f);	// Bottom Left Of The Quad (Right)
        gl.glVertex3f (1.0f, -0.25f, -1.0f);	// Bottom Right Of The Quad 
(Right)

        /*gl.glTexCoord2f(1.0f, 0.0f); gl.glVertex3f( 1.0f, -1.0f, -1.0f);
        gl.glTexCoord2f(1.0f, 1.0f); gl.glVertex3f( 1.0f,  1.0f, -1.0f);
        gl.glTexCoord2f(0.0f, 1.0f); gl.glVertex3f( 1.0f,  1.0f,  1.0f);
        gl.glTexCoord2f(0.0f, 0.0f); gl.glVertex3f( 1.0f, -1.0f,  1.0f);*/
        // Left Face
        gl.glColor3f(0.0f, 0.4f, 0.0f); // Set The Color To Blue
        gl.glVertex3f( -1.0f, 0.0f, 1.0f); // Top Right Of The Quad (Left)
        gl.glVertex3f( -1.0f, 0.0f, -1.0f); // Top Left Of The Quad (Left)
        gl.glVertex3f( -1.0f, -0.25f, -1.0f); // Bottom Left Of The Quad (Left)
        gl.glVertex3f (-1.0f, -0.25f, 1.0f);	// Bottom Right Of The Quad (Left)


        /*gl.glTexCoord2f(0.0f, 0.0f); gl.glVertex3f(-1.0f, -1.0f, -1.0f);
        gl.glTexCoord2f(1.0f, 0.0f); gl.glVertex3f(-1.0f, -1.0f,  1.0f);
        gl.glTexCoord2f(1.0f, 1.0f); gl.glVertex3f(-1.0f,  1.0f,  1.0f);
        gl.glTexCoord2f(0.0f, 1.0f); gl.glVertex3f(-1.0f,  1.0f, -1.0f);
        */
      gl.glEnd();

      xrot+=0.3f;
      yrot+=0.2f;
      zrot+=0.4f;
    }


    /** Called when the display mode has been changed.  <B>!! CURRENTLY 
UNIMPLEMENTED IN JOGL !!</B>
     * @param gLDrawable The GLDrawable object.
     * @param modeChanged Indicates if the video mode has changed.
     * @param deviceChanged Indicates if the video device has changed.
     */
    public void displayChanged(GLDrawable gLDrawable, boolean modeChanged, 
boolean deviceChanged)
    {
    }

    /** Called by the drawable immediately after the OpenGL context is
     * initialized for the first time. Can be used to perform one-time OpenGL
     * initialization such as setup of lights and display lists.
     * @param gLDrawable The GLDrawable object.
     */
    public void init(GLDrawable gLDrawable)
    {
      final GL gl = gLDrawable.getGL();
      gl.glShadeModel(GL.GL_SMOOTH);              // Enable Smooth Shading
      gl.glClearColor(0.0f, 0.0f, 0.0f, 0.5f);    // Black Background
      gl.glClearDepth(1.0f);                      // Depth Buffer Setup
      gl.glEnable(GL.GL_DEPTH_TEST);					
		// Enables Depth Testing
      gl.glDepthFunc(GL.GL_LEQUAL);					
			// The Type Of Depth Testing To Do
      gl.glHint(GL.GL_PERSPECTIVE_CORRECTION_HINT, GL.GL_NICEST);	// 
Really Nice Perspective Calculations
      gl.glEnable(GL.GL_TEXTURE_2D);
      gLDrawable.addKeyListener(this);
      texture[0] = genTexture(gl);
      gl.glBindTexture(GL.GL_TEXTURE_2D, texture[0]);
      BufferedImage img = readPNGImage("./tnetMSP.jpg");
      makeRGBTexture(gl, gLDrawable.getGLU(), img, GL.GL_TEXTURE_2D, false);
      gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER,
                         GL.GL_LINEAR);
      gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER,
                         GL.GL_LINEAR);
      texture[1] = genTexture(gl);
      gl.glBindTexture(GL.GL_TEXTURE_2D, texture[1]);
      BufferedImage img2 = readPNGImage("./tnetRF.jpg");
      makeRGBTexture(gl, gLDrawable.getGLU(), img2, GL.GL_TEXTURE_2D, false);
      gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER,
                         GL.GL_LINEAR);
      gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER,
                         GL.GL_LINEAR);

    }

    /** Called by the drawable during the first repaint after the component has
     * been resized. The client can update the viewport and view volume of the
     * window appropriately, for example by a call to
     * GL.glViewport(int, int, int, int); note that for convenience the component
     * has already called GL.glViewport(int, int, int, int)(x, y, width, height)
     * when this method is called, so the client may not have to do anything in
     * this method.
     * @param gLDrawable The GLDrawable object.
     * @param x The X Coordinate of the viewport rectangle.
     * @param y The Y coordinate of the viewport rectanble.
     * @param width The new width of the window.
     * @param height The new height of the window.
     */
    public void reshape(GLDrawable gLDrawable, int x, int y, int width, int height)
    {
      final GL gl = gLDrawable.getGL();
      final GLU glu = gLDrawable.getGLU();

      if (height <= 0) // avoid a divide by zero error!
        height = 1;
      final float h = (float)width / (float)height;
      gl.glViewport(0, 0, width, height);
      gl.glMatrixMode(GL.GL_PROJECTION);
      gl.glLoadIdentity();
      glu.gluPerspective(45.0f, h, 1.0, 20.0);
      gl.glMatrixMode(GL.GL_MODELVIEW);
      gl.glLoadIdentity();
    }

    /** Invoked when a key has been pressed.
     * See the class description for {@link KeyEvent} for a definition of
     * a key pressed event.
     * @param e The KeyEvent.
     */
    public void keyPressed(KeyEvent e)
    {}

    /** Invoked when a key has been released.
     * See the class description for {@link KeyEvent} for a definition of
     * a key released event.
     * @param e The KeyEvent.
     */
    public void keyReleased(KeyEvent e)
    {}

    /** Invoked when a key has been typed.
     * See the class description for {@link KeyEvent} for a definition of
     * a key typed event.
     * @param e The KeyEvent.
     */
    public void keyTyped(KeyEvent e)
    {
      if (e.getKeyChar() == KeyEvent.VK_ESCAPE)
      {

        System.exit(0);
      }
    }

    private BufferedImage readPNGImage(String resourceName)
    {
      try
      {
        URL url = getResource(resourceName);
        if (url == null)
        {
          throw new RuntimeException("Error reading resource " + resourceName);
        }
        BufferedImage img = ImageIO.read(url);
        java.awt.geom.AffineTransform tx = 
java.awt.geom.AffineTransform.getScaleInstance(1, -1);
        tx.translate(0, -img.getHeight(null));
        AffineTransformOp op = new AffineTransformOp(tx, 
AffineTransformOp.TYPE_NEAREST_NEIGHBOR);
        img = op.filter(img, null);
        return img;
      }
      catch (IOException e)
      {
        throw new RuntimeException(e);
      }
    }

    private void makeRGBTexture(GL gl, GLU glu, BufferedImage img, int target, 
boolean mipmapped)
    {
      ByteBuffer dest = null;
      switch (img.getType())
      {
        case BufferedImage.TYPE_3BYTE_BGR:
        case BufferedImage.TYPE_CUSTOM:
        {
          byte[] data = ((DataBufferByte) img.getRaster().getDataBuffer()).getData
();
          dest = ByteBuffer.allocateDirect(data.length);
          dest.order(ByteOrder.nativeOrder());
          dest.put(data, 0, data.length);
          break;
        }
        case BufferedImage.TYPE_INT_RGB:
        {
          int[] data = ((DataBufferInt) img.getRaster().getDataBuffer()).getData();
          dest = ByteBuffer.allocateDirect(data.length * BufferUtils.SIZEOF_INT);
          dest.order(ByteOrder.nativeOrder());
          dest.asIntBuffer().put(data, 0, data.length);
          break;
        }
        default:
          throw new RuntimeException("Unsupported image type " + img.getType());
      }

      if (mipmapped)
      {
        glu.gluBuild2DMipmaps(target, GL.GL_RGB8, img.getWidth(), img.getHeight(), 
GL.GL_RGB, GL.GL_UNSIGNED_BYTE, dest);
      }
      else
      {
        gl.glTexImage2D(target, 0, GL.GL_RGB, img.getWidth(), img.getHeight(), 0, 
GL.GL_RGB, GL.GL_UNSIGNED_BYTE, dest);
      }
    }

    private int genTexture(GL gl)
    {
      final int[] tmp = new int[1];
      gl.glGenTextures(1, tmp);
      return tmp[0];
    }
  }

  /** Retrieve a URL resource from the jar.  If the resource is not found, then
   * the local disk is also checked.
   * @param filename Complete filename, including parent path
   * @return a URL object if resource is found, otherwise null.
   */
  public final static URL getResource(final String filename)
  {
    // Try to load resource from jar
    URL url = ClassLoader.getSystemResource(filename);
    // If not found in jar, then load from disk
    if (url == null)
    {
      try
      {
        url = new URL("file", "localhost", filename);
      }
      catch (Exception urlException){} // ignore
    }
    return url;
  }

  /** Program's main entry point
   * @param args command line arguments.
   */
  public static void main(String[] args)
  {
    Frame frame = new Frame("Lesson 6: Texture Mapping");

    JDesktopPane desktop=new JDesktopPane();
    JInternalFrame l6frame = new JInternalFrame("3D texture", true,true,true,true);

    l6frame.setBounds(0, 0, 400, 400);

    GLCanvas canvas = GLDrawableFactory.getFactory().createGLCanvas(new 
GLCapabilities());

    canvas.addGLEventListener(new Renderer());
    animator = new Animator(canvas);
    l6frame.getContentPane().add(canvas);

    desktop.add("Center",l6frame);

//    frame.add(canvas);
    frame.add(desktop);
    frame.setSize(1024, 768);


    frame.addWindowListener(new WindowAdapter()
    {
      public void windowClosing(WindowEvent e)
      {
        animator.stop();
        System.exit(0);
      }
    });

    frame.show();
    l6frame.setVisible(true);
    animator.start();

  }
}



---- Additional Comments From moussaba 2003-08-07 13:33:11 ----

Created an attachment
Test Case for generating Exception with JinternalFrame




---- Additional Comments From moussaba 2003-08-07 13:34:56 ----

Created an attachment
Test Case for generating Exception with JinternalFrame




---- Additional Comments From moussaba 2003-08-07 13:36:04 ----

Created an attachment
Jar File for reproducing error




---- Additional Comments From kbr 2005-01-31 01:53:52 ----

Sorry for not investigating this bug until now. JOGL had proper
addNotify/removeNotify tracking added a while ago and the current JOGL source
runs the enclosed demo correctly. Please reopen this bug or file a new one if
you are still seeing problems.




--- Bug imported by sgothel@jausoft.com 2010-03-24 07:45 EDT  ---

This bug was previously known as _bug_ 30 at https://jogl.dev.java.net/bugs/show_bug.cgi?id=30
Imported an attachment (id=7)
Imported an attachment (id=8)
Imported an attachment (id=9)

The original submitter of attachment 7 [details] is unknown.
   Reassigning to the person who moved it here: sgothel@jausoft.com.
The original submitter of attachment 8 [details] is unknown.
   Reassigning to the person who moved it here: sgothel@jausoft.com.
The original submitter of attachment 9 [details] is unknown.
   Reassigning to the person who moved it here: sgothel@jausoft.com.