Hi Mark,
On Sep 17, 2006, at 11:41 PM, [EMAIL PROTECTED] wrote:
Chris,
Thanks for your reply. I have now changed my PoC to use the Swing
backbuffer.
What kind of image is this? Is it a BufferedImage?
It is a plain old Image. This is being returned (asynchronously) by
a third party API, then blitted to the screen in paintComponent().
Hmm, your code below doesn't show how the Image fits into the equation.
Are you rendering the 5000 shapes to the image just
once, or is the
image being constantly updated (like in an animated
fashion)?
It is being constantly panned and zoomed, and occasionally updated
with new shapes.
You could go one of two ways:
1) Render everything into the Swing backbuffer upon every update. In
this case, you will be scaling the map image each time to the
backbuffer, and then on top of that you're rendering thousands of
translucent shapes to the backbuffer. The image scaling and
translucent shape rendering will be accelerated by the OpenGL
pipeline, but even then it's still a lot of work to do for every
refresh. It will likely be even worse when the OpenGL pipeline is
not enabled, since those operations typically aren't accelerated. In
either case, that's probably why you're seeing the slow menu
painting, since it has to do so much painting work underneath.
2) Render everything into an offscreen image (a VolatileImage in
particular); this is the intermediate image approach that Chet
advocates. The image scaling and translucent shape rendering will
still be accelerated by OpenGL. The benefit here is that if you're
not updating the image often, then you don't need to render all those
shapes each time; the result is essentially cached in the offscreen
image. So in your paintComponent() method, all you have to do is
copy the VolatileImage to the Swing backbuffer, and then you're
done. This will be much faster than rendering all those primitives
each time. This should work well for things like panning, since you
can just translate the image around the Swing backbuffer.
For zooming, you have a couple different options: a) recreate/
rerender to the offscreen image for each frame, then copy it to the
Swing backbuffer b) just scale the offscreen image to the Swing
backbuffer (of course, this may look grainy depending on the scale
factor since you're doing raster scaling, not vector scaling) c) just
render the map/shapes directly to the Swing backbuffer. I'd probably
go with (c), and once the component becomes stable again (i.e., when
the user's done scrolling) go back to option (2).
Now that I am using the Swing backbuffer, everything appears to be
working fine except for the following:
1) Menus are quite slow to paint (because of the time taken to
render beneath it and also repainting the area where a menu was
(the "grey rect")
Are you saying that menus are slower to paint now than they were
before (i.e., before you made the change to draw the image directly
into the Swing backbuffer)?
2) Enabling OpenGL kills it completely. Only parts of the menu and
toolbars render, and none of the shapes.
Are you using JDK 5 or 6? What kind of graphics card and driver
version?
It is possible to get OpenGL working in this case (to improve the
performance)? Or, alternatively, is it possible to have a separate
thread to render the shapes to take the load off the Event Thread?
When dealing with Swing, you should do all rendering and whatnot on
the Event Dispatch Thread.
Thanks,
Chris
Below is the relevant parts of my PoC (its a little messy) - any
comments / suggestions/ help would be greatly appreciated.
Mark
public class MapRenderer
// Constructor creates an ArrayList of random ShapePrimitives,
which are just Java2D Shapes which know how to render themselves
public void render (Graphics2D graphics)
{
try
{
isRendering = true;
StopWatch watch = new StopWatch ();
watch.startWatch ("Starting Rendering");
Rectangle bounds = graphics.getClipBounds ();
graphics.setComposite (AlphaComposite.getInstance
(AlphaComposite.SRC_OVER, 0.25f));
ShapePrimitive s = null;
for (int i = 0; i < shapeCount && i < shapes.size (); i++)
{
s = shapes.get (i);
if (s.isWithin (bounds))
s.drawShape (graphics);
}
watch.stopWatch ("Rendering");
isRendering = false;
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
}
public class MapPanel extends JPanel implements Runnable
{
public MapPanel ()
{
super (true);
initComponents ();
this.setSize (SCREEN_WIDTH, SCREEN_HEIGHT);
this.setName ("Map Panel");
RepaintManager rm = RepaintManager.currentManager (this);
rm.setDoubleBufferingEnabled (true);
rend = new MapRenderer (shapeCount);
}
public void render ()
{
try
{
for (int i = 0; i < iterations; i++)
{
try
{
Thread.sleep (SLEEP_TIME);
}
catch (InterruptedException ex)
{
ex.printStackTrace();
}
while (rend.isRendering ())
{
Thread.sleep (100);
}
System.out.println("Repainting Now");
this.repaint ();
}
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
public void run ()
{
render ();
}
protected void paintComponent (Graphics g)
{
Graphics2D graphics = (Graphics2D) g;
rend.render (graphics);
graphics.dispose ();
graphics = null;
g.dispose ();
g = null;
}
}
public class PanelTest extends javax.swing.JFrame
{
private static MapPanel mapPanel = new MapPanel ();
public PanelTest (MapPanel mp)
{
initComponents ();
this.add (mp);
Thread t = new Thread (mp);
t.setName ("Map Compositor");
t.start ();
this.setSize (SCREEN_WIDTH, SCREEN_HEIGHT);
}
public static void main (String args[])
{
SwingUtilities.invokeLater (new Runnable ()
{
public void run ()
{
new PanelTest (mapPanel).setVisible (true);
}
});
}
}
}
[Message sent by forum member 'markgrantham' (markgrantham)]
http://forums.java.net/jive/thread.jspa?messageID=154042
======================================================================
=====
To unsubscribe, send email to [EMAIL PROTECTED] and include in
the body
of the message "signoff JAVA2D-INTEREST". For general help, send
email to
[EMAIL PROTECTED] and include in the body of the message "help".
===========================================================================
To unsubscribe, send email to [EMAIL PROTECTED] and include in the body
of the message "signoff JAVA2D-INTEREST". For general help, send email to
[EMAIL PROTECTED] and include in the body of the message "help".