开发者

BufferStrategy.getDrawGraphics() sometimes fails after a swap to fullscreen-exclusive mode

I initialize an extended jFrame with a BufferStrategy and so forth, getting a nice animating circle on the screen. I have set a key listener (outside of the update-draw thread) that tells the update-draw thread to change to and from fullscreen exclusive mode, without doing updates or draws until the change is done. This usually works, but on occasion, the draw part of the update-draw thread (update does nothing so far) will have an exception and crash immediately after the switch. Most of the time, it doesn't do this crash, but even this is unacceptable for any program.

Edit: Ah, it's done it again. Notably, though, it actually does it a few frames after the switch, and it seems to only do it on the first time running after my computer starts up! Here's the stack trace:

java.lang.IllegalStateException: Buffers have not been created
at sun.awt.windows.WComponentPeer.getBackBuffer(Unknown Source)
at java.awt.Component$FlipBufferStrategy.getBackBuffer(Unknown Source)
at java.awt.Component$FlipBufferStrategy.updateInternalBuffers(Unknown Source)
at java.awt.Component$FlipBufferStrategy.revalidate(Unknown Source)
at java.awt.Component$FlipBufferStrategy.revalidate(Unknown Source)
at java.awt.Component$FlipBufferStrategy.getDrawGraphics(Unknown Source)
at albeyamakiir.lightspeed.LightSpeedFrame.screenUpdate(LightSpeedFrame.java:194)
at albeyamakiir.lightspeed.LightSpeedFrame.run(LightSpeedFrame.java:187)
at java.lang.Thread.run(Unknown Source)

End Edit.

I suspect some kind of thread problem, but that's why I told it to change between fullscreen and windowed mode inside the thread, so it wouldn't try to access anything while messing around with displays.

Relevent code: Extract from the JFrame constructor:

initWindow();
if(fullScreen){
    initFullscreen();
}
//Setting graphics buffer strategy
createBufferStrategy(2);//double-buffered
bufferStrategy = g开发者_运维技巧etBufferStrategy();

Entirety of screenUpdate() (in the update-draw loop):

try{
        graphics = bufferStrategy.getDrawGraphics();
        gameRender(graphics);
        graphics.dispose();
        if(!bufferStrategy.contentsLost()){
            bufferStrategy.show();
        }else{
            System.out.println("Contents Lost");
        }

        //Sync the display on some systems. (I'm told that on Linux, this fixes event queue problems)
        Toolkit.getDefaultToolkit().sync();
    }catch (Exception e){
        e.printStackTrace();  
        dontExit = false;
    }

gameRender() just draws a random ellipse.

Also:

private void initFullscreen(){
    if (!gDevice.isFullScreenSupported()){
        System.out.println("Full-screen exclusive mode not supported");
    }else{
        gDevice.setFullScreenWindow(this);

        validate();

        setDisplayMode(resolutionX, resolutionY, 32);//TODO: set to current resolution instead

        fullScreen = true;
    }
}

private void disableFullscreen(){
    gDevice.setFullScreenWindow(null);

    fullScreen = false;
}

Edit: So, I guess my question comes down to; Why is BufferStrategy changing state, what is it changing to, and how can I prevent it? This bug is most peculiar if it really does only show up the first time it runs after startup, and a few frames after changing to fullscreen.

Edit2: Here's the compilable and runnable source: [Zip file]http://www.albeyamakiir.hostzi.com/web_documents/LighSpeedFrame.zip


Verify that you are constructing the GUI on the event dispatch thread.


I don't know what is wrong, but I should try to compare your code with the code from Ivo Wetzel his game engine called Bonsai, written in Java. I used it for some of my games. And it works quite perfectly. But keep in mind, if you would use the engine there were some errors with Mouse Events (depending on fullscreen mode enabled or not), I think the location was incorrect...

And if the problem is the "Exclusive Fullscreen Mode", then you can try to set your frame fullscreen with some tricks:

frame.setUndecorated(true);
frame.setPreferredSize(Toolkit.getDefaultToolkit().getScreenSize());
frame.setAlwaysOnTop(true);
frame.pack();
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