I'm working on a class this is responsible to manage 2D side scrolling using a map format generated by the map editor Mappy.

I've downloaded a provided source code to perform side scrolling in Java BUT it is really slow! :-/

I've wrote a simple test class that uses it. In this test class I set the mode in 640x480x32 with full screen exclusive mode. The program blits tiles on the entire screen with tiles of size 16x16.

Unfortunaly I get only 43 fps but from my point of view I should get near 75 fps (a preview program provided with the map editor acheives this rate). I mean, I run the test on an Athlon 1.4 gigaherts with a GeForce 2 32 megs of VRAM.

I think there is real problem here.

The tile images I blit are suppose to be accelerated because I create them using GraphicsConfiguration.createCompatibleImage(w, h)and withGraphicsConfiguration.createCompatibleImage(w, h, Transparency.BITMASK)

Is the code rendering _to_ those images on each frame? If so, the images aren't being accelerated, as we accelerate them after a few copies from the image have been made w/o the image being modified.

Also, have you tried to increase the tile size?

There is a way to find out if your tile images are accelerated: run your app with tracing turned on: java -Dsun.java2d.trace=log YourApp

(run it with -Dsun.java2d.trace=help for more info on the tracing facility)It'll spit out the information on which rendering primitives are being used. If you see lots of lines like this sun.awt.windows.Win32BlitLoops::Blit(),then we're using ddraw for rendering your image to the screen/backbuffer, and thus your images are accelerated.

Note that it'll print out lots of info, so you might want to use-Dsun.java2d.trace=count , so it'll print out only the number of times each primitive was used when the app exits.

I create the tile images only one time just before starting performing the scroll.

I've done a simple test yesterday to see if the tile images are accelerated by replacing them with on tile image loaded from file using Toolkit.getImage() and suddenly the test ran at 75 fps. Strange isn't it?

I think that the context I create the tile images is not appropriate which make them not accelerated. I create a Frame, I do setUndecorated(true) then setIgnoreRepaint(true) and after that I use a BufferStrategy on that frame to perform page flipping (I verified the use of page flipping with the BufferCapabilities)

Maybe because I create image tiles with a frame that was instantiated before changing the display mode make them unaccelerated???

I create the tile images only one time just before starting performing the scroll.

I've done a simple test yesterday to see if the tile images are accelerated by replacing them with on tile image loaded from file using Toolkit.getImage() and suddenly the test ran at 75 fps. Strange isn't it?

I think that the context I create the tile images is not appropriate which make them not accelerated. I create a Frame, I do setUndecorated(true) then setIgnoreRepaint(true) and after that I use a BufferStrategy on that frame to perform page flipping (I verified the use of page flipping with the BufferCapabilities)

Maybe because I create image tiles with a frame that was instantiated before changing the display mode make them unaccelerated???

But doesn't the fact the the display is, say 16bpp, and you createCompatible, switch to 32bpp and the compatible image is no longer compatible? Maybe the "accelerated" version is, and the transformation into it only is a bit heavier due to the conversion...

