From 7e9a1e7c135761837cfa26f793664d3d5aff2bcb Mon Sep 17 00:00:00 2001 From: Andrew S Date: Sat, 25 Dec 2021 20:01:48 -0500 Subject: [PATCH] Fix Render GUI on Retina Screens (fixes #338) window.getFramebufferWidth/Height() should be used instead of window.getWidth/Height() Co-authored-by: Jonas Herzig --- .../render/mixin/MainWindowAccessor.java | 9 ++++ .../render/rendering/VideoRenderer.java | 47 +++++++++++++------ .../com/replaymod/core/versions/Window.java | 5 ++ .../render/mixin/MainWindowAccessor.java | 3 ++ 4 files changed, 50 insertions(+), 14 deletions(-) diff --git a/src/main/java/com/replaymod/render/mixin/MainWindowAccessor.java b/src/main/java/com/replaymod/render/mixin/MainWindowAccessor.java index 335c9908..a54dd178 100644 --- a/src/main/java/com/replaymod/render/mixin/MainWindowAccessor.java +++ b/src/main/java/com/replaymod/render/mixin/MainWindowAccessor.java @@ -3,6 +3,7 @@ package com.replaymod.render.mixin; import net.minecraft.client.util.Window; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; +import org.spongepowered.asm.mixin.gen.Invoker; @Mixin(Window.class) public interface MainWindowAccessor { @@ -14,4 +15,12 @@ public interface MainWindowAccessor { int getFramebufferHeight(); @Accessor void setFramebufferHeight(int value); + // FIXME preprocessor should be able to infer this mapping + // FIXME preprocessor should be able to remap this one when the mapping is given manually + //#if MC>=11500 + @Invoker + //#else + //$$ @Invoker("method_4483") + //#endif + void invokeUpdateFramebufferSize(); } diff --git a/src/main/java/com/replaymod/render/rendering/VideoRenderer.java b/src/main/java/com/replaymod/render/rendering/VideoRenderer.java index dfa7e096..9eb819d5 100644 --- a/src/main/java/com/replaymod/render/rendering/VideoRenderer.java +++ b/src/main/java/com/replaymod/render/rendering/VideoRenderer.java @@ -120,6 +120,7 @@ public class VideoRenderer implements RenderInfo { private Framebuffer guiFramebuffer; private int displayWidth, displayHeight; + private int framebufferWidth, framebufferHeight; public VideoRenderer(RenderSettings settings, ReplayHandler replayHandler, Timeline timeline) throws IOException { this.settings = settings; @@ -245,10 +246,10 @@ public class VideoRenderer implements RenderInfo { public float updateForNextFrame() { // because the jGui lib uses Minecraft's displayWidth and displayHeight values, update these temporarily MainWindowAccessor acc = (MainWindowAccessor) (Object) mc.getWindow(); - int displayWidthBefore = acc.getFramebufferWidth(); - int displayHeightBefore = acc.getFramebufferHeight(); - acc.setFramebufferWidth(displayWidth); - acc.setFramebufferHeight(displayHeight); + int framebufferWidthBefore = acc.getFramebufferWidth(); + int framebufferHeightBefore = acc.getFramebufferHeight(); + acc.setFramebufferWidth(framebufferWidth); + acc.setFramebufferHeight(framebufferHeight); if (!settings.isHighPerformance() || framesDone % fps == 0) { while (drawGui() && paused) { @@ -289,8 +290,8 @@ public class VideoRenderer implements RenderInfo { } // change Minecraft's display size back - acc.setFramebufferWidth(displayWidthBefore); - acc.setFramebufferHeight(displayHeightBefore); + acc.setFramebufferWidth(framebufferWidthBefore); + acc.setFramebufferHeight(framebufferHeightBefore); if (cameraPathExporter != null) { cameraPathExporter.recordFrame(timer.tickDelta); @@ -362,6 +363,7 @@ public class VideoRenderer implements RenderInfo { } updateDisplaySize(); + updateFramebufferSize(); gui.toMinecraft().init(mc, mc.getWindow().getScaledWidth(), mc.getWindow().getScaledHeight()); @@ -369,9 +371,9 @@ public class VideoRenderer implements RenderInfo { // Set up our own framebuffer to render the GUI to //#if MC>=11700 - //$$ guiFramebuffer = new WindowFramebuffer(displayWidth, displayHeight); + //$$ guiFramebuffer = new WindowFramebuffer(framebufferWidth, framebufferHeight); //#else - guiFramebuffer = new Framebuffer(displayWidth, displayHeight, true + guiFramebuffer = new Framebuffer(framebufferWidth, framebufferHeight, true //#if MC>=11400 , false //#endif @@ -425,7 +427,7 @@ public class VideoRenderer implements RenderInfo { } // Finally, resize the Minecraft framebuffer to the actual width/height of the window - resizeMainWindow(mc, displayWidth, displayHeight); + resizeMainWindow(mc, framebufferWidth, framebufferHeight); } private void executeTaskQueue() { @@ -483,17 +485,23 @@ public class VideoRenderer implements RenderInfo { return false; } - // Resize the GUI framebuffer if the display size changed + // Check if display size has changes and force recalculate GUI framebuffer size. if (displaySizeChanged()) { updateDisplaySize(); + ((MainWindowAccessor) (Object) window).invokeUpdateFramebufferSize(); + } + + // Resize the GUI framebuffer if the display size changed + if (framebufferSizeChanged()) { + updateFramebufferSize(); //#if MC>=11400 - guiFramebuffer.resize(displayWidth, displayHeight + guiFramebuffer.resize(framebufferWidth, framebufferHeight //#if MC>=11400 , false //#endif ); //#else - //$$ guiFramebuffer.createBindFramebuffer(mc.displayWidth, mc.displayHeight); + //$$ guiFramebuffer.createBindFramebuffer(framebufferWidth, framebufferHeight); //#endif } @@ -594,7 +602,7 @@ public class VideoRenderer implements RenderInfo { guiFramebuffer.endWrite(); popMatrix(); pushMatrix(); - guiFramebuffer.draw(displayWidth, displayHeight); + guiFramebuffer.draw(framebufferWidth, framebufferHeight); popMatrix(); //#if MC>=11500 @@ -633,12 +641,18 @@ public class VideoRenderer implements RenderInfo { private boolean displaySizeChanged() { int realWidth = mc.getWindow().getWidth(); int realHeight = mc.getWindow().getHeight(); + return displayWidth != realWidth || displayHeight != realHeight; + } + + private boolean framebufferSizeChanged() { + int realWidth = mc.getWindow().getFramebufferWidth(); + int realHeight = mc.getWindow().getFramebufferHeight(); if (realWidth == 0 || realHeight == 0) { // These can be zero on Windows if minimized. // Creating zero-sized framebuffers however will throw an error, so we never want to switch to zero values. return false; } - return displayWidth != realWidth || displayHeight != realHeight; + return framebufferWidth != realWidth || framebufferHeight != realHeight; } private void updateDisplaySize() { @@ -646,6 +660,11 @@ public class VideoRenderer implements RenderInfo { displayHeight = mc.getWindow().getHeight(); } + private void updateFramebufferSize() { + framebufferWidth = mc.getWindow().getFramebufferWidth(); + framebufferHeight = mc.getWindow().getFramebufferHeight(); + } + public int getFramesDone() { return framesDone; } diff --git a/versions/1.12.2/src/main/java/com/replaymod/core/versions/Window.java b/versions/1.12.2/src/main/java/com/replaymod/core/versions/Window.java index fdcadef3..26d697d2 100644 --- a/versions/1.12.2/src/main/java/com/replaymod/core/versions/Window.java +++ b/versions/1.12.2/src/main/java/com/replaymod/core/versions/Window.java @@ -34,6 +34,11 @@ public class Window implements MainWindowAccessor { mc.displayHeight = value; } + @Override + public void invokeUpdateFramebufferSize() { + // no-op, pre-LWJGL3 MC doesn't differentiate between window and framebuffer size + } + public long getHandle() { return 0; } diff --git a/versions/1.12.2/src/main/java/com/replaymod/render/mixin/MainWindowAccessor.java b/versions/1.12.2/src/main/java/com/replaymod/render/mixin/MainWindowAccessor.java index 2d91cb58..a6166095 100644 --- a/versions/1.12.2/src/main/java/com/replaymod/render/mixin/MainWindowAccessor.java +++ b/versions/1.12.2/src/main/java/com/replaymod/render/mixin/MainWindowAccessor.java @@ -3,6 +3,7 @@ package com.replaymod.render.mixin; import net.minecraft.client.Minecraft; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Accessor; +import org.spongepowered.asm.mixin.gen.Invoker; @Mixin(Minecraft.class) public interface MainWindowAccessor { @@ -14,4 +15,6 @@ public interface MainWindowAccessor { int getFramebufferHeight(); @Accessor("displayHeight") void setFramebufferHeight(int value); + @Invoker + void invokeUpdateFramebufferSize(); }