[OT] Component.repaint() & stutter

Apologies if this is somewhat off-topic but…

I’m developing an app which uses a GLCanvas to render some scene. The user has certain tools they can use to draw some kind of shapes (this is all relatively basic 2-D btw). These tools are done via mouse listeners on the canvas, and there’s some pretty computation expensive code that creates these shapes (mask shapes they are, and they are rendered as textured quads btw). Once a shape has been created or modified in the listener, it calls repaint() on the canvas to update the view. OK so the problem I have is that while creating a new shape in the listener code takes around 10…15ms (rendering the scene itself takes about the same, depending on no of objects), view updates aren’t smooth at all, and in fact the faster I drag the mouse around the worse it gets, to the point where I get virtually no view updates at all!

So why is this off-topic? Because… it appears that repaint events are batched together and enter the event queue at low priority. My guess is that the mouse events are flooding the queue so that none the repaint events makes it. This has nothing to do with JOGL but I found no better place to post this, and I’m hoping someone will be able to help!

Possible solutions I’ve thought of so far:

  • Whenever a view parameter changes, call GLCanvas.display() directly, instead of replying on the repaint mechanism. This is problematic with the way the app is designed. There’s so many listeners watching various different view properties that I cannot guarantee that only one of them will trigger display(). It would be very inefficient (and slow) if I get multiple updates upon a single change to one view property.
  • Move the computation from the listener code into a separate worker thread which, once the computation is finished, will invoke repaint() or display() even. This may well work for an isolated test case, but will make the design very complex and error prone.
  • Use a JComponent instead of a canvas. I’m not joking; obviously I don’t see how that would be compatible with JOGL but: I have attached a non-GL test case that shows the difference in repaint mechanism between heavyweights and lightweights. I’m wondering if I could employ a Swing RepaintManager maybe ??? I dunno…

Very interesting problem.

Under the circumstances I would suggest you build your own repainting mechanism on top of the display() method. Start a worker thread whose only job it is to wait for “repaint” requests on a particular GLAutoDrawable and call display() on it. If you make the requests asynchronous from when they are actually performed this will have the effect of batching them up as necessary. Here’s a modified version of your test case doing this for the pure Java case; doing something similar for JOGL should actually be easier, since the RepaintHandler would deal only with GLAutoDrawables rather than having to interact with the EventQueue and do something different for the lightweight and heavyweight cases.

I’d also recommend you post your test case on the Swing and AWT board on javadesktop.org. It’s surprising the behavior is so different between the two (and portably different, too – I see the difference on Solaris/SPARC as well).