fillPolygon Performance

Im loading data in somewhat realtime over the internet and then parsing it. The end result is in the range of 6,000+ polygons. As you can imagine drawing all of these is somewhat slow. The default image size is 520x520px however the user can zoom in to 8X for a picture size of 4160x4160px. When one is zoomed all the way in the drawing becomes very slow often a few seconds to render the image.

Currently I am drawing to a BufferedImage that was created like image = getGraphicsConfiguration().createCompatibleImage((int) (520 * scaleFactor), (int) (520 * scaleFactor), Transparency.BITMASK); Is there anything I can do here to improve this?

Would rendering to a GLCanvas and then converting that to a BufferedImage be faster? Note: Im using JInternalFrames so unless something has changed it doesn’t appear I can use GLCanvas directly. Ive also read that GLJPanel is software rendered so using it wouldn’t seem like much of an improvement.

  • Render into a VolatileImage instead of BufferedImage (you must take some extra-care, not just replacing buffred with volatile g)
  • Do not render into such large images (even VolatileImages cannot be accerlated when that large), instead try:
  • Why do you always render everything when zooming -> render in demand just the size you need.
    use graphics.scale and graphics.translate to show the requested area of the polygon.
    Java2D will take care of areas which do not need to be rendered -> much faster!

Is there any reason why you render into images at all?

lg Clemens

My first question is the one LH already asked.

In this day and age of 3D hardware standard on desktops, why are you sofwtare rendering at all??

  • limitations of the hardware or 3d-apis (4096x4096 max texture size, no support for several common operations used in guis, no guarantee to hold content)
  • BufferedImage provides access to pixel-values and guarantees that content won’t be lost -> not doable till now (ext_framebuffer_object would help) with OpenGL since pbuffers are not guaranteed to keep their content.
  • Fast pixel-access won’t be possible if images resides in Vram

So its clearly up to you wether you use accerlation or render in software, but with the difference that java provides you a consistent api (ever tried writing a UI in OpenGL - I did :frowning: ) and ways to trace calls to java2d to see how effectiv your code can be accerlated.

Thats it

[quote]pbuffers are not guaranteed to keep their content
[/quote]
Ehhhh!?? Is this true?

Cas :slight_smile:

Ehhhh!?? Is this true?
[/quote]
Well, thats at least what campbell told us :wink:
Thats the main-reason for ManagedImages beeing no VolatileImages any more under Mustang :frowning:

lg Clemens

Well, thats at least what campbell told us :wink:
Thats the main-reason for ManagedImages beeing no VolatileImages any more under Mustang :frowning:

lg Clemens
[/quote]
Yes, pbuffers can lose their contents, e.g. after a display change event. The GLX spec refers to this as a pbuffer “clobber” event; the WGL spec calls it pbuffer “loss”, I believe.

Regardless, that is not the “main reason” we’re no longer using pbuffers (not VolatileImages, as you state) under the hood of certain managed images. There are a whole host of other issues (poor performance, maintenance headache, etc), and pbuffer loss is nowhere near the top.

And don’t be confused about the GL_EXT_framebuffer_object extension. We’re only planning to support FBO as a way to accelerate VolatileImages, not managed images. (Not out of the question, but unlikely. Just wanted to clear this up, because this is how misinformation spreads…)

Chris

Err… while you are clearing things up maybe you can straighten me out…

I thought that Managed Images essentially used Volatile Images, or an equivalent internal representation for the “managed” accelerated image data. From what you wrote above it would seem that this is not the case. So now I’m wondering, why isn’t it the case? It would seem to make sense from a debugging, code-reuse, etc. point of view that a Managed Image should basically just be a way to get a Volatile Image when you didn’t specifically ask for one. I.e. the volatile image is “managed” for you, so you don’t have to worry about restoring a lost accelerated surface.

I assume I am somehow oversimplifying the problem. But I would appreciate it if you could toss a few clues my way so I have an appreciation for what a Managed Image really means.

Hi Scott,

Conceptually, it works pretty much like you mention. But this is another area where misinformation has been spread by certain people on this board… Basically they say a “managed image” uses VolatileImages internally, but that’s simply not true.

Inside all kinds of Images (since JDK 5) we have something called a SurfaceManager. So BufferedImages have a CachingSurfaceManager, and VolatileImages have a VolatileSurfaceManager. In the end, both SM’s manage surfaces that may or may not be “volatile”, but the strategies they use for managing those surfaces are slightly different. When I say “surface”, I mean a heap-based buffer, or an OpenGL texture, or an OpenGL pbuffer, or a DDraw surface, or a D3D texture, or an X11 Pixmap, or something else. If you really want the full story, download the Mustang sources and poke around src/share/classes/sun/awt/image/*SurfaceManager.java… I could go on, but frankly it’s my birthday, and I don’t even know why I’m working at all today :slight_smile:

This blog may help a bit too:
http://weblogs.java.net/blog/chet/archive/2003/08/bufferedimage_a_1.html

Chris

Ok, so I should just draw the part of the image that is currently being viewed when zoomed way in? Is there an easy way to do this considering im drawing on a jpanel inside a jscrollpane?

How big is the performance gain from using a VolatileImage over a BufferedImage? It seems to me that if a VolatileImage loses its contents once all that was gained is now lost?

1.) What do you zoom? Do you draw the polygons into an images and when zooming you do scale that image or do you re-paint your polygons with scaled coordinates?

2.) A BufferedImage can be fast if its blitted over and over withought any change (e.g. drawing on BufferedImage’s Graphics) but if you paint on it and the draw it you’ll experience heavy performance problems. Rendering onto BufferedImages is software-only.
For rendering complex things into images you should use VolatileImages (rendering done in HW) and handle eventually surface losses (this does not happen frequently, but often enought to handle it gracefully).

I can only recommend the following since image-scaling is always a very ram/cpu intensive task:

  • Allocate a VolatileImage that is just as big as your screen. (Handle surface losses!!)
  • If the user scales, just paint into that image and change the points of your coordinates. try to experiment with Graphics2d.scale and Graphics2d.translate while painting.
  • Implement “virtual” scrolling -> not in a JScrollPane, only a JScrollBar and you calculate what you draw and how you draw it by the value of the scrollbar. Together with Graphics.copyArea you’ll only need to draw a VERY small portion while scrolling.

this is hard to do but should give best performance.

lg Clemens

Im scaling the polygons and then redrawing them. Will scaling the image produce the same results? This is going to have geospatial information overlayed on it so its important that it is accurate. I guess ill give VolatileImage a go and see how it works out.

Hmm…
Scaling the polygons is a good idea, better than scaling the image!
Try only to paint the visible polygons, use the VolaileImage just as backbuffer.

lg Clemens