Feasible Fullscreen Model?

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

Feasible Fullscreen Model?

klatu
Hi!

After hours and hours of trying to wrap my head around JOGL, NEWT, etc I have finally managed to implement a simple JOGL application that:
-displays something using OpenGL
-has common GUI support (AWT)
-and can toggle fullscreen mode (without bugging out!)

Considering that I have rewritten the same app three times before, never fully utilizing all of the above, I just wanted to get some confirmation that the basic model I have now is feasible at all before I spent any more time on it.

Please leave suggestions on how to avoid problems down the road. If there is a better solution, please let me know.

CODE:

import java.awt.*;
import java.awt.Frame;
import java.awt.Button;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;

import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLProfile;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GL;
import javax.media.opengl.GL2;
import javax.media.opengl.glu.GLU;

import com.jogamp.opengl.util.FPSAnimator;
import com.jogamp.opengl.util.texture.Texture;
import com.jogamp.opengl.util.texture.TextureIO;
import com.jogamp.newt.awt.NewtCanvasAWT;

import com.jogamp.newt.opengl.GLWindow;
import com.jogamp.newt.event.KeyListener;
import com.jogamp.newt.event.KeyEvent;


public class NewtSuite
implements GLEventListener, KeyListener, ActionListener
{
	private	long		fps_time_start,
				fps_time_current,
				fps_time_passed;
	private	int		fps_frames, fps_frames_com;
	private			FPSAnimator	gl_FPSAnimator;
	private			GL2			gGL;
	private			GLU			gGLU;

	private			GLWindow		gl_GLWindow;

	NewtCanvasAWT	gl_canvas; 
	
	
	private boolean isFullscreen;
	
	
	private Frame	frame_normal, frame_full;
	
	
	public NewtSuite()
	{
		init_GLWindow();
		reparent_normal();
		gl_FPSAnimator	= new FPSAnimator(gl_GLWindow, 120);
		gl_FPSAnimator.start();
	}
	
	
	private void init_GLWindow()
	{
		gl_GLWindow	= GLWindow.create(getGLCapabilities());
		gl_GLWindow.setSize(800, 600);
		gl_GLWindow.addGLEventListener(this);
		gl_GLWindow.addKeyListener(this);
		gl_GLWindow.setVisible(true);

		gl_canvas	= new NewtCanvasAWT(gl_GLWindow);
		
		isFullscreen	= false;
	}
	
	private void reparent_normal()
	{
		frame_normal = new Frame("AWT Frame Normal");
		
		frame_normal.addWindowListener
			(new java.awt.event.WindowAdapter() {
				public void windowClosing(java.awt.event.WindowEvent e) {
					gl_FPSAnimator.stop();
					System.exit(0);
				}
			}
		);
		
		Button btn;
		
		frame_normal.setLayout(new BorderLayout());
		
		btn	= new Button("North");
		btn.setActionCommand("North");
		btn.addActionListener(this);
		frame_normal.add(btn, BorderLayout.NORTH);
		
		btn	= new Button("South");
		btn.setActionCommand("South");
		btn.addActionListener(this);
		frame_normal.add(btn, BorderLayout.SOUTH);

		btn	= new Button("East");
		btn.setActionCommand("East");
		btn.addActionListener(this);
		frame_normal.add(btn, BorderLayout.EAST);

		btn	= new Button("West");
		btn.setActionCommand("West");
		btn.addActionListener(this);		
		frame_normal.add(btn, BorderLayout.WEST);
		frame_normal.setSize(500, 500);
		frame_normal.setLocation(0, 0);
		

		frame_normal.setUndecorated(false);
		frame_normal.setExtendedState(Frame.NORMAL);
		frame_normal.setVisible(true);
		
		frame_normal.add(gl_canvas);
	}

	private void reparent_full()
	{
		frame_full = new Frame("AWT Frame Normal");
		
		frame_full.addWindowListener
			(new java.awt.event.WindowAdapter() {
				public void windowClosing(java.awt.event.WindowEvent e) {
					gl_FPSAnimator.stop();
					System.exit(0);
				}
			}
		);
		
		Button btn;
		
		frame_full.setLayout(new BorderLayout());
		
		btn	= new Button("North");
		btn.setActionCommand("North");
		btn.addActionListener(this);
		frame_full.add(btn, BorderLayout.NORTH);
		
		btn	= new Button("South");
		btn.setActionCommand("South");
		btn.addActionListener(this);
		frame_full.add(btn, BorderLayout.SOUTH);

		btn	= new Button("East");
		btn.setActionCommand("East");
		btn.addActionListener(this);
		frame_full.add(btn, BorderLayout.EAST);

		btn	= new Button("West");
		btn.setActionCommand("West");
		btn.addActionListener(this);		
		frame_full.add(btn, BorderLayout.WEST);
		frame_full.setSize(500, 500);
		frame_full.setLocation(0, 0);
		

		frame_full.setUndecorated(true);
		frame_full.setExtendedState(Frame.MAXIMIZED_BOTH);
		frame_full.setVisible(true);
		
		frame_full.add(gl_canvas);
	}
	
	private void toggle_fullscreen()
	{
		if (frame_full != null && frame_full.isVisible()){
			
			reparent_normal();
			isFullscreen	= false;
			frame_full.setVisible(false);
		}else{
		
			reparent_full();
			isFullscreen	= true;
			frame_normal.setVisible(false);
		}
		gl_GLWindow.requestFocus();
	}

	@Override
	public void keyPressed(KeyEvent e)
	{
		System.out.println("pressed");
		toggle_fullscreen();
	}
	
	@Override
	public void keyReleased(KeyEvent e)
	{

	}
	
	@Override
	public void keyTyped(KeyEvent e)
	{

	}

	public void actionPerformed(ActionEvent e)
	{
		System.out.println(e.getActionCommand()+"");
	
	}
	
	@Override
	public void init(GLAutoDrawable arg0) {
		this.gGL		= arg0.getGL().getGL2();
		this.gGLU	= new GLU();
		this.gGL.glEnable(GL2.GL_DEPTH_TEST);
		this.gGL.glEnable(GL2.GL_TEXTURE_2D);

		this.gGL.glEnableClientState(GL2.GL_VERTEX_ARRAY);
		this.gGL.glEnableClientState(GL2.GL_TEXTURE_COORD_ARRAY);
		
		
		fps_time_start	= System.currentTimeMillis();
		fps_frames		= 0;
	}

	@Override
	public void display(GLAutoDrawable arg0) {
		this.gGL.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT);
		this.gGL.glMatrixMode(GL2.GL_PROJECTION);
		this.gGL.glLoadIdentity();
		this.gGL.glOrtho(0,500,0,500,-1,1);
		this.gGL.glBegin(GL2.GL_QUADS);
			this.gGL.glTexCoord2d	(0.0,1.0);
			this.gGL.glVertex2d	(100, 100); // Bottom Left
			this.gGL.glTexCoord2d	(1.0,1.0);
			this.gGL.glVertex2d	(200, 100); // Bottom Right
			this.gGL.glTexCoord2d	(1.0,0.0);
			this.gGL.glVertex2d	(200, 200); // Top Right
			this.gGL.glTexCoord2d	(0.0,0.0);
			this.gGL.glVertex2d	(100, 200+ fps_frames); // Top Left
		this.gGL.glEnd();
		
		
		fps_frames++;

		fps_time_current	= System.currentTimeMillis();
		
		fps_time_passed		= fps_time_current - fps_time_start;
		if (fps_time_passed > 1000)
		{
			System.out.println(""+fps_frames);
			fps_frames_com	= fps_frames;
			fps_frames		= 0;
			fps_time_start	= fps_time_current;
			
		}
	}
	
	@Override
	public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, int height) {

	}

	public GLCapabilities getGLCapabilities() {
		GLProfile glp = GLProfile.getDefault();
		return new GLCapabilities(glp);
	}
	
	@Override
	public void dispose(GLAutoDrawable arg0) {
	
	}

	public static void main(String[] args) {
		new NewtSuite();
	}

}









