Sun engineering dude Chet Haase’s latest blog entry explains some concepts of VolatileImages. It’s worth a read…
http://weblogs.java.net/pub/wlg/435
“Rendering-to and Copying-from should be way faster than the current BufferedImage objects”
I thought my hardware accelerated “automatic images” had the same performance as volatile images?
I use
image = Toolkit.getDefaultToolkit().getImage(imageName);
to load images and they get painted to my back buffer which is created with
private BufferStrategy bs;
.
this.createBufferStrategy(2);
bs = this.getBufferStrategy();
(in the loop)
Graphics g = bs.getDrawGraphics();
.
render(g);
g.dispose();
am I doing something wrong. Should I have volatile images and do the checks that he lists in the article for content loss?
I think that automatic or managed image automatically do the checking for you and restore themselves. I’ve been wrong before though.
[quote]Sun engineering dude Chet Haase’s latest blog entry explains some concepts of VolatileImages. It’s worth a read…
http://weblogs.java.net/pub/wlg/435
[/quote]
Pretty much what the javadoc comments say for VolatileImage.
How recent is that article?
I was under the impression the VolatileImage API is going to be considerably different in 1.5 in light of the fact the API simply can’t work correctly for translucent images :o
He posted it on the 9th.
What is the issue with translucent images? Why can’t it work?
Because the ‘while’ render loop (quoted below) can result in the image being drawn onto the destination more than once.
Which, in the case of a translucent image [or some of the more exotic AlphaComposite operations] will have a cumulative effect. (OPAQUE and BITMASK images drawn with SRC_OVER do not suffer from this issue because destination pixels are either written, or not written, they are never composited with the source)
1 solution would be to change the definition of the contentsLost() method from this :-
to this :-
However, if you were drawing the VolatileImage multiple times, you would have to check contentsLost after each draw operation. Which IMO is ugly, tedious and slow.
I think the entire API needs rethinking.
Do we realy need to know whether the underlying accelerated surface was lost?
I believe ManagedImages are the solution; where by a copy in main memory is kept at all times, and the managment (and rebuilding) of the volatile surface is managed entirely out of our hands.
do
{
int valCode = backBuffer.validate(comp.getGraphicsConfig());
if (valCode == VolatileImage.IMAGE_RESTORED)
{
// This case is just here for illustration
// purposes. Actually, since we are
// recreating the contents of the back buffer
// every time through this loop, we actually
// do not need to do anything here to recreate
// the contents. If our VImage was an image that
// we were going to be copying from, then we
// would need to restore the contents at this point
}
else if (valCode == VolatileImage.IMAGE_INCOMPATIBLE)
{
createBackBuffer();
}
// Now we've handled validation, get on with the rendering
// rendering to the back buffer:
// Graphics gBB = backBuffer.getGraphics();
// gBB.setColor(lineColor);
// gBB.drawLine(0, 0, 50, 50);
// gBB.drawImage(sprite, 0, 0, this);
// etc.; left as an exercise to the reader
g.drawImage(backBuffer, 0, 0, this);
}
while (!backBuffer.contentsLost());
Thanks for checking out the blog: It’s so nice to get noticed!
Let me clarify a couple of things about VolatileImages and the issues that were raised on this forum.:
-
VolatileImage vs. managed images (aka “automatic images”, but I prefer “managed images” because it’s more accurate and informative): There is almost no reason to use VolatileImages instead of managed images for most cases. The only reasons to use a VolatileImage are:
- If you want rendering TO the image to be accelerated (managed images have their primary copy in system memory and thus all rendering operations TO that image happen through software routines)
- If you want to more actively manage the accelerated memory (eg, VRAM). It’s a little easier to tell what’s going on with a VolatileImage (in terms of VRAM usage) than with a managed image.
If all you want is a sprite that probably gets accelerated for its copies to the back buffer or screen, managed images are the way to go. No need to hassle with Volatiles.
-
VolatileImage vs. BufferStrategy buffers: If you are using a BufferStrategy, then these are (sorta) managed for you; if one gets lost, then it will automatically be reinstated (we manage all of this with VolatileImages internally, and call validate when necessary). Note that you still have a contentsLost() method and situation to deal with, but in the case of a back buffer (which gets re-rendered every frame), that’s not a big deal since you’re just going to wipe it and re-render anyway.
-
VolatileImages and translucency:
a) The API: in 1.5, we will (finally) have the ability to create a translucent VolatileImage (currently, you can only get an opaque VImage).
b) contentsLost() and re-compositing VImages problems: I don’t see a huge issue here. Image loss is not a common occurrence (unless your game wants to change the display mode every frame to freak out the users. I can see it now: “Seizure: A game of epileptic proprotions”). So the way to handle any image loss situation is just to re-render the entire frame. Sure, it costs you a frame’s worth of rendering time; but when the display mode changes there are a lot more disturbing things happening on the screen than an momentary drop in your frame rate. -
VolatileImage and automatic revalidation:
The whole reason that we force you to manage these images is that we cannot restore the contents for you. If we were to keep the primary copy in memory and do an automatic restore (hmmm - sounds like a managed image to me…), then by definition, we would have to do all of the rendering to that primary surface first (since we can lose the VRAM version at any time). This means that all of that fine rendering would happen through our software loops and you’d lose the benefits of hw acceleration on your rendering-to ops. “But I don’t care about the render-to speed; I only render to my sprites once and then just care about the copy-from speed” - See my point above about managed images; you shouldn’t have to use a VolatileImage in this case.
Hopefully this clears things up a bit. In any case, please check out the follow-on blog, which is basically a series of Q&As on common VolatileImage issues (including some of the points raised here; in fact, I might borrow some of these ideas for more Qs).
And feel free to post replies to the blogs; I think the discussions after the blogs can be even more informative than the original article (check out the ones on BufferedImage on that site; there’s some good stuff in the feedback sections).
Chet.
I agree, it isn’t a huge issue, but it is a bug[limitation?] in the API that could (admittedly only in very bizarre situations) cause graphics corruption of certain images :