I’m writing a small Asteroids clone (Stroids 8)), and on my first slightly playable build, I noticed that my graphics were lagging something horrible. So I logged on here, looked around, and noticed that VolatileImage is recommended for doing graphics. I was using BufferedImage and Graphics.drawImage(buffered, x, y, null), so I thought the volatile might work better.
So I wrote a simple class today and tested it. And much to my astonishment, BufferedImage is outperforming VolatileImage ( :o). This doesn’t make sense except that I have onboard video so there may be some hidden optimization. What I’m wondering is if anyone can spot something I did wrong in this test.
public class Form extends JFrame imple....
...
private BufferedImage buffered1;
private BufferedImage buffered2;
private VolatileImage volatile1;
private VolatileImage volatile2;
private VolatileImage comp;
private javax.swing.Timer timer;
public Form()
{
super();
setSize(800, 800); //This is the same size Stroids uses
setVisible(true);
//Load the buffered images
try {
buffered1 = ImageIO.read(new File("img1.png"));
buffered2 = ImageIO.read(new File("img2.png"));
} catch (IOException ex) {
ex.printStackTrace();
}
...
x = 0; //Initalize the scrolling variables
y = 0;
timer = new javax.swing.Timer(30, this); //Create a timer to cause a repaint every 30 ms
timer.start(); //Start the timer
}
/*
* One or more of the VolatileImages needs to be re-created, or created the first time
*/
private void restoreVolatiles()
{
if (volatile1 == null) //No image
volatile1 = createVolatileImage(800, 800); //Create the image
if (volatile2 == null) //No image
volatile2 = createVolatileImage(20, 20); //Create the image
if (comp == null) //No image (used for off-screen rendering)
comp = createVolatileImage(800, 800); //Create the image
Graphics g;
if (volatile1.validate(getGraphicsConfiguration()) != VolatileImage.IMAGE_OK) //Not ok, so redraw it
{
g = volatile1.getGraphics();
g.drawImage(buffered1, 0, 0, this);
}
if (volatile2.validate(getGraphicsConfiguration()) != VolatileImage.IMAGE_OK) //Not ok, so redraw it
{
g = volatile2.getGraphics();
g.drawImage(buffered2, 0, 0, this);
}
}
public void paintComponent(Graphics _g2)
{
Graphics2D g2 = (Graphics2D)_g2;
long volatileDuration, bufferedDuration; //Used to determine how long rendering takes
long startNano = System.nanoTime(); //Get the start time
if (volatile1 == null || volatile2 == null ||
volatile1.validate(getGraphicsConfiguration()) != VolatileImage.IMAGE_OK || volatile2.validate(getGraphicsConfiguration()) != VolatileImage.IMAGE_OK)
{ //Check if anything needs to be fixed (always runs on first time through: volatile1 == null)
restoreVolatiles(); //Restore the volatiles
}
Graphics2D g = comp.createGraphics(); //Get the graphics to composite it
g.drawImage(volatile1, 0, 0, this); //Draw the background (big, 800x800)
g.drawImage(volatile2, x, y, this); //Draw the random image (small, 20x20)
g2.drawImage(comp, 0, 0, this); //Copy to the screen (big 800x800)
volatileDuration = System.nanoTime() - startNano; //Get the time taken
startNano = System.nanoTime(); //Get the start time
g2.drawImage(buffered1, 0, 0, this); //Draw the background
g2.drawImage(buffered2, x, y, this); //Draw the random image
bufferedDuration = System.nanoTime() - startNano; //Get the end time
//Now print out the stats
try
{ //writer is initalized in the constructor, and is a FileWriter
System.out.println("Buffered draw took " + bufferedDuration / 1000000.0 + " ms.");
writer.write("Buffered draw took " + bufferedDuration / 1000000.0 + " ms.\n");
System.out.println("Volatile draw took " + volatileDuration / 1000000.0 + " ms.");
writer.write("Volatile draw took " + volatileDuration / 1000000.0 + " ms.\n");
System.out.println("Volatile was faster by " + (bufferedDuration - volatileDuration) / 1000000.0 + " ms.");
writer.write("Volatile was faster by " + (bufferedDuration - volatileDuration) / 1000000.0 + " ms.\n");
writer.flush();
} catch (IOException ex)
{
ex.printStackTrace();
}
}
}
The file that writer prints to gives this (only an excerpt):
[quote]Buffered draw took 0.058667 ms.
Volatile draw took 0.118451 ms.
Volatile was faster by -0.059784 ms.
Buffered draw took 0.060064 ms.
Volatile draw took 0.111466 ms.
Volatile was faster by -0.051402 ms.
Buffered draw took 0.059225 ms.
Volatile draw took 0.136889 ms.
Volatile was faster by -0.077664 ms.
Buffered draw took 0.059225 ms.
Volatile draw took 0.135213 ms.
Volatile was faster by -0.075988 ms.
Buffered draw took 0.056432 ms.
Volatile draw took 0.143874 ms.
Volatile was faster by -0.087442 ms.
Buffered draw took 0.059784 ms.
Volatile draw took 0.137168 ms.
Volatile was faster by -0.077384 ms.
Buffered draw took 0.062019 ms.
Volatile draw took 0.137168 ms.
Volatile was faster by -0.075149 ms.
[/quote]
I am missing something? Is my rendering strategy off? Or do I just need to render many more images per cycle to see the difference? ???