Skip to main content

volatile image slow?

1 reply [Last post]
jn
Offline
Joined: 2004-11-23

I'm trying to improve the rendering speed of a custom graphics-intensive component we have. It's basically a graph view with a large number of vertices and edges.

Rendering the vertices directly to the drawing surface is slow, particularly since we need to use anti-aliasing. Since a lot of the vertices look the same, I'd like to pre-render them to an image in vram, so that I can get very fast image draws of that image to the screen. I understand that I have two options: managed images, and volatile images. I tried both approaches, but for some reason the results for the volatile image approach were very poor. In one of my tests, I have managed images at 300fps, and volatile images at 15fps.

I'd really like to get the volatile image approach working for the following reason. It's my understanding that managed images keep two copies of the image data around -- one in system memory and one in vram (space permitting). I'd like to avoid keeping the extra image data in system memory, because it could potentially use a lot of memory. Since the images are rendered from icons (specifically, svg), I can re-render them at any time, without needing to keep the rendered image data around in system memory.

Since managed images supposedly use volatile images under the cover, I must be doing something wrong. Here's what I'm currently doing. I wrote a simple icon wrapper (called AcceleratedIcon) which simply wraps some other icon and renders to an intermediate volatile image. Whenever paintIcon() is called, it checks if the volatile image is still the right size and still valid; if necessary it constructs a new image and/or re-renders the icon contents. My managed image approach is just a variant of this.

Following are the significant code parts for the volatile image approach. There's a little complexity to support arbitrary scaling (depending on the affine transform, the image buffer may be larger or smaller than the icon size). The scaling is partially done and some of it is commented out, but that's just an implementation issue you can ignore.

private final Icon icon; // initialized in constructor
private VolatileImage image;

public void paintIcon(Component c, Graphics g, int x, int y) {
Graphics2D graphics = (Graphics2D) g;
AffineTransform transform = graphics.getTransform();
double scaleX = 1.0; // transform.getScaleX();
double scaleY = 1.0; // transform.getScaleY();
int width = this.width; // icon.getIconWidth();
int height = this.height; // icon.getIconHeight();
int imageWidth = (int) (scaleX * width);
int imageHeight = (int) (scaleY * height);
if (image != null && (image.getWidth() != imageWidth || image.getHeight() != imageHeight)) {
image = null;
}
do {
GraphicsConfiguration gc = c.getGraphicsConfiguration();
if (image == null) {
image = c.createVolatileImage(imageWidth, imageHeight);
image.setAccelerationPriority(1.0f);
paintIcon(c, image, width, height);
}
else if (image.validate(gc) != VolatileImage.IMAGE_OK) {
System.err.println("rendering icon");
paintIcon(c, image, width, height);
}
//graphics.drawImage(image, x, y, x + width, y + height, 0, 0, imageWidth, imageHeight, null);
graphics.drawImage(image, x, y, null);
}
while(image.contentsLost());
//graphics.dispose();
}

private void paintIcon(Component c, VolatileImage image, int width, int height) {
Graphics2D imageGraphics = (Graphics2D) image.getGraphics();
//imageGraphics.setComposite(AlphaComposite.Src);
icon.paintIcon(c, imageGraphics, 0, 0);
imageGraphics.dispose();
}

Any help is appreciated. Thanks,
Jim

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
jn
Offline
Joined: 2004-11-23

Well, I never got an answer to this question, but I eventually figured it out. The component that I was drawing to was doing some double-buffering on its own, so that I was rendering into an image and then that image was being copied to the screen. I presume that using a volatile image slow because the image data was read back from vram in order to write it to the image buffer which was not in vram.