diff options
3 files changed, 253 insertions, 75 deletions
diff --git a/ardor3d-core/src/main/java/com/ardor3d/framework/DisplaySettings.java b/ardor3d-core/src/main/java/com/ardor3d/framework/DisplaySettings.java index 19aed1c..a7a75ef 100644 --- a/ardor3d-core/src/main/java/com/ardor3d/framework/DisplaySettings.java +++ b/ardor3d-core/src/main/java/com/ardor3d/framework/DisplaySettings.java @@ -22,40 +22,82 @@ public class DisplaySettings { private final boolean _fullScreen; private final boolean _stereo; private final CanvasRenderer _shareContext; + private final int _rotation; /** - * Convenience method equivalent to <code>DisplaySettings(width, height, 0, 0, 0, 8, 0, 0, - * false, false, null)</code> - * + * Creates a new <code>DisplaySettings</code> object. + * * @param width * the canvas width * @param height * the canvas height + * @param colorDepth + * the number of color bits used to represent the color of a single pixel + * @param frequency + * the number of times per second to repaint the canvas + * @param alphaBits + * the numner of bits used to represent the translucency of a single pixel * @param depthBits * the number of bits making up the z-buffer + * @param stencilBits + * the number of bits making up the stencil buffer * @param samples * the number of samples used to anti-alias + * @param fullScreen + * true if the canvas should assume exclusive access to the screen + * @param stereo + * true if the canvas should be rendered stereoscopically (for 3D glasses) + * @param shareContext + * the renderer used to render the canvas (see "ardor3d.useMultipleContexts" property) + * @param rotation + * the rotation of the first monitor * @see http://en.wikipedia.org/wiki/Z-buffering * @see http://en.wikipedia.org/wiki/Multisample_anti-aliasing + * @see http://en.wikipedia.org/wiki/Refresh_rate + * @see http://en.wikipedia.org/wiki/Alpha_compositing + * @see http://en.wikipedia.org/wiki/Stencil_buffer + * @see http://en.wikipedia.org/wiki/Stereoscopy + * @see http://www.ardor3d.com/forums/viewtopic.php?f=13&t=318&p=2311&hilit=ardor3d.useMultipleContexts#p2311 */ - public DisplaySettings(final int width, final int height, final int depthBits, final int samples) { + public DisplaySettings(final int width, final int height, final int colorDepth, final int frequency, + final int alphaBits, final int depthBits, final int stencilBits, final int samples, + final boolean fullScreen, final boolean stereo, final CanvasRenderer shareContext, final int rotation) { + super(); _width = width; _height = height; - _colorDepth = 0; - _frequency = 0; - _alphaBits = 0; + _colorDepth = colorDepth; + _frequency = frequency; + _alphaBits = alphaBits; _depthBits = depthBits; - _stencilBits = 0; + _stencilBits = stencilBits; _samples = samples; - _fullScreen = false; - _stereo = false; - _shareContext = null; + _fullScreen = fullScreen; + _stereo = stereo; + _shareContext = shareContext; + _rotation = rotation; + } + + /** + * Convenience method + * + * @param width + * the canvas width + * @param height + * the canvas height + * @param depthBits + * the number of bits making up the z-buffer + * @param samples + * the number of samples used to anti-alias + * @see http://en.wikipedia.org/wiki/Z-buffering + * @see http://en.wikipedia.org/wiki/Multisample_anti-aliasing + */ + public DisplaySettings(final int width, final int height, final int depthBits, final int samples) { + this(width, height, 0, 0, 0, depthBits, 0, samples, false, false, null, 0); } /** - * Convenience method equivalent to <code>DisplaySettings(width, height, colorDepth, frequency, - * 0, 8, 0, 0, fullScreen, false, null)</code> - * + * Convenience method + * * @param width * the canvas width * @param height @@ -70,23 +112,13 @@ public class DisplaySettings { */ public DisplaySettings(final int width, final int height, final int colorDepth, final int frequency, final boolean fullScreen) { - _width = width; - _height = height; - _colorDepth = colorDepth; - _frequency = frequency; - _alphaBits = 0; - _depthBits = 8; - _stencilBits = 0; - _samples = 0; - _fullScreen = fullScreen; - _stereo = false; - _shareContext = null; + this(width, height, colorDepth, frequency, 0, 8, 0, 0, fullScreen, false, null, 0); } /** - * Convenience method equivalent to <code>DisplaySettings(width, height, colorDepth, frequency, - * alphaBits, depthBits, stencilBits, samples, fullScreen, stereo, null)</code> - * + * Convenience method equivalent to <code>DisplaySettings(width, height, colorDepth, frequency, + * alphaBits, depthBits, stencilBits, samples, fullScreen, stereo, null, 0)</code> + * * @param width * the canvas width * @param height @@ -115,22 +147,13 @@ public class DisplaySettings { public DisplaySettings(final int width, final int height, final int colorDepth, final int frequency, final int alphaBits, final int depthBits, final int stencilBits, final int samples, final boolean fullScreen, final boolean stereo) { - _width = width; - _height = height; - _colorDepth = colorDepth; - _frequency = frequency; - _alphaBits = alphaBits; - _depthBits = depthBits; - _stencilBits = stencilBits; - _samples = samples; - _fullScreen = fullScreen; - _stereo = stereo; - _shareContext = null; + this(width, height, colorDepth, frequency, alphaBits, depthBits, stencilBits, samples, fullScreen, stereo, + null, 0); } /** - * Creates a new <code>DisplaySettings</code> object. - * + * Creates a new <code>DisplaySettings</code> object with no rotation. + * * @param width * the canvas width * @param height @@ -164,17 +187,8 @@ public class DisplaySettings { public DisplaySettings(final int width, final int height, final int colorDepth, final int frequency, final int alphaBits, final int depthBits, final int stencilBits, final int samples, final boolean fullScreen, final boolean stereo, final CanvasRenderer shareContext) { - _width = width; - _height = height; - _colorDepth = colorDepth; - _frequency = frequency; - _alphaBits = alphaBits; - _depthBits = depthBits; - _stencilBits = stencilBits; - _samples = samples; - _fullScreen = fullScreen; - _stereo = stereo; - _shareContext = shareContext; + this(width, height, colorDepth, frequency, alphaBits, depthBits, stencilBits, samples, fullScreen, stereo, + shareContext, 0); } public CanvasRenderer getShareContext() { @@ -221,6 +235,10 @@ public class DisplaySettings { return _stereo; } + public int getRotation() { + return _rotation; + } + @Override public boolean equals(final Object o) { if (this == o) { @@ -243,7 +261,7 @@ public class DisplaySettings { && _samples != that._samples && _stereo != that._stereo && ((_shareContext == that._shareContext) || (_shareContext != null && _shareContext - .equals(that._shareContext))); + .equals(that._shareContext))); } @Override diff --git a/ardor3d-jogl/src/main/java/com/ardor3d/framework/jogl/CapsUtil.java b/ardor3d-jogl/src/main/java/com/ardor3d/framework/jogl/CapsUtil.java index de995a9..8d46d28 100644 --- a/ardor3d-jogl/src/main/java/com/ardor3d/framework/jogl/CapsUtil.java +++ b/ardor3d-jogl/src/main/java/com/ardor3d/framework/jogl/CapsUtil.java @@ -41,6 +41,29 @@ public class CapsUtil { return getCapsForSettings(settings, true, false, false, false); } + /** + * for internal use only, tolerates artificial display settings containing hints + * + * @param settings + * @param onscreen + * @param bitmapRequested + * @param pbufferRequested + * @param fboRequested + * @return + */ + GLCapabilities getCapsForSettingsWithHints(final DisplaySettings settings, final boolean onscreen, + final boolean bitmapRequested, final boolean pbufferRequested, final boolean fboRequested) { + final DisplaySettings realSettings; + if (settings.isFullScreen() && (settings.getWidth() == 0 || settings.getHeight() == 0)) { + realSettings = new DisplaySettings(1, 1, settings.getColorDepth(), settings.getFrequency(), + settings.getAlphaBits(), settings.getDepthBits(), settings.getStencilBits(), settings.getSamples(), + true, settings.isStereo(), settings.getShareContext(), settings.getRotation()); + } else { + realSettings = settings; + } + return getCapsForSettings(realSettings, onscreen, bitmapRequested, pbufferRequested, fboRequested); + } + public GLCapabilities getCapsForSettings(final DisplaySettings settings, final boolean onscreen, final boolean bitmapRequested, final boolean pbufferRequested, final boolean fboRequested) { @@ -51,7 +74,7 @@ public class CapsUtil { // Validate bit depth. if ((settings.getColorDepth() != 32) && (settings.getColorDepth() != 16) && (settings.getColorDepth() != 24) - && (settings.getColorDepth() != -1)) { + && (settings.getColorDepth() != 0) && (settings.getColorDepth() != -1)) { throw new Ardor3dException("Invalid pixel depth: " + settings.getColorDepth()); } diff --git a/ardor3d-jogl/src/main/java/com/ardor3d/framework/jogl/JoglNewtWindow.java b/ardor3d-jogl/src/main/java/com/ardor3d/framework/jogl/JoglNewtWindow.java index 0f73157..1063026 100644 --- a/ardor3d-jogl/src/main/java/com/ardor3d/framework/jogl/JoglNewtWindow.java +++ b/ardor3d-jogl/src/main/java/com/ardor3d/framework/jogl/JoglNewtWindow.java @@ -10,6 +10,8 @@ package com.ardor3d.framework.jogl; +import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.concurrent.CountDownLatch; @@ -19,6 +21,7 @@ import com.ardor3d.framework.NativeCanvas; import com.ardor3d.image.Image; import com.jogamp.nativewindow.ScalableSurface; import com.jogamp.nativewindow.util.Dimension; +import com.jogamp.nativewindow.util.DimensionImmutable; import com.jogamp.newt.MonitorDevice; import com.jogamp.newt.MonitorMode; import com.jogamp.newt.event.KeyListener; @@ -49,6 +52,9 @@ public class JoglNewtWindow implements NativeCanvas, NewtWindowContainer { private final GLWindow _newtWindow; + /** list of monitor devices used in fullscreen mode, ignored in windowed mode */ + private List<MonitorDevice> _monitorDevices; + public JoglNewtWindow(final JoglCanvasRenderer canvasRenderer, final DisplaySettings settings) { this(canvasRenderer, settings, true, false, false, false); } @@ -62,13 +68,29 @@ public class JoglNewtWindow implements NativeCanvas, NewtWindowContainer { public JoglNewtWindow(final JoglCanvasRenderer canvasRenderer, final DisplaySettings settings, final boolean onscreen, final boolean bitmapRequested, final boolean pbufferRequested, final boolean fboRequested, final CapsUtil capsUtil) { - _newtWindow = GLWindow.create(capsUtil.getCapsForSettings(settings, onscreen, bitmapRequested, + // FIXME rather pass the monitor(s) to the constructor, create a screen to get the primary monitor + _newtWindow = GLWindow.create(capsUtil.getCapsForSettingsWithHints(settings, onscreen, bitmapRequested, pbufferRequested, fboRequested)); + _monitorDevices = new ArrayList<MonitorDevice>(); + // uses the primary monitor by default + _newtWindow.getScreen().createNative(); + final MonitorDevice primaryMonitor = _newtWindow.getScreen().getPrimaryMonitor(); + _monitorDevices.add(primaryMonitor); // disables HiDPI, see https://github.com/gouessej/Ardor3D/issues/14 _newtWindow.setSurfaceScale(new float[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE }); _drawerGLRunnable = new JoglDrawerRunnable(canvasRenderer); - _settings = settings; + if (settings.isFullScreen() && settings.getWidth() == 0 || settings.getHeight() == 0) { + // FIXME use all available monitor devices to compute the size + final DimensionImmutable currentResolution = primaryMonitor.queryCurrentMode().getSurfaceSize() + .getResolution(); + _settings = new DisplaySettings(currentResolution.getWidth(), currentResolution.getHeight(), + settings.getColorDepth(), settings.getFrequency(), settings.getAlphaBits(), + settings.getDepthBits(), settings.getStencilBits(), settings.getSamples(), true, + settings.isStereo(), settings.getShareContext(), settings.getRotation()); + } else { + _settings = settings; + } _canvasRenderer = canvasRenderer; _canvasRenderer._doSwap = true;// true - do swap in renderer. setAutoSwapBufferMode(false);// false - doesn't swap automatically in JOGL itself @@ -77,27 +99,78 @@ public class JoglNewtWindow implements NativeCanvas, NewtWindowContainer { /** * Applies all settings not related to OpenGL (screen resolution, screen size, etc...) * */ - private void applySettings() { + protected void applySettings() { _newtWindow.setUndecorated(_settings.isFullScreen()); - _newtWindow.setFullscreen(_settings.isFullScreen()); - // FIXME Ardor3D does not allow to change the resolution - /** - * uses the filtering relying on resolution with the size to fetch only the screen mode matching with the - * current resolution - */ if (_settings.isFullScreen()) { - final MonitorDevice monitor = _newtWindow.getMainMonitor(); - List<MonitorMode> monitorModes = monitor.getSupportedModes(); - // the resolution is provided by the user - final Dimension dimension = new Dimension(_settings.getWidth(), _settings.getHeight()); - monitorModes = MonitorModeUtil.filterByResolution(monitorModes, dimension); - monitorModes = MonitorModeUtil.getHighestAvailableBpp(monitorModes); - if (_settings.getFrequency() > 0) { - monitorModes = MonitorModeUtil.filterByRate(monitorModes, _settings.getFrequency()); - } else { - monitorModes = MonitorModeUtil.getHighestAvailableRate(monitorModes); + _newtWindow.setFullscreen(_monitorDevices); + for (final MonitorDevice monitorDevice : _monitorDevices) { + List<MonitorMode> monitorModes = monitorDevice.getSupportedModes(); + final MonitorMode currentMode = monitorDevice.getCurrentMode(); + if (monitorDevice == _monitorDevices.get(0)) { + final Dimension dimension; + // the resolution is taken into account only if it is valid + if (_settings.getWidth() > 0 && _settings.getHeight() > 0) { + dimension = new Dimension(_settings.getWidth(), _settings.getHeight()); + } else { + final DimensionImmutable currentResolution = currentMode.getSurfaceSize().getResolution(); + dimension = new Dimension(currentResolution.getWidth(), currentResolution.getHeight()); + } + monitorModes = MonitorModeUtil.filterByResolution(monitorModes, dimension); + } else { + // FIXME the display settings should store the size of the other monitors + } + // if the frequency may be valid (greater than zero), it tries to use it + final List<MonitorMode> byRateMonitorModes; + if (_settings.getFrequency() > 0) { + byRateMonitorModes = MonitorModeUtil.filterByRate(monitorModes, _settings.getFrequency()); + } else { + // if the frequency is set to zero, it tries to preserve the refresh rate + if (_settings.getFrequency() == 0) { + byRateMonitorModes = MonitorModeUtil.filterByRate(monitorModes, currentMode.getRefreshRate()); + } else { + // otherwise it picks the highest available rate + byRateMonitorModes = MonitorModeUtil.getHighestAvailableRate(monitorModes); + } + } + if (!byRateMonitorModes.isEmpty()) { + monitorModes = byRateMonitorModes; + } + final List<MonitorMode> byBppMonitorModes; + switch (_settings.getColorDepth()) { + case 16: + case 24: + case 32: { + byBppMonitorModes = MonitorModeUtil.filterByBpp(monitorModes, _settings.getColorDepth()); + break; + } + case 0: { + byBppMonitorModes = MonitorModeUtil.filterByBpp(monitorModes, currentMode.getSurfaceSize() + .getBitsPerPixel()); + break; + } + case -1: { + byBppMonitorModes = MonitorModeUtil.getHighestAvailableBpp(monitorModes); + break; + } + default: { + byBppMonitorModes = monitorModes; + } + } + if (!byBppMonitorModes.isEmpty()) { + monitorModes = byBppMonitorModes; + } + if (_settings.getRotation() == 0 || _settings.getRotation() == 90 || _settings.getRotation() == 180 + || _settings.getRotation() == 270) { + final List<MonitorMode> rotatedMonitorModes = MonitorModeUtil.filterByRotation(monitorModes, + _settings.getRotation()); + if (!rotatedMonitorModes.isEmpty()) { + monitorModes = rotatedMonitorModes; + } + } + monitorDevice.setCurrentMode(monitorModes.get(0)); } - monitor.setCurrentMode(monitorModes.get(0)); + } else { + _newtWindow.setFullscreen(false); } } @@ -227,7 +300,13 @@ public class JoglNewtWindow implements NativeCanvas, NewtWindowContainer { } // Set the size very early to prevent the default one from being used (typically when exiting full screen mode) - setSize(_settings.getWidth(), _settings.getHeight()); + if (_settings.getWidth() == 0 || _settings.getHeight() == 0) { + final DimensionImmutable currentResolution = _monitorDevices.get(0).queryCurrentMode().getSurfaceSize() + .getResolution(); + setSize(currentResolution.getWidth(), currentResolution.getHeight()); + } else { + setSize(_settings.getWidth(), _settings.getHeight()); + } // Make the window visible to realize the OpenGL surface. setVisible(true); if (_newtWindow.isRealized()) { @@ -331,6 +410,64 @@ public class JoglNewtWindow implements NativeCanvas, NewtWindowContainer { _newtWindow.setTopLevelPosition(locX, locY); } + public boolean isResizable() { + return _newtWindow.isResizable(); + } + + public void setResizable(final boolean resizable) { + _newtWindow.setResizable(resizable); + } + + public boolean isDecorated() { + return !_newtWindow.isUndecorated(); + } + + public void setDecorated(final boolean decorated) { + _newtWindow.setUndecorated(!decorated); + } + + public boolean isSticky() { + return _newtWindow.isSticky(); + } + + public void setSticky(final boolean sticky) { + _newtWindow.setSticky(sticky); + } + + public boolean isAlwaysOnTop() { + return _newtWindow.isAlwaysOnTop(); + } + + public void setAlwaysOnTop(final boolean alwaysOnTop) { + _newtWindow.setAlwaysOnTop(alwaysOnTop); + } + + public boolean isAlwaysOnBottom() { + return _newtWindow.isAlwaysOnBottom(); + } + + public void setAlwaysOnBottom(final boolean alwaysOnBottom) { + _newtWindow.setAlwaysOnBottom(alwaysOnBottom); + } + + /** + * Returns a list of monitor devices used in fullscreen mode, ignored in windowed mode + * + * @return list of monitor devices used in fullscreen mode, ignored in windowed mode + */ + public List<MonitorDevice> getMonitorDevices() { + return Collections.unmodifiableList(_monitorDevices); + } + + public void setMonitorDevices(final List<MonitorDevice> monitorDevices) { + if (_monitorDevices == null || _monitorDevices.isEmpty()) { + throw new IllegalArgumentException("The list of monitor devices cannot be null or empty"); + } + + _monitorDevices = monitorDevices; + // FIXME recompute the width and the height of the settings, apply the settings anew + } + @Override public GLWindow getNewtWindow() { return _newtWindow; |