slow performance of java2d

I’m currently using a bufferstrategy in fullscreen exclusive mode using 2 buffers. Using mostly BufferedImages and VolatileImages to cache static parts like backgrounds etc and paint those on the screen.

On a new box with a high en ATI 3800 HD card at 1680x1050 i get only 50fps, on a slower box using an ATI Radeon 9200 on 1080x800 i barely et 30fps.(these are with jdk6N)

Some machines, get even 10fps or even worse 2fps (mostly the linux machines are performing piss poorly) (these were tested on the latest non beta jdk6)

So my question is, is there anyway to speed this up, without enabling the opengl pipeline? enabling it gives performance boost but cause alot of problems, like graphics corruption and starvation of threads (even though the synchronization is correct and should prevent this). the images are created using the createCompatibleImage calls, mostly, and the ones that aren’t use type INT_ARGB. I could paste the code, butt he class is quite big, so i wanted to ask what are the things that i should be looking for?

Oh and the java2d log file shows an insane amount of calls to maskFill.

Hopefully someone out there can help me :slight_smile:

On windows, do you see a lot of D3D* operations in that log?
Are you sure you’re rendering to the back-buffer and not some
buffered image first? With the new d3d pipeline in 6uN
most operations should be hw accelerated.

Also, if you run your app in windowed mode (same dimensions) do you see
any difference in performance?

Could you please post the output from your (or any graphics/swing) app
with J2D_TRACE_LEVEL=4 environment variable set?

Thanks,
Dmitri
Java2D Team

Hi,

I think i’m drawing on the backbuffer. i’m drawing on the graphic object i get from the strategy, then show it, get another one etc. I used the tutorial on fullscreen exclusive mode on sun’s site as the basis for the code.

here’s the trace on the slower machine

4825 calls to sun.java2d.loops.MaskBlit::MaskBlit(IntArgb, SrcOver, IntRgb)
2170 calls to sun.java2d.loops.Blit$GeneralMaskBlit::Blit(IntArgb, SrcOverNoEa, IntArgb)
46 calls to sun.java2d.loops.DrawGlyphList::DrawGlyphList(AnyColor, SrcNoEa, AnyInt)
10390 calls to sun.java2d.loops.Blit$GeneralMaskBlit::Blit(IntArgbPre, SrcOverNoEa, IntRgb)
2 calls to sun.java2d.loops.Blit$GeneralMaskBlit::Blit(Any, SrcOverNoEa, IntArgb)
2 calls to sun.java2d.loops.MaskBlit$General::MaskBlit(Any, SrcOverNoEa, IntArgb)
210739 calls to sun.java2d.loops.MaskFill::MaskFill(AnyColor, SrcOver, IntRgb)
72 calls to sun.java2d.loops.FillPath::FillPath(AnyColor, SrcNoEa, AnyInt)
162 calls to sun.java2d.loops.DrawPath::DrawPath(AnyColor, SrcNoEa, AnyInt)
30 calls to sun.java2d.loops.MaskBlit::MaskBlit(IntArgbPre, SrcOver, IntArgbPre)
72 calls to sun.java2d.loops.MaskBlit$General::MaskBlit(Any, SrcOverNoEa, IntArgbPre)
30 calls to sun.java2d.loops.Blit$GeneralMaskBlit::Blit(IntArgbPre, SrcOverNoEa, IntArgbPre)
6 calls to sun.java2d.loops.FillSpans::FillSpans(AnyColor, SrcNoEa, AnyInt)
2172 calls to sun.java2d.loops.MaskBlit::MaskBlit(IntArgb, SrcOver, IntArgb)
72 calls to sun.java2d.loops.Blit$GeneralMaskBlit::Blit(Any, SrcOverNoEa, IntArgbPre)
1276 calls to sun.java2d.loops.OpaqueCopyAnyToArgb::Blit(Any, SrcNoEa, IntArgb)
116384 calls to sun.java2d.loops.MaskBlit::MaskBlit(IntArgb, SrcOver, IntArgbPre)
4829 calls to sun.java2d.loops.Blit$GeneralMaskBlit::Blit(IntArgb, SrcOverNoEa, IntRgb)
1218 calls to sun.java2d.loops.ScaledBlit::ScaledBlit(ByteIndexed, SrcNoEa, IntRgb)
1214 calls to sun.java2d.loops.TransformHelper::TransformHelper(IntArgb, SrcNoEa, IntArgbPre)
116312 calls to sun.java2d.loops.Blit$GeneralMaskBlit::Blit(IntArgb, SrcOverNoEa, IntArgbPre)
10399 calls to sun.java2d.loops.MaskBlit::MaskBlit(IntArgbPre, SrcOver, IntRgb)
1212 calls to sun.java2d.windows.GDIBlitLoops::Blit(IntRgb, SrcNoEa, “GDI”)
8 calls to sun.java2d.loops.FillRect::FillRect(AnyColor, SrcNoEa, AnyInt)
483642 total calls to 24 different primitives

