diff --git a/jme3-examples/build.gradle b/jme3-examples/build.gradle index b5979feceb..7fd7034dae 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') diff --git a/jme3-examples/src/main/java/jme3test/awt/TestCanvas.java b/jme3-examples/src/main/java/jme3test/awt/TestCanvas.java index bb4b39ac95..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,7 +170,7 @@ public void actionPerformed(ActionEvent e){ public void actionPerformed(ActionEvent e) { currentPanel.remove(canvas); app.stop(true); - + createCanvas(appClass); currentPanel.add(canvas, BorderLayout.CENTER); frame.pack(); diff --git a/jme3-lwjgl3/build.gradle b/jme3-lwjgl3/build.gradle index f035ac7229..e20ce923b9 100644 --- a/jme3-lwjgl3/build.gradle +++ b/jme3-lwjgl3/build.gradle @@ -1,9 +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 index 0614cba16c..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-2022 jMonkeyEngine + * Copyright (c) 2009-2024 jMonkeyEngine * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -37,151 +37,538 @@ import com.jme3.input.awt.AwtMouseInput; import com.jme3.system.AppSettings; import com.jme3.system.JmeCanvasContext; -import com.jme3.system.JmeContext.Type; -import com.jme3.texture.FrameBuffer; -import com.jme3.texture.FrameBuffer.FrameBufferTarget; -import com.jme3.texture.Image; -import com.jme3.util.BufferUtils; -import com.jme3.util.Screenshots; +import com.jme3.system.lwjglx.LwjglxGLPlatform; + import java.awt.AWTException; -import java.awt.BufferCapabilities; import java.awt.Canvas; import java.awt.Graphics; import java.awt.Graphics2D; -import java.awt.ImageCapabilities; -import java.awt.RenderingHints; +import java.awt.GraphicsConfiguration; +import java.awt.Toolkit; import java.awt.event.ComponentAdapter; import java.awt.event.ComponentEvent; +import java.awt.event.ComponentListener; import java.awt.geom.AffineTransform; -import java.awt.image.AffineTransformOp; -import java.awt.image.BufferStrategy; -import java.awt.image.BufferedImage; -import java.nio.ByteBuffer; -import java.nio.IntBuffer; +import java.text.MessageFormat; +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; +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.*; +import static com.jme3.system.lwjglx.LwjglxDefaultGLPlatform.*; + +/** + * 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);
+ * ...
+ * 
+ * + *

+ * 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 { - private static final Logger logger = Logger.getLogger(LwjglCanvas.class.getName()); - - private final Canvas canvas; - - private BufferedImage img; - private FrameBuffer fb; - - private ByteBuffer byteBuf; - private IntBuffer intBuf; - - private BufferStrategy strategy; - private AffineTransformOp transformOp; + /** Logger class. */ + private static final Logger LOGGER = Logger.getLogger(LwjglCanvas.class.getName()); + + /** 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(); + + /* + 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.majorVersion = 3; + data.minorVersion = 2; + data.profile = GLData.Profile.COMPATIBILITY; + }); + RENDER_CONFIGS.put(AppSettings.LWJGL_OPENGL33, (data) -> { + data.majorVersion = 3; + data.minorVersion = 3; + data.profile = GLData.Profile.COMPATIBILITY; + }); + RENDER_CONFIGS.put(AppSettings.LWJGL_OPENGL40, (data) -> { + data.majorVersion = 4; + data.minorVersion = 0; + data.profile = GLData.Profile.COMPATIBILITY; + }); + RENDER_CONFIGS.put(AppSettings.LWJGL_OPENGL41, (data) -> { + data.majorVersion = 4; + data.minorVersion = 1; + data.profile = GLData.Profile.COMPATIBILITY; + }); + RENDER_CONFIGS.put(AppSettings.LWJGL_OPENGL42, (data) -> { + data.majorVersion = 4; + data.minorVersion = 2; + data.profile = GLData.Profile.COMPATIBILITY; + }); + RENDER_CONFIGS.put(AppSettings.LWJGL_OPENGL43, (data) -> { + data.majorVersion = 4; + data.minorVersion = 3; + data.profile = GLData.Profile.COMPATIBILITY; + }); + RENDER_CONFIGS.put(AppSettings.LWJGL_OPENGL44, (data) -> { + data.majorVersion = 4; + data.minorVersion = 4; + data.profile = GLData.Profile.COMPATIBILITY; + }); + RENDER_CONFIGS.put(AppSettings.LWJGL_OPENGL45, (data) -> { + data.majorVersion = 4; + data.minorVersion = 5; + data.profile = GLData.Profile.COMPATIBILITY; + }); + } + + /** + * 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 = 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 + } catch (AWTException e) { + listener.handleError("Failed to unlock Canvas", e); + } + } + + /** + * 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); + } catch (AWTException e) { + listener.handleError("Exception while creating the OpenGL context", e); + 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() { + 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.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 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(); + if (graphics instanceof Graphics2D) { + return new NonClearGraphics2D((Graphics2D) graphics); + } + return new NonClearGraphics(graphics); + } + } + + /** 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); - - private int width = 1; - private int height = 1; + + /** Notify if there is a change in canvas dimensions. */ private AtomicBoolean needResize = new AtomicBoolean(false); - private final Object lock = new Object(); + + /** + * 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); - - canvas = new Canvas() { - @Override - public void paint(Graphics g) { - Graphics2D g2d = (Graphics2D) g; - synchronized (lock) { - g2d.drawImage(img, transformOp, 0, 0); - } - } - - @Override - public void addNotify() { - super.addNotify(); - - synchronized (lock) { - hasNativePeer.set(true); - } - - requestFocusInWindow(); - } - + 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 removeNotify() { + public void componentResized(ComponentEvent e) { synchronized (lock) { - hasNativePeer.set(false); - } + GraphicsConfiguration gc = canvas.getGraphicsConfiguration(); + if (gc == null) { + return; + } + + AffineTransform at = gc.getDefaultTransform(); + float sx = (float) at.getScaleX(), + sy = (float) at.getScaleY(); - super.removeNotify(); - } - }; - canvas.addComponentListener(new ComponentAdapter() { + int fw = (int) (canvas.getWidth() * sx); + int fh = (int) (canvas.getHeight() * sy); - @Override - public void componentResized(ComponentEvent e) { - synchronized (lock) { - int newWidth = Math.max(canvas.getWidth(), 1); - int newHeight = Math.max(canvas.getHeight(), 1); - if (width != newWidth || height != newHeight) { - width = newWidth; - height = newHeight; + if (fw != framebufferWidth || fh != framebufferHeight) { + framebufferWidth = Math.max(fw, 1); + framebufferHeight = Math.max(fh, 1); needResize.set(true); } } - } + } }); - canvas.setFocusable(true); - canvas.setIgnoreRepaint(true); } + /** + * (non-Javadoc) + * @see com.jme3.system.JmeContext#destroy(boolean) + * @param waitFor boolean + */ @Override - public Canvas getCanvas() { - return canvas; + 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 - protected void showWindow() { + 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 setWindowIcon(final AppSettings settings) { + protected void createContext(AppSettings 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; + data.minorVersion = 0; + }; + }).accept(glData); + + 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; + } + + // Enable vsync for LWJGL3-AWT + if (settings.isVSync()) { + glData.swapInterval = 1; + } else { + 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(); // Not compatible with very old devices + + glData.depthSize = settings.getDepthBits(); + glData.stencilSize = settings.getStencilBits(); + glData.samples = settings.getSamples(); + glData.stereo = settings.useStereo3D(); + + glData.debug = settings.isGraphicsDebug(); + glData.api = GLData.API.GL; } - + + /** + * Returns the AWT component where it is drawn (canvas). + * @return Canvas + */ @Override - public void setTitle(String title) { + public Canvas getCanvas() { + return canvas; } + /** (non-Javadoc) */ + @Override + protected void showWindow() { } + /** (non-Javadoc) */ + @Override + protected void setWindowIcon(final AppSettings settings) { } + /** (non-Javadoc) */ + @Override + 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) { keyInput = new AwtKeyInput(); keyInput.setInputSource(canvas); } - 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) { mouseInput = new AwtMouseInput(); mouseInput.setInputSource(canvas); } - 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) { - if (strategy != null) { - strategy.dispose(); - strategy = null; - } + canvas.doDisposeCanvas(); } return false; } @@ -191,111 +578,179 @@ public boolean checkVisibilityState() { return currentShowing; } + /** + * (non-Javadoc) + * @see com.jme3.system.lwjgl.LwjglWindow#destroyContext() + */ @Override protected void destroyContext() { synchronized (lock) { - destroyFrameBuffer(); - img = null; - byteBuf = null; - intBuf = null; + canvas.destroy(); } + // request the cleanup + signalTerminate.release(); super.destroyContext(); } - @Override - protected void createContext(AppSettings settings) { - super.createContext(settings); - - if (renderer != null) { - createFrameBuffer(width, height); - } - } - + /** + * (non-Javadoc) + * @see com.jme3.system.lwjgl.LwjglWindow#runLoop() + */ @Override protected void runLoop() { if (needResize.get()) { needResize.set(false); - listener.reshape(width, height); - createFrameBuffer(width, height); + settings.setResolution(framebufferWidth, framebufferHeight); + listener.reshape(framebufferWidth, framebufferHeight); } - + + // check component status if (!checkVisibilityState()) { return; } - super.runLoop(); - - drawFrameInThread(); - } - - public void drawFrameInThread() { - - // Convert screenshot - byteBuf.clear(); - renderer.readFrameBuffer(fb, byteBuf); - Screenshots.convertScreenShot2(intBuf, img); - - synchronized (lock) { - // All operations on strategy should be synchronized (?) - if (strategy == null) { - try { - canvas.createBufferStrategy(1, - new BufferCapabilities( - new ImageCapabilities(true), - new ImageCapabilities(true), - BufferCapabilities.FlipContents.UNDEFINED) - ); - } catch (AWTException ex) { - logger.log(Level.SEVERE, "Failed to create buffer strategy!", ex); - } - strategy = canvas.getBufferStrategy(); + //---------------------------------------------------------------------- + // 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(); + if (allowSwapBuffers && autoFlush) { + canvas.swapBuffers(); } - - // Draw screenshot - do { - do { - Graphics2D g2d = (Graphics2D) strategy.getDrawGraphics(); - if (g2d == null) { - logger.log(Level.WARNING, "OGL: DrawGraphics was null."); - return; - } - - g2d.setRenderingHint(RenderingHints.KEY_RENDERING, - RenderingHints.VALUE_RENDER_QUALITY); - - g2d.drawImage(img, transformOp, 0, 0); - g2d.dispose(); - strategy.show(); - } while (strategy.contentsRestored()); - } while (strategy.contentsLost()); + } finally { + canvas.afterRender(); + } + + // 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}", + getPrintContextInitInfo(canvas.getGLDataEffective()))); } - } - - private void createFrameBuffer(int width, int height) { - byteBuf = BufferUtils.ensureLargeEnough(byteBuf, width * height * 4); - intBuf = byteBuf.asIntBuffer(); - - destroyFrameBuffer(); - - fb = new FrameBuffer(width, height, settings.getSamples()); - fb.setDepthTarget(FrameBufferTarget.newTarget(Image.Format.Depth)); - fb.addColorTarget(FrameBufferTarget.newTarget(Image.Format.RGB8)); - fb.setSrgb(settings.isGammaCorrection()); - - renderer.setMainFrameBufferOverride(fb); - - img = new BufferedImage(width, height, BufferedImage.TYPE_INT_BGR); - AffineTransform tx = AffineTransform.getScaleInstance(1, -1); - tx.translate(0, -img.getHeight()); - transformOp = new AffineTransformOp(tx, AffineTransformOp.TYPE_NEAREST_NEIGHBOR); + try { + if (signalTerminate.tryAcquire(10, TimeUnit.MILLISECONDS)) { + canvas.doDisposeCanvas(); + } + } catch (InterruptedException ignored) { } + } + + /** + * (non-Javadoc) + * @see com.jme3.system.lwjgl.LwjglContext#printContextInitInfo() + */ + @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(" * 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); + } + + /** + * (non-Javadoc) + * @see com.jme3.system.lwjgl.LwjglWindow#getFramebufferHeight() + * @return int + */ + @Override + public int getFramebufferHeight() { + return this.framebufferHeight; } - public void destroyFrameBuffer() { - if (fb != null) { - fb.dispose(); - fb = null; - } + /** + * (non-Javadoc) + * @see com.jme3.system.lwjgl.LwjglWindow#getFramebufferWidth() + * @return int + */ + @Override + public int getFramebufferWidth() { + 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 155693c8b9..4d92383b50 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,16 @@ 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; +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.image.BufferedImage; import java.nio.ByteBuffer; @@ -55,17 +65,10 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.logging.Level; import java.util.logging.Logger; -import org.lwjgl.Version; + import static org.lwjgl.glfw.GLFW.*; -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 static org.lwjgl.opengl.GL11.GL_FALSE; import static org.lwjgl.system.MemoryUtil.NULL; -import org.lwjgl.system.Platform; /** * A wrapper class over the GLFW framework in LWJGL 3. @@ -631,9 +634,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) { 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; 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..3f7be3bcf3 --- /dev/null +++ b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjglx/LwjglxDefaultGLPlatform.java @@ -0,0 +1,66 @@ +/* + * 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.*; + +/** + * 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: + return new Win32GLPlatform(); + //case FREEBSD: -> In future versions of lwjgl3 (possibly) + case LINUX: + return new X11GLPlatform(); + case MACOSX: + return new MacOSXGLPlatform(); + default: + throw new UnsupportedOperationException("Platform " + Platform.get() + " not yet supported"); + } + } + + /** + * private constructor. + */ + 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..bce9b4c6da --- /dev/null +++ b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjglx/MacOSXGLPlatform.java @@ -0,0 +1,56 @@ +/* + * 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; +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 + */ +final 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(); + } + } + } 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..794498a52c --- /dev/null +++ b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjglx/Win32GLPlatform.java @@ -0,0 +1,56 @@ +/* + * 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 static org.lwjgl.system.jawt.JAWTFunctions.*; +import org.lwjgl.opengl.awt.PlatformWin32GLCanvas; + +/** + * Win32GLPlatform class that implements the {@link com.jme3.system.lwjglx.LwjglxGLPlatform} + * interface for the Windows (Win32) platform. + * + * @author wil + */ +final class Win32GLPlatform extends PlatformWin32GLCanvas 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(); + } + } +} 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..198b9b7317 --- /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 + */ +final 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(); + } + } +} 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 c406da86de..77e6330696 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; }