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.