Add mechanic for ImmediateWindowProviders to react to Graphics backed settings

Disable early loading screen when using Vulkan. Fixes #10829
This commit is contained in:
LexManos 2026-06-30 15:57:35 -07:00
parent 72be0c9ccd
commit c5d015e60a
No known key found for this signature in database
GPG key ID: 6E90061A7AE1F652
3 changed files with 86 additions and 2 deletions

View file

@ -113,6 +113,14 @@ public class DisplayWindow implements ImmediateWindowProvider {
return "fmlearlywindow";
}
@Override
public ImmediateWindowProvider selectBackend(String backend) {
// We only support opengl
if ("default".equals(backend) || "opengl".equals(backend))
return this;
return ImmediateWindowProvider.getFallbackHandler();
}
@Override
public Runnable initialize(String[] arguments) {
String mcVersion = FMLLoader.versionInfo().mcVersion();
@ -137,7 +145,7 @@ public class DisplayWindow implements ImmediateWindowProvider {
this.colourScheme = ColourScheme.BLACK;
} else {
try {
// check the options file for the colour scheme
// check the options file for the color scheme
var optionLines = Files.readAllLines(FMLPaths.GAMEDIR.get().resolve(Path.of("options.txt")));
var keyName = "darkMojangStudiosBackground:";
for (String line : optionLines) {

View file

@ -10,8 +10,13 @@ import net.minecraftforge.fml.loading.progress.StartupNotificationManager;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import joptsimple.OptionParser;
import java.io.IOException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.*;
import java.util.function.*;
import java.util.stream.Collectors;
@ -41,16 +46,62 @@ public class ImmediateWindowHandler {
if (provider == null) {
LOGGER.info("Failed to find ImmediateWindowProvider {}, disabling", providername);
provider = new DummyProvider();
} else {
var backend = findBackend(arguments);
var newProvider = provider.selectBackend(backend);
if (provider != newProvider) {
if (newProvider == null)
newProvider = new DummyProvider();
LOGGER.info("ImmediateWindowProvider {} does not support {}, switching to {}", provider.name(), backend, newProvider.name());
provider = newProvider;
}
}
}
// Only update config if the provider isn't the dummy provider
if (!Objects.equals(provider.name(), "dummyprovider"))
FMLConfig.updateConfig(FMLConfig.ConfigValue.EARLY_WINDOW_PROVIDER, provider.name());
FMLLoader.progressWindowTick = provider.initialize(arguments);
earlyProgress = StartupNotificationManager.addProgressBar("EARLY", 0);
earlyProgress.label("Bootstrapping Minecraft");
}
private static String findBackend(String[] arguments) {
// Try and parse from the command line arguments
var parser = new OptionParser();
var backendOption = parser.accepts("graphicsBackend").withRequiredArg();
parser.allowsUnrecognizedOptions();
var parsed = parser.parse(arguments);
if (parsed.has(backendOption))
return parsed.valueOf(backendOption).toLowerCase(Locale.ENGLISH);
// Read the options.txt if it exists.
var optionsFile = FMLPaths.GAMEDIR.get().resolve(Path.of("options.txt"));
if (!Files.exists(optionsFile)) // Default is OpenGL first
return "default";
List<String> lines = null;
try {
lines = Files.readAllLines(optionsFile);
} catch (IOException e) {
return "default"; // We failed to read for some reason, assume we're using the default.
}
final String key = "preferredGraphicsBackend:";
for (var line : lines) {
if (line.startsWith(key)) {
var backend = line.substring(key.length() + 1, line.length() - 1);
return backend.toLowerCase(Locale.ENGLISH);
}
}
return "default";
}
public static long setupMinecraftWindow(final int width, final int height, final String title, final long monitor, final Supplier<Object> backend) {
return provider.setupMinecraftWindow(width, height, title, monitor, backend);
}
@ -83,7 +134,7 @@ public class ImmediateWindowHandler {
earlyProgress.label(message);
}
private record DummyProvider() implements ImmediateWindowProvider {
record DummyProvider() implements ImmediateWindowProvider {
private static Method NV_HANDOFF;
private static Method NV_POSITION;
private static Method NV_OVERLAY;

View file

@ -24,11 +24,36 @@ import java.util.function.Supplier;
* No doubt many more things can be said here.
*/
public interface ImmediateWindowProvider {
/**
* Returns a new instance of ImmediateWindowProvider which just bounces to the vanilla code.
* This can be useful when you want to disable your provider and defer to vanilla behavior for some reason.
*/
public static ImmediateWindowProvider getFallbackHandler() {
return new ImmediateWindowHandler.DummyProvider();
}
/**
* @return The name of this window provider. Do NOT use fmlearlywindow.
*/
String name();
/**
* This is called before initialize, but after reading the preferred graphics backend config value from the user's
* options.txt or command line.
*
* If you do not support the requested backend, you can return a new ImmediateWindowProvider that does.
* {@link #getFallbackHandler()} can be used to get an instance that falls back to Vanilla's code effectively
* disabling the early loading screen.
*
* @param backend - The backend the user has selected, known values: "default", "opengl", and "vulkan". However this
* is read from the config file, or command line arguments so could be anything.
* Default and OpenGL are treated the same, attempting to load OpenGL first, then Vulkan.
* Vulkan attempts to load Vulkan first then OpenGL
*/
default ImmediateWindowProvider selectBackend(String backend) {
return this;
}
/**
* This is called very early on to initialize ourselves. Use this to initialize the window and other GL core resources.
*