TransAccel

A simple question about transparent acceleration of managed images:

I tried to access the pixels directly through Raster->DataBufferInt but as soon as I call:


DataBufferInt dbi = (DataBufferInt)(raster.getDataBuffer());

the image becomes non accelerated and there’s apparently no way to “re-accelerate” it.

I also noticed that setting the raster pixels with:


raster.setPixel(x,y,a,r,g,b);

works, but I suppose this solution gives very low performance expecially if compared to direct pixel access in the DataBuffer array.

so the question is: which is the best way to change the pixels of an accelerated (managed) image on the fly ?
Maybe an image copy ? Yes, could be, but imagine you want to direct-access the pixels to do some kind of filtering…

Mik

What you keep bumping into is the bus between client and server here.

An accelerated image lives on the “server” side - the graphics card. It’s a very, very slow operation reading data back across the AGP (or worse, PCI) bus and modifying it.

The moment you want to get access to some ints to play with, Java has to read the whole thing back from the server, and then copy it into an array of ints. You are then of course not dealing with VRAM at all, it’s just plain Java heap memory. You could conceivably do all sorts of dickery with the image data and then punt it back into VRAM but if you’re doing it on a frame-by-frame basis your performance will totally bomb from the original read operation.

The only way to do what you want to do correctly is to be able to send “server” drawing commands to the graphics chip to get it to achieve the same effect but without the “client” ever knowing what the pixels actually are.

Cas :slight_smile:

There is no read-back from vram when using managed images.
When you modify a managed image, you are changing the copy on the java heap. Doing this, causes the vram copy to be invalidated, this means the next time you draw the image it will be using the version on the heap, hence the operation wont be hardware accelerated.
If you are using the default settings, it takes 2 image draws before the image will be re-cached in vram.

As to your problem, if you want to modify an image but keep it accelerated, use a VolatileImage.
You will then be modifying the image in vram directly. However, if your filtering requires any operation that can’t be done in hardware, the image in vram will have to be shunted back to the heap (which as Cas pointed out, is painfully slow)

fillrect is hardware accelerated, so you could use that - however, if you are performing the filter operation on every single pixel in an image, it would likely be just as slow as doing the filtering using a software loop.

How often are you performing the filtering operation?
and how many of the images pixels are modified in a single filter pass?

If its every game frame, and most of the pixels, your best option is to not cache the image in vram at all.
Modify it on the heap, and then draw it from there.
(basically you want an unmanaged image)

The volatileimage approach outlined by Abuse is something I should investigate.

The main problem I have is accelerating translucent blits of dynamically changing images i.e. coming from an AVI stream.

Maybe using a volatileimage I could copy AVI frame data there by using JNI and still keep hardware accelerated blits. By doing this way I could avoid a double copy from jni-heap to java-heap to image raster and do a simple jni-heap copy to image raster.

Reading back pixels from “server” to “client” could be a minor issue as I could still double-buffer pixel operations into the java heap and then copy the result to he accelerated image.

There’s one big sad point affecting the performance of Java2D gaming/graphics on Win: we always talk about accelerating translucent blits, but we always have to keep in mind that acceleration only takes place with non-affinetransformed Graphics2D contexts.

p.s. Hey PrinceC you didn’t reply to my last post in “Managing graphics memory” !

I’ll get round to it :wink:

Cas :slight_smile: