VolatileImage under D3D

I’m in the early stages of developing an accelerated graphics engine for Java 5. I’m relying heavily on the performance benefits of the VolatileImage class, and am currently testing the project with Direct3D. Most of what I’ve tried to do so far has been successful, but I’ve reached an odd stumbling block which doesn’t really make sense when I try to rationalize it.

The major problem I’m having is that, although I’m able to support translucent ARGB images, simple transparent colors provided by the Color class slow down performance substantially. If I try to use the fillRect(x,y,w,h) method in the Graphics class, and the current Color has an Alpha component, rendering slows to a crawl.

I’ve posted a screenshot of the display as it is when it’s running correctly:

http://people.umass.edu/eraboin/volatile.jpg

As you can see, I have three windows open, and one of them is maximized. The number in the top left corner is the framerate, which should be independant of the framerate of the model. The borders on the top and the bottom of the screen are drawn with the ‘fillRect’ method, only the Color is a solid black.

Now, here’s a screenshot when I set the border to a translucent Color.

http://people.umass.edu/eraboin/slow.jpg

Now the framerate has dropped substantially. For some reason the simple change in translucency devastates performance. This is in spite of the fact that I’m drawing 6 of those huge ARGB bubbles in both pictures, which should (by common sense) be a far more demanding operation.

I should also mention, the same thing happens if the images I draw have not been converted to ARGB BufferedImages before I render them. For instance, if I just used the BufferedImage produced by ImageIO.read(str), it would have the same negative impact.

I’m wondering if the properties of the VolatileImage are being adversely affected when I perform these operations. The reason I ask, is because the operation that’s most affected by this change is the one which immediately follows it. After a frame is finished rendering, I draw it to my Component coupled with the Graphics2D ‘scale’ operation. It’s the scaling that suffers the most, since it performs very quickly in normal situations, but seems to run incredibly slow otherwise.

When I create my VolatileImage I use;

getGraphicsConfiguration().createCompatibleVolatileImage(w, h, Transparency.OPAQUE)

I don’t see any need for the VolatileImage itself to be transparent, since there’s nothing being displayed beneath it. Transparency only matters for the images being drawn on top, such as ARGB BufferedImages.

If I create my VolatileImage using Transparency.TRANSLUCENT it also runs horribly, but the change is different. Whatever problem I’m experiencing with fillRect, it’s not the same thing, although both are irritating.

I’ve been hopping from forum to forum attempting to find a solution to this problem, and not being very successful. I think if I could get Java to load with OGL enabled, that might help me find a workaround (currently it crashes when I try this).

One solution was to create a BufferedImage for the entire layer, render it in the constructor, and just draw that to the VolatileImage. It worked, but it hogged about 2mb of memory… which is a lot of wasted resources for just a stupid border.

I enabled Java’s d3d logging feature, and I noticed something interesting. When the border is a solid color I get this output:

DDFillRect
DDFillRect

Which makes perfect sense, because there’s a rectangle at the top and at the bottom. But when I do it with a translucent border I get about 200 of these:

sun.java2d.loops.Blit$GeneralMaskBlit::Blit(IntArgb, SrcOverNoEa, “D3D texture destination”)
sun.java2d.loops.MaskBlit::MaskBlit(IntArgb, SrcOver, IntRgb)

Which… to me seems kind of pathetic. It’s almost as though the fillRect implementation is ‘tiling’ little translucent color swatches many times over. As a result this affects the VolatileImage in the same way as though I had used an unformatted BufferedImage.

This is all really stupid… I mean, I could write a custom implementation which does the same thing, only doesn’t screw up my acceleration. I’m beginning to wonder how much of this stuff needs to be obscured from the developer in order to preserve portability, and if we’d be better off if we had more control over graphics without resorting to JNI.

I don’t know whats the problem with your game, sorry, I am not one of those java2d gurus.

You already have direct control over graphics withought JNI, call it JOGL, LWJGL or GL4Java. Java2d wasn’t really designed for games but it does a very good job in accerlating almost everything. Have you ever tried writing a 2D game with those libs - its not a lot of fun and you have to play a lot to get as good performance as Java2d does (accerlated)!
The problem of portability is of course that you cannot accerlate everything everywhere that the API supports.

Also keep in mind that the D3D pipeline has been made available about 1-2months ago as alpha version.

As a short-term solution I would recommend to use the OGL-pipeline instead, its quite stable and I also think its good to keep some preassure on graphic-card manufactureres to support OpenGL well.

lg Clemens

Hi Michael,

it looks like you’re running your application on 5.0 or earlier release, is that the case?

If so, it’d explain the poor performance. In those releases there were only a handful of operations accelerated via direct3d.

One of them was acceleration of blits of translucent images, but only with special flag enabled. All you could do was blit a translucent image to an opaque volatile image. No transformations.

The rest of operations requiring compositing (like your fillRect with non-opaque color, or compositing with any composite with extra alpha) weren’t accelerated.

Translucent volatileImages are not accelerated either, they’re just BufferedImage with INT_ARGB format type, mostly added to the api for consistency.

In 6.0 aka mustang we do have a new Direct3D pipeline, starting with build b34, but it’s disabled by default (enabled via -Dsun.java2d.d3d=true). Note that in that build there were a number of performance issues, and on some video boards/desktop bit depth combinations it wasn’t enabed even with a flag.
Here’s more info on the pipeline:
http://weblogs.java.net/blog/chet/archive/2005/05/graphics_accele.html

In the upcoming build b39 (end of may) there will be a new version of the pipeline, with many fixed bugs and improved performance.

Have you tried your app with 6.0?

Also, what is your hardware configuration?

Thanks,
Dmitri
Java2D Team

Yeah, I’ve just been using Java 5…

I’ve got a Radeon 9800 128mb with Omega drivers 2.5.90 installed. I’m running this under Windows XP SP1, and P4 3Ghz with a gig of memory.

I find the general performance to be excellent, but when I perform certain operations (such as a translucent fillRect) it slows down everything else along with it.

I’m downloading Mustang right now, I’ll tell you how it performs when I get things up and running with it.

Hmm… it seems to have worked;

http://people.umass.edu/eraboin/fast.jpg

Plus, it allows me to use BufferedImages taken straight from ImageIO.read(…) now too… which is nice, because the code I was using to make a copy was lame anyway.

Scaling is also much faster too.