From 3a96def36e431e76c63aa834436e4d00024669c9 Mon Sep 17 00:00:00 2001 From: wil Date: Wed, 29 Nov 2023 17:39:02 -0600 Subject: [PATCH 01/15] Canvas rendering solution using lwjgl-jawt --- jme3-lwjgl3/build.gradle | 4 + .../com/jme3/system/lwjgl/LwjglCanvas.java | 372 ++++++++++++++++++ 2 files changed, 376 insertions(+) create mode 100644 jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglCanvas.java diff --git a/jme3-lwjgl3/build.gradle b/jme3-lwjgl3/build.gradle index c3cb630545..256c09631f 100644 --- a/jme3-lwjgl3/build.gradle +++ b/jme3-lwjgl3/build.gradle @@ -1,8 +1,12 @@ dependencies { api project(':jme3-core') + api project(':jme3-desktop') + + api "org.lwjglx:lwjgl3-awt:0.1.8" api "org.lwjgl:lwjgl:${lwjgl3Version}" api "org.lwjgl:lwjgl-glfw:${lwjgl3Version}" + api "org.lwjgl:lwjgl-jawt:${lwjgl3Version}" api "org.lwjgl:lwjgl-jemalloc:${lwjgl3Version}" api "org.lwjgl:lwjgl-openal:${lwjgl3Version}" api "org.lwjgl:lwjgl-opencl:${lwjgl3Version}" diff --git a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglCanvas.java b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglCanvas.java new file mode 100644 index 0000000000..e22d8c30be --- /dev/null +++ b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglCanvas.java @@ -0,0 +1,372 @@ +/* + * Copyright (c) 2009-2023 jMonkeyEngine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'jMonkeyEngine' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.jme3.system.lwjgl; + +import com.jme3.input.KeyInput; +import com.jme3.input.MouseInput; +import com.jme3.input.awt.AwtKeyInput; +import com.jme3.input.awt.AwtMouseInput; +import com.jme3.system.AppSettings; +import com.jme3.system.JmeCanvasContext; + +import java.awt.Canvas; +import java.awt.GraphicsConfiguration; +import java.awt.event.ComponentAdapter; +import java.awt.event.ComponentEvent; +import java.awt.event.ComponentListener; +import java.awt.geom.AffineTransform; +import java.util.concurrent.Semaphore; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.lwjgl.opengl.awt.AWTGLCanvas; +import org.lwjgl.opengl.awt.GLData; + +/** + * Class LwjglCanvas that integrates LWJGLX + * which allows using AWT-Swing components. + * + * @author wil + */ +public class LwjglCanvas extends LwjglWindow implements JmeCanvasContext, Runnable { + + /** Logger class. */ + private static final Logger LOGGER = Logger.getLogger(LwjglCanvas.class.getName()); + + private class LwjglAWTGLCanvas extends AWTGLCanvas { + + public LwjglAWTGLCanvas(GLData data) { + super(data); + } + + @Override + public void initGL() { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public void paintGL() { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public synchronized void addComponentListener(ComponentListener l) { + super.addComponentListener(l); + } + + @Override + public void afterRender() { + super.afterRender(); + } + + @Override + public void beforeRender() { + super.beforeRender(); + } + + @Override + public void disposeCanvas() { } + + public void doDisposeCanvas() { + super.disposeCanvas(); + } + + public void deleteContext() { + platformCanvas.deleteContext(context); + } + + @Override + public void addNotify() { + super.addNotify(); + synchronized (lock) { + hasNativePeer.set(true); + } + requestFocusInWindow(); + } + + @Override + public void removeNotify() { + synchronized (lock) { + hasNativePeer.set(false); + } + super.removeNotify(); + } + } + + private final LwjglAWTGLCanvas canvas; + private GLData glData; + + private final AtomicBoolean hasNativePeer = new AtomicBoolean(false); + private final AtomicBoolean showing = new AtomicBoolean(false); + private AtomicBoolean needResize = new AtomicBoolean(false); + + private final Semaphore signalTerminate = new Semaphore(0); + private final Semaphore signalTerminated = new Semaphore(0); + + private final Object lock = new Object(); + private int framebufferWidth = 1; + private int framebufferHeight = 1; + + private AwtKeyInput keyInput; + private AwtMouseInput mouseInput; + + public LwjglCanvas() { + super(Type.Canvas); + + glData = new GLData(); + canvas = new LwjglAWTGLCanvas(glData); + canvas.setIgnoreRepaint(true); + canvas.addComponentListener(new ComponentAdapter() { + @Override + public void componentResized(ComponentEvent e) { + synchronized (lock) { + GraphicsConfiguration gc = canvas.getGraphicsConfiguration(); + if (gc == null) { + return; + } + + AffineTransform at = gc.getDefaultTransform(); + float sx = (float) at.getScaleX(), + sy = (float) at.getScaleY(); + + int fw = (int) (canvas.getWidth() * sx); + int fh = (int) (canvas.getHeight() * sy); + + if (fw != framebufferWidth || fh != framebufferHeight) { + framebufferWidth = Math.max(fw, 1); + framebufferHeight = Math.max(fh, 1); + needResize.set(true); + } + } + } + }); + } + + @Override + protected void createContext(AppSettings settings) { + super.createContext(settings); + if (settings.getBitsPerPixel() == 24) { + glData.redSize = 8; + glData.greenSize = 8; + glData.blueSize = 8; + } else if (settings.getBitsPerPixel() == 16) { + glData.redSize = 5; + glData.greenSize = 6; + glData.blueSize = 5; + } + + glData.depthSize = settings.getBitsPerPixel(); + glData.alphaSize = settings.getAlphaBits(); + glData.sRGB = settings.isGammaCorrection(); + + glData.depthSize = settings.getDepthBits(); + glData.stencilSize = settings.getStencilBits(); + glData.samples = settings.getSamples(); + glData.stereo = settings.useStereo3D(); + + glData.debug = settings.isGraphicsDebug(); + glData.profile = GLData.Profile.CORE; + glData.api = GLData.API.GL; + } + + @Override + public Canvas getCanvas() { + return canvas; + } + + @Override + protected void showWindow() { + } + + @Override + protected void setWindowIcon(final AppSettings settings) { + } + + @Override + public void setTitle(String title) { + } + + @Override + public KeyInput getKeyInput() { + if (keyInput == null) { + keyInput = new AwtKeyInput(); + keyInput.setInputSource(canvas); + } + return keyInput; + } + + @Override + public MouseInput getMouseInput() { + if (mouseInput == null) { + mouseInput = new AwtMouseInput(); + mouseInput.setInputSource(canvas); + } + return mouseInput; + } + + public boolean checkVisibilityState() { + if (!hasNativePeer.get()) { + synchronized (lock) { + canvas.doDisposeCanvas(); + } + return false; + } + + boolean currentShowing = canvas.isShowing(); + showing.set(currentShowing); + return currentShowing; + } + + + @Override + protected void destroyContext() { + synchronized (lock) { + canvas.deleteContext(); + } + //// request the cleanup + //signalTerminate.release(); + //try { + // // wait until the thread is done with the cleanup + // signalTerminated.acquire(); + //} catch (InterruptedException ignored) { + //} + super.destroyContext(); + } + + @Override + protected void runLoop() { + if (needResize.get()) { + needResize.set(false); + settings.setResolution(framebufferWidth, framebufferHeight); + listener.reshape(framebufferWidth, framebufferHeight); + } + + if (!checkVisibilityState()) { + return; + } + + canvas.beforeRender(); + try { + super.runLoop(); + canvas.swapBuffers(); + } finally { + canvas.afterRender(); + } + + try { + if (signalTerminate.tryAcquire(10, TimeUnit.MILLISECONDS)) { + canvas.doDisposeCanvas(); + signalTerminated.release(); + } + } catch (InterruptedException ignored) { } + } + + @Override + protected void printContextInitInfo() { + super.printContextInitInfo(); + StringBuilder sb = new StringBuilder(); + sb.append("Initializing LWJGL3-AWT with jMonkeyEngine"); + sb.append('\n') + .append(" * Double Buffer: ").append(glData.doubleBuffer); + sb.append('\n') + .append(" * Stereo: ").append(glData.stereo); + sb.append('\n') + .append(" * Red Size: ").append(glData.redSize); + sb.append('\n') + .append(" * Rreen Size: ").append(glData.greenSize); + sb.append('\n') + .append(" * Blue Size: ").append(glData.blueSize); + sb.append('\n') + .append(" * Alpha Size: ").append(glData.alphaSize); + sb.append('\n') + .append(" * Depth Size: ").append(glData.depthSize); + sb.append('\n') + .append(" * Stencil Size: ").append(glData.stencilSize); + sb.append('\n') + .append(" * Accum Red Size: ").append(glData.accumRedSize); + sb.append('\n') + .append(" * Accum Green Size: ").append(glData.accumGreenSize); + sb.append('\n') + .append(" * Accum Blue Size: ").append(glData.accumBlueSize); + sb.append('\n') + .append(" * Accum Alpha Size: ").append(glData.accumAlphaSize); + sb.append('\n') + .append(" * Sample Buffers: ").append(glData.sampleBuffers); + sb.append('\n') + .append(" * Share Context: ").append(glData.shareContext); + sb.append('\n') + .append(" * Major Version: ").append(glData.majorVersion); + sb.append('\n') + .append(" * Minor Version: ").append(glData.minorVersion); + sb.append('\n') + .append(" * Forward Compatible: ").append(glData.forwardCompatible); + sb.append('\n') + .append(" * Profile: ").append(glData.profile); + sb.append('\n') + .append(" * API: ").append(glData.api); + sb.append('\n') + .append(" * Debug: ").append(glData.debug); + sb.append('\n') + .append(" * Swap Interval: ").append(glData.swapInterval); + sb.append('\n') + .append(" * SRGB (Gamma Correction): ").append(glData.sRGB); + sb.append('\n') + .append(" * Pixel Format Float: ").append(glData.pixelFormatFloat); + sb.append('\n') + .append(" * Context Release Behavior: ").append(glData.contextReleaseBehavior); + sb.append('\n') + .append(" * Color Samples NV: ").append(glData.colorSamplesNV); + sb.append('\n') + .append(" * Swap Group NV: ").append(glData.swapGroupNV); + sb.append('\n') + .append(" * Swap Barrier NV: ").append(glData.swapBarrierNV); + sb.append('\n') + .append(" * Robustness: ").append(glData.robustness); + sb.append('\n') + .append(" * Lose Context On Reset: ").append(glData.loseContextOnReset); + sb.append('\n') + .append(" * Context Reset Isolation: ").append(glData.contextResetIsolation); + LOGGER.log(Level.INFO, String.valueOf(sb)); + } + + @Override + public int getFramebufferHeight() { + return framebufferHeight; + } + + @Override + public int getFramebufferWidth() { + return framebufferWidth; + } +} From 0786bfd8a28be15f73d2068dbe9e59d2d2e52584 Mon Sep 17 00:00:00 2001 From: wil Date: Mon, 18 Dec 2023 15:19:45 -0600 Subject: [PATCH 02/15] GL Compatibility Support. --- .../com/jme3/system/lwjgl/LwjglCanvas.java | 91 ++++++++++++++++--- 1 file changed, 79 insertions(+), 12 deletions(-) diff --git a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglCanvas.java b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglCanvas.java index e22d8c30be..7f7fa4070a 100644 --- a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglCanvas.java +++ b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglCanvas.java @@ -44,9 +44,12 @@ import java.awt.event.ComponentEvent; import java.awt.event.ComponentListener; import java.awt.geom.AffineTransform; +import java.util.HashMap; +import java.util.Map; import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.Consumer; import java.util.logging.Level; import java.util.logging.Logger; @@ -64,6 +67,71 @@ public class LwjglCanvas extends LwjglWindow implements JmeCanvasContext, Runnab /** Logger class. */ private static final Logger LOGGER = Logger.getLogger(LwjglCanvas.class.getName()); + /** GL versions map. */ + private static final Map> RENDER_CONFIGS = new HashMap<>(); + + /* + Register the different versions. + */ + static { + RENDER_CONFIGS.put(AppSettings.LWJGL_OPENGL30, (data) -> { + data.majorVersion = 3; + data.minorVersion = 0; + }); + RENDER_CONFIGS.put(AppSettings.LWJGL_OPENGL31, (data) -> { + data.majorVersion = 3; + data.minorVersion = 1; + }); + RENDER_CONFIGS.put(AppSettings.LWJGL_OPENGL32, (data) -> { + //data.forwardCompatible = false; + data.majorVersion = 3; + data.minorVersion = 2; + data.profile = GLData.Profile.COMPATIBILITY; + }); + RENDER_CONFIGS.put(AppSettings.LWJGL_OPENGL33, (data) -> { + //data.forwardCompatible = true; + data.majorVersion = 3; + data.minorVersion = 3; + data.profile = GLData.Profile.COMPATIBILITY; + }); + RENDER_CONFIGS.put(AppSettings.LWJGL_OPENGL40, (data) -> { + //data.forwardCompatible = true; + data.majorVersion = 4; + data.minorVersion = 0; + data.profile = GLData.Profile.COMPATIBILITY; + }); + RENDER_CONFIGS.put(AppSettings.LWJGL_OPENGL41, (data) -> { + //data.forwardCompatible = true; + data.majorVersion = 4; + data.minorVersion = 1; + data.profile = GLData.Profile.COMPATIBILITY; + }); + RENDER_CONFIGS.put(AppSettings.LWJGL_OPENGL42, (data) -> { + //data.forwardCompatible = true; + data.majorVersion = 4; + data.minorVersion = 2; + data.profile = GLData.Profile.COMPATIBILITY; + }); + RENDER_CONFIGS.put(AppSettings.LWJGL_OPENGL43, (data) -> { + //data.forwardCompatible = true; + data.majorVersion = 4; + data.minorVersion = 3; + data.profile = GLData.Profile.COMPATIBILITY; + }); + RENDER_CONFIGS.put(AppSettings.LWJGL_OPENGL44, (data) -> { + //data.forwardCompatible = true; + data.majorVersion = 4; + data.minorVersion = 4; + data.profile = GLData.Profile.COMPATIBILITY; + }); + RENDER_CONFIGS.put(AppSettings.LWJGL_OPENGL45, (data) -> { + //data.forwardCompatible = true; + data.majorVersion = 4; + data.minorVersion = 5; + data.profile = GLData.Profile.COMPATIBILITY; + }); + } + private class LwjglAWTGLCanvas extends AWTGLCanvas { public LwjglAWTGLCanvas(GLData data) { @@ -175,7 +243,14 @@ public void componentResized(ComponentEvent e) { @Override protected void createContext(AppSettings settings) { - super.createContext(settings); + super.createContext(settings); + RENDER_CONFIGS.computeIfAbsent(settings.getRenderer(), (t) -> { + return (data) -> { + data.majorVersion = 2; + data.minorVersion = 0; + }; + }).accept(glData); + if (settings.getBitsPerPixel() == 24) { glData.redSize = 8; glData.greenSize = 8; @@ -196,7 +271,6 @@ protected void createContext(AppSettings settings) { glData.stereo = settings.useStereo3D(); glData.debug = settings.isGraphicsDebug(); - glData.profile = GLData.Profile.CORE; glData.api = GLData.API.GL; } @@ -251,15 +325,8 @@ public boolean checkVisibilityState() { @Override protected void destroyContext() { - synchronized (lock) { - canvas.deleteContext(); - } - //// request the cleanup - //signalTerminate.release(); - //try { - // // wait until the thread is done with the cleanup - // signalTerminated.acquire(); - //} catch (InterruptedException ignored) { + //synchronized (lock) { + // canvas.deleteContext(); //} super.destroyContext(); } @@ -294,7 +361,7 @@ protected void runLoop() { @Override protected void printContextInitInfo() { - super.printContextInitInfo(); + super.printContextInitInfo(); StringBuilder sb = new StringBuilder(); sb.append("Initializing LWJGL3-AWT with jMonkeyEngine"); sb.append('\n') From e251961eb383cd1c945c09d9563912f4ed703097 Mon Sep 17 00:00:00 2001 From: wil Date: Mon, 18 Dec 2023 15:50:18 -0600 Subject: [PATCH 03/15] module change: lwjgl to lwjgl3 --- jme3-examples/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/jme3-examples/build.gradle b/jme3-examples/build.gradle index 60912ff1a8..46ce34882b 100644 --- a/jme3-examples/build.gradle +++ b/jme3-examples/build.gradle @@ -19,8 +19,8 @@ dependencies { implementation project(':jme3-effects') implementation project(':jme3-jbullet') implementation project(':jme3-jogg') - implementation project(':jme3-lwjgl') -// implementation project(':jme3-lwjgl3') +// implementation project(':jme3-lwjgl') + implementation project(':jme3-lwjgl3') implementation project(':jme3-networking') implementation project(':jme3-niftygui') implementation project(':jme3-plugins') From 04a16766d417acab6e977b145bb7a74b20c6741d Mon Sep 17 00:00:00 2001 From: wil Date: Mon, 18 Dec 2023 15:55:21 -0600 Subject: [PATCH 04/15] Stop/Start Canvas --- jme3-examples/src/main/java/jme3test/awt/TestCanvas.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/jme3-examples/src/main/java/jme3test/awt/TestCanvas.java b/jme3-examples/src/main/java/jme3test/awt/TestCanvas.java index bb4b39ac95..771f1dc988 100644 --- a/jme3-examples/src/main/java/jme3test/awt/TestCanvas.java +++ b/jme3-examples/src/main/java/jme3test/awt/TestCanvas.java @@ -172,6 +172,10 @@ public void actionPerformed(ActionEvent e) { currentPanel.remove(canvas); app.stop(true); + try { + Thread.sleep(1000); + } catch (InterruptedException ex) { } + createCanvas(appClass); currentPanel.add(canvas, BorderLayout.CENTER); frame.pack(); @@ -234,7 +238,7 @@ public static void createCanvas(String appClass){ } public static void startApp(){ - app.startCanvas(); + /*app.startCanvas();*/ app.enqueue(new Callable(){ @Override public Void call(){ From 9e3952c52a0b6e3c1d60a4974380df1166200abd Mon Sep 17 00:00:00 2001 From: wil Date: Wed, 20 Dec 2023 13:10:25 -0600 Subject: [PATCH 05/15] Enable vsync for LWJGL3-AWT, A debugger that displays the effective data for the context in case it fails. --- .../com/jme3/system/lwjgl/LwjglCanvas.java | 62 +++++++++++++++---- 1 file changed, 49 insertions(+), 13 deletions(-) diff --git a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglCanvas.java b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglCanvas.java index 7f7fa4070a..3bba0765dc 100644 --- a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglCanvas.java +++ b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglCanvas.java @@ -44,6 +44,7 @@ import java.awt.event.ComponentEvent; import java.awt.event.ComponentListener; import java.awt.geom.AffineTransform; +import java.text.MessageFormat; import java.util.HashMap; import java.util.Map; import java.util.concurrent.Semaphore; @@ -60,6 +61,18 @@ * Class LwjglCanvas that integrates LWJGLX * which allows using AWT-Swing components. * + *

+ * If LwjglCanvas throws an exception due to configuration problems, we can debug as follows: + *
+ * - In AppSettings, set this property to enable a debug that displays + * the effective data for the context. + *


+ * ....
+ *  AppSettings settings = new AppSettings(true);
+ *  settings.putBoolean("GLDataEffectiveDebug", true);
+ * ...
+ * 
+ * * @author wil */ public class LwjglCanvas extends LwjglWindow implements JmeCanvasContext, Runnable { @@ -83,49 +96,41 @@ public class LwjglCanvas extends LwjglWindow implements JmeCanvasContext, Runnab data.minorVersion = 1; }); RENDER_CONFIGS.put(AppSettings.LWJGL_OPENGL32, (data) -> { - //data.forwardCompatible = false; data.majorVersion = 3; data.minorVersion = 2; data.profile = GLData.Profile.COMPATIBILITY; }); RENDER_CONFIGS.put(AppSettings.LWJGL_OPENGL33, (data) -> { - //data.forwardCompatible = true; data.majorVersion = 3; data.minorVersion = 3; data.profile = GLData.Profile.COMPATIBILITY; }); RENDER_CONFIGS.put(AppSettings.LWJGL_OPENGL40, (data) -> { - //data.forwardCompatible = true; data.majorVersion = 4; data.minorVersion = 0; data.profile = GLData.Profile.COMPATIBILITY; }); RENDER_CONFIGS.put(AppSettings.LWJGL_OPENGL41, (data) -> { - //data.forwardCompatible = true; data.majorVersion = 4; data.minorVersion = 1; data.profile = GLData.Profile.COMPATIBILITY; }); RENDER_CONFIGS.put(AppSettings.LWJGL_OPENGL42, (data) -> { - //data.forwardCompatible = true; data.majorVersion = 4; data.minorVersion = 2; data.profile = GLData.Profile.COMPATIBILITY; }); RENDER_CONFIGS.put(AppSettings.LWJGL_OPENGL43, (data) -> { - //data.forwardCompatible = true; data.majorVersion = 4; data.minorVersion = 3; data.profile = GLData.Profile.COMPATIBILITY; }); RENDER_CONFIGS.put(AppSettings.LWJGL_OPENGL44, (data) -> { - //data.forwardCompatible = true; data.majorVersion = 4; data.minorVersion = 4; data.profile = GLData.Profile.COMPATIBILITY; }); RENDER_CONFIGS.put(AppSettings.LWJGL_OPENGL45, (data) -> { - //data.forwardCompatible = true; data.majorVersion = 4; data.minorVersion = 5; data.profile = GLData.Profile.COMPATIBILITY; @@ -137,7 +142,7 @@ private class LwjglAWTGLCanvas extends AWTGLCanvas { public LwjglAWTGLCanvas(GLData data) { super(data); } - + @Override public void initGL() { throw new UnsupportedOperationException("Not supported yet."); @@ -152,6 +157,10 @@ public void paintGL() { public synchronized void addComponentListener(ComponentListener l) { super.addComponentListener(l); } + + public GLData getGLDataEffective() { + return effective; + } @Override public void afterRender() { @@ -195,6 +204,7 @@ public void removeNotify() { private final LwjglAWTGLCanvas canvas; private GLData glData; + private final AtomicBoolean showGLDataEffective = new AtomicBoolean(false); private final AtomicBoolean hasNativePeer = new AtomicBoolean(false); private final AtomicBoolean showing = new AtomicBoolean(false); private AtomicBoolean needResize = new AtomicBoolean(false); @@ -261,6 +271,15 @@ protected void createContext(AppSettings settings) { glData.blueSize = 5; } + // Enable vsync for LWJGL3-AWT + if (settings.isVSync()) { + glData.swapInterval = 1; + } else { + glData.swapInterval = 0; + } + + showGLDataEffective.set(settings.getBoolean("GLDataEffectiveDebug")); + glData.depthSize = settings.getBitsPerPixel(); glData.alphaSize = settings.getAlphaBits(); glData.sRGB = settings.isGammaCorrection(); @@ -351,6 +370,14 @@ protected void runLoop() { canvas.afterRender(); } + // Whether it is necessary to know the effective attributes to + // initialize the LWJGL3-AWT context + if (showGLDataEffective.get()) { + showGLDataEffective.set(false); + System.out.println(MessageFormat.format("[ DEBUGGER ] :Effective data to initialize the LWJGL3-AWT context\n{0}", + getPrintContextInitInfo(canvas.getGLDataEffective()))); + } + try { if (signalTerminate.tryAcquire(10, TimeUnit.MILLISECONDS)) { canvas.doDisposeCanvas(); @@ -362,10 +389,19 @@ protected void runLoop() { @Override protected void printContextInitInfo() { super.printContextInitInfo(); + LOGGER.log(Level.INFO, "Initializing LWJGL3-AWT with jMonkeyEngine\n{0}", getPrintContextInitInfo(glData)); + } + + /** + * Returns a string with the information obtained from GLData + * so that it can be displayed. + * + * @param glData context information + * @return String + */ + protected String getPrintContextInitInfo(GLData glData) { StringBuilder sb = new StringBuilder(); - sb.append("Initializing LWJGL3-AWT with jMonkeyEngine"); - sb.append('\n') - .append(" * Double Buffer: ").append(glData.doubleBuffer); + sb.append(" * Double Buffer: ").append(glData.doubleBuffer); sb.append('\n') .append(" * Stereo: ").append(glData.stereo); sb.append('\n') @@ -424,7 +460,7 @@ protected void printContextInitInfo() { .append(" * Lose Context On Reset: ").append(glData.loseContextOnReset); sb.append('\n') .append(" * Context Reset Isolation: ").append(glData.contextResetIsolation); - LOGGER.log(Level.INFO, String.valueOf(sb)); + return String.valueOf(sb); } @Override From 732f92a43a47c4bb47542e9929c5503207862dd5 Mon Sep 17 00:00:00 2001 From: wil Date: Wed, 27 Dec 2023 14:30:29 -0600 Subject: [PATCH 06/15] Solution (Linux): Remove/Add Canvas --- .../com/jme3/system/lwjgl/LwjglCanvas.java | 101 +++++++++----- .../lwjglx/LwjglxDefaultGLPlatform.java | 57 ++++++++ .../jme3/system/lwjglx/LwjglxGLPlatform.java | 48 +++++++ .../jme3/system/lwjglx/MacOSXGLPlatform.java | 46 +++++++ .../jme3/system/lwjglx/Win32GLPlatform.java | 46 +++++++ .../com/jme3/system/lwjglx/X11GLPlatform.java | 123 ++++++++++++++++++ 6 files changed, 390 insertions(+), 31 deletions(-) create mode 100644 jme3-lwjgl3/src/main/java/com/jme3/system/lwjglx/LwjglxDefaultGLPlatform.java create mode 100644 jme3-lwjgl3/src/main/java/com/jme3/system/lwjglx/LwjglxGLPlatform.java create mode 100644 jme3-lwjgl3/src/main/java/com/jme3/system/lwjglx/MacOSXGLPlatform.java create mode 100644 jme3-lwjgl3/src/main/java/com/jme3/system/lwjglx/Win32GLPlatform.java create mode 100644 jme3-lwjgl3/src/main/java/com/jme3/system/lwjglx/X11GLPlatform.java diff --git a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglCanvas.java b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglCanvas.java index 3bba0765dc..7211123eb9 100644 --- a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglCanvas.java +++ b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglCanvas.java @@ -37,8 +37,13 @@ import com.jme3.input.awt.AwtMouseInput; import com.jme3.system.AppSettings; import com.jme3.system.JmeCanvasContext; +import com.jme3.system.lwjglx.LwjglxDefaultGLPlatform; +import com.jme3.system.lwjglx.LwjglxGLPlatform; +import java.awt.AWTException; import java.awt.Canvas; +import java.awt.Graphics; +import java.awt.Graphics2D; import java.awt.GraphicsConfiguration; import java.awt.event.ComponentAdapter; import java.awt.event.ComponentEvent; @@ -54,9 +59,12 @@ import java.util.logging.Level; import java.util.logging.Logger; -import org.lwjgl.opengl.awt.AWTGLCanvas; +import org.lwjgl.awthacks.NonClearGraphics; +import org.lwjgl.awthacks.NonClearGraphics2D; import org.lwjgl.opengl.awt.GLData; +import static org.lwjgl.system.MemoryUtil.*; + /** * Class LwjglCanvas that integrates LWJGLX * which allows using AWT-Swing components. @@ -137,20 +145,24 @@ public class LwjglCanvas extends LwjglWindow implements JmeCanvasContext, Runnab }); } - private class LwjglAWTGLCanvas extends AWTGLCanvas { + private class LwjglAWTGLCanvas extends Canvas { + + private LwjglxGLPlatform platformCanvas; + + private long context; + private GLData data; + private GLData effective; public LwjglAWTGLCanvas(GLData data) { - super(data); - } - - @Override - public void initGL() { - throw new UnsupportedOperationException("Not supported yet."); - } - - @Override - public void paintGL() { - throw new UnsupportedOperationException("Not supported yet."); + this.effective = new GLData(); + this.context = NULL; + this.data = data; + + try { + platformCanvas = LwjglxDefaultGLPlatform.createLwjglxGLPlatform(); + } catch (UnsupportedOperationException e) { + listener.handleError(e.getLocalizedMessage(), e); + } } @Override @@ -161,26 +173,39 @@ public synchronized void addComponentListener(ComponentListener l) { public GLData getGLDataEffective() { return effective; } - - @Override + public void afterRender() { - super.afterRender(); + platformCanvas.makeCurrent(NULL); + try { + platformCanvas.unlock(); // <- MUST unlock on Linux + } catch (AWTException e) { + listener.handleError("Failed to unlock Canvas", e); + } } - - @Override + public void beforeRender() { - super.beforeRender(); + if (context == NULL) { + try { + context = platformCanvas.create(this, data, effective); + } catch (AWTException e) { + listener.handleError("Exception while creating the OpenGL context", e); + return; + } + } + try { + platformCanvas.lock(); // <- MUST lock on Linux + } catch (AWTException e) { + listener.handleError("Failed to lock Canvas", e); + } + platformCanvas.makeCurrent(context); } - - @Override - public void disposeCanvas() { } public void doDisposeCanvas() { - super.disposeCanvas(); + platformCanvas.dispose(); } - public void deleteContext() { - platformCanvas.deleteContext(context); + public void swapBuffers() { + platformCanvas.swapBuffers(); } @Override @@ -199,6 +224,23 @@ public void removeNotify() { } super.removeNotify(); } + + public void destroy() { + platformCanvas.destroy(); + } + + /** + * Returns Graphics object that ignores {@link Graphics#clearRect(int, int, int, int)} + * calls. + * This is done so that the frame buffer will not be cleared by AWT/Swing internals. + */ + @Override + public Graphics getGraphics() { + Graphics graphics = super.getGraphics(); + return (graphics instanceof Graphics2D) + ? new NonClearGraphics2D((Graphics2D) graphics) + : new NonClearGraphics(graphics); + } } private final LwjglAWTGLCanvas canvas; @@ -330,9 +372,6 @@ public MouseInput getMouseInput() { public boolean checkVisibilityState() { if (!hasNativePeer.get()) { - synchronized (lock) { - canvas.doDisposeCanvas(); - } return false; } @@ -344,9 +383,9 @@ public boolean checkVisibilityState() { @Override protected void destroyContext() { - //synchronized (lock) { - // canvas.deleteContext(); - //} + synchronized (lock) { + canvas.destroy(); + } super.destroyContext(); } diff --git a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjglx/LwjglxDefaultGLPlatform.java b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjglx/LwjglxDefaultGLPlatform.java new file mode 100644 index 0000000000..debee75cab --- /dev/null +++ b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjglx/LwjglxDefaultGLPlatform.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2009-2023 jMonkeyEngine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'jMonkeyEngine' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.jme3.system.lwjglx; + +import org.lwjgl.system.Platform; +import static org.lwjgl.system.Platform.*; + +/** + * + * @author wil + */ +public final class LwjglxDefaultGLPlatform { + + public static LwjglxGLPlatform createLwjglxGLPlatform() throws UnsupportedOperationException { + switch (Platform.get()) { + case WINDOWS: + return new Win32GLPlatform(); + case LINUX: + return new X11GLPlatform(); + case MACOSX: + return new MacOSXGLPlatform(); + default: + throw new UnsupportedOperationException("Platform " + Platform.get() + " not yet supported"); + } + } + + private LwjglxDefaultGLPlatform() {} +} diff --git a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjglx/LwjglxGLPlatform.java b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjglx/LwjglxGLPlatform.java new file mode 100644 index 0000000000..a04ad57923 --- /dev/null +++ b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjglx/LwjglxGLPlatform.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2009-2023 jMonkeyEngine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'jMonkeyEngine' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.jme3.system.lwjglx; + +import org.lwjgl.opengl.awt.PlatformGLCanvas; + +/** + * Interface LwjglxGLPlatform; It is used to implement and manage + * the context of a specific platform. + * + * @author wil + */ +public interface LwjglxGLPlatform extends PlatformGLCanvas { + + /** + * Free the drawing surface. + */ + public void destroy(); +} diff --git a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjglx/MacOSXGLPlatform.java b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjglx/MacOSXGLPlatform.java new file mode 100644 index 0000000000..789ef1a029 --- /dev/null +++ b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjglx/MacOSXGLPlatform.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2009-2023 jMonkeyEngine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'jMonkeyEngine' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.jme3.system.lwjglx; + +import org.lwjgl.opengl.awt.PlatformMacOSXGLCanvas; + +/** + * + * @author wil + */ +public class MacOSXGLPlatform extends PlatformMacOSXGLCanvas implements LwjglxGLPlatform { + + @Override + public void destroy() { + + } +} diff --git a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjglx/Win32GLPlatform.java b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjglx/Win32GLPlatform.java new file mode 100644 index 0000000000..807d4f90c3 --- /dev/null +++ b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjglx/Win32GLPlatform.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2009-2023 jMonkeyEngine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'jMonkeyEngine' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.jme3.system.lwjglx; + +import org.lwjgl.opengl.awt.PlatformWin32GLCanvas; + +/** + * + * @author wil + */ +public class Win32GLPlatform extends PlatformWin32GLCanvas implements LwjglxGLPlatform { + + @Override + public void destroy() { + + } +} diff --git a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjglx/X11GLPlatform.java b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjglx/X11GLPlatform.java new file mode 100644 index 0000000000..d3e1a2d71d --- /dev/null +++ b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjglx/X11GLPlatform.java @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2009-2023 jMonkeyEngine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'jMonkeyEngine' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package com.jme3.system.lwjglx; + +import org.lwjgl.opengl.awt.PlatformLinuxGLCanvas; +import org.lwjgl.system.jawt.*; + +import static org.lwjgl.system.MemoryUtil.*; +import static org.lwjgl.system.jawt.JAWTFunctions.*; + +/** + * Class X11GLPlatform; overrides the following methods: swapBuffers() + * and makeCurrent(long context). So that the canvas can be removed and + * added back from its parent component. + * + *

+ * Works only for Linux based platforms + * + * @author wil + */ +public class X11GLPlatform extends PlatformLinuxGLCanvas implements LwjglxGLPlatform { + + /** + * (non-JavaDoc) + * @see org.lwjgl.opengl.awt.PlatformGLCanvas#swapBuffers() + * @return boolean + */ + @Override + public boolean swapBuffers() { + // Get the drawing surface info + JAWTDrawingSurfaceInfo dsi = JAWT_DrawingSurface_GetDrawingSurfaceInfo(ds, ds.GetDrawingSurfaceInfo()); + if (dsi == null) { + throw new IllegalStateException("JAWT_DrawingSurface_GetDrawingSurfaceInfo() failed"); + } + + try { + // Get the platform-specific drawing info + JAWTX11DrawingSurfaceInfo dsi_x11 = JAWTX11DrawingSurfaceInfo.create(dsi.platformInfo()); + + // Set new values + display = dsi_x11.display(); + drawable = dsi_x11.drawable(); + + // Swap-Buffers + return super.swapBuffers(); + } finally { + JAWT_DrawingSurface_FreeDrawingSurfaceInfo(dsi, ds.FreeDrawingSurfaceInfo()); + } + } + + /** + * (non-JavaDoc) + * @see org.lwjgl.opengl.awt.PlatformGLCanvas#makeCurrent(long) + * + * @param context long + * @return boolean + */ + @Override + public boolean makeCurrent(long context) { + // Get the drawing surface info + JAWTDrawingSurfaceInfo dsi = JAWT_DrawingSurface_GetDrawingSurfaceInfo(ds, ds.GetDrawingSurfaceInfo()); + if (dsi == null) { + throw new IllegalStateException("JAWT_DrawingSurface_GetDrawingSurfaceInfo() failed"); + } + + try { + // Get the platform-specific drawing info + JAWTX11DrawingSurfaceInfo dsi_x11 = JAWTX11DrawingSurfaceInfo.create(dsi.platformInfo()); + + // Set new values + display = dsi_x11.display(); + drawable = dsi_x11.drawable(); + + if (drawable == NULL) { + return false; + } + return super.makeCurrent(context); + } finally { + JAWT_DrawingSurface_FreeDrawingSurfaceInfo(dsi, ds.FreeDrawingSurfaceInfo()); + } + } + + /** + * (non-JavaDoc) + * @see com.jme3.system.lwjglx.LwjglxGLPlatform#destroy() + */ + @Override + public void destroy() { + if (ds != null) { + JAWT_FreeDrawingSurface(ds, awt.FreeDrawingSurface()); + awt.free(); + } + } +} From 67e029b250ba61b6eb2995f4d58356660db5c201 Mon Sep 17 00:00:00 2001 From: wil Date: Wed, 27 Dec 2023 15:04:22 -0600 Subject: [PATCH 07/15] MacOS compatibility (no drastic changes) --- .../com/jme3/system/lwjglx/MacOSXGLPlatform.java | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjglx/MacOSXGLPlatform.java b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjglx/MacOSXGLPlatform.java index 789ef1a029..96d5456c6d 100644 --- a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjglx/MacOSXGLPlatform.java +++ b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjglx/MacOSXGLPlatform.java @@ -32,15 +32,25 @@ package com.jme3.system.lwjglx; import org.lwjgl.opengl.awt.PlatformMacOSXGLCanvas; +import static org.lwjgl.system.jawt.JAWTFunctions.*; /** - * + * MacOSXGLPlatform class that implements the {@link com.jme3.system.lwjglx.LwjglxGLPlatform} + * interface for the MacOS platform. + * * @author wil */ public class MacOSXGLPlatform extends PlatformMacOSXGLCanvas implements LwjglxGLPlatform { + /** + * (non-JavaDoc) + * @see com.jme3.system.lwjglx.LwjglxGLPlatform#destroy() + */ @Override public void destroy() { - + if (ds != null) { + JAWT_FreeDrawingSurface(ds, awt.FreeDrawingSurface()); + awt.free(); + } } } From 29a2ff7c13c9e88fef4303615d14ee4d1aef8185 Mon Sep 17 00:00:00 2001 From: wil Date: Wed, 27 Dec 2023 17:30:41 -0600 Subject: [PATCH 08/15] Solution (Windows): Remove/Add Canvas --- .../jme3/system/lwjglx/Win32GLPlatform.java | 97 ++++++++++++++++++- 1 file changed, 95 insertions(+), 2 deletions(-) diff --git a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjglx/Win32GLPlatform.java b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjglx/Win32GLPlatform.java index 807d4f90c3..d466d27271 100644 --- a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjglx/Win32GLPlatform.java +++ b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjglx/Win32GLPlatform.java @@ -31,16 +31,109 @@ */ package com.jme3.system.lwjglx; +import static org.lwjgl.system.jawt.JAWTFunctions.*; + import org.lwjgl.opengl.awt.PlatformWin32GLCanvas; +import org.lwjgl.system.jawt.JAWTDrawingSurfaceInfo; +import org.lwjgl.system.jawt.JAWTWin32DrawingSurfaceInfo; + /** - * + * Class Win32GLPlatform; overrides the following methods: swapBuffers() + * ,makeCurrent(long context) and delayBeforeSwapNV(float seconds). + * So that the canvas can be removed and added back from its parent component. + *

+ * Only for windows. + * * @author wil */ public class Win32GLPlatform extends PlatformWin32GLCanvas implements LwjglxGLPlatform { + + /** + * (non-JavaDoc) + * @see org.lwjgl.opengl.awt.PlatformGLCanvas#swapBuffers() + * @return boolean + */ + @Override + public boolean swapBuffers() { + // Get the drawing surface info + JAWTDrawingSurfaceInfo dsi = JAWT_DrawingSurface_GetDrawingSurfaceInfo(ds, ds.GetDrawingSurfaceInfo()); + if (dsi == null) { + throw new IllegalStateException("JAWT_DrawingSurface_GetDrawingSurfaceInfo() failed"); + } + + try { + // Get the platform-specific drawing info + JAWTWin32DrawingSurfaceInfo dsiWin = JAWTWin32DrawingSurfaceInfo.create(dsi.platformInfo()); + hwnd = dsiWin.hwnd(); + return super.swapBuffers(); + } finally { + // Free the drawing surface info + JAWT_DrawingSurface_FreeDrawingSurfaceInfo(dsi, ds.FreeDrawingSurfaceInfo()); + } + } + /** + * (non-JavaDoc) + * @see org.lwjgl.opengl.awt.PlatformGLCanvas#makeCurrent(long) + * + * @param context long + * @return boolean + */ @Override - public void destroy() { + public boolean makeCurrent(long context) { + // Get the drawing surface info + JAWTDrawingSurfaceInfo dsi = JAWT_DrawingSurface_GetDrawingSurfaceInfo(ds, ds.GetDrawingSurfaceInfo()); + if (dsi == null) { + throw new IllegalStateException("JAWT_DrawingSurface_GetDrawingSurfaceInfo() failed"); + } + try { + // Get the platform-specific drawing info + JAWTWin32DrawingSurfaceInfo dsiWin = JAWTWin32DrawingSurfaceInfo.create(dsi.platformInfo()); + hwnd = dsiWin.hwnd(); + return super.makeCurrent(context); + } finally { + // Free the drawing surface info + JAWT_DrawingSurface_FreeDrawingSurfaceInfo(dsi, ds.FreeDrawingSurfaceInfo()); + } + } + + /** + * (non-JavaDoc) + * @see org.lwjgl.opengl.awt.PlatformGLCanvas#delayBeforeSwapNV(float) + * + * @param seconds float + * @return boolean + */ + @Override + public boolean delayBeforeSwapNV(float seconds) { + // Get the drawing surface info + JAWTDrawingSurfaceInfo dsi = JAWT_DrawingSurface_GetDrawingSurfaceInfo(ds, ds.GetDrawingSurfaceInfo()); + if (dsi == null) { + throw new IllegalStateException("JAWT_DrawingSurface_GetDrawingSurfaceInfo() failed"); + } + + try { + // Get the platform-specific drawing info + JAWTWin32DrawingSurfaceInfo dsiWin = JAWTWin32DrawingSurfaceInfo.create(dsi.platformInfo()); + hwnd = dsiWin.hwnd(); + return super.delayBeforeSwapNV(seconds); + } finally { + // Free the drawing surface info + JAWT_DrawingSurface_FreeDrawingSurfaceInfo(dsi, ds.FreeDrawingSurfaceInfo()); + } + } + + /** + * (non-JavaDoc) + * @see com.jme3.system.lwjglx.LwjglxGLPlatform#destroy() + */ + @Override + public void destroy() { + if (ds != null) { + JAWT_FreeDrawingSurface(ds, awt.FreeDrawingSurface()); + awt.free(); + } } } From 9cd0ea95902688c24bbb85f7e770d09b9938d8aa Mon Sep 17 00:00:00 2001 From: wil Date: Wed, 27 Dec 2023 17:43:01 -0600 Subject: [PATCH 09/15] Auxiliary class 'LwjglxDefaultGLPlatform' --- .../jme3/system/lwjglx/LwjglxDefaultGLPlatform.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjglx/LwjglxDefaultGLPlatform.java b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjglx/LwjglxDefaultGLPlatform.java index debee75cab..d6f8bee801 100644 --- a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjglx/LwjglxDefaultGLPlatform.java +++ b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjglx/LwjglxDefaultGLPlatform.java @@ -35,11 +35,16 @@ import static org.lwjgl.system.Platform.*; /** - * + * Class wjglxDefaultGLPlatform used to create a drawing platform. * @author wil */ public final class LwjglxDefaultGLPlatform { + /** + * Returns a drawing platform based on the platform it is running on. + * @return LwjglxGLPlatform + * @throws UnsupportedOperationException throws exception if platform is not supported + */ public static LwjglxGLPlatform createLwjglxGLPlatform() throws UnsupportedOperationException { switch (Platform.get()) { case WINDOWS: @@ -53,5 +58,8 @@ public static LwjglxGLPlatform createLwjglxGLPlatform() throws UnsupportedOperat } } + /** + * private constructor. + */ private LwjglxDefaultGLPlatform() {} } From 7e704494622a1e83f3e124ee6cce6d64de193f28 Mon Sep 17 00:00:00 2001 From: wil Date: Wed, 3 Jan 2024 12:20:31 -0600 Subject: [PATCH 10/15] Java-doc --- .../com/jme3/system/lwjgl/LwjglCanvas.java | 31 ++++++++++++++----- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglCanvas.java b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglCanvas.java index 7211123eb9..dca501c916 100644 --- a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglCanvas.java +++ b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglCanvas.java @@ -230,10 +230,11 @@ public void destroy() { } /** - * Returns Graphics object that ignores {@link Graphics#clearRect(int, int, int, int)} - * calls. - * This is done so that the frame buffer will not be cleared by AWT/Swing internals. - */ + * Returns Graphics object that ignores {@link Graphics#clearRect(int, int, int, int)} + * calls. + * This is done so that the frame buffer will not be cleared by AWT/Swing internals. + * @return Graphics + */ @Override public Graphics getGraphics() { Graphics graphics = super.getGraphics(); @@ -243,17 +244,31 @@ public Graphics getGraphics() { } } + /** Canvas-AWT. */ private final LwjglAWTGLCanvas canvas; + + /** + * Configuration data to start the AWT context, this is used by the + * {@code lwjgl-awt} library. + */ private GLData glData; + /** Used to display the effective data for the {@code AWT-Swing} drawing surface per console. */ private final AtomicBoolean showGLDataEffective = new AtomicBoolean(false); + + /** Used to notify the canvas status ({@code remove()/add()}). */ private final AtomicBoolean hasNativePeer = new AtomicBoolean(false); + + /** Notify if the canvas is visible and has a parent.*/ private final AtomicBoolean showing = new AtomicBoolean(false); + + /** Notify if there is a change in canvas dimensions. */ private AtomicBoolean needResize = new AtomicBoolean(false); + /** Semaphort used to check the "terminate" signal. */ private final Semaphore signalTerminate = new Semaphore(0); - private final Semaphore signalTerminated = new Semaphore(0); + /** lock-object. */ private final Object lock = new Object(); private int framebufferWidth = 1; private int framebufferHeight = 1; @@ -386,6 +401,9 @@ protected void destroyContext() { synchronized (lock) { canvas.destroy(); } + + // request the cleanup + signalTerminate.release(); super.destroyContext(); } @@ -416,11 +434,10 @@ protected void runLoop() { System.out.println(MessageFormat.format("[ DEBUGGER ] :Effective data to initialize the LWJGL3-AWT context\n{0}", getPrintContextInitInfo(canvas.getGLDataEffective()))); } - + try { if (signalTerminate.tryAcquire(10, TimeUnit.MILLISECONDS)) { canvas.doDisposeCanvas(); - signalTerminated.release(); } } catch (InterruptedException ignored) { } } From b2ce0478ebfe2a7004a29f970cafdf361bfef538 Mon Sep 17 00:00:00 2001 From: wil Date: Mon, 22 Jan 2024 16:17:34 -0600 Subject: [PATCH 11/15] To check who will do the 'swap buffer' --- .../src/main/java/com/jme3/system/lwjgl/LwjglWindow.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglWindow.java b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglWindow.java index c2b5e47402..884ef9e4fe 100644 --- a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglWindow.java +++ b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglWindow.java @@ -631,9 +631,10 @@ protected void runLoop() { // If the canvas is not active, there's no need to waste time // doing that. if (renderable.get()) { - // calls swap buffers, etc. try { - if (allowSwapBuffers && autoFlush) { + // If type is 'Canvas'; lwjgl-awt takes care of swap buffers. + if ((type != Type.Canvas) && allowSwapBuffers && autoFlush) { + // calls swap buffers, etc. glfwSwapBuffers(window); } } catch (Throwable ex) { From 7b33a14f36c2845d70fee6a760f5965494ef0b67 Mon Sep 17 00:00:00 2001 From: wil Date: Mon, 22 Jan 2024 16:38:19 -0600 Subject: [PATCH 12/15] swap buffers --- .../com/jme3/system/lwjgl/LwjglCanvas.java | 129 ++++++++++-------- 1 file changed, 69 insertions(+), 60 deletions(-) diff --git a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglCanvas.java b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglCanvas.java index dca501c916..e5a1d62f15 100644 --- a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglCanvas.java +++ b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglCanvas.java @@ -62,6 +62,7 @@ import org.lwjgl.awthacks.NonClearGraphics; import org.lwjgl.awthacks.NonClearGraphics2D; import org.lwjgl.opengl.awt.GLData; +import org.lwjgl.system.Platform; import static org.lwjgl.system.MemoryUtil.*; @@ -91,6 +92,8 @@ public class LwjglCanvas extends LwjglWindow implements JmeCanvasContext, Runnab /** GL versions map. */ private static final Map> RENDER_CONFIGS = new HashMap<>(); + private static final Platform OS = Platform.get(); + /* Register the different versions. */ @@ -223,6 +226,10 @@ public void removeNotify() { hasNativePeer.set(false); } super.removeNotify(); + if ((OS == Platform.MACOSX) && (context != NULL)) { + platformCanvas.deleteContext(context); + context = NULL; + } } public void destroy() { @@ -422,7 +429,9 @@ protected void runLoop() { canvas.beforeRender(); try { super.runLoop(); - canvas.swapBuffers(); + if (allowSwapBuffers && autoFlush) { + canvas.swapBuffers(); + } } finally { canvas.afterRender(); } @@ -457,65 +466,65 @@ protected void printContextInitInfo() { */ protected String getPrintContextInitInfo(GLData glData) { StringBuilder sb = new StringBuilder(); - sb.append(" * Double Buffer: ").append(glData.doubleBuffer); - sb.append('\n') - .append(" * Stereo: ").append(glData.stereo); - sb.append('\n') - .append(" * Red Size: ").append(glData.redSize); - sb.append('\n') - .append(" * Rreen Size: ").append(glData.greenSize); - sb.append('\n') - .append(" * Blue Size: ").append(glData.blueSize); - sb.append('\n') - .append(" * Alpha Size: ").append(glData.alphaSize); - sb.append('\n') - .append(" * Depth Size: ").append(glData.depthSize); - sb.append('\n') - .append(" * Stencil Size: ").append(glData.stencilSize); - sb.append('\n') - .append(" * Accum Red Size: ").append(glData.accumRedSize); - sb.append('\n') - .append(" * Accum Green Size: ").append(glData.accumGreenSize); - sb.append('\n') - .append(" * Accum Blue Size: ").append(glData.accumBlueSize); - sb.append('\n') - .append(" * Accum Alpha Size: ").append(glData.accumAlphaSize); - sb.append('\n') - .append(" * Sample Buffers: ").append(glData.sampleBuffers); - sb.append('\n') - .append(" * Share Context: ").append(glData.shareContext); - sb.append('\n') - .append(" * Major Version: ").append(glData.majorVersion); - sb.append('\n') - .append(" * Minor Version: ").append(glData.minorVersion); - sb.append('\n') - .append(" * Forward Compatible: ").append(glData.forwardCompatible); - sb.append('\n') - .append(" * Profile: ").append(glData.profile); - sb.append('\n') - .append(" * API: ").append(glData.api); - sb.append('\n') - .append(" * Debug: ").append(glData.debug); - sb.append('\n') - .append(" * Swap Interval: ").append(glData.swapInterval); - sb.append('\n') - .append(" * SRGB (Gamma Correction): ").append(glData.sRGB); - sb.append('\n') - .append(" * Pixel Format Float: ").append(glData.pixelFormatFloat); - sb.append('\n') - .append(" * Context Release Behavior: ").append(glData.contextReleaseBehavior); - sb.append('\n') - .append(" * Color Samples NV: ").append(glData.colorSamplesNV); - sb.append('\n') - .append(" * Swap Group NV: ").append(glData.swapGroupNV); - sb.append('\n') - .append(" * Swap Barrier NV: ").append(glData.swapBarrierNV); - sb.append('\n') - .append(" * Robustness: ").append(glData.robustness); - sb.append('\n') - .append(" * Lose Context On Reset: ").append(glData.loseContextOnReset); - sb.append('\n') - .append(" * Context Reset Isolation: ").append(glData.contextResetIsolation); + sb.append(" * Double Buffer: ").append(glData.doubleBuffer); + sb.append('\n') + .append(" * Stereo: ").append(glData.stereo); + sb.append('\n') + .append(" * Red Size: ").append(glData.redSize); + sb.append('\n') + .append(" * Rreen Size: ").append(glData.greenSize); + sb.append('\n') + .append(" * Blue Size: ").append(glData.blueSize); + sb.append('\n') + .append(" * Alpha Size: ").append(glData.alphaSize); + sb.append('\n') + .append(" * Depth Size: ").append(glData.depthSize); + sb.append('\n') + .append(" * Stencil Size: ").append(glData.stencilSize); + sb.append('\n') + .append(" * Accum Red Size: ").append(glData.accumRedSize); + sb.append('\n') + .append(" * Accum Green Size: ").append(glData.accumGreenSize); + sb.append('\n') + .append(" * Accum Blue Size: ").append(glData.accumBlueSize); + sb.append('\n') + .append(" * Accum Alpha Size: ").append(glData.accumAlphaSize); + sb.append('\n') + .append(" * Sample Buffers: ").append(glData.sampleBuffers); + sb.append('\n') + .append(" * Share Context: ").append(glData.shareContext); + sb.append('\n') + .append(" * Major Version: ").append(glData.majorVersion); + sb.append('\n') + .append(" * Minor Version: ").append(glData.minorVersion); + sb.append('\n') + .append(" * Forward Compatible: ").append(glData.forwardCompatible); + sb.append('\n') + .append(" * Profile: ").append(glData.profile); + sb.append('\n') + .append(" * API: ").append(glData.api); + sb.append('\n') + .append(" * Debug: ").append(glData.debug); + sb.append('\n') + .append(" * Swap Interval: ").append(glData.swapInterval); + sb.append('\n') + .append(" * SRGB (Gamma Correction): ").append(glData.sRGB); + sb.append('\n') + .append(" * Pixel Format Float: ").append(glData.pixelFormatFloat); + sb.append('\n') + .append(" * Context Release Behavior: ").append(glData.contextReleaseBehavior); + sb.append('\n') + .append(" * Color Samples NV: ").append(glData.colorSamplesNV); + sb.append('\n') + .append(" * Swap Group NV: ").append(glData.swapGroupNV); + sb.append('\n') + .append(" * Swap Barrier NV: ").append(glData.swapBarrierNV); + sb.append('\n') + .append(" * Robustness: ").append(glData.robustness); + sb.append('\n') + .append(" * Lose Context On Reset: ").append(glData.loseContextOnReset); + sb.append('\n') + .append(" * Context Reset Isolation: ").append(glData.contextResetIsolation); return String.valueOf(sb); } From 5546cc13f93cdf299e4b5b7da88bc2f2a7a73d00 Mon Sep 17 00:00:00 2001 From: wil Date: Thu, 1 Feb 2024 19:09:54 -0600 Subject: [PATCH 13/15] Change: from "LOGGER.warning()" to "LOGGER.log()" --- .../src/main/java/com/jme3/util/LWJGLBufferAllocator.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/jme3-lwjgl3/src/main/java/com/jme3/util/LWJGLBufferAllocator.java b/jme3-lwjgl3/src/main/java/com/jme3/util/LWJGLBufferAllocator.java index 75e27c5400..a132c31edd 100644 --- a/jme3-lwjgl3/src/main/java/com/jme3/util/LWJGLBufferAllocator.java +++ b/jme3-lwjgl3/src/main/java/com/jme3/util/LWJGLBufferAllocator.java @@ -8,6 +8,7 @@ import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.locks.StampedLock; +import java.util.logging.Level; import java.util.logging.Logger; /** @@ -164,7 +165,7 @@ public void destroyDirectBuffer(final Buffer buffer) { final long address = getAddress(buffer); if (address == -1) { - LOGGER.warning("Not found address of the " + buffer); + LOGGER.log(Level.WARNING, "Not found address of the {0}", buffer); return; } @@ -172,7 +173,7 @@ public void destroyDirectBuffer(final Buffer buffer) { final Deallocator deallocator = DEALLOCATORS.remove(address); if (deallocator == null) { - LOGGER.warning("Not found a deallocator for address " + address); + LOGGER.log(Level.WARNING, "Not found a deallocator for address {0}", address); return; } From c8f2f5ff3e28f20b89958f701748a931fde9691a Mon Sep 17 00:00:00 2001 From: wil Date: Sat, 3 Feb 2024 17:20:24 -0600 Subject: [PATCH 14/15] Format... --- jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/Sync.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/Sync.java b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/Sync.java index db9beef520..3161f00a9b 100644 --- a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/Sync.java +++ b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/Sync.java @@ -31,7 +31,6 @@ */ package com.jme3.system.lwjgl; - /** * A highly accurate sync method that continually adapts to the system * it runs on to provide reliable results. @@ -41,8 +40,6 @@ */ class Sync { - - /** number of nanoseconds in a second */ private static final long NANOS_IN_SECOND = 1000L * 1000L * 1000L; From 375f74d588bf527dbaf1c70edd5c651e68a0e4e9 Mon Sep 17 00:00:00 2001 From: wil Date: Sun, 4 Feb 2024 11:31:47 -0600 Subject: [PATCH 15/15] Bug fixes and Javadoc --- .../main/java/jme3test/awt/TestCanvas.java | 7 +- .../com/jme3/system/lwjgl/LwjglCanvas.java | 274 ++++++++++++++++-- .../com/jme3/system/lwjgl/LwjglWindow.java | 1 + .../lwjglx/LwjglxDefaultGLPlatform.java | 1 + .../jme3/system/lwjglx/MacOSXGLPlatform.java | 6 +- .../jme3/system/lwjglx/Win32GLPlatform.java | 91 +----- .../com/jme3/system/lwjglx/X11GLPlatform.java | 8 +- 7 files changed, 259 insertions(+), 129 deletions(-) diff --git a/jme3-examples/src/main/java/jme3test/awt/TestCanvas.java b/jme3-examples/src/main/java/jme3test/awt/TestCanvas.java index 771f1dc988..5f97ba8c27 100644 --- a/jme3-examples/src/main/java/jme3test/awt/TestCanvas.java +++ b/jme3-examples/src/main/java/jme3test/awt/TestCanvas.java @@ -29,7 +29,6 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - package jme3test.awt; import com.jme3.app.LegacyApplication; @@ -171,10 +170,6 @@ public void actionPerformed(ActionEvent e){ public void actionPerformed(ActionEvent e) { currentPanel.remove(canvas); app.stop(true); - - try { - Thread.sleep(1000); - } catch (InterruptedException ex) { } createCanvas(appClass); currentPanel.add(canvas, BorderLayout.CENTER); @@ -238,7 +233,7 @@ public static void createCanvas(String appClass){ } public static void startApp(){ - /*app.startCanvas();*/ + app.startCanvas(); app.enqueue(new Callable(){ @Override public Void call(){ diff --git a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglCanvas.java b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglCanvas.java index e5a1d62f15..e5e13117e2 100644 --- a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglCanvas.java +++ b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglCanvas.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2023 jMonkeyEngine + * Copyright (c) 2009-2024 jMonkeyEngine * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -37,7 +37,6 @@ import com.jme3.input.awt.AwtMouseInput; import com.jme3.system.AppSettings; import com.jme3.system.JmeCanvasContext; -import com.jme3.system.lwjglx.LwjglxDefaultGLPlatform; import com.jme3.system.lwjglx.LwjglxGLPlatform; import java.awt.AWTException; @@ -45,6 +44,7 @@ import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.GraphicsConfiguration; +import java.awt.Toolkit; import java.awt.event.ComponentAdapter; import java.awt.event.ComponentEvent; import java.awt.event.ComponentListener; @@ -65,6 +65,7 @@ import org.lwjgl.system.Platform; import static org.lwjgl.system.MemoryUtil.*; +import static com.jme3.system.lwjglx.LwjglxDefaultGLPlatform.*; /** * Class LwjglCanvas that integrates LWJGLX @@ -82,6 +83,16 @@ * ... * * + *

+ * NOTE: If running LwjglCanvas on older machines, the SRGB | Gamma Correction option + * will raise an exception, so it should be disabled. + *


+ * ....
+ *  AppSettings settings = new AppSettings(true);
+ *  settings.setGammaCorrection(false);
+ * ...
+ * 
+ * * @author wil */ public class LwjglCanvas extends LwjglWindow implements JmeCanvasContext, Runnable { @@ -92,6 +103,7 @@ public class LwjglCanvas extends LwjglWindow implements JmeCanvasContext, Runnab /** GL versions map. */ private static final Map> RENDER_CONFIGS = new HashMap<>(); + /** Type of operating system where this context is running. */ private static final Platform OS = Platform.get(); /* @@ -148,36 +160,76 @@ public class LwjglCanvas extends LwjglWindow implements JmeCanvasContext, Runnab }); } + /** + * An AWT java.awt.Canvas that supports to be drawn on using OpenGL. + */ private class LwjglAWTGLCanvas extends Canvas { + /** + * A {@link com.jme3.system.lwjglx.LwjglxGLPlatform} object. + * @see org.lwjgl.opengl.awt.PlatformGLCanvas + */ private LwjglxGLPlatform platformCanvas; + /** The OpenGL context (LWJGL3-AWT). */ private long context; + + /** + * Information object used to create the OpenGL context. + */ private GLData data; + + /** Effective data to initialize the context. */ private GLData effective; + /** + * Constructor of the LwjglAWTGLCanva class where objects are + * initialized for OpenGL-AWT rendering + * + * @param data A {@link org.lwjgl.opengl.awt.GLData} object + */ public LwjglAWTGLCanvas(GLData data) { this.effective = new GLData(); this.context = NULL; this.data = data; try { - platformCanvas = LwjglxDefaultGLPlatform.createLwjglxGLPlatform(); + platformCanvas = createLwjglxGLPlatform(); } catch (UnsupportedOperationException e) { listener.handleError(e.getLocalizedMessage(), e); } } + /** + * (non-Javadoc) + * @see java.awt.Component#addComponentListener(java.awt.event.ComponentListener) + * @param l object-listener + */ @Override public synchronized void addComponentListener(ComponentListener l) { super.addComponentListener(l); } + /** + * Returns the effective data (recommended or ideal) to initialize the + * LWJGL3-AWT context. + * + * @return A {@link org.lwjgl.opengl.awt.GLData} object + */ public GLData getGLDataEffective() { return effective; } + /** + * Called after beforeRender() to release the threads (unlock); + * so that AWT can update its threads normally. + *

+ * NOTE: It is very important to call this method and not leave AWT + * hanging (breaking it) regardless of whether an error occurs during OpenGL + * rendering. + */ public void afterRender() { + // release the rendering context platformCanvas.makeCurrent(NULL); try { platformCanvas.unlock(); // <- MUST unlock on Linux @@ -186,7 +238,11 @@ public void afterRender() { } } + /** + * Called before afterRender() to prepare the AWT drawing surface. + */ public void beforeRender() { + // this is where the OpenGL rendering context is generated. if (context == NULL) { try { context = platformCanvas.create(this, data, effective); @@ -195,59 +251,99 @@ public void beforeRender() { return; } } + + /* + * To start drawing on the AWT surface, the AWT threads must be locked to + * avoid conflicts when drawing on the canvas. + */ try { platformCanvas.lock(); // <- MUST lock on Linux } catch (AWTException e) { listener.handleError("Failed to lock Canvas", e); } + + /* + * The 'makeCurrent(long)' method converts the specified OpenGL rendering + * context to the current rendering context. + */ platformCanvas.makeCurrent(context); } + /** + * Frees up the drawing surface (only on Windows and MacOSX). + */ public void doDisposeCanvas() { - platformCanvas.dispose(); + if (OS != Platform.LINUX) { + platformCanvas.dispose(); + } } + /** + * This is where you actually draw on the canvas (framebuffer). + */ public void swapBuffers() { platformCanvas.swapBuffers(); } + /** + * (non-Javadoc) + * @see java.awt.Component#addNotify() + */ @Override public void addNotify() { super.addNotify(); + /* you have to notify if the canvas is visible to draw on it. */ synchronized (lock) { hasNativePeer.set(true); } requestFocusInWindow(); } + /** + * (non-Javadoc) + * @see java.awt.Component#removeNotify() + */ @Override public void removeNotify() { synchronized (lock) { + // prepare for a possible re-adding + if ((OS != Platform.LINUX) && (context != NULL)) { + platformCanvas.deleteContext(context); + context = NULL; + } hasNativePeer.set(false); } super.removeNotify(); - if ((OS == Platform.MACOSX) && (context != NULL)) { - platformCanvas.deleteContext(context); - context = NULL; + if (OS == Platform.WINDOWS) { + LOGGER.log(Level.WARNING, "Windows does not support this functionality: remove(__canvas__)"); } } + /** + * (non-Javadoc) + * @see com.jme3.system.lwjglx.LwjglxGLPlatform#destroy() + */ public void destroy() { platformCanvas.destroy(); } /** - * Returns Graphics object that ignores {@link Graphics#clearRect(int, int, int, int)} + * Returns Graphics object that ignores {@link java.awt.Graphics#clearRect(int, int, int, int)} * calls. + *

* This is done so that the frame buffer will not be cleared by AWT/Swing internals. + * + * @see org.lwjgl.awthacks.NonClearGraphics2D + * @see org.lwjgl.awthacks.NonClearGraphics * @return Graphics */ @Override public Graphics getGraphics() { Graphics graphics = super.getGraphics(); - return (graphics instanceof Graphics2D) - ? new NonClearGraphics2D((Graphics2D) graphics) - : new NonClearGraphics(graphics); + if (graphics instanceof Graphics2D) { + return new NonClearGraphics2D((Graphics2D) graphics); + } + return new NonClearGraphics(graphics); } } @@ -271,24 +367,43 @@ public Graphics getGraphics() { /** Notify if there is a change in canvas dimensions. */ private AtomicBoolean needResize = new AtomicBoolean(false); + + /** + * Flag that uses the context to check if it is initialized or not, this prevents + * it from being initialized multiple times and potentially breaking the JVM. + */ + private AtomicBoolean contextFlag = new AtomicBoolean(false); /** Semaphort used to check the "terminate" signal. */ private final Semaphore signalTerminate = new Semaphore(0); /** lock-object. */ private final Object lock = new Object(); + + /** Framebuffer width. */ private int framebufferWidth = 1; + + /** Framebuffer height. */ private int framebufferHeight = 1; + /** AWT keyboard input manager. */ private AwtKeyInput keyInput; + + /** AWT mouse input manager. */ private AwtMouseInput mouseInput; + /** + * Generate a new OpenGL context (LwjglCanvas) to integrate + * AWT/Swing with JME3 in your desktop applications. + */ public LwjglCanvas() { super(Type.Canvas); - glData = new GLData(); canvas = new LwjglAWTGLCanvas(glData); canvas.setIgnoreRepaint(true); + + // To determine the size of the framebuffer every time the user resizes + // the canvas (this works if the component has a parent) canvas.addComponentListener(new ComponentAdapter() { @Override public void componentResized(ComponentEvent e) { @@ -314,10 +429,47 @@ public void componentResized(ComponentEvent e) { } }); } + + /** + * (non-Javadoc) + * @see com.jme3.system.JmeContext#destroy(boolean) + * @param waitFor boolean + */ + @Override + public void destroy(boolean waitFor) { + super.destroy(waitFor); + this.contextFlag.set(false); + } + + /** + * (non-Javadoc) + * @see com.jme3.system.JmeContext#create(boolean) + * @param waitFor boolean + */ + @Override + public void create(boolean waitFor) { + if (this.contextFlag.get()) { + return; + } + // create context + super.create(waitFor); + this.contextFlag.set(true); + } + /** + * (non-Javadoc) + * @see com.jme3.system.lwjgl.LwjglWindow#createContext(com.jme3.system.AppSettings) + * @param settings A {@link com.jme3.system.AppSettings} object + */ @Override protected void createContext(AppSettings settings) { - super.createContext(settings); + try { + Thread.sleep(1000); + } catch (InterruptedException ex) { + LOGGER.log(Level.SEVERE, "LWJGL3-AWT: Interrupted!", ex); + } + + super.createContext(settings); RENDER_CONFIGS.computeIfAbsent(settings.getRenderer(), (t) -> { return (data) -> { data.majorVersion = 2; @@ -342,11 +494,12 @@ protected void createContext(AppSettings settings) { glData.swapInterval = 0; } + // This will activate the "effective data" scrubber. showGLDataEffective.set(settings.getBoolean("GLDataEffectiveDebug")); glData.depthSize = settings.getBitsPerPixel(); glData.alphaSize = settings.getAlphaBits(); - glData.sRGB = settings.isGammaCorrection(); + glData.sRGB = settings.isGammaCorrection(); // Not compatible with very old devices glData.depthSize = settings.getDepthBits(); glData.stencilSize = settings.getStencilBits(); @@ -357,23 +510,30 @@ protected void createContext(AppSettings settings) { glData.api = GLData.API.GL; } + /** + * Returns the AWT component where it is drawn (canvas). + * @return Canvas + */ @Override public Canvas getCanvas() { return canvas; } + /** (non-Javadoc) */ @Override - protected void showWindow() { - } - - @Override - protected void setWindowIcon(final AppSettings settings) { - } - + protected void showWindow() { } + /** (non-Javadoc) */ + @Override + protected void setWindowIcon(final AppSettings settings) { } + /** (non-Javadoc) */ @Override - public void setTitle(String title) { - } + public void setTitle(String title) { } + /** + * (non-Javadoc) + * @see com.jme3.system.lwjgl.LwjglWindow#getKeyInput() + * @return returns a {@link com.jme3.input.awt.AwtKeyInput} object + */ @Override public KeyInput getKeyInput() { if (keyInput == null) { @@ -383,6 +543,11 @@ public KeyInput getKeyInput() { return keyInput; } + /** + * (non-Javadoc) + * @see com.jme3.system.lwjgl.LwjglWindow#getMouseInput() + * @return returns a {@link com.jme3.input.awt.AwtMouseInput} object + */ @Override public MouseInput getMouseInput() { if (mouseInput == null) { @@ -392,8 +557,19 @@ public MouseInput getMouseInput() { return mouseInput; } + /** + * Check if the canvas is displayed, that is, if it has a parent that has set it up. + *

+ * It is very important that this verification be done so that LWJGL3-AWT works correctly. + * + * @return returns true if the canvas is ready to draw; otherwise + * returns false + */ public boolean checkVisibilityState() { if (!hasNativePeer.get()) { + synchronized (lock) { + canvas.doDisposeCanvas(); + } return false; } @@ -402,7 +578,10 @@ public boolean checkVisibilityState() { return currentShowing; } - + /** + * (non-Javadoc) + * @see com.jme3.system.lwjgl.LwjglWindow#destroyContext() + */ @Override protected void destroyContext() { synchronized (lock) { @@ -414,6 +593,10 @@ protected void destroyContext() { super.destroyContext(); } + /** + * (non-Javadoc) + * @see com.jme3.system.lwjgl.LwjglWindow#runLoop() + */ @Override protected void runLoop() { if (needResize.get()) { @@ -421,11 +604,23 @@ protected void runLoop() { settings.setResolution(framebufferWidth, framebufferHeight); listener.reshape(framebufferWidth, framebufferHeight); } - + + // check component status if (!checkVisibilityState()) { return; } + //---------------------------------------------------------------------- + // AWT - RENDERER + //---------------------------------------------------------------------- + /* + * The same logic as AWTGLCanvas is used to draw on the awt drawing surface: + * + * 1. Lock any thread to avoid any conflict. + * 2. Buffer swap (this is where the framebuffer is actually drawn): swapBuffers() + * 3. Unlock so that the AWT thread can work normally. IF NOT DONE, IT WILL + * BE WAITING AND BREAK ANY AWT/Swing APP. + */ canvas.beforeRender(); try { super.runLoop(); @@ -436,8 +631,15 @@ protected void runLoop() { canvas.afterRender(); } - // Whether it is necessary to know the effective attributes to - // initialize the LWJGL3-AWT context + // Sync the display on some systems. + Toolkit.getDefaultToolkit().sync(); + + //---------------------------------------------------------------------- + /* + * Whether it is necessary to know the effective attributes to + * initialize the LWJGL3-AWT context + */ + //---------------------------------------------------------------------- if (showGLDataEffective.get()) { showGLDataEffective.set(false); System.out.println(MessageFormat.format("[ DEBUGGER ] :Effective data to initialize the LWJGL3-AWT context\n{0}", @@ -451,6 +653,10 @@ protected void runLoop() { } catch (InterruptedException ignored) { } } + /** + * (non-Javadoc) + * @see com.jme3.system.lwjgl.LwjglContext#printContextInitInfo() + */ @Override protected void printContextInitInfo() { super.printContextInitInfo(); @@ -528,13 +734,23 @@ protected String getPrintContextInitInfo(GLData glData) { return String.valueOf(sb); } + /** + * (non-Javadoc) + * @see com.jme3.system.lwjgl.LwjglWindow#getFramebufferHeight() + * @return int + */ @Override public int getFramebufferHeight() { - return framebufferHeight; + return this.framebufferHeight; } + /** + * (non-Javadoc) + * @see com.jme3.system.lwjgl.LwjglWindow#getFramebufferWidth() + * @return int + */ @Override public int getFramebufferWidth() { - return framebufferWidth; + return this.framebufferWidth; } } diff --git a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglWindow.java b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglWindow.java index 884ef9e4fe..e380786244 100644 --- a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglWindow.java +++ b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglWindow.java @@ -46,6 +46,7 @@ import com.jme3.system.NanoTimer; import com.jme3.util.BufferUtils; import com.jme3.util.SafeArrayList; + import org.lwjgl.Version; import org.lwjgl.glfw.GLFWErrorCallback; import org.lwjgl.glfw.GLFWFramebufferSizeCallback; diff --git a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjglx/LwjglxDefaultGLPlatform.java b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjglx/LwjglxDefaultGLPlatform.java index d6f8bee801..3f7be3bcf3 100644 --- a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjglx/LwjglxDefaultGLPlatform.java +++ b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjglx/LwjglxDefaultGLPlatform.java @@ -49,6 +49,7 @@ public static LwjglxGLPlatform createLwjglxGLPlatform() throws UnsupportedOperat switch (Platform.get()) { case WINDOWS: return new Win32GLPlatform(); + //case FREEBSD: -> In future versions of lwjgl3 (possibly) case LINUX: return new X11GLPlatform(); case MACOSX: diff --git a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjglx/MacOSXGLPlatform.java b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjglx/MacOSXGLPlatform.java index 96d5456c6d..bce9b4c6da 100644 --- a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjglx/MacOSXGLPlatform.java +++ b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjglx/MacOSXGLPlatform.java @@ -40,10 +40,10 @@ * * @author wil */ -public class MacOSXGLPlatform extends PlatformMacOSXGLCanvas implements LwjglxGLPlatform { +final class MacOSXGLPlatform extends PlatformMacOSXGLCanvas implements LwjglxGLPlatform { /** - * (non-JavaDoc) + * (non-Javadoc) * @see com.jme3.system.lwjglx.LwjglxGLPlatform#destroy() */ @Override @@ -53,4 +53,4 @@ public void destroy() { awt.free(); } } -} + } diff --git a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjglx/Win32GLPlatform.java b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjglx/Win32GLPlatform.java index d466d27271..794498a52c 100644 --- a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjglx/Win32GLPlatform.java +++ b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjglx/Win32GLPlatform.java @@ -32,101 +32,18 @@ package com.jme3.system.lwjglx; import static org.lwjgl.system.jawt.JAWTFunctions.*; - import org.lwjgl.opengl.awt.PlatformWin32GLCanvas; -import org.lwjgl.system.jawt.JAWTDrawingSurfaceInfo; -import org.lwjgl.system.jawt.JAWTWin32DrawingSurfaceInfo; - /** - * Class Win32GLPlatform; overrides the following methods: swapBuffers() - * ,makeCurrent(long context) and delayBeforeSwapNV(float seconds). - * So that the canvas can be removed and added back from its parent component. - *

- * Only for windows. + * Win32GLPlatform class that implements the {@link com.jme3.system.lwjglx.LwjglxGLPlatform} + * interface for the Windows (Win32) platform. * * @author wil */ -public class Win32GLPlatform extends PlatformWin32GLCanvas implements LwjglxGLPlatform { - - /** - * (non-JavaDoc) - * @see org.lwjgl.opengl.awt.PlatformGLCanvas#swapBuffers() - * @return boolean - */ - @Override - public boolean swapBuffers() { - // Get the drawing surface info - JAWTDrawingSurfaceInfo dsi = JAWT_DrawingSurface_GetDrawingSurfaceInfo(ds, ds.GetDrawingSurfaceInfo()); - if (dsi == null) { - throw new IllegalStateException("JAWT_DrawingSurface_GetDrawingSurfaceInfo() failed"); - } - - try { - // Get the platform-specific drawing info - JAWTWin32DrawingSurfaceInfo dsiWin = JAWTWin32DrawingSurfaceInfo.create(dsi.platformInfo()); - hwnd = dsiWin.hwnd(); - return super.swapBuffers(); - } finally { - // Free the drawing surface info - JAWT_DrawingSurface_FreeDrawingSurfaceInfo(dsi, ds.FreeDrawingSurfaceInfo()); - } - } +final class Win32GLPlatform extends PlatformWin32GLCanvas implements LwjglxGLPlatform { /** - * (non-JavaDoc) - * @see org.lwjgl.opengl.awt.PlatformGLCanvas#makeCurrent(long) - * - * @param context long - * @return boolean - */ - @Override - public boolean makeCurrent(long context) { - // Get the drawing surface info - JAWTDrawingSurfaceInfo dsi = JAWT_DrawingSurface_GetDrawingSurfaceInfo(ds, ds.GetDrawingSurfaceInfo()); - if (dsi == null) { - throw new IllegalStateException("JAWT_DrawingSurface_GetDrawingSurfaceInfo() failed"); - } - - try { - // Get the platform-specific drawing info - JAWTWin32DrawingSurfaceInfo dsiWin = JAWTWin32DrawingSurfaceInfo.create(dsi.platformInfo()); - hwnd = dsiWin.hwnd(); - return super.makeCurrent(context); - } finally { - // Free the drawing surface info - JAWT_DrawingSurface_FreeDrawingSurfaceInfo(dsi, ds.FreeDrawingSurfaceInfo()); - } - } - - /** - * (non-JavaDoc) - * @see org.lwjgl.opengl.awt.PlatformGLCanvas#delayBeforeSwapNV(float) - * - * @param seconds float - * @return boolean - */ - @Override - public boolean delayBeforeSwapNV(float seconds) { - // Get the drawing surface info - JAWTDrawingSurfaceInfo dsi = JAWT_DrawingSurface_GetDrawingSurfaceInfo(ds, ds.GetDrawingSurfaceInfo()); - if (dsi == null) { - throw new IllegalStateException("JAWT_DrawingSurface_GetDrawingSurfaceInfo() failed"); - } - - try { - // Get the platform-specific drawing info - JAWTWin32DrawingSurfaceInfo dsiWin = JAWTWin32DrawingSurfaceInfo.create(dsi.platformInfo()); - hwnd = dsiWin.hwnd(); - return super.delayBeforeSwapNV(seconds); - } finally { - // Free the drawing surface info - JAWT_DrawingSurface_FreeDrawingSurfaceInfo(dsi, ds.FreeDrawingSurfaceInfo()); - } - } - - /** - * (non-JavaDoc) + * (non-Javadoc) * @see com.jme3.system.lwjglx.LwjglxGLPlatform#destroy() */ @Override diff --git a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjglx/X11GLPlatform.java b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjglx/X11GLPlatform.java index d3e1a2d71d..198b9b7317 100644 --- a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjglx/X11GLPlatform.java +++ b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjglx/X11GLPlatform.java @@ -47,10 +47,10 @@ * * @author wil */ -public class X11GLPlatform extends PlatformLinuxGLCanvas implements LwjglxGLPlatform { +final class X11GLPlatform extends PlatformLinuxGLCanvas implements LwjglxGLPlatform { /** - * (non-JavaDoc) + * (non-Javadoc) * @see org.lwjgl.opengl.awt.PlatformGLCanvas#swapBuffers() * @return boolean */ @@ -78,7 +78,7 @@ public boolean swapBuffers() { } /** - * (non-JavaDoc) + * (non-Javadoc) * @see org.lwjgl.opengl.awt.PlatformGLCanvas#makeCurrent(long) * * @param context long @@ -110,7 +110,7 @@ public boolean makeCurrent(long context) { } /** - * (non-JavaDoc) + * (non-Javadoc) * @see com.jme3.system.lwjglx.LwjglxGLPlatform#destroy() */ @Override