Pārlūkot izejas kodu

refactored and upgraed lwjgl3 module.

javasabr 7 gadi atpakaļ
vecāks
revīzija
555a348692

+ 1 - 1
jme3-lwjgl3/build.gradle

@@ -2,7 +2,7 @@ if (!hasProperty('mainClass')) {
     ext.mainClass = ''
 }
 
-def lwjglVersion = '3.1.2'
+def lwjglVersion = '3.1.5'
 
 sourceCompatibility = '1.8'
 

+ 41 - 21
jme3-lwjgl3/src/main/java/com/jme3/audio/lwjgl/LwjglAL.java

@@ -31,8 +31,6 @@
  */package com.jme3.audio.lwjgl;
 
 import com.jme3.audio.openal.AL;
-import com.jme3.system.NativeLibraryLoader;
-import com.jme3.system.Platform;
 import org.lwjgl.openal.AL10;
 import org.lwjgl.openal.AL11;
 
@@ -40,101 +38,123 @@ import java.nio.ByteBuffer;
 import java.nio.FloatBuffer;
 import java.nio.IntBuffer;
 
+/**
+ * The LWJGL implementation of {@link AL}.
+ */
 public final class LwjglAL implements AL {
 
     public LwjglAL() {
     }
 
-    public String alGetString(int parameter) {
+    @Override
+    public String alGetString(final int parameter) {
         return AL10.alGetString(parameter);
     }
 
+    @Override
     public int alGenSources() {
         return AL10.alGenSources();
     }
 
+    @Override
     public int alGetError() {
         return AL10.alGetError();
     }
 
-    public void alDeleteSources(int numSources, IntBuffer sources) {
+    @Override
+    public void alDeleteSources(final int numSources, final IntBuffer sources) {
         if (sources.position() != 0) throw new AssertionError();
         if (sources.limit() != numSources) throw new AssertionError();
         AL10.alDeleteSources(sources);
     }
 
-    public void alGenBuffers(int numBuffers, IntBuffer buffers) {
+    @Override
+    public void alGenBuffers(final int numBuffers, final IntBuffer buffers) {
         if (buffers.position() != 0) throw new AssertionError();
         if (buffers.limit() != numBuffers) throw new AssertionError();
         AL10.alGenBuffers(buffers);
     }
 
-    public void alDeleteBuffers(int numBuffers, IntBuffer buffers) {
+    @Override
+    public void alDeleteBuffers(final int numBuffers, final IntBuffer buffers) {
         if (buffers.position() != 0) throw new AssertionError();
         if (buffers.limit() != numBuffers) throw new AssertionError();
         AL10.alDeleteBuffers(buffers);
     }
 
-    public void alSourceStop(int source) {
+    @Override
+    public void alSourceStop(final int source) {
         AL10.alSourceStop(source);
     }
 
-    public void alSourcei(int source, int param, int value) {
+    @Override
+    public void alSourcei(final int source, final int param, final int value) {
         AL10.alSourcei(source, param, value);
     }
 
-    public void alBufferData(int buffer, int format, ByteBuffer data, int size, int frequency) {
+    @Override
+    public void alBufferData(final int buffer, final int format, final ByteBuffer data, final int size, final int frequency) {
         if (data.position() != 0) throw new AssertionError();
         if (data.limit() != size) throw new AssertionError();
         AL10.alBufferData(buffer, format, data, frequency);
     }
 
-    public void alSourcePlay(int source) {
+    @Override
+    public void alSourcePlay(final int source) {
         AL10.alSourcePlay(source);
     }
 
-    public void alSourcePause(int source) {
+    @Override
+    public void alSourcePause(final int source) {
         AL10.alSourcePause(source);
     }
 
-    public void alSourcef(int source, int param, float value) {
+    @Override
+    public void alSourcef(final int source, final int param, final float value) {
         AL10.alSourcef(source, param, value);
     }
 
-    public void alSource3f(int source, int param, float value1, float value2, float value3) {
+    @Override
+    public void alSource3f(final int source, final int param, final float value1, final float value2, final float value3) {
         AL10.alSource3f(source, param, value1, value2, value3);
     }
 
-    public int alGetSourcei(int source, int param) {
+    @Override
+    public int alGetSourcei(final int source, final int param) {
         return AL10.alGetSourcei(source, param);
     }
 
-    public void alSourceUnqueueBuffers(int source, int numBuffers, IntBuffer buffers) {
+    @Override
+    public void alSourceUnqueueBuffers(final int source, final int numBuffers, final IntBuffer buffers) {
         if (buffers.position() != 0) throw new AssertionError();
         if (buffers.limit() != numBuffers) throw new AssertionError();
         AL10.alSourceUnqueueBuffers(source, buffers);
     }
 
-    public void alSourceQueueBuffers(int source, int numBuffers, IntBuffer buffers) {
+    @Override
+    public void alSourceQueueBuffers(final int source, final int numBuffers, final IntBuffer buffers) {
         if (buffers.position() != 0) throw new AssertionError();
         if (buffers.limit() != numBuffers) throw new AssertionError();
         AL10.alSourceQueueBuffers(source, buffers);
     }
 
-    public void alListener(int param, FloatBuffer data) {
+    @Override
+    public void alListener(final int param, final FloatBuffer data) {
         AL10.alListenerfv(param, data);
     }
 
-    public void alListenerf(int param, float value) {
+    @Override
+    public void alListenerf(final int param, final float value) {
         AL10.alListenerf(param, value);
     }
 
-    public void alListener3f(int param, float value1, float value2, float value3) {
+    @Override
+    public void alListener3f(final int param, final float value1, final float value2, final float value3) {
         AL10.alListener3f(param, value1, value2, value3);
     }
 
-    public void alSource3i(int source, int param, int value1, int value2, int value3) {
+    @Override
+    public void alSource3i(final int source, final int param, final int value1, final int value2, final int value3) {
         AL11.alSource3i(source, param, value1, value2, value3);
     }
-
 }

+ 20 - 6
jme3-lwjgl3/src/main/java/com/jme3/audio/lwjgl/LwjglALC.java

@@ -31,19 +31,27 @@
  */
 package com.jme3.audio.lwjgl;
 
+import org.lwjgl.openal.*;
+
 import java.nio.ByteBuffer;
 import java.nio.IntBuffer;
-import org.lwjgl.openal.AL;
-import org.lwjgl.openal.ALC;
-import org.lwjgl.openal.ALC10;
-import org.lwjgl.openal.ALCCapabilities;
-import org.lwjgl.openal.SOFTPauseDevice;
 
+/**
+ * The LWJGL implementation of {@link com.jme3.audio.openal.ALC}.
+ */
 public class LwjglALC implements com.jme3.audio.openal.ALC {
 
+    /**
+     * The device id.
+     */
     private long device;
+
+    /**
+     * The context id.
+     */
     private long context;
 
+    @Override
     public void createALC() {
         device = ALC10.alcOpenDevice((ByteBuffer) null);
         ALCCapabilities deviceCaps = ALC.createCapabilities(device);
@@ -52,6 +60,7 @@ public class LwjglALC implements com.jme3.audio.openal.ALC {
         AL.createCapabilities(deviceCaps);
     }
 
+    @Override
     public void destroyALC() {
         if (context != 0) {
             ALC10.alcDestroyContext(context);
@@ -64,18 +73,22 @@ public class LwjglALC implements com.jme3.audio.openal.ALC {
         }
     }
 
+    @Override
     public boolean isCreated() {
         return context != 0;
     }
 
+    @Override
     public String alcGetString(final int parameter) {
         return ALC10.alcGetString(device, parameter);
     }
 
+    @Override
     public boolean alcIsExtensionPresent(final String extension) {
         return ALC10.alcIsExtensionPresent(device, extension);
     }
 
+    @Override
     public void alcGetInteger(final int param, final IntBuffer buffer, final int size) {
         if (buffer.position() != 0) {
             throw new AssertionError();
@@ -86,12 +99,13 @@ public class LwjglALC implements com.jme3.audio.openal.ALC {
         ALC10.alcGetIntegerv(device, param, buffer);
     }
 
+    @Override
     public void alcDevicePauseSOFT() {
         SOFTPauseDevice.alcDevicePauseSOFT(device);
     }
 
+    @Override
     public void alcDeviceResumeSOFT() {
         SOFTPauseDevice.alcDeviceResumeSOFT(device);
     }
-
 }

+ 25 - 12
jme3-lwjgl3/src/main/java/com/jme3/audio/lwjgl/LwjglEFX.java

@@ -36,62 +36,75 @@ import org.lwjgl.openal.EXTEfx;
 
 import java.nio.IntBuffer;
 
+/**
+ * The LWJGL implementation of {@link EFX}.
+ */
 public class LwjglEFX implements EFX {
 
-    public void alGenAuxiliaryEffectSlots(int numSlots, IntBuffer buffers) {
+    @Override
+    public void alGenAuxiliaryEffectSlots(final int numSlots, final IntBuffer buffers) {
         if (buffers.position() != 0) throw new AssertionError();
         if (buffers.limit() != numSlots) throw new AssertionError();
         EXTEfx.alGenAuxiliaryEffectSlots(buffers);
     }
 
-    public void alGenEffects(int numEffects, IntBuffer buffers) {
+    @Override
+    public void alGenEffects(final int numEffects, final IntBuffer buffers) {
         if (buffers.position() != 0) throw new AssertionError();
         if (buffers.limit() != numEffects) throw new AssertionError();
         EXTEfx.alGenEffects(buffers);
     }
 
-    public void alEffecti(int effect, int param, int value) {
+    @Override
+    public void alEffecti(final int effect, final int param, final int value) {
         EXTEfx.alEffecti(effect, param, value);
     }
 
-    public void alAuxiliaryEffectSloti(int effectSlot, int param, int value) {
+    @Override
+    public void alAuxiliaryEffectSloti(final int effectSlot, final int param, final int value) {
         EXTEfx.alAuxiliaryEffectSloti(effectSlot, param, value);
     }
 
-    public void alDeleteEffects(int numEffects, IntBuffer buffers) {
+    @Override
+    public void alDeleteEffects(final int numEffects, final IntBuffer buffers) {
         if (buffers.position() != 0) throw new AssertionError();
         if (buffers.limit() != numEffects) throw new AssertionError();
         EXTEfx.alDeleteEffects(buffers);
     }
 
-    public void alDeleteAuxiliaryEffectSlots(int numEffectSlots, IntBuffer buffers) {
+    @Override
+    public void alDeleteAuxiliaryEffectSlots(final int numEffectSlots, final IntBuffer buffers) {
         if (buffers.position() != 0) throw new AssertionError();
         if (buffers.limit() != numEffectSlots) throw new AssertionError();
         EXTEfx.alDeleteAuxiliaryEffectSlots(buffers);
     }
 
-    public void alGenFilters(int numFilters, IntBuffer buffers) {
+    @Override
+    public void alGenFilters(final int numFilters, final IntBuffer buffers) {
         if (buffers.position() != 0) throw new AssertionError();
         if (buffers.limit() != numFilters) throw new AssertionError();
         EXTEfx.alGenFilters(buffers);
     }
 
-    public void alFilteri(int filter, int param, int value) {
+    @Override
+    public void alFilteri(final int filter, final int param, final int value) {
         EXTEfx.alFilteri(filter, param, value);
     }
 
-    public void alFilterf(int filter, int param, float value) {
+    @Override
+    public void alFilterf(final int filter, final int param, final float value) {
         EXTEfx.alFilterf(filter, param, value);
     }
 
-    public void alDeleteFilters(int numFilters, IntBuffer buffers) {
+    @Override
+    public void alDeleteFilters(final int numFilters, final IntBuffer buffers) {
         if (buffers.position() != 0) throw new AssertionError();
         if (buffers.limit() != numFilters) throw new AssertionError();
         EXTEfx.alDeleteFilters(buffers);
     }
 
-    public void alEffectf(int effect, int param, float value) {
+    @Override
+    public void alEffectf(final int effect, final int param, final float value) {
         EXTEfx.alEffectf(effect, param, value);
     }
-    
 }

+ 17 - 9
jme3-lwjgl3/src/main/java/com/jme3/input/lwjgl/GlfwJoystickInput.java

@@ -31,10 +31,10 @@
  */
 package com.jme3.input.lwjgl;
 
+import static org.lwjgl.glfw.GLFW.*;
 import com.jme3.input.*;
 import com.jme3.input.event.JoyAxisEvent;
 import com.jme3.input.event.JoyButtonEvent;
-import org.lwjgl.opengl.GL11;
 
 import java.nio.ByteBuffer;
 import java.nio.FloatBuffer;
@@ -42,9 +42,9 @@ import java.util.HashMap;
 import java.util.Map;
 import java.util.logging.Logger;
 
-import static org.lwjgl.glfw.GLFW.*;
-
 /**
+ * The LWJGL implementation of {@link JoyInput}.
+ *
  * @author Daniel Johansson (dannyjo)
  * @since 3.1
  */
@@ -52,11 +52,13 @@ public class GlfwJoystickInput implements JoyInput {
 
     private static final Logger LOGGER = Logger.getLogger(InputManager.class.getName());
 
-    private boolean initialized = false;
     private RawInputListener listener;
-    private Map<Integer, GlfwJoystick> joysticks = new HashMap<Integer, GlfwJoystick>();
+    private Map<Integer, GlfwJoystick> joysticks = new HashMap<>();
+
+    private boolean initialized = false;
 
-    public void setJoyRumble(int joyId, float amount) {
+    @Override
+    public void setJoyRumble(final int joyId, final float amount) {
         if (joyId >= joysticks.size()) {
             throw new IllegalArgumentException();
         }
@@ -111,10 +113,12 @@ public class GlfwJoystickInput implements JoyInput {
         return String.valueOf(index);
     }
 
+    @Override
     public void initialize() {
         initialized = true;
     }
 
+    @Override
     public void update() {
         for (final Map.Entry<Integer, GlfwJoystick> entry : joysticks.entrySet()) {
             // Axes
@@ -135,18 +139,22 @@ public class GlfwJoystickInput implements JoyInput {
         }
     }
 
+    @Override
     public void destroy() {
         initialized = false;
     }
 
+    @Override
     public boolean isInitialized() {
         return initialized;
     }
 
-    public void setInputListener(RawInputListener listener) {
+    @Override
+    public void setInputListener(final RawInputListener listener) {
         this.listener = listener;
     }
 
+    @Override
     public long getInputTimeNanos() {
         return 0;
     }
@@ -156,7 +164,7 @@ public class GlfwJoystickInput implements JoyInput {
         private JoystickAxis povAxisX;
         private JoystickAxis povAxisY;
 
-        public GlfwJoystick(InputManager inputManager, JoyInput joyInput, int joyId, String name) {
+        public GlfwJoystick(final InputManager inputManager, final JoyInput joyInput, final int joyId, final String name) {
             super(inputManager, joyInput, joyId, name);
         }
 
@@ -171,7 +179,7 @@ public class GlfwJoystickInput implements JoyInput {
         }
 
         @Override
-        protected void addButton(JoystickButton button) {
+        protected void addButton(final JoystickButton button) {
             super.addButton(button);
         }
 

+ 38 - 37
jme3-lwjgl3/src/main/java/com/jme3/input/lwjgl/GlfwKeyInput.java

@@ -32,11 +32,11 @@
 
 package com.jme3.input.lwjgl;
 
+import static org.lwjgl.glfw.GLFW.*;
 import com.jme3.input.KeyInput;
 import com.jme3.input.RawInputListener;
 import com.jme3.input.event.KeyInputEvent;
 import com.jme3.system.lwjgl.LwjglWindow;
-
 import org.lwjgl.glfw.GLFWCharCallback;
 import org.lwjgl.glfw.GLFWKeyCallback;
 
@@ -44,37 +44,54 @@ import java.util.LinkedList;
 import java.util.Queue;
 import java.util.logging.Logger;
 
-import static org.lwjgl.glfw.GLFW.GLFW_KEY_LAST;
-import static org.lwjgl.glfw.GLFW.GLFW_KEY_SPACE;
-import static org.lwjgl.glfw.GLFW.GLFW_PRESS;
-import static org.lwjgl.glfw.GLFW.GLFW_REPEAT;
-import static org.lwjgl.glfw.GLFW.glfwGetTime;
-import static org.lwjgl.glfw.GLFW.glfwSetCharCallback;
-import static org.lwjgl.glfw.GLFW.glfwSetKeyCallback;
-
+/**
+ * The LWJGL implementation of {@link KeyInput}.
+ */
 public class GlfwKeyInput implements KeyInput {
 
     private static final Logger logger = Logger.getLogger(GlfwKeyInput.class.getName());
 
+    /**
+     * The queue of key events.
+     */
+    private final Queue<KeyInputEvent> keyInputEvents = new LinkedList<>();
+
+    /**
+     * The LWJGL context.
+     */
     private LwjglWindow context;
-    private RawInputListener listener;
-    private boolean initialized;
+
+    /**
+     * The key callback.
+     */
     private GLFWKeyCallback keyCallback;
+
+    /**
+     * The char callback.
+     */
     private GLFWCharCallback charCallback;
-    private Queue<KeyInputEvent> keyInputEvents = new LinkedList<KeyInputEvent>();
 
-    public GlfwKeyInput(LwjglWindow context) {
+    /**
+     * The raw input listener.
+     */
+    private RawInputListener listener;
+
+    private boolean initialized;
+
+    public GlfwKeyInput(final LwjglWindow context) {
         this.context = context;
     }
 
+    @Override
     public void initialize() {
+
         if (!context.isRenderable()) {
             return;
         }
 
         glfwSetKeyCallback(context.getWindowHandle(), keyCallback = new GLFWKeyCallback() {
             @Override
-            public void invoke(long window, int key, int scancode, int action, int mods) {
+            public void invoke(final long window, final int key, final int scancode, final int action, final int mods) {
 
                 if (key < 0 || key > GLFW_KEY_LAST) {
                     return;
@@ -87,22 +104,11 @@ public class GlfwKeyInput implements KeyInput {
 
                 keyInputEvents.add(event);
             }
-
-            @Override
-            public void close() {
-                super.close();
-            }
-
-            @Override
-            public void callback(long args) {
-                super.callback(args);
-            }
         });
 
         glfwSetCharCallback(context.getWindowHandle(), charCallback = new GLFWCharCallback() {
-
             @Override
-            public void invoke(long window, int codepoint) {
+            public void invoke(final long window, final int codepoint) {
 
                 final char keyChar = (char) codepoint;
 
@@ -116,16 +122,6 @@ public class GlfwKeyInput implements KeyInput {
 
                 keyInputEvents.add(released);
             }
-
-            @Override
-            public void close() {
-                super.close();
-            }
-
-            @Override
-            public void callback(long args) {
-                super.callback(args);
-            }
         });
 
         initialized = true;
@@ -137,6 +133,7 @@ public class GlfwKeyInput implements KeyInput {
         return GLFW_KEY_LAST - GLFW_KEY_SPACE;
     }
 
+    @Override
     public void update() {
         if (!context.isRenderable()) {
             return;
@@ -147,6 +144,7 @@ public class GlfwKeyInput implements KeyInput {
         }
     }
 
+    @Override
     public void destroy() {
         if (!context.isRenderable()) {
             return;
@@ -157,14 +155,17 @@ public class GlfwKeyInput implements KeyInput {
         logger.fine("Keyboard destroyed.");
     }
 
+    @Override
     public boolean isInitialized() {
         return initialized;
     }
 
-    public void setInputListener(RawInputListener listener) {
+    @Override
+    public void setInputListener(final RawInputListener listener) {
         this.listener = listener;
     }
 
+    @Override
     public long getInputTimeNanos() {
         return (long) (glfwGetTime() * 1000000000);
     }

+ 5 - 5
jme3-lwjgl3/src/main/java/com/jme3/input/lwjgl/GlfwKeyMap.java

@@ -36,10 +36,10 @@ import static com.jme3.input.KeyInput.*;
 
 public class GlfwKeyMap {
 
-    private static final int[] glfwToJmeKeyMap = new int[GLFW_KEY_LAST + 1];
+    private static final int[] GLFW_TO_JME_KEY_MAP = new int[GLFW_KEY_LAST + 1];
 
-    private static void reg(int jmeKey, int glfwKey) {
-        glfwToJmeKeyMap[glfwKey] = jmeKey;
+    private static void reg(final int jmeKey, final int glfwKey) {
+        GLFW_TO_JME_KEY_MAP[glfwKey] = jmeKey;
     }
 
     static {
@@ -165,7 +165,7 @@ public class GlfwKeyMap {
         reg(KEY_RMETA, GLFW_KEY_RIGHT_SUPER);
     }
 
-    public static int toJmeKeyCode(int glfwKey) {
-        return glfwToJmeKeyMap[glfwKey];
+    public static int toJmeKeyCode(final int glfwKey) {
+        return GLFW_TO_JME_KEY_MAP[glfwKey];
     }
 }

+ 104 - 92
jme3-lwjgl3/src/main/java/com/jme3/input/lwjgl/GlfwMouseInput.java

@@ -31,6 +31,7 @@
  */
 package com.jme3.input.lwjgl;
 
+import static org.lwjgl.glfw.GLFW.*;
 import com.jme3.cursors.plugins.JmeCursor;
 import com.jme3.input.MouseInput;
 import com.jme3.input.RawInputListener;
@@ -38,19 +39,17 @@ import com.jme3.input.event.MouseButtonEvent;
 import com.jme3.input.event.MouseMotionEvent;
 import com.jme3.system.lwjgl.LwjglWindow;
 import com.jme3.util.BufferUtils;
+import org.lwjgl.glfw.*;
+import org.lwjgl.system.MemoryStack;
+import org.lwjgl.system.MemoryUtil;
+
 import java.nio.ByteBuffer;
 import java.nio.IntBuffer;
-import java.util.ArrayDeque;
 import java.util.HashMap;
+import java.util.LinkedList;
 import java.util.Map;
 import java.util.Queue;
 import java.util.logging.Logger;
-import static org.lwjgl.glfw.GLFW.*;
-import org.lwjgl.glfw.GLFWCursorPosCallback;
-import org.lwjgl.glfw.GLFWImage;
-import org.lwjgl.glfw.GLFWMouseButtonCallback;
-import org.lwjgl.glfw.GLFWScrollCallback;
-import org.lwjgl.system.MemoryUtil;
 
 /**
  * Captures mouse input using GLFW callbacks. It then temporarily stores these
@@ -68,34 +67,86 @@ public class GlfwMouseInput implements MouseInput {
 
     private static final int WHEEL_SCALE = 120;
 
+    private static long[] createGlfwCursor(final JmeCursor jmeCursor) {
+
+        long[] cursorArray = new long[jmeCursor.getNumImages()];
+
+        for (int i = 0; i < jmeCursor.getNumImages(); i++) {
+
+            final ByteBuffer buffer = transformCursorImage(jmeCursor.getImagesData(), jmeCursor.getWidth(), jmeCursor.getHeight(), i);
+            final GLFWImage glfwImage = new GLFWImage(BufferUtils.createByteBuffer(GLFWImage.SIZEOF));
+            glfwImage.set(jmeCursor.getWidth(), jmeCursor.getHeight(), buffer);
+
+            final int hotspotX = jmeCursor.getXHotSpot();
+            final int hotspotY = jmeCursor.getHeight() - jmeCursor.getYHotSpot();
+
+            cursorArray[i] = glfwCreateCursor(glfwImage, hotspotX, hotspotY);
+        }
+
+        return cursorArray;
+    }
+
+
+    private static ByteBuffer transformCursorImage(final IntBuffer imageData, final int width, final int height,
+                                                   final int index) {
+
+        final ByteBuffer byteBuffer = BufferUtils.createByteBuffer(width * height * 4);
+
+        // Transform image: ARGB -> RGBA, vertical flip
+        for (int y = height - 1; y >= 0; --y) {
+            for (int x = 0; x < width; ++x) {
+                int pixel = imageData.get(width * height * index + y * width + x);
+                byteBuffer.put((byte) ((pixel >> 16) & 0xFF));  // red
+                byteBuffer.put((byte) ((pixel >> 8) & 0xFF));   // green
+                byteBuffer.put((byte) (pixel & 0xFF));          // blue
+                byteBuffer.put((byte) ((pixel >> 24) & 0xFF));  // alpha
+            }
+        }
+
+        byteBuffer.flip();
+
+        return byteBuffer;
+    }
+
+    private final Map<JmeCursor, long[]> jmeToGlfwCursorMap = new HashMap<>();
+
+    private final Queue<MouseMotionEvent> mouseMotionEvents = new LinkedList<>();
+    private final Queue<MouseButtonEvent> mouseButtonEvents = new LinkedList<>();
+
     private final LwjglWindow context;
+
     private RawInputListener listener;
-    private boolean cursorVisible = true;
-    private long[] currentCursor;
+
     private IntBuffer currentCursorDelays;
-    private int currentCursorFrame = 0;
+    private GLFWCursorPosCallback cursorPosCallback;
+    private GLFWScrollCallback scrollCallback;
+    private GLFWMouseButtonCallback mouseButtonCallback;
+
+    private long[] currentCursor;
+
     private double currentCursorFrameStartTime = 0.0;
+
+    private int currentCursorFrame = 0;
     private int mouseX;
     private int mouseY;
     private int mouseWheel;
-    private boolean initialized;
-    private GLFWCursorPosCallback cursorPosCallback;
-    private GLFWScrollCallback scrollCallback;
-    private GLFWMouseButtonCallback mouseButtonCallback;
-    private final Queue<MouseMotionEvent> mouseMotionEvents = new ArrayDeque<>();
-    private final Queue<MouseButtonEvent> mouseButtonEvents = new ArrayDeque<>();
+    private int currentWidth;
+    private int currentHeight;
 
-    private final Map<JmeCursor, long[]> jmeToGlfwCursorMap = new HashMap<>();
+    private boolean cursorVisible;
+    private boolean initialized;
 
-    public GlfwMouseInput(LwjglWindow context) {
+    public GlfwMouseInput(final LwjglWindow context) {
         this.context = context;
+        this.cursorVisible = true;
     }
 
-    private void onCursorPos(long window, double xpos, double ypos) {
+    private void onCursorPos(final long window, final double xpos, final double ypos) {
+
         int xDelta;
         int yDelta;
         int x = (int) Math.round(xpos);
-        int y = context.getSettings().getHeight() - (int) Math.round(ypos);
+        int y = currentHeight - (int) Math.round(ypos);
 
         if (mouseX == 0) {
             mouseX = x;
@@ -117,7 +168,7 @@ public class GlfwMouseInput implements MouseInput {
         }
     }
 
-    private void onWheelScroll(long window, double xOffset, double yOffset) {
+    private void onWheelScroll(final long window, final double xOffset, final double yOffset) {
         mouseWheel += yOffset;
         final MouseMotionEvent mouseMotionEvent = new MouseMotionEvent(mouseX, mouseY, 0, 0, mouseWheel, (int) Math.round(yOffset));
         mouseMotionEvent.setTime(getInputTimeNanos());
@@ -125,61 +176,54 @@ public class GlfwMouseInput implements MouseInput {
     }
 
     private void onMouseButton(final long window, final int button, final int action, final int mods) {
-        final MouseButtonEvent mouseButtonEvent = new MouseButtonEvent(convertButton(button), action == GLFW_PRESS, mouseX, mouseY);
+        final boolean pressed = action == GLFW_PRESS;
+        final MouseButtonEvent mouseButtonEvent = new MouseButtonEvent(convertButton(button), pressed, mouseX, mouseY);
         mouseButtonEvent.setTime(getInputTimeNanos());
         mouseButtonEvents.add(mouseButtonEvent);
     }
 
     @Override
     public void initialize() {
-        glfwSetCursorPosCallback(context.getWindowHandle(), cursorPosCallback = new GLFWCursorPosCallback() {
-            @Override
-            public void invoke(long window, double xpos, double ypos) {
-                onCursorPos(window, xpos, ypos);
-            }
 
-            @Override
-            public void close() {
-                super.close();
-            }
+        final long window = context.getWindowHandle();
+
+        try (MemoryStack stack = MemoryStack.stackPush()) {
+
+            final IntBuffer width = stack.callocInt(1);
+            final IntBuffer height = stack.callocInt(1);
+
+            glfwGetWindowSize(window, width, height);
+
+            currentWidth = width.get();
+            currentHeight = height.get();
+        }
 
+        glfwSetCursorPosCallback(window, cursorPosCallback = new GLFWCursorPosCallback() {
             @Override
-            public void callback(long args) {
-                super.callback(args);
+            public void invoke(final long window, final double xpos, final double ypos) {
+                onCursorPos(window, xpos, ypos);
             }
         });
 
-        glfwSetScrollCallback(context.getWindowHandle(), scrollCallback = new GLFWScrollCallback() {
+        glfwSetScrollCallback(window, scrollCallback = new GLFWScrollCallback() {
             @Override
             public void invoke(final long window, final double xOffset, final double yOffset) {
                 onWheelScroll(window, xOffset, yOffset * WHEEL_SCALE);
             }
-
-            @Override
-            public void close() {
-                super.close();
-            }
-
-            @Override
-            public void callback(long args) {
-                super.callback(args);
-            }
         });
 
-        glfwSetMouseButtonCallback(context.getWindowHandle(), mouseButtonCallback = new GLFWMouseButtonCallback() {
+        glfwSetMouseButtonCallback(window, mouseButtonCallback = new GLFWMouseButtonCallback() {
             @Override
             public void invoke(final long window, final int button, final int action, final int mods) {
                 onMouseButton(window, button, action, mods);
             }
+        });
 
+        glfwSetWindowSizeCallback(window, new GLFWWindowSizeCallback() {
             @Override
-            public void close() {
-                super.close();
-            }
-
-            @Override
-            public void callback(long args) {
-                super.callback(args);
+            public void invoke(final long window, final int width, final int height) {
+                currentHeight = height;
+                currentWidth = width;
             }
         });
 
@@ -224,6 +268,7 @@ public class GlfwMouseInput implements MouseInput {
 
     @Override
     public void destroy() {
+
         if (!context.isRenderable()) {
             return;
         }
@@ -234,11 +279,13 @@ public class GlfwMouseInput implements MouseInput {
 
         currentCursor = null;
         currentCursorDelays = null;
+
         for (long[] glfwCursors : jmeToGlfwCursorMap.values()) {
             for (long glfwCursor : glfwCursors) {
                 glfwDestroyCursor(glfwCursor);
             }
         }
+
         jmeToGlfwCursorMap.clear();
 
         logger.fine("Mouse destroyed.");
@@ -269,58 +316,23 @@ public class GlfwMouseInput implements MouseInput {
         return (long) (glfwGetTime() * 1000000000);
     }
 
-    private ByteBuffer transformCursorImage(IntBuffer imageData, int w, int h, int index) {
-        ByteBuffer buf = BufferUtils.createByteBuffer(w * h * 4);
-
-        // Transform image: ARGB -> RGBA, vertical flip
-        for (int y = h - 1; y >= 0; --y) {
-            for (int x = 0; x < w; ++x) {
-                int pixel = imageData.get(w * h * index + y * w + x);
-                buf.put((byte) ((pixel >> 16) & 0xFF));  // red
-                buf.put((byte) ((pixel >> 8) & 0xFF));  // green
-                buf.put((byte) (pixel & 0xFF));  // blue
-                buf.put((byte) ((pixel >> 24) & 0xFF));  // alpha
-            }
-        }
-
-        buf.flip();
-        return buf;
-    }
-
-    private long[] createGlfwCursor(JmeCursor jmeCursor) {
-        long[] cursorArray = new long[jmeCursor.getNumImages()];
-        for (int i = 0; i < jmeCursor.getNumImages(); i++) {
-            ByteBuffer buf = transformCursorImage(jmeCursor.getImagesData(), jmeCursor.getWidth(), jmeCursor.getHeight(), i);
-
-            GLFWImage glfwImage = new GLFWImage(BufferUtils.createByteBuffer(GLFWImage.SIZEOF));
-            glfwImage.set(jmeCursor.getWidth(), jmeCursor.getHeight(), buf);
-
-            int hotspotX = jmeCursor.getXHotSpot();
-            int hotspotY = jmeCursor.getHeight() - jmeCursor.getYHotSpot();
-
-            cursorArray[i] = glfwCreateCursor(glfwImage, hotspotX, hotspotY);
-        }
-        return cursorArray;
-    }
-
     @Override
-    public void setNativeCursor(JmeCursor jmeCursor) {
+    public void setNativeCursor(final JmeCursor jmeCursor) {
         if (jmeCursor != null) {
-            long[] glfwCursor = jmeToGlfwCursorMap.get(jmeCursor);
 
-            if (glfwCursor == null) {
-                glfwCursor = createGlfwCursor(jmeCursor);
-                jmeToGlfwCursorMap.put(jmeCursor, glfwCursor);
-            }
+            final long[] glfwCursor = jmeToGlfwCursorMap.computeIfAbsent(jmeCursor, GlfwMouseInput::createGlfwCursor);
 
             currentCursorFrame = 0;
             currentCursor = glfwCursor;
             currentCursorDelays = null;
             currentCursorFrameStartTime = glfwGetTime();
+
             if (jmeCursor.getImagesDelay() != null) {
                 currentCursorDelays = jmeCursor.getImagesDelay();
             }
+
             glfwSetCursor(context.getWindowHandle(), glfwCursor[currentCursorFrame]);
+
         } else {
             currentCursor = null;
             currentCursorDelays = null;

+ 12 - 6
jme3-lwjgl3/src/main/java/com/jme3/lwjgl3/utils/APIUtil.java

@@ -20,16 +20,22 @@ import java.util.regex.Pattern;
  */
 public final class APIUtil {
 
-    private static final ThreadLocal<APIBuffer> API_BUFFERS = new ThreadLocal<APIBuffer>() {
-        @Override
-        protected APIBuffer initialValue() {
-            return new APIBuffer();
-        }
-    };
+    private static final ThreadLocal<APIBuffer> API_BUFFERS = ThreadLocal.withInitial(APIBuffer::new);
 
     private APIUtil() {
     }
 
+    /**
+     * Converts dynamic arguments to object array.
+     *
+     * @param arguments the list of arguments.
+     * @return the object array.
+     */
+    @SafeVarargs
+    public static <T> T[] toArray(T... arguments) {
+        return arguments;
+    }
+
     /**
      * Returns a thread-local {@link APIBuffer} that has been reset.
      */

+ 353 - 249
jme3-lwjgl3/src/main/java/com/jme3/renderer/lwjgl/LwjglGL.java

@@ -31,449 +31,553 @@
  */
 package com.jme3.renderer.lwjgl;
 
-import com.jme3.renderer.RendererException;
 import com.jme3.renderer.opengl.GL;
 import com.jme3.renderer.opengl.GL2;
 import com.jme3.renderer.opengl.GL3;
 import com.jme3.renderer.opengl.GL4;
 import org.lwjgl.opengl.*;
 
-import java.nio.*;
+import java.nio.ByteBuffer;
+import java.nio.FloatBuffer;
+import java.nio.IntBuffer;
+import java.nio.ShortBuffer;
 
-public class LwjglGL implements GL, GL2, GL3, GL4 {
+/**
+ * The LWJGL implementation of interfaces {@link GL}, {@link GL2}, {@link GL3}, {@link GL4}.
+ */
+public class LwjglGL extends LwjglRender implements GL, GL2, GL3, GL4 {
 
-    private static void checkLimit(Buffer buffer) {
-        if (buffer == null) {
-            return;
-        }
-        if (buffer.limit() == 0) {
-            throw new RendererException("Attempting to upload empty buffer (limit = 0), that's an error");
-        }
-        if (buffer.remaining() == 0) {
-            throw new RendererException("Attempting to upload empty buffer (remaining = 0), that's an error");
-        }
-    }
-    
+    @Override
     public void resetStats() {
     }
-    
-    public void glActiveTexture(int param1) {
-        GL13.glActiveTexture(param1);
+
+    @Override
+    public void glActiveTexture(final int texture) {
+        GL13.glActiveTexture(texture);
     }
 
-    public void glAlphaFunc(int param1, float param2) {
-        GL11.glAlphaFunc(param1, param2);
+    @Override
+    public void glAlphaFunc(final int func, final float ref) {
+        GL11.glAlphaFunc(func, ref);
     }
 
-    public void glAttachShader(int param1, int param2) {
-        GL20.glAttachShader(param1, param2);
+    @Override
+    public void glAttachShader(final int program, final int shader) {
+        GL20.glAttachShader(program, shader);
     }
 
     @Override
-    public void glBeginQuery(int target, int query) {
+    public void glBeginQuery(final int target, final int query) {
         GL15.glBeginQuery(target, query);
     }
 
-    public void glBindBuffer(int param1, int param2) {
-        GL15.glBindBuffer(param1, param2);
+    @Override
+    public void glBindBuffer(final int target, final int buffer) {
+        GL15.glBindBuffer(target, buffer);
     }
 
-    public void glBindTexture(int param1, int param2) {
-        GL11.glBindTexture(param1, param2);
+    @Override
+    public void glBindTexture(final int target, final int texture) {
+        GL11.glBindTexture(target, texture);
     }
 
-    public void glBlendEquationSeparate(int colorMode, int alphaMode){
-        GL20.glBlendEquationSeparate(colorMode,alphaMode);
+    @Override
+    public void glBlendEquationSeparate(final int colorMode, final int alphaMode) {
+        GL20.glBlendEquationSeparate(colorMode, alphaMode);
     }
 
-    public void glBlendFunc(int param1, int param2) {
-        GL11.glBlendFunc(param1, param2);
+    @Override
+    public void glBlendFunc(final int sfactor, final int dfactor) {
+        GL11.glBlendFunc(sfactor, dfactor);
     }
-    
-    public void glBlendFuncSeparate(int param1, int param2, int param3, int param4) {
-        GL14.glBlendFuncSeparate(param1, param2, param3, param4);
+
+    @Override
+    public void glBlendFuncSeparate(final int sfactorRGB, final int dfactorRGB, final int sfactorAlpha,
+                                    final int dfactorAlpha) {
+        GL14.glBlendFuncSeparate(sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha);
     }
 
-    public void glBufferData(int param1, long param2, int param3) {
-        GL15.glBufferData(param1, param2, param3);
+    @Override
+    public void glBufferData(final int target, final long dataSize, final int usage) {
+        GL15.glBufferData(target, dataSize, usage);
     }
-    
-    public void glBufferData(int param1, FloatBuffer param2, int param3) {
-        checkLimit(param2);
-        GL15.glBufferData(param1, param2, param3);
+
+    @Override
+    public void glBufferData(final int target, final FloatBuffer data, final int usage) {
+        checkLimit(data);
+        GL15.glBufferData(target, data, usage);
     }
 
-    public void glBufferData(int param1, ShortBuffer param2, int param3) {
-        checkLimit(param2);
-        GL15.glBufferData(param1, param2, param3);
+    @Override
+    public void glBufferData(final int target, final ShortBuffer data, final int usage) {
+        checkLimit(data);
+        GL15.glBufferData(target, data, usage);
     }
 
-    public void glBufferData(int param1, ByteBuffer param2, int param3) {
-        checkLimit(param2);
-        GL15.glBufferData(param1, param2, param3);
+    @Override
+    public void glBufferData(final int target, final ByteBuffer data, final int usage) {
+        checkLimit(data);
+        GL15.glBufferData(target, data, usage);
     }
 
-    public void glBufferSubData(int param1, long param2, FloatBuffer param3) {
-        checkLimit(param3);
-        GL15.glBufferSubData(param1, param2, param3);
+    @Override
+    public void glBufferSubData(final int target, final long offset, final FloatBuffer data) {
+        checkLimit(data);
+        GL15.glBufferSubData(target, offset, data);
     }
 
-    public void glBufferSubData(int param1, long param2, ShortBuffer param3) {
-        checkLimit(param3);
-        GL15.glBufferSubData(param1, param2, param3);
+    @Override
+    public void glBufferSubData(final int target, final long offset, final ShortBuffer data) {
+        checkLimit(data);
+        GL15.glBufferSubData(target, offset, data);
     }
 
-    public void glBufferSubData(int param1, long param2, ByteBuffer param3) {
-        checkLimit(param3);
-        GL15.glBufferSubData(param1, param2, param3);
+    @Override
+    public void glBufferSubData(final int target, final long offset, final ByteBuffer data) {
+        checkLimit(data);
+        GL15.glBufferSubData(target, offset, data);
     }
 
-    public void glClear(int param1) {
-        GL11.glClear(param1);
+    @Override
+    public void glClear(final int mask) {
+        GL11.glClear(mask);
     }
 
-    public void glClearColor(float param1, float param2, float param3, float param4) {
-        GL11.glClearColor(param1, param2, param3, param4);
+    @Override
+    public void glClearColor(final float red, final float green, final float blue, final float alpha) {
+        GL11.glClearColor(red, green, blue, alpha);
     }
 
-    public void glColorMask(boolean param1, boolean param2, boolean param3, boolean param4) {
-        GL11.glColorMask(param1, param2, param3, param4);
+    @Override
+    public void glColorMask(final boolean red, final boolean green, final boolean blue, final boolean alpha) {
+        GL11.glColorMask(red, green, blue, alpha);
     }
 
-    public void glCompileShader(int param1) {
-        GL20.glCompileShader(param1);
+    @Override
+    public void glCompileShader(final int shader) {
+        GL20.glCompileShader(shader);
     }
 
-    public void glCompressedTexImage2D(int param1, int param2, int param3, int param4, int param5, int param6, ByteBuffer param7) {
-        checkLimit(param7);
-        GL13.glCompressedTexImage2D(param1, param2, param3, param4, param5, param6, param7);
+    @Override
+    public void glCompressedTexImage2D(final int target, final int level, final int internalFormat, final int width,
+                                       final int height, final int border, final ByteBuffer data) {
+        checkLimit(data);
+        GL13.glCompressedTexImage2D(target, level, internalFormat, width, height, border, data);
     }
 
-    public void glCompressedTexImage3D(int param1, int param2, int param3, int param4, int param5, int param6, int param7, ByteBuffer param8) {
-        checkLimit(param8);
-        GL13.glCompressedTexImage3D(param1, param2, param3, param4, param5, param6, param7, param8);
+    @Override
+    public void glCompressedTexImage3D(final int target, final int level, final int internalFormat, final int width,
+                                       final int height, final int depth, final int border, final ByteBuffer data) {
+        checkLimit(data);
+        GL13.glCompressedTexImage3D(target, level, internalFormat, width, height, depth, border, data);
     }
 
-    public void glCompressedTexSubImage2D(int param1, int param2, int param3, int param4, int param5, int param6, int param7, ByteBuffer param8) {
-        checkLimit(param8);
-        GL13.glCompressedTexSubImage2D(param1, param2, param3, param4, param5, param6, param7, param8);
+    @Override
+    public void glCompressedTexSubImage2D(final int target, final int level, final int xoffset, final int yoffset,
+                                          final int width, final int height, final int format, final ByteBuffer data) {
+        checkLimit(data);
+        GL13.glCompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, data);
     }
 
-    public void glCompressedTexSubImage3D(int param1, int param2, int param3, int param4, int param5, int param6, int param7, int param8, int param9, ByteBuffer param10) {
-        checkLimit(param10);
-        GL13.glCompressedTexSubImage3D(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10);
+    @Override
+    public void glCompressedTexSubImage3D(final int target, final int level, final int xoffset, final int yoffset,
+                                          final int zoffset, final int width, final int height, final int depth,
+                                          final int format, final ByteBuffer data) {
+        checkLimit(data);
+        GL13.glCompressedTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, data);
     }
 
+    @Override
     public int glCreateProgram() {
         return GL20.glCreateProgram();
     }
 
-    public int glCreateShader(int param1) {
-        return GL20.glCreateShader(param1);
+    @Override
+    public int glCreateShader(final int shaderType) {
+        return GL20.glCreateShader(shaderType);
     }
 
-    public void glCullFace(int param1) {
-        GL11.glCullFace(param1);
+    @Override
+    public void glCullFace(final int mode) {
+        GL11.glCullFace(mode);
     }
 
-    public void glDeleteBuffers(IntBuffer param1) {
-        checkLimit(param1);
-        GL15.glDeleteBuffers(param1);
+    @Override
+    public void glDeleteBuffers(final IntBuffer buffers) {
+        checkLimit(buffers);
+        GL15.glDeleteBuffers(buffers);
     }
 
-    public void glDeleteProgram(int param1) {
-        GL20.glDeleteProgram(param1);
+    @Override
+    public void glDeleteProgram(final int program) {
+        GL20.glDeleteProgram(program);
     }
 
-    public void glDeleteShader(int param1) {
-        GL20.glDeleteShader(param1);
+    @Override
+    public void glDeleteShader(final int shader) {
+        GL20.glDeleteShader(shader);
     }
 
-    public void glDeleteTextures(IntBuffer param1) {
-        checkLimit(param1);
-        GL11.glDeleteTextures(param1);
+    @Override
+    public void glDeleteTextures(final IntBuffer textures) {
+        checkLimit(textures);
+        GL11.glDeleteTextures(textures);
     }
 
-    public void glDepthFunc(int param1) {
-        GL11.glDepthFunc(param1);
+    @Override
+    public void glDepthFunc(final int func) {
+        GL11.glDepthFunc(func);
     }
 
-    public void glDepthMask(boolean param1) {
-        GL11.glDepthMask(param1);
+    @Override
+    public void glDepthMask(final boolean flag) {
+        GL11.glDepthMask(flag);
     }
 
-    public void glDepthRange(double param1, double param2) {
-        GL11.glDepthRange(param1, param2);
+    @Override
+    public void glDepthRange(final double nearVal, final double farVal) {
+        GL11.glDepthRange(nearVal, farVal);
     }
 
-    public void glDetachShader(int param1, int param2) {
-        GL20.glDetachShader(param1, param2);
+    @Override
+    public void glDetachShader(final int program, final int shader) {
+        GL20.glDetachShader(program, shader);
     }
 
-    public void glDisable(int param1) {
-        GL11.glDisable(param1);
+    @Override
+    public void glDisable(final int cap) {
+        GL11.glDisable(cap);
     }
 
-    public void glDisableVertexAttribArray(int param1) {
-        GL20.glDisableVertexAttribArray(param1);
+    @Override
+    public void glDisableVertexAttribArray(final int index) {
+        GL20.glDisableVertexAttribArray(index);
     }
 
-    public void glDrawArrays(int param1, int param2, int param3) {
-        GL11.glDrawArrays(param1, param2, param3);
+    @Override
+    public void glDrawArrays(final int mode, final int first, final int count) {
+        GL11.glDrawArrays(mode, first, count);
     }
 
-    public void glDrawBuffer(int param1) {
-        GL11.glDrawBuffer(param1);
+    @Override
+    public void glDrawBuffer(final int mode) {
+        GL11.glDrawBuffer(mode);
     }
-    
-    public void glDrawRangeElements(int param1, int param2, int param3, int param4, int param5, long param6) {
-        GL12.glDrawRangeElements(param1, param2, param3, param4, param5, param6);
+
+    @Override
+    public void glDrawRangeElements(final int mode, final int start, final int end, final int count, final int type,
+                                    final long indices) {
+        GL12.glDrawRangeElements(mode, start, end, count, type, indices);
     }
 
-    public void glEnable(int param1) {
-        GL11.glEnable(param1);
+    @Override
+    public void glEnable(final int cap) {
+        GL11.glEnable(cap);
     }
 
-    public void glEnableVertexAttribArray(int param1) {
-        GL20.glEnableVertexAttribArray(param1);
+    @Override
+    public void glEnableVertexAttribArray(final int index) {
+        GL20.glEnableVertexAttribArray(index);
     }
 
     @Override
-    public void glEndQuery(int target) {
+    public void glEndQuery(final int target) {
         GL15.glEndQuery(target);
     }
 
-    public void glGenBuffers(IntBuffer param1) {
-        checkLimit(param1);
-        GL15.glGenBuffers(param1);
+    @Override
+    public void glGenBuffers(final IntBuffer buffers) {
+        checkLimit(buffers);
+        GL15.glGenBuffers(buffers);
     }
 
-    public void glGenTextures(IntBuffer param1) {
-        checkLimit(param1);
-        GL11.glGenTextures(param1);
+    @Override
+    public void glGenTextures(final IntBuffer textures) {
+        checkLimit(textures);
+        GL11.glGenTextures(textures);
     }
 
     @Override
-    public void glGenQueries(int num, IntBuffer ids) {
+    public void glGenQueries(final int num, final IntBuffer ids) {
         GL15.glGenQueries(ids);
     }
 
-    public void glGetBoolean(int param1, ByteBuffer param2) {
-        checkLimit(param2);
-        GL11.glGetBooleanv(param1, param2);
+    @Override
+    public void glGetBoolean(final int pname, final ByteBuffer params) {
+        checkLimit(params);
+        GL11.glGetBooleanv(pname, params);
     }
-    
-    public void glGetBufferSubData(int target, long offset, ByteBuffer data) {
+
+    @Override
+    public void glGetBufferSubData(final int target, final long offset, final ByteBuffer data) {
         checkLimit(data);
         GL15.glGetBufferSubData(target, offset, data);
     }
 
+    @Override
     public int glGetError() {
         return GL11.glGetError();
     }
-    
-    public void glGetInteger(int param1, IntBuffer param2) {
-        checkLimit(param2);
-        GL11.glGetIntegerv(param1, param2);
+
+    @Override
+    public void glGetInteger(final int pname, final IntBuffer params) {
+        checkLimit(params);
+        GL11.glGetIntegerv(pname, params);
     }
 
-    public void glGetProgram(int param1, int param2, IntBuffer param3) {
-        checkLimit(param3);
-        GL20.glGetProgramiv(param1, param2, param3);
+    @Override
+    public void glGetProgram(final int program, final int pname, final IntBuffer params) {
+        checkLimit(params);
+        GL20.glGetProgramiv(program, pname, params);
     }
 
-    public void glGetShader(int param1, int param2, IntBuffer param3) {
-        checkLimit(param3);
-        GL20.glGetShaderiv(param1, param2, param3);
+    @Override
+    public void glGetShader(final int shader, final int pname, final IntBuffer params) {
+        checkLimit(params);
+        GL20.glGetShaderiv(shader, pname, params);
     }
 
-    public String glGetString(int param1) {
-        return GL11.glGetString(param1);
+    @Override
+    public String glGetString(final int name) {
+        return GL11.glGetString(name);
     }
-    
-    public String glGetString(int param1, int param2) {
-        return GL30.glGetStringi(param1, param2);
+
+    @Override
+    public String glGetString(final int name, final int index) {
+        return GL30.glGetStringi(name, index);
     }
 
-    public boolean glIsEnabled(int param1) {
-        return GL11.glIsEnabled(param1);
+    @Override
+    public boolean glIsEnabled(final int cap) {
+        return GL11.glIsEnabled(cap);
     }
 
-    public void glLineWidth(float param1) {
-        GL11.glLineWidth(param1);
+    @Override
+    public void glLineWidth(final float width) {
+        GL11.glLineWidth(width);
     }
 
-    public void glLinkProgram(int param1) {
-        GL20.glLinkProgram(param1);
+    @Override
+    public void glLinkProgram(final int program) {
+        GL20.glLinkProgram(program);
     }
 
-    public void glPixelStorei(int param1, int param2) {
-        GL11.glPixelStorei(param1, param2);
+    @Override
+    public void glPixelStorei(final int pname, final int param) {
+        GL11.glPixelStorei(pname, param);
     }
 
-    public void glPointSize(float param1) {
-        GL11.glPointSize(param1);
+    @Override
+    public void glPointSize(final float size) {
+        GL11.glPointSize(size);
     }
 
-    public void glPolygonMode(int param1, int param2) {
-        GL11.glPolygonMode(param1, param2);
+    @Override
+    public void glPolygonMode(final int face, final int mode) {
+        GL11.glPolygonMode(face, mode);
     }
 
-    public void glPolygonOffset(float param1, float param2) {
-        GL11.glPolygonOffset(param1, param2);
+    @Override
+    public void glPolygonOffset(final float factor, final float units) {
+        GL11.glPolygonOffset(factor, units);
     }
 
-    public void glReadBuffer(int param1) {
-        GL11.glReadBuffer(param1);
+    @Override
+    public void glReadBuffer(final int mode) {
+        GL11.glReadBuffer(mode);
     }
 
-    public void glReadPixels(int param1, int param2, int param3, int param4, int param5, int param6, ByteBuffer param7) {
-        checkLimit(param7);
-        GL11.glReadPixels(param1, param2, param3, param4, param5, param6, param7);
+    @Override
+    public void glReadPixels(final int x, final int y, final int width, final int height, final int format,
+                             final int type, final ByteBuffer data) {
+        checkLimit(data);
+        GL11.glReadPixels(x, y, width, height, format, type, data);
     }
-    
-    public void glReadPixels(int param1, int param2, int param3, int param4, int param5, int param6, long param7) {
-        GL11.glReadPixels(param1, param2, param3, param4, param5, param6, param7);
+
+    @Override
+    public void glReadPixels(final int x, final int y, final int width, final int height, final int format,
+                             final int type, final long offset) {
+        GL11.glReadPixels(x, y, width, height, format, type, offset);
     }
 
-    public void glScissor(int param1, int param2, int param3, int param4) {
-        GL11.glScissor(param1, param2, param3, param4);
+    @Override
+    public void glScissor(final int x, final int y, final int width, final int height) {
+        GL11.glScissor(x, y, width, height);
     }
 
-    public void glStencilFuncSeparate(int param1, int param2, int param3, int param4) {
-        GL20.glStencilFuncSeparate(param1, param2, param3, param4);
+    @Override
+    public void glStencilFuncSeparate(final int face, final int func, final int ref, final int mask) {
+        GL20.glStencilFuncSeparate(face, func, ref, mask);
     }
 
-    public void glStencilOpSeparate(int param1, int param2, int param3, int param4) {
-        GL20.glStencilOpSeparate(param1, param2, param3, param4);
+    @Override
+    public void glStencilOpSeparate(final int face, final int sfail, final int dpfail, final int dppass) {
+        GL20.glStencilOpSeparate(face, sfail, dpfail, dppass);
     }
 
-    public void glTexImage2D(int param1, int param2, int param3, int param4, int param5, int param6, int param7, int param8, ByteBuffer param9) {
-        checkLimit(param9);
-        GL11.glTexImage2D(param1, param2, param3, param4, param5, param6, param7, param8, param9);
+    @Override
+    public void glTexImage2D(final int target, final int level, final int internalFormat, final int width,
+                             final int height, final int border, final int format, final int type,
+                             final ByteBuffer data) {
+        checkLimit(data);
+        GL11.glTexImage2D(target, level, internalFormat, width, height, border, format, type, data);
     }
 
-    public void glTexImage3D(int param1, int param2, int param3, int param4, int param5, int param6, int param7, int param8, int param9, ByteBuffer param10) {
-        checkLimit(param10);
-        GL12.glTexImage3D(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10);
+    @Override
+    public void glTexImage3D(final int target, final int level, final int internalFormat, final int width,
+                             final int height, final int depth, final int border, final int format, final int type,
+                             final ByteBuffer data) {
+        checkLimit(data);
+        GL12.glTexImage3D(target, level, internalFormat, width, height, depth, border, format, type, data);
     }
 
-    public void glTexParameterf(int param1, int param2, float param3) {
-        GL11.glTexParameterf(param1, param2, param3);
+    @Override
+    public void glTexParameterf(final int target, final int pname, final float param) {
+        GL11.glTexParameterf(target, pname, param);
     }
 
-    public void glTexParameteri(int param1, int param2, int param3) {
-        GL11.glTexParameteri(param1, param2, param3);
+    @Override
+    public void glTexParameteri(final int target, final int pname, final int param) {
+        GL11.glTexParameteri(target, pname, param);
     }
 
-    public void glTexSubImage2D(int param1, int param2, int param3, int param4, int param5, int param6, int param7, int param8, ByteBuffer param9) {
-        checkLimit(param9);
-        GL11.glTexSubImage2D(param1, param2, param3, param4, param5, param6, param7, param8, param9);
+    @Override
+    public void glTexSubImage2D(final int target, final int level, final int xoffset, final int yoffset,
+                                final int width, final int height, final int format, final int type,
+                                final ByteBuffer data) {
+        checkLimit(data);
+        GL11.glTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, data);
     }
 
-    public void glTexSubImage3D(int param1, int param2, int param3, int param4, int param5, int param6, int param7, int param8, int param9, int param10, ByteBuffer param11) {
-        checkLimit(param11);
-        GL12.glTexSubImage3D(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11);
+    @Override
+    public void glTexSubImage3D(final int target, final int level, final int xoffset, final int yoffset,
+                                final int zoffset, final int width, final int height, final int depth, final int format,
+                                final int type, final ByteBuffer data) {
+        checkLimit(data);
+        GL12.glTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, data);
     }
 
-    public void glUniform1(int param1, FloatBuffer param2) {
-        checkLimit(param2);
-        GL20.glUniform1fv(param1, param2);
+    @Override
+    public void glUniform1(final int location, final FloatBuffer value) {
+        checkLimit(value);
+        GL20.glUniform1fv(location, value);
     }
 
-    public void glUniform1(int param1, IntBuffer param2) {
-        checkLimit(param2);
-        GL20.glUniform1iv(param1, param2);
+    @Override
+    public void glUniform1(final int location, final IntBuffer value) {
+        checkLimit(value);
+        GL20.glUniform1iv(location, value);
     }
 
-    public void glUniform1f(int param1, float param2) {
-        GL20.glUniform1f(param1, param2);
+    @Override
+    public void glUniform1f(final int location, final float v0) {
+        GL20.glUniform1f(location, v0);
     }
 
-    public void glUniform1i(int param1, int param2) {
-        GL20.glUniform1i(param1, param2);
+    @Override
+    public void glUniform1i(final int location, final int v0) {
+        GL20.glUniform1i(location, v0);
     }
 
-    public void glUniform2(int param1, IntBuffer param2) {
-        checkLimit(param2);
-        GL20.glUniform2iv(param1, param2);
+    @Override
+    public void glUniform2(final int location, final IntBuffer value) {
+        checkLimit(value);
+        GL20.glUniform2iv(location, value);
     }
 
-    public void glUniform2(int param1, FloatBuffer param2) {
-        checkLimit(param2);
-        GL20.glUniform2fv(param1, param2);
+    @Override
+    public void glUniform2(final int location, final FloatBuffer value) {
+        checkLimit(value);
+        GL20.glUniform2fv(location, value);
     }
 
-    public void glUniform2f(int param1, float param2, float param3) {
-        GL20.glUniform2f(param1, param2, param3);
+    @Override
+    public void glUniform2f(final int location, final float v0, final float v1) {
+        GL20.glUniform2f(location, v0, v1);
     }
 
-    public void glUniform3(int param1, IntBuffer param2) {
-        checkLimit(param2);
-        GL20.glUniform3iv(param1, param2);
+    @Override
+    public void glUniform3(final int location, final IntBuffer value) {
+        checkLimit(value);
+        GL20.glUniform3iv(location, value);
     }
 
-    public void glUniform3(int param1, FloatBuffer param2) {
-        checkLimit(param2);
-        GL20.glUniform3fv(param1, param2);
+    @Override
+    public void glUniform3(final int location, final FloatBuffer value) {
+        checkLimit(value);
+        GL20.glUniform3fv(location, value);
     }
 
-    public void glUniform3f(int param1, float param2, float param3, float param4) {
-        GL20.glUniform3f(param1, param2, param3, param4);
+    @Override
+    public void glUniform3f(final int location, final float v0, final float v1, final float v2) {
+        GL20.glUniform3f(location, v0, v1, v2);
     }
 
-    public void glUniform4(int param1, FloatBuffer param2) {
-        checkLimit(param2);
-        GL20.glUniform4fv(param1, param2);
+    @Override
+    public void glUniform4(final int location, final FloatBuffer value) {
+        checkLimit(value);
+        GL20.glUniform4fv(location, value);
     }
 
-    public void glUniform4(int param1, IntBuffer param2) {
-        checkLimit(param2);
-        GL20.glUniform4iv(param1, param2);
+    @Override
+    public void glUniform4(final int location, final IntBuffer value) {
+        checkLimit(value);
+        GL20.glUniform4iv(location, value);
     }
 
-    public void glUniform4f(int param1, float param2, float param3, float param4, float param5) {
-        GL20.glUniform4f(param1, param2, param3, param4, param5);
+    @Override
+    public void glUniform4f(final int location, final float v0, final float v1, final float v2, final float v3) {
+        GL20.glUniform4f(location, v0, v1, v2, v3);
     }
 
-    public void glUniformMatrix3(int param1, boolean param2, FloatBuffer param3) {
-        checkLimit(param3);
-        GL20.glUniformMatrix3fv(param1, param2, param3);
+    @Override
+    public void glUniformMatrix3(final int location, final boolean transpose, final FloatBuffer value) {
+        checkLimit(value);
+        GL20.glUniformMatrix3fv(location, transpose, value);
     }
 
-    public void glUniformMatrix4(int param1, boolean param2, FloatBuffer param3) {
-        checkLimit(param3);
-        GL20.glUniformMatrix4fv(param1, param2, param3);
+    @Override
+    public void glUniformMatrix4(final int location, final boolean transpose, final FloatBuffer value) {
+        checkLimit(value);
+        GL20.glUniformMatrix4fv(location, transpose, value);
     }
 
-    public void glUseProgram(int param1) {
-        GL20.glUseProgram(param1);
+    @Override
+    public void glUseProgram(final int program) {
+        GL20.glUseProgram(program);
     }
 
-    public void glVertexAttribPointer(int param1, int param2, int param3, boolean param4, int param5, long param6) {
-        GL20.glVertexAttribPointer(param1, param2, param3, param4, param5, param6);
+    @Override
+    public void glVertexAttribPointer(final int index, final int size, final int type, final boolean normalized,
+                                      final int stride, final long pointer) {
+        GL20.glVertexAttribPointer(index, size, type, normalized, stride, pointer);
     }
 
-    public void glViewport(int param1, int param2, int param3, int param4) {
-        GL11.glViewport(param1, param2, param3, param4);
+    @Override
+    public void glViewport(final int x, final int y, final int width, final int height) {
+        GL11.glViewport(x, y, width, height);
     }
 
-    public int glGetAttribLocation(int param1, String param2) {
+    @Override
+    public int glGetAttribLocation(final int program, final String name) {
         // NOTE: LWJGL requires null-terminated strings
-        return GL20.glGetAttribLocation(param1, param2 + "\0");
+        return GL20.glGetAttribLocation(program, name + "\0");
     }
 
-    public int glGetUniformLocation(int param1, String param2) {
+    @Override
+    public int glGetUniformLocation(final int program, final String name) {
         // NOTE: LWJGL requires null-terminated strings
-        return GL20.glGetUniformLocation(param1, param2 + "\0");
+        return GL20.glGetUniformLocation(program, name + "\0");
     }
 
-    public void glShaderSource(int param1, String[] param2, IntBuffer param3) {
-        checkLimit(param3);
-        GL20.glShaderSource(param1, param2);
+    @Override
+    public void glShaderSource(final int shader, final String[] strings, final IntBuffer length) {
+        checkLimit(length);
+        GL20.glShaderSource(shader, strings);
     }
 
-    public String glGetProgramInfoLog(int program, int maxSize) {
+    @Override
+    public String glGetProgramInfoLog(final int program, final int maxSize) {
         return GL20.glGetProgramInfoLog(program, maxSize);
     }
 
@@ -492,28 +596,28 @@ public class LwjglGL implements GL, GL2, GL3, GL4 {
     }
 
     @Override
-    public void glBindFragDataLocation(int param1, int param2, String param3) {
-        GL30.glBindFragDataLocation(param1, param2, param3);
+    public void glBindFragDataLocation(final int program, final int colorNumber, final String name) {
+        GL30.glBindFragDataLocation(program, colorNumber, name);
     }
 
     @Override
-    public void glBindVertexArray(int param1) {
-        GL30.glBindVertexArray(param1);
+    public void glBindVertexArray(final int array) {
+        GL30.glBindVertexArray(array);
     }
 
     @Override
-    public void glGenVertexArrays(IntBuffer param1) {
-        checkLimit(param1);
-        GL30.glGenVertexArrays(param1);
+    public void glGenVertexArrays(final IntBuffer arrays) {
+        checkLimit(arrays);
+        GL30.glGenVertexArrays(arrays);
     }
 
     @Override
-    public void glPatchParameter(int count) {
-        GL40.glPatchParameteri(GL40.GL_PATCH_VERTICES,count);
+    public void glPatchParameter(final int count) {
+        GL40.glPatchParameteri(GL40.GL_PATCH_VERTICES, count);
     }
-    
+
     @Override
-    public void glDeleteVertexArrays(IntBuffer arrays) {
+    public void glDeleteVertexArrays(final IntBuffer arrays) {
         checkLimit(arrays);
         ARBVertexArrayObject.glDeleteVertexArrays(arrays);
     }

+ 18 - 27
jme3-lwjgl3/src/main/java/com/jme3/renderer/lwjgl/LwjglGLExt.java

@@ -31,74 +31,65 @@
  */
 package com.jme3.renderer.lwjgl;
 
-import com.jme3.renderer.RendererException;
 import com.jme3.renderer.opengl.GLExt;
 import org.lwjgl.opengl.*;
 
-import java.nio.Buffer;
 import java.nio.FloatBuffer;
 import java.nio.IntBuffer;
 
-public class LwjglGLExt implements GLExt {
-
-    private static void checkLimit(Buffer buffer) {
-        if (buffer == null) {
-            return;
-        }
-        if (buffer.limit() == 0) {
-            throw new RendererException("Attempting to upload empty buffer (limit = 0), that's an error");
-        }
-        if (buffer.remaining() == 0) {
-            throw new RendererException("Attempting to upload empty buffer (remaining = 0), that's an error");
-        }
-    }
+/**
+ * The LWJGL implementation og {@link GLExt}.
+ */
+public class LwjglGLExt extends LwjglRender implements GLExt {
 
     @Override
-    public void glBufferData(int target, IntBuffer data, int usage) {
+    public void glBufferData(final int target, final IntBuffer data, final int usage) {
         checkLimit(data);
         GL15.glBufferData(target, data, usage);
     }
 
     @Override
-    public void glBufferSubData(int target, long offset, IntBuffer data) {
+    public void glBufferSubData(final int target, final long offset, final IntBuffer data) {
         checkLimit(data);
         GL15.glBufferSubData(target, offset, data);
     }
 
     @Override
-    public void glDrawArraysInstancedARB(int mode, int first, int count, int primcount) {
-        ARBDrawInstanced.glDrawArraysInstancedARB(mode, first, count, primcount);
+    public void glDrawArraysInstancedARB(final int mode, final int first, final int count, final int primCount) {
+        ARBDrawInstanced.glDrawArraysInstancedARB(mode, first, count, primCount);
     }
 
     @Override
-    public void glDrawBuffers(IntBuffer bufs) {
+    public void glDrawBuffers(final IntBuffer bufs) {
         checkLimit(bufs);
         GL20.glDrawBuffers(bufs);
     }
 
     @Override
-    public void glDrawElementsInstancedARB(int mode, int indices_count, int type, long indices_buffer_offset, int primcount) {
-        ARBDrawInstanced.glDrawElementsInstancedARB(mode, indices_count, type, indices_buffer_offset, primcount);
+    public void glDrawElementsInstancedARB(final int mode, final int indicesCount, final int type,
+                                           final long indicesBufferOffset, final int primCount) {
+        ARBDrawInstanced.glDrawElementsInstancedARB(mode, indicesCount, type, indicesBufferOffset, primCount);
     }
 
     @Override
-    public void glGetMultisample(int pname, int index, FloatBuffer val) {
+    public void glGetMultisample(final int pname, final int index, final FloatBuffer val) {
         checkLimit(val);
         ARBTextureMultisample.glGetMultisamplefv(pname, index, val);
     }
 
     @Override
-    public void glTexImage2DMultisample(int target, int samples, int internalformat, int width, int height, boolean fixedsamplelocations) {
-        ARBTextureMultisample.glTexImage2DMultisample(target, samples, internalformat, width, height, fixedsamplelocations);
+    public void glTexImage2DMultisample(final int target, final int samples, final int internalFormat, final int width,
+                                        final int height, final boolean fixedSampleLocations) {
+        ARBTextureMultisample.glTexImage2DMultisample(target, samples, internalFormat, width, height, fixedSampleLocations);
     }
 
     @Override
-    public void glVertexAttribDivisorARB(int index, int divisor) {
+    public void glVertexAttribDivisorARB(final int index, final int divisor) {
         ARBInstancedArrays.glVertexAttribDivisorARB(index, divisor);
     }
 
     @Override
-    public Object glFenceSync(int condition, int flags) {
+    public Object glFenceSync(final int condition, final int flags) {
         return ARBSync.glFenceSync(condition, flags);
     }
     

+ 54 - 61
jme3-lwjgl3/src/main/java/com/jme3/renderer/lwjgl/LwjglGLFboEXT.java

@@ -31,106 +31,99 @@
  */
 package com.jme3.renderer.lwjgl;
 
-import com.jme3.renderer.RendererException;
 import com.jme3.renderer.opengl.GLFbo;
 import org.lwjgl.opengl.EXTFramebufferBlit;
 import org.lwjgl.opengl.EXTFramebufferMultisample;
 import org.lwjgl.opengl.EXTFramebufferObject;
+import org.lwjgl.opengl.EXTTextureArray;
 
-import java.nio.Buffer;
 import java.nio.IntBuffer;
-import org.lwjgl.opengl.EXTTextureArray;
 
 /**
  * Implements GLFbo via GL_EXT_framebuffer_object.
- * 
+ *
  * @author Kirill Vainer
  */
-public class LwjglGLFboEXT implements GLFbo {
-
-    private static void checkLimit(Buffer buffer) {
-        if (buffer == null) {
-            return;
-        }
-        if (buffer.limit() == 0) {
-            throw new RendererException("Attempting to upload empty buffer (limit = 0), that's an error");
-        }
-        if (buffer.remaining() == 0) {
-            throw new RendererException("Attempting to upload empty buffer (remaining = 0), that's an error");
-        }
-    }
-    
+public class LwjglGLFboEXT extends LwjglRender implements GLFbo {
+
     @Override
-    public void glBlitFramebufferEXT(int srcX0, int srcY0, int srcX1, int srcY1, int dstX0, int dstY0, int dstX1, int dstY1, int mask, int filter) {
+    public void glBlitFramebufferEXT(final int srcX0, final int srcY0, final int srcX1, final int srcY1,
+                                     final int dstX0, final int dstY0, final int dstX1, final int dstY1, final int mask,
+                                     final int filter) {
         EXTFramebufferBlit.glBlitFramebufferEXT(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
     }
-    
+
     @Override
-    public void glRenderbufferStorageMultisampleEXT(int target, int samples, int internalformat, int width, int height) {
-        EXTFramebufferMultisample.glRenderbufferStorageMultisampleEXT(target, samples, internalformat, width, height);
+    public void glRenderbufferStorageMultisampleEXT(final int target, final int samples, final int internalFormat,
+                                                    final int width, final int height) {
+        EXTFramebufferMultisample.glRenderbufferStorageMultisampleEXT(target, samples, internalFormat, width, height);
     }
-    
+
     @Override
-    public void glBindFramebufferEXT(int param1, int param2) {
-        EXTFramebufferObject.glBindFramebufferEXT(param1, param2);
+    public void glBindFramebufferEXT(final int target, final int frameBuffer) {
+        EXTFramebufferObject.glBindFramebufferEXT(target, frameBuffer);
     }
-    
+
     @Override
-    public void glBindRenderbufferEXT(int param1, int param2) {
-        EXTFramebufferObject.glBindRenderbufferEXT(param1, param2);
+    public void glBindRenderbufferEXT(final int target, final int renderBuffer) {
+        EXTFramebufferObject.glBindRenderbufferEXT(target, renderBuffer);
     }
-    
+
     @Override
-    public int glCheckFramebufferStatusEXT(int param1) {
-        return EXTFramebufferObject.glCheckFramebufferStatusEXT(param1);
+    public int glCheckFramebufferStatusEXT(final int target) {
+        return EXTFramebufferObject.glCheckFramebufferStatusEXT(target);
     }
-    
+
     @Override
-    public void glDeleteFramebuffersEXT(IntBuffer param1) {
-        checkLimit(param1);
-        EXTFramebufferObject.glDeleteFramebuffersEXT(param1);
+    public void glDeleteFramebuffersEXT(final IntBuffer frameBuffers) {
+        checkLimit(frameBuffers);
+        EXTFramebufferObject.glDeleteFramebuffersEXT(frameBuffers);
     }
-    
+
     @Override
-    public void glDeleteRenderbuffersEXT(IntBuffer param1) {
-        checkLimit(param1);
-        EXTFramebufferObject.glDeleteRenderbuffersEXT(param1);
+    public void glDeleteRenderbuffersEXT(final IntBuffer renderBuffers) {
+        checkLimit(renderBuffers);
+        EXTFramebufferObject.glDeleteRenderbuffersEXT(renderBuffers);
     }
-    
+
     @Override
-    public void glFramebufferRenderbufferEXT(int param1, int param2, int param3, int param4) {
-        EXTFramebufferObject.glFramebufferRenderbufferEXT(param1, param2, param3, param4);
+    public void glFramebufferRenderbufferEXT(final int target, final int attachment, final int renderBufferTarget,
+                                             final int renderBuffer) {
+        EXTFramebufferObject.glFramebufferRenderbufferEXT(target, attachment, renderBufferTarget, renderBuffer);
     }
-    
+
     @Override
-    public void glFramebufferTexture2DEXT(int param1, int param2, int param3, int param4, int param5) {
-        EXTFramebufferObject.glFramebufferTexture2DEXT(param1, param2, param3, param4, param5);
+    public void glFramebufferTexture2DEXT(final int target, final int attachment, final int texTarget,
+                                          final int texture, final int level) {
+        EXTFramebufferObject.glFramebufferTexture2DEXT(target, attachment, texTarget, texture, level);
     }
-    
+
     @Override
-    public void glGenFramebuffersEXT(IntBuffer param1) {
-        checkLimit(param1);
-        EXTFramebufferObject.glGenFramebuffersEXT(param1);
+    public void glGenFramebuffersEXT(final IntBuffer frameBuffers) {
+        checkLimit(frameBuffers);
+        EXTFramebufferObject.glGenFramebuffersEXT(frameBuffers);
     }
-    
+
     @Override
-    public void glGenRenderbuffersEXT(IntBuffer param1) {
-        checkLimit(param1);
-        EXTFramebufferObject.glGenRenderbuffersEXT(param1);
+    public void glGenRenderbuffersEXT(final IntBuffer renderBuffers) {
+        checkLimit(renderBuffers);
+        EXTFramebufferObject.glGenRenderbuffersEXT(renderBuffers);
     }
-    
+
     @Override
-    public void glGenerateMipmapEXT(int param1) {
-        EXTFramebufferObject.glGenerateMipmapEXT(param1);
+    public void glGenerateMipmapEXT(final int target) {
+        EXTFramebufferObject.glGenerateMipmapEXT(target);
     }
-    
+
     @Override
-    public void glRenderbufferStorageEXT(int param1, int param2, int param3, int param4) {
-        EXTFramebufferObject.glRenderbufferStorageEXT(param1, param2, param3, param4);
+    public void glRenderbufferStorageEXT(final int target, final int internalFormat, final int width,
+                                         final int height) {
+        EXTFramebufferObject.glRenderbufferStorageEXT(target, internalFormat, width, height);
     }
-    
+
     @Override
-    public void glFramebufferTextureLayerEXT(int target, int attachment, int texture, int level, int layer) {
+    public void glFramebufferTextureLayerEXT(final int target, final int attachment, final int texture, final int level,
+                                             final int layer) {
         EXTTextureArray.glFramebufferTextureLayerEXT(target, attachment, texture, level, layer);
     }
 }

+ 54 - 61
jme3-lwjgl3/src/main/java/com/jme3/renderer/lwjgl/LwjglGLFboGL3.java

@@ -31,103 +31,96 @@
  */
 package com.jme3.renderer.lwjgl;
 
-import com.jme3.renderer.RendererException;
 import com.jme3.renderer.opengl.GLFbo;
 import org.lwjgl.opengl.GL30;
 
-import java.nio.Buffer;
 import java.nio.IntBuffer;
 
 /**
  * Implements GLFbo via OpenGL3+.
- * 
+ *
  * @author Kirill Vainer
  */
-public class LwjglGLFboGL3 implements GLFbo {
-
-    private static void checkLimit(Buffer buffer) {
-        if (buffer == null) {
-            return;
-        }
-        if (buffer.limit() == 0) {
-            throw new RendererException("Attempting to upload empty buffer (limit = 0), that's an error");
-        }
-        if (buffer.remaining() == 0) {
-            throw new RendererException("Attempting to upload empty buffer (remaining = 0), that's an error");
-        }
-    }
-    
+public class LwjglGLFboGL3 extends LwjglRender implements GLFbo {
+
     @Override
-    public void glBlitFramebufferEXT(int srcX0, int srcY0, int srcX1, int srcY1, int dstX0, int dstY0, int dstX1, int dstY1, int mask, int filter) {
+    public void glBlitFramebufferEXT(final int srcX0, final int srcY0, final int srcX1, final int srcY1,
+                                     final int dstX0, final int dstY0, final int dstX1, final int dstY1, final int mask,
+                                     final int filter) {
         GL30.glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
     }
-    
+
     @Override
-    public void glRenderbufferStorageMultisampleEXT(int target, int samples, int internalformat, int width, int height) {
-        GL30.glRenderbufferStorageMultisample(target, samples, internalformat, width, height);
+    public void glRenderbufferStorageMultisampleEXT(final int target, final int samples, final int internalFormat,
+                                                    final int width, final int height) {
+        GL30.glRenderbufferStorageMultisample(target, samples, internalFormat, width, height);
     }
-    
+
     @Override
-    public void glBindFramebufferEXT(int param1, int param2) {
-        GL30.glBindFramebuffer(param1, param2);
+    public void glBindFramebufferEXT(final int target, final int frameBuffer) {
+        GL30.glBindFramebuffer(target, frameBuffer);
     }
-    
+
     @Override
-    public void glBindRenderbufferEXT(int param1, int param2) {
-        GL30.glBindRenderbuffer(param1, param2);
+    public void glBindRenderbufferEXT(final int target, final int renderBuffer) {
+        GL30.glBindRenderbuffer(target, renderBuffer);
     }
-    
+
     @Override
-    public int glCheckFramebufferStatusEXT(int param1) {
-        return GL30.glCheckFramebufferStatus(param1);
+    public int glCheckFramebufferStatusEXT(final int target) {
+        return GL30.glCheckFramebufferStatus(target);
     }
-    
+
     @Override
-    public void glDeleteFramebuffersEXT(IntBuffer param1) {
-        checkLimit(param1);
-        GL30.glDeleteFramebuffers(param1);
+    public void glDeleteFramebuffersEXT(final IntBuffer frameBuffers) {
+        checkLimit(frameBuffers);
+        GL30.glDeleteFramebuffers(frameBuffers);
     }
-    
+
     @Override
-    public void glDeleteRenderbuffersEXT(IntBuffer param1) {
-        checkLimit(param1);
-        GL30.glDeleteRenderbuffers(param1);
+    public void glDeleteRenderbuffersEXT(final IntBuffer renderBuffers) {
+        checkLimit(renderBuffers);
+        GL30.glDeleteRenderbuffers(renderBuffers);
     }
-    
+
     @Override
-    public void glFramebufferRenderbufferEXT(int param1, int param2, int param3, int param4) {
-        GL30.glFramebufferRenderbuffer(param1, param2, param3, param4);
+    public void glFramebufferRenderbufferEXT(final int target, final int attachment, final int renderBufferTarget,
+                                             final int renderBuffer) {
+        GL30.glFramebufferRenderbuffer(target, attachment, renderBufferTarget, renderBuffer);
     }
-    
+
     @Override
-    public void glFramebufferTexture2DEXT(int param1, int param2, int param3, int param4, int param5) {
-        GL30.glFramebufferTexture2D(param1, param2, param3, param4, param5);
+    public void glFramebufferTexture2DEXT(final int target, final int attachment, final int texTarget,
+                                          final int texture, final int level) {
+        GL30.glFramebufferTexture2D(target, attachment, texTarget, texture, level);
     }
-    
+
     @Override
-    public void glGenFramebuffersEXT(IntBuffer param1) {
-        checkLimit(param1);
-        GL30.glGenFramebuffers(param1);
+    public void glGenFramebuffersEXT(final IntBuffer frameBuffers) {
+        checkLimit(frameBuffers);
+        GL30.glGenFramebuffers(frameBuffers);
     }
-    
+
     @Override
-    public void glGenRenderbuffersEXT(IntBuffer param1) {
-        checkLimit(param1);
-        GL30.glGenRenderbuffers(param1);
+    public void glGenRenderbuffersEXT(final IntBuffer renderBuffers) {
+        checkLimit(renderBuffers);
+        GL30.glGenRenderbuffers(renderBuffers);
     }
-    
+
     @Override
-    public void glGenerateMipmapEXT(int param1) {
-        GL30.glGenerateMipmap(param1);
+    public void glGenerateMipmapEXT(final int target) {
+        GL30.glGenerateMipmap(target);
     }
-    
+
     @Override
-    public void glRenderbufferStorageEXT(int param1, int param2, int param3, int param4) {
-        GL30.glRenderbufferStorage(param1, param2, param3, param4);
+    public void glRenderbufferStorageEXT(final int target, final int internalFormat, final int width,
+                                         final int height) {
+        GL30.glRenderbufferStorage(target, internalFormat, width, height);
     }
-    
+
     @Override
-    public void glFramebufferTextureLayerEXT(int param1, int param2, int param3, int param4, int param5) {
-        GL30.glFramebufferTextureLayer(param1, param2, param3, param4, param5);
+    public void glFramebufferTextureLayerEXT(final int target, final int attachment, final int texture, final int level,
+                                             final int layer) {
+        GL30.glFramebufferTextureLayer(target, attachment, texture, level, layer);
     }
 }

+ 25 - 0
jme3-lwjgl3/src/main/java/com/jme3/renderer/lwjgl/LwjglRender.java

@@ -0,0 +1,25 @@
+package com.jme3.renderer.lwjgl;
+
+import com.jme3.renderer.RendererException;
+
+import java.nio.Buffer;
+
+/**
+ * The base class of LWJGL implementations.
+ *
+ * @author JavaSaBr
+ */
+public class LwjglRender {
+
+    protected static void checkLimit(final Buffer buffer) {
+        if (buffer == null) {
+            return;
+        }
+        if (buffer.limit() == 0) {
+            throw new RendererException("Attempting to upload empty buffer (limit = 0), that's an error");
+        }
+        if (buffer.remaining() == 0) {
+            throw new RendererException("Attempting to upload empty buffer (remaining = 0), that's an error");
+        }
+    }
+}

+ 170 - 146
jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglContext.java

@@ -33,12 +33,14 @@
 package com.jme3.system.lwjgl;
 
 import static com.jme3.util.LWJGLBufferAllocator.PROPERTY_CONCURRENT_BUFFER_ALLOCATOR;
+import static java.util.stream.Collectors.toSet;
 import static org.lwjgl.opencl.CL10.CL_CONTEXT_PLATFORM;
 import static org.lwjgl.opengl.GL.createCapabilities;
 import static org.lwjgl.opengl.GL11.glGetInteger;
 import com.jme3.input.lwjgl.GlfwJoystickInput;
 import com.jme3.input.lwjgl.GlfwKeyInput;
 import com.jme3.input.lwjgl.GlfwMouseInput;
+import com.jme3.lwjgl3.utils.APIUtil;
 import com.jme3.opencl.Context;
 import com.jme3.opencl.DefaultPlatformChooser;
 import com.jme3.opencl.Device;
@@ -61,6 +63,7 @@ import com.jme3.util.BufferAllocatorFactory;
 import com.jme3.util.LWJGLBufferAllocator;
 import com.jme3.util.LWJGLBufferAllocator.ConcurrentLWJGLBufferAllocator;
 import org.lwjgl.PointerBuffer;
+import org.lwjgl.Version;
 import org.lwjgl.glfw.GLFW;
 import org.lwjgl.opencl.APPLEGLSharing;
 import org.lwjgl.opencl.CL10;
@@ -69,11 +72,11 @@ import org.lwjgl.opengl.ARBDebugOutput;
 import org.lwjgl.opengl.ARBFramebufferObject;
 import org.lwjgl.opengl.EXTFramebufferMultisample;
 import org.lwjgl.opengl.GLCapabilities;
+import org.lwjgl.system.MemoryStack;
 import org.lwjgl.system.Platform;
 
 import java.nio.IntBuffer;
-import java.util.ArrayList;
-import java.util.List;
+import java.util.*;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.logging.Level;
 import java.util.logging.Logger;
@@ -98,35 +101,48 @@ public abstract class LwjglContext implements JmeContext {
         }
     }
 
+    private static final Set<String> SUPPORTED_RENDERS = new HashSet<>(Arrays.asList(
+            AppSettings.LWJGL_OPENGL2,
+            AppSettings.LWJGL_OPENGL3,
+            AppSettings.LWJGL_OPENGL33,
+            AppSettings.LWJGL_OPENGL4,
+            AppSettings.LWJGL_OPENGL41,
+            AppSettings.LWJGL_OPENGL42,
+            AppSettings.LWJGL_OPENGL43,
+            AppSettings.LWJGL_OPENGL44,
+            AppSettings.LWJGL_OPENGL45
+    ));
+
     public static final boolean CL_GL_SHARING_POSSIBLE = true;
-    
-    protected static final String THREAD_NAME = "jME3 Main";
 
-    protected AtomicBoolean created = new AtomicBoolean(false);
-    protected AtomicBoolean renderable = new AtomicBoolean(false);
     protected final Object createdLock = new Object();
+    protected final AtomicBoolean created = new AtomicBoolean(false);
+    protected final AtomicBoolean renderable = new AtomicBoolean(false);
+    protected final AppSettings settings = new AppSettings(true);
 
-    protected AppSettings settings = new AppSettings(true);
-    protected Renderer renderer;
     protected GlfwKeyInput keyInput;
     protected GlfwMouseInput mouseInput;
     protected GlfwJoystickInput joyInput;
+
     protected Timer timer;
+
+    protected Renderer renderer;
     protected SystemListener listener;
     
     protected com.jme3.opencl.lwjgl.LwjglContext clContext;
 
-    public void setSystemListener(SystemListener listener) {
+    @Override
+    public void setSystemListener(final SystemListener listener) {
         this.listener = listener;
     }
 
     protected void printContextInitInfo() {
-        logger.log(Level.INFO, "LWJGL {0} context running on thread {1}\n"
-                        + " * Graphics Adapter: GLFW {2}",
-                new Object[]{org.lwjgl.Version.getVersion(), Thread.currentThread().getName(), GLFW.glfwGetVersionString()});
+        logger.log(Level.INFO, "LWJGL {0} context running on thread {1}\n * Graphics Adapter: GLFW {2}",
+                APIUtil.toArray(Version.getVersion(), Thread.currentThread().getName(), GLFW.glfwGetVersionString()));
     }
 
     protected int determineMaxSamples() {
+
         // If we already have a valid context, determine samples using current context.
         if (GLFW.glfwExtensionSupported("GL_ARB_framebuffer_object")) {
             return glGetInteger(ARBFramebufferObject.GL_MAX_SAMPLES);
@@ -138,19 +154,19 @@ public abstract class LwjglContext implements JmeContext {
     }
 
     protected int getNumSamplesToUse() {
+
         int samples = 0;
+
         if (settings.getSamples() > 1) {
             samples = settings.getSamples();
             final int supportedSamples = determineMaxSamples();
             if (supportedSamples < samples) {
-                logger.log(Level.WARNING,
-                        "Couldn't satisfy antialiasing samples requirement: x{0}. "
-                                + "Video hardware only supports: x{1}",
-                        new Object[]{samples, supportedSamples});
-
+                logger.log(Level.WARNING, "Couldn't satisfy antialiasing samples requirement: x{0}. " +
+                        "Video hardware only supports: x{1}", APIUtil.toArray(samples, supportedSamples));
                 samples = supportedSamples;
             }
         }
+
         return samples;
     }
 
@@ -161,53 +177,42 @@ public abstract class LwjglContext implements JmeContext {
 
         if (!capabilities.OpenGL20) {
             throw new RendererException("OpenGL 2.0 or higher is required for jMonkeyEngine");
+        } else if (!SUPPORTED_RENDERS.contains(renderer)) {
+            throw new UnsupportedOperationException("Unsupported renderer: " + renderer);
         }
 
-        if (renderer.equals(AppSettings.LWJGL_OPENGL2)
-                || renderer.equals(AppSettings.LWJGL_OPENGL3)
-                || renderer.equals(AppSettings.LWJGL_OPENGL33)
-                || renderer.equals(AppSettings.LWJGL_OPENGL4)
-                || renderer.equals(AppSettings.LWJGL_OPENGL41)
-                || renderer.equals(AppSettings.LWJGL_OPENGL42)
-                || renderer.equals(AppSettings.LWJGL_OPENGL43)
-                || renderer.equals(AppSettings.LWJGL_OPENGL44)
-                || renderer.equals(AppSettings.LWJGL_OPENGL45)) {
-
-            GL gl = new LwjglGL();
-            GLExt glext = new LwjglGLExt();
-            GLFbo glfbo;
-
-            if (capabilities.OpenGL30) {
-                glfbo = new LwjglGLFboGL3();
-            } else {
-                glfbo = new LwjglGLFboEXT();
-            }
+        GL gl = new LwjglGL();
+        GLExt glext = new LwjglGLExt();
+        GLFbo glfbo;
 
-            if (settings.getBoolean("GraphicsDebug")) {
-                gl = new GLDebugDesktop(gl, glext, glfbo);
-                glext = (GLExt) gl;
-                glfbo = (GLFbo) gl;
-            }
+        if (capabilities.OpenGL30) {
+            glfbo = new LwjglGLFboGL3();
+        } else {
+            glfbo = new LwjglGLFboEXT();
+        }
 
-            if (settings.getBoolean("GraphicsTiming")) {
-                GLTimingState timingState = new GLTimingState();
-                gl = (GL) GLTiming.createGLTiming(gl, timingState, GL.class, GL2.class, GL3.class, GL4.class);
-                glext = (GLExt) GLTiming.createGLTiming(glext, timingState, GLExt.class);
-                glfbo = (GLFbo) GLTiming.createGLTiming(glfbo, timingState, GLFbo.class);
-            }
+        if (settings.getBoolean("GraphicsDebug")) {
+            gl = new GLDebugDesktop(gl, glext, glfbo);
+            glext = (GLExt) gl;
+            glfbo = (GLFbo) gl;
+        }
 
-            if (settings.getBoolean("GraphicsTrace")) {
-                gl = (GL) GLTracer.createDesktopGlTracer(gl, GL.class, GL2.class, GL3.class, GL4.class);
-                glext = (GLExt) GLTracer.createDesktopGlTracer(glext, GLExt.class);
-                glfbo = (GLFbo) GLTracer.createDesktopGlTracer(glfbo, GLFbo.class);
-            }
+        if (settings.getBoolean("GraphicsTiming")) {
+            GLTimingState timingState = new GLTimingState();
+            gl = (GL) GLTiming.createGLTiming(gl, timingState, GL.class, GL2.class, GL3.class, GL4.class);
+            glext = (GLExt) GLTiming.createGLTiming(glext, timingState, GLExt.class);
+            glfbo = (GLFbo) GLTiming.createGLTiming(glfbo, timingState, GLFbo.class);
+        }
 
-            this.renderer = new GLRenderer(gl, glext, glfbo);
-            this.renderer.initialize();
-        } else {
-            throw new UnsupportedOperationException("Unsupported renderer: " + renderer);
+        if (settings.getBoolean("GraphicsTrace")) {
+            gl = (GL) GLTracer.createDesktopGlTracer(gl, GL.class, GL2.class, GL3.class, GL4.class);
+            glext = (GLExt) GLTracer.createDesktopGlTracer(glext, GLExt.class);
+            glfbo = (GLFbo) GLTracer.createDesktopGlTracer(glfbo, GLFbo.class);
         }
 
+        this.renderer = new GLRenderer(gl, glext, glfbo);
+        this.renderer.initialize();
+
         if (capabilities.GL_ARB_debug_output && settings.getBoolean("GraphicsDebug")) {
             ARBDebugOutput.glDebugMessageCallbackARB(new LwjglGLDebugOutputHandler(), 0);
         }
@@ -227,42 +232,41 @@ public abstract class LwjglContext implements JmeContext {
         if (joyInput != null) {
             joyInput.initialize();
         }
+
         renderable.set(true);
-        
     }
 
     /**
      * Returns a list of the available platforms, filtered by the specified
      * filter.
-     *
+     * <p>
      * Copied from the old release
      *
      * @return the available platforms
      */
     private static long[] getPlatforms() {
-        int[] count = new int[1];
-        int errcode = CL10.clGetPlatformIDs(null, count);
-        Utils.checkError(errcode, "clGetDeviceIDs");
+        try (MemoryStack stack = MemoryStack.stackPush()) {
 
-        int num_platforms = count[0];
-        if (num_platforms == 0) {
-            return new long[0];
-        }
+            final IntBuffer countBuffer = stack.callocInt(1);
+            int errcode = CL10.clGetPlatformIDs(null, countBuffer);
+            Utils.checkError(errcode, "clGetDeviceIDs");
 
-        PointerBuffer platforms = PointerBuffer.allocateDirect(num_platforms);
-        errcode = CL10.clGetPlatformIDs(platforms, (IntBuffer) null);
-        Utils.checkError(errcode, "clGetDeviceIDs");
+            final int count = countBuffer.get();
+            final PointerBuffer pointer = stack.callocPointer(count);
 
-        platforms.rewind();
-        long[] platformIDs = new long[num_platforms];
-        for (int i = 0; i < num_platforms; i++) {
-            platformIDs[i] = platforms.get();
-        }
+            errcode = CL10.clGetPlatformIDs(pointer, (IntBuffer) null);
+            Utils.checkError(errcode, "clGetDeviceIDs");
+
+            final long[] platformIDs = new long[count];
+            for (int i = 0; i < count; i++) {
+                platformIDs[i] = pointer.get();
+            }
 
-        return platformIDs;
+            return platformIDs;
+        }
     }
 
-    protected void initOpenCL(long window) {
+    protected void initOpenCL(final long window) {
         logger.info("Initialize OpenCL with LWJGL3");
         
 //        try {
@@ -272,16 +276,18 @@ public abstract class LwjglContext implements JmeContext {
 //            return;
 //        }
         
-        //load platforms and devices
+        // load platforms and devices
         StringBuilder platformInfos = new StringBuilder();
-        ArrayList<LwjglPlatform> platforms = new ArrayList<>();
-        for (long p : getPlatforms()) {
-            platforms.add(new LwjglPlatform(p));
+        List<LwjglPlatform> platforms = new ArrayList<>();
+        for (long platformId : getPlatforms()) {
+            platforms.add(new LwjglPlatform(platformId));
         }
+
         platformInfos.append("Available OpenCL platforms:");
-        for (int i=0; i<platforms.size(); ++i) {
+
+        for (int i = 0; i < platforms.size(); ++i) {
             LwjglPlatform platform = platforms.get(i);
-            platformInfos.append("\n * Platform ").append(i+1);
+            platformInfos.append("\n * Platform ").append(i + 1);
             platformInfos.append("\n *   Name: ").append(platform.getName());
             platformInfos.append("\n *   Vendor: ").append(platform.getVendor());
             platformInfos.append("\n *   Version: ").append(platform.getVersion());
@@ -291,7 +297,7 @@ public abstract class LwjglContext implements JmeContext {
             platformInfos.append("\n *   Available devices:");
             for (int j=0; j<devices.size(); ++j) {
                 LwjglDevice device = devices.get(j);
-                platformInfos.append("\n *    * Device ").append(j+1);
+                platformInfos.append("\n *    * Device ").append(j + 1);
                 platformInfos.append("\n *    *   Name: ").append(device.getName());
                 platformInfos.append("\n *    *   Vendor: ").append(device.getVendor());
                 platformInfos.append("\n *    *   Version: ").append(device.getVersion());
@@ -309,6 +315,7 @@ public abstract class LwjglContext implements JmeContext {
                 platformInfos.append("\n *    *   Supports interop: ").append(device.hasOpenGLInterop());
             }
         }
+
         logger.info(platformInfos.toString());
         
         //choose devices
@@ -317,40 +324,56 @@ public abstract class LwjglContext implements JmeContext {
             try {
                 chooser = (PlatformChooser) Class.forName(settings.getOpenCLPlatformChooser()).newInstance();
             } catch (Exception ex) {
-                logger.log(Level.WARNING, "unable to instantiate custom PlatformChooser", ex);
+                logger.log(Level.WARNING, "Unable to instantiate custom PlatformChooser", ex);
             }
         }
+
         if (chooser == null) {
             chooser = new DefaultPlatformChooser();
         }
-        List<? extends Device> choosenDevices = chooser.chooseDevices(platforms);
-        List<Long> devices = new ArrayList<>(choosenDevices.size());
-        LwjglPlatform platform = null;
-        for (Device d : choosenDevices) {
-            if (!(d instanceof LwjglDevice)) {
-                logger.log(Level.SEVERE, "attempt to return a custom Device implementation from PlatformChooser: {0}", d);
-                return;
-            }
-            LwjglDevice ld = (LwjglDevice) d;
-            if (platform == null) {
-                platform = ld.getPlatform();
-            } else if (platform != ld.getPlatform()) {
-                logger.severe("attempt to use devices from different platforms");
-                return;
-            }
-            devices.add(ld.getDevice());
+
+        final List<? extends Device> choosenDevices = chooser.chooseDevices(platforms);
+        final Optional<? extends Device> unsupportedDevice = choosenDevices.stream()
+                .filter(dev -> !(dev instanceof LwjglDevice))
+                .findAny();
+
+        if (unsupportedDevice.isPresent()) {
+            logger.log(Level.SEVERE, "attempt to return a custom Device implementation " +
+                    "from PlatformChooser: {0}", unsupportedDevice.get());
+            return;
+        }
+
+        final Set<LwjglPlatform> lwjglPlatforms = choosenDevices.stream()
+                .map(LwjglDevice.class::cast)
+                .map(LwjglDevice::getPlatform)
+                .collect(toSet());
+
+        if (lwjglPlatforms.size() != 1) {
+            logger.severe("attempt to use devices from different platforms");
+            return;
         }
-        if (devices.isEmpty()) {
+
+        final long[] deviceIds = choosenDevices.stream()
+                .map(LwjglDevice.class::cast)
+                .mapToLong(LwjglDevice::getDevice)
+                .toArray();
+
+        if (deviceIds.length < 1) {
             logger.warning("no devices specified, no OpenCL context created");
             return;
         }
+
+        final LwjglPlatform platform = lwjglPlatforms.stream()
+                .findFirst()
+                .orElseThrow(() -> new RuntimeException("not found a platform"));
+
         logger.log(Level.INFO, "chosen platform: {0}", platform.getName());
         logger.log(Level.INFO, "chosen devices: {0}", choosenDevices);
         
-        //create context
+        // create context
         try {
-            long c = createContext(platform.getPlatform(), devices, window);
-            clContext = new com.jme3.opencl.lwjgl.LwjglContext(c, (List<LwjglDevice>) choosenDevices);
+            long context = createContext(platform.getPlatform(), deviceIds, window);
+            clContext = new com.jme3.opencl.lwjgl.LwjglContext(context, (List<LwjglDevice>) choosenDevices);
         } catch (final Exception ex) {
             logger.log(Level.SEVERE, "Unable to create OpenCL context", ex);
             return;
@@ -358,50 +381,52 @@ public abstract class LwjglContext implements JmeContext {
         
         logger.info("OpenCL context created");
     }
-    private long createContext(final long platform, final List<Long> devices, long window) throws Exception {
-        
-        final int propertyCount = 2 + 4 + 1;
 
-        final PointerBuffer properties = PointerBuffer.allocateDirect(propertyCount + devices.size());
-        
-        //set sharing properties
-        //https://github.com/glfw/glfw/issues/104
-        //https://github.com/LWJGL/lwjgl3/blob/master/modules/core/src/test/java/org/lwjgl/demo/opencl/Mandelbrot.java
-        //TODO: test on Linus and MacOSX
-        switch (Platform.get()) {
-            case WINDOWS:
-                properties
-                        .put(KHRGLSharing.CL_GL_CONTEXT_KHR)
-                        .put(org.lwjgl.glfw.GLFWNativeWGL.glfwGetWGLContext(window))
-                        .put(KHRGLSharing.CL_WGL_HDC_KHR)
-                        .put(org.lwjgl.opengl.WGL.wglGetCurrentDC());
-                break;
-            case LINUX:
-                properties
-                        .put(KHRGLSharing.CL_GL_CONTEXT_KHR)
-                        .put(org.lwjgl.glfw.GLFWNativeGLX.glfwGetGLXContext(window))
-                        .put(KHRGLSharing.CL_GLX_DISPLAY_KHR)
-                        .put(org.lwjgl.glfw.GLFWNativeX11.glfwGetX11Display());
-                break;
-            case MACOSX:
-                properties
-                        .put(APPLEGLSharing.CL_CONTEXT_PROPERTY_USE_CGL_SHAREGROUP_APPLE)
-                        .put(org.lwjgl.opengl.CGL.CGLGetShareGroup(org.lwjgl.opengl.CGL.CGLGetCurrentContext()));
-        }
-        properties.put(CL_CONTEXT_PLATFORM).put(platform);
-        properties.put(0);
-        properties.flip();
-
-        Utils.errorBuffer.rewind();
-        PointerBuffer deviceBuffer = PointerBuffer.allocateDirect(devices.size());
-        for (long d : devices) {
-            deviceBuffer.put(d);
+    private long createContext(final long platform, final long[] devices, long window) {
+        try (MemoryStack stack = MemoryStack.stackPush()) {
+
+            final int propertyCount = 2 + 4 + 1;
+            final PointerBuffer properties = stack.callocPointer(propertyCount + devices.length);
+
+            // set sharing properties
+            // https://github.com/glfw/glfw/issues/104
+            // https://github.com/LWJGL/lwjgl3/blob/master/modules/core/src/test/java/org/lwjgl/demo/opencl/Mandelbrot.java
+            // TODO: test on Linux and MacOSX
+            switch (Platform.get()) {
+                case WINDOWS:
+                    properties.put(KHRGLSharing.CL_GL_CONTEXT_KHR)
+                            .put(org.lwjgl.glfw.GLFWNativeWGL.glfwGetWGLContext(window))
+                            .put(KHRGLSharing.CL_WGL_HDC_KHR)
+                            .put(org.lwjgl.opengl.WGL.wglGetCurrentDC());
+                    break;
+                case LINUX:
+                    properties.put(KHRGLSharing.CL_GL_CONTEXT_KHR)
+                            .put(org.lwjgl.glfw.GLFWNativeGLX.glfwGetGLXContext(window))
+                            .put(KHRGLSharing.CL_GLX_DISPLAY_KHR)
+                            .put(org.lwjgl.glfw.GLFWNativeX11.glfwGetX11Display());
+                    break;
+                case MACOSX:
+                    properties.put(APPLEGLSharing.CL_CONTEXT_PROPERTY_USE_CGL_SHAREGROUP_APPLE)
+                            .put(org.lwjgl.opengl.CGL.CGLGetShareGroup(org.lwjgl.opengl.CGL.CGLGetCurrentContext()));
+            }
+
+            properties.put(CL_CONTEXT_PLATFORM).put(platform);
+            properties.put(0);
+            properties.flip();
+
+            final IntBuffer error = stack.callocInt(1);
+            final PointerBuffer deviceBuffer = stack.callocPointer(devices.length);
+            for (final long deviceId : devices) {
+                deviceBuffer.put(deviceId);
+            }
+
+            deviceBuffer.flip();
+
+            long context = CL10.clCreateContext(properties, deviceBuffer, null, 0, error);
+            Utils.checkError(error, "clCreateContext");
+
+            return context;
         }
-        deviceBuffer.flip();
-        long context = CL10.clCreateContext(properties, deviceBuffer, null, 0, Utils.errorBuffer);
-        Utils.checkError(Utils.errorBuffer, "clCreateContext");
-        
-        return context;
     }
 
     public void internalDestroy() {
@@ -419,7 +444,6 @@ public abstract class LwjglContext implements JmeContext {
             created.set(true);
             createdLock.notifyAll();
         }
-
         initContextFirstTime();
     }
 

+ 0 - 10
jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglGLDebugOutputHandler.java

@@ -75,14 +75,4 @@ class LwjglGLDebugOutputHandler extends GLDebugMessageARBCallback {
 
         System.err.println(String.format(MESSAGE_FORMAT, id, sourceStr, typeStr, severityStr, message));
     }
-
-    @Override
-    public void close() {
-        super.close();
-    }
-
-    @Override
-    public void callback(long args) {
-        super.callback(args);
-    }
 }

+ 61 - 68
jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglWindow.java

@@ -53,6 +53,9 @@ import org.lwjgl.glfw.*;
 import java.awt.*;
 import java.awt.image.BufferedImage;
 import java.nio.ByteBuffer;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.Map;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.logging.Level;
 import java.util.logging.Logger;
@@ -66,6 +69,48 @@ public abstract class LwjglWindow extends LwjglContext implements Runnable {
 
     private static final Logger LOGGER = Logger.getLogger(LwjglWindow.class.getName());
 
+    private static final EnumSet<JmeContext.Type> SUPPORTED_TYPES = EnumSet.of(
+            JmeContext.Type.Display,
+            JmeContext.Type.Canvas,
+            JmeContext.Type.OffscreenSurface);
+
+    private static final Map<String, Runnable> RENDER_CONFIGS = new HashMap<>();
+
+    static {
+        RENDER_CONFIGS.put(AppSettings.LWJGL_OPENGL3, () -> {
+            glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
+            glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
+        });
+        RENDER_CONFIGS.put(AppSettings.LWJGL_OPENGL33, () -> {
+            glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
+            glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
+        });
+        RENDER_CONFIGS.put(AppSettings.LWJGL_OPENGL4, () -> {
+            glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
+            glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
+        });
+        RENDER_CONFIGS.put(AppSettings.LWJGL_OPENGL41, () -> {
+            glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
+            glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
+        });
+        RENDER_CONFIGS.put(AppSettings.LWJGL_OPENGL42, () -> {
+            glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
+            glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
+        });
+        RENDER_CONFIGS.put(AppSettings.LWJGL_OPENGL43, () -> {
+            glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
+            glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
+        });
+        RENDER_CONFIGS.put(AppSettings.LWJGL_OPENGL44, () -> {
+            glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
+            glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 4);
+        });
+        RENDER_CONFIGS.put(AppSettings.LWJGL_OPENGL45, () -> {
+            glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
+            glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 5);
+        });
+    }
+
     protected final AtomicBoolean needClose = new AtomicBoolean(false);
     protected final AtomicBoolean needRestart = new AtomicBoolean(false);
 
@@ -86,7 +131,8 @@ public abstract class LwjglWindow extends LwjglContext implements Runnable {
     protected boolean allowSwapBuffers = false;
 
     public LwjglWindow(final JmeContext.Type type) {
-        if (!JmeContext.Type.Display.equals(type) && !JmeContext.Type.OffscreenSurface.equals(type) && !JmeContext.Type.Canvas.equals(type)) {
+
+        if (!SUPPORTED_TYPES.contains(type)) {
             throw new IllegalArgumentException("Unsupported type '" + type.name() + "' provided");
         }
 
@@ -134,16 +180,6 @@ public abstract class LwjglWindow extends LwjglContext implements Runnable {
                 final String message = GLFWErrorCallback.getDescription(description);
                 listener.handleError(message, new Exception(message));
             }
-
-            @Override
-            public void close(){
-                super.close();
-            }
-
-            @Override
-            public void callback(long args) {
-                super.callback(args);
-            }
         });
 
         if (!glfwInit()) {
@@ -157,36 +193,12 @@ public abstract class LwjglWindow extends LwjglContext implements Runnable {
         glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE);
         glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
 
-        if (renderer.equals(AppSettings.LWJGL_OPENGL3)) {
-            glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
-            glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
-        } else if (renderer.equals(AppSettings.LWJGL_OPENGL33)) {
-            glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
-            glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
-        } else if (renderer.equals(AppSettings.LWJGL_OPENGL4)) {
-            glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
-            glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
-        } else if (renderer.equals(AppSettings.LWJGL_OPENGL41)) {
-            glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
-            glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
-        } else if (renderer.equals(AppSettings.LWJGL_OPENGL42)) {
-            glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
-            glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
-        } else if (renderer.equals(AppSettings.LWJGL_OPENGL43)) {
-            glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
-            glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
-        } else if (renderer.equals(AppSettings.LWJGL_OPENGL44)) {
-            glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
-            glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 4);
-        } else if (renderer.equals(AppSettings.LWJGL_OPENGL45)) {
-            glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
-            glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 5);
-        } else {
+        RENDER_CONFIGS.computeIfAbsent(renderer, s -> () -> {
             glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_FALSE);
             glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_ANY_PROFILE);
             glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
             glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
-        }
+        }).run();
 
         if (settings.getBoolean("RendererDebug")) {
             glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GLFW_TRUE);
@@ -242,16 +254,6 @@ public abstract class LwjglWindow extends LwjglContext implements Runnable {
                 settings.setResolution(width, height);
                 listener.reshape(width, height);
             }
-
-            @Override
-            public void close() {
-                super.close();
-            }
-
-            @Override
-            public void callback(long args) {
-                super.callback(args);
-            }
         });
 
         glfwSetWindowFocusCallback(window, windowFocusCallback = new GLFWWindowFocusCallback() {
@@ -264,20 +266,9 @@ public abstract class LwjglWindow extends LwjglContext implements Runnable {
                     } else {
                         listener.loseFocus();
                     }
-
                     wasActive = !wasActive;
                 }
             }
-
-            @Override
-            public void close() {
-                super.close();
-            }
-
-            @Override
-            public void callback(long args) {
-                super.callback(args);
-            }
         });
 
         // Center the window
@@ -434,15 +425,12 @@ public abstract class LwjglWindow extends LwjglContext implements Runnable {
         try {
             if (!JmeSystem.isLowPermissions()) {
                 // Enable uncaught exception handler only for current thread
-                Thread.currentThread().setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
-                    @Override
-                    public void uncaughtException(Thread thread, Throwable thrown) {
-                        listener.handleError("Uncaught exception thrown in " + thread.toString(), thrown);
-                        if (needClose.get()) {
-                            // listener.handleError() has requested the
-                            // context to close. Satisfy request.
-                            deinitInThread();
-                        }
+                Thread.currentThread().setUncaughtExceptionHandler((thread, thrown) -> {
+                    listener.handleError("Uncaught exception thrown in " + thread.toString(), thrown);
+                    if (needClose.get()) {
+                        // listener.handleError() has requested the
+                        // context to close. Satisfy request.
+                        deinitInThread();
                     }
                 });
             }
@@ -600,6 +588,7 @@ public abstract class LwjglWindow extends LwjglContext implements Runnable {
         deinitInThread();
     }
 
+    @Override
     public JoyInput getJoyInput() {
         if (joyInput == null) {
             joyInput = new GlfwJoystickInput();
@@ -607,6 +596,7 @@ public abstract class LwjglWindow extends LwjglContext implements Runnable {
         return joyInput;
     }
 
+    @Override
     public MouseInput getMouseInput() {
         if (mouseInput == null) {
             mouseInput = new GlfwMouseInput(this);
@@ -614,22 +604,25 @@ public abstract class LwjglWindow extends LwjglContext implements Runnable {
         return mouseInput;
     }
 
+    @Override
     public KeyInput getKeyInput() {
         if (keyInput == null) {
             keyInput = new GlfwKeyInput(this);
         }
-
         return keyInput;
     }
 
+    @Override
     public TouchInput getTouchInput() {
         return null;
     }
 
+    @Override
     public void setAutoFlushFrames(boolean enabled) {
         this.autoFlush = enabled;
     }
 
+    @Override
     public void destroy(boolean waitFor) {
         needClose.set(true);