Accelerating 2D Graphics drawing

Ok, I don’t know if it’s been said before, but I just want to share the results of a little experimentation.

I wanted to do some simple sprite stuff, and I wasn’t happy at all with the results I got. ~35 fps on a P4 2.4 GHz, Nvidia GF FX etc etc wasn’t what I was expecting.

The bottleneck, it appeared, was the Graphics.drawImage(). For some reason it was SO SLOW, so I digged further and further. It appeared my graphics weren’t accelerated by my gfx card. everything was done is software. No wonder it was so slow.

So I started poking around and I found some java runtime options which greatly helped my performance.

System.setProperty(“sun.java2d.translaccel”,“true”);
System.setProperty(“sun.java2d.accthreshold”, “0”);
System.setProperty(“sun.java2d.ddscale”,“true”);
System.setProperty(“sun.java2d.ddforcevram”, “true”);

now I get ~150 fps constantly.

I played with “sun.java2d.opengl”,“true” too, but that appears to be buggy. Dunno, just didn’t work for me.

I hope this is helpful to someone.

regards,

  • Vincent 8)

Theres a useful doc on this referenced here:

http://www.java-gaming.org/cgi-bin/JGNetForums/YaBB.cgi?board=2D;action=display;num=1093578600

Kev

The following settings:

System.setProperty(“sun.java2d.translaccel”,“true”);
System.setProperty(“sun.java2d.accthreshold”, “0”);
System.setProperty(“sun.java2d.ddscale”,“true”);
System.setProperty(“sun.java2d.ddforcevram”, “true”);

make my Swing gui look ugly on 1.4.2.

Did anyone notice this ?

Those properties did not change anything to GoSub. Maybe i was doing things that are only accelerated using 1.5’s GL.
Looks like transforming blits is completely software.
never saw problems with UI, by the way.

I do not have problems on the latest 1.5.

My application is quite big and allocates a lot of things at startup. Maybe this is one of the causes of the problems with 1.4.

Last: if I turn accthreshold to 1 the problem disappears, but the gadgets borders are not painted after playing a bit with the gui.

Mik.

what do you mean by ‘ugly’? Can you post a screenshot?
(some would argue that Swing’s Metal theme always looks ugly =)

UGLY -> messed up. In my case the gui is almost completely clean. I only see some parts of gadgets and everything is background color.

I dumped the STDERR and that’s what I get (a driver issue ? I’m on a Matrox P650/Win2k):

java.lang.InternalError: not implemented yet
at sun.awt.windows.Win32OffScreenSurfaceData.getRaster(Win32OffScreenSurfaceData.java:338)
at sun.java2d.loops.OpaqueCopyAnyToArgb.Blit(CustomComponent.java:73)
at sun.java2d.loops.GraphicsPrimitive.convertFrom(GraphicsPrimitive.java:526)
at sun.java2d.loops.MaskBlit$General.MaskBlit(MaskBlit.java:191)
at sun.java2d.loops.MaskFill$General.MaskFill(MaskFill.java:155)
at sun.java2d.loops.DrawGlyphList$General.DrawGlyphList(DrawGlyphList.java:109)
at sun.java2d.pipe.SolidTextRenderer.drawGlyphList(SolidTextRenderer.java:38)
at sun.java2d.pipe.GlyphListPipe.drawString(GlyphListPipe.java:47)
at sun.java2d.SunGraphics2D.drawString(SunGraphics2D.java:2538)
at javax.swing.plaf.basic.BasicGraphicsUtils.drawStringUnderlineCharAt(BasicGraphicsUtils.java:234)
at javax.swing.plaf.basic.BasicLabelUI.paintEnabledText(BasicLabelUI.java:81)
at javax.swing.plaf.basic.BasicLabelUI.paint(BasicLabelUI.java:164)
at javax.swing.plaf.ComponentUI.update(ComponentUI.java:142)
at javax.swing.JComponent.paintComponent(JComponent.java:541)
at javax.swing.JComponent.paint(JComponent.java:808)
at javax.swing.JComponent.paintChildren(JComponent.java:647)
at javax.swing.JComponent.paint(JComponent.java:817)
at javax.swing.JComponent.paintChildren(JComponent.java:647)
at javax.swing.JComponent.paint(JComponent.java:817)
at javax.swing.JLayeredPane.paint(JLayeredPane.java:557)
at javax.swing.JComponent.paintChildren(JComponent.java:647)
at javax.swing.JComponent.paintWithOffscreenBuffer(JComponent.java:4794)
at javax.swing.JComponent.paintDoubleBuffered(JComponent.java:4740)
at javax.swing.JComponent.paint(JComponent.java:798)
at java.awt.GraphicsCallback$PaintCallback.run(GraphicsCallback.java:21)
at sun.awt.SunGraphicsCallback.runOneComponent(SunGraphicsCallback.java:60)
at sun.awt.SunGraphicsCallback.runComponents(SunGraphicsCallback.java:97)
at java.awt.Container.paint(Container.java:1312)
at sun.awt.RepaintArea.paint(RepaintArea.java:177)
at sun.awt.windows.WComponentPeer.handleEvent(WComponentPeer.java:260)
at java.awt.Component.dispatchEventImpl(Component.java:3678)
at java.awt.Container.dispatchEventImpl(Container.java:1627)
at java.awt.Window.dispatchEventImpl(Window.java:1606)
at java.awt.Component.dispatchEvent(Component.java:3477)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:456)
at java.awt.EventDispatchThread.pumpOneEventForHierarchy(EventDispatchThread.java:201)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:151)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:145)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:137)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:100)

