Alex Socha
Alex Socha

Reputation: 13

LWJGL Display in JFrame has poor performance on OSX

I was recently using LWJGL to make an application, and I decided to set a JFrame as the parent of the display. I did this because it provides better functionality for resizing and moving. Especially on windows, where LWJGL seems to have bug that makes the application freeze when moved and resized.

The problem is, when I try the application on my mac, which is much faster than my windows computer, the performance is really poor. When I use the regular native display on mac, it runs smoothly at 60fps, but here is the strange thing: when I run it in a JFrame on the mac, the fps seems unaffected, still 60, but it looks horribly jerky, especially at full screen. It's as if the display is only updating once every 5 or more frames, though the logic seems to update every frame like it should. Why is it like this? Is there any way to fix it? Here is the window initialization code:

public JFrame frame;
public final Canvas frameCanvas = new Canvas();

private static boolean closeRequested = false;
private final static AtomicReference<Dimension> newCanvasSize = new AtomicReference<Dimension>();

public BaseGame()
{
    this.frame = new JFrame("Game");
    this.frame.setLayout(new BorderLayout());
    this.frameCanvas.addComponentListener(new ComponentAdapter()
    {
        @Override
        public void componentResized(ComponentEvent e)
        {
            newCanvasSize.set(BaseGame.this.frameCanvas.getSize());
        }
    });

    this.frame.addWindowFocusListener(new WindowAdapter()
    {
        @Override
        public void windowGainedFocus(WindowEvent e)
        {
            BaseGame.this.frameCanvas.requestFocusInWindow();
        }

    });

    this.frame.addWindowListener(new WindowAdapter()
    {
        @Override
        public void windowClosing(WindowEvent e)
        {
            closeRequested = true;
        }
    });

    this.frame.add(this.frameCanvas, BorderLayout.CENTER);

    try
    {
        Display.setParent(this.frameCanvas);
        Display.setVSyncEnabled(true);
        this.frame.setPreferredSize(new Dimension(800, 500));
        this.frame.setMinimumSize(new Dimension(400, 400));
        this.frame.pack();
        Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
        this.frame.setLocation(dim.width / 2 - this.frame.getSize().width / 2, dim.height / 2 - this.frame.getSize().height / 2);
        this.frame.setVisible(true);
        Display.create();

        this.runTick();

        Display.destroy();
        this.frame.dispose();
        System.exit(0);
    }
    catch (Exception e)
    {
        e.printStackTrace();
    }
}

private void runTick()
{
    this.initGL();
    Dimension newDim;
    this.resize(this.frameCanvas.getWidth(), this.frameCanvas.getHeight(), Display.isFullscreen());

    while (!Display.isCloseRequested() && !closeRequested)
    {
        thisFrame = getCurrentTime();

        newDim = newCanvasSize.getAndSet(null);

        if (newDim != null)
        {
            this.resize(this.frameCanvas.getWidth(), this.frameCanvas.getHeight(), Display.isFullscreen());
        }

        this.updateTick();
        this.renderTick();

        Display.update();
        Display.sync(60);
    }
}

public void initGL()
{
    GL11.glEnable(GL11.GL_TEXTURE_2D);
    GL11.glDisable(GL11.GL_DEPTH_TEST);
    GL11.glDisable(GL11.GL_LIGHTING);

    GL11.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    GL11.glClearDepth(1);

    GL11.glViewport(0, 0, 800, 500);
    GL11.glMatrixMode(GL11.GL_MODELVIEW);

    GL11.glMatrixMode(GL11.GL_PROJECTION);
    GL11.glLoadIdentity();
    GL11.glOrtho(0, 800, 500, 0, 1, -1);
    GL11.glMatrixMode(GL11.GL_MODELVIEW);
}

public void resize(int width, int height, boolean fullScreen)
{
    GL11.glMatrixMode(GL11.GL_PROJECTION);
    GL11.glLoadIdentity();
    GL11.glViewport(0, 0, width, height);
    GLU.gluPerspective(45.0f, ((float) width) / ((float) height), 0.1f, 100.0f);
    GL11.glMatrixMode(GL11.GL_MODELVIEW);
    GL11.glLoadIdentity();
}

Upvotes: 0

Views: 377

Answers (1)

Anubian Noob
Anubian Noob

Reputation: 13596

If you're using LWJGL, don't use a JFrame. Swing is the cause of your troubles. Use LWJGL's optimized window:

Setting up the window:

Display.setDisplayMode(new DisplayMode(width,height));
Display.create();

And Keyboard:

Keyboard.isKeyDown(Keyboard.KEY_ESCAPE);

You need a loop in the main method that looks something like this:

while (!done) {
    // Update anything you want to update.

    // Clear screen.
    GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
    GL11.glLoadIdentity();

    // Render stuff.    

    Display.update();

    // Optional VSync.
    Display.sync(FRAME_RATE);
}

Upvotes: 2

Related Questions