refactored and upgraed lwjgl3 module.

monkanim
javasabr 7 years ago committed by Rémy Bouquet
parent 28353cf747
commit 555a348692
  1. 2
      jme3-lwjgl3/build.gradle
  2. 62
      jme3-lwjgl3/src/main/java/com/jme3/audio/lwjgl/LwjglAL.java
  3. 26
      jme3-lwjgl3/src/main/java/com/jme3/audio/lwjgl/LwjglALC.java
  4. 37
      jme3-lwjgl3/src/main/java/com/jme3/audio/lwjgl/LwjglEFX.java
  5. 26
      jme3-lwjgl3/src/main/java/com/jme3/input/lwjgl/GlfwJoystickInput.java
  6. 75
      jme3-lwjgl3/src/main/java/com/jme3/input/lwjgl/GlfwKeyInput.java
  7. 10
      jme3-lwjgl3/src/main/java/com/jme3/input/lwjgl/GlfwKeyMap.java
  8. 196
      jme3-lwjgl3/src/main/java/com/jme3/input/lwjgl/GlfwMouseInput.java
  9. 18
      jme3-lwjgl3/src/main/java/com/jme3/lwjgl3/utils/APIUtil.java
  10. 602
      jme3-lwjgl3/src/main/java/com/jme3/renderer/lwjgl/LwjglGL.java
  11. 45
      jme3-lwjgl3/src/main/java/com/jme3/renderer/lwjgl/LwjglGLExt.java
  12. 115
      jme3-lwjgl3/src/main/java/com/jme3/renderer/lwjgl/LwjglGLFboEXT.java
  13. 115
      jme3-lwjgl3/src/main/java/com/jme3/renderer/lwjgl/LwjglGLFboGL3.java
  14. 25
      jme3-lwjgl3/src/main/java/com/jme3/renderer/lwjgl/LwjglRender.java
  15. 316
      jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglContext.java
  16. 10
      jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglGLDebugOutputHandler.java
  17. 129
      jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglWindow.java

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

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

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

@ -36,62 +36,75 @@ import org.lwjgl.openal.EXTEfx;
import java.nio.IntBuffer; import java.nio.IntBuffer;
/**
* The LWJGL implementation of {@link EFX}.
*/
public class LwjglEFX implements 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.position() != 0) throw new AssertionError();
if (buffers.limit() != numSlots) throw new AssertionError(); if (buffers.limit() != numSlots) throw new AssertionError();
EXTEfx.alGenAuxiliaryEffectSlots(buffers); 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.position() != 0) throw new AssertionError();
if (buffers.limit() != numEffects) throw new AssertionError(); if (buffers.limit() != numEffects) throw new AssertionError();
EXTEfx.alGenEffects(buffers); 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); 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); 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.position() != 0) throw new AssertionError();
if (buffers.limit() != numEffects) throw new AssertionError(); if (buffers.limit() != numEffects) throw new AssertionError();
EXTEfx.alDeleteEffects(buffers); 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.position() != 0) throw new AssertionError();
if (buffers.limit() != numEffectSlots) throw new AssertionError(); if (buffers.limit() != numEffectSlots) throw new AssertionError();
EXTEfx.alDeleteAuxiliaryEffectSlots(buffers); 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.position() != 0) throw new AssertionError();
if (buffers.limit() != numFilters) throw new AssertionError(); if (buffers.limit() != numFilters) throw new AssertionError();
EXTEfx.alGenFilters(buffers); 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); 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); 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.position() != 0) throw new AssertionError();
if (buffers.limit() != numFilters) throw new AssertionError(); if (buffers.limit() != numFilters) throw new AssertionError();
EXTEfx.alDeleteFilters(buffers); 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); EXTEfx.alEffectf(effect, param, value);
} }
} }

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

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

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

@ -31,6 +31,7 @@
*/ */
package com.jme3.input.lwjgl; package com.jme3.input.lwjgl;
import static org.lwjgl.glfw.GLFW.*;
import com.jme3.cursors.plugins.JmeCursor; import com.jme3.cursors.plugins.JmeCursor;
import com.jme3.input.MouseInput; import com.jme3.input.MouseInput;
import com.jme3.input.RawInputListener; import com.jme3.input.RawInputListener;
@ -38,19 +39,17 @@ import com.jme3.input.event.MouseButtonEvent;
import com.jme3.input.event.MouseMotionEvent; import com.jme3.input.event.MouseMotionEvent;
import com.jme3.system.lwjgl.LwjglWindow; import com.jme3.system.lwjgl.LwjglWindow;
import com.jme3.util.BufferUtils; 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.ByteBuffer;
import java.nio.IntBuffer; import java.nio.IntBuffer;
import java.util.ArrayDeque;
import java.util.HashMap; import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map; import java.util.Map;
import java.util.Queue; import java.util.Queue;
import java.util.logging.Logger; 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 * 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 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 final LwjglWindow context;
private RawInputListener listener; private RawInputListener listener;
private boolean cursorVisible = true;
private long[] currentCursor;
private IntBuffer currentCursorDelays; 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 double currentCursorFrameStartTime = 0.0;
private int currentCursorFrame = 0;
private int mouseX; private int mouseX;
private int mouseY; private int mouseY;
private int mouseWheel; private int mouseWheel;
private boolean initialized; private int currentWidth;
private GLFWCursorPosCallback cursorPosCallback; private int currentHeight;
private GLFWScrollCallback scrollCallback;
private GLFWMouseButtonCallback mouseButtonCallback;
private final Queue<MouseMotionEvent> mouseMotionEvents = new ArrayDeque<>();
private final Queue<MouseButtonEvent> mouseButtonEvents = new ArrayDeque<>();
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.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 xDelta;
int yDelta; int yDelta;
int x = (int) Math.round(xpos); 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) { if (mouseX == 0) {
mouseX = x; 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; mouseWheel += yOffset;
final MouseMotionEvent mouseMotionEvent = new MouseMotionEvent(mouseX, mouseY, 0, 0, mouseWheel, (int) Math.round(yOffset)); final MouseMotionEvent mouseMotionEvent = new MouseMotionEvent(mouseX, mouseY, 0, 0, mouseWheel, (int) Math.round(yOffset));
mouseMotionEvent.setTime(getInputTimeNanos()); 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) { 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()); mouseButtonEvent.setTime(getInputTimeNanos());
mouseButtonEvents.add(mouseButtonEvent); mouseButtonEvents.add(mouseButtonEvent);
} }
@Override @Override
public void initialize() { public void initialize() {
glfwSetCursorPosCallback(context.getWindowHandle(), cursorPosCallback = new GLFWCursorPosCallback() {
@Override
public void invoke(long window, double xpos, double ypos) {
onCursorPos(window, xpos, ypos);
}
@Override final long window = context.getWindowHandle();
public void close() {
super.close(); 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 @Override
public void callback(long args) { public void invoke(final long window, final double xpos, final double ypos) {
super.callback(args); onCursorPos(window, xpos, ypos);
} }
}); });
glfwSetScrollCallback(context.getWindowHandle(), scrollCallback = new GLFWScrollCallback() { glfwSetScrollCallback(window, scrollCallback = new GLFWScrollCallback() {
@Override @Override
public void invoke(final long window, final double xOffset, final double yOffset) { public void invoke(final long window, final double xOffset, final double yOffset) {
onWheelScroll(window, xOffset, yOffset * WHEEL_SCALE); 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 @Override
public void invoke(final long window, final int button, final int action, final int mods) { public void invoke(final long window, final int button, final int action, final int mods) {
onMouseButton(window, button, action, mods); onMouseButton(window, button, action, mods);
} }
});
glfwSetWindowSizeCallback(window, new GLFWWindowSizeCallback() {
@Override @Override
public void close() { public void invoke(final long window, final int width, final int height) {
super.close(); currentHeight = height;
} currentWidth = width;
@Override
public void callback(long args) {
super.callback(args);
} }
}); });
@ -224,6 +268,7 @@ public class GlfwMouseInput implements MouseInput {
@Override @Override
public void destroy() { public void destroy() {
if (!context.isRenderable()) { if (!context.isRenderable()) {
return; return;
} }
@ -234,11 +279,13 @@ public class GlfwMouseInput implements MouseInput {
currentCursor = null; currentCursor = null;
currentCursorDelays = null; currentCursorDelays = null;
for (long[] glfwCursors : jmeToGlfwCursorMap.values()) { for (long[] glfwCursors : jmeToGlfwCursorMap.values()) {
for (long glfwCursor : glfwCursors) { for (long glfwCursor : glfwCursors) {
glfwDestroyCursor(glfwCursor); glfwDestroyCursor(glfwCursor);
} }
} }
jmeToGlfwCursorMap.clear(); jmeToGlfwCursorMap.clear();
logger.fine("Mouse destroyed."); logger.fine("Mouse destroyed.");
@ -269,58 +316,23 @@ public class GlfwMouseInput implements MouseInput {
return (long) (glfwGetTime() * 1000000000); 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 @Override
public void setNativeCursor(JmeCursor jmeCursor) { public void setNativeCursor(final JmeCursor jmeCursor) {
if (jmeCursor != null) { if (jmeCursor != null) {
long[] glfwCursor = jmeToGlfwCursorMap.get(jmeCursor);
if (glfwCursor == null) { final long[] glfwCursor = jmeToGlfwCursorMap.computeIfAbsent(jmeCursor, GlfwMouseInput::createGlfwCursor);
glfwCursor = createGlfwCursor(jmeCursor);
jmeToGlfwCursorMap.put(jmeCursor, glfwCursor);
}
currentCursorFrame = 0; currentCursorFrame = 0;
currentCursor = glfwCursor; currentCursor = glfwCursor;
currentCursorDelays = null; currentCursorDelays = null;
currentCursorFrameStartTime = glfwGetTime(); currentCursorFrameStartTime = glfwGetTime();
if (jmeCursor.getImagesDelay() != null) { if (jmeCursor.getImagesDelay() != null) {
currentCursorDelays = jmeCursor.getImagesDelay(); currentCursorDelays = jmeCursor.getImagesDelay();
} }
glfwSetCursor(context.getWindowHandle(), glfwCursor[currentCursorFrame]); glfwSetCursor(context.getWindowHandle(), glfwCursor[currentCursorFrame]);
} else { } else {
currentCursor = null; currentCursor = null;
currentCursorDelays = null; currentCursorDelays = null;

@ -20,16 +20,22 @@ import java.util.regex.Pattern;
*/ */
public final class APIUtil { public final class APIUtil {
private static final ThreadLocal<APIBuffer> API_BUFFERS = new ThreadLocal<APIBuffer>() { private static final ThreadLocal<APIBuffer> API_BUFFERS = ThreadLocal.withInitial(APIBuffer::new);
@Override
protected APIBuffer initialValue() {
return new APIBuffer();
}
};
private APIUtil() { 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. * Returns a thread-local {@link APIBuffer} that has been reset.
*/ */

@ -31,449 +31,553 @@
*/ */
package com.jme3.renderer.lwjgl; package com.jme3.renderer.lwjgl;
import com.jme3.renderer.RendererException;
import com.jme3.renderer.opengl.GL; import com.jme3.renderer.opengl.GL;
import com.jme3.renderer.opengl.GL2; import com.jme3.renderer.opengl.GL2;
import com.jme3.renderer.opengl.GL3; import com.jme3.renderer.opengl.GL3;
import com.jme3.renderer.opengl.GL4; import com.jme3.renderer.opengl.GL4;
import org.lwjgl.opengl.*; 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) { @Override
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 void resetStats() { public void resetStats() {
} }
public void glActiveTexture(int param1) { @Override
GL13.glActiveTexture(param1); public void glActiveTexture(final int texture) {
GL13.glActiveTexture(texture);
} }
public void glAlphaFunc(int param1, float param2) { @Override
GL11.glAlphaFunc(param1, param2); public void glAlphaFunc(final int func, final float ref) {
GL11.glAlphaFunc(func, ref);
} }
public void glAttachShader(int param1, int param2) { @Override
GL20.glAttachShader(param1, param2); public void glAttachShader(final int program, final int shader) {
GL20.glAttachShader(program, shader);
} }
@Override @Override
public void glBeginQuery(int target, int query) { public void glBeginQuery(final int target, final int query) {
GL15.glBeginQuery(target, query); GL15.glBeginQuery(target, query);
} }
public void glBindBuffer(int param1, int param2) { @Override
GL15.glBindBuffer(param1, param2); public void glBindBuffer(final int target, final int buffer) {
GL15.glBindBuffer(target, buffer);
} }
public void glBindTexture(int param1, int param2) { @Override
GL11.glBindTexture(param1, param2); public void glBindTexture(final int target, final int texture) {
GL11.glBindTexture(target, texture);
} }
public void glBlendEquationSeparate(int colorMode, int alphaMode){ @Override
GL20.glBlendEquationSeparate(colorMode,alphaMode); public void glBlendEquationSeparate(final int colorMode, final int alphaMode) {
GL20.glBlendEquationSeparate(colorMode, alphaMode);
} }
public void glBlendFunc(int param1, int param2) { @Override
GL11.glBlendFunc(param1, param2); public void glBlendFunc(final int sfactor, final int dfactor) {
GL11.glBlendFunc(sfactor, dfactor);
} }
public void glBlendFuncSeparate(int param1, int param2, int param3, int param4) { @Override
GL14.glBlendFuncSeparate(param1, param2, param3, param4); 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) { @Override
GL15.glBufferData(param1, param2, param3); 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) { @Override
checkLimit(param2); public void glBufferData(final int target, final FloatBuffer data, final int usage) {
GL15.glBufferData(param1, param2, param3); checkLimit(data);
GL15.glBufferData(target, data, usage);
} }
public void glBufferData(int param1, ShortBuffer param2, int param3) { @Override
checkLimit(param2); public void glBufferData(final int target, final ShortBuffer data, final int usage) {
GL15.glBufferData(param1, param2, param3); checkLimit(data);
GL15.glBufferData(target, data, usage);
} }
public void glBufferData(int param1, ByteBuffer param2, int param3) { @Override
checkLimit(param2); public void glBufferData(final int target, final ByteBuffer data, final int usage) {
GL15.glBufferData(param1, param2, param3); checkLimit(data);
GL15.glBufferData(target, data, usage);
} }
public void glBufferSubData(int param1, long param2, FloatBuffer param3) { @Override
checkLimit(param3); public void glBufferSubData(final int target, final long offset, final FloatBuffer data) {
GL15.glBufferSubData(param1, param2, param3); checkLimit(data);
GL15.glBufferSubData(target, offset, data);
} }
public void glBufferSubData(int param1, long param2, ShortBuffer param3) { @Override
checkLimit(param3); public void glBufferSubData(final int target, final long offset, final ShortBuffer data) {
GL15.glBufferSubData(param1, param2, param3); checkLimit(data);
GL15.glBufferSubData(target, offset, data);
} }
public void glBufferSubData(int param1, long param2, ByteBuffer param3) { @Override
checkLimit(param3); public void glBufferSubData(final int target, final long offset, final ByteBuffer data) {
GL15.glBufferSubData(param1, param2, param3); checkLimit(data);
GL15.glBufferSubData(target, offset, data);
} }
public void glClear(int param1) { @Override
GL11.glClear(param1); public void glClear(final int mask) {
GL11.glClear(mask);
} }
public void glClearColor(float param1, float param2, float param3, float param4) { @Override
GL11.glClearColor(param1, param2, param3, param4); 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) { @Override
GL11.glColorMask(param1, param2, param3, param4); 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) { @Override
GL20.glCompileShader(param1); 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) { @Override
checkLimit(param7); public void glCompressedTexImage2D(final int target, final int level, final int internalFormat, final int width,
GL13.glCompressedTexImage2D(param1, param2, param3, param4, param5, param6, param7); 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) { @Override
checkLimit(param8); public void glCompressedTexImage3D(final int target, final int level, final int internalFormat, final int width,
GL13.glCompressedTexImage3D(param1, param2, param3, param4, param5, param6, param7, param8); 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) { @Override
checkLimit(param8); public void glCompressedTexSubImage2D(final int target, final int level, final int xoffset, final int yoffset,
GL13.glCompressedTexSubImage2D(param1, param2, param3, param4, param5, param6, param7, param8); 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) { @Override
checkLimit(param10); public void glCompressedTexSubImage3D(final int target, final int level, final int xoffset, final int yoffset,
GL13.glCompressedTexSubImage3D(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10); 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() { public int glCreateProgram() {
return GL20.glCreateProgram(); return GL20.glCreateProgram();
} }
public int glCreateShader(int param1) { @Override
return GL20.glCreateShader(param1); public int glCreateShader(final int shaderType) {
return GL20.glCreateShader(shaderType);
} }
public void glCullFace(int param1) { @Override
GL11.glCullFace(param1); public void glCullFace(final int mode) {
GL11.glCullFace(mode);
} }
public void glDeleteBuffers(IntBuffer param1) { @Override
checkLimit(param1); public void glDeleteBuffers(final IntBuffer buffers) {
GL15.glDeleteBuffers(param1); checkLimit(buffers);
GL15.glDeleteBuffers(buffers);
} }
public void glDeleteProgram(int param1) { @Override
GL20.glDeleteProgram(param1); public void glDeleteProgram(final int program) {
GL20.glDeleteProgram(program);
} }
public void glDeleteShader(int param1) { @Override
GL20.glDeleteShader(param1); public void glDeleteShader(final int shader) {
GL20.glDeleteShader(shader);
} }
public void glDeleteTextures(IntBuffer param1) { @Override
checkLimit(param1); public void glDeleteTextures(final IntBuffer textures) {
GL11.glDeleteTextures(param1); checkLimit(textures);
GL11.glDeleteTextures(textures);
} }
public void glDepthFunc(int param1) { @Override
GL11.glDepthFunc(param1); public void glDepthFunc(final int func) {
GL11.glDepthFunc(func);
} }
public void glDepthMask(boolean param1) { @Override
GL11.glDepthMask(param1); public void glDepthMask(final boolean flag) {
GL11.glDepthMask(flag);
} }
public void glDepthRange(double param1, double param2) { @Override
GL11.glDepthRange(param1, param2); public void glDepthRange(final double nearVal, final double farVal) {
GL11.glDepthRange(nearVal, farVal);
} }
public void glDetachShader(int param1, int param2) { @Override
GL20.glDetachShader(param1, param2); public void glDetachShader(final int program, final int shader) {
GL20.glDetachShader(program, shader);
} }
public void glDisable(int param1) { @Override
GL11.glDisable(param1); public void glDisable(final int cap) {
GL11.glDisable(cap);
} }
public void glDisableVertexAttribArray(int param1) { @Override
GL20.glDisableVertexAttribArray(param1); public void glDisableVertexAttribArray(final int index) {
GL20.glDisableVertexAttribArray(index);
} }
public void glDrawArrays(int param1, int param2, int param3) { @Override
GL11.glDrawArrays(param1, param2, param3); public void glDrawArrays(final int mode, final int first, final int count) {
GL11.glDrawArrays(mode, first, count);
} }
public void glDrawBuffer(int param1) { @Override
GL11.glDrawBuffer(param1); public void glDrawBuffer(final int mode) {
GL11.glDrawBuffer(mode);
} }
public void glDrawRangeElements(int param1, int param2, int param3, int param4, int param5, long param6) { @Override
GL12.glDrawRangeElements(param1, param2, param3, param4, param5, param6); 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) { @Override
GL11.glEnable(param1); public void glEnable(final int cap) {
GL11.glEnable(cap);
} }
public void glEnableVertexAttribArray(int param1) { @Override
GL20.glEnableVertexAttribArray(param1); public void glEnableVertexAttribArray(final int index) {
GL20.glEnableVertexAttribArray(index);
} }
@Override @Override
public void glEndQuery(int target) { public void glEndQuery(final int target) {
GL15.glEndQuery(target); GL15.glEndQuery(target);
} }
public void glGenBuffers(IntBuffer param1) { @Override
checkLimit(param1); public void glGenBuffers(final IntBuffer buffers) {
GL15.glGenBuffers(param1); checkLimit(buffers);
GL15.glGenBuffers(buffers);
} }
public void glGenTextures(IntBuffer param1) { @Override
checkLimit(param1); public void glGenTextures(final IntBuffer textures) {
GL11.glGenTextures(param1); checkLimit(textures);
GL11.glGenTextures(textures);
} }
@Override @Override
public void glGenQueries(int num, IntBuffer ids) { public void glGenQueries(final int num, final IntBuffer ids) {
GL15.glGenQueries(ids); GL15.glGenQueries(ids);
} }
public void glGetBoolean(int param1, ByteBuffer param2) { @Override
checkLimit(param2); public void glGetBoolean(final int pname, final ByteBuffer params) {
GL11.glGetBooleanv(param1, param2); 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); checkLimit(data);
GL15.glGetBufferSubData(target, offset, data); GL15.glGetBufferSubData(target, offset, data);
} }
@Override
public int glGetError() { public int glGetError() {
return GL11.glGetError(); return GL11.glGetError();
} }
public void glGetInteger(int param1, IntBuffer param2) { @Override
checkLimit(param2); public void glGetInteger(final int pname, final IntBuffer params) {
GL11.glGetIntegerv(param1, param2); checkLimit(params);
GL11.glGetIntegerv(pname, params);
} }
public void glGetProgram(int param1, int param2, IntBuffer param3) { @Override
checkLimit(param3); public void glGetProgram(final int program, final int pname, final IntBuffer params) {
GL20.glGetProgramiv(param1, param2, param3); checkLimit(params);
GL20.glGetProgramiv(program, pname, params);
} }
public void glGetShader(int param1, int param2, IntBuffer param3) { @Override
checkLimit(param3); public void glGetShader(final int shader, final int pname, final IntBuffer params) {
GL20.glGetShaderiv(param1, param2, param3); checkLimit(params);
GL20.glGetShaderiv(shader, pname, params);
} }
public String glGetString(int param1) { @Override
return GL11.glGetString(param1); public String glGetString(final int name) {
return GL11.glGetString(name);
} }
public String glGetString(int param1, int param2) { @Override
return GL30.glGetStringi(param1, param2); public String glGetString(final int name, final int index) {
return GL30.glGetStringi(name, index);
} }
public boolean glIsEnabled(int param1) { @Override
return GL11.glIsEnabled(param1); public boolean glIsEnabled(final int cap) {
return GL11.glIsEnabled(cap);
} }
public void glLineWidth(float param1) { @Override
GL11.glLineWidth(param1); public void glLineWidth(final float width) {
GL11.glLineWidth(width);
} }
public void glLinkProgram(int param1) { @Override
GL20.glLinkProgram(param1); public void glLinkProgram(final int program) {
GL20.glLinkProgram(program);
} }
public void glPixelStorei(int param1, int param2) { @Override
GL11.glPixelStorei(param1, param2); public void glPixelStorei(final int pname, final int param) {
GL11.glPixelStorei(pname, param);
} }
public void glPointSize(float param1) { @Override
GL11.glPointSize(param1); public void glPointSize(final float size) {
GL11.glPointSize(size);
} }
public void glPolygonMode(int param1, int param2) { @Override
GL11.glPolygonMode(param1, param2); public void glPolygonMode(final int face, final int mode) {
GL11.glPolygonMode(face, mode);
} }
public void glPolygonOffset(float param1, float param2) { @Override
GL11.glPolygonOffset(param1, param2); public void glPolygonOffset(final float factor, final float units) {
GL11.glPolygonOffset(factor, units);
} }
public void glReadBuffer(int param1) { @Override
GL11.glReadBuffer(param1); 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) { @Override
checkLimit(param7); public void glReadPixels(final int x, final int y, final int width, final int height, final int format,
GL11.glReadPixels(param1, param2, param3, param4, param5, param6, param7); 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) { @Override
GL11.glReadPixels(param1, param2, param3, param4, param5, param6, param7); 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) { @Override
GL11.glScissor(param1, param2, param3, param4); 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) { @Override
GL20.glStencilFuncSeparate(param1, param2, param3, param4); 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) { @Override
GL20.glStencilOpSeparate(param1, param2, param3, param4); 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) { @Override
checkLimit(param9); public void glTexImage2D(final int target, final int level, final int internalFormat, final int width,
GL11.glTexImage2D(param1, param2, param3, param4, param5, param6, param7, param8, param9); 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) { @Override
checkLimit(param10); public void glTexImage3D(final int target, final int level, final int internalFormat, final int width,
GL12.glTexImage3D(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10); 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) { @Override
GL11.glTexParameterf(param1, param2, param3); 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) { @Override
GL11.glTexParameteri(param1, param2, param3); 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) { @Override
checkLimit(param9); public void glTexSubImage2D(final int target, final int level, final int xoffset, final int yoffset,
GL11.glTexSubImage2D(param1, param2, param3, param4, param5, param6, param7, param8, param9); 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) { @Override
checkLimit(param11); public void glTexSubImage3D(final int target, final int level, final int xoffset, final int yoffset,
GL12.glTexSubImage3D(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10, param11); 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) { @Override
checkLimit(param2); public void glUniform1(final int location, final FloatBuffer value) {
GL20.glUniform1fv(param1, param2); checkLimit(value);
GL20.glUniform1fv(location, value);
} }
public void glUniform1(int param1, IntBuffer param2) { @Override
checkLimit(param2); public void glUniform1(final int location, final IntBuffer value) {
GL20.glUniform1iv(param1, param2); checkLimit(value);
GL20.glUniform1iv(location, value);
} }
public void glUniform1f(int param1, float param2) { @Override
GL20.glUniform1f(param1, param2); public void glUniform1f(final int location, final float v0) {
GL20.glUniform1f(location, v0);
} }
public void glUniform1i(int param1, int param2) { @Override
GL20.glUniform1i(param1, param2); public void glUniform1i(final int location, final int v0) {
GL20.glUniform1i(location, v0);
} }
public void glUniform2(int param1, IntBuffer param2) { @Override
checkLimit(param2); public void glUniform2(final int location, final IntBuffer value) {
GL20.glUniform2iv(param1, param2); checkLimit(value);
GL20.glUniform2iv(location, value);
} }
public void glUniform2(int param1, FloatBuffer param2) { @Override
checkLimit(param2); public void glUniform2(final int location, final FloatBuffer value) {
GL20.glUniform2fv(param1, param2); checkLimit(value);
GL20.glUniform2fv(location, value);
} }
public void glUniform2f(int param1, float param2, float param3) { @Override
GL20.glUniform2f(param1, param2, param3); public void glUniform2f(final int location, final float v0, final float v1) {
GL20.glUniform2f(location, v0, v1);
} }
public void glUniform3(int param1, IntBuffer param2) { @Override
checkLimit(param2); public void glUniform3(final int location, final IntBuffer value) {
GL20.glUniform3iv(param1, param2); checkLimit(value);
GL20.glUniform3iv(location, value);
} }
public void glUniform3(int param1, FloatBuffer param2) { @Override
checkLimit(param2); public void glUniform3(final int location, final FloatBuffer value) {
GL20.glUniform3fv(param1, param2); checkLimit(value);
GL20.glUniform3fv(location, value);
} }
public void glUniform3f(int param1, float param2, float param3, float param4) { @Override
GL20.glUniform3f(param1, param2, param3, param4); 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) { @Override
checkLimit(param2); public void glUniform4(final int location, final FloatBuffer value) {
GL20.glUniform4fv(param1, param2); checkLimit(value);
GL20.glUniform4fv(location, value);
} }
public void glUniform4(int param1, IntBuffer param2) { @Override
checkLimit(param2); public void glUniform4(final int location, final IntBuffer value) {
GL20.glUniform4iv(param1, param2); checkLimit(value);
GL20.glUniform4iv(location, value);
} }
public void glUniform4f(int param1, float param2, float param3, float param4, float param5) { @Override
GL20.glUniform4f(param1, param2, param3, param4, param5); 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) { @Override
checkLimit(param3); public void glUniformMatrix3(final int location, final boolean transpose, final FloatBuffer value) {
GL20.glUniformMatrix3fv(param1, param2, param3); checkLimit(value);
GL20.glUniformMatrix3fv(location, transpose, value);
} }
public void glUniformMatrix4(int param1, boolean param2, FloatBuffer param3) { @Override
checkLimit(param3); public void glUniformMatrix4(final int location, final boolean transpose, final FloatBuffer value) {
GL20.glUniformMatrix4fv(param1, param2, param3); checkLimit(value);
GL20.glUniformMatrix4fv(location, transpose, value);
} }
public void glUseProgram(int param1) { @Override
GL20.glUseProgram(param1); public void glUseProgram(final int program) {
GL20.glUseProgram(program);
} }
public void glVertexAttribPointer(int param1, int param2, int param3, boolean param4, int param5, long param6) { @Override
GL20.glVertexAttribPointer(param1, param2, param3, param4, param5, param6); 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) { @Override
GL11.glViewport(param1, param2, param3, param4); 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 // 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 // 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) { @Override
checkLimit(param3); public void glShaderSource(final int shader, final String[] strings, final IntBuffer length) {
GL20.glShaderSource(param1, param2); 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); return GL20.glGetProgramInfoLog(program, maxSize);
} }
@ -492,28 +596,28 @@ public class LwjglGL implements GL, GL2, GL3, GL4 {
} }
@Override @Override
public void glBindFragDataLocation(int param1, int param2, String param3) { public void glBindFragDataLocation(final int program, final int colorNumber, final String name) {
GL30.glBindFragDataLocation(param1, param2, param3); GL30.glBindFragDataLocation(program, colorNumber, name);
} }
@Override @Override
public void glBindVertexArray(int param1) { public void glBindVertexArray(final int array) {
GL30.glBindVertexArray(param1); GL30.glBindVertexArray(array);
} }
@Override @Override
public void glGenVertexArrays(IntBuffer param1) { public void glGenVertexArrays(final IntBuffer arrays) {
checkLimit(param1); checkLimit(arrays);
GL30.glGenVertexArrays(param1); GL30.glGenVertexArrays(arrays);
} }
@Override @Override
public void glPatchParameter(int count) { public void glPatchParameter(final int count) {
GL40.glPatchParameteri(GL40.GL_PATCH_VERTICES,count); GL40.glPatchParameteri(GL40.GL_PATCH_VERTICES, count);
} }
@Override @Override
public void glDeleteVertexArrays(IntBuffer arrays) { public void glDeleteVertexArrays(final IntBuffer arrays) {
checkLimit(arrays); checkLimit(arrays);
ARBVertexArrayObject.glDeleteVertexArrays(arrays); ARBVertexArrayObject.glDeleteVertexArrays(arrays);
} }

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

@ -31,106 +31,99 @@
*/ */
package com.jme3.renderer.lwjgl; package com.jme3.renderer.lwjgl;
import com.jme3.renderer.RendererException;
import com.jme3.renderer.opengl.GLFbo; import com.jme3.renderer.opengl.GLFbo;
import org.lwjgl.opengl.EXTFramebufferBlit; import org.lwjgl.opengl.EXTFramebufferBlit;
import org.lwjgl.opengl.EXTFramebufferMultisample; import org.lwjgl.opengl.EXTFramebufferMultisample;
import org.lwjgl.opengl.EXTFramebufferObject; import org.lwjgl.opengl.EXTFramebufferObject;
import org.lwjgl.opengl.EXTTextureArray;
import java.nio.Buffer;
import java.nio.IntBuffer; import java.nio.IntBuffer;
import org.lwjgl.opengl.EXTTextureArray;
/** /**
* Implements GLFbo via GL_EXT_framebuffer_object. * Implements GLFbo via GL_EXT_framebuffer_object.
* *
* @author Kirill Vainer * @author Kirill Vainer
*/ */
public class LwjglGLFboEXT implements GLFbo { public class LwjglGLFboEXT extends LwjglRender 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");
}
}
@Override @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); EXTFramebufferBlit.glBlitFramebufferEXT(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
} }
@Override @Override
public void glRenderbufferStorageMultisampleEXT(int target, int samples, int internalformat, int width, int height) { public void glRenderbufferStorageMultisampleEXT(final int target, final int samples, final int internalFormat,
EXTFramebufferMultisample.glRenderbufferStorageMultisampleEXT(target, samples, internalformat, width, height); final int width, final int height) {
EXTFramebufferMultisample.glRenderbufferStorageMultisampleEXT(target, samples, internalFormat, width, height);
} }
@Override @Override
public void glBindFramebufferEXT(int param1, int param2) { public void glBindFramebufferEXT(final int target, final int frameBuffer) {
EXTFramebufferObject.glBindFramebufferEXT(param1, param2); EXTFramebufferObject.glBindFramebufferEXT(target, frameBuffer);
} }
@Override @Override
public void glBindRenderbufferEXT(int param1, int param2) { public void glBindRenderbufferEXT(final int target, final int renderBuffer) {
EXTFramebufferObject.glBindRenderbufferEXT(param1, param2); EXTFramebufferObject.glBindRenderbufferEXT(target, renderBuffer);
} }
@Override @Override
public int glCheckFramebufferStatusEXT(int param1) { public int glCheckFramebufferStatusEXT(final int target) {
return EXTFramebufferObject.glCheckFramebufferStatusEXT(param1); return EXTFramebufferObject.glCheckFramebufferStatusEXT(target);
} }
@Override @Override
public void glDeleteFramebuffersEXT(IntBuffer param1) { public void glDeleteFramebuffersEXT(final IntBuffer frameBuffers) {
checkLimit(param1); checkLimit(frameBuffers);
EXTFramebufferObject.glDeleteFramebuffersEXT(param1); EXTFramebufferObject.glDeleteFramebuffersEXT(frameBuffers);
} }
@Override @Override
public void glDeleteRenderbuffersEXT(IntBuffer param1) { public void glDeleteRenderbuffersEXT(final IntBuffer renderBuffers) {
checkLimit(param1); checkLimit(renderBuffers);
EXTFramebufferObject.glDeleteRenderbuffersEXT(param1); EXTFramebufferObject.glDeleteRenderbuffersEXT(renderBuffers);
} }
@Override @Override
public void glFramebufferRenderbufferEXT(int param1, int param2, int param3, int param4) { public void glFramebufferRenderbufferEXT(final int target, final int attachment, final int renderBufferTarget,
EXTFramebufferObject.glFramebufferRenderbufferEXT(param1, param2, param3, param4); final int renderBuffer) {
EXTFramebufferObject.glFramebufferRenderbufferEXT(target, attachment, renderBufferTarget, renderBuffer);
} }
@Override @Override
public void glFramebufferTexture2DEXT(int param1, int param2, int param3, int param4, int param5) { public void glFramebufferTexture2DEXT(final int target, final int attachment, final int texTarget,
EXTFramebufferObject.glFramebufferTexture2DEXT(param1, param2, param3, param4, param5); final int texture, final int level) {
EXTFramebufferObject.glFramebufferTexture2DEXT(target, attachment, texTarget, texture, level);
} }
@Override @Override
public void glGenFramebuffersEXT(IntBuffer param1) { public void glGenFramebuffersEXT(final IntBuffer frameBuffers) {
checkLimit(param1); checkLimit(frameBuffers);
EXTFramebufferObject.glGenFramebuffersEXT(param1); EXTFramebufferObject.glGenFramebuffersEXT(frameBuffers);
} }
@Override @Override
public void glGenRenderbuffersEXT(IntBuffer param1) { public void glGenRenderbuffersEXT(final IntBuffer renderBuffers) {
checkLimit(param1); checkLimit(renderBuffers);
EXTFramebufferObject.glGenRenderbuffersEXT(param1); EXTFramebufferObject.glGenRenderbuffersEXT(renderBuffers);
} }
@Override @Override
public void glGenerateMipmapEXT(int param1) { public void glGenerateMipmapEXT(final int target) {
EXTFramebufferObject.glGenerateMipmapEXT(param1); EXTFramebufferObject.glGenerateMipmapEXT(target);
} }
@Override @Override
public void glRenderbufferStorageEXT(int param1, int param2, int param3, int param4) { public void glRenderbufferStorageEXT(final int target, final int internalFormat, final int width,
EXTFramebufferObject.glRenderbufferStorageEXT(param1, param2, param3, param4); final int height) {
EXTFramebufferObject.glRenderbufferStorageEXT(target, internalFormat, width, height);
} }
@Override @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); EXTTextureArray.glFramebufferTextureLayerEXT(target, attachment, texture, level, layer);
} }
} }

@ -31,103 +31,96 @@
*/ */
package com.jme3.renderer.lwjgl; package com.jme3.renderer.lwjgl;
import com.jme3.renderer.RendererException;
import com.jme3.renderer.opengl.GLFbo; import com.jme3.renderer.opengl.GLFbo;
import org.lwjgl.opengl.GL30; import org.lwjgl.opengl.GL30;
import java.nio.Buffer;
import java.nio.IntBuffer; import java.nio.IntBuffer;
/** /**
* Implements GLFbo via OpenGL3+. * Implements GLFbo via OpenGL3+.
* *
* @author Kirill Vainer * @author Kirill Vainer
*/ */
public class LwjglGLFboGL3 implements GLFbo { public class LwjglGLFboGL3 extends LwjglRender 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");
}
}
@Override @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); GL30.glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
} }
@Override @Override
public void glRenderbufferStorageMultisampleEXT(int target, int samples, int internalformat, int width, int height) { public void glRenderbufferStorageMultisampleEXT(final int target, final int samples, final int internalFormat,
GL30.glRenderbufferStorageMultisample(target, samples, internalformat, width, height); final int width, final int height) {
GL30.glRenderbufferStorageMultisample(target, samples, internalFormat, width, height);
} }
@Override @Override
public void glBindFramebufferEXT(int param1, int param2) { public void glBindFramebufferEXT(final int target, final int frameBuffer) {
GL30.glBindFramebuffer(param1, param2); GL30.glBindFramebuffer(target, frameBuffer);
} }
@Override @Override
public void glBindRenderbufferEXT(int param1, int param2) { public void glBindRenderbufferEXT(final int target, final int renderBuffer) {
GL30.glBindRenderbuffer(param1, param2); GL30.glBindRenderbuffer(target, renderBuffer);
} }
@Override @Override
public int glCheckFramebufferStatusEXT(int param1) { public int glCheckFramebufferStatusEXT(final int target) {
return GL30.glCheckFramebufferStatus(param1); return GL30.glCheckFramebufferStatus(target);
} }
@Override @Override
public void glDeleteFramebuffersEXT(IntBuffer param1) { public void glDeleteFramebuffersEXT(final IntBuffer frameBuffers) {
checkLimit(param1); checkLimit(frameBuffers);
GL30.glDeleteFramebuffers(param1); GL30.glDeleteFramebuffers(frameBuffers);
} }
@Override @Override
public void glDeleteRenderbuffersEXT(IntBuffer param1) { public void glDeleteRenderbuffersEXT(final IntBuffer renderBuffers) {
checkLimit(param1); checkLimit(renderBuffers);
GL30.glDeleteRenderbuffers(param1); GL30.glDeleteRenderbuffers(renderBuffers);
} }
@Override @Override
public void glFramebufferRenderbufferEXT(int param1, int param2, int param3, int param4) { public void glFramebufferRenderbufferEXT(final int target, final int attachment, final int renderBufferTarget,
GL30.glFramebufferRenderbuffer(param1, param2, param3, param4); final int renderBuffer) {
GL30.glFramebufferRenderbuffer(target, attachment, renderBufferTarget, renderBuffer);
} }
@Override @Override
public void glFramebufferTexture2DEXT(int param1, int param2, int param3, int param4, int param5) { public void glFramebufferTexture2DEXT(final int target, final int attachment, final int texTarget,
GL30.glFramebufferTexture2D(param1, param2, param3, param4, param5); final int texture, final int level) {
GL30.glFramebufferTexture2D(target, attachment, texTarget, texture, level);
} }
@Override @Override
public void glGenFramebuffersEXT(IntBuffer param1) { public void glGenFramebuffersEXT(final IntBuffer frameBuffers) {
checkLimit(param1); checkLimit(frameBuffers);
GL30.glGenFramebuffers(param1); GL30.glGenFramebuffers(frameBuffers);
} }
@Override @Override
public void glGenRenderbuffersEXT(IntBuffer param1) { public void glGenRenderbuffersEXT(final IntBuffer renderBuffers) {
checkLimit(param1); checkLimit(renderBuffers);
GL30.glGenRenderbuffers(param1); GL30.glGenRenderbuffers(renderBuffers);
} }
@Override @Override
public void glGenerateMipmapEXT(int param1) { public void glGenerateMipmapEXT(final int target) {
GL30.glGenerateMipmap(param1); GL30.glGenerateMipmap(target);
} }
@Override @Override
public void glRenderbufferStorageEXT(int param1, int param2, int param3, int param4) { public void glRenderbufferStorageEXT(final int target, final int internalFormat, final int width,
GL30.glRenderbufferStorage(param1, param2, param3, param4); final int height) {
GL30.glRenderbufferStorage(target, internalFormat, width, height);
} }
@Override @Override
public void glFramebufferTextureLayerEXT(int param1, int param2, int param3, int param4, int param5) { public void glFramebufferTextureLayerEXT(final int target, final int attachment, final int texture, final int level,
GL30.glFramebufferTextureLayer(param1, param2, param3, param4, param5); final int layer) {
GL30.glFramebufferTextureLayer(target, attachment, texture, level, layer);
} }
} }

@ -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");
}
}
}

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

@ -75,14 +75,4 @@ class LwjglGLDebugOutputHandler extends GLDebugMessageARBCallback {
System.err.println(String.format(MESSAGE_FORMAT, id, sourceStr, typeStr, severityStr, message)); 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);
}
} }

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

Loading…
Cancel
Save