From bcf3349fcffcc64badeef438356f687a39b9ff3a Mon Sep 17 00:00:00 2001 From: wil Date: Tue, 12 May 2026 15:48:13 -0600 Subject: [PATCH 1/5] fix: fix the canvas tearing problem with lwjglx. --- .../main/java/jme3test/awt/TestCanvas.java | 1 + .../com/jme3/system/lwjgl/LwjglCanvas.java | 96 ++++++++++++++++--- .../com/jme3/system/lwjgl/LwjglContext.java | 20 ++-- .../com/jme3/system/lwjgl/LwjglWindow.java | 35 ++++--- 4 files changed, 116 insertions(+), 36 deletions(-) diff --git a/jme3-examples/src/main/java/jme3test/awt/TestCanvas.java b/jme3-examples/src/main/java/jme3test/awt/TestCanvas.java index 0b59110485..189bf0b7ed 100644 --- a/jme3-examples/src/main/java/jme3test/awt/TestCanvas.java +++ b/jme3-examples/src/main/java/jme3test/awt/TestCanvas.java @@ -210,6 +210,7 @@ public static void createCanvas(String appClass){ // Note: Only for Linux and Wayland platforms, forces you to // use XWayland (x11) with awt. settings.setX11PlatformPreferred(true); + settings.setRenderer(AppSettings.LWJGL_OPENGL32); settings.setWidth(640); settings.setHeight(480); 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 8ed443f337..8c9e756d7a 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 @@ -77,6 +77,7 @@ import static org.lwjgl.system.MemoryUtil.*; import static com.jme3.system.lwjglx.LwjglxDefaultGLPlatform.*; +import org.lwjgl.system.Platform; /** * Class LwjglCanvas that integrates LWJGLX @@ -116,47 +117,53 @@ public class LwjglCanvas extends LwjglWindow implements JmeCanvasContext, Runnab /* Register the different versions. + + The 'COMPATIBILITY' profile is used for operational reasons on different + platforms. + + see the discussion: + https://github.com/jMonkeyEngine/jmonkeyengine/pull/2153#issuecomment-1860913192 */ static { RENDER_CONFIGS.put(AppSettings.LWJGL_OPENGL32, (data) -> { data.majorVersion = 3; data.minorVersion = 2; - data.profile = GLData.Profile.CORE; + data.profile = GLData.Profile.COMPATIBILITY; }); RENDER_CONFIGS.put(AppSettings.LWJGL_OPENGL33, (data) -> { data.majorVersion = 3; data.minorVersion = 3; - data.profile = GLData.Profile.CORE; + data.profile = GLData.Profile.COMPATIBILITY; }); RENDER_CONFIGS.put(AppSettings.LWJGL_OPENGL40, (data) -> { data.majorVersion = 4; data.minorVersion = 0; - data.profile = GLData.Profile.CORE; + data.profile = GLData.Profile.COMPATIBILITY; }); RENDER_CONFIGS.put(AppSettings.LWJGL_OPENGL41, (data) -> { data.majorVersion = 4; data.minorVersion = 1; - data.profile = GLData.Profile.CORE; + data.profile = GLData.Profile.COMPATIBILITY; }); RENDER_CONFIGS.put(AppSettings.LWJGL_OPENGL42, (data) -> { data.majorVersion = 4; data.minorVersion = 2; - data.profile = GLData.Profile.CORE; + data.profile = GLData.Profile.COMPATIBILITY; }); RENDER_CONFIGS.put(AppSettings.LWJGL_OPENGL43, (data) -> { data.majorVersion = 4; data.minorVersion = 3; - data.profile = GLData.Profile.CORE; + data.profile = GLData.Profile.COMPATIBILITY; }); RENDER_CONFIGS.put(AppSettings.LWJGL_OPENGL44, (data) -> { data.majorVersion = 4; data.minorVersion = 4; - data.profile = GLData.Profile.CORE; + data.profile = GLData.Profile.COMPATIBILITY; }); RENDER_CONFIGS.put(AppSettings.LWJGL_OPENGL45, (data) -> { data.majorVersion = 4; data.minorVersion = 5; - data.profile = GLData.Profile.CORE; + data.profile = GLData.Profile.COMPATIBILITY; }); } @@ -452,6 +459,47 @@ public void componentResized(ComponentEvent e) { }); } + /** + * Returns the GL context handler. + * + * @return String + */ + @Override + protected String getCurrentVideoDriver() { + StringBuilder buffer = new StringBuilder(); + buffer.append("AWT|Swing (LWJGLX) GLv") + .append(canvas.data.majorVersion) + .append('.') + .append(canvas.data.minorVersion); + + String driver = isWayland() ? "(XWayland|X11) GLX" : "X11 GLX"; + + Platform platform = Platform.get(); + if (null == platform) { + buffer.append(" Unknown NULL"); + } else { + switch (platform) { + case FREEBSD: + buffer.append(" FreeBSD ") + .append(driver); + break; + case LINUX: + buffer.append(" Linux ") + .append(driver); + break; + case MACOSX: + buffer.append(" MacOSX Cocoa NSGL"); + break; + case WINDOWS: + buffer.append(" Win32 WGL"); + break; + default: + break; + } + } + return String.valueOf(buffer); + } + /** * Check if the canvas is displayed, that is, if it has a parent that has set it up. *

@@ -688,7 +736,7 @@ protected void createContext(AppSettings settings) { } glData.alphaSize = settings.getAlphaBits(); - glData.sRGB = settings.isGammaCorrection() && !useAuxFramebufferSrgb(); + glData.sRGB = settings.isGammaCorrection(); // Not compatible with very old devices glData.depthSize = settings.getDepthBits(); glData.stencilSize = settings.getStencilBits(); @@ -697,7 +745,11 @@ protected void createContext(AppSettings settings) { glData.debug = settings.isGraphicsDebug(); glData.api = GLData.API.GL; - glData.forwardCompatible = true; + + /* This is done to prevent the context from breaking in Windows, + * since the 'CORE' profile causes rendering failures (black screen). + */ + glData.forwardCompatible = false; allowSwapBuffers = settings.isSwapBuffers(); @@ -766,7 +818,7 @@ public JoyInput getJoyInput() { /** (non-Javadoc) */ @Override protected void showWindow() { } /** (non-Javadoc) */ - @Override protected void setWindowIcon(final AppSettings settings) { } + @Override protected void setWindowIcon(final AppSettings settings) { } /**(non-Javadoc) */ @Override public Vector2f getWindowContentScale(Vector2f store) { return store == null ? new Vector2f() : store; @@ -1005,4 +1057,26 @@ public int getPrimaryDisplay() { public Canvas getCanvas() { return canvas; } + + /** + * {@inheritDoc} + * @param settings AppSettings + */ + @Override + public void setSettings(AppSettings settings) { + if (settings.getRenderer().equals(AppSettings.ANGLE_GLES3)) { + StringBuilder buffer = new StringBuilder(); + buffer.append("LWJGX is not compatible with ANGLE/SDL or GLES, as it only supports the following:") + .append('\n').append(" * WGL | Windows") + .append('\n').append(" * GLX | Linux (X11/XWayland)") + .append('\n').append(" * CGL | MacOsX") + .append('\n').append(" * Therefore, version ") + .append(AppSettings.LWJGL_OPENGL32) + .append("(3.2) will be used for the GL context."); + + LOGGER.log(Level.WARNING, String.valueOf(buffer)); + settings.setRenderer(AppSettings.LWJGL_OPENGL32); + } + super.setSettings(settings); + } } diff --git a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglContext.java b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglContext.java index 0f02d0fa5e..b78d39952c 100644 --- a/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglContext.java +++ b/jme3-lwjgl3/src/main/java/com/jme3/system/lwjgl/LwjglContext.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2023 jMonkeyEngine + * Copyright (c) 2009-2026 jMonkeyEngine * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -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 com.jme3.system.lwjgl; import com.jme3.input.JoyInput; @@ -55,28 +54,27 @@ import com.jme3.util.LWJGLBufferAllocator.ConcurrentLWJGLBufferAllocator; import com.jme3.util.LWJGLSaferAllocMemoryAllocator; -import static com.jme3.util.LWJGLBufferAllocator.PROPERTY_CONCURRENT_BUFFER_ALLOCATOR; import java.nio.IntBuffer; import java.util.*; import java.util.concurrent.atomic.AtomicBoolean; import java.util.logging.Level; import java.util.logging.Logger; + import org.lwjgl.Version; import org.lwjgl.opengl.ARBDebugOutput; import org.lwjgl.opengl.ARBFramebufferObject; import org.lwjgl.opengl.EXTFramebufferMultisample; import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL30; - -import static org.lwjgl.opengl.GL.createCapabilities; -import static org.lwjgl.opengl.GL11.glGetInteger; import org.lwjgl.opengl.GLCapabilities; import org.lwjgl.opengles.GLES; import org.lwjgl.opengles.GLES30; import org.lwjgl.opengles.GLESCapabilities; -import static org.lwjgl.sdl.SDLVideo.*; import org.lwjgl.system.Configuration; -import org.lwjgl.system.MemoryStack; + +import static org.lwjgl.opengl.GL.createCapabilities; +import static org.lwjgl.opengl.GL11.glGetInteger; +import static com.jme3.util.LWJGLBufferAllocator.PROPERTY_CONCURRENT_BUFFER_ALLOCATOR; /** * A LWJGL implementation of a graphics context. @@ -149,11 +147,13 @@ public void setSystemListener(final SystemListener listener) { protected void printContextInitInfo() { if (logger.isLoggable(Level.INFO)) { - logger.log(Level.INFO, "LWJGL {0} context running on thread {1}\n * Video backend: SDL {2}", - APIUtil.toArray(Version.getVersion(), Thread.currentThread().getName(), SDL_GetCurrentVideoDriver())); + logger.log(Level.INFO, "LWJGL {0} context running on thread {1}\n * Video backend: {2}", + APIUtil.toArray(Version.getVersion(), Thread.currentThread().getName(), getCurrentVideoDriver())); } } + protected abstract String getCurrentVideoDriver(); + protected int determineMaxSamples() { final GLCapabilities capabilities = org.lwjgl.opengl.GL.getCapabilities(); if (capabilities.GL_ARB_framebuffer_object) { 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 2ba6e89670..bfb5070210 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 @@ -31,20 +31,6 @@ */ package com.jme3.system.lwjgl; -import static org.lwjgl.egl.EXTPlatformWayland.EGL_PLATFORM_WAYLAND_EXT; -import static org.lwjgl.egl.EXTPlatformX11.EGL_PLATFORM_X11_EXT; -import static org.lwjgl.sdl.SDLError.*; -import static org.lwjgl.sdl.SDLEvents.*; -import static org.lwjgl.sdl.SDLHints.*; -import static org.lwjgl.sdl.SDLInit.*; -import static org.lwjgl.sdl.SDLKeyboard.*; -import static org.lwjgl.sdl.SDLMouse.*; -import static org.lwjgl.sdl.SDLPixels.*; -import static org.lwjgl.sdl.SDLSurface.*; -import static org.lwjgl.sdl.SDLStdinc.SDL_setenv_unsafe; -import static org.lwjgl.sdl.SDLVideo.*; -import static org.lwjgl.system.MemoryUtil.NULL; - import com.jme3.app.Application; import com.jme3.asset.AssetManager; import com.jme3.input.JoyInput; @@ -75,6 +61,8 @@ import com.jme3.ui.Picture; import com.jme3.util.BufferUtils; import com.jme3.util.SafeArrayList; +import com.jme3.renderer.opengl.GLRenderer; + import java.awt.Graphics2D; import java.awt.image.BufferedImage; import java.nio.ByteBuffer; @@ -85,6 +73,7 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.logging.Level; import java.util.logging.Logger; + import org.lwjgl.Version; import org.lwjgl.sdl.SDL_DisplayMode; import org.lwjgl.sdl.SDL_Event; @@ -92,7 +81,18 @@ import org.lwjgl.sdl.SDLStdinc; import org.lwjgl.system.Configuration; import org.lwjgl.system.MemoryStack; -import com.jme3.renderer.opengl.GLRenderer; + +import static org.lwjgl.egl.EXTPlatformWayland.EGL_PLATFORM_WAYLAND_EXT; +import static org.lwjgl.egl.EXTPlatformX11.EGL_PLATFORM_X11_EXT; +import static org.lwjgl.sdl.SDLError.*; +import static org.lwjgl.sdl.SDLEvents.*; +import static org.lwjgl.sdl.SDLHints.*; +import static org.lwjgl.sdl.SDLInit.*; +import static org.lwjgl.sdl.SDLPixels.*; +import static org.lwjgl.sdl.SDLSurface.*; +import static org.lwjgl.sdl.SDLStdinc.SDL_setenv_unsafe; +import static org.lwjgl.sdl.SDLVideo.*; +import static org.lwjgl.system.MemoryUtil.NULL; /** * SDL3-backed window/context implementation for LWJGL 3.4+. @@ -243,6 +243,11 @@ private static void disableNvidiaThreadedOptimizations() { } } + @Override + protected String getCurrentVideoDriver() { + return "SDL " + SDL_GetCurrentVideoDriver(); + } + @Override public JmeContext.Type getType() { return type; From e1851f6379ff30ec8ddd1ba755769b061ce35041 Mon Sep 17 00:00:00 2001 From: wil Date: Tue, 12 May 2026 15:49:18 -0600 Subject: [PATCH 2/5] docs: update|javadoc --- .../src/main/java/com/jme3/system/lwjgl/LwjglCanvas.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 8c9e756d7a..fa8af1178f 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 @@ -101,7 +101,8 @@ *


  * ....
  *  AppSettings settings = new AppSettings(true);
- *  settings.setGammaCorrection(false);
+ *  settings.setGammaCorrection(true);
+ *  settings.setRenderer(AppSettings.LWJGL_OPENGL32);
  * ...
  * 
* From 89ee757950ed95e0727d5a15c32935eefbd42727 Mon Sep 17 00:00:00 2001 From: wil Date: Tue, 12 May 2026 16:57:27 -0600 Subject: [PATCH 3/5] fix: fix the canvas tearing problem with lwjglx. --- .../src/main/java/com/jme3/system/awt/AwtPanelsContext.java | 4 ++-- jme3-examples/src/main/java/jme3test/awt/TestCanvas.java | 2 +- jme3-examples/src/main/java/jme3test/awt/TestSafeCanvas.java | 2 ++ .../src/main/java/com/jme3/system/lwjgl/LwjglCanvas.java | 2 +- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/jme3-desktop/src/main/java/com/jme3/system/awt/AwtPanelsContext.java b/jme3-desktop/src/main/java/com/jme3/system/awt/AwtPanelsContext.java index d8da620bf2..cc512c2198 100644 --- a/jme3-desktop/src/main/java/com/jme3/system/awt/AwtPanelsContext.java +++ b/jme3-desktop/src/main/java/com/jme3/system/awt/AwtPanelsContext.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2023 jMonkeyEngine + * Copyright (c) 2009-2026 jMonkeyEngine * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -239,7 +239,7 @@ private void destroyInThread() { @Override public void setSettings(AppSettings settings) { this.settings.copyFrom(settings); - this.settings.setRenderer(AppSettings.LWJGL_OPENGL2); + this.settings.setRenderer(AppSettings.LWJGL_OPENGL32); if (actualContext != null) { actualContext.setSettings(settings); } diff --git a/jme3-examples/src/main/java/jme3test/awt/TestCanvas.java b/jme3-examples/src/main/java/jme3test/awt/TestCanvas.java index 189bf0b7ed..18aa0183ca 100644 --- a/jme3-examples/src/main/java/jme3test/awt/TestCanvas.java +++ b/jme3-examples/src/main/java/jme3test/awt/TestCanvas.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2021 jMonkeyEngine + * Copyright (c) 2009-2026 jMonkeyEngine * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/jme3-examples/src/main/java/jme3test/awt/TestSafeCanvas.java b/jme3-examples/src/main/java/jme3test/awt/TestSafeCanvas.java index 5c6940df31..135650f809 100644 --- a/jme3-examples/src/main/java/jme3test/awt/TestSafeCanvas.java +++ b/jme3-examples/src/main/java/jme3test/awt/TestSafeCanvas.java @@ -15,6 +15,8 @@ public class TestSafeCanvas extends SimpleApplication { public static void main(String[] args) throws InterruptedException{ AppSettings settings = new AppSettings(true); + settings.setX11PlatformPreferred(true); + settings.setRenderer(AppSettings.LWJGL_OPENGL32); settings.setWidth(640); settings.setHeight(480); 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 fa8af1178f..7e15db665e 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 @@ -1067,7 +1067,7 @@ public Canvas getCanvas() { public void setSettings(AppSettings settings) { if (settings.getRenderer().equals(AppSettings.ANGLE_GLES3)) { StringBuilder buffer = new StringBuilder(); - buffer.append("LWJGX is not compatible with ANGLE/SDL or GLES, as it only supports the following:") + buffer.append("LWJGLX is not compatible with ANGLE/SDL or GLES, as it only supports the following:") .append('\n').append(" * WGL | Windows") .append('\n').append(" * GLX | Linux (X11/XWayland)") .append('\n').append(" * CGL | MacOsX") From 5df5ffae576b158a3bb90a63af03aef430df8ce1 Mon Sep 17 00:00:00 2001 From: wil Date: Tue, 12 May 2026 16:59:00 -0600 Subject: [PATCH 4/5] fix: fix the canvas tearing problem with lwjglx. --- .../src/main/java/com/jme3/system/lwjgl/LwjglCanvas.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 7e15db665e..24a63523c4 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 @@ -74,10 +74,10 @@ import org.lwjgl.opengl.awt.GLData; import org.lwjgl.system.Configuration; +import org.lwjgl.system.Platform; import static org.lwjgl.system.MemoryUtil.*; import static com.jme3.system.lwjglx.LwjglxDefaultGLPlatform.*; -import org.lwjgl.system.Platform; /** * Class LwjglCanvas that integrates LWJGLX From 311a192de49233db2b85e696201c8700ff6e058f Mon Sep 17 00:00:00 2001 From: wil Date: Tue, 12 May 2026 18:28:44 -0600 Subject: [PATCH 5/5] fix: fix the canvas tearing problem with lwjglx --- .../src/main/java/com/jme3/system/lwjgl/LwjglCanvas.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 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 24a63523c4..ae0c544063 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 @@ -81,7 +81,10 @@ /** * Class LwjglCanvas that integrates LWJGLX - * which allows using AWT-Swing components. + * which allows using AWT-Swing components, make sure you use an OpenGL renderer: + *

+ * settings.setRenderer(AppSettings.LWJGL_OPENGL32);
+ * 
* *

* If LwjglCanvas throws an exception due to configuration problems, we can debug as follows: @@ -101,8 +104,7 @@ *


  * ....
  *  AppSettings settings = new AppSettings(true);
- *  settings.setGammaCorrection(true);
- *  settings.setRenderer(AppSettings.LWJGL_OPENGL32);
+ *  settings.setGammaCorrection(false);
  * ...
  * 
*