running java version

java version “1.6.0_10-ea”
Java™ SE Runtime Environment (build 1.6.0_10-ea-b09)
Java HotSpot™ Client VM (build 11.0-b09, mixed mode, sharing)

the only thing i get with the environment var set is

[I] OS Version = OS_WINSERV_2003
[E] D3DPPLM::CheckOSVersion: Windows 2000 or earlier (or a server) OS detected,
failed

DOn’t know if this is helpful, but using JRockit 6 i get

[W] GetFlagValues: DDraw screen locking is disabled (W2K, XP+)
[I] InitDirectX
[V] CheckRegistry: Found Display Device 0: RADEON 9200
[I] CreateDevice: lpGUID=0x2bd1c0 hMon=0x10001
[I] DDSetupDevice
[I] DDraw::CreateDDPrimarySurface: back-buffers=0
[V] DDSetupDevice: successfully created primary surface
[V] DDSetupDevice: successfully setup ddraw device
GraphicsPrimitive logging [and timestamps] disabled
GraphicsPrimitive invocation counts enabled
GraphicsPrimitive trace output to file ‘trace.log’
[I] DDSetupDevice
[I] DDraw::CreateDDPrimarySurface: back-buffers=0
[V] DDSetupDevice: successfully created primary surface
[V] DDSetupDevice: successfully setup ddraw device
[I] DDSetupDevice
[I] DDraw::CreateDDPrimarySurface: back-buffers=1
[V] DDSetupDevice: successfully created primary surface
[V] DDSetupDevice: successfully setup ddraw device
[I] D3DContext::D3DContext
[V] D3DUtils_SelectDeviceGUID: using TNL rasterizer
[I] D3DContext::CreateD3DDevice
[I] D3DContext::CreateAndTestD3DDevice
[I] D3DContext::InitD3DDevice: d3dDevice=Oxb0220
[V] D3DContext::CreateAndTestD3DDevice: D3D device creation/initialization succe
ssful
[W] TestRenderingResults: Quality test failed due to value 0 at (44, 0)
[W] TestRenderingResults: Quality test failed due to value ff0000ff at (34, 0)
[E] CreateD3DDevice: tests FAILED, d3d disabled.

checking dxdiag seems to confirm that there’s something wrong with d3d, but ok. i’ll try on another machine later on. what would explain the low framerate on linux?

Ok, ran it on a laptop, which has an ATI Mobility HD 2600