I repeat:

  • everything is OK on 1.5;
  • everything is OK on 1.4.2_05 with default “acceleration flags” settings;

Well, it looks like for some reason one one of the generic loops is being used, triggering a call to getRaster(), which wasn’t implemented in 1.4.2 for accelerated offscreen surfaces. Because of the exception some stuff is not being rendered, that’s why it looks weird.

It’s not clear what’s triggering this loop to be used.
Could you try to run your app with tracing turned on (-Dsun.java2d.trace=log) and post the output right before the exception?

Here it is:

sun.java2d.loops.Blit::Blit(ByteIndexedBm, SrcOverNoEa, IntRgb)
sun.java2d.loops.Blit::Blit(ByteIndexedBm, SrcOverNoEa, IntRgb)
sun.java2d.loops.Blit::Blit(ByteIndexedBm, SrcOverNoEa, IntRgb)
sun.java2d.loops.Blit::Blit(ByteIndexedBm, SrcOverNoEa, IntRgb)
sun.java2d.loops.Blit::Blit(ByteIndexedBm, SrcOverNoEa, IntRgb)
sun.java2d.loops.Blit::Blit(ByteIndexedBm, SrcOverNoEa, IntRgb)
sun.java2d.loops.Blit::Blit(ByteIndexedBm, SrcOverNoEa, IntRgb)
sun.java2d.loops.Blit::Blit(ByteIndexedBm, SrcOverNoEa, IntRgb)
sun.java2d.loops.Blit::Blit(ByteIndexedBm, SrcOverNoEa, IntRgb)
sun.java2d.loops.Blit::Blit(ByteIndexedBm, SrcOverNoEa, IntRgb)
sun.java2d.loops.Blit::Blit(ByteIndexedBm, SrcOverNoEa, IntRgb)
GDIFillRect
DDFillRect
DDFillRect
DDFillRect
sun.java2d.loops.DrawGlyphList$General::DrawGlyphList(OpaqueColor, SrcNoEa, “Integer RGB DirectDraw with 1 bit transp”)
sun.java2d.loops.MaskFill$General::MaskFill(OpaqueColor, SrcNoEa, “Integer RGB DirectDraw with 1 bit transp”)
sun.java2d.loops.FillRect::FillRect(OpaqueColor, SrcNoEa, AnyInt)
sun.java2d.loops.MaskBlit$General::MaskBlit(IntArgb, SrcNoEa, “Integer RGB DirectDraw with 1 bit transp”)
sun.java2d.loops.OpaqueCopyAnyToArgb::Blit(Any, SrcNoEa, IntArgb)
java.lang.InternalError: not implemented yet
at sun.awt.windows.Win32OffScreenSurfaceData.getRaster(Win32OffScreenSurfaceData.java:338)
at sun.java2d.loops.OpaqueCopyAnyToArgb.Blit(CustomComponent.java:73)
at sun.java2d.loops.Blit$TraceBlit.Blit(Blit.java:310)
at sun.java2d.loops.GraphicsPrimitive.convertFrom(GraphicsPrimitive.java:526)
at sun.java2d.loops.MaskBlit$General.MaskBlit(MaskBlit.java:191)
at sun.java2d.loops.MaskBlit$TraceMaskBlit.MaskBlit(MaskBlit.java:238)
at sun.java2d.loops.MaskFill$General.MaskFill(MaskFill.java:155)
at sun.java2d.loops.MaskFill$TraceMaskFill.MaskFill(MaskFill.java:185)
at sun.java2d.loops.DrawGlyphList$General.DrawGlyphList(DrawGlyphList.java:109)
at sun.java2d.loops.DrawGlyphList$TraceDrawGlyphList.DrawGlyphList(DrawGlyphList.java:139)
at sun.java2d.pipe.SolidTextRenderer.drawGlyphList(SolidTextRenderer.java:38)
at sun.java2d.pipe.GlyphListPipe.drawString(GlyphListPipe.java:47)
at sun.java2d.SunGraphics2D.drawString(SunGraphics2D.java:2538)
at javax.swing.plaf.basic.BasicGraphicsUtils.drawStringUnderlineCharAt(BasicGraphicsUtils.java:234)
at javax.swing.plaf.basic.BasicLabelUI.paintEnabledText(BasicLabelUI.java:81)
at javax.swing.plaf.basic.BasicLabelUI.paint(BasicLabelUI.java:164)
at javax.swing.plaf.ComponentUI.update(ComponentUI.java:142)
at javax.swing.JComponent.paintComponent(JComponent.java:541)
at javax.swing.JComponent.paint(JComponent.java:808)
at javax.swing.JComponent.paintChildren(JComponent.java:647)
at javax.swing.JComponent.paint(JComponent.java:817)
at javax.swing.JComponent.paintChildren(JComponent.java:647)
at javax.swing.JComponent.paint(JComponent.java:817)
at javax.swing.JLayeredPane.paint(JLayeredPane.java:557)
at javax.swing.JComponent.paintChildren(JComponent.java:647)
at javax.swing.JComponent.paintWithOffscreenBuffer(JComponent.java:4794)
at javax.swing.JComponent.paintDoubleBuffered(JComponent.java:4740)
at javax.swing.JComponent.paint(JComponent.java:798)
at java.awt.GraphicsCallback$PaintCallback.run(GraphicsCallback.java:21)
at sun.awt.SunGraphicsCallback.runOneComponent(SunGraphicsCallback.java:60)
at sun.awt.SunGraphicsCallback.runComponents(SunGraphicsCallback.java:97)
at java.awt.Container.paint(Container.java:1312)
at sun.awt.RepaintArea.paint(RepaintArea.java:177)
at sun.awt.windows.WComponentPeer.handleEvent(WComponentPeer.java:260)
at java.awt.Component.dispatchEventImpl(Component.java:3678)
at java.awt.Container.dispatchEventImpl(Container.java:1627)
at java.awt.Window.dispatchEventImpl(Window.java:1606)
at java.awt.Component.dispatchEvent(Component.java:3477)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:456)
at java.awt.EventDispatchThread.pumpOneEventForHierarchy(EventDispatchThread.java:201)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:151)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:145)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:137)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:100)

Cheers!

Mik

Well, something went kind of wrong: we’re attempting to render to an accelerated 1-bit transparent surface which should never happen…

This may still be happening in 1.5, but it’s masked by the fact that we have a getRaster implementation…

If you can isolate this problem in a standalone testcase, that’d be great.

By this time the only thing I can say is that I open a window in order to display a splash. I don’t know…

I’ll try to create a testcase.

Cheers,

Mik