LWJGL context instantiation problem

Started by Icyene, March 10, 2013, 00:59:50

Previous topic - Next topic

Icyene

Hello!

I've wanted to create a simple tile-based game for a while, and recently I've had the time to do it. I originally wrote said game using Java2D, and then decided for performance reasons to switch to LWJGL. Since then, I've run across a problem which strikes me as exceedingly newbish, yet which I seem to be unable to solve.

I am trying to initialize a 480x320p frame, and paint an image of the same dimensions on it using LWJGL.

I am utilizing the following code:

public class TestApplet extends Applet {

    /**
     * The Canvas where the LWJGL Display is added
     */
    Canvas display_parent;

    /**
     * Thread which runs the main game loop
     */
    Thread gameThread;

    int width = 480;
    int height = 320;

    public TestApplet() {
        init();
    }

    /**
     * Once the Canvas is created its add notify method will call this method to
     * start the LWJGL Display and game loop in another thread.
     */
      public void startLWJGL() {
        try {
            Display.setParent(display_parent);

            // get modes
            Display.setTitle("Test");
            Display.setFullscreen(false);
            Display.create();
            // enable textures since we're going to use these for our sprites
            glEnable(GL_TEXTURE_2D);

            // disable the OpenGL depth test since we're rendering 2D graphics
            glDisable(GL_DEPTH_TEST);

            glMatrixMode(GL_PROJECTION);
            glLoadIdentity();

            glOrtho(0, width, height, 0, -1, 1);
            glMatrixMode(GL_MODELVIEW);
            glLoadIdentity();
            glViewport(0, 0, width, height);
        } catch (LWJGLException e) {
            e.printStackTrace();
        }

        gameThread = new Thread() {
            public void run() {
                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
                new TextureLoader().getSprite("Test.png").draw(0, 0);
            }
        };

        gameThread.start();
    }


    /**
     * Tell game loop to stop running, after which the LWJGL Display will be destoryed.
     * The main thread will wait for the Display.destroy() to complete
     */
    private void stopLWJGL() {
        // TODO some stopping code here
    }

    /**
     * Applet Destroy method will remove the canvas, before canvas is destroyed it will notify
     * stopLWJGL() to stop main game loop and to destroy the Display
     */
    public void destroy() {
        remove(display_parent);
        super.destroy();
        System.out.println("Clear up");
    }

    /**
     * initialise applet by adding a canvas to it, this canvas will start the LWJGL Display and game loop
     * in another thread. It will also stop the game loop and destroy the display on canvas removal when
     * applet is destroyed.
     */
    public void init() {
        setLayout(new BorderLayout());
        try {
            display_parent = new Canvas() {
                public void addNotify() {
                    super.addNotify();
                    startLWJGL();
                }

                public void removeNotify() {
                    stopLWJGL();
                    super.removeNotify();
                }
            };
            display_parent.setSize(getWidth(), getHeight());
            add(display_parent);
            display_parent.setFocusable(true);
            display_parent.requestFocus();
            display_parent.setIgnoreRepaint(true);
            setVisible(true);
        } catch (Exception e) {
            System.err.println(e);
            throw new RuntimeException("Unable to create display");
        }
    }
}


Essentially, it is the same as the example on LWJGL's Github example folder, yet with no logic but painting a screen constantly.

And yet, whenever I attempt to run the above snippet, I am hit with the following exceptions:

Exception in thread "Thread-5" java.lang.NullPointerException
	at org.lwjgl.opengl.GL11.glClear(GL11.java:586)
	at amber.TestApplet$1.run(TestApplet.java:69)
java.lang.RuntimeException: Unable to create display
	at amber.TestApplet.init(TestApplet.java:135)
	at sun.applet.AppletPanel.run(AppletPanel.java:424)
	at java.lang.Thread.run(Thread.java:662)
Caused by: java.lang.IllegalStateException: From thread Thread[thread applet-amber.TestApplet,4,file:/a/path/-threadGroup]: Thread[Thread-3,4,] already has the context current
	at org.lwjgl.opengl.ContextGL.checkAccess(ContextGL.java:184)
	at org.lwjgl.opengl.ContextGL.makeCurrent(ContextGL.java:189)
	at org.lwjgl.opengl.DrawableGL.makeCurrent(DrawableGL.java:110)
	at org.lwjgl.opengl.Display.makeCurrent(Display.java:731)
	at org.lwjgl.opengl.Display.makeCurrentAndSetSwapInterval(Display.java:1050)
	at org.lwjgl.opengl.Display.setParent(Display.java:478)
	at amber.TestApplet.startLWJGL(TestApplet.java:43)
	at amber.TestApplet$2.addNotify(TestApplet.java:120)
	at java.awt.Container.addImpl(Container.java:1068)
	at java.awt.Container.add(Container.java:365)
	at amber.TestApplet.init(TestApplet.java:129)
	... 2 more


Googling for a solution has been useless so far: all the results point to an error involving LWJGL which the game MineCraft encountered at some point in time.

Needless to say, I am very confused and I would greatly appreciate any tidbit of light that could be shed on this beginner issue of mine.

Cornix

lwjgl has some problems with multi-threading since the openGl library is static.
Judging from this exception:
Quotejava.lang.IllegalStateException: From thread Thread[thread applet-amber.TestApplet,4,file:/a/path/-threadGroup]: Thread[Thread-3,4,] already has the context current
I'd say this is your problem.
Try it without creating a new thread in your code.

quew8

I've never really understood the benefits of running your main game loop on anything but the main thread.

Icyene

That seemed to fix that issue, thanks!