Java2D pipeline problem?

Aaarghhh!!!

Another strange problem with VM 1.4.2 …

After a random period of time after the startup, my new game slows down form stable 60FPS to a permanent 10FPS situation…

It happens only in two cases:

  1. If alpha transparency of shadows is enabled:

g2.setComposite( java.awt.AlphaComposite.getInstance( java.awt.AlphaComposite.SRC_OVER, alphaValue) );
// DRAW SPRITES
g2.setComposite( java.awt.AlphaComposite.getInstance( java.awt.AlphaComposite.SRC_OVER, 1f) );

Doesn’t matter if hardware accelerated transparency is enabled or not.

  1. If I use rotations -=WITH=- interpolation active:

g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,RenderingHints.VALUE_INTERPOLATION_BILINEAR);

I’ve discovered that the problem is not related with my PC, I’ve tested the demo also on a P4 1.7Ghz with GeForce2MX: The SAME result.

For SURE it the problem doesn’t exist with VM 1.4.1_02 (tested five minutes ago).

Probably the drawing pipeline in some way wrecks after many “state” changes…

Maybe Abuse (who seems to work with rotations) have encountered a similar problem???

I hope the problem won’t be present in the future release, otherwise I’ll better turn back on my steps and
restart from ZERO with DX (I hate them!).

May Java 1.5 be with you.

Can’t help, sorry :frowning:

i’ve never used bilinear interpolation, and I don’t use rotation at runtime. Until its HW accelerated, i don’t see much point. (and if said feature doesn’t get into Win32 JRE1.5, im going to give up on Java2D and switch to JOGL :-/)

Can you construct a small test case so we can see the problem in action?

It seems that I’m not able to reproduce the problem…

I’ve created a simple demo containing rotations and alpha transparency but it runs fine also after minutes.

Maybe I’m wrong and the problem is not directly connected with alpha transparency or rotation… and in some way it is related with my scrolling…

BUT the problem doesn’t exist with the previous release and it is not present if I switch off DDraw acceleration.

Sot I must think it is related with Java2D.

I’ve uploaded a test with graphics badly altered (sorry but I cannot show real graphics right now).
The entities shadows are transparent, rotation is filtered and HW transparency is enabled.

http://www.fish-bros.it/test.zip

If you use “Run.bat” (I hope you’re using Windows!) you get accelerated version, with RunSW the unaccelerated one…

Use Arrows to move and CTRL to shoot.
After a while you run around you should notice (in the log window) a drastic fall of the framerate. That’s it…

The scrolling is very bad cause I’ve used CopyArea instead of DrawImage, because CopyArea works fine also in software mode. But it is veeery slow because CopyArea sucks: when scrolling to the left or upward it slow down all.

I’m interested in JOGL (I’ve worked with OpenGL) but I’m also very interested in creating online games so no ZIP so no additional DLLs…

Maybe if it was a part of Java core…

" I’m interested in JOGL (I’ve worked with OpenGL) but I’m also very interested in creating online games so no ZIP so no additional DLLs… "

can’t you just use Java Web Start ?

I’ve never used WebStart ::slight_smile:

But my development is oriented at online gaming, so there are sponsors, banners, and so I don’t know if bypassing the browser is always a good idea…

Thanks for the suggestion
I’m thinking about it…

You might try turning on verbose GC… see if it is any more active when you slow down. Also turn on profiling… that time has to be spent somewhere…

The GC is OK…

Here is the Profiler Log:

----------------->>> FPS CHANGE HERE <<<-----------------------

----------------->>> CLOSING APP <<<-----------------------

Flat profile of 57.06 secs (3581 total ticks): AWT-Windows

Interpreted + native Method
99.9% 0 + 3576 sun.awt.windows.WToolkit.eventLoop
0.0% 1 + 0 sun.awt.SunToolkit.targetToAppContext
0.0% 0 + 1 sun.awt.windows.WToolkit.run
0.0% 0 + 1 sun.awt.windows.WToolkit.init
99.9% 1 + 3578 Total interpreted

Thread-local ticks:
0.1% 2 Compilation

Flat profile of 0.08 secs (5 total ticks): Thread-1

Interpreted + native Method
80.0% 1 + 3 sun.reflect.Reflection.ensureMemberAccess
20.0% 1 + 0 java.lang.reflect.ReflectAccess.copyField
100.0% 2 + 3 Total interpreted

Flat profile of 53.78 secs (3425 total ticks): DestroyJavaVM

Thread-local ticks:
100.0% 3425 Blocked (of total)

Flat profile of 53.79 secs (3426 total ticks): Thread-2

