Merge branch 'HD-Mode_Fix_Windows' into 'master'

These changes fix the HD-Mode lag and crashes that happen when the client is...

See merge request 2009scape/rt4-client!33
This commit is contained in:
Ceikry 2026-03-14 17:00:38 +00:00
commit a7c7dea3c7
4 changed files with 55 additions and 15 deletions

View file

@ -14,7 +14,7 @@ public final class DisplayMode {
@OriginalMember(owner = "client!ib", name = "i", descriptor = "[Lclient!od;") @OriginalMember(owner = "client!ib", name = "i", descriptor = "[Lclient!od;")
public static DisplayMode[] aClass114Array1; public static DisplayMode[] aClass114Array1;
@OriginalMember(owner = "client!rc", name = "M", descriptor = "Z") @OriginalMember(owner = "client!rc", name = "M", descriptor = "Z")
public static boolean aBoolean73 = false; public static boolean start_GLRenderer = false;
@OriginalMember(owner = "client!jk", name = "y", descriptor = "Z") @OriginalMember(owner = "client!jk", name = "y", descriptor = "Z")
public static boolean resizable = false; public static boolean resizable = false;
@OriginalMember(owner = "client!hi", name = "f", descriptor = "J") @OriginalMember(owner = "client!hi", name = "f", descriptor = "J")
@ -94,6 +94,10 @@ public final class DisplayMode {
Preferences.write(GameShell.signLink); Preferences.write(GameShell.signLink);
} }
} }
/**
* If somehow the above code block fails to produce a frame for Fullscreen then this block is a safeguard
* to fall back to Standard Mode.
*/
if (newMode == 3 && GameShell.fullScreenFrame == null) { if (newMode == 3 && GameShell.fullScreenFrame == null) {
setWindowMode(true, Preferences.favoriteWorlds, true, currentMode, -1, -1); setWindowMode(true, Preferences.favoriteWorlds, true, currentMode, -1, -1);
return; return;
@ -125,6 +129,11 @@ public final class DisplayMode {
GameShell.canvasWidth = 765; GameShell.canvasWidth = 765;
GameShell.canvasHeight = 503; GameShell.canvasHeight = 503;
} }
/**
* This code bock executes for Fullscreen mode and removes current canvas in main frame window
* with a new canvas for the fullscreen frame window. Else if no canvas is replaced then just makes
* size adjustments to current canvas.
*/
if (replaceCanvas) { if (replaceCanvas) {
Keyboard.stop(GameShell.canvas); Keyboard.stop(GameShell.canvas);
Mouse.stop(GameShell.canvas); Mouse.stop(GameShell.canvas);
@ -149,12 +158,18 @@ public final class DisplayMode {
GameShell.canvas.setLocation(GameShell.leftMargin, GameShell.topMargin); GameShell.canvas.setLocation(GameShell.leftMargin, GameShell.topMargin);
} }
} }
/**
* newMode 0 is no mode, so this would be a reset of the canvas and glrenderer
*/
if (newMode == 0 && currentMode > 0) { if (newMode == 0 && currentMode > 0) {
GlRenderer.createAndDestroyContext(GameShell.canvas); GlRenderer.createAndDestroyContext(GameShell.canvas);
} }
/**
* This Code block starts on mode 1=HD,2=HDResize,3=Fullscreen. It also Starts the GLrenderer.
*/
if (useHD && newMode > 0) { if (useHD && newMode > 0) {
GameShell.canvas.setIgnoreRepaint(true); GameShell.canvas.setIgnoreRepaint(true);
if (!aBoolean73) { if (!start_GLRenderer) {
SceneGraph.clear(); SceneGraph.clear();
SoftwareRaster.frameBuffer = null; SoftwareRaster.frameBuffer = null;
SoftwareRaster.frameBuffer = FrameBuffer.create(GameShell.canvasHeight, GameShell.canvasWidth, GameShell.canvas); SoftwareRaster.frameBuffer = FrameBuffer.create(GameShell.canvasHeight, GameShell.canvasWidth, GameShell.canvas);
@ -169,7 +184,7 @@ public final class DisplayMode {
SoftwareRaster.frameBuffer.draw(graphics); SoftwareRaster.frameBuffer.draw(graphics);
} catch (@Pc(277) Exception local277) { } catch (@Pc(277) Exception local277) {
} }
GameShell.method2704(); GameShell.method2704(); // Creates a black background for SD Mode window, gameplay frame will render on top of.
if (currentMode == 0) { if (currentMode == 0) {
if(resizableSD) if(resizableSD)
SoftwareRaster.frameBuffer = FrameBuffer.create(GameShell.frameHeight, GameShell.frameWidth, GameShell.canvas); SoftwareRaster.frameBuffer = FrameBuffer.create(GameShell.frameHeight, GameShell.frameWidth, GameShell.canvas);
@ -178,22 +193,40 @@ public final class DisplayMode {
} else { } else {
SoftwareRaster.frameBuffer = null; SoftwareRaster.frameBuffer = null;
} }
@Pc(300) PrivilegedRequest local300 = GameShell.signLink.loadGlNatives(client.instance.getClass());
while (local300.status == 0) { /**
ThreadUtils.sleep(100L); * Code below tries to trigger GLProfile.initSingleton() through a queue in PrivilegedRequest where it waits
} * for its turn. This along with the while loop waits long enough to cause a de-sync in the start process which causes
if (local300.status == 1) { * lag and delay when switching to HD Mode and when launching the client in HD Mode.
aBoolean73 = true; * GLProfile.initSingleton() is automatically run starting with jogl 2.0 and later. So no need to execute it.
} * After it returns status code 1, it also sets an important variable aBoolean73(Start_Renderer) to true.
* This triggers the needed GLRenderer.init() function which we can control to be true manually as intended.
**/
/**
@Pc(300) PrivilegedRequest local300 = GameShell.signLink.loadGlNatives(client.instance.getClass());
while (local300.status == 0) {
ThreadUtils.sleep(100L);
}
if (local300.status == 1) {
aBoolean73 = true;
}
*/
start_GLRenderer = true; // Manually set here to allow GLRenderer.init() to execute.
} }
if (aBoolean73) { if (start_GLRenderer) {
GlRenderer.init(GameShell.canvas, Preferences.antiAliasingMode * 2); GlRenderer.init(GameShell.canvas, Preferences.antiAliasingMode * 2);
} }
} }
// If HD Mode fails, this restarts the whole process to enter into SD Mode
if (!GlRenderer.enabled && newMode > 0) { if (!GlRenderer.enabled && newMode > 0) {
setWindowMode(true, 0, true, currentMode, -1, -1); setWindowMode(true, 0, true, currentMode, -1, -1);
return; return;
} }
/**
* Executes once when the client is launched. Doesn't need to be executed more than that.
*/
if (newMode > 0 && currentMode == 0) { if (newMode > 0 && currentMode == 0) {
GameShell.thread.setPriority(5); GameShell.thread.setPriority(5);
SoftwareRaster.frameBuffer = null; SoftwareRaster.frameBuffer = null;
@ -203,7 +236,7 @@ public final class DisplayMode {
Rasteriser.setBrightness(0.7F); Rasteriser.setBrightness(0.7F);
} }
LoginManager.method4637(); LoginManager.method4637();
} else if (newMode == 0 && currentMode > 0) { } else if (newMode == 0 && currentMode > 0) { // This is when client switches from any other mode to SD Mode
GameShell.thread.setPriority(1); GameShell.thread.setPriority(1);
if(resizableSD) if(resizableSD)
SoftwareRaster.frameBuffer = FrameBuffer.create(GameShell.frameHeight, GameShell.frameWidth, GameShell.canvas); SoftwareRaster.frameBuffer = FrameBuffer.create(GameShell.frameHeight, GameShell.frameWidth, GameShell.canvas);
@ -233,7 +266,7 @@ public final class DisplayMode {
if (useHD) { if (useHD) {
client.method2721(); client.method2721();
} }
resizable = newMode >= 2; resizable = newMode == 2; // resizeable should only be done in HD-Resizeable mode and not full screen mode.
if (InterfaceList.topLevelInterface != -1) { if (InterfaceList.topLevelInterface != -1) {
InterfaceList.method3712(true); InterfaceList.method3712(true);
} }

View file

@ -4668,6 +4668,7 @@ public final class ScriptRunner {
if (int1 < 0 || int1 > 2) { if (int1 < 0 || int1 > 2) {
int1 = 0; int1 = 0;
} }
// Gets called on every mode change.
DisplayMode.setWindowMode(false, int1, -1, -1); DisplayMode.setWindowMode(false, int1, -1, -1);
continue; continue;
} }

View file

@ -840,6 +840,12 @@ public final class client extends GameShell {
DisplayMode.aLong89 = MonotonicClock.currentTimeMillis() + 500L; DisplayMode.aLong89 = MonotonicClock.currentTimeMillis() + 500L;
} }
} }
/**
* If the game is running in fullscreen mode and focus is lost, by alt tab or ctrl alt tab, the client exits
* fullscreen mode and enters window mode.
* This line can also be used to launch back into full screen when out of focus and refocused by sending mode 3
* with the right width and height, by Preference.width and Preference.height for exmaple.
*/
if (GameShell.fullScreenFrame != null && !GameShell.focus && (gameState == 30 || gameState == 10)) { if (GameShell.fullScreenFrame != null && !GameShell.focus && (gameState == 30 || gameState == 10)) {
DisplayMode.setWindowMode(false, Preferences.favoriteWorlds, -1, -1); DisplayMode.setWindowMode(false, Preferences.favoriteWorlds, -1, -1);
} }
@ -849,7 +855,7 @@ public final class client extends GameShell {
GameShell.fullRedraw = false; GameShell.fullRedraw = false;
} }
if (local158) { if (local158) {
GameShell.method2704(); GameShell.method2704(); // Creates a black background for SD Mode gameplay frame to render on top of.
} }
if (GlRenderer.enabled) { if (GlRenderer.enabled) {
for (local80 = 0; local80 < 100; local80++) { for (local80 = 0; local80 < 100; local80++) {

View file

@ -410,7 +410,7 @@ public final class SignLink implements Runnable {
} }
request.result = ((Class) args[0]).getDeclaredField((String) args[1]); request.result = ((Class) args[0]).getDeclaredField((String) args[1]);
} else if (type == 10) { } else if (type == 10) {
GLProfile.initSingleton(); //GLProfile.initSingleton(); //this is no longer necessary with jogl versions 2.0+.
} else if (type == 11) { } else if (type == 11) {
GLProfile.shutdown(); GLProfile.shutdown();
} else if (type == 12) { } else if (type == 12) {