Finally! Thank you! JSR-231 works the way I want opengl support to work! :D

Thanks for the detailed writeup and objective conclusions. Would you consider putting this on a web page somewhere to make it a little more permanent? We need to start a wiki or at least some pages with FAQs and informational links like this one.

I thought http://wiki.java.net/bin/view/Games/WebHome was The Wiki™

If anyone wants to clean up and copy my test there, you’re more than welcome to do so. =)

Hello everybody!
As you can probably guess by my lack of posts, I’m new to JOGL but want to write my games using it. (I’ve played around with DirectX a fair bit, so I’m not completely new to 3D graphics, but then I decided that having multiplatform support would be a good thing for games.) Anyway, as I’ll be using JOGL for games, I became very excited as I was reading this thread, because naturally I want the best performance possible. Unfortunately, I haven’t seen any tutorials or code samples on the new direct implementation. So, I looked over the current javadocs in an attempt to teach myself, but failed. So, some questions. If Ken or Markus could answer these, or better yet, post some sample code, I’d greatly appreciate it.

  1. Should I just use a GLDrawableFactory to get a drawable, then use that drawable to get a GLContext, and use that context to get the GL object?
  2. Is it best to use the normal AWT Canvas for rendering or is there a faster way?
  3. If I use a canvas, do I have to call paint() or anything to get the OpenGL graphics to display? I know I have to manually call swapBuffers() in the render loop, but is that all?
  4. Are there any other issues I should be aware of with the new implementation? Multithreading, etc?

Thanks in advance!

Some example code:

package com.mojang.joxsi.demo;

import java.awt.*;
import javax.media.opengl.*;
import javax.media.opengl.glu.*;

public class SingleThreadedGlCanvas extends Canvas implements Runnable
{
    private GLDrawable drawable;
    private GLContext context;
    private boolean ok = false;

    public SingleThreadedGlCanvas()
    {
        this(null);
    }

    public SingleThreadedGlCanvas(GLCapabilities capabilities)
    {
        this(capabilities, null, null, null);
    }

    public SingleThreadedGlCanvas(GLCapabilities capabilities, GLCapabilitiesChooser chooser, GLContext shareWith, GraphicsDevice device)
    {
        super(unwrap((AWTGraphicsConfiguration)GLDrawableFactory.getFactory().chooseGraphicsConfiguration(capabilities, chooser, new AWTGraphicsDevice(device))));
        drawable = GLDrawableFactory.getFactory().getGLDrawable(this, capabilities, chooser);
        context = drawable.createContext(shareWith);
    }

    public void addNotify()
    {
        super.addNotify();
        drawable.setRealized(true);
        ok = true;
    }

    public void update(Graphics g)
    {
    }

    public void paint(Graphics g)
    {
    }

    protected void renderLoop(GL gl, GLU glu)
    { 
        while(true) // While the game is still running
        {
             // normal opengl rendering goes here
            drawable.swapBuffers();
        }
    }

    public void run()
    {
        try
        {
            while (!ok || !isVisible())
            {
                Thread.sleep(100);
            }

            while (context.makeCurrent() == GLContext.CONTEXT_NOT_CURRENT)
            {
                Thread.sleep(100);
            }
        }
        catch (InterruptedException e)
        {
            e.printStackTrace();
        }

        GL gl = context.getGL();
        GLU glu = new GLU();

        renderLoop(gl, glu);

        context.release();
        context.destroy();
        System.exit(0);
    }

    private static GraphicsConfiguration unwrap(AWTGraphicsConfiguration config)
    {
        if (config == null) { return null; }
        return config.getGraphicsConfiguration();
    }
}
        JFrame frame = new JFrame("Model Displayer");

        SingleThreadedGlCanvas canvas = new SingleThreadedGlCanvas();
        frame.add(canvas);

        frame.setLocation(200, 0);
        frame.setSize(512, 384);
        frame.setVisible(true);

        new Thread(canvas).start();

And, to answer your questions:

  1. See the example code.
  2. AWT Canvases are almost certainly the fastest way
  3. Yep, after the context is set up, that is all.
  4. Don’t touch the opengl context or GL/GLU objects outside of the thread running the renderLoop() method. Also, you will have to add some code to deal with contexts that goes bad/lost. I’m not entirely sure how this can happen, but I understand it can.

Thanks Markus!
I have followed your example and it looks like OpenGL is working. I haven’t actually done any framerate benchmarks yet, soon I plan on adding a framerate counting/limiting system to my renderer. Before I do that though, I ran into a small issue. Your example adds the SingleThreadedGlCanvas to a JFrame, but based on my reading these forums and the user guide, I thought that Swing components can cause problems. Or is this only when I try to overlap them, use many components in the same container, etc? Either way, I used a JFrame in my code, and was wondering what to about closing the window. As I would like the program to exit when the user closes the windw, obviously there’s setDefaultCloseOperation(EXIT_ON_CLOSE), but when I tried that, I get an exception (I named my canvas extension RenderCanvas instead of SingleThreadedGlCanvas):

Exception in thread "Thread-2" javax.media.opengl.GLException: Error swapping buffers
        at com.sun.opengl.impl.windows.WindowsOnscreenGLDrawable.swapBuffers(WindowsOnscreenGLDrawable.java:113)
        at RenderCanvas.renderLoop(RenderCanvas.java:48)
        at RenderCanvas.run(RenderCanvas.java:74)
        at java.lang.Thread.run(Thread.java:595)

Is it correct to assume that this is because the program is calling System.exit immediately, without calling context.release() or context.destroy(); first? If so, is there an easy way around this, or should I just write a windowClosing event listener that calls context.release() and context.destroy()? Might this cause a threading issue?

Thanks for the help.

JOGL reports all OpenGL errors during context management as exceptions rather than silently squelching them. You’re correct that the reason you’re getting the exception is that you’re attempting to do OpenGL rendering while the system is tearing down the windows. To correct this you should add some synchronization to your program to ensure you aren’t attempting to render while in the middle of System.exit(). The jogl-demos workspace contains several examples of how to do this, though in the context of the GLEventListener and Animator.

In my example code above, the correct way of quitting is to return from the renderLoop() method.
To do this, you need to change while(true) into while(keepRunning) or something, then set keepRunning to false when the quit button is pressed.

This will ensure that System.exit only gets run after the context has been properly disposed.