diff --git a/engine/src/jogl/com/jme3/system/jogl/JoglAbstractDisplay.java b/engine/src/jogl/com/jme3/system/jogl/JoglAbstractDisplay.java index a96a6a2c2..7c892ff7d 100644 --- a/engine/src/jogl/com/jme3/system/jogl/JoglAbstractDisplay.java +++ b/engine/src/jogl/com/jme3/system/jogl/JoglAbstractDisplay.java @@ -77,7 +77,7 @@ public abstract class JoglAbstractDisplay extends JoglContext implements GLEvent device = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice(); GLCapabilities caps = new GLCapabilities(GLProfile.getDefault()); - caps.setHardwareAccelerated(true); + /*caps.setHardwareAccelerated(true); caps.setDoubleBuffered(true); caps.setStencilBits(settings.getStencilBits()); caps.setDepthBits(settings.getDepthBits()); @@ -85,7 +85,7 @@ public abstract class JoglAbstractDisplay extends JoglContext implements GLEvent if (settings.getSamples() > 1) { caps.setSampleBuffers(true); caps.setNumSamples(settings.getSamples()); - } + }*/ canvas = new GLCanvas(caps) { @Override @@ -105,9 +105,14 @@ public abstract class JoglAbstractDisplay extends JoglContext implements GLEvent canvas.getGL().setSwapInterval(1); } canvas.setFocusable(true); + canvas.requestFocus(); + canvas.setSize(settings.getWidth(), settings.getHeight()); canvas.setIgnoreRepaint(true); + //canvas.setAutoSwapBufferMode(false); canvas.addGLEventListener(this); + + // N.B: it is too early to get the GL instance from the canvas // if (false){ // trace mode @@ -128,8 +133,9 @@ public abstract class JoglAbstractDisplay extends JoglContext implements GLEvent // ((FPSAnimator)animator).setRunAsFastAsPossible(true); } else { - animator = new Animator(canvas); - ((Animator) animator).setRunAsFastAsPossible(true); + animator = new Animator(); + animator.add(canvas); + //((Animator) animator).setRunAsFastAsPossible(true); } animator.start(); @@ -144,12 +150,16 @@ public abstract class JoglAbstractDisplay extends JoglContext implements GLEvent @Override public KeyInput getKeyInput() { - return new AwtKeyInput(/*canvas*/); + AwtKeyInput awtKeyInput = new AwtKeyInput(); + awtKeyInput.setInputSource(canvas); + return awtKeyInput; } @Override public MouseInput getMouseInput() { - return new AwtMouseInput(/*canvas*/); + AwtMouseInput awtMouseInput = new AwtMouseInput(); + awtMouseInput.setInputSource(canvas); + return awtMouseInput; } public TouchInput getTouchInput() { diff --git a/engine/src/jogl/com/jme3/system/jogl/JoglCanvas.java b/engine/src/jogl/com/jme3/system/jogl/JoglCanvas.java index e626cbefd..71ef11934 100644 --- a/engine/src/jogl/com/jme3/system/jogl/JoglCanvas.java +++ b/engine/src/jogl/com/jme3/system/jogl/JoglCanvas.java @@ -97,11 +97,14 @@ public class JoglCanvas extends JoglAbstractDisplay implements JmeCanvasContext return; } - if (width != canvas.getWidth() || height != canvas.getHeight()){ - width = canvas.getWidth(); - height = canvas.getHeight(); - if (listener != null) + int newWidth = Math.max(canvas.getWidth(), 1); + int newHeight = Math.max(canvas.getHeight(), 1); + if (width != newWidth || height != newHeight) { + width = newWidth; + height = newHeight; + if (listener != null) { listener.reshape(width, height); + } } boolean flush = autoFlush.get(); diff --git a/engine/src/jogl/com/jme3/system/jogl/JoglDisplay.java b/engine/src/jogl/com/jme3/system/jogl/JoglDisplay.java index 7a8eb3465..32469f208 100644 --- a/engine/src/jogl/com/jme3/system/jogl/JoglDisplay.java +++ b/engine/src/jogl/com/jme3/system/jogl/JoglDisplay.java @@ -33,11 +33,11 @@ package com.jme3.system.jogl; import com.jme3.system.AppSettings; -import java.awt.BorderLayout; -import java.awt.Container; import java.awt.Dimension; import java.awt.DisplayMode; import java.awt.Frame; +import java.awt.GraphicsDevice; +import java.awt.GraphicsEnvironment; import java.awt.Toolkit; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; @@ -46,6 +46,7 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.logging.Level; import java.util.logging.Logger; import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLContext; import javax.swing.JFrame; import javax.swing.SwingUtilities; @@ -56,14 +57,14 @@ public class JoglDisplay extends JoglAbstractDisplay { protected AtomicBoolean windowCloseRequest = new AtomicBoolean(false); protected AtomicBoolean needClose = new AtomicBoolean(false); protected AtomicBoolean needRestart = new AtomicBoolean(false); - protected boolean wasInited = false; + protected volatile boolean wasInited = false; protected Frame frame; public Type getType() { return Type.Display; } - protected DisplayMode getFullscreenDisplayMode(DisplayMode[] modes, int width, int height, int bpp, int freq){ + /*protected DisplayMode getFullscreenDisplayMode(DisplayMode[] modes, int width, int height, int bpp, int freq){ for (DisplayMode mode : modes){ if (mode.getWidth() == width && mode.getHeight() == height @@ -75,43 +76,34 @@ public class JoglDisplay extends JoglAbstractDisplay { } } return null; - } + }*/ protected void createGLFrame(){ - Container contentPane; + //Container contentPane; if (useAwt){ frame = new Frame(settings.getTitle()); - contentPane = frame; + //contentPane = frame; }else{ frame = new JFrame(settings.getTitle()); - contentPane = ((JFrame)frame).getContentPane(); + //contentPane = ((JFrame)frame).getContentPane(); } - - contentPane.setLayout(new BorderLayout()); - - applySettings(settings); - frame.setResizable(false); - frame.setFocusable(true); - - // only add canvas after frame is visible - contentPane.add(canvas, BorderLayout.CENTER); - //frame.pack(); -// frame.setSize(contentPane.getPreferredSize()); - frame.setSize(settings.getWidth(),settings.getHeight()); - - if (device.getFullScreenWindow() == null){ - // now that canvas is attached, - // determine optimal size to contain it - - Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); - frame.setLocation((screenSize.width - frame.getWidth()) / 2, - (screenSize.height - frame.getHeight()) / 2); - } - + frame.add(canvas); + //frame.validate(); + + applySettings(settings); + frame.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent evt) { + // If required, restore the previous display mode + /*if (isDisplayModeModified) { + gd.setDisplayMode(previousDisplayMode); + } + // If required, get back to the windowed mode + if (gd.getFullScreenWindow() == frame) { + gd.setFullScreenWindow(null); + }*/ windowCloseRequest.set(true); } @Override @@ -124,65 +116,136 @@ public class JoglDisplay extends JoglAbstractDisplay { active.set(false); } }); + + // Make the window visible to realize the OpenGL surface. + frame.setVisible(true); + + canvas.setVisible(true); + + final GLContext context = canvas.getContext(); + + /*canvas.invoke(true, new GLRunnable() { + @Override + public boolean run(GLAutoDrawable glAutoDrawable) { + context.makeCurrent(); + try { + startGLCanvas(); + } + finally { + context.release(); + } + return true; + } + });*/ } protected void applySettings(AppSettings settings){ - DisplayMode displayMode; - if (settings.getWidth() <= 0 || settings.getHeight() <= 0){ - displayMode = device.getDisplayMode(); - settings.setResolution(displayMode.getWidth(), displayMode.getHeight()); - }else if (settings.isFullscreen()){ - displayMode = getFullscreenDisplayMode(device.getDisplayModes(), - settings.getWidth(), settings.getHeight(), - settings.getBitsPerPixel(), settings.getFrequency()); - if (displayMode == null) - throw new RuntimeException("Unable to find fullscreen display mode matching settings"); - }else{ - displayMode = new DisplayMode(settings.getWidth(), settings.getHeight(), DisplayMode.BIT_DEPTH_MULTI, DisplayMode.REFRESH_RATE_UNKNOWN); - } - - // FIXME: seems to return false even though - // it is supported.. -// if (!device.isDisplayChangeSupported()){ -// // must use current device mode if display mode change not supported -// displayMode = device.getDisplayMode(); -// settings.setResolution(displayMode.getWidth(), displayMode.getHeight()); -// } - - frameRate = settings.getFrameRate(); - logger.log(Level.INFO, "Selected display mode: {0}x{1}x{2} @{3}", - new Object[]{displayMode.getWidth(), - displayMode.getHeight(), - displayMode.getBitDepth(), - displayMode.getRefreshRate()}); - - canvas.setSize(displayMode.getWidth(), displayMode.getHeight()); - - DisplayMode prevDisplayMode = device.getDisplayMode(); - - if (settings.isFullscreen() && device.isFullScreenSupported()){ + final boolean isDisplayModeModified; + final GraphicsDevice gd = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice(); + // Get the current display mode + final DisplayMode previousDisplayMode = gd.getDisplayMode(); + // Handle full screen mode if requested. + if (settings.isFullscreen()) { frame.setUndecorated(true); - - try{ - device.setFullScreenWindow(frame); - if (!prevDisplayMode.equals(displayMode) - && device.isDisplayChangeSupported()){ - device.setDisplayMode(displayMode); + // Check if the full-screen mode is supported by the OS + boolean isFullScreenSupported = gd.isFullScreenSupported(); + if (isFullScreenSupported) { + gd.setFullScreenWindow(frame); + // Check if display mode changes are supported by the OS + if (gd.isDisplayChangeSupported()) { + // Get all available display modes + final DisplayMode[] displayModes = gd.getDisplayModes(); + DisplayMode multiBitsDepthSupportedDisplayMode = null; + DisplayMode refreshRateUnknownDisplayMode = null; + DisplayMode multiBitsDepthSupportedAndRefreshRateUnknownDisplayMode = null; + DisplayMode matchingDisplayMode = null; + DisplayMode currentDisplayMode; + // Look for the display mode that matches with our parameters + // Look for some display modes that are close to these parameters + // and that could be used as substitutes + // On some machines, the refresh rate is unknown and/or multi bit + // depths are supported. If you try to force a particular refresh + // rate or a bit depth, you might find no available display mode + // that matches exactly with your parameters + for (int i = 0; i < displayModes.length && matchingDisplayMode == null; i++) { + currentDisplayMode = displayModes[i]; + if (currentDisplayMode.getWidth() == settings.getWidth() + && currentDisplayMode.getHeight() == settings.getHeight()) { + if (currentDisplayMode.getBitDepth() == settings.getBitsPerPixel()) { + if (currentDisplayMode.getRefreshRate() == settings.getFrequency()) { + matchingDisplayMode = currentDisplayMode; + } else if (currentDisplayMode.getRefreshRate() == DisplayMode.REFRESH_RATE_UNKNOWN) { + refreshRateUnknownDisplayMode = currentDisplayMode; + } + } else if (currentDisplayMode.getBitDepth() == DisplayMode.BIT_DEPTH_MULTI) { + if (currentDisplayMode.getRefreshRate() == settings.getFrequency()) { + multiBitsDepthSupportedDisplayMode = currentDisplayMode; + } else if (currentDisplayMode.getRefreshRate() == DisplayMode.REFRESH_RATE_UNKNOWN) { + multiBitsDepthSupportedAndRefreshRateUnknownDisplayMode = currentDisplayMode; + } + } + } + } + DisplayMode nextDisplayMode = null; + if (matchingDisplayMode != null) { + nextDisplayMode = matchingDisplayMode; + } else if (multiBitsDepthSupportedDisplayMode != null) { + nextDisplayMode = multiBitsDepthSupportedDisplayMode; + } else if (refreshRateUnknownDisplayMode != null) { + nextDisplayMode = refreshRateUnknownDisplayMode; + } else if (multiBitsDepthSupportedAndRefreshRateUnknownDisplayMode != null) { + nextDisplayMode = multiBitsDepthSupportedAndRefreshRateUnknownDisplayMode; + } else { + isFullScreenSupported = false; + } + // If we have found a display mode that approximatively matches + // with the input parameters, use it + if (nextDisplayMode != null) { + gd.setDisplayMode(nextDisplayMode); + isDisplayModeModified = true; + } else { + isDisplayModeModified = false; + } + } else { + isDisplayModeModified = false; + // Resize the canvas if the display mode cannot be changed + // and the screen size is not equal to the canvas size + final Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); + if (screenSize.width != settings.getWidth() || screenSize.height != settings.getHeight()) { + canvas.setSize(screenSize); + } } - } catch (Throwable t){ - logger.log(Level.SEVERE, "Failed to enter fullscreen mode", t); - device.setFullScreenWindow(null); - } - }else{ - if (!device.isFullScreenSupported()){ - logger.warning("Fullscreen not supported."); - }else{ - frame.setUndecorated(false); - device.setFullScreenWindow(null); + } else { + isDisplayModeModified = false; } - frame.setVisible(true); + // Software windowed full-screen mode + if (!isFullScreenSupported) { + final Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); + // Resize the canvas + canvas.setSize(screenSize); + // Resize the frame so that it occupies the whole screen + frame.setSize(screenSize); + // Set its location at the top left corner + frame.setLocation(0, 0); + } + } + // Otherwise, center the window on the screen. + else { + isDisplayModeModified = false; + frame.pack(); + + int x, y; + x = (Toolkit.getDefaultToolkit().getScreenSize().width - settings.getWidth()) / 2; + y = (Toolkit.getDefaultToolkit().getScreenSize().height - settings.getHeight()) / 2; + frame.setLocation(x, y); } + + logger.log(Level.INFO, "Selected display mode: {0}x{1}x{2} @{3}", + new Object[]{frame.getWidth(), + frame.getHeight(), + 0, + 0}); } private void initInEDT(){