Possible to have GLCanvas's display() called *after* all other Swing events?

classic Classic list List threaded Threaded
17 messages Options
Reply | Threaded
Open this post in threaded view
|

Possible to have GLCanvas's display() called *after* all other Swing events?

farrellf
Hi,

It looks like display() is called before some Swing events occur. For example, if you register a mouse listener on the enclosing JPanel, and have display() draw something at the mouse's "current" location, it looks like there is always a one frame delay.

I see similar delays if, for example, I resize the enclosing JPanel. The GLCanvas's size is always one frame old, so there's very obvious stuttering.

Is there any way to remove these delays? I assume this is because some Swing events occur after the GLCanvas's display() method is called.

If it is not possible to remove this delay, do I have any other options if I want my OpenGL drawing to properly line up with GUI events?

Thanks,
-Farrell
Reply | Threaded
Open this post in threaded view
|

Re: Possible to have GLCanvas's display() called *after* all other Swing events?

gouessej
Administrator
Hi

Do you use an animator? How is GLAutoDrawable.display() called in your software? In my case, the events are queued and treated in the continuous rendering, I have no such problems as far as I know. You can call java.awt.MouseInfo.getPointerInfo().getLocation() in GLEventListener.display(GLAutoDrawable) if you don't want to rely on the mouse listener.
Julien Gouesse | Personal blog | Website
Reply | Threaded
Open this post in threaded view
|

Re: Possible to have GLCanvas's display() called *after* all other Swing events?

farrellf
Yes, I use an Animator. My code looks like this:

        glCanvas = new GLCanvas(new GLCapabilities(GLProfile.get(GLProfile.GL2)));
        glCanvas.addGLEventListener(new GLEventListener() { ... }
       
        setLayout(new BorderLayout());
        add(glCanvas, BorderLayout.CENTER);

        animator = new Animator(glCanvas);
        animator.setUpdateFPSFrames(1, null);
        animator.start();

Thanks for the tip about mouse position. But that still leaves the more visually annoying problem when the glCanvas is resized. It looks like reshape() is called one frame after the enclosing component size changes. There is a very noticeable stutter if I resize the JFrame, or if I resize one of the JPanels in my BorderLayout (which therefore causes the glCanvas to be resized.) Any ideas?

-Farrell
Reply | Threaded
Open this post in threaded view
|

Re: Possible to have GLCanvas's display() called *after* all other Swing events?

farrellf
While writing a minimalist demo to show the problem, I realized this even occurs if the GLCanvas is the only thing being drawn. Here's a short video clip showing the problem:

http://www.farrellf.com/temp/jogl_not_redrawing_in_sync_with_jframe_size.mp4

Notice how resizing the JFrame causes black bars to appear in the "new" space until the next frame when the GLCanvas is drawn at the correct size. The demo is literally just drawing one triangle, so I don't think this is related to the GPU being unable to keep up.

Any ideas?

Thanks,
-Farrell
Reply | Threaded
Open this post in threaded view
|

Re: Possible to have GLCanvas's display() called *after* all other Swing events?

farrellf
Any ideas?

-Farrell
Reply | Threaded
Open this post in threaded view
|

Re: Possible to have GLCanvas's display() called *after* all other Swing events?

gouessej
Administrator
We do our best, this effect isn't very pleasant but there is nothing we can do. Please can you indicate which version of Java and which operating system you use?
Julien Gouesse | Personal blog | Website
Reply | Threaded
Open this post in threaded view
|

Re: Possible to have GLCanvas's display() called *after* all other Swing events?

farrellf
Java version is:

java version "1.8.0_151"
Java(TM) SE Runtime Environment (build 1.8.0_151-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.151-b12, mixed mode)

OS version is: Windows 10 Pro, Version 1709.

-Farrell
Reply | Threaded
Open this post in threaded view
|

Re: Possible to have GLCanvas's display() called *after* all other Swing events?

farrellf
Source code for that demo is:

import javax.swing.JFrame;
import com.jogamp.opengl.GL2;
import com.jogamp.opengl.GLAutoDrawable;
import com.jogamp.opengl.GLCapabilities;
import com.jogamp.opengl.GLEventListener;
import com.jogamp.opengl.GLProfile;
import com.jogamp.opengl.awt.GLCanvas;
import com.jogamp.opengl.util.Animator;

public class Test {

        public static void main(String[] args) {
               
                JFrame window = new JFrame("Test");
               
                GLCanvas canvas = new GLCanvas(new GLCapabilities(GLProfile.get(GLProfile.GL2)));
                canvas.addGLEventListener(new GLEventListener() {
                       
                        @Override public void init(GLAutoDrawable drawable) {
                                GL2 gl = drawable.getGL().getGL2();
                                gl.setSwapInterval(1);
                        }
                       
                        @Override public void display(GLAutoDrawable drawable) {
                                GL2 gl = drawable.getGL().getGL2();

                                gl.glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
                                gl.glClear(GL2.GL_COLOR_BUFFER_BIT);
                               
                                gl.glColor3f(0, 0, 0);
                                gl.glBegin(GL2.GL_TRIANGLES);
                                        gl.glVertex2f(-0.9f, -0.9f);
                                        gl.glVertex2f( 0.0f,  0.9f);
                                        gl.glVertex2f( 0.9f, -0.9f);
                                gl.glEnd();
                        }
                       
                        @Override public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) { }
                        @Override public void dispose(GLAutoDrawable drawable) { }
                       
                });
               
                Animator animator = new Animator(canvas);
                animator.setUpdateFPSFrames(1, null);
                animator.start();
               
                window.add(canvas);
                window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                window.setSize(600, 600);
                window.setVisible(true);
               
        }
       
}
Reply | Threaded
Open this post in threaded view
|

