Skip to content

Commit 4e80c9b

Browse files
authored
Fix #1890 (crashes attempting to run example apps in fullscreen with LWJGL v2) (#1898)
* jme3-lwjgl:fallback to standard 60Hz fullscreen display mode if the specified frequency in the AppSettings is not available and log a warning. * Fallback to whatever bps or frequency is available. Added a wild-card value to let selecting any bps or frequency available by passing -1. * Support AWT display frequency model. Looks like AWT uses mathematics round to convert float frequency values to int while lwjgl 2 uses mathematics floor. For example if frequency is 59.83, AWT will return 60 but lwjgl 2 will return 59. * Remove redundant check. * Added documentation for getFullscreenDisplayMode method.
1 parent 3e1b823 commit 4e80c9b

File tree

1 file changed

+31
-8
lines changed

1 file changed

+31
-8
lines changed

jme3-lwjgl/src/main/java/com/jme3/system/lwjgl/LwjglDisplay.java

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2009-2021 jMonkeyEngine
2+
* Copyright (c) 2009-2023 jMonkeyEngine
33
* All rights reserved.
44
*
55
* Redistribution and use in source and binary forms, with or without
@@ -37,6 +37,9 @@
3737
import java.awt.Graphics2D;
3838
import java.awt.image.BufferedImage;
3939
import java.nio.ByteBuffer;
40+
import java.util.ArrayList;
41+
import java.util.Arrays;
42+
import java.util.List;
4043
import java.util.concurrent.atomic.AtomicBoolean;
4144
import java.util.logging.Level;
4245
import java.util.logging.Logger;
@@ -50,14 +53,28 @@ public class LwjglDisplay extends LwjglAbstractDisplay {
5053
private final AtomicBoolean needRestart = new AtomicBoolean(false);
5154
private PixelFormat pixelFormat;
5255

56+
/**
57+
* @param width The required display width
58+
* @param height The required display height
59+
* @param bpp The required bits per pixel. If -1 is passed it will return
60+
* whatever bpp is found
61+
* @param freq The required frequency, if -1 is passed it will return
62+
* whatever frequency is found
63+
* @return The {@link DisplayMode} matches with specified settings or
64+
* return null if no matching display mode is found
65+
*/
5366
protected DisplayMode getFullscreenDisplayMode(int width, int height, int bpp, int freq){
5467
try {
5568
DisplayMode[] modes = Display.getAvailableDisplayModes();
5669
for (DisplayMode mode : modes) {
5770
if (mode.getWidth() == width
5871
&& mode.getHeight() == height
59-
&& (mode.getBitsPerPixel() == bpp || (bpp == 24 && mode.getBitsPerPixel() == 32))
60-
&& (mode.getFrequency() == freq || (freq == 60 && mode.getFrequency() == 59))) {
72+
&& (mode.getBitsPerPixel() == bpp || (bpp == 24 && mode.getBitsPerPixel() == 32) || bpp == -1)
73+
// Looks like AWT uses mathematical round to convert floating point
74+
// frequency values to int while lwjgl 2 uses mathematical floor.
75+
// For example if frequency is 59.83, AWT will return 60 but lwjgl2
76+
// will return 59. This is what I observed on Linux. - Ali-RS 2023-1-10
77+
&& (Math.abs(mode.getFrequency() - freq) <= 1 || freq == -1)) {
6178
return mode;
6279
}
6380
}
@@ -70,16 +87,22 @@ protected DisplayMode getFullscreenDisplayMode(int width, int height, int bpp, i
7087
@Override
7188
protected void createContext(AppSettings settings) throws LWJGLException{
7289
DisplayMode displayMode;
73-
if (settings.getWidth() <= 0 || settings.getHeight() <= 0){
90+
if (settings.getWidth() <= 0 || settings.getHeight() <= 0) {
7491
displayMode = Display.getDesktopDisplayMode();
7592
settings.setResolution(displayMode.getWidth(), displayMode.getHeight());
76-
}else if (settings.isFullscreen()){
93+
} else if (settings.isFullscreen()) {
7794
displayMode = getFullscreenDisplayMode(settings.getWidth(), settings.getHeight(),
78-
settings.getBitsPerPixel(), settings.getFrequency());
95+
settings.getBitsPerPixel(), settings.getFrequency());
7996
if (displayMode == null) {
80-
throw new RuntimeException("Unable to find fullscreen display mode matching settings");
97+
// Fall back to whatever mode is available at the specified width & height
98+
displayMode = getFullscreenDisplayMode(settings.getWidth(), settings.getHeight(), -1, -1);
99+
if (displayMode == null) {
100+
throw new RuntimeException("Unable to find fullscreen display mode matching settings");
101+
} else {
102+
logger.log(Level.WARNING, "Unable to find fullscreen display mode matching settings, falling back to: {0}", displayMode);
103+
}
81104
}
82-
}else{
105+
} else {
83106
displayMode = new DisplayMode(settings.getWidth(), settings.getHeight());
84107
}
85108

0 commit comments

Comments
 (0)