Sometimes when I load images quickly after switching to FS Excl and changed DSP-mode, the code runs *a lot* slower than last time (I exit and rerun and voila! It's snappy again!) I'll try a few runs with the trace turned on and see if I can spot a difference when it starts up in this dreaded slo-mo

I got a whole bunch of differences when I removed the sleep after switching DisplayMode (It seems I've seen the problem before, since I put that sleep in). I do not, however, use multiple buffers for now, but instead a VolatileImage as backbuffer which is blit onto the screen. With the startup delay (fastmode) I see alot of sun.awt.windows.Win32BlitLoops::BlitWithout the startup delay (slowmode) I see alot of sun.java2d.loops.Blit::Blit

Thanks a lot guys for all your tips but I still have this performance problem. I've tried the trace option and it displays a lot of sun.awt.windows.Win32BlitLoops::Blit() which means that my tile images are accelerated. But again if I replace those images by a tile image loaded from file, the performance is correct. Here is the portion code that creates the tile images (sorry for the formatting):

Hi, I noticed you're using createCompatibleImage(), you should use createCompatibleVolatileImage(), only then can you be relatively assured the image is accelerated.

Here's a side scrolling thingy I wrote. Compare the speeds. In my tests there were definite performance improvements.

Some comments on this code. The display mode is hardcoded. It's not checking for available display modes before doing the switch, so you should know beforehand what's supported by your system. you can change it in the constructor, reference name 'fullScreenMode'. alt-enter to switch into full screen.

Don't take this code as the correct way to run a rendering loop though. I hacked it up today. The correct way should turn off paint events.

I still didn't had time to complete trying your solution but it seems very well!

I'm wondering why you must code yourself the caching of Image through VolatileImage while it is suppose to be implemented when using Image created from component.createImage() or GraphicsConfiguration.createCompatibleImage()?

Here are some performance numbers I got from running a modified version. In this version I use a direct rendering loop, and I call setIgnoreRepaint(true). This way I could get some timings.

All the tests were done at 640x480x32 full-screen.

I got around 78fps on a Duron 900 runing in a pc-chips 810 motherboard (this is a very low end motherboard with a SiS chipset and SiS integrated graphics sharing the RAM with the cpu, in otherwords, no dedicated vRam).

On an Athlon 1.3GHz (actual clock speed, not the model name) I get 128fps on the same motherboard.

Now there are still some issues I believe. I still have to check my code just in case I'm doing something wroung, but in my 600MHz P3 with a geForce 2 MX I must get something like 10 fps!! There might be some compatibility issues with the drivers, although as I said, it could be my fault. I have to check the code.

As far as Component.createImage(...) is concerned, I found no documentation indicating it returns VolatileImages. What's more, the only documented ways I found a developer can create an accelerated image is requesting one explicitly through the createCompatibleVolatileImage(...) methods.

For Beta 3, Shared Memory Extension is used on Solaris and Linux in the local display environment, resulting in better performance when rendering to the screen and to the images. When DGA is not available, toolkit images and images created with Component.createImage or GraphicsConfiguration.createCompatibleImage are stored in pixmaps instead of system memory, enabling faster copies to the screen using X protocol requests. You can override this behavior with the pmoffscreen runtime flag, described in the section Runtime Flag For Solaris and Linux .

It seems to me that this is referring only to the unix family of O. Systems, specifically Solaris and Linux.

Regarding creatImage images:

Quote

When creating an image whose data is copied to the screen, you should create the image with the same depth and type of the screen. This way, no pixel format conversion between the image and the screen is necessary before copying the image. To create such an image, use either Component.createImage or GraphicsConfiguration.createCompatibleImage, or use a BufferedImage created with the ColorModel of the screen. The pre-defined types of BufferedImage have their own color models.

This means to me that compatible image is faster than your average image only because there is no pixel transformation applied when copying. But it doesn't mention about storage in vRam.

I also found this, which is quite suggestive since it's rather odd that createImage would call createVolatileImage which would call createImage again. Of course its not impossible, just awkward:

Quote

-Dsun.java2d.ddoffscreen=false Setting this flag to false turns off DirectDraw offscreen surfaces acceleration by forcing all createVolatileImage calls to become createImage calls, and disables hidden acceleration performed on surfaces created with createImage

And out of my own personal experience with the code I posted before, when method getTile is modified to return BufferedImages created with createCompatibleImage(...), the result is faster than using some generic image format, but not as fast as using VolatileImage.

Ok, after your comments I did some more testing. I ran both tests on different machines and you're right, direct handling of VolatileImages is apparently not necessary, at least on most machines.

On the one where I wrote the little test originally there is a performance difference between both implementations, as there is on the geForce 2 MX machine, but there is no difference in the machines with the SiS chipset.

So, there still is a difference on some machines, but having tested this, I would do the same thing your doing, use createComatibleImage() since it caused less problems on the geForce, although performance was only slighly better, around 12 fps, compared to 128 fps on the athlon/sis configuration!

Oh well, the problem might be related to the fact that I hardcode the DisplayMode, I don't get it from a list of available modes. I'll see.

there's a number of reasons which may affect performance on certain configurations. Like, for example, the amount of available vram. Or the fact that, say, your sprites are all accelerated (i.e, in vram), but your back-buffer is not, for some reason.

It also depends on the operations you perform on the back-buffer - if you do any of compositing, antialiasing and such, it could be punted to system memory.

Try running your app with-Dsun.java2d.ddforcevram=true parameter and see if it helps.

I'd suggest to try to create a simple test which just copies different types of images to the backbuffer (or screen), and see which one is faster under which circumstances.

Jeff's article indeed has answers to some of your questions, so hopefully it'll be back soon.

I found what was causing the bad performance on my pentium 3/geForce2mx/w2k configuration. As I commented before I am getting 128 fps on another system while I got 10fps in this one.

The problem was due to Direct3D use in Java2D. I turned it off with -Dsun.java2d.d3d=false and immediatelly got 25fps on the geForce. Not a great improvement but the redraws are a lot smoother now.

It's also interesting to note, this system has another PCI display adapter (Matrox Millenium II - no 3D acceleration) besides the primary AGP. I got a frame rate improvemnt on both adapters after turning off direct3D.

I disabled the matrox, I still get bad performance if Java2D uses Direct3D.

I have to add though that I didn't reboot the computer with the Matrox disabled, that could conceivably modify the operating environment and fix the problem. I'll try this at a later time when this machine can be taken offline.

Since I posted the last message I upgraded my computer. My new setup is Windows XP on a Duron 1200. I'm still using both the geForce and the Matrox. Both are using microsoft drivers this time, last time I was using the original nVidia and matrox drivers.

What's curious is that I'm still having bad performance if I don't disable Direct3D on Java2D

So it appears the problem is not a driver issue. It seems to be either with the card itself, or Java2D's use of Direct3D.

java-gaming.org is not responsible for the content posted by its members, including references to external websites,
and other references that may or may not have a relation with our primarily
gaming and game production oriented community.
inquiries and complaints can be sent via email to the info‑account of the
company managing the website of java‑gaming.org