Reply | Threaded
Open this post in threaded view
|

Re: Feasible Fullscreen Model?

gouessej
Administrator
Hi

AWT full screen mode is broken on some platforms including GNU Linux. You can fix solve this problem by using GLWindow. Sorry to disappoint you.
Julien Gouesse | Personal blog | Website
Reply | Threaded
Open this post in threaded view
|

Re: Feasible Fullscreen Model?

klatu
That is kind of my question. I am using a GLWindow that gets re-parented into different AWT-Frames when switching modes.

Alternatively, is there any way to have standard UI components in a GLWindow?
Reply | Threaded
Open this post in threaded view
|

Re: Feasible Fullscreen Model?

gouessej
Administrator
I have forgotten another problem. If you don't use NEWT, the OpenGL context will be destroyed when switching from full screen to windowed mode and vice versa except if you tinker... a lot.

Perhaps you can use a GLWindow whose child component is a NEWTCanvasAWT. Then, you don't need to use an instance of java.awt.Frame. When you want to switch from full screen mode, just call setUndecorated(boolean) and setFullscreen(boolean) on your main GLWindow.

If it doesn't work, I will try to provide you a better solution. There are GUI libraries directly based on JOGL but they have all some drawbacks:
- some widgets are directly in JOGL but they require shader support
- FengGui is somehow unusable, a contributor started a big code redesign on the SVN repository and left it unfinished
- Nifty Gui is very good but its memory footprint is prohibitive
- PureSwing could be ported to JOGL but its main contributor plans to stop its development soon
- TWL could be ported to JOGL but I don't know whether it would be a trivial task

@Sven, do you have a better solution to suggest?
Julien Gouesse | Personal blog | Website
Reply | Threaded
Open this post in threaded view
|

Re: Feasible Fullscreen Model?

klatu
I don't think it's possible to add Components to a GLWindow.

Using GLWindow's addChild method only works with NativeWindow objects. NewtCanvasAWT is of the Component class and can't be added to GLWindow. Or I don't know how, anyway.