[I] OS Version = OS_VISTA or newer
[I] CheckAdaptersInfo
[I] ------------------
[I] Adapter Ordinal : 0
[I] Adapter Handle : 0x10001
[I] Description : ATI Mobility Radeon HD 2600
[I] GDI Name, Driver : \.\DISPLAY1, atiumdag.dll
[I] Vendor Id : 0x1002
[I] Device Id : 0x9581
[I] SubSys Id : 0x30c5103c
[I] Driver Version : 7.14.10.503
[I] GUID : {D7B71EE2-D6C1-11CF-7B72-CF10A1C2CA35}
[I] D3DPPLM::CheckDeviceCaps: adapter 0: Passed
[I] ------------------
[I] D3DGD_getDeviceCapsNative
[I] D3DContext::InitContext device 0
[I] D3DContext::ConfigureContext device 0
[V] dwBehaviorFlags=D3DCREATE_FPU_PRESERVE|D3DCREATE_HARDWARE_VERTEXPROCESSING
[I] D3DContext::ConfigureContext: successfully created device: 0
[I] D3DContext::InitDevice: device 0
[I] D3DContext::InitDefice: successfully initialized device 0
[V] | CAPS_DEVICE_OK
[V] | CAPS_RT_PLAIN_ALPHA
[V] | CAPS_RT_TEXTURE_ALPHA
[V] | CAPS_RT_TEXTURE_OPAQUE
[V] | CAPS_LCD_SHADER | CAPS_BIOP_SHADER | CAPS_PS20
[V] | CAPS_PS30
[V] | CAPS_MULTITEXTURE
[V] | CAPS_TEXNONPOW2
[V] | CAPS_TEXNONSQUARE
GraphicsPrimitive logging [and timestamps] disabled
GraphicsPrimitive invocation counts enabled
GraphicsPrimitive trace output to file ‘trace.log’
[I] D3DContext::ConfigureContext device 0
[V] dwBehaviorFlags=D3DCREATE_FPU_PRESERVE|D3DCREATE_HARDWARE_VERTEXPROCESSING
[I] D3DContext::ConfigureContext: successfully created device: 0
[I] D3DContext::InitDevice: device 0
[I] D3DContext::InitDefice: successfully initialized device 0
[V] | CAPS_DEVICE_OK
[V] | CAPS_RT_PLAIN_ALPHA
[V] | CAPS_RT_TEXTURE_ALPHA
[V] | CAPS_RT_TEXTURE_OPAQUE
[V] | CAPS_LCD_SHADER | CAPS_BIOP_SHADER | CAPS_PS20
[V] | CAPS_PS30
[V] | CAPS_MULTITEXTURE
[V] | CAPS_TEXNONPOW2
[V] | CAPS_TEXNONSQUARE
[I] D3DContext::ConfigureContext device 0
[I] D3DContext::ConfigureContext: successfully reset device: 0
[I] D3DContext::InitDevice: device 0
[I] D3DContext::InitDefice: successfully initialized device 0
[V] | CAPS_DEVICE_OK
[V] | CAPS_RT_PLAIN_ALPHA
[V] | CAPS_RT_TEXTURE_ALPHA
[V] | CAPS_RT_TEXTURE_OPAQUE
[V] | CAPS_LCD_SHADER | CAPS_BIOP_SHADER | CAPS_PS20
[V] | CAPS_PS30
[V] | CAPS_MULTITEXTURE
[V] | CAPS_TEXNONPOW2
[V] | CAPS_TEXNONSQUARE
[I] D3DContext::ConfigureContext device 0
[I] D3DContext::ConfigureContext: successfully reset device: 0
[I] D3DContext::InitDevice: device 0
[I] D3DContext::InitDefice: successfully initialized device 0
[V] | CAPS_DEVICE_OK
[V] | CAPS_RT_PLAIN_ALPHA
[V] | CAPS_RT_TEXTURE_ALPHA
[V] | CAPS_RT_TEXTURE_OPAQUE
[V] | CAPS_LCD_SHADER | CAPS_BIOP_SHADER | CAPS_PS20
[V] | CAPS_PS30
[V] | CAPS_MULTITEXTURE
[V] | CAPS_TEXNONPOW2
[V] | CAPS_TEXNONSQUARE

and trace.log contained

