diff --git a/common.gradle b/common.gradle index c225588c4..237ee5e7f 100644 --- a/common.gradle +++ b/common.gradle @@ -16,9 +16,6 @@ repositories { maven { url "http://nifty-gui.sourceforge.net/nifty-maven-repo" } - maven { - url "https://oss.sonatype.org/content/repositories/snapshots" - } } configurations { diff --git a/jme3-desktop/src/main/java/com/jme3/system/NativeLibraryLoader.java b/jme3-desktop/src/main/java/com/jme3/system/NativeLibraryLoader.java index 6e83e0e6b..53898883c 100644 --- a/jme3-desktop/src/main/java/com/jme3/system/NativeLibraryLoader.java +++ b/jme3-desktop/src/main/java/com/jme3/system/NativeLibraryLoader.java @@ -124,6 +124,42 @@ public final class NativeLibraryLoader { } static { + // LWJGL + registerNativeLibrary("lwjgl", Platform.Windows32, "native/windows/lwjgl.dll"); + registerNativeLibrary("lwjgl", Platform.Windows64, "native/windows/lwjgl64.dll"); + registerNativeLibrary("lwjgl", Platform.Linux32, "native/linux/liblwjgl.so"); + registerNativeLibrary("lwjgl", Platform.Linux64, "native/linux/liblwjgl64.so"); + registerNativeLibrary("lwjgl", Platform.MacOSX32, "native/macosx/liblwjgl.dylib"); + registerNativeLibrary("lwjgl", Platform.MacOSX64, "native/macosx/liblwjgl.dylib"); + + // OpenAL + // For OSX: Need to add lib prefix when extracting + registerNativeLibrary("openal", Platform.Windows32, "native/windows/OpenAL32.dll"); + registerNativeLibrary("openal", Platform.Windows64, "native/windows/OpenAL64.dll"); + registerNativeLibrary("openal", Platform.Linux32, "native/linux/libopenal.so"); + registerNativeLibrary("openal", Platform.Linux64, "native/linux/libopenal64.so"); + registerNativeLibrary("openal", Platform.MacOSX32, "native/macosx/openal.dylib", "libopenal.dylib"); + registerNativeLibrary("openal", Platform.MacOSX64, "native/macosx/openal.dylib", "libopenal.dylib"); + + // LWJGL 3.x + registerNativeLibrary("lwjgl3", Platform.Windows32, "native/windows/lwjgl32.dll"); + registerNativeLibrary("lwjgl3", Platform.Windows64, "native/windows/lwjgl.dll"); + registerNativeLibrary("lwjgl3", Platform.Linux32, "native/linux/liblwjgl32.so"); + registerNativeLibrary("lwjgl3", Platform.Linux64, "native/linux/liblwjgl.so"); + registerNativeLibrary("lwjgl3", Platform.MacOSX32, "native/macosx/liblwjgl.dylib"); + registerNativeLibrary("lwjgl3", Platform.MacOSX64, "native/macosx/liblwjgl.dylib"); + registerNativeLibrary("lwjgl3", Platform.Windows32, "native/windows/jemalloc32.dll"); + registerNativeLibrary("lwjgl3", Platform.Windows64, "native/windows/jemalloc.dll"); + + // OpenAL for LWJGL 3.x + // For OSX: Need to add lib prefix when extracting + registerNativeLibrary("openal-lwjgl3", Platform.Windows32, "native/windows/OpenAL32.dll"); + registerNativeLibrary("openal-lwjgl3", Platform.Windows64, "native/windows/OpenAL.dll"); + registerNativeLibrary("openal-lwjgl3", Platform.Linux32, "native/linux/libopenal32.so"); + registerNativeLibrary("openal-lwjgl3", Platform.Linux64, "native/linux/libopenal.so"); + registerNativeLibrary("openal-lwjgl3", Platform.MacOSX32, "native/macosx/openal.dylib", "libopenal.dylib"); + registerNativeLibrary("openal-lwjgl3", Platform.MacOSX64, "native/macosx/openal.dylib", "libopenal.dylib"); + // BulletJme registerNativeLibrary("bulletjme", Platform.Windows32, "native/windows/x86/bulletjme.dll"); registerNativeLibrary("bulletjme", Platform.Windows64, "native/windows/x86_64/bulletjme.dll"); diff --git a/jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglAbstractDisplay.java b/jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglAbstractDisplay.java index 415084788..802b12a0f 100644 --- a/jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglAbstractDisplay.java +++ b/jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglAbstractDisplay.java @@ -206,7 +206,6 @@ public abstract class LwjglAbstractDisplay extends LwjglContext implements Runna + "Must set with JmeContext.setSystemListner()."); } - registerNatives(); loadNatives(); logger.log(Level.FINE, "Using LWJGL {0}", Sys.getVersion()); if (!initInThread()) { diff --git a/jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglContext.java b/jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglContext.java index 70885c39b..ee12d1fea 100644 --- a/jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglContext.java +++ b/jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglContext.java @@ -162,26 +162,7 @@ public abstract class LwjglContext implements JmeContext { } } } - - protected void registerNatives() { - // LWJGL - NativeLibraryLoader.registerNativeLibrary("lwjgl", Platform.Windows32, "native/windows/lwjgl.dll"); - NativeLibraryLoader.registerNativeLibrary("lwjgl", Platform.Windows64, "native/windows/lwjgl64.dll"); - NativeLibraryLoader.registerNativeLibrary("lwjgl", Platform.Linux32, "native/linux/liblwjgl.so"); - NativeLibraryLoader.registerNativeLibrary("lwjgl", Platform.Linux64, "native/linux/liblwjgl64.so"); - NativeLibraryLoader.registerNativeLibrary("lwjgl", Platform.MacOSX32, "native/macosx/liblwjgl.dylib"); - NativeLibraryLoader.registerNativeLibrary("lwjgl", Platform.MacOSX64, "native/macosx/liblwjgl.dylib"); - - // For OSX: Need to add lib prefix when extracting - NativeLibraryLoader.registerNativeLibrary("openal", Platform.Windows32, "native/windows/OpenAL32.dll"); - NativeLibraryLoader.registerNativeLibrary("openal", Platform.Windows64, "native/windows/OpenAL64.dll"); - NativeLibraryLoader.registerNativeLibrary("openal", Platform.Linux32, "native/linux/libopenal.so"); - NativeLibraryLoader.registerNativeLibrary("openal", Platform.Linux64, "native/linux/libopenal64.so"); - NativeLibraryLoader.registerNativeLibrary("openal", Platform.MacOSX32, "native/macosx/openal.dylib", "libopenal.dylib"); - NativeLibraryLoader.registerNativeLibrary("openal", Platform.MacOSX64, "native/macosx/openal.dylib", "libopenal.dylib"); - } - - protected void loadNatives() { + protected void loadNatives() { if (JmeSystem.isLowPermissions()) { return; } diff --git a/jme3-lwjgl3/build.gradle b/jme3-lwjgl3/build.gradle index c9b43e0de..3c7e4e646 100644 --- a/jme3-lwjgl3/build.gradle +++ b/jme3-lwjgl3/build.gradle @@ -2,6 +2,12 @@ if (!hasProperty('mainClass')) { ext.mainClass = '' } +repositories { + maven { + url "https://oss.sonatype.org/content/repositories/snapshots" + } +} + dependencies { compile project(':jme3-core') compile project(':jme3-desktop') diff --git a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglCanvas.java b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglCanvas.java deleted file mode 100644 index 1f1ef2ab5..000000000 --- a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglCanvas.java +++ /dev/null @@ -1,369 +0,0 @@ -/* - * Copyright (c) 2009-2012 jMonkeyEngine - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of 'jMonkeyEngine' nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package com.jme3.system.lwjgl; - -import com.jme3.system.AppSettings; -import com.jme3.system.JmeCanvasContext; - -import javax.swing.*; -import java.awt.*; -import java.util.logging.Level; -import java.util.logging.Logger; - -import static org.lwjgl.glfw.GLFW.glfwDestroyWindow; - -public class LwjglCanvas extends LwjglWindow implements JmeCanvasContext { - - protected static final int TASK_NOTHING = 0, - TASK_DESTROY_DISPLAY = 1, - TASK_CREATE_DISPLAY = 2, - TASK_COMPLETE = 3; - -// protected static final boolean USE_SHARED_CONTEXT = -// Boolean.parseBoolean(System.getProperty("jme3.canvas.sharedctx", "true")); - - protected static final boolean USE_SHARED_CONTEXT = false; - - private static final Logger logger = Logger.getLogger(LwjglCanvas.class.getName()); - private Canvas canvas; - private int width; - private int height; - - private final Object taskLock = new Object(); - private int desiredTask = TASK_NOTHING; - - private Thread renderThread; - private boolean runningFirstTime = true; - private boolean mouseWasGrabbed = false; - - private boolean mouseWasCreated = false; - private boolean keyboardWasCreated = false; - - private long window; - - private class GLCanvas extends Canvas { - @Override - public void addNotify(){ - super.addNotify(); - - if (renderThread != null && renderThread.getState() == Thread.State.TERMINATED) { - return; // already destroyed. - } - - if (renderThread == null){ - logger.log(Level.FINE, "EDT: Creating OGL thread."); - - // Also set some settings on the canvas here. - // So we don't do it outside the AWT thread. - canvas.setFocusable(true); - canvas.setIgnoreRepaint(true); - - renderThread = new Thread(LwjglCanvas.this, THREAD_NAME); - renderThread.start(); - }else if (needClose.get()){ - return; - } - - logger.log(Level.FINE, "EDT: Telling OGL to create display .."); - synchronized (taskLock){ - desiredTask = TASK_CREATE_DISPLAY; -// while (desiredTask != TASK_COMPLETE){ -// try { -// taskLock.wait(); -// } catch (InterruptedException ex) { -// return; -// } -// } -// desiredTask = TASK_NOTHING; - } -// logger.log(Level.FINE, "EDT: OGL has created the display"); - } - - @Override - public void removeNotify(){ - if (needClose.get()){ - logger.log(Level.FINE, "EDT: Application is stopped. Not restoring canvas."); - super.removeNotify(); - return; - } - - // We must tell GL context to shutdown and wait for it to - // shutdown, otherwise, issues will occur. - logger.log(Level.FINE, "EDT: Telling OGL to destroy display .."); - synchronized (taskLock){ - desiredTask = TASK_DESTROY_DISPLAY; - while (desiredTask != TASK_COMPLETE){ - try { - taskLock.wait(); - } catch (InterruptedException ex){ - super.removeNotify(); - return; - } - } - desiredTask = TASK_NOTHING; - } - - logger.log(Level.FINE, "EDT: Acknowledged receipt of canvas death"); - // GL context is dead at this point - - super.removeNotify(); - } - } - - public LwjglCanvas(){ - super(Type.Canvas); - canvas = new GLCanvas(); - } - - public void create(boolean waitFor){ - if (renderThread == null){ - logger.log(Level.FINE, "MAIN: Creating OGL thread."); - - renderThread = new Thread(LwjglCanvas.this, THREAD_NAME); - renderThread.start(); - } - // do not do anything. - // superclass's create() will be called at initInThread() - if (waitFor) { - waitFor(true); - } - } - - public Canvas getCanvas(){ - return canvas; - } - - @Override - protected void runLoop(){ - if (desiredTask != TASK_NOTHING){ - synchronized (taskLock){ - switch (desiredTask){ - case TASK_CREATE_DISPLAY: - logger.log(Level.FINE, "OGL: Creating display .."); - restoreCanvas(); - listener.gainFocus(); - desiredTask = TASK_NOTHING; - break; - case TASK_DESTROY_DISPLAY: - logger.log(Level.FINE, "OGL: Destroying display .."); - listener.loseFocus(); - pauseCanvas(); - break; - } - desiredTask = TASK_COMPLETE; - taskLock.notifyAll(); - } - } - - if (renderable.get()){ - 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); - } - } - } - - super.runLoop(); - } - - private void pauseCanvas(){ - if (mouseInput != null) { - mouseInput.setCursorVisible(true); - mouseWasCreated = true; - } - -/* - if (Mouse.isCreated()){ - if (Mouse.isGrabbed()){ - Mouse.setGrabbed(false); - mouseWasGrabbed = true; - } - mouseWasCreated = true; - Mouse.destroy(); - } - if (Keyboard.isCreated()){ - keyboardWasCreated = true; - Keyboard.destroy(); - } -*/ - - renderable.set(false); - destroyContext(); - } - - /** - * Called to restore the canvas. - */ - private void restoreCanvas(){ - logger.log(Level.FINE, "OGL: Waiting for canvas to become displayable.."); - while (!canvas.isDisplayable()){ - try { - Thread.sleep(10); - } catch (InterruptedException ex) { - logger.log(Level.SEVERE, "OGL: Interrupted! ", ex); - } - } - - logger.log(Level.FINE, "OGL: Creating display context .."); - - // Set renderable to true, since canvas is now displayable. - renderable.set(true); - createContext(settings); - - logger.log(Level.FINE, "OGL: Display is active!"); - - try { - if (mouseWasCreated){ -// Mouse.create(); -// if (mouseWasGrabbed){ -// Mouse.setGrabbed(true); -// mouseWasGrabbed = false; -// } - } - if (keyboardWasCreated){ -// Keyboard.create(); -// keyboardWasCreated = false; - } - } catch (Exception ex){ - logger.log(Level.SEVERE, "Encountered exception when restoring input", ex); - } - - SwingUtilities.invokeLater(new Runnable(){ - public void run(){ - canvas.requestFocus(); - } - }); - } - -/* - */ -/** - * Makes sure the pbuffer is available and ready for use - *//* - - protected void makePbufferAvailable() throws LWJGLException{ - if (pbuffer != null && pbuffer.isBufferLost()){ - logger.log(Level.WARNING, "PBuffer was lost!"); - pbuffer.destroy(); - pbuffer = null; - } - - if (pbuffer == null) { - pbuffer = new Pbuffer(1, 1, acquirePixelFormat(true), null); - pbuffer.makeCurrent(); - logger.log(Level.FINE, "OGL: Pbuffer has been created"); - - // Any created objects are no longer valid - if (!runningFirstTime){ - renderer.resetGLObjects(); - } - } - - pbuffer.makeCurrent(); - if (!pbuffer.isCurrent()){ - throw new LWJGLException("Pbuffer cannot be made current"); - } - } - - protected void destroyPbuffer(){ - if (pbuffer != null){ - if (!pbuffer.isBufferLost()){ - pbuffer.destroy(); - } - pbuffer = null; - } - } -*/ - - /** - * This is called: - * 1) When the context thread ends - * 2) Any time the canvas becomes non-displayable - */ - protected void destroyContext(){ - // invalidate the state so renderer can resume operation - if (!USE_SHARED_CONTEXT){ - renderer.cleanup(); - } - - if (window != 0) { - glfwDestroyWindow(window); - } - - // TODO: Destroy input - - - // The canvas is no longer visible, - // but the context thread is still running. - if (!needClose.get()){ - renderer.invalidateState(); - } - } - - /** - * This is called: - * 1) When the context thread starts - * 2) Any time the canvas becomes displayable again. - */ - @Override - protected void createContext(final AppSettings settings) { - // In case canvas is not visible, we still take framerate - // from settings to prevent "100% CPU usage" - allowSwapBuffers = settings.isSwapBuffers(); - - if (renderable.get()){ - if (!runningFirstTime){ - // because the display is a different opengl context - // must reset the context state. - if (!USE_SHARED_CONTEXT){ - renderer.cleanup(); - } - } - - super.createContext(settings); - } - - // At this point, the OpenGL context is active. - if (runningFirstTime) { - // THIS is the part that creates the renderer. - // It must always be called, now that we have the pbuffer workaround. - initContextFirstTime(); - runningFirstTime = false; - } - } -} diff --git a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglContext.java b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglContext.java index 86b6a294a..7f62a447e 100644 --- a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglContext.java +++ b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglContext.java @@ -98,41 +98,20 @@ public abstract class LwjglContext implements JmeContext { return Integer.MAX_VALUE; } - protected void registerNatives() { - // LWJGL - NativeLibraryLoader.registerNativeLibrary("lwjgl", Platform.Windows32, "native/windows/lwjgl32.dll"); - NativeLibraryLoader.registerNativeLibrary("lwjgl", Platform.Windows64, "native/windows/lwjgl.dll"); - NativeLibraryLoader.registerNativeLibrary("lwjgl", Platform.Linux32, "native/linux/liblwjgl32.so"); - NativeLibraryLoader.registerNativeLibrary("lwjgl", Platform.Linux64, "native/linux/liblwjgl.so"); - NativeLibraryLoader.registerNativeLibrary("lwjgl", Platform.MacOSX32, "native/macosx/liblwjgl.dylib"); - NativeLibraryLoader.registerNativeLibrary("lwjgl", Platform.MacOSX64, "native/macosx/liblwjgl.dylib"); - NativeLibraryLoader.registerNativeLibrary("lwjgl", Platform.Windows32, "native/windows/jemalloc32.dll"); - NativeLibraryLoader.registerNativeLibrary("lwjgl", Platform.Windows64, "native/windows/jemalloc.dll"); - - // OpenAL - // For OSX: Need to add lib prefix when extracting - NativeLibraryLoader.registerNativeLibrary("openal", Platform.Windows32, "native/windows/OpenAL32.dll"); - NativeLibraryLoader.registerNativeLibrary("openal", Platform.Windows64, "native/windows/OpenAL.dll"); - NativeLibraryLoader.registerNativeLibrary("openal", Platform.Linux32, "native/linux/libopenal32.so"); - NativeLibraryLoader.registerNativeLibrary("openal", Platform.Linux64, "native/linux/libopenal.so"); - NativeLibraryLoader.registerNativeLibrary("openal", Platform.MacOSX32, "native/macosx/openal.dylib", "libopenal.dylib"); - NativeLibraryLoader.registerNativeLibrary("openal", Platform.MacOSX64, "native/macosx/openal.dylib", "libopenal.dylib"); - } - protected void loadNatives() { if (JmeSystem.isLowPermissions()) { return; } if ("LWJGL".equals(settings.getAudioRenderer())) { - NativeLibraryLoader.loadNativeLibrary("openal", true); + NativeLibraryLoader.loadNativeLibrary("openal-lwjgl3", true); } if (NativeLibraryLoader.isUsingNativeBullet()) { NativeLibraryLoader.loadNativeLibrary("bulletjme", true); } - NativeLibraryLoader.loadNativeLibrary("lwjgl", true); + NativeLibraryLoader.loadNativeLibrary("lwjgl3", true); } protected int getNumSamplesToUse() { diff --git a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglSmoothingTimer.java b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglSmoothingTimer.java deleted file mode 100644 index a7960a261..000000000 --- a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglSmoothingTimer.java +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Copyright (c) 2009-2012 jMonkeyEngine - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of 'jMonkeyEngine' nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package com.jme3.system.lwjgl; - -import com.jme3.math.FastMath; -import com.jme3.system.Timer; -import org.lwjgl.glfw.GLFW; - -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * Timer handles the system's time related functionality. This - * allows the calculation of the framerate. To keep the framerate calculation - * accurate, a call to update each frame is required. Timer is a - * singleton object and must be created via the getTimer method. - * - * @author Mark Powell - * @version $Id: LWJGLTimer.java,v 1.21 2007/09/22 16:46:35 irrisor Exp $ - */ -public class LwjglSmoothingTimer extends LwjglTimer { - private static final Logger logger = Logger.getLogger(LwjglSmoothingTimer.class - .getName()); - - private long lastFrameDiff; - - //frame rate parameters. - private long oldTime; - - private float lastTPF, lastFPS; - - public static int TIMER_SMOOTHNESS = 32; - - private long[] tpf; - - private int smoothIndex; - - private final static long LWJGL_TIMER_RES = 1; - private final static float INV_LWJGL_TIMER_RES = ( 1f / LWJGL_TIMER_RES ); - private static float invTimerRezSmooth; - - public final static long LWJGL_TIME_TO_NANOS = (1000000000 / LWJGL_TIMER_RES); - - private long startTime; - - private boolean allSmooth = false; - - /** - * Constructor builds a Timer object. All values will be - * initialized to it's default values. - */ - public LwjglSmoothingTimer() { - reset(); - - //print timer resolution info - logger.log(Level.FINE, "Timer resolution: {0} ticks per second", LWJGL_TIMER_RES); - } - - public void reset() { - lastFrameDiff = 0; - lastFPS = 0; - lastTPF = 0; - - // init to -1 to indicate this is a new timer. - oldTime = -1; - //reset time - startTime = (long) (GLFW.glfwGetTime() * LWJGL_TIME_TO_NANOS); - - tpf = new long[TIMER_SMOOTHNESS]; - smoothIndex = TIMER_SMOOTHNESS - 1; - invTimerRezSmooth = ( 1f / (LWJGL_TIMER_RES * TIMER_SMOOTHNESS)); - - // set tpf... -1 values will not be used for calculating the average in update() - for ( int i = tpf.length; --i >= 0; ) { - tpf[i] = -1; - } - } - - /** - * @see Timer#getResolution() - */ - public long getResolution() { - return LWJGL_TIMER_RES; - } - - /** - * getFrameRate returns the current frame rate since the last - * call to update. - * - * @return the current frame rate. - */ - public float getFrameRate() { - return lastFPS; - } - - public float getTimePerFrame() { - return lastTPF; - } - - /** - * update recalulates the frame rate based on the previous - * call to update. It is assumed that update is called each frame. - */ - public void update() { - long newTime = (long) (GLFW.glfwGetTime() * LWJGL_TIME_TO_NANOS); - long oldTime = this.oldTime; - this.oldTime = newTime; - if ( oldTime == -1 ) { - // For the first frame use 60 fps. This value will not be counted in further averages. - // This is done so initialization code between creating the timer and the first - // frame is not counted as a single frame on it's own. - lastTPF = 1 / 60f; - lastFPS = 1f / lastTPF; - return; - } - - long frameDiff = newTime - oldTime; - long lastFrameDiff = this.lastFrameDiff; - if ( lastFrameDiff > 0 && frameDiff > lastFrameDiff *100 ) { - frameDiff = lastFrameDiff *100; - } - this.lastFrameDiff = frameDiff; - tpf[smoothIndex] = frameDiff; - smoothIndex--; - if ( smoothIndex < 0 ) { - smoothIndex = tpf.length - 1; - } - - lastTPF = 0.0f; - if (!allSmooth) { - int smoothCount = 0; - for ( int i = tpf.length; --i >= 0; ) { - if ( tpf[i] != -1 ) { - lastTPF += tpf[i]; - smoothCount++; - } - } - if (smoothCount == tpf.length) - allSmooth = true; - lastTPF *= ( INV_LWJGL_TIMER_RES / smoothCount ); - } else { - for ( int i = tpf.length; --i >= 0; ) { - if ( tpf[i] != -1 ) { - lastTPF += tpf[i]; - } - } - lastTPF *= invTimerRezSmooth; - } - if ( lastTPF < FastMath.FLT_EPSILON ) { - lastTPF = FastMath.FLT_EPSILON; - } - - lastFPS = 1f / lastTPF; - } - - /** - * toString returns the string representation of this timer - * in the format:
- *
- * jme.utility.Timer@1db699b
- * Time: {LONG}
- * FPS: {LONG}
- * - * @return the string representation of this object. - */ - @Override - public String toString() { - String string = super.toString(); - string += "\nTime: " + oldTime; - string += "\nFPS: " + getFrameRate(); - return string; - } -} \ No newline at end of file diff --git a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglTimer.java b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglTimer.java deleted file mode 100644 index c4a0e5025..000000000 --- a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglTimer.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright (c) 2009-2012 jMonkeyEngine - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * * Neither the name of 'jMonkeyEngine' nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package com.jme3.system.lwjgl; - -import com.jme3.system.Timer; -import org.lwjgl.glfw.GLFW; - -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * Timer handles the system's time related functionality. This - * allows the calculation of the framerate. To keep the framerate calculation - * accurate, a call to update each frame is required. Timer is a - * singleton object and must be created via the getTimer method. - * - * @author Mark Powell - * @version $Id: LWJGLTimer.java,v 1.21 2007/09/22 16:46:35 irrisor Exp $ - */ -public class LwjglTimer extends Timer { - - private static final Logger logger = Logger.getLogger(LwjglTimer.class.getName()); - - //frame rate parameters. - private long oldTime; - private long startTime; - - private float lastTPF, lastFPS; - - private final static long LWJGL_TIMER_RES = 1; - private final static float INV_LWJGL_TIMER_RES = ( 1f / LWJGL_TIMER_RES ); - public final static long LWJGL_TIME_TO_NANOS = (1000000000 / LWJGL_TIMER_RES); - - /** - * Constructor builds a Timer object. All values will be - * initialized to it's default values. - */ - public LwjglTimer() { - reset(); - logger.log(Level.FINE, "Timer resolution: {0} ticks per second", LWJGL_TIMER_RES); - } - - public void reset() { - startTime = (long) (GLFW.glfwGetTime() * LWJGL_TIME_TO_NANOS); - oldTime = getTime(); - } - - @Override - public float getTimeInSeconds() { - return getTime() * INV_LWJGL_TIMER_RES; - } - - /** - * @see Timer#getTime() - */ - public long getTime() { - return ((long) (GLFW.glfwGetTime() * LWJGL_TIME_TO_NANOS) - startTime); - } - - /** - * @see Timer#getResolution() - */ - public long getResolution() { - return LWJGL_TIMER_RES; - } - - /** - * getFrameRate returns the current frame rate since the last - * call to update. - * - * @return the current frame rate. - */ - public float getFrameRate() { - return lastFPS; - } - - public float getTimePerFrame() { - return lastTPF; - } - - /** - * update recalulates the frame rate based on the previous - * call to update. It is assumed that update is called each frame. - */ - public void update() { - long curTime = getTime(); - lastTPF = (curTime - oldTime) * (1.0f / LWJGL_TIMER_RES); - lastFPS = 1.0f / lastTPF; - oldTime = curTime; - } - - /** - * toString returns the string representation of this timer - * in the format:
- *
- * jme.utility.Timer@1db699b
- * Time: {LONG}
- * FPS: {LONG}
- * - * @return the string representation of this object. - */ - @Override - public String toString() { - String string = super.toString(); - string += "\nTime: " + oldTime; - string += "\nFPS: " + getFrameRate(); - return string; - } -} \ No newline at end of file diff --git a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglWindow.java b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglWindow.java index c5cb35e03..2f00eb700 100644 --- a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglWindow.java +++ b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglWindow.java @@ -42,6 +42,7 @@ import com.jme3.input.lwjgl.GlfwMouseInput; import com.jme3.system.AppSettings; import com.jme3.system.JmeContext; import com.jme3.system.JmeSystem; +import com.jme3.system.NanoTimer; import org.lwjgl.Sys; import org.lwjgl.glfw.*; @@ -73,6 +74,8 @@ public abstract class LwjglWindow extends LwjglContext implements Runnable { protected boolean allowSwapBuffers = false; private long window = -1; private final JmeContext.Type type; + private int frameRateLimit = -1; + private double frameSleepTime; private GLFWErrorCallback errorCallback; private GLFWWindowSizeCallback windowSizeCallback; @@ -160,16 +163,7 @@ public abstract class LwjglWindow extends LwjglContext implements Runnable { glfwWindowHint(GLFW_STENCIL_BITS, settings.getStencilBits()); glfwWindowHint(GLFW_SAMPLES, settings.getSamples()); glfwWindowHint(GLFW_STEREO, settings.useStereo3D() ? GL_TRUE : GL_FALSE); - - int frameRateCap = settings.getFrameRate(); - - if (!autoFlush) { - frameRateCap = 20; - } - - if (frameRateCap > 0) { - glfwWindowHint(GLFW_REFRESH_RATE, frameRateCap); - } + glfwWindowHint(GLFW_REFRESH_RATE, settings.getFrequency()); // Not sure how else to support bits per pixel if (settings.getBitsPerPixel() == 24) { @@ -289,7 +283,7 @@ public abstract class LwjglWindow extends LwjglContext implements Runnable { }); } - timer = new LwjglTimer(); + timer = new NanoTimer(); // For canvas, this will create a pbuffer, // allowing us to query information. @@ -303,7 +297,6 @@ public abstract class LwjglWindow extends LwjglContext implements Runnable { } catch (Exception ex) { try { if (window != -1) { - //glfwSetWindowShouldClose(window, GL_TRUE); glfwDestroyWindow(window); } } catch (Exception ex2) { @@ -360,11 +353,41 @@ public abstract class LwjglWindow extends LwjglContext implements Runnable { if (renderer != null) { renderer.postFrame(); } + + if (autoFlush) { + if (frameRateLimit != getSettings().getFrameRate()) { + setFrameRateLimit(getSettings().getFrameRate()); + } + } else if (frameRateLimit != 20) { + setFrameRateLimit(20); + } + + // If software frame rate limiting has been asked for, lets calculate sleep time based on a base value calculated + // from 1000 / frameRateLimit in milliseconds subtracting the time it has taken to render last frame. + // This gives an approximate limit within 3 fps of the given frame rate limit. + if (frameRateLimit > 0) { + final double sleep = frameSleepTime - (timer.getTimePerFrame() / 1000.0); + final long sleepMillis = (long) sleep; + final int additionalNanos = (int) ((sleep - sleepMillis) * 1000000.0); + + if (sleepMillis >= 0 && additionalNanos >= 0) { + try { + Thread.sleep(sleepMillis, additionalNanos); + } catch (InterruptedException ignored) { + } + } + } + } + + private void setFrameRateLimit(int frameRateLimit) { + this.frameRateLimit = frameRateLimit; + frameSleepTime = 1000.0 / this.frameRateLimit; } /** * De-initialize in the OpenGL thread. */ + protected void deinitInThread() { destroyContext(); @@ -379,7 +402,6 @@ public abstract class LwjglWindow extends LwjglContext implements Runnable { + "Must set with JmeContext.setSystemListener()."); } - registerNatives(); loadNatives(); LOGGER.log(Level.FINE, "Using LWJGL {0}", Sys.getVersion()); @@ -445,6 +467,9 @@ public abstract class LwjglWindow extends LwjglContext implements Runnable { return window; } + + // TODO: Implement support for window icon when GLFW supports it. + private ByteBuffer[] imagesToByteBuffers(Object[] images) { ByteBuffer[] out = new ByteBuffer[images.length]; for (int i = 0; i < images.length; i++) {