Interpreted + native Method
0.3% 0 + 9 sun.awt.image.ImagingLib.transformBI
0.1% 0 + 3 sun.java2d.loops.Blit.Blit
0.1% 0 + 2 fishbros._spacetroopers.Alien.live
0.1% 1 + 1 java.awt.image.PackedColorModel.
0.1% 2 + 0 sun.awt.windows.Win32OffScreenSurfaceData.validatePipe
0.0% 1 + 0 sun.awt.image.IntegerInterleavedRaster.
0.0% 1 + 0 java.awt.image.BufferedImage.getSubimage
0.0% 1 + 0 java.awt.Component.getBackground
0.0% 1 + 0 java.lang.ThreadLocal$ThreadLocalMap.get
0.0% 1 + 0 fishbros.pyro.EntityRoster.makeEmLive
0.0% 1 + 0 fishbros._spacetroopers.Game.drawGame
0.0% 1 + 0 fishbros.pyro.SpriteBank.drawPrimitive
0.0% 1 + 0 java.awt.AlphaComposite.
0.0% 0 + 1 sun.java2d.SunGraphicsEnvironment.createGraphics
0.0% 1 + 0 sun.java2d.pipe.Region.isEmpty
0.0% 1 + 0 sun.awt.windows.Win32OffScreenSurfaceData.getRenderLoops
0.0% 1 + 0 fishbros._spacetroopers.Player.drawShadow
0.0% 1 + 0 sun.java2d.pipe.DrawImage.imageReady
0.0% 1 + 0 sun.awt.image.IntegerInterleavedRaster.createCompatibleWritableRaster
0.0% 1 + 0 java.awt.image.AffineTransformOp.
0.0% 1 + 0 sun.awt.image.IntegerInterleavedRaster.setDataElements
0.0% 1 + 0 java.awt.geom.RectangularShape.getBounds
0.0% 1 + 0 java.util.Vector$1.
0.0% 1 + 0 java.lang.Integer.getChars
0.0% 0 + 1 sun.awt.windows.Win32BlitLoops.Blit
1.7% 32 + 25 Total interpreted (including elided)

 Compiled + native   Method                        

2.5% 85 + 0 fishbros.utils.SysTimer.waitUntilNextTick
0.4% 5 + 9 java.awt.image.Raster.createPackedRaster
0.3% 11 + 0 vtable chunks
0.2% 3 + 4 java.awt.image.SinglePixelPackedSampleModel.createDataBuffer
0.1% 5 + 0 java.util.HashMap.get
0.1% 2 + 2 sun.java2d.SunGraphics2D.checkFontInfo
0.1% 2 + 1 java.awt.image.SinglePixelPackedSampleModel.
0.1% 3 + 0 sun.java2d.loops.GraphicsPrimitive.tracePrimitive
0.1% 2 + 0 java.lang.Math.abs
0.1% 2 + 0 java.util.Hashtable.put
0.1% 2 + 0 java.awt.image.ComponentSampleModel.getNumDataElements
0.1% 2 + 0 fishbros.pyro.Map.drawLayer
0.1% 2 + 0 fishbros.pyro.SpriteBank.drawPrimitive
0.1% 2 + 0 sun.java2d.loops.Blit.getFromCache
0.1% 2 + 0 sun.java2d.SunGraphics2D.drawImage
0.1% 2 + 0 sun.awt.image.IntegerComponentRaster.
0.1% 1 + 1 sun.java2d.pipe.DrawImage.transformImage
0.1% 2 + 0 sun.java2d.SunGraphicsEnvironment.createGraphics
0.1% 1 + 1 sun.java2d.pipe.ValidatePipe.scaleImage
0.1% 1 + 1 java.awt.image.BufferedImage.getSubimage
0.1% 2 + 0 sun.java2d.loops.MaskBlit$TraceMaskBlit.MaskBlit
0.0% 1 + 0 sun.java2d.SunGraphics2D.setDevClip
0.0% 1 + 0 fishbros._spacetroopers.TopDownEntity.clipAngle
0.0% 0 + 1 java.awt.image.DataBufferInt.
0.0% 1 + 0 java.awt.image.PackedColorModel.countBits
5.8% 175 + 23 Total compiled (including elided)

     Stub + native   Method                        

66.6% 1 + 2275 sun.awt.windows.Win32BlitLoops.Blit
12.2% 41 + 375 sun.misc.Perf.highResCounter
6.1% 0 + 207 sun.java2d.loops.MaskBlit.MaskBlit
2.4% 1 + 81 sun.awt.image.ImagingLib.transformBI
2.2% 0 + 75 sun.java2d.loops.Blit.Blit
0.8% 0 + 29 sun.awt.image.BufImgSurfaceData.initRaster
0.7% 0 + 24 java.lang.Object.clone
0.1% 1 + 4 java.lang.Object.hashCode
0.1% 1 + 3 java.lang.StrictMath.ceil
0.1% 0 + 3 java.lang.StrictMath.floor
0.1% 0 + 3 sun.awt.image.BufImgSurfaceData.setSurfaceData
0.1% 1 + 1 sun.awt.image.BufImgSurfaceData.getSurfaceData
91.5% 46 + 3080 Total stub

Runtime stub + native Method
0.7% 24 + 0 d2l_stub Runtime1 stub
0.1% 4 + 0 interpreter_entries Runtime1 stub
0.8% 28 + 0 Total runtime stubs

Thread-local ticks:
0.2% 8 Blocked (of total)
0.1% 3 Interpreter
0.1% 5 Compilation
0.0% 1 Unknown: no last frame

Flat profile of 57.01 secs (3578 total ticks): AWT-EventQueue-0

Interpreted + native Method
12.5% 0 + 1 java.lang.Object.wait
12.5% 0 + 1 sun.awt.windows.Win32Renderer.doFillRect
12.5% 1 + 0 java.awt.EventQueue.noEvents
12.5% 1 + 0 java.util.LinkedList.clone
12.5% 0 + 1 sun.awt.windows.WInputMethod.disableNativeIME
62.5% 2 + 3 Total interpreted

Thread-local ticks:
99.8% 3570 Blocked (of total)
37.5% 3 Compilation

Flat profile of 57.02 secs (3578 total ticks): Java2D Disposer

Thread-local ticks:
100.0% 3577 Blocked (of total)
100.0% 1 Compilation

Flat profile of 57.14 secs (3586 total ticks): AWT-Shutdown

Thread-local ticks:
100.0% 3586 Blocked (of total)

Global summary of 57.82 seconds:
100.0% 3673 Received ticks
1.1% 39 Received GC ticks
0.8% 28 Compilation
0.0% 1 Other VM operations
0.2% 7 Class loader
0.1% 4 Interpreter
0.1% 2 Unknown code

Excuse this very long log… :o

I don’t understand exactly what this output means; if someone can decrypt it…

Thanks

This shows the time spend in each method, broken down by thread…

If you take one thread, eg:[quote]Flat profile of 57.01 secs (3578 total ticks): AWT-EventQueue-0
[/quote]
shows that the AWT event thread was sampled 3578 times

[quote]Interpreted + native Method
12.5% 0 + 1 java.lang.Object.wait
12.5% 0 + 1 sun.awt.windows.Win32Renderer.doFillRect
12.5% 1 + 0 java.awt.EventQueue.noEvents
12.5% 1 + 0 java.util.LinkedList.clone
12.5% 0 + 1 sun.awt.windows.WInputMethod.disableNativeIME
62.5% 2 + 3 Total interpreted
[/quote]
This shows that only 5 of those times were any methods running (2 times it was interpreting, 3 times it was running native code)

[quote]Thread-local ticks:
99.8% 3570 Blocked (of total)
37.5% 3 Compilation
[/quote]
This shows that most of the time this thread was blocked, and the remaining three ticks it was compiling bytecode.

So overall the main bottle necks seem to be:
66.6% 1 + 2275 sun.awt.windows.Win32BlitLoops.Blit
which is somewhat expected, since the bulk of the game is software blitting to animate things.

And… I’m not sure if this is normal or not… this AWT thread seems to have been in a busy loop… but I could be reading this wrong. (I expected to see some ‘blocked’ time for this thread)
99.9% 0 + 3576 sun.awt.windows.WToolkit.eventLoop

The thing to do is to compare this with a profile of when it isn’t slowed down.

Try running your game in windowed mode, see if the problem manifests. If it does, run it with primitives logging:
java -Dsun.java2d.trace=log YourApp
and see if it starts to use some funny loops when it’s slowing down.

Another thing is that you may have run into problem with surface punting: a mechanism which moves an accelerated surface to system memory when we detect that we have to read a lot from video memory (a slow operation).

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

Yeahh!

That was the problem!

So Java detects “too many” readings from VRAM and moves images to SysRam trying to speed up things, right?
But the result is to slow down things more than before :frowning:

Many thanks

[OT]
Too many problems…
If you want simple graphics Java2D it’s OK, but if you try to add some cool effects all the problems comes to block you…

I think I’ll give up and start to write down a 2D library upon J3D!
No more strange problems with Java2D but only REAL 3D acceleration…

Using openGL is surely much simpler but I DON’T WANT to use non standard libraries…

Also if rotation and alpha transparency will come with 1.5 I think I’ll get ever lower FPS than a J3D implementation.
[/OT]

There’s no difference in the drawings log before and after that “effect”.

Following there’s the Profiler log before FPS fall…

Flat profile of 4.03 secs (204 total ticks): main

Interpreted + native Method
14.2% 0 + 27 sun.awt.windows.Win32SurfaceData.initDDraw
5.3% 0 + 10 sun.java2d.loops.MaskBlit.MaskBlit
1.6% 3 + 0 org.apache.crimson.tree.TreeWalker.
1.1% 0 + 2 java.io.WinNTFileSystem.getBooleanAttributes
1.1% 1 + 1 fishbros._spacetroopers.Playfield.init
1.1% 0 + 2 sun.awt.image.BufImgSurfaceData.initRaster
0.5% 1 + 0 java.awt.image.DirectColorModel.getRedMask
0.5% 0 + 1 java.lang.ClassLoader.defineClass0
0.5% 0 + 1 sun.awt.font.NativeFontWrapper.registerFonts
0.5% 0 + 1 java.util.zip.ZipFile.open
0.5% 1 + 0 sun.java2d.loops.SurfaceType.pixelFor
0.5% 0 + 1 java.io.WinNTFileSystem.checkAccess
0.5% 0 + 1 java.lang.Math.
0.5% 0 + 1 java.lang.Class.getDeclaredFields0
0.5% 0 + 1 sun.awt.Win32GraphicsEnvironment.registerFontWithPlatform
0.5% 0 + 1 sun.java2d.Disposer.addRecord
0.5% 0 + 1 fishbros.pyro.GameEntity.
0.5% 0 + 1 java.lang.ClassLoader$NativeLibrary.load
0.5% 0 + 1 fishbros.pyro.SpriteBank.
0.5% 0 + 1 sun.java2d.pipe.AlphaPaintPipe.startSequence
0.5% 1 + 0 org.apache.crimson.parser.AttributesExImpl.addAttribute
0.5% 0 + 1 java.lang.ref.Reference.
0.5% 1 + 0 fishbros.utils.XMLhandler.getElement
0.5% 1 + 0 org.apache.crimson.tree.TreeWalker.getNextElement
0.5% 0 + 1 sun.awt.windows.WComponentPeer.pShow
44.7% 16 + 69 Total interpreted (including elided)

 Compiled + native   Method                        

8.4% 16 + 0 vtable chunks
6.8% 13 + 0 org.apache.crimson.tree.ParentNode.item
3.2% 6 + 0 org.apache.crimson.tree.NodeBase.getNextSibling
3.2% 6 + 0 org.apache.crimson.tree.TreeWalker.getNext
2.6% 5 + 0 org.apache.crimson.tree.ElementNode2.getNodeType
2.6% 5 + 0 org.apache.crimson.tree.TreeWalker.getNextElement
1.6% 3 + 0 org.apache.crimson.tree.TextNode.getNodeType
1.6% 3 + 0 org.apache.crimson.tree.ParentNode.getFirstChild
1.1% 1 + 1 java.util.HashMap.addEntry
0.5% 1 + 0 java.awt.RenderingHints$Key.hashCode
0.5% 1 + 0 java.util.Arrays.fill
0.5% 1 + 0 java.util.Vector.addElement
0.5% 1 + 0 org.xml.sax.helpers.AttributesImpl.getValue
0.5% 1 + 0 java.util.Vector.elementAt
0.5% 1 + 0 StubRoutines (1)
0.5% 1 + 0 java.lang.String.equals
0.5% 0 + 1 java.awt.image.Raster.createPackedRaster
0.5% 1 + 0 org.apache.crimson.tree.AttributeSet.createAttributeSet1
0.5% 1 + 0 java.util.HashMap.put
0.5% 1 + 0 sun.java2d.SunGraphics2D.makeHints
0.5% 1 + 0 java.util.Hashtable.put
0.5% 1 + 0 sun.awt.image.IntegerComponentRaster.
0.5% 0 + 1 sun.java2d.pipe.SpanShapeRenderer.renderRect
38.4% 70 + 3 Total compiled

     Stub + native   Method                        

4.2% 0 + 8 sun.java2d.loops.MaskBlit.MaskBlit
2.1% 0 + 4 sun.awt.image.BufImgSurfaceData.initRaster
0.5% 0 + 1 java.lang.System.identityHashCode
0.5% 0 + 1 java.lang.Object.clone
7.4% 0 + 14 Total stub

Thread-local ticks:
6.9% 14 Blocked (of total)
3.7% 7 Class loader
0.5% 1 Interpreter
4.7% 9 Compilation
0.5% 1 Unknown: no last frame

Flat profile of 7.96 secs (450 total ticks): Image Fetcher 0

Interpreted + native Method
54.5% 0 + 6 java.awt.MediaTracker.setDone
9.1% 1 + 0 java.awt.ImageMediaEntry.imageUpdate
63.6% 1 + 6 Total interpreted

Thread-local ticks:
97.6% 439 Blocked (of total)
36.4% 4 Compilation

Flat profile of 7.72 secs (440 total ticks): Image Fetcher 1

Interpreted + native Method
90.5% 0 + 57 java.awt.MediaTracker.setDone
1.6% 0 + 1 java.lang.System.arraycopy
1.6% 0 + 1 sun.awt.image.PixelStore32.allocateLines
1.6% 1 + 0 sun.awt.image.PixelStore.setPixels
1.6% 1 + 0 sun.awt.image.ImageRepresentation.setPixels
1.6% 0 + 1 java.lang.Thread.setPriority0
98.4% 2 + 60 Total interpreted

Thread-local ticks:
85.7% 377 Blocked (of total)
1.6% 1 Compilation

How about abstracting away your 2D layer altogether, then you can switch from rendering method to rendering method as you see fit.

Kev

Now while i’ll be the first to recommend a switch to a vector based rendering API, I really don’t think you want to be using J3D, the whole thing really isn’t designed for 2d graphics - even doing a HUD in J3D is a pain, especially if you want crisp edges.

The argument about ‘non-standard’ librarys doesn’t hold any water, especially since using J3D will need an extra download anyway. And being able to use the stencil and alpha buffers comes in very handy for 2d effects, you don’t get to mess with them if you use J3D
:’(

As I thought… This is a very hot argument!

Bad news…

But maybe I can divide 2D games from 2D/3D ones:
I can continue using my 2D library (pure Java2D) for 2D games that do not require rotation or transparency.
And I can write a new hybrid library using J3D ONLY to make 3D games AND mixed 2D/3D games.

For mixed 2D/3D games I mean something like G.T.A. 2, so I’ve no problem with the edges (or the non-pixel-exact dimension) of the sprite cause all the graphics can be scaled using filtering.

Yeah but the probability to found J3D on a client are more (in my opinion) than to found JOGL, and J3D is related with users’ library (DX or OGL) and don’t force users to use OGL if they have a ULTRA-VIDEO-CARD designed for DX.

Well I’ve already a 2D library which I’ve ported from DX 7, to SDL/openGL and then to Java2D.
It’s rich of features that I don’t want to trash… so an abstraction layer should be a good idea.

But I must hope that it will possible to revert it to Java2D the next year…
Because I’m making games to attract people on websites and if I use WebStart adios banners.

Maybe I can give a good look to your J2DA and see if I can integrate it with Pyro2D (my library), maybe I can give help to the cause as well :slight_smile:

It’s already online?

Anyway JOGL seems to be the only way out for now.

Thanks to all

PS: I’ve downloaded Kevglass JOGLtest but it gives this result

--------------------------
Target was:
GLCapabilities [DoubleBuffered: true, Stereo: false, HardwareAccelerated: true,
DepthBits: 24, StencilBits: 0, Red: 8, Green: 8, Blue: 8, Alpha: 8, Red Accum: 0
, Green Accum: 0, Blue Accum: 0, Alpha Accum: 0 ]
--------------------------
Would have chosen:
GLCapabilities [DoubleBuffered: true, Stereo: false, HardwareAccelerated: true,
DepthBits: 24, StencilBits: 8, Red: 8, Green: 8, Blue: 8, Alpha: 8, Red Accum: 1
6, Green Accum: 16, Blue Accum: 16, Alpha Accum: 16 ]
--------------------------
Exception in thread "main" net.java.games.jogl.GLException: Error swapping buffe
rs
        at net.java.games.jogl.impl.windows.WindowsOnscreenGLContext.swapBuffers
(WindowsOnscreenGLContext.java:140)
        at net.java.games.jogl.impl.GLContext.invokeGL(GLContext.java:193)
        at net.java.games.jogl.GLCanvas.reshape(GLCanvas.java:119)
        at java.awt.Component.setBounds(Component.java:1664)
        at java.awt.BorderLayout.layoutContainer(BorderLayout.java:691)
        at java.awt.Container.layout(Container.java:1020)
        at java.awt.Container.doLayout(Container.java:1010)
        at java.awt.Container.validateTree(Container.java:1092)
        at java.awt.Container.validate(Container.java:1067)
        at java.awt.Window.show(Window.java:461)

I’m using Java 1.4.2