Handle some Intel driver shenanigans (#1951)

This commit is contained in:
Jason Mitchell authored and GitHub committed 2026-07-21 08:05:46 -07:00
1 parent 10a5b550f2
commit 2db20ad866
4 files changed
+85 -4

No files matched your search

+1
View File
@@ -12,6 +12,7 @@ build/
/config/
/crash-reports/
/logs/
tmp/
options.txt
/saves/
usernamecache.json
@@ -146,6 +146,9 @@ public class RenderSystem {
coreProfile = true;
GLStateManager.LOGGER.info("GL 3.3 core profile detected, enabling FFP shader emulation.");
ShaderManager.getInstance().enable();
} else {
throw new IllegalStateException("Non-core GL context (profile mask 0x" + Integer.toHexString(profileMask)
+ "); FFP emulation requires a core profile and nothing would render. Context creation should have rejected this.");
}
}
@@ -549,7 +552,7 @@ public class RenderSystem {
}
}
/** Parse a GL version string (e.g. "4.6.0 NVIDIA ...") into concatenated digits "460". Inlined from StandardMacros.getGlVersion(). */
/** Parse a GL version string (e.g. "4.6.0 NVIDIA ...") into concatenated digits "460" */
static String parseGlVersionString(String info) {
final Matcher matcher = SEMVER_PATTERN.matcher(Objects.requireNonNull(info));
if (!matcher.matches()) {
@@ -561,4 +564,18 @@ public class RenderSystem {
if (bugfix == null || bugfix.isEmpty()) bugfix = "0";
return major + minor + bugfix;
}
/** Parse a GL version string into packed major*10+minor (e.g. "4.3.0 - Build ..." -> 43), or -1 if unparseable. */
public static int parseMajorMinor(String glVersion) {
if (glVersion == null) return -1;
final Matcher matcher = SEMVER_PATTERN.matcher(glVersion.trim());
if (!matcher.matches()) return -1;
return Integer.parseInt(matcher.group("major")) * 10 + Integer.parseInt(matcher.group("minor"));
}
public static boolean isContextValid(int requestedMajor, int requestedMinor, int actualVersion, boolean coreBitSet) {
if (!coreBitSet) return false;
if (actualVersion < 0) return true;
return actualVersion >= requestedMajor * 10 + requestedMinor;
}
}
@@ -0,0 +1,34 @@
package com.gtnewhorizons.angelica.glsm;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
class GLVersionParseTest {
@Test
void parseMajorMinor() {
assertEquals(43, RenderSystem.parseMajorMinor("4.3.0 - Build 20.19.15.4835"));
assertEquals(46, RenderSystem.parseMajorMinor("4.6.0 NVIDIA 551.61"));
assertEquals(41, RenderSystem.parseMajorMinor("4.1 Metal - 88"));
assertEquals(33, RenderSystem.parseMajorMinor("3.3"));
assertEquals(46, RenderSystem.parseMajorMinor("4.6 (Core Profile) Mesa 24.0.3"));
assertEquals(-1, RenderSystem.parseMajorMinor(null));
assertEquals(-1, RenderSystem.parseMajorMinor(""));
assertEquals(-1, RenderSystem.parseMajorMinor("garbage"));
assertEquals(-1, RenderSystem.parseMajorMinor("OpenGL ES 3.2"));
}
@Test
void isContextValid() {
assertTrue(RenderSystem.isContextValid(4, 4, 46, true));
assertTrue(RenderSystem.isContextValid(4, 4, 44, true));
assertFalse(RenderSystem.isContextValid(4, 4, 43, true));
assertFalse(RenderSystem.isContextValid(4, 4, 44, false));
assertTrue(RenderSystem.isContextValid(4, 4, -1, true));
assertFalse(RenderSystem.isContextValid(4, 4, -1, false));
assertTrue(RenderSystem.isContextValid(3, 3, 33, true));
}
}
@@ -3,6 +3,7 @@ package com.gtnewhorizons.angelica.mixins.early.angelica;
import com.gtnewhorizon.gtnhlib.config.ConfigurationManager;
import com.gtnewhorizons.angelica.AngelicaMod;
import com.gtnewhorizons.angelica.config.AngelicaConfig;
import com.gtnewhorizons.angelica.glsm.RenderSystem;
import com.gtnewhorizons.angelica.glsm.GLStateManager;
import net.minecraftforge.client.ForgeHooksClient;
import org.apache.logging.log4j.LogManager;
@@ -11,6 +12,7 @@ import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.ContextAttribs;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL32;
import org.lwjgl.opengl.PixelFormat;
import org.lwjgl.LWJGLUtil;
import org.spongepowered.asm.mixin.Mixin;
@@ -63,15 +65,22 @@ public abstract class MixinForgeHooksClient_CoreProfile {
final int platformMaxMinor = (LWJGLUtil.getPlatform() == LWJGLUtil.PLATFORM_MACOSX) ? 1 : 6;
final int platformMax = platformMaxMajor * 10 + platformMaxMinor;
int maxProbe = platformMax;
// Try pinned version first if configured
final int pinned = angelica$clampPinned(AngelicaConfig.pinnedGLVersion, platformMax);
if (pinned >= 33) {
final Exception e = angelica$tryCreate(attribs, format, setMajor, setMinor, pinned / 10, pinned % 10);
if (e == null) {
LOGGER.info("Created GL {}.{} core profile context (pinned)", pinned / 10, pinned % 10);
return;
final int cap = angelica$validateContext(pinned / 10, pinned % 10);
if (cap == 0) {
LOGGER.info("Created GL {}.{} core profile context (pinned)", pinned / 10, pinned % 10);
return;
}
maxProbe = Math.min(maxProbe, cap);
} else {
LOGGER.warn("Pinned GL version {}.{} failed, probing from highest", pinned / 10, pinned % 10);
}
LOGGER.warn("Pinned GL version {}.{} failed, probing from highest", pinned / 10, pinned % 10);
}
// Probe from highest to lowest
@@ -80,8 +89,14 @@ public abstract class MixinForgeHooksClient_CoreProfile {
final int maxMinor = (major == 4) ? platformMaxMinor : 3;
final int minMinor = (major == 3) ? 3 : 0;
for (int minor = maxMinor; minor >= minMinor; --minor) {
if (major * 10 + minor > maxProbe) continue;
final Exception e = angelica$tryCreate(attribs, format, setMajor, setMinor, major, minor);
if (e == null) {
final int cap = angelica$validateContext(major, minor);
if (cap != 0) {
maxProbe = Math.min(maxProbe, cap);
continue;
}
final int version = major * 10 + minor;
LOGGER.info("Created GL {}.{} core profile context", major, minor);
// Auto-pin if below platform max, or update a stale pin
@@ -127,6 +142,20 @@ public abstract class MixinForgeHooksClient_CoreProfile {
}
}
@Unique
private static int angelica$validateContext(int major, int minor) {
final String glVersion = GLStateManager.glGetString(GL11.GL_VERSION);
final int actual = RenderSystem.parseMajorMinor(glVersion);
final boolean core = (GLStateManager.glGetInteger(GL32.GL_CONTEXT_PROFILE_MASK) & GL32.GL_CONTEXT_CORE_PROFILE_BIT) != 0;
if (RenderSystem.isContextValid(major, minor, actual, core)) {
return 0;
}
LOGGER.warn("Requested GL {}.{} core context but driver returned \"{}\" (core profile: {}, GPU: {}); falling back to a lower version", major, minor, glVersion, core, GLStateManager.glGetString(GL11.GL_RENDERER));
try { Display.destroy(); } catch (Exception ignored) {}
final int requested = major * 10 + minor;
return (actual >= 0 && actual < requested) ? actual : requested - 1;
}
@Unique
private static void angelica$savePin(int version) {
AngelicaConfig.pinnedGLVersion = version;