weird mac+fullscreen excl. framerate issue

hey!

i’m writing a fullscreen-library for the processing programming language and one of the users pointed out to me that on his mac in fullscreen-exclusive mode he can only achieve 30fps.
it turns out this bug only appears on nvidia cards.

so i’ve tested on different versions of jogl to confirm this behavior.
with the jogl-jsr231-2.0 library from
in window mode i get ~900fps, while i only get a constant 30fps in fullscreen-exclusive mode.

so honestly i’m feeling lost and don’t know where to start searching for this problem.
sorry for this vague question, but if you have any advice or guess i’d be happy.

best,
hansi.

p.s.
I don’t think it matters much, but here’s the code i used:


package test;


import java.awt.GraphicsDevice;

import javax.media.opengl.GL;
import javax.media.opengl.GL2;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.awt.GLCanvas;
import javax.media.opengl.glu.GLU;
import javax.swing.JFrame;

import com.sun.opengl.util.FPSAnimator;
import com.sun.opengl.util.gl2.GLUT;

public class Test extends JFrame implements GLEventListener{
	// When is the last time we measured? 
	long lastMeasure = 0; 
	int frameCounter = 0; 
	float fps = 0; 
	
	GLUT glut = new GLUT();
	
    public static void main(String[] args) {
    	new Test(); 
    }
    
    public Test(){
        super( "hey ho!" ); 
        setSize( 300, 300 ); 
        setDefaultCloseOperation( EXIT_ON_CLOSE ); 
        setUndecorated( true ); 
        
        //enable/disable the next two lines for fullscreen-excl. mode
        //GraphicsDevice device = getGraphicsConfiguration().getDevice(); 
        //device.setFullScreenWindow( this ); 
        
        final GLCanvas canvas = new GLCanvas();
        canvas.addGLEventListener( this ); 
        getContentPane().add( canvas );

        
        setVisible( true );
    }

	@Override
	public void display( GLAutoDrawable drawable ){
		frameCounter ++; 
		
		if( System.currentTimeMillis() - lastMeasure > 1000 ){
			fps = frameCounter * 1000f / ( System.currentTimeMillis() - lastMeasure ); 
			lastMeasure = System.currentTimeMillis(); 
			frameCounter = 0; 
			
			System.out.println( fps ); 
		}
		
		GL2 gl = drawable.getGL().getGL2();
		gl.glLoadIdentity();  
		gl.glClearColor( 0, 0, 0, 1 );
		gl.glClear( GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT );
		
		gl.setSwapInterval( 0 ); 
		gl.glColor3f( 1, 1, 1 ); 
		gl.glRasterPos2i( 0, 0 ); 
		glut.glutBitmapString( GLUT.BITMAP_8_BY_13, fps + " fps" ); 
	}

	// All the code from here on is just annoying boilerplate. 
	@Override
	public void init( final GLAutoDrawable drawable ){
		System.out.println( "Init!" );
		GL2 gl = drawable.getGL().getGL2();
		
        gl.glShadeModel( GL2.GL_SMOOTH );
        gl.glClearDepth( 1.0 );
        gl.glDepthFunc( GL.GL_LEQUAL );
        gl.glEnable( GL.GL_DEPTH_TEST );
        gl.glHint( GL2.GL_PERSPECTIVE_CORRECTION_HINT, GL.GL_NICEST );
        
        gl.setSwapInterval( 0 ); 
        FPSAnimator animator = new FPSAnimator( drawable, 1000 );
        animator.start(); 
        
        // Also doesn't work: 
        // Animator animator2 = new Animator( drawable ); 
        // animator2.setRunAsFastAsPossible( true ); 
        // animator2.start();
	}

	@Override
	public void reshape( GLAutoDrawable drawable, int x, int y, int width, int height ){
		GL2 gl = drawable.getGL().getGL2();
		GLU glu = new GLU(); 
        gl.glViewport( 0, 0, width, height );
        gl.glMatrixMode( GL2.GL_PROJECTION );
        gl.glLoadIdentity();
        glu.gluPerspective( 45.0f, 0, 0.1f, 1000.0f);
        gl.glMatrixMode( GL2.GL_MODELVIEW );
        gl.glLoadIdentity(); 
        gl.setSwapInterval( 0 ); 
	}

	@Override
	public void dispose(GLAutoDrawable arg0) {
		// TODO Auto-generated method stub
	}
}

Hi!

Please remove this from the method display(GLAutoDrawable drawable):


gl.glClearColor( 0, 0, 0, 1 );
...
gl.setSwapInterval( 0 ); 

Do it only in init(GLAutoDrawable drawable).

Try to use a GLCanvas only to check if the problem comes from the GLJPanel. Let me know your results as soon as you can, I have no Mac :frowning:

Hey!

I moved glClearColor and setSwapInterval to init().

I was already using GLCanvas, but I tried replacing it with a GLJPanel.
Now I get the following results:

glJPanel, fullscreen: 42fps
glJPanel, windowed: 350fps

glCanvas, fullscreen: 30fps
glJPanel, windowd: 900fps

I have moved on to OpenCL4Java ( and maybe even to JavaCL ), so when I used JOGL it was never for visual purposes. I do still check here occasionally.

Looking at your code, this is your trigger for fullscreen right, and you are always doing undecorated in your tests?
//enable/disable the next two lines for fullscreen-excl. mode
//GraphicsDevice device = getGraphicsConfiguration().getDevice();
//device.setFullScreenWindow( this );

What happens if you use :
setExtendedState(java.awt.Frame.MAXIMIZED_BOTH);

I thought this might be worth a shot, since it is only a one line change.

Wow, this seriously worked!!!

My new resuls are
GLJPanel: 40fps
GLCanvas: 400fps

because I used setExtendedState(java.awt.Frame.MAXIMIZED_BOTH) in both, fullscreen and windowed mode, the framerates are basically the same now.
also i don’t really mind that GLJPanel is so slow, i´m using GLCanvas anyways :slight_smile:

Thanks a lot, this is like magic to me :slight_smile:

As I said in another topic, I found the myframe.setUndecorated(true) on mac dramatically decreases performances (300Hz to 15Hz for me). if someone has a workaround (the setExtendedState trick didn’t work for me)

hey!

can you post a link to “that other topic”?
for me the above solved the issue for fullscreen-exclusive mode only.
maximized windows (not fsem) still have the same problem for me, a simple but nasty workaround is to set the boundaries of your GLCanvas to (0, 0, screen.width-1,height)

best, h,-

one additional note:

when using FSEM and switching resolution it is important that the extended state is set AFTER changing the resolution, otherwise it will have no effect!