9 calls to sun.java2d.loops.FillRect::FillRect(AnyColor, SrcNoEa, AnyInt)
10178 calls to sun.java2d.d3d.D3DMaskFill::MaskFill(AnyColor, SrcOver, “D3D Surface”)
79 calls to sun.java2d.loops.DrawGlyphList::DrawGlyphList(AnyColor, SrcNoEa, AnyInt)
124 calls to sun.java2d.d3d.D3DSwToSurfaceBlit::Blit(IntArgbPre, AnyAlpha, “D3D Surface”)
72 calls to sun.java2d.loops.FillPath::FillPath(AnyColor, SrcNoEa, AnyInt)
1 call to sun.java2d.d3d.D3DSurfaceToGDIWindowSurfaceBlit::Blit(“D3D Surface”, AnyAlpha, “GDI”)
74 calls to sun.java2d.loops.MaskBlit$General::MaskBlit(Any, SrcOverNoEa, IntArgbPre)
119205 calls to sun.java2d.loops.MaskBlit::MaskBlit(IntArgb, SrcOver, IntArgbPre)
27124 calls to sun.java2d.d3d.D3DSwToSurfaceBlit::Blit(IntArgb, AnyAlpha, “D3D Surface”)
575 calls to sun.java2d.loops.TransformHelper::TransformHelper(IntArgb, SrcNoEa, IntArgbPre)
565 calls to sun.java2d.d3d.D3DTextureToSurfaceScale::ScaledBlit(“D3D Texture”, AnyAlpha, “D3D Surface”)
7668 calls to D3DDrawGlyphs
8191 calls to sun.java2d.d3d.D3DTextureToSurfaceBlit::Blit(“D3D Texture”, AnyAlpha, “D3D Surface”)
1 call to sun.java2d.d3d.D3DSwToTextureBlit::Blit(ByteIndexed, SrcNoEa, “D3D Texture”)
119131 calls to sun.java2d.loops.Blit$GeneralMaskBlit::Blit(IntArgb, SrcOverNoEa, IntArgbPre)
75 calls to sun.java2d.loops.MaskBlit::MaskBlit(IntArgbPre, SrcOver, IntArgbPre)
40 calls to sun.java2d.d3d.D3DSwToTextureBlit::Blit(IntArgbPre, SrcNoEa, “D3D Texture”)
153 calls to sun.java2d.loops.DrawPath::DrawPath(AnyColor, SrcNoEa, AnyInt)
10 calls to D3DFillRect
1 call to sun.java2d.d3d.D3DSwToSurfaceScale::ScaledBlit(ByteIndexed, AnyAlpha, “D3D Surface”)
74 calls to sun.java2d.loops.Blit$GeneralMaskBlit::Blit(Any, SrcOverNoEa, IntArgbPre)
643 calls to sun.java2d.loops.OpaqueCopyAnyToArgb::Blit(Any, SrcNoEa, IntArgb)
6 calls to sun.java2d.loops.FillSpans::FillSpans(AnyColor, SrcNoEa, AnyInt)
75 calls to sun.java2d.loops.Blit$GeneralMaskBlit::Blit(IntArgbPre, SrcOverNoEa, IntArgbPre)
27124 calls to sun.java2d.d3d.D3DMaskBlit::MaskBlit(IntArgbPre, SrcOver, “D3D Surface”)
2 calls to sun.java2d.windows.GDIBlitLoops::Blit(IntRgb, SrcNoEa, “GDI”)
321200 total calls to 26 different primitives

slow perf might be caused by some Thread unsafe operations that overlap on heap stack. Please provide us some code sample to better statify on it ! :slight_smile:

Any parts in particulair? the project is big so if you could specify which parts you’d like to see?

Didn’t hear anything about what specific parts to post, so here’s the full code for the buffer class
http://www.nopaste.com/p/aOy34WV2W

The code you posted seem to be fine. I do see some locking but it’s
not clear that it’d cause the slowdowns.

The only thing is that it appears that you’re using swing components.
Typically one would use AWT if you’re rolling your own back-buffer
unless you need to use Swing for your UI or something.

Regarding the logs you posted:

[E] D3DPPLM::CheckOSVersion: Windows 2000 or earlier (or a server) OS detected,
failed

So on this system the d3d pipeline is disabled because of the server class OS
(win2k). We have found that server-class systems don’t get as much
driver love so the drivers are rather buggy.

So all you get on this machine is software rendering, which could be
slow (depending on the CPU/bus speed) -especially for high
resolutions. This also explains why you’re seeing even worse
performance on X (linux, solaris) - it’s all in software there
as well, with added X11 overhead. You can try running with
“-Dsun.java2d.pmoffscreen=false” property on Linux - see
if it helps to at least get it to windows’ level.

The second one, with JRockit:

[E] CreateD3DDevice: tests FAILED, d3d disabled.

The d3d is disabled as well with the older java version because we
detected problems with rendering quality (the older java used DirectX7,
the new one - DirectX 9, where things have somewhat improved).

ATI Mobility HD 2600

On this one the pipeline had initialized successfully.

One question: I see repeating InitDevice calls - I presume
these are because you were alt+tabbing in/out of the application?

Was the laptop’s power plugged in when you ran the test?

From the log it seems that most operations were in HW.

Without seeing the rendering code it’s hard to recommend
something specific. You can try commenting off parts of
your rendering code to see which part takes most time.

The usual performance improvement suggestions also apply, of
course:

  • run with profiler if possible
    (either standalone like in NB or built-in, good old -Xrunhprof)
  • don’t render what you don’t need to (if you need to render
    to a 10x10 area don’t set clip to 10x10 and render world,
    instead just limit your rendering to 10x10 as it takes time
    to figure out what has to be rendered and what’s not)
  • do use clipping in cases it’s needed instead of painting
    over
  • if something is rendering-intensive that doesn’t change much
    from frame to frame, consider rendering it
    to an intermediate image, then just copy from that image
  • see if your locking is messing things up - do a quick and dirty
    “no locking” experiment

Thanks,
Dmitri

good enough ! it is a bit confusing when looking at the nextFrame() method that makes the rendering, appearently recursing on the bufferStrategy and the context. See, when you retrieve the buffered graphics, bufferStrategy is called-back :

Graphics2D g = (Graphics2D)(bufferStrategy.getDrawGraphics());

and looking at the following rendering, context draws where the bufferStrategy has already been called-back. BufferStrategy must be the direct-rendering context and the buffered contents can be retrieved from a TRUE BUFFERED CONTEXT, which always specifies an OFFSCREEN IMAGE.
Advice : Changing the g variable to an offscreen image and the context to the correct bufferStrategy will solve a recursive call-back on the bufferStrategy that always belongs a peer-component or device (Frame or Window sub-classes).

if (bufCap.isPageFlipping())
                                        {
                                                if (!flipContents.equals(BufferCapabilities.FlipContents.BACKGROUND))
                                                {
                                                        if (directCall) this.getLock();
                                                        context.drawFrame(g, size, framecount, System.nanoTime() - start);
                                                        if (directCall) this.setLock();
                                                }
                                        }
                                        else
                                        {
                                                if (directCall) this.getLock();
                                                context.drawFrame(g, size, framecount, System.nanoTime() - start);
                                                if (directCall) this.setLock();
                                        }
                                }

Another point I wanted to make is that in full-screen mode the BufferStrategy is v-synced,
so you won’t get more than 60fps (or your screen refresh rate) anyway.

Thanks,
Dmitri
Java2D Team

Thanks for all the replies, really appreciate the help.

i’ll try responding to all the input.

For the vsync, yes, that’s partly why we went fullscreen with a bufferstrategy, since we needed to wait for the vsync to avoid nasty tearing, but on the one that gets 50fps the refresh rate us 75hz and i thought i could atleast match it in framerate.

the locking is there because different modules themselves don’t have any synchronization. they would draw in an inconsistent state because there was no synchronization between the draw thread and them changing the variables due to user input/mouse move. So we moved it up there. The other part of the synchronization is in the event system.

as for the JFrame, it is because at times we need to show a configuration screen. in a previous version i had the components being added to the JFrame and then calling paintAll using the graphics from the bufferstrategy, unfortunately this didn’t do much. So as an ugly hack we added them to the rootpane and update it, and that worked, with all sort of nasty side effects, and we couldn’t use things like comboboxes. So as a solution i moved everything to a second frame hidden behind the first. and i just swap them out. So there’s no real reason for the first one to remain a JFrame, and i’ll change that.

i’ll try the “-Dsun.java2d.pmoffscreen=false” on the linux systems see it that helps, and as for the directx being dissabled on the server system, it’s something i’m working on to correct, seems something/someone did something to the driver.

I beleive the laptop was plugged in at the time, don’t remeber so can’t be 100% sure

as for the rendering code, the only one that’s mine is the main gui, which i’m basing my tests on anyway. that code is

    public void drawFrame(Graphics2D e, Rectangle dimensions, int framecount, long redrawtime) {

        e.setColor(Color.white);

        if (shifting && scrollbuf != null) {
            e.drawImage(segment(scrollbuf), (dimensions.width - (currentEntries * (5 + mwidth))) / 2, (height - mheight) / 2, myObserver);
        } else {
            for (int x = 0; x < currentEntries; x++) {
                medias.get(x + entryoffset).drawFrame(e);
            }
        }

        scroll.drawFrame(e);
        languages.drawFrame(e, dimensions);

        for (GuiButton b : staticchildren) {
           b.drawFrame(e);
        }

        if(level!=null){
            welcome = level.getTitle();
            welcomemsg = level.getDescription();

            Font old = e.getFont();
            e.setColor(Color.white);
            e.setFont(new Font("Arial", Font.BOLD, 45));
            e.drawString(welcome, 10, (int) (start - epad - e.getFontMetrics().getLineMetrics(welcome, e).getHeight() - 10));
            e.setFont(new Font("Arial", Font.BOLD, 20));
            e.drawString(welcomemsg, 20, (int) (start - epad - e.getFontMetrics().getLineMetrics(welcomemsg, e).getHeight() - 5));
            e.drawString(tooltip, (int) ((dimensions.width - e.getFontMetrics().getStringBounds(tooltip, e).getWidth()) / 2),
                    mheight + epad + start + 50);
            e.setFont(old);
        }
    }

most if not all of the calls in here the calls to drawFrame have internally just a set of images which it choses from depending on the current state and draws them, this to prevent repeated calls to fillrects etc, which was the initial cauze of my first slowdown problem.

I’m a little confused by broumbroum’s post, The first part i get, so you want me to change g to an offscreen image and always draw an image to g instead of really drawing on it. but the second part "context to the correct bufferStrategy " context is any class that implements my IDraw interface. it’s unrelated to the bufferStrategy, maybe this is a case of poor variable names?

Also on a side note, all the other boxes we’ve used to test on ran win2000, and seems from the debug output that it doesn’t support acceleration, or am i reading it wrong?

and really, thanks again for all the replies, you guys have been really helpfull

For the vsync, yes, that’s partly why we went fullscreen with a bufferstrategy, since we needed to wait for the vsync to avoid nasty tearing, but on the one that gets 50fps the refresh rate us 75hz and i thought i could atleast match it in framerate.

Understood. It doesn’t look like you’re doing something
outrageous in your rendering (to the extend I can tell by
looking at the snippet). If you’re just rendering
a bunch of images, some text and shapes it should
handle it just fine for 75 fps. I have an internal benchmark
which renders around 2000 sprites with alpha compositing
and scaling at 60 fps - albeight on a desktop system.

Have you tried to run it on a desktop machine with decent
board? We have found that embedded chips typically
aren’t the greatest in terms of performance.

Also on a side note, all the other boxes we’ve used to test on ran win2000, and seems from the debug output that it doesn’t support acceleration, or am i reading it wrong?

Yes, the new Direct3D pipeline is disabled on Win2k, Win2k3, Win2k8 etc -
the server class OS-es.

As I mentioned, we found that server systems generally have older
drivers (either because the manifacturers don’t have the
drivers or because the admins don’t like installing new stuff)
so we considered it dangerous to enable the pipeline
on those systems.

It’s unfortunate that some folks use them as development
machines - they have no way to test with the pipeline enabled.
If you really want to test the d3d pipeline
on your win2k, I can give a flag to disable the OS check - for
testing purposes only - I would strongly advise against using
it in production.

Thanks,
Dmitri

For the vsync, yes, that’s partly why we went fullscreen with a bufferstrategy, since we needed to wait for the vsync to avoid nasty tearing, but on the one that gets 50fps the refresh rate us 75hz and i thought i could atleast match it in framerate.

Hmm. 75hz on a laptop? Was it hooked up to an external monitor?

Dmitri

Yes, it was hooked up on an external monitor. And yeah i do use windows server as a development os mainly because some software i use don’t install on the desktop counterparts. but the drivers are installed and dx is enabled. or should be, but i can live with it not getting the full speed due the pipeline being dissabled. aslong as the production machines get a decent framerate.

Unfortunately the only none server machine i have is running vista, which is the laptop. at the uni we only have windows 2000 boxes and with onboard intel cards.

But i’ll make changes from the previous post(making g an offscreen image) and i’ll see what happens.

Thanks for all the help, i really got some usefull information :slight_smile:

OK, I see.

I looked again at the primitive tracing you posted, looks like
you still have a ton of SW rendering:

119131 calls to sun.java2d.loops.Blit$GeneralMaskBlit::Blit(IntArgb, SrcOverNoEa, IntArgbPre)
119205 calls to sun.java2d.loops.MaskBlit::MaskBlit(IntArgb, SrcOver, IntArgbPre)

This one especially is worrysome.
Do you render lots of fills with gradients or something?

I also noticed that you do all your rendering with antialiasing enabled.
Is that intentional? Note that with AA enabled even FillRects will
be rendered with AA - and those don’t really look any different
with AA, and if you’re filling the whole background using fillRect -
may be rather costly.

I think you’ll need to comment out parts of the rendering
to see which one causes these MaskBlits.
Or you can do the following in windowed mode:

  • set some delay in your frame rate (like a second)
    and use -Dsun.java2d.trace=log parameter for runtime primitive
    logging - you may see which part of the code causes the non-accelerated
    maskblits.

If you’re unix-savvy and have cygwin installed you can grep the output
on the fly for MaskBlit to limit the output:
java -Dsun.java2d.trace=log App | grep MaskBlit 2>&1

Thanks,
Dmitri

Hi ! I was a bit confused with the manner bufferStrategy was held in a context, and simultaneously painted with the graphics. But anyway I cannot imagine how your rendering schema really is, btw different from mine. The very stuff about rendering is held in two concepts : buffering on offscreen and synch’in with the actual render on the graphics device, k.a. vertical-synch.
Since you mentioned the IDraw interface as unrelated to bufferStrategy then it seems correct in terms of the protected aspect of the bufferStrategy, know I mean ! Thought you were trying to modify the buffers in the BufferStrategy…
:smiley:

Yeah we do do alot of fills with gradients and such, but those are all 1 time things. for instant a control i use commonly on the gui generates when it starts up 4x images for all the states it’s in. Memory really isn’t an issue, and the images are always small, 128x128. after that, no fills are done anymore. and only the images are used. I originally had a way higher amount of maskFills, by using the cache images i reduced them to that number. but yeah, it’s still high. yes AA was intended. but i only really need it the first time. i guess i can move it to where i create the images only

as an example,

	/**
	 * Create a new Menu item
	 * 
	 * @param normal_state
	 *            Image to use when the item is inactive
	 * @param hover_state
	 *            Image to use when the item is being hovered over
	 * @param title
	 *            title of the item
	 * @param size
	 *            the size wanted for the item
	 * @param parent
	 *            the parent to which the item belongs
	 * @param classpath
	 *            the path to the class belonging to the item
	 * @param args
	 *            optional commandline arguments
	 * @see BTF
	 */
	public MediaEntry(BufferedImage normal_state, BufferedImage hover_state,
			String title,String tooltip, Rectangle size, String classpath,
			String args, ActionListener host, MainGUI gui) {
		this.normal = shadowed ? normal_state : hover_state;
		this.hover = hover_state;
		this.tooltip_n=tooltip;
		this.title_n = title;
		this.size = size;
		this.classpath = classpath;
		this.args = args;
		this.host=host;
                this.gui=gui;
			try {
				this.normal_state = new BufferedImage(size.width,
						size.height, BufferedImage.TYPE_INT_ARGB);
				action_state = new BufferedImage(size.width,
						size.height, BufferedImage.TYPE_INT_ARGB);
				normal_state_hover = new BufferedImage(size.width,
						size.height, BufferedImage.TYPE_INT_ARGB);
				action_state_hover = new BufferedImage(size.width,
						size.height, BufferedImage.TYPE_INT_ARGB);
				paintLayout(this.normal_state, false, false);
				paintLayout(action_state, true, false);
				paintLayout(normal_state_hover, false, true);
				paintLayout(action_state_hover, true, true);
			} catch (Exception e) {
				e.printStackTrace();
			}
		Languages.addListener(this);
	}

	/**
	 * Generate the images needed for performance reasons.
	 * 
	 * @param img
	 *            The image on which to draw on
	 * @param selected
	 * @param hovered
	 */
	private void paintLayout(BufferedImage img, boolean selected,
			boolean hovered) {
		Graphics2D e = img.createGraphics();

		e.setColor(selected ? tselect : tnormal);
		e.fillRoundRect(0, 0, size.width, size.height, 10, 10);

		e.setColor(selected ? new Color(255, 255, 255, 60) : new Color(255,
				255, 255, 30));
		e.fillRoundRect(0, 0, size.width, size.height - spade / 2, 10, 10);

		e.setColor(selected ? new Color(0, 0, 0, 30) : new Color(0, 0, 0, 50));
		e.drawLine(0, size.height - spade / 2, size.width, size.height - spade
				/ 2);

		e.setColor(hovered ? thover : new Color(00, 00, 00, 250));
		e.fillRoundRect(0, 0, size.width, size.height - spade, 10, 10);
		e.setColor(Color.white);
		e.drawRoundRect(0, 0, size.width - 1, size.height - 1, 10, 10);
		e.drawRoundRect(0, 0, size.width - 1, size.height - spade, 10, 10);
                
                int pad = 10;

		e.drawImage(mousedown ? normal : (selected ? hover : (hovered ? hover
				: normal)), 0 + (mousedown ? pad : (hovered ? 0 : pad)),
				0 + (mousedown ? pad : (hovered ? 0 : pad)), size.width
						- 2 * pad, size.height - 2 * pad - spade, myObserver);
	}

the AA was really only for the text. Turning it off, the text looks a bit unsharp, but i get an extra ±15fps but only on the sofware rendered one. the hardware rendered one shows no difference in fps.

FYI, if you’re only setting AA for text, you should use appropriate hint:
KEY_TEXT_ANTIALIASING (http://java.sun.com/javase/6/docs/api/java/awt/RenderingHints.html#KEY_TEXT_ANTIALIASING).
I doubt that it’d help though.

In general it is a good idea to only set the hints for what and when you
need.

I don’t know, what you’re doing seems to be just fine,
you do all the right things (caching the rendering and such).

It just can’t be that the pipeline is slow! =)

I suggest the commenting out of parts experiment
to see where the time is spent.

Also, run with -Xverbose:gc to see if you have excessive GC
activity.

Thanks,
Dmitri

Doing that i found that with or without the scrollbars makes a ±10fps difference on the software rendered pc, bringing it to 30fps. It seems i still had some fill and draw polygons in it to draw the direction triangles. though they’re very small… i can’t seem to think why they’d be such a performance hits, but i moved them to the cached images. seems i just forgot about them before :slight_smile:

btw, this is the output from the graphicsconfiguration

  [ MultiBuffers ] Available Graphics memory: 282292224
  [ MultiBuffers ] Screen refresh rate: 60
  [ MultiBuffers ] Screen color dept: 32
  [ MultiBuffers ] Front Buffer --
                      	Graphics acceleration: true
                      	Volatile: false
  [ MultiBuffers ] Back Buffer --
                      	Graphics acceleration: true
                      	Volatile: false
  [ MultiBuffers ] Page Flipping: true
  [ MultiBuffers ] Fullscreen Required: false
  [ MultiBuffers ] Fullscreen Supported: true
  [ MultiBuffers ] Display mode change Supported: true
  [ MultiBuffers ] Multiple buffers: false

about the gc, the output is:

http://pastebin.com/d3a713e03

which is insanely excessive, i managed to find a System.gc() in one of the components, i need to figure out who committed that, but that’s another story :slight_smile: removing it i now get

http://pastebin.com/m347c1909

text only aliasing seems to be ±4 fps slower then without any aliasing