AWTGLCanvas problem + question.

Started by EvilOne, April 14, 2010, 15:35:30

Previous topic - Next topic

EvilOne

Howdy,

I have a little problem with AWTGLCanvas. The rendering disappears after the execution of paintGL(). That is, the rendering takes place, after swapBuffers you see it for one frame and then it goes back to the components backcolor (that is, goes white). This can be solved by simply calling repaint() after buffer swap, to keep a steady repaint loop. But this isn't really the solution imho... The results of the last paint call should stay on screen, until the next painting is needed. Don't know if this is fixable.

Oh, and something completely different. I'm using the following code to do some rendering tasks using the context of the AWTGLPanel, synced on the AWT event thread. Is this the correct way to go?

Cheers,
E1.


/**
* Executes rendering on the AWT event thread.
*/
public final class GLExecutor implements Runnable
{
   /** The canvas to paint on. */
   private final AWTGLCanvas canvas;
   /** The runnable to execute. */
   private final Runnable runnable;
   /** Success. */
   private boolean success;
   
   /**
    * Creates a new executor.
    * @param canvas Canvas to paint on.
    * @param runnable Runnable to execute.
    */
   private GLExecutor(final AWTGLCanvas canvas, final Runnable runnable)
   {
      this.canvas   = canvas;
      this.runnable = runnable;
   }
   
   @Override
   public void run()
   {
      try
      {
         // Use the context.
         canvas.makeCurrent();
         
         // Execute.
         runnable.run();
         
         // Done.
         success = true;
      }
      catch(Exception e)
      {
         // Who cares.
         e.printStackTrace();
      }
   }
   
   /**
    * Executes the runnable.
    * @param canvas Canvas to paint on.
    * @param runnable Runnable to execute.
    */
   public final static boolean execute(final AWTGLCanvas canvas, final Runnable runnable)
   {
      try
      {
         // Inkvoke the executor.
         GLExecutor executor = new GLExecutor(canvas, runnable);
         EventQueue.invokeAndWait(executor);
         return executor.success;
      }
      catch(Exception e)
      {
         // Again, who cares.
         e.printStackTrace();
         
         // Failed.
         return false;
      }
   }
}


If you got a shiny new hammer, every problem looks like a nail!

broumbroum

Quote... The results of the last paint call should stay on screen, until the next painting is needed. Don't know if this is fixable
I've been using AWTGLCanvas for a while. Canvas is rendered actively only, hence repaint should not be invoked, and hence you can disable passive rendering with Canvas.setIgnoreRepaint(true), this should fix that issue. ;)
QuoteIs this the correct way to go?
Yes,it is fully correct. EDT must be invoked. :D

EvilOne

Thanks.

But the question is, how to render correctly. Using setIgnoreRepaint(true) doesn't paint anything at all - that is, how do I trigger a repaint...

Cheers,
E1.
If you got a shiny new hammer, every problem looks like a nail!

broumbroum

to repaint with AWTGLCanvas it's up to your renderer to run AWTGLCanvas.update(canvas.getGraphics()) and then swap buffers. Why using repaint if you are already running on EDT ?
QuoteThe results of the last paint call should stay on screen, until the next painting is needed
Or are you willing  to implement a passive rendering ? that is not actually possible, openGL overlays with a volatile fashion as you wrote :
QuoteThat is, the rendering takes place, after swapBuffers you see it for one frame and then it goes back to the components backcolor (that is, goes white)
So, there it is, what do you like ? 8)

EvilOne

What I am trying to do is using the GPU for computing, I have a large graph of connected filters, that do a render-to-texture. The GL canvas is just there for preview purposes, but most of the time not visible... everytime I need to do a computation, a runnable (via. GLExecutor) is invoked like:


@Override
void run()
{
    renderer.setFramebuffer(fb);
    renderer.begin();

    // Do some rendering to texture.

    renderer.end();
    renderer.setFramebuffer(null);
}


At least, thats the idea. Example: http://i41.tinypic.com/hw0d8j.png

The thing I was not sure about, is the correct rendering and interleaving between the canvas and the runnables. But what I do now is simply, if the canvas is visible, let it keep pumping via incremental repaint(), it's then in preview mode anyways, where the generated material is previewed on a mesh (gimme more teapots)... otherwise, just return immediately from paint. Works. If the preview is visible, the runnables get simply interleaved while rendering, otherwise the executor is invoked... Hope this is the correct thing to do.

The world is not only fullscreen apps!

Cheers,
E1.
If you got a shiny new hammer, every problem looks like a nail!

broumbroum

I think FB is not necessary. I tried once ago with the FB, but was too hard to code and finally understood that FB Extension is intended to high end applications like a FPS Quake scene with virtual TVs spots or any samples of movies etc.
opengl can handle cached textures, real-time rendering, so fast that you can let your app refresh forever without overloading your cpu. => render to opengl in paintGL then call swapBuffers and IMMEDIATELY schedule the next render.
Use a java.util.Timer or Swing Timer (cos LWJGL needs edt  to render, right ?), and
QuoteIf the preview is visible, the runnables get simply interleaved while rendering, otherwise the executor is invoked...
Whatsoever you like... interleaving on swing is very handy, use swingUtilities, would you ?
:D