From what I can tell, my GLContext doesn't get destroyed. I haven't been getting any exceptions so far.
Are you saying it might be possible to add AWT components to the NewtCanvasAWT directly? I haven't actually tried that yet.


I don't think I have the skill or patience to port any of those GUIs. I wouldn't even know where to begin.
Reply | Threaded
Open this post in threaded view
|

Re: Feasible Fullscreen Model?

klatu
Hmm, I can only add a PopupMenu to the NewtCanvasAwt and even that causes an exception because the canvas is not actually a visible component. Bummer.

I still hope there's a solution with no awt frame.

Thank you for the help so far.
Reply | Threaded
Open this post in threaded view
|

Re: Feasible Fullscreen Model?

Sven Gothel
Administrator
In reply to this post by gouessej
On Tuesday, January 17, 2012 12:11:26 AM gouessej [via jogamp] wrote:

>
> I have forgotten another problem. If you don't use NEWT, the OpenGL context
> will be destroyed when switching from full screen to windowed mode and vice
> versa except if you tinker... a lot.
>
> Perhaps you can use a GLWindow whose child component is a NEWTCanvasAWT.
> Then, you don't need to use an instance of java.awt.Frame. When you want to
> switch from full screen mode, just call setUndecorated(boolean) and
> setFullscreen(boolean) on your main GLWindow.
>
> If it doesn't work, I will try to provide you a better solution. There are
> GUI libraries directly based on JOGL but they have all some drawbacks:
> - some widgets are directly in JOGL but they require shader support
> - FengGui is somehow unusable, a contributor started a big code redesign on
> the SVN repository and left it unfinished
> - Nifty Gui is very good but its memory footprint is prohibitive
> - PureSwing could be ported to JOGL but its main contributor plans to stop
> its development soon
> - TWL could be ported to JOGL but I don't know whether it would be a trivial
> task
>
> @Sven, do you have a better solution to suggest?

It would be great if an active maintainer of the above mentioned
OpenGL GUI's would port or accept our patches, yes.

AFAIK there were some approaches to render AWT/Swing to an offscreen image,
but I don't know whats the status of it. Nevertheless this would require a
solution for input events as well.

I guess Julien is more up to date with all the packages floating around.

+++

At least Rami and I will enhance Graph UI this year to become more usable.

GLWindow is a pure NEWT component not designed to hold AWT or SWT,
it supports proper fullscreen mode w/ screen mode change.

NewtCanvasAWT is an adapter to plug-in NEWT to AWT,
not the other way around.

~Sven
Reply | Threaded
Open this post in threaded view
|

Re: Feasible Fullscreen Model?

gouessej
Administrator
In reply to this post by klatu
I wrote a bug report, I tried to port Sven's fix in AWT but I failed. I think it would be the best solution because it would allow you to use AWT and Swing inside a full screen frame without any other third party library except JOGL, the only remaining problem would be the handling of the OpenGL context.

As far as I know, you can create a NewtCanvasAWT with a GLWindow as a parent:
http://jogamp.org/deployment/jogamp-next/javadoc/jogl/javadoc/com/jogamp/newt/awt/NewtCanvasAWT.html#NewtCanvasAWT(com.jogamp.newt.Window)
Give it a try and if it works for you, I will check if it works fine on GNU Linux too.
Julien Gouesse | Personal blog | Website
Reply | Threaded
Open this post in threaded view
|

Re: Feasible Fullscreen Model?

Sven Gothel
Administrator
On Tuesday, January 17, 2012 10:36:01 AM gouessej [via jogamp] wrote:
>
> As far as I know, you can create a NewtCanvasAWT with a GLWindow as a
> parent:

*as a child.

GLWindow is a native _child_ of NewtCanvasAWT.
NewtCanvasAWT is a native _parent_ of GLWindow.

*native*, because it utilizes the native windowing toolkit's parenting
not AWT's, which is the solution to make it work.

> http://jogamp.org/deployment/jogamp-next/javadoc/jogl/javadoc/com/jogamp/newt/awt/NewtCanvasAWT.html#NewtCanvasAWT(com.jogamp.newt.Window)
> http://jogamp.org/deployment/jogamp-next/javadoc/jogl/javadoc/com/jogamp/newt/awt/NewtCanvasAWT.html#NewtCanvasAWT(com.jogamp.newt.Window)
> Give it a try and if it works for you, I will check if it works fine on GNU
> Linux too.
Reply | Threaded
Open this post in threaded view
|

Re: Feasible Fullscreen Model?

klatu
Thank you both for the effort!

It's not the answer I was hoping for, but at least I know how it works now.

@gouessej
I may be wrong, but I remember reading on this board somewhere that you have made a port for Nifty GUI. If so, where could I find it?

@Sven
Graph UI looks like it has potential. Sadly it's not really what I'm looking for right now.

Luckily I don't need my app to be platform independent, so I will stick to my current model for the time being.

Thank you.
Reply | Threaded
Open this post in threaded view
|

Re: Feasible Fullscreen Model?

gouessej
Administrator
The source code is here but my renderer has probably not been maintained:
http://nifty-gui.git.sourceforge.net/git/gitweb-index.cgi
Julien Gouesse | Personal blog | Website