Problems with Swing, OGL, 6uN, 1.6.0 and active rendering

Hello,
I started to optimize freerails. First I only wanted to make the game logic much faster, but now I’m lost in swing :wink:
Using the OpenGL rendering pipeline in 1.6.0_03 or the DirectX rendering pipeline in 1.6.0_10-b08 (from the Java SE 6 Update N site) I have the following problem:
The game works and the fps is around 100, everything works ok, as long as I don’t open an internal dialog (of type JInternalFrame), then the whole swing gui responds very slow. The weird thing is that the game still runs at 100fps (but now with maximum cpu load), but e.g. mouse events have a delay of 2-4 seconds.
One thing is that the number of events in the SynchronizedEventQueue rises (from 1-2 events/second to 700events/s). Almost all of this came from revalidate() (see stack trace below). The problem occurs with JLabel.setText(). If I generate all possible JLabels at start (at this point the text can have only some values) and instead return them in getListCellRendererComponent(), the GUI does again responds to mouse actions.
If I don’t use the OpenGL rendering pipeline, I still have the many Events, but no GUI response problem.
AND I don’t have the problem in 6uN build 08 with the OpenGL rendering pipeline!

Had anyone similiar problems?

bye
Roland


Stacktrace:
at jfreerails.client.top.SynchronizedEventQueue.postEvent(SynchronizedEventQueue.java:49)
	at java.awt.EventQueue.invokeLater(EventQueue.java:954)
	at javax.swing.SwingUtilities.invokeLater(SwingUtilities.java:1264)
	at javax.swing.JComponent.revalidate(JComponent.java:4796)
	at javax.swing.JLabel.setText(JLabel.java:325)
	at jfreerails.client.view.TrainSummaryJPanel.getListCellRendererComponent(TrainSummaryJPanel.java:99)
	at javax.swing.plaf.basic.BasicListUI.paintCell(BasicListUI.java:195)
	at javax.swing.plaf.basic.BasicListUI.paintImpl(BasicListUI.java:304)
	at javax.swing.plaf.basic.BasicListUI.paint(BasicListUI.java:227)
	at javax.swing.plaf.ComponentUI.update(ComponentUI.java:143)
	at javax.swing.JComponent.paintComponent(JComponent.java:763)
	at javax.swing.JComponent.paint(JComponent.java:1027)
	at javax.swing.JComponent.paintChildren(JComponent.java:864)
	at javax.swing.JComponent.paint(JComponent.java:1036)
	at javax.swing.JViewport.paint(JViewport.java:747)
	at javax.swing.JComponent.paintChildren(JComponent.java:864)
	at javax.swing.JComponent.paint(JComponent.java:1036)
	at javax.swing.JComponent.paintChildren(JComponent.java:864)
	at javax.swing.JComponent.paint(JComponent.java:1036)
	at jfreerails.client.view.TrainListJPanel.paint(TrainListJPanel.java:300)
	at javax.swing.JComponent.paintChildren(JComponent.java:864)
	at javax.swing.JComponent.paint(JComponent.java:1036)
	at javax.swing.JComponent.paintChildren(JComponent.java:864)
	at javax.swing.JComponent.paint(JComponent.java:1036)
	at javax.swing.JLayeredPane.paint(JLayeredPane.java:564)
	at javax.swing.JComponent.paintChildren(JComponent.java:864)
	at javax.swing.JComponent.paintToOffscreen(JComponent.java:5129)
	at javax.swing.RepaintManager$PaintManager.paintDoubleBuffered(RepaintManager.java:1382)
	at javax.swing.RepaintManager$PaintManager.paint(RepaintManager.java:1313)
	at javax.swing.RepaintManager.paint(RepaintManager.java:1128)
	at javax.swing.JComponent.paint(JComponent.java:1013)
	at javax.swing.JComponent.paintChildren(JComponent.java:864)
	at javax.swing.JComponent.paint(JComponent.java:1036)
	at javax.swing.JComponent.paintChildren(JComponent.java:864)
	at javax.swing.JComponent.paint(JComponent.java:1036)
	at javax.swing.JLayeredPane.paint(JLayeredPane.java:564)
	at javax.swing.JComponent.paintChildren(JComponent.java:864)
	at javax.swing.JComponent.paint(JComponent.java:1036)
	at java.awt.Component.lightweightPaint(Component.java:2896)
	at java.awt.Container.lightweightPaint(Container.java:1878)
	at java.awt.GraphicsCallback$PeerPaintCallback.run(GraphicsCallback.java:67)
	at sun.awt.SunGraphicsCallback.runOneComponent(SunGraphicsCallback.java:60)
	at java.awt.Component.paintAll(Component.java:2881)
	at java.awt.GraphicsCallback$PaintAllCallback.run(GraphicsCallback.java:43)
	at sun.awt.SunGraphicsCallback.runOneComponent(SunGraphicsCallback.java:60)
	at sun.awt.SunGraphicsCallback.runComponents(SunGraphicsCallback.java:90)
	at java.awt.Container.paintComponents(Container.java:1865)
	at jfreerails.client.top.GameLoop.run(GameLoop.java:106)
	at jfreerails.launcher.Launcher$1.run(Launcher.java:259)
	at java.lang.Thread.run(Thread.java:619)

I have added the program and a save game (1.sav, must be put in the same dir as the jar) to sourceforge https://sourceforge.net/project/showfiles.php?group_id=209321 (a new project called freerails2).
If you use the DirectX rendering pipeline you start with a white playfield. Looks like a bug …

to start the program:

java -Dsun.java2d.opengl=True -Dsun.java2d.trace=count -jar jfreerails-20071205-2306.jar
select single player, 1.sav and windowed modus
bye
Roland

I think this could be because you are not using BufferStrategy as carefully
as you should. For example you don’t seem to check for contentsRestored()
in your ScreenHandler class. But then again, it may be something different.

The proper loop is shown here:
http://java.sun.com/javase/6/docs/api/java/awt/image/BufferStrategy.html

Also, if you use VolatileImages, make sure you validate them
and respond to all validation return codes:
http://java.sun.com/javase/6/docs/api/java/awt/image/VolatileImage.html
like make sure you loop around contentsLost().

Dmitri

Looks like you do validate your v. images (BufferedTiledBackgroundRenderer.paintRect).

I’d trace and see what happens there on the first repaint.

Something there goes awry and you actually painting to the
screen, not to your BufferStrategy as you think you do.
Most likely because of a race condition between EDT and your
code disabling double-buffering and creating the BS.

Once you draw your volatile image to the screen it will be
lost.

One thing I’d suggest - when you create the BufferStrategy and disable
the double-buffering, make sure you are doing it on the EDT - I think
now you are doing it on the rendering thread.

Thanks,
Dmitri

Another thought: to prevent rendering to the screen you might try to
override getGraphics() on your game frame, and return the graphics
of your BufferStrategy.

Dmitri

those are the options to set properly up :
- Windows 32 bits:
java -Dcom.sun.media.imageio.disableCodecLib=true -Dsun.java2d.opengl=False -Dsun.java2d.d3d=True -Dsun.java2d.noddraw=false (Windows does NOT support OpenGL pipeline, nor the native codec libs but the Direct3D pipeline if available)
- Mac OS X :
java -Dcom.sun.media.imageio.disableCodecLib=false|null -Dsun.java2d.opengl=True -Dsun.java2d.translaccel=true
plus the ImageIO.setUseCache(true) is recommended at the beginning of the code.
try surfing about the Java Sun articles if you want more information !

To be honest I don’t quite understand how your response has anything
to do with the conversation here. It is also not entirely correct:

That these two together don’t make sense. noddraw will turn off both
ddraw and d3d.

This one is superficial, the opengl pipeline is disabled by default,
no need to re-disable it.

Thanks,
Dmitri
Java2D Team

Hi,
you were right, the first paint was in the EDT. If I ignore paints in the EDT, it works.
Thank you
Roland

Good to hear. Although I’d still suggest to disable double buffering
and create BS on the EDT instead of the rendering thread.

Did you see any performance improvements with the fix?

Dmitri

Hello,
perhaps I misunderstood something about the rendering logic. It uses active rendering and all painting in the EDT is denied. So the fix only affects the first painting.

I have the performance decrease if I open an JInternalFrame (e.g. TrainList), but the main problem is that the GUI with certain configuration no longer reacts on input. The InternalFrame gets rendered to an internal image, I disabled “doubleBuffering” in the RepaintManagerForActiveRendering, so in the profiler it looks a bit better. With jdk 6uN build 08 and opengl rendering pipeline the problem vanished completely. The framerate in all configuration (directx, opengl, jdk1.6, 6uN) is now always the same (around 50fps).
bye
Roland

Hi,
obviously, the problem is that the SynchronizedEventQueue was blocked 100% of the time, so only a small amount of the Events was processed. A little sleep solved the problem. I think of a better solution, but not today :wink:
bye
Roland