|
@@ -1,5 +1,5 @@
|
|
/*
|
|
/*
|
|
-* Copyright (c) 2009-2023 jMonkeyEngine
|
|
|
|
|
|
+ * Copyright (c) 2009-2023 jMonkeyEngine
|
|
* All rights reserved.
|
|
* All rights reserved.
|
|
*
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* Redistribution and use in source and binary forms, with or without
|
|
@@ -32,6 +32,10 @@
|
|
|
|
|
|
package com.jme3.system.lwjgl;
|
|
package com.jme3.system.lwjgl;
|
|
|
|
|
|
|
|
+import static org.lwjgl.glfw.GLFW.*;
|
|
|
|
+import static org.lwjgl.opengl.GL11.GL_FALSE;
|
|
|
|
+import static org.lwjgl.system.MemoryUtil.NULL;
|
|
|
|
+
|
|
import com.jme3.input.JoyInput;
|
|
import com.jme3.input.JoyInput;
|
|
import com.jme3.input.KeyInput;
|
|
import com.jme3.input.KeyInput;
|
|
import com.jme3.input.MouseInput;
|
|
import com.jme3.input.MouseInput;
|
|
@@ -47,17 +51,6 @@ import com.jme3.system.JmeSystem;
|
|
import com.jme3.system.NanoTimer;
|
|
import com.jme3.system.NanoTimer;
|
|
import com.jme3.util.BufferUtils;
|
|
import com.jme3.util.BufferUtils;
|
|
import com.jme3.util.SafeArrayList;
|
|
import com.jme3.util.SafeArrayList;
|
|
-
|
|
|
|
-import org.lwjgl.PointerBuffer;
|
|
|
|
-import org.lwjgl.Version;
|
|
|
|
-import org.lwjgl.glfw.GLFWErrorCallback;
|
|
|
|
-import org.lwjgl.glfw.GLFWFramebufferSizeCallback;
|
|
|
|
-import org.lwjgl.glfw.GLFWImage;
|
|
|
|
-import org.lwjgl.glfw.GLFWVidMode;
|
|
|
|
-import org.lwjgl.glfw.GLFWWindowFocusCallback;
|
|
|
|
-import org.lwjgl.glfw.GLFWWindowSizeCallback;
|
|
|
|
-import org.lwjgl.system.Platform;
|
|
|
|
-
|
|
|
|
import java.awt.Graphics2D;
|
|
import java.awt.Graphics2D;
|
|
import java.awt.image.BufferedImage;
|
|
import java.awt.image.BufferedImage;
|
|
import java.nio.ByteBuffer;
|
|
import java.nio.ByteBuffer;
|
|
@@ -69,10 +62,15 @@ import java.util.Objects;
|
|
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;
|
|
-
|
|
|
|
-import static org.lwjgl.glfw.GLFW.*;
|
|
|
|
-import static org.lwjgl.opengl.GL11.GL_FALSE;
|
|
|
|
-import static org.lwjgl.system.MemoryUtil.NULL;
|
|
|
|
|
|
+import org.lwjgl.PointerBuffer;
|
|
|
|
+import org.lwjgl.Version;
|
|
|
|
+import org.lwjgl.glfw.GLFWErrorCallback;
|
|
|
|
+import org.lwjgl.glfw.GLFWFramebufferSizeCallback;
|
|
|
|
+import org.lwjgl.glfw.GLFWImage;
|
|
|
|
+import org.lwjgl.glfw.GLFWVidMode;
|
|
|
|
+import org.lwjgl.glfw.GLFWWindowFocusCallback;
|
|
|
|
+import org.lwjgl.glfw.GLFWWindowSizeCallback;
|
|
|
|
+import org.lwjgl.system.Platform;
|
|
|
|
|
|
/**
|
|
/**
|
|
* A wrapper class over the GLFW framework in LWJGL 3.
|
|
* A wrapper class over the GLFW framework in LWJGL 3.
|
|
@@ -84,66 +82,99 @@ 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(
|
|
private static final EnumSet<JmeContext.Type> SUPPORTED_TYPES = EnumSet.of(
|
|
- JmeContext.Type.Display,
|
|
|
|
- JmeContext.Type.Canvas,
|
|
|
|
- JmeContext.Type.OffscreenSurface);
|
|
|
|
|
|
+ JmeContext.Type.Display,
|
|
|
|
+ JmeContext.Type.Canvas,
|
|
|
|
+ JmeContext.Type.OffscreenSurface
|
|
|
|
+ );
|
|
|
|
|
|
private static final Map<String, Runnable> RENDER_CONFIGS = new HashMap<>();
|
|
private static final Map<String, Runnable> RENDER_CONFIGS = new HashMap<>();
|
|
|
|
|
|
static {
|
|
static {
|
|
- RENDER_CONFIGS.put(AppSettings.LWJGL_OPENGL30, () -> {
|
|
|
|
- // Based on GLFW docs for OpenGL version below 3.2,
|
|
|
|
- // GLFW_OPENGL_ANY_PROFILE must be used.
|
|
|
|
- glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_ANY_PROFILE);
|
|
|
|
- glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
|
|
|
- glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
|
|
|
|
- });
|
|
|
|
- RENDER_CONFIGS.put(AppSettings.LWJGL_OPENGL31, () -> {
|
|
|
|
- // Based on GLFW docs for OpenGL version below 3.2,
|
|
|
|
- // GLFW_OPENGL_ANY_PROFILE must be used.
|
|
|
|
- glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_ANY_PROFILE);
|
|
|
|
- glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
|
|
|
- glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
|
|
|
|
- });
|
|
|
|
- RENDER_CONFIGS.put(AppSettings.LWJGL_OPENGL32, () -> {
|
|
|
|
- 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_OPENGL40, () -> {
|
|
|
|
- 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);
|
|
|
|
- });
|
|
|
|
|
|
+ RENDER_CONFIGS.put(
|
|
|
|
+ AppSettings.LWJGL_OPENGL30,
|
|
|
|
+ () -> {
|
|
|
|
+ // Based on GLFW docs for OpenGL version below 3.2,
|
|
|
|
+ // GLFW_OPENGL_ANY_PROFILE must be used.
|
|
|
|
+ glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_ANY_PROFILE);
|
|
|
|
+ glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
|
|
|
+ glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
|
|
|
|
+ }
|
|
|
|
+ );
|
|
|
|
+ RENDER_CONFIGS.put(
|
|
|
|
+ AppSettings.LWJGL_OPENGL31,
|
|
|
|
+ () -> {
|
|
|
|
+ // Based on GLFW docs for OpenGL version below 3.2,
|
|
|
|
+ // GLFW_OPENGL_ANY_PROFILE must be used.
|
|
|
|
+ glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_ANY_PROFILE);
|
|
|
|
+ glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
|
|
|
+ glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
|
|
|
|
+ }
|
|
|
|
+ );
|
|
|
|
+ RENDER_CONFIGS.put(
|
|
|
|
+ AppSettings.LWJGL_OPENGL32,
|
|
|
|
+ () -> {
|
|
|
|
+ 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_OPENGL40,
|
|
|
|
+ () -> {
|
|
|
|
+ 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);
|
|
|
|
|
|
private final JmeContext.Type type;
|
|
private final JmeContext.Type type;
|
|
- private final SafeArrayList<WindowSizeListener> windowSizeListeners = new SafeArrayList<>(WindowSizeListener.class);
|
|
|
|
|
|
+ private final SafeArrayList<WindowSizeListener> windowSizeListeners = new SafeArrayList<>(
|
|
|
|
+ WindowSizeListener.class
|
|
|
|
+ );
|
|
|
|
|
|
private GLFWErrorCallback errorCallback;
|
|
private GLFWErrorCallback errorCallback;
|
|
private GLFWWindowSizeCallback windowSizeCallback;
|
|
private GLFWWindowSizeCallback windowSizeCallback;
|
|
@@ -170,7 +201,6 @@ public abstract class LwjglWindow extends LwjglContext implements Runnable {
|
|
private final Vector2f oldScale = new Vector2f(1, 1);
|
|
private final Vector2f oldScale = new Vector2f(1, 1);
|
|
|
|
|
|
public LwjglWindow(final JmeContext.Type type) {
|
|
public LwjglWindow(final JmeContext.Type type) {
|
|
-
|
|
|
|
if (!SUPPORTED_TYPES.contains(type)) {
|
|
if (!SUPPORTED_TYPES.contains(type)) {
|
|
throw new IllegalArgumentException("Unsupported type '" + type.name() + "' provided");
|
|
throw new IllegalArgumentException("Unsupported type '" + type.name() + "' provided");
|
|
}
|
|
}
|
|
@@ -234,13 +264,16 @@ public abstract class LwjglWindow extends LwjglContext implements Runnable {
|
|
* @param settings the settings to apply when creating the context.
|
|
* @param settings the settings to apply when creating the context.
|
|
*/
|
|
*/
|
|
protected void createContext(final AppSettings settings) {
|
|
protected void createContext(final AppSettings settings) {
|
|
- glfwSetErrorCallback(errorCallback = new GLFWErrorCallback() {
|
|
|
|
- @Override
|
|
|
|
- public void invoke(int error, long description) {
|
|
|
|
- final String message = GLFWErrorCallback.getDescription(description);
|
|
|
|
- listener.handleError(message, new Exception(message));
|
|
|
|
- }
|
|
|
|
- });
|
|
|
|
|
|
+ glfwSetErrorCallback(
|
|
|
|
+ errorCallback =
|
|
|
|
+ new GLFWErrorCallback() {
|
|
|
|
+ @Override
|
|
|
|
+ public void invoke(int error, long description) {
|
|
|
|
+ final String message = GLFWErrorCallback.getDescription(description);
|
|
|
|
+ listener.handleError(message, new Exception(message));
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ );
|
|
|
|
|
|
if (!glfwInit()) {
|
|
if (!glfwInit()) {
|
|
throw new IllegalStateException("Unable to initialize GLFW");
|
|
throw new IllegalStateException("Unable to initialize GLFW");
|
|
@@ -253,12 +286,18 @@ 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);
|
|
|
|
|
|
- RENDER_CONFIGS.computeIfAbsent(renderer, s -> () -> {
|
|
|
|
- glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_FALSE);
|
|
|
|
- glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_ANY_PROFILE);
|
|
|
|
- glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
|
|
|
|
- glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
|
|
|
|
- }).run();
|
|
|
|
|
|
+ RENDER_CONFIGS
|
|
|
|
+ .computeIfAbsent(
|
|
|
|
+ renderer,
|
|
|
|
+ s ->
|
|
|
|
+ () -> {
|
|
|
|
+ glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_FALSE);
|
|
|
|
+ glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_ANY_PROFILE);
|
|
|
|
+ glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
|
|
|
|
+ glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
|
|
|
|
+ }
|
|
|
|
+ )
|
|
|
|
+ .run();
|
|
|
|
|
|
if (settings.getBoolean("RendererDebug")) {
|
|
if (settings.getBoolean("RendererDebug")) {
|
|
glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GLFW_TRUE);
|
|
glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GLFW_TRUE);
|
|
@@ -274,8 +313,14 @@ public abstract class LwjglWindow extends LwjglContext implements Runnable {
|
|
glfwWindowHint(GLFW_STENCIL_BITS, settings.getStencilBits());
|
|
glfwWindowHint(GLFW_STENCIL_BITS, settings.getStencilBits());
|
|
glfwWindowHint(GLFW_SAMPLES, settings.getSamples());
|
|
glfwWindowHint(GLFW_SAMPLES, settings.getSamples());
|
|
glfwWindowHint(GLFW_STEREO, settings.useStereo3D() ? GLFW_TRUE : GLFW_FALSE);
|
|
glfwWindowHint(GLFW_STEREO, settings.useStereo3D() ? GLFW_TRUE : GLFW_FALSE);
|
|
- glfwWindowHint(GLFW_REFRESH_RATE, settings.getFrequency()<=0?GLFW_DONT_CARE:settings.getFrequency());
|
|
|
|
- glfwWindowHint(GLFW_COCOA_RETINA_FRAMEBUFFER, settings.isUseRetinaFrameBuffer() ? GLFW_TRUE : GLFW_FALSE);
|
|
|
|
|
|
+ glfwWindowHint(
|
|
|
|
+ GLFW_REFRESH_RATE,
|
|
|
|
+ settings.getFrequency() <= 0 ? GLFW_DONT_CARE : settings.getFrequency()
|
|
|
|
+ );
|
|
|
|
+ glfwWindowHint(
|
|
|
|
+ GLFW_COCOA_RETINA_FRAMEBUFFER,
|
|
|
|
+ settings.isUseRetinaFrameBuffer() ? GLFW_TRUE : GLFW_FALSE
|
|
|
|
+ );
|
|
|
|
|
|
if (settings.getBitsPerPixel() == 24) {
|
|
if (settings.getBitsPerPixel() == 24) {
|
|
glfwWindowHint(GLFW_RED_BITS, 8);
|
|
glfwWindowHint(GLFW_RED_BITS, 8);
|
|
@@ -289,65 +334,65 @@ public abstract class LwjglWindow extends LwjglContext implements Runnable {
|
|
|
|
|
|
glfwWindowHint(GLFW_ALPHA_BITS, settings.getAlphaBits());
|
|
glfwWindowHint(GLFW_ALPHA_BITS, settings.getAlphaBits());
|
|
|
|
|
|
-// long monitor = NULL;
|
|
|
|
|
|
+ // long monitor = NULL;
|
|
|
|
|
|
/**
|
|
/**
|
|
* Let's grab the display selected, if not found it will return
|
|
* Let's grab the display selected, if not found it will return
|
|
* primaryMonitor. if not full screen just use primary display data.
|
|
* primaryMonitor. if not full screen just use primary display data.
|
|
*/
|
|
*/
|
|
if (settings.isFullscreen()) {
|
|
if (settings.isFullscreen()) {
|
|
- monitor = getDisplay(settings.getDisplay());
|
|
|
|
|
|
+ monitor = getDisplay(settings.getDisplay());
|
|
} else {
|
|
} else {
|
|
- monitor = glfwGetPrimaryMonitor();
|
|
|
|
|
|
+ monitor = glfwGetPrimaryMonitor();
|
|
}
|
|
}
|
|
|
|
|
|
final GLFWVidMode videoMode = glfwGetVideoMode(monitor);
|
|
final GLFWVidMode videoMode = glfwGetVideoMode(monitor);
|
|
int requestWidth = settings.getWindowWidth();
|
|
int requestWidth = settings.getWindowWidth();
|
|
int requestHeight = settings.getWindowHeight();
|
|
int requestHeight = settings.getWindowHeight();
|
|
if (requestWidth <= 0 || requestHeight <= 0) {
|
|
if (requestWidth <= 0 || requestHeight <= 0) {
|
|
- requestWidth = videoMode.width();
|
|
|
|
- requestHeight = videoMode.height();
|
|
|
|
|
|
+ requestWidth = videoMode.width();
|
|
|
|
+ requestHeight = videoMode.height();
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
// Lets use the monitor selected from AppSettings if FullScreen is
|
|
// Lets use the monitor selected from AppSettings if FullScreen is
|
|
// set.
|
|
// set.
|
|
- if (settings.isFullscreen())
|
|
|
|
- window = glfwCreateWindow(requestWidth, requestHeight,
|
|
|
|
- settings.getTitle(), monitor, NULL);
|
|
|
|
- else
|
|
|
|
- window = glfwCreateWindow(requestWidth, requestHeight,
|
|
|
|
- settings.getTitle(), NULL, NULL);
|
|
|
|
|
|
+ if (settings.isFullscreen()) window =
|
|
|
|
+ glfwCreateWindow(requestWidth, requestHeight, settings.getTitle(), monitor, NULL); else window =
|
|
|
|
+ glfwCreateWindow(requestWidth, requestHeight, settings.getTitle(), NULL, NULL);
|
|
|
|
|
|
if (window == NULL) {
|
|
if (window == NULL) {
|
|
throw new RuntimeException("Failed to create the GLFW window");
|
|
throw new RuntimeException("Failed to create the GLFW window");
|
|
}
|
|
}
|
|
|
|
|
|
- glfwSetWindowFocusCallback(window, windowFocusCallback = new GLFWWindowFocusCallback() {
|
|
|
|
-
|
|
|
|
- @Override
|
|
|
|
- public void invoke(final long window, final boolean focus) {
|
|
|
|
- if (wasActive != focus) {
|
|
|
|
- if (!wasActive) {
|
|
|
|
- listener.gainFocus();
|
|
|
|
- timer.reset();
|
|
|
|
- } else {
|
|
|
|
- listener.loseFocus();
|
|
|
|
|
|
+ glfwSetWindowFocusCallback(
|
|
|
|
+ window,
|
|
|
|
+ windowFocusCallback =
|
|
|
|
+ new GLFWWindowFocusCallback() {
|
|
|
|
+ @Override
|
|
|
|
+ public void invoke(final long window, final boolean focus) {
|
|
|
|
+ if (wasActive != focus) {
|
|
|
|
+ if (!wasActive) {
|
|
|
|
+ listener.gainFocus();
|
|
|
|
+ timer.reset();
|
|
|
|
+ } else {
|
|
|
|
+ listener.loseFocus();
|
|
|
|
+ }
|
|
|
|
+ wasActive = !wasActive;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
- wasActive = !wasActive;
|
|
|
|
}
|
|
}
|
|
- }
|
|
|
|
- });
|
|
|
|
|
|
+ );
|
|
|
|
|
|
if (!settings.isFullscreen()) {
|
|
if (!settings.isFullscreen()) {
|
|
if (settings.getCenterWindow()) {
|
|
if (settings.getCenterWindow()) {
|
|
// Center the window
|
|
// Center the window
|
|
- glfwSetWindowPos(window,
|
|
|
|
- (videoMode.width() - requestWidth) / 2,
|
|
|
|
- (videoMode.height() - requestHeight) / 2);
|
|
|
|
|
|
+ glfwSetWindowPos(
|
|
|
|
+ window,
|
|
|
|
+ (videoMode.width() - requestWidth) / 2,
|
|
|
|
+ (videoMode.height() - requestHeight) / 2
|
|
|
|
+ );
|
|
} else {
|
|
} else {
|
|
- glfwSetWindowPos(window,
|
|
|
|
- settings.getWindowXPosition(),
|
|
|
|
- settings.getWindowYPosition());
|
|
|
|
|
|
+ glfwSetWindowPos(window, settings.getWindowXPosition(), settings.getWindowYPosition());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -367,24 +412,30 @@ public abstract class LwjglWindow extends LwjglContext implements Runnable {
|
|
// HACK: the framebuffer seems to be initialized with the wrong size
|
|
// HACK: the framebuffer seems to be initialized with the wrong size
|
|
// on some HiDPI platforms until glfwPollEvents is called 2 or 3 times
|
|
// on some HiDPI platforms until glfwPollEvents is called 2 or 3 times
|
|
for (int i = 0; i < 4; i++) glfwPollEvents();
|
|
for (int i = 0; i < 4; i++) glfwPollEvents();
|
|
-
|
|
|
|
- // Windows resize callback
|
|
|
|
- glfwSetWindowSizeCallback(window, windowSizeCallback = new GLFWWindowSizeCallback() {
|
|
|
|
|
|
|
|
- @Override
|
|
|
|
- public void invoke(final long window, final int width, final int height) {
|
|
|
|
- updateSizes();
|
|
|
|
- }
|
|
|
|
- });
|
|
|
|
|
|
+ // Windows resize callback
|
|
|
|
+ glfwSetWindowSizeCallback(
|
|
|
|
+ window,
|
|
|
|
+ windowSizeCallback =
|
|
|
|
+ new GLFWWindowSizeCallback() {
|
|
|
|
+ @Override
|
|
|
|
+ public void invoke(final long window, final int width, final int height) {
|
|
|
|
+ updateSizes();
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ );
|
|
|
|
|
|
// Add a framebuffer resize callback which delegates to the listener
|
|
// Add a framebuffer resize callback which delegates to the listener
|
|
- glfwSetFramebufferSizeCallback(window, framebufferSizeCallback = new GLFWFramebufferSizeCallback() {
|
|
|
|
-
|
|
|
|
- @Override
|
|
|
|
- public void invoke(final long window, final int width, final int height) {
|
|
|
|
- updateSizes();
|
|
|
|
- }
|
|
|
|
- });
|
|
|
|
|
|
+ glfwSetFramebufferSizeCallback(
|
|
|
|
+ window,
|
|
|
|
+ framebufferSizeCallback =
|
|
|
|
+ new GLFWFramebufferSizeCallback() {
|
|
|
|
+ @Override
|
|
|
|
+ public void invoke(final long window, final int width, final int height) {
|
|
|
|
+ updateSizes();
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ );
|
|
|
|
|
|
allowSwapBuffers = settings.isSwapBuffers();
|
|
allowSwapBuffers = settings.isSwapBuffers();
|
|
|
|
|
|
@@ -402,8 +453,7 @@ public abstract class LwjglWindow extends LwjglContext implements Runnable {
|
|
glfwGetWindowSize(window, width, height);
|
|
glfwGetWindowSize(window, width, height);
|
|
int windowWidth = width[0] < 1 ? 1 : width[0];
|
|
int windowWidth = width[0] < 1 ? 1 : width[0];
|
|
int windowHeight = height[0] < 1 ? 1 : height[0];
|
|
int windowHeight = height[0] < 1 ? 1 : height[0];
|
|
- if (settings.getWindowWidth() != windowWidth
|
|
|
|
- || settings.getWindowHeight() != windowHeight) {
|
|
|
|
|
|
+ if (settings.getWindowWidth() != windowWidth || settings.getWindowHeight() != windowHeight) {
|
|
settings.setWindowSize(windowWidth, windowHeight);
|
|
settings.setWindowSize(windowWidth, windowHeight);
|
|
for (WindowSizeListener wsListener : windowSizeListeners.getArray()) {
|
|
for (WindowSizeListener wsListener : windowSizeListeners.getArray()) {
|
|
wsListener.onWindowSizeChanged(windowWidth, windowHeight);
|
|
wsListener.onWindowSizeChanged(windowWidth, windowHeight);
|
|
@@ -413,8 +463,7 @@ public abstract class LwjglWindow extends LwjglContext implements Runnable {
|
|
glfwGetFramebufferSize(window, width, height);
|
|
glfwGetFramebufferSize(window, width, height);
|
|
int framebufferWidth = width[0];
|
|
int framebufferWidth = width[0];
|
|
int framebufferHeight = height[0];
|
|
int framebufferHeight = height[0];
|
|
- if (framebufferWidth != oldFramebufferWidth
|
|
|
|
- || framebufferHeight != oldFramebufferHeight) {
|
|
|
|
|
|
+ if (framebufferWidth != oldFramebufferWidth || framebufferHeight != oldFramebufferHeight) {
|
|
settings.setResolution(framebufferWidth, framebufferHeight);
|
|
settings.setResolution(framebufferWidth, framebufferHeight);
|
|
listener.reshape(framebufferWidth, framebufferHeight);
|
|
listener.reshape(framebufferWidth, framebufferHeight);
|
|
|
|
|
|
@@ -441,14 +490,12 @@ public abstract class LwjglWindow extends LwjglContext implements Runnable {
|
|
* @param settings settings for getting the icons
|
|
* @param settings settings for getting the icons
|
|
*/
|
|
*/
|
|
protected void setWindowIcon(final AppSettings settings) {
|
|
protected void setWindowIcon(final AppSettings settings) {
|
|
-
|
|
|
|
final Object[] icons = settings.getIcons();
|
|
final Object[] icons = settings.getIcons();
|
|
if (icons == null) return;
|
|
if (icons == null) return;
|
|
|
|
|
|
final GLFWImage[] images = imagesToGLFWImages(icons);
|
|
final GLFWImage[] images = imagesToGLFWImages(icons);
|
|
|
|
|
|
try (final GLFWImage.Buffer iconSet = GLFWImage.malloc(images.length)) {
|
|
try (final GLFWImage.Buffer iconSet = GLFWImage.malloc(images.length)) {
|
|
-
|
|
|
|
for (int i = images.length - 1; i >= 0; i--) {
|
|
for (int i = images.length - 1; i >= 0; i--) {
|
|
final GLFWImage image = images[i];
|
|
final GLFWImage image = images[i];
|
|
iconSet.put(i, image);
|
|
iconSet.put(i, image);
|
|
@@ -462,7 +509,6 @@ public abstract class LwjglWindow extends LwjglContext implements Runnable {
|
|
* Convert array of images to array of {@link GLFWImage}.
|
|
* Convert array of images to array of {@link GLFWImage}.
|
|
*/
|
|
*/
|
|
private GLFWImage[] imagesToGLFWImages(final Object[] images) {
|
|
private GLFWImage[] imagesToGLFWImages(final Object[] images) {
|
|
-
|
|
|
|
final GLFWImage[] out = new GLFWImage[images.length];
|
|
final GLFWImage[] out = new GLFWImage[images.length];
|
|
|
|
|
|
for (int i = 0; i < images.length; i++) {
|
|
for (int i = 0; i < images.length; i++) {
|
|
@@ -477,10 +523,12 @@ public abstract class LwjglWindow extends LwjglContext implements Runnable {
|
|
* Convert the {@link BufferedImage} to the {@link GLFWImage}.
|
|
* Convert the {@link BufferedImage} to the {@link GLFWImage}.
|
|
*/
|
|
*/
|
|
private GLFWImage imageToGLFWImage(BufferedImage image) {
|
|
private GLFWImage imageToGLFWImage(BufferedImage image) {
|
|
-
|
|
|
|
if (image.getType() != BufferedImage.TYPE_INT_ARGB_PRE) {
|
|
if (image.getType() != BufferedImage.TYPE_INT_ARGB_PRE) {
|
|
-
|
|
|
|
- final BufferedImage convertedImage = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_ARGB_PRE);
|
|
|
|
|
|
+ final BufferedImage convertedImage = new BufferedImage(
|
|
|
|
+ image.getWidth(),
|
|
|
|
+ image.getHeight(),
|
|
|
|
+ BufferedImage.TYPE_INT_ARGB_PRE
|
|
|
|
+ );
|
|
final Graphics2D graphics = convertedImage.createGraphics();
|
|
final Graphics2D graphics = convertedImage.createGraphics();
|
|
|
|
|
|
final int targetWidth = image.getWidth();
|
|
final int targetWidth = image.getWidth();
|
|
@@ -522,7 +570,6 @@ public abstract class LwjglWindow extends LwjglContext implements Runnable {
|
|
}
|
|
}
|
|
|
|
|
|
if (errorCallback != null) {
|
|
if (errorCallback != null) {
|
|
-
|
|
|
|
// We need to specifically set this to null as we might set a new callback before we reinit GLFW
|
|
// We need to specifically set this to null as we might set a new callback before we reinit GLFW
|
|
glfwSetErrorCallback(null);
|
|
glfwSetErrorCallback(null);
|
|
|
|
|
|
@@ -549,7 +596,6 @@ public abstract class LwjglWindow extends LwjglContext implements Runnable {
|
|
glfwDestroyWindow(window);
|
|
glfwDestroyWindow(window);
|
|
window = NULL;
|
|
window = NULL;
|
|
}
|
|
}
|
|
-
|
|
|
|
} catch (final Exception ex) {
|
|
} catch (final Exception ex) {
|
|
listener.handleError("Failed to destroy context", ex);
|
|
listener.handleError("Failed to destroy context", ex);
|
|
}
|
|
}
|
|
@@ -577,7 +623,6 @@ public abstract class LwjglWindow extends LwjglContext implements Runnable {
|
|
waitFor(true);
|
|
waitFor(true);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
-
|
|
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -589,14 +634,16 @@ 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((thread, thrown) -> {
|
|
|
|
- listener.handleError("Uncaught exception thrown in " + thread.toString(), thrown);
|
|
|
|
- if (needClose.get()) {
|
|
|
|
- // listener.handleError() has requested the
|
|
|
|
- // context to close. Satisfy request.
|
|
|
|
- deinitInThread();
|
|
|
|
- }
|
|
|
|
- });
|
|
|
|
|
|
+ Thread
|
|
|
|
+ .currentThread()
|
|
|
|
+ .setUncaughtExceptionHandler((thread, thrown) -> {
|
|
|
|
+ listener.handleError("Uncaught exception thrown in " + thread.toString(), thrown);
|
|
|
|
+ if (needClose.get()) {
|
|
|
|
+ // listener.handleError() has requested the
|
|
|
|
+ // context to close. Satisfy request.
|
|
|
|
+ deinitInThread();
|
|
|
|
+ }
|
|
|
|
+ });
|
|
}
|
|
}
|
|
|
|
|
|
timer = new NanoTimer();
|
|
timer = new NanoTimer();
|
|
@@ -630,7 +677,6 @@ public abstract class LwjglWindow extends LwjglContext implements Runnable {
|
|
return true;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|
|
/**
|
|
/**
|
|
* execute one iteration of the render loop in the OpenGL thread
|
|
* execute one iteration of the render loop in the OpenGL thread
|
|
*/
|
|
*/
|
|
@@ -644,7 +690,6 @@ public abstract class LwjglWindow extends LwjglContext implements Runnable {
|
|
throw new IllegalStateException();
|
|
throw new IllegalStateException();
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|
|
listener.update();
|
|
listener.update();
|
|
|
|
|
|
// All this does is call glfwSwapBuffers().
|
|
// All this does is call glfwSwapBuffers().
|
|
@@ -721,8 +766,9 @@ public abstract class LwjglWindow extends LwjglContext implements Runnable {
|
|
@Override
|
|
@Override
|
|
public void run() {
|
|
public void run() {
|
|
if (listener == null) {
|
|
if (listener == null) {
|
|
- throw new IllegalStateException("SystemListener is not set on context!"
|
|
|
|
- + "Must set with JmeContext.setSystemListener().");
|
|
|
|
|
|
+ throw new IllegalStateException(
|
|
|
|
+ "SystemListener is not set on context!" + "Must set with JmeContext.setSystemListener()."
|
|
|
|
+ );
|
|
}
|
|
}
|
|
|
|
|
|
LOGGER.log(Level.FINE, "Using LWJGL {0}", Version.getVersion());
|
|
LOGGER.log(Level.FINE, "Using LWJGL {0}", Version.getVersion());
|
|
@@ -733,7 +779,6 @@ public abstract class LwjglWindow extends LwjglContext implements Runnable {
|
|
}
|
|
}
|
|
|
|
|
|
while (true) {
|
|
while (true) {
|
|
-
|
|
|
|
runLoop();
|
|
runLoop();
|
|
|
|
|
|
if (needClose.get()) {
|
|
if (needClose.get()) {
|
|
@@ -873,76 +918,80 @@ public abstract class LwjglWindow extends LwjglContext implements Runnable {
|
|
int result = height[0];
|
|
int result = height[0];
|
|
return result;
|
|
return result;
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
/**
|
|
/**
|
|
* Returns the Primary Monitor position number from the list of monitors
|
|
* Returns the Primary Monitor position number from the list of monitors
|
|
* returned by glfwGetPrimaryMonitor(). If primary monitor not found
|
|
* returned by glfwGetPrimaryMonitor(). If primary monitor not found
|
|
* it will return -1 and report the error.
|
|
* it will return -1 and report the error.
|
|
- *
|
|
|
|
|
|
+ *
|
|
* @return returns the Primary Monitor Position.
|
|
* @return returns the Primary Monitor Position.
|
|
*/
|
|
*/
|
|
@Override
|
|
@Override
|
|
- public int getPrimaryDisplay()
|
|
|
|
- {
|
|
|
|
- long prim = glfwGetPrimaryMonitor();
|
|
|
|
- Displays monitors = getDisplays();
|
|
|
|
- for ( int i = 0; i < monitors.size(); i++ ) {
|
|
|
|
- long monitorI = monitors.get(i).displayID;
|
|
|
|
- if (monitorI == prim)
|
|
|
|
- return i;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- LOGGER.log(Level.SEVERE,"Couldn't locate Primary Monitor in the list of Monitors.");
|
|
|
|
- return -1;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
-
|
|
|
|
|
|
+ public int getPrimaryDisplay() {
|
|
|
|
+ long prim = glfwGetPrimaryMonitor();
|
|
|
|
+ Displays monitors = getDisplays();
|
|
|
|
+ for (int i = 0; i < monitors.size(); i++) {
|
|
|
|
+ long monitorI = monitors.get(i).displayID;
|
|
|
|
+ if (monitorI == prim) return i;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ LOGGER.log(Level.SEVERE, "Couldn't locate Primary Monitor in the list of Monitors.");
|
|
|
|
+ return -1;
|
|
|
|
+ }
|
|
|
|
+
|
|
/**
|
|
/**
|
|
* This routines return the display ID by position in an array of display returned
|
|
* This routines return the display ID by position in an array of display returned
|
|
* by glfwGetMonitors().
|
|
* by glfwGetMonitors().
|
|
- *
|
|
|
|
|
|
+ *
|
|
* @param pos the position of the display in the list of displays returned.
|
|
* @param pos the position of the display in the list of displays returned.
|
|
* @return return the displayID if found otherwise return Primary display
|
|
* @return return the displayID if found otherwise return Primary display
|
|
*/
|
|
*/
|
|
private long getDisplay(int pos) {
|
|
private long getDisplay(int pos) {
|
|
- Displays displays = getDisplays();
|
|
|
|
- if (pos < displays.size())
|
|
|
|
- return displays.get(pos).displayID;
|
|
|
|
-
|
|
|
|
- LOGGER.log(Level.SEVERE,"Couldn't locate Display requested in the list of Displays. pos:"+pos+" size: "+ displays.size());
|
|
|
|
- return glfwGetPrimaryMonitor();
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
|
|
+ Displays displays = getDisplays();
|
|
|
|
+ if (pos < displays.size()) return displays.get(pos).displayID;
|
|
|
|
+
|
|
|
|
+ LOGGER.log(
|
|
|
|
+ Level.SEVERE,
|
|
|
|
+ "Couldn't locate Display requested in the list of Displays. pos:" +
|
|
|
|
+ pos +
|
|
|
|
+ " size: " +
|
|
|
|
+ displays.size()
|
|
|
|
+ );
|
|
|
|
+ return glfwGetPrimaryMonitor();
|
|
|
|
+ }
|
|
|
|
+
|
|
/**
|
|
/**
|
|
* This returns an arraylist of all the Display returned by OpenGL get Monitor
|
|
* This returns an arraylist of all the Display returned by OpenGL get Monitor
|
|
* call. It will also has some limited information about each display, like:
|
|
* call. It will also has some limited information about each display, like:
|
|
* width, height and refresh rate.
|
|
* width, height and refresh rate.
|
|
- *
|
|
|
|
|
|
+ *
|
|
* @return returns an ArrayList of all Display returned by glfwGetMonitors()
|
|
* @return returns an ArrayList of all Display returned by glfwGetMonitors()
|
|
*/
|
|
*/
|
|
-
|
|
|
|
|
|
+
|
|
@Override
|
|
@Override
|
|
- public Displays getDisplays() {
|
|
|
|
- PointerBuffer displays = glfwGetMonitors();
|
|
|
|
- long primary = glfwGetPrimaryMonitor();
|
|
|
|
- Displays displayList = new Displays();
|
|
|
|
-
|
|
|
|
- for ( int i = 0; i < displays.limit(); i++ ) {
|
|
|
|
- long monitorI = displays.get(i);
|
|
|
|
- int monPos = displayList.addNewMonitor(monitorI);
|
|
|
|
- //lets check if this display is the primary display. If use mark it as such.
|
|
|
|
- if (primary == monitorI)
|
|
|
|
- displayList.setPrimaryDisplay(monPos);
|
|
|
|
-
|
|
|
|
- final GLFWVidMode modes = glfwGetVideoMode(monitorI);
|
|
|
|
- String name = glfwGetMonitorName(monitorI);
|
|
|
|
-
|
|
|
|
- int width = modes.width();
|
|
|
|
- int height = modes.height();
|
|
|
|
- int rate = modes.refreshRate();
|
|
|
|
- displayList.setInfo(monPos, name, width, height, rate);
|
|
|
|
- LOGGER.log(Level.INFO, "Display id: "+monitorI+" Resolution: " + width + " x " + height + " @ " + rate);
|
|
|
|
- }
|
|
|
|
- return displayList;
|
|
|
|
|
|
+ public Displays getDisplays() {
|
|
|
|
+ PointerBuffer displays = glfwGetMonitors();
|
|
|
|
+ long primary = glfwGetPrimaryMonitor();
|
|
|
|
+ Displays displayList = new Displays();
|
|
|
|
+
|
|
|
|
+ for (int i = 0; i < displays.limit(); i++) {
|
|
|
|
+ long monitorI = displays.get(i);
|
|
|
|
+ int monPos = displayList.addNewMonitor(monitorI);
|
|
|
|
+ //lets check if this display is the primary display. If use mark it as such.
|
|
|
|
+ if (primary == monitorI) displayList.setPrimaryDisplay(monPos);
|
|
|
|
+
|
|
|
|
+ final GLFWVidMode modes = glfwGetVideoMode(monitorI);
|
|
|
|
+ String name = glfwGetMonitorName(monitorI);
|
|
|
|
+
|
|
|
|
+ int width = modes.width();
|
|
|
|
+ int height = modes.height();
|
|
|
|
+ int rate = modes.refreshRate();
|
|
|
|
+ displayList.setInfo(monPos, name, width, height, rate);
|
|
|
|
+ LOGGER.log(
|
|
|
|
+ Level.INFO,
|
|
|
|
+ "Display id: " + monitorI + " Resolution: " + width + " x " + height + " @ " + rate
|
|
|
|
+ );
|
|
|
|
+ }
|
|
|
|
+ return displayList;
|
|
}
|
|
}
|
|
}
|
|
}
|