Re: Possible to have GLCanvas's display() called *after* all other Swing events?

gouessej
Administrator
Do you reproduce your bug with this example?
https://gist.github.com/gouessej/3420e2b6f632efdddf98
Julien Gouesse | Personal blog | Website
Reply | Threaded
Open this post in threaded view
|

Re: Possible to have GLCanvas's display() called *after* all other Swing events?

farrellf
Yes, I have the same problem with that code too. I had to make the window resizeable (by changing line 78.) When I resize the window I see a white region where the OpenGL rendering region size is one-frame behind the current window size.

-Farrell
Reply | Threaded
Open this post in threaded view
|

Re: Possible to have GLCanvas's display() called *after* all other Swing events?

gouessej
Administrator
Which graphics card do you use?
Julien Gouesse | Personal blog | Website
Reply | Threaded
Open this post in threaded view
|

Re: Possible to have GLCanvas's display() called *after* all other Swing events?

farrellf
This happens with both an nVidia GTX1080 and with integrated graphics (Intel Iris Graphics 540, in a i7-6650U)

-Farrell
Reply | Threaded
Open this post in threaded view
|

Re: Possible to have GLCanvas's display() called *after* all other Swing events?

gouessej
Administrator
Intel Iris? Is it a surface book?
Julien Gouesse | Personal blog | Website
Reply | Threaded
Open this post in threaded view
|

Re: Possible to have GLCanvas's display() called *after* all other Swing events?

farrellf
Surface Pro 4. But like I said, this also happens with a GTX1080 (on my desktop.)

-Farrell
Reply | Threaded
Open this post in threaded view
|

Re: Possible to have GLCanvas's display() called *after* all other Swing events?

gouessej
Administrator
I reproduced this problem under Windows in a GUI written in Swing without using JOGL containing a JTreeTable and a few other component. This problem has nothing to do with JOGL but some options of Java2D might affect the behaviour of Swing. Do you use sun.awt.noerasebackground?
Julien Gouesse | Personal blog | Website
Reply | Threaded
Open this post in threaded view
|

Re: Possible to have GLCanvas's display() called *after* all other Swing events?

farrellf
I tried with and without "System.setProperty("sun.awt.noerasebackground", "true");" as my first line in main(). It looked the same both times.

So if this problem is related to Swing, would using NEWT prevent this?

-Farrell
Reply | Threaded
Open this post in threaded view
|

Re: Possible to have GLCanvas's display() called *after* all other Swing events?

gouessej
Administrator
Yes.

Does it look like this bug?
https://jogamp.org/bugzilla/show_bug.cgi?id=1182
Julien Gouesse | Personal blog | Website