Double Buffering in Applets

I come across an article that was talking about double buffering for games. https://ping.dev.java.net/

They using BufferStrategy to manage the double buffering (which may use VolatileImage in the background). I currently have some good for applet that creates a BufferedImage, but would like to change it to use BufferStrategy and take advantage of VolatileImage. However, createBufferStrategy seems to only exist on java.awt.Window which JApplet is not a part of.

So does this mean you are stuck using VolatileImage directly yourself?

use a Canvas to render your game (see Canvas.createBufferStrategy(int))

it extends Component so you can just add it on top of your JApplet

What if I want to add swing UI around the game area? IIRC you not suppose to mix heavyweight (Canvas) with lightweight components (JButton, etc)

Hi!
This quite simple to implement if you’re familiar with Graphics components and the Swing interface. As a rule, each Swing or AWT components inherits from the JComponent and deeply to Component whose abstract methods are to be implement by each subclasses. That is, Canvas is an AWT component. If you want Double-Buffering you must use an Image to store your graphics-buffer before to paint. As a second rule, each Component uses ALL THE RESOURCES FROM A ComponentPEER which is deeply the ScreenDevice your focusing on, and hopefully your screen. Then it’s up to you to manage to fetch all required resources from this PEER. As a consequence, the JApplet, which has no other peer than the AppletViewer or the Browser, cannot get all information from the screen devices. This is the reason why Canvas cannot occur on a JApplet with full support unlike a Frame would.
Solution should be to instance a new Window for your applet and to put the Applet in it or, an easier way is, to let the JApplet logging data and focus on user interface, while another Window will display your contents.
Moreover, double-buffering is implemented in all JComponents-subclasses so that you don’t need to touch them if you don’t customize them, obviously.

I’d say to choose whether to use Applet or Window for your applications, depending on what you’re looking forward to do. To summarize, Volatileimage contents should be used only if you’re in a fully supported environment, in the lesser case you will substitute VolatileImage to BufferedImage that are supported by all browsers. ::slight_smile:

So to clarify what you said… Don’t mix AWT with Swing?

And what do you mean by VolatileImage should only be used in fully supported environment? What is a fully supported environment?

What restrictions do applets have in terms of using VolatileImage?

it’s not about mixing, because Swing is AWT extended. It’s about a better interpreted environment, that is to check for required capabilities (look for Capabilities in the JDK !).

For instance, VolatileImage are used to get instanced if and only if the VRAM buffer is activated for a specific config. You cannot change this property, or you may try the java2d forceVram JVM option. VolatileImage fetches for a memory allocation directly in the VRAM buffer. Say you have a 2D/3D accelerated graphics card in your pc-box, then VolatileImage is obviously a supported capability (Capabilites.isTrueVolatile() and you can use native codecs management, too).
So it is for VolatileImage, so on it is for BufferStrategy which features multi-buffer flipping. There are several options to check for before you launch your graphical environment. BTW a native Graphical Environment means that VRAM is fully used unlike a software Graphical Environment would use the shared memory buffer in your system RAM.

Hence understand that sharing memory for both graphics Threads and usual system Threads is very “tightened” for the System to constrain its resources (just have a look to your system resources usage if you’re in Win32 environment)!

E.g. for Applets, just try to put a VolatileImage entirely covering the background of your applet ! You’ll see that your buffer is sometimes reconstructed and that the background desapear or crashes somehow when invoking repaint() several times. Next time use a BufferedImage and you’ll certainly observe a better and smoother rendering !
To make a correct use of the VolatileImage, instance a Frame cover the background with the same VolatileImage and repaint() several times, no crashes should occur or your config doesn’t support it ! :smiley:

Here is my current code for rendering


// off screen rendering
        private Graphics dbg;
        private Image dbImage = null;

        private void updateDisplay() {
            if (dbImage == null) {
                // Create buffer image
                        dbImage = createImage(width, height);
                        if (dbImage == null) {
                                System.out.println("dbImage is null");
                                return;
                        } else {
                                dbg = dbImage.getGraphics();
                        }
                }

            // Render frame to off-screen buffer
            renderFrame((Graphics2D) dbg);

                // Use active rendering
            Graphics g;
                try {
                       g = this.getGraphics();
                        if ((g != null) && (dbImage != null)) {
                                g.drawImage(dbImage, 0, 0, null);
                                Toolkit.getDefaultToolkit().sync();  // sync the
 display on some systems
                                g.dispose();
                        }
                } catch (Exception e) {
                        System.out.println("Graphics context error: " + e);
                }
        }

I was just looking to use createVolativeImage instead of createImage. And the best way todo that for an JApplet. JApplet doesn’t provide createBufferStrategy and using JFrame not an option since I want to use JApplet for display in the page.

Are you by any chance reading the book written by Andrew Davison? This code looks awfully familiar :slight_smile:

Yes, this code is basically what he shows in “Killer Game Programming in Java”.

can you put here some demo ?

Here is my VolatileImage version. I did some testing and it was roughly 150% faster.


	public void updateDisplay() {
		if (vImg == null) {
			vImg = createVolatileImage(getWidth(), getHeight());
		}

		Graphics g = this.getGraphics();
		do {
			int returnCode = vImg.validate(getGraphicsConfiguration());
			if (returnCode == VolatileImage.IMAGE_INCOMPATIBLE) {
				// old vImg doesn't work with new GraphicsConfig; re-create it
				vImg = createVolatileImage(getWidth(), getHeight());
			}
			Graphics2D dbg = null;
			try {
				dbg = vImg.createGraphics();
				renderFrame(dbg);
			} finally {
				if(dbg != null) dbg.dispose();
			}
			g.drawImage(vImg, 0, 0, null);
		} while (vImg.contentsLost());
		Toolkit.getDefaultToolkit().sync();  // sync the display on some systems
		g.dispose();
	}

Okay I have uploaded the file here http://grom358.mygamesonline.org/bouncingballs_src.7z

In Main.java you can change with rendering option to use between Canvas with BufferedStrategy, BufferedImage JComponent and VolatileImage JComponent. Please note the code is a bit rough and is just for demo purposes.

PS. Anyone know of good file upload sites? My personal homepage host doesn’t allow uploading of zip files and limited to 500Kb. Makes it hard to share source code. Even this forum only allows attaching image files.