Properly using VolatileImage

I’ve been reading about VolatileImage but I’m not sure I know how to use it properly yet, so I was hoping somebody could look at this program I wrote. Is there anything I should be checking but aren’t? Things that I’m checking but I shouldn’t? If it means anything, the picture I’m trying to draw is translucent.

Also, I read I should use sun.java2d.trace to detect software rendering, but I don’t quite understand it. I set it to “count” and I see the following when my program ends.

1 call to sun.java2d.loops.Blit$GeneralMaskBlit::Blit(FourByteAbgr, SrcNoEa, IntArgbPre)
101 calls to D3DFillRect
1 call to sun.java2d.d3d.D3DSurfaceToGDIWindowSurfaceBlit::Blit(“D3D Surface”, AnyAlpha, “GDI”)
89 calls to sun.java2d.d3d.D3DRTTSurfaceToSurfaceBlit::Blit(“D3D Surface (render-to-texture)”, AnyAlpha, “D3D Surface”)
1 call to sun.java2d.d3d.D3DGeneralBlit::Blit(Any, AnyAlpha, “D3D Surface”)
3 calls to sun.java2d.loops.FillRect::FillRect(AnyColor, SrcNoEa, AnyInt)
1 call to sun.java2d.loops.MaskBlit::MaskBlit(IntArgb, AnyAlpha, IntArgbPre)
1 call to sun.java2d.windows.GDIBlitLoops::Blit(IntRgb, SrcNoEa, “GDI”)
1 call to sun.java2d.loops.MaskBlit$General::MaskBlit(FourByteAbgr, SrcNoEa, IntArgbPre)
1 call to sun.java2d.loops.Blit::Blit(FourByteAbgr, SrcNoEa, IntArgb)
200 total calls to 10 different primitives

I’ve assumed that “sun.java2d.loops” indicates software rendering but…well I’m not sure what to do about that.

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.awt.image.VolatileImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.Timer;

public class Main implements ActionListener {
    static final GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
    static final GraphicsDevice gd = ge.getDefaultScreenDevice();
    static final GraphicsConfiguration gc = gd.getDefaultConfiguration();
    static BufferedImage bufferedImage;
    static VolatileImage image;
    static BufferStrategy bs;
    static JFrame frame;

    public static void fillImage(){
        Graphics2D g = image.createGraphics();
        g.setComposite(AlphaComposite.Src);
        g.drawImage(bufferedImage, null, 0, 0);
        g.dispose();
    }

    public static void main(String[] args) throws IOException {
        String os = System.getProperty("os.name");
        System.setProperty("sun.java2d.trace", "count");
        if(os.contains("Windows")){
            System.setProperty("sun.java2d.d3d", "True");
        }else{
            System.setProperty("sun.java2d.opengl", "True");
        }
        bufferedImage = ImageIO.read(new File("fig6.png"));
        do{
            image = gc.createCompatibleVolatileImage(bufferedImage.getWidth(), bufferedImage.getHeight(), bufferedImage.getTransparency());
        }while(image.validate(gc) == VolatileImage.IMAGE_INCOMPATIBLE);
        fillImage();

        frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
        frame.setIgnoreRepaint(true);
        frame.createBufferStrategy(2);
        bs = frame.getBufferStrategy();
        frame.setSize(500, 500);
        frame.setLocationRelativeTo(null);
        new Timer(16, new Main()).start();
    }

    public void actionPerformed(ActionEvent e) {
        while(image.validate(gc) != VolatileImage.IMAGE_OK){
            while(image.validate(gc) == VolatileImage.IMAGE_INCOMPATIBLE || image.contentsLost()){
                image = gc.createCompatibleVolatileImage(bufferedImage.getWidth(), bufferedImage.getHeight(), bufferedImage.getTransparency());
            }
            fillImage();
        }
        do{
            Graphics g = bs.getDrawGraphics();
            g.setColor(Color.black);
            g.fillRect(frame.getInsets().left, frame.getInsets().top, frame.getContentPane().getWidth(), frame.getContentPane().getHeight());
            g.drawImage(image, 0, 0, null);
            g.dispose();
        }while(bs.contentsLost());
        bs.show();
    }
}