Add in a check to the splash screen. If the Display.update call takes

too long on average (over first 200 frames) we'll use a sleep based
timer to allow mods doing splash screen work some time on the
LWJGL global lock.

(cherry picked from commit 03d7eaa)
This commit is contained in:
cpw 2017-03-06 17:31:26 -05:00
parent 69b72201ac
commit cec90d7f48
6 changed files with 52 additions and 5 deletions

View File

@ -1098,4 +1098,10 @@ public class FMLClientHandler implements IFMLSidedHandler
{
return (CompoundDataFixer)this.client.getDataFixer();
}
@Override
public boolean isDisplayVSyncForced()
{
return SplashProgress.isDisplayVSyncForced;
}
}

View File

@ -115,6 +115,10 @@ public class SplashProgress
private static int memoryLowColor;
private static float memoryColorPercent;
private static long memoryColorChangeTime;
static boolean isDisplayVSyncForced = false;
private static final int TIMING_FRAME_COUNT = 200;
private static final int TIMING_FRAME_THRESHOLD = TIMING_FRAME_COUNT * 5 * 1000000; // 5 ms per frame, scaled to nanos
static final Semaphore mutex = new Semaphore(1);
private static String getString(String name, String def)
@ -254,7 +258,8 @@ public class SplashProgress
private final int barHeight = 20;
private final int textHeight2 = 20;
private final int barOffset = 55;
private long updateTiming;
private long framecount;
public void run()
{
setGL();
@ -266,6 +271,7 @@ public class SplashProgress
glDisable(GL_TEXTURE_2D);
while(!done)
{
framecount++;
ProgressBar first = null, penult = null, last = null;
Iterator<ProgressBar> i = ProgressManager.barIterator();
while(i.hasNext())
@ -371,16 +377,40 @@ public class SplashProgress
// is trying to impose a framerate or other thing is occurring. Without the mutex, the main
// thread would delay waiting for the same global display lock
mutex.acquireUninterruptibly();
long updateStart = System.nanoTime();
Display.update();
// As soon as we're done, we release the mutex. The other thread can now ping the processmessages
// call as often as it wants until we get get back here again
long dur = System.nanoTime() - updateStart;
if (framecount < TIMING_FRAME_COUNT) {
updateTiming += dur;
}
mutex.release();
if(pause)
{
clearGL();
setGL();
}
Display.sync(100);
// Such a hack - if the time taken is greater than 10 milliseconds, we're gonna guess that we're on a
// system where vsync is forced through the swapBuffers call - so we have to force a sleep and let the
// loading thread have a turn - some badly designed mods access Keyboard and therefore GlobalLock.lock
// during splash screen, and mutex against the above Display.update call as a result.
// 4 milliseconds is a guess - but it should be enough to trigger in most circumstances. (Maybe if
// 240FPS is possible, this won't fire?)
if (framecount >= TIMING_FRAME_COUNT && updateTiming > TIMING_FRAME_THRESHOLD) {
if (!isDisplayVSyncForced)
{
isDisplayVSyncForced = true;
FMLLog.log(Level.INFO, "Using alternative sync timing : %d frames of Display.update took %d nanos", TIMING_FRAME_COUNT, updateTiming);
}
try { Thread.sleep(16); } catch (InterruptedException ie) {}
} else
{
if (framecount ==TIMING_FRAME_COUNT) {
FMLLog.log(Level.INFO, "Using sync timing. %d frames of Display.update took %d nanos", TIMING_FRAME_COUNT, updateTiming);
}
Display.sync(100);
}
}
clearGL();
}
@ -464,7 +494,7 @@ public class SplashProgress
memoryColorChangeTime = time;
memoryColorPercent = usedMemoryPercent;
}
int memoryBarColor;
if (memoryColorPercent < 0.75f)
{

View File

@ -757,4 +757,6 @@ public class FMLCommonHandler
{
return (CompoundDataFixer)sidedDelegate.getDataFixer();
}
public boolean isDisplayVSyncForced() { return sidedDelegate.isDisplayVSyncForced(); }
}

View File

@ -80,4 +80,6 @@ public interface IFMLSidedHandler
void fireSidedRegistryEvents();
CompoundDataFixer getDataFixer();
boolean isDisplayVSyncForced();
}

View File

@ -32,7 +32,6 @@ import com.google.common.base.Joiner;
public class ProgressManager
{
private static final List<ProgressBar> bars = new CopyOnWriteArrayList<ProgressBar>();
/**
* Not a fully fleshed out API, may change in future MC versions.
* However feel free to use and suggest additions.
@ -57,7 +56,9 @@ public class ProgressManager
return bar;
}
public static boolean isDisplayVSyncForced() {
return FMLCommonHandler.instance().isDisplayVSyncForced();
}
/**
* Not a fully fleshed out API, may change in future MC versions.
* However feel free to use and suggest additions.

View File

@ -349,4 +349,10 @@ public class FMLServerHandler implements IFMLSidedHandler
{
return (CompoundDataFixer)this.server.getDataFixer();
}
@Override
public boolean isDisplayVSyncForced()
{
return false;
}
}