Skip to main content

Use directx or Jogl acceleration may be less interesting than turn of them.

6 replies [Last post]
claudeabb
Offline
Joined: 2006-08-09
Points: 0

Hi Everybody,

Has anybody noticed that the using of directx or Jogl may slow down a swing application displaying? (at least since Java 1.6.10 and later, No problem with all the previous recent version).

I have written an animation scheduler that looks like flash editor.
The animation does not currently work in full screen mode.

I have made some tests using diferent ways to animate some elements. and the results I got are quite different.

1) I have created two BufferedImages on which the elements are drawn. while the first BufferedImage is shown ,I draw onto the second one and so one (nothing special , it's the double buffering approach)
The BufferedImages are drawn to the graphics context of a JPanel.
To get the best result, I have to turn off the graphical acceleration through the parameter sun.java2d.d3d=false

2) I have created a canvas and used the bufferstrategy features with of course the DirectX acceleration turned on.

Until now I get better results with the first way above all when calculation to transform the elements are needed.

The second approach is quite similar as the first one if directx is turned off too, but where is the interest to use buffer strategy if the graphical acceleration is turned off.

Simple case.
The main container (JPanel or Canvas) dimensions: 700x700
The only one element is an image: dimensions: 291x 222

I have set that the animation has 103 cycles, the image appears onto the screen with a blur effect. (the main rule that the scheduler has to take care is the total time that the animation has to take to be played entirely even if for that some frames have to be skipped. (nothing special common case)

Results:
FPS Settings

75 FPS 60 FPS 50 FPS 40 FPS 30 FPS

sun.java2d.d3d=false
First way:
Number of frames
skipped: 12/103 2/103 0/103 0/103 0/103

sun.java2d.d3d=true
BufferStrategy and
canvas
Number of frames
skipped:
36/103 22/103 5/103 2/103 0/103

Finally whatever the approach used, as soon as the d3d pipeline is turned on , the animation slow down.

any idea?

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
mikofclassx
Offline
Joined: 2003-07-02
Points: 0

Source please..

claudeabb
Offline
Joined: 2006-08-09
Points: 0

Hi

Sorry but this application is huge. several thousand of lines code just for the animation part.

As I already wrote, there is no any problems while I use the previous versions of Java 1.6.0_13.
After more investigation it seems that the JNI memory exchanges suffer also of slow down. Indeed some transform effects need a lof of calculation (done at least 25 times per second) that's why I have written some of them in Pascal. It's mainly these effects wich take much more time to be managed as soon as the graphical acceleration is turned on.

All the tests I made have been done on different OS and I got the same results.
Windows XP, Vista and Seven.

Note that the first test case described in the first topic does not use any JNI effects.

claudeabb
Offline
Joined: 2006-08-09
Points: 0

Hi

After more investigation I have figured out what takes much more time to be treated. The problem occurs as soon as java 1.6.0_10 version and next are used.

These ones implement a new Graphics2D pipeline rendering.

To transform a picture I get an int array of pixels colour value by the method
pixels= (int[]) image.getRaster().getDataElements(x, y, width, height,
null);

I apply some tranformations to this array and upload it back into the original BufferedImage via the method
image.getRaster().setDataElements(x, y, width, height, pixels);

It's precisely these both methods which take more time as soon as the graphic acceleration is turned on.

It seems preferable to recreate a new bufferededimage than changes an existing one following the few lines code hereafter:

public static BufferedImage getBI( ColorModel dstCM, int[] pixels, int w, int h) {
int[] bitMasks = new int[] {0x00ff0000, 0x0000ff00, 0x000000ff, 0xff};
SinglePixelPackedSampleModel sampleModel = new SinglePixelPackedSampleModel(
DataBuffer.TYPE_INT, w,
h, bitMasks);
DataBufferInt d = new DataBufferInt(pixels, pixels.length);
WritableRaster destRaster = Raster.createWritableRaster(sampleModel, d, null);

BufferedImage res = new BufferedImage(dstCM, destRaster, true, null);
return res;
}
.
For a same test case the first method takes about 15ms and the next on less than 2ms.

Is there any other faster way to get an int array of a picture' pixels instead using getDataElements?

Note that all bufferedimages are created using the lines code:

GraphicsEnvironment environment =
GraphicsEnvironment.getLocalGraphicsEnvironment();

GraphicsDevice device =
environment.getDefaultScreenDevice();

GraphicsConfiguration config = device.getDefaultConfiguration();

bi = config.createCompatibleImage(this.getWidth(), this.getHeight(),Transparency.TRANSLUCENT);

Maybe the translucent type is neither the good parameter and that this one should be substitud by bitmask.

The Bufferedimage type create is TYPE_INT_ARGB_PRE.

Any remark that could improve the complete process is welcome.

Claude

linuxhippy
Offline
Joined: 2004-01-07
Points: 0

byte[] data=((DataBufferByte)tex.getRaster().getDataBuffer()).getData() or the equivalent for your image type.
This way you have *direct* access to the image data.

You should not however that you'll use all acceleration for this image when using it.

- Clemens

claudeabb
Offline
Joined: 2006-08-09
Points: 0

Hi Clemens

Thanks for your prompt answer.

I know this other manner which can also be substitued by

DataBufferInt dataBuffer = (DataBufferInt)raster.getDataBuffer();
int pixels[] = dataBuffer.getData();

but make any modifcation to this array seems modify the original bufferedimage.

I have not understood what do you mean by
"You should not however that you'll use all acceleration for this image when using it."

Please explain with more details

Claude

claudeabb
Offline
Joined: 2006-08-09
Points: 0

Hi

Finally the response time issue is due to using a bufferedImage "ARGB" with the [b]alpha pre-multiplied[/b].

This kind of bufferedimage is automatically returned if I use the code hereafter:

GraphicsEnvironment environment = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice device =
environment.getDefaultScreenDevice();
GraphicsConfiguration config = device.getDefaultConfiguration();
bi = config.createCompatibleImage(this.getWidth(), this.getHeight(),Transparency.TRANSLUCENT);

Before being able to modify any pixel value we have to get all the pixels using in this case the method getRGB instead getDataElements directly because the pixels’ value have first to be converted into a non pre-multiplied format.

I wonder why this kind of "heavy" treatment has not been written in native language exactly as it's the case for the method System.arraycopy? Finally it’s just a matter of manipulating an array’s values.

I do not want use only no pre-multiplied bufferedimage because I have to manage some blur effects.

Claude