From 6844d05480a2a35375bec4c9c640a85547b6a026 Mon Sep 17 00:00:00 2001 From: Saad Nadeem Date: Wed, 19 Aug 2026 16:48:13 -0400 Subject: [PATCH 1/4] fix(hud): prevent flicker when opening/closing OneConfig --- .../mixin/events/Mixin_HudRenderEvent.java | 1 + .../oneconfig/internal/ui/compose/SkiaCtx.kt | 29 +++++++++++++++++++ .../ui/compose/impls/OneConfigUIScreen.kt | 15 +++++++++- 3 files changed, 44 insertions(+), 1 deletion(-) diff --git a/minecraft/src/main/java/org/polyfrost/oneconfig/internal/mixin/events/Mixin_HudRenderEvent.java b/minecraft/src/main/java/org/polyfrost/oneconfig/internal/mixin/events/Mixin_HudRenderEvent.java index 0da7c4a85..48b91765f 100644 --- a/minecraft/src/main/java/org/polyfrost/oneconfig/internal/mixin/events/Mixin_HudRenderEvent.java +++ b/minecraft/src/main/java/org/polyfrost/oneconfig/internal/mixin/events/Mixin_HudRenderEvent.java @@ -26,6 +26,7 @@ public class Mixin_HudRenderEvent { @Inject(method = "extractRenderState", at = @At("TAIL")) private void renderHudCallback(GuiGraphicsExtractor ctx, DeltaTracker deltaTracker, CallbackInfo ci) { OneConfig.render(ctx, deltaTracker.getRealtimeDeltaTicks()); + //~ if < 1.21.8 '.suppressInGameHudRender' -> '.shouldSuppressInGameHudRender()' if (!SkiaCtx.INSTANCE.suppressInGameHudRender) { SkiaCtx.INSTANCE.blitHud(ctx); } diff --git a/minecraft/src/main/kotlin/org/polyfrost/oneconfig/internal/ui/compose/SkiaCtx.kt b/minecraft/src/main/kotlin/org/polyfrost/oneconfig/internal/ui/compose/SkiaCtx.kt index 680a3c9f1..a8e8bb31f 100644 --- a/minecraft/src/main/kotlin/org/polyfrost/oneconfig/internal/ui/compose/SkiaCtx.kt +++ b/minecraft/src/main/kotlin/org/polyfrost/oneconfig/internal/ui/compose/SkiaCtx.kt @@ -74,6 +74,9 @@ object SkiaCtx { private var hudRealIsGeneral = false private var composeRealIsGeneral = false + //? if < 1.21.8 + //private var clearComposeAfterDraw = false + @Volatile private var composeActive = false @Volatile @@ -82,6 +85,8 @@ object SkiaCtx { private var composeRender: (() -> Unit)? = null fun submitComposeFrame(dirty: Boolean, render: Runnable) { + //? if < 1.21.8 + //clearComposeAfterDraw = false composeActive = true if (dirty || composeRender == null) { composeRender = { render.run() } @@ -90,9 +95,17 @@ object SkiaCtx { } fun clearComposeFrame() { + //? if >= 1.21.8 { composeActive = false composeDirty = false composeRender = null + //?} else { + /*// Screen removal calls this before the frame's final Skia draw. + // Clearing immediately would leave that frame without a HUD. + // Keep the cached Compose surface for that draw so the HUD remains visible. + clearComposeAfterDraw = true + composeDirty = false + *///?} } //? >= 1.21.5 { @@ -329,6 +342,15 @@ object SkiaCtx { @JvmField var suppressInGameHudRender = false + //? if < 1.21.8 { + /*// The HUD pass runs before the Compose surface exists, so keep the HUD visible until then. + fun shouldSuppressInGameHudRender(): Boolean = suppressInGameHudRender && composeSurface != null + + fun prepareComposeSurface() { + if (this::directContext.isInitialized) resolveComposeSurface() + } + *///? } + fun blitHud(guiGraphics: GuiGraphicsExtractor) { val rt = hudTarget ?: return val w = rt.width @@ -504,6 +526,13 @@ object SkiaCtx { } } finally { currentSurface = null + //? if < 1.21.8 { + /*if (clearComposeAfterDraw) { + clearComposeAfterDraw = false + composeActive = false + composeRender = null + } + *///?} } } diff --git a/minecraft/src/main/kotlin/org/polyfrost/oneconfig/internal/ui/compose/impls/OneConfigUIScreen.kt b/minecraft/src/main/kotlin/org/polyfrost/oneconfig/internal/ui/compose/impls/OneConfigUIScreen.kt index bcac29862..f1b6400de 100644 --- a/minecraft/src/main/kotlin/org/polyfrost/oneconfig/internal/ui/compose/impls/OneConfigUIScreen.kt +++ b/minecraft/src/main/kotlin/org/polyfrost/oneconfig/internal/ui/compose/impls/OneConfigUIScreen.kt @@ -29,6 +29,7 @@ import org.polyfrost.oneconfig.internal.ui.shell.ShellState import org.polyfrost.oneconfig.internal.ui.sound.UiSoundEvent import org.polyfrost.oneconfig.internal.ui.sound.UiSounds import org.polyfrost.oneconfig.api.platform.v1.Platform +import org.polyfrost.oneconfig.internal.OneConfig import kotlin.math.pow class OneConfigUIScreen @JvmOverloads constructor( @@ -111,7 +112,7 @@ class OneConfigUIScreen @JvmOverloads constructor( } override fun init() { - org.polyfrost.oneconfig.internal.OneConfig.dismissFirstLaunchToast() + OneConfig.dismissFirstLaunchToast() ConfigRegistry.loadFrom(ConfigManager.active(), ConfigSource.OC) initialTree?.let { ConfigRegistry.registerTree(it, ConfigSource.OC) } @@ -163,6 +164,12 @@ class OneConfigUIScreen @JvmOverloads constructor( ShellState.versionLabel = "OneConfig" } + //? if < 1.21.8 { + /*// Compose normally creates its surface after the HUD pass. + // Create the surface now to avoid drawing the HUD twice. + SkiaCtx.prepareComposeSurface() + *///?} + SkiaCtx.suppressInGameHudRender = true HudManager.overrideShowInScreens = true HudManager.isConfigUiOpen = true @@ -257,6 +264,12 @@ class OneConfigUIScreen @JvmOverloads constructor( if (Platform.screen().current() !== this) return if (closeRequested && System.currentTimeMillis() - closeRequestedAt >= closeAnimationMs) { Platform.screen().close() + //? if >= 1.21.8 { + // This frame skipped normal HUD rendering because OneConfig was open. + // Closing removes the Compose copy as well, so add the normal HUD back. + OneConfig.render(ctx, tickDelta) + SkiaCtx.blitHud(ctx) + //?} return } if (client.level == null) { From f4e2c26d231f0b87fa026a1cc76d7c7a9839b72d Mon Sep 17 00:00:00 2001 From: Julian Chang Date: Thu, 20 Aug 2026 17:06:08 +0700 Subject: [PATCH 2/4] some fixes --- .../oneconfig/internal/OneConfig.java | 1 + .../oneconfig/internal/ui/compose/SkiaCtx.kt | 44 +++++++++++++++---- .../ui/compose/impls/OneConfigUIScreen.kt | 8 +++- 3 files changed, 43 insertions(+), 10 deletions(-) diff --git a/minecraft/src/main/java/org/polyfrost/oneconfig/internal/OneConfig.java b/minecraft/src/main/java/org/polyfrost/oneconfig/internal/OneConfig.java index 1aed22a26..657b96b87 100644 --- a/minecraft/src/main/java/org/polyfrost/oneconfig/internal/OneConfig.java +++ b/minecraft/src/main/java/org/polyfrost/oneconfig/internal/OneConfig.java @@ -183,6 +183,7 @@ public static void render(GuiGraphicsExtractor graphics, float partial) { HudManager.targetPixelWidth = Platform.screen().viewportWidth(); HudManager.targetPixelHeight = Platform.screen().viewportHeight(); + //~ if < 1.21.8 '.suppressInGameHudRender' -> '.shouldSuppressInGameHudRender()' if (!SkiaCtx.INSTANCE.suppressInGameHudRender) { LegacyHudRenderer.INSTANCE.renderLive(graphics); } diff --git a/minecraft/src/main/kotlin/org/polyfrost/oneconfig/internal/ui/compose/SkiaCtx.kt b/minecraft/src/main/kotlin/org/polyfrost/oneconfig/internal/ui/compose/SkiaCtx.kt index a8e8bb31f..239e78d74 100644 --- a/minecraft/src/main/kotlin/org/polyfrost/oneconfig/internal/ui/compose/SkiaCtx.kt +++ b/minecraft/src/main/kotlin/org/polyfrost/oneconfig/internal/ui/compose/SkiaCtx.kt @@ -74,8 +74,13 @@ object SkiaCtx { private var hudRealIsGeneral = false private var composeRealIsGeneral = false - //? if < 1.21.8 - //private var clearComposeAfterDraw = false + //? if < 1.21.8 { + /*@Volatile + private var clearComposeAfterDraw = false + + @Volatile + private var hudBlitSuppressed = false + *///? } @Volatile private var composeActive = false @@ -108,6 +113,21 @@ object SkiaCtx { *///?} } + //? if < 1.21.8 { + /*fun discardComposeFrame() { + clearComposeAfterDraw = false + composeActive = false + composeDirty = false + composeRender = null + } + + private fun finishComposeClear() { + clearComposeAfterDraw = false + composeActive = false + composeRender = null + } + *///? } + //? >= 1.21.5 { private val HUD_TEXTURE_LOC = Identifier.fromNamespaceAndPath("oneconfig", "hud_skia") private val COMPOSE_TEXTURE_LOC = Identifier.fromNamespaceAndPath("oneconfig", "compose_skia") @@ -344,10 +364,15 @@ object SkiaCtx { //? if < 1.21.8 { /*// The HUD pass runs before the Compose surface exists, so keep the HUD visible until then. - fun shouldSuppressInGameHudRender(): Boolean = suppressInGameHudRender && composeSurface != null + fun shouldSuppressInGameHudRender(): Boolean { + val suppress = suppressInGameHudRender && composeSurface != null + hudBlitSuppressed = suppress + return suppress + } fun prepareComposeSurface() { - if (this::directContext.isInitialized) resolveComposeSurface() + if (!isReady || currentSurface != null) return + resolveComposeSurface() } *///? } @@ -461,6 +486,11 @@ object SkiaCtx { fun draw() { if (!this::directContext.isInitialized) return + //? if < 1.21.8 { + /*val composeStandsInForHud = hudBlitSuppressed + hudBlitSuppressed = false + if (clearComposeAfterDraw && !composeStandsInForHud) finishComposeClear() + *///? } runWarmups() val draws = queuedDraws.toList() queuedDraws.clear() @@ -527,11 +557,7 @@ object SkiaCtx { } finally { currentSurface = null //? if < 1.21.8 { - /*if (clearComposeAfterDraw) { - clearComposeAfterDraw = false - composeActive = false - composeRender = null - } + /*if (clearComposeAfterDraw) finishComposeClear() *///?} } } diff --git a/minecraft/src/main/kotlin/org/polyfrost/oneconfig/internal/ui/compose/impls/OneConfigUIScreen.kt b/minecraft/src/main/kotlin/org/polyfrost/oneconfig/internal/ui/compose/impls/OneConfigUIScreen.kt index f1b6400de..5045879e5 100644 --- a/minecraft/src/main/kotlin/org/polyfrost/oneconfig/internal/ui/compose/impls/OneConfigUIScreen.kt +++ b/minecraft/src/main/kotlin/org/polyfrost/oneconfig/internal/ui/compose/impls/OneConfigUIScreen.kt @@ -269,7 +269,13 @@ class OneConfigUIScreen @JvmOverloads constructor( // Closing removes the Compose copy as well, so add the normal HUD back. OneConfig.render(ctx, tickDelta) SkiaCtx.blitHud(ctx) - //?} + //?} else { + /*if (closeAnimationMs <= 0L) { + SkiaCtx.discardComposeFrame() + OneConfig.render(ctx, tickDelta) + SkiaCtx.blitHud(ctx) + } + *///?} return } if (client.level == null) { From 332d47391fb27ff02f44b7c3d0c3b5ed760cd966 Mon Sep 17 00:00:00 2001 From: Saad Nadeem Date: Wed, 19 Aug 2026 20:33:51 -0400 Subject: [PATCH 3/4] fix(hud): offscreen legacy HUD rendering across 1.21 --- .../oneconfig/internal/OneConfig.java | 7 +- .../internal/ui/SkiaOffscreenTarget.kt | 77 ++++++ .../internal/ui/hud/DebugOverlayOffscreen.kt | 96 +------ .../internal/ui/hud/LegacyHudOffscreen.kt | 243 +++++++++--------- 4 files changed, 221 insertions(+), 202 deletions(-) create mode 100644 minecraft/src/main/kotlin/org/polyfrost/oneconfig/internal/ui/SkiaOffscreenTarget.kt diff --git a/minecraft/src/main/java/org/polyfrost/oneconfig/internal/OneConfig.java b/minecraft/src/main/java/org/polyfrost/oneconfig/internal/OneConfig.java index 657b96b87..778618dfc 100644 --- a/minecraft/src/main/java/org/polyfrost/oneconfig/internal/OneConfig.java +++ b/minecraft/src/main/java/org/polyfrost/oneconfig/internal/OneConfig.java @@ -186,12 +186,9 @@ public static void render(GuiGraphicsExtractor graphics, float partial) { //~ if < 1.21.8 '.suppressInGameHudRender' -> '.shouldSuppressInGameHudRender()' if (!SkiaCtx.INSTANCE.suppressInGameHudRender) { LegacyHudRenderer.INSTANCE.renderLive(graphics); + } else { + org.polyfrost.oneconfig.internal.ui.hud.LegacyHudOffscreen.INSTANCE.render(); } - //? if >= 26.1 { - else org.polyfrost.oneconfig.internal.ui.hud.LegacyHudOffscreen.INSTANCE.render(); - //? } else { - /*else LegacyHudRenderer.INSTANCE.renderLive(graphics); - *///? } // records the F3 overlay offscreen so Skia can put it above the Compose UI instead of below the // blur and it must run every frame regardless of the HUD dirty gate org.polyfrost.oneconfig.internal.ui.hud.DebugOverlayOffscreen.INSTANCE.render(); diff --git a/minecraft/src/main/kotlin/org/polyfrost/oneconfig/internal/ui/SkiaOffscreenTarget.kt b/minecraft/src/main/kotlin/org/polyfrost/oneconfig/internal/ui/SkiaOffscreenTarget.kt new file mode 100644 index 000000000..15e65a29e --- /dev/null +++ b/minecraft/src/main/kotlin/org/polyfrost/oneconfig/internal/ui/SkiaOffscreenTarget.kt @@ -0,0 +1,77 @@ +package org.polyfrost.oneconfig.internal.ui + +import com.mojang.blaze3d.pipeline.RenderTarget +import com.mojang.blaze3d.pipeline.TextureTarget +import org.jetbrains.skia.BackendRenderTarget +import org.jetbrains.skia.ColorSpace +import org.jetbrains.skia.Surface +import org.jetbrains.skia.SurfaceOrigin +import org.polyfrost.oneconfig.internal.ui.compose.SkiaCtx +import org.slf4j.LoggerFactory + +/** Owns a Minecraft render target and its Skia surface, cached by size. */ +class SkiaOffscreenTarget { + private val LOG = LoggerFactory.getLogger("OneConfig/SkiaOffscreenTarget") + + var target: RenderTarget? = null + private set + private var brt: BackendRenderTarget? = null + var surface: Surface? = null + private set + private var lastW = -1 + private var lastH = -1 + + fun resolveTarget(w: Int, h: Int): Boolean { + if (target != null && lastW == w && lastH == h && surface != null) return true + destroy() + try { + //? if >= 26.2 { + val rt = TextureTarget(null, w, h, true, com.mojang.blaze3d.GpuFormat.RGBA8_UNORM) + //?} else if >= 1.21.5 { + /*val rt = TextureTarget(null, w, h, true) + *///?} else if >= 1.21.4 { + /*val rt = TextureTarget(w, h, true) + *///?} else { + /*val rt = TextureTarget(w, h, true, net.minecraft.client.Minecraft.ON_OSX) + *///?} + target = rt + //? if < 1.21.5 + /*rt.setClearColor(0f, 0f, 0f, 0f)*/ + val svc = SkiaCtx.vulkanService ?: return false + if (!SkiaCtx.isVulkanMode) { + //? if >= 1.21.5 { + val fboId = RenderTargetFbo.getFboId(rt) + //? } else + /*val fboId = rt.frameBufferId*/ + if (fboId <= 0) { + target = null + rt.destroyBuffers() + return false + } + } + val (b, colorFmt) = svc.makeOffscreenBRT(rt, w, h) + brt = b + val origin = if (SkiaCtx.isDeferredComposeBackend) SurfaceOrigin.TOP_LEFT else SurfaceOrigin.BOTTOM_LEFT + surface = Surface.makeFromBackendRenderTarget( + SkiaCtx.directContext, b, origin, colorFmt, ColorSpace.sRGB, null, + ) + if (surface == null) { + b.close(); brt = null + return false + } + lastW = w; lastH = h + return true + } catch (t: Throwable) { + LOG.warn("Failed to create offscreen target", t) + destroy() + return false + } + } + + fun destroy() { + surface?.close(); surface = null + brt?.close(); brt = null + target?.destroyBuffers(); target = null + lastW = -1; lastH = -1 + } +} diff --git a/minecraft/src/main/kotlin/org/polyfrost/oneconfig/internal/ui/hud/DebugOverlayOffscreen.kt b/minecraft/src/main/kotlin/org/polyfrost/oneconfig/internal/ui/hud/DebugOverlayOffscreen.kt index 5363fcb84..c8d773bcf 100644 --- a/minecraft/src/main/kotlin/org/polyfrost/oneconfig/internal/ui/hud/DebugOverlayOffscreen.kt +++ b/minecraft/src/main/kotlin/org/polyfrost/oneconfig/internal/ui/hud/DebugOverlayOffscreen.kt @@ -1,6 +1,6 @@ package org.polyfrost.oneconfig.internal.ui.hud -import com.mojang.blaze3d.pipeline.TextureTarget +import com.mojang.blaze3d.pipeline.RenderTarget import net.minecraft.client.Minecraft import net.minecraft.client.gui.GuiGraphicsExtractor //? if >= 26.1 { @@ -12,12 +12,9 @@ import org.polyfrost.oneconfig.internal.mixin.render.GuiRendererAccessor import org.polyfrost.oneconfig.internal.mixin.render.GameRendererAccessor import org.polyfrost.oneconfig.internal.mixin.render.GuiRendererAccessor *///? } -import org.jetbrains.skia.BackendRenderTarget -import org.jetbrains.skia.ColorSpace import org.jetbrains.skia.Paint -import org.jetbrains.skia.Surface -import org.jetbrains.skia.SurfaceOrigin import org.polyfrost.oneconfig.api.platform.v1.Platform +import org.polyfrost.oneconfig.internal.ui.SkiaOffscreenTarget import org.polyfrost.oneconfig.internal.ui.compose.ComposeScreen import org.polyfrost.oneconfig.internal.ui.compose.SkiaCtx import org.slf4j.LoggerFactory @@ -33,11 +30,7 @@ object DebugOverlayOffscreen { private val LOG = LoggerFactory.getLogger("OneConfig/DebugOverlayOffscreen") private val client get() = Minecraft.getInstance() - private var target: TextureTarget? = null - private var brt: BackendRenderTarget? = null - private var surface: Surface? = null - private var lastW = -1 - private var lastH = -1 + private val offscreen = SkiaOffscreenTarget() @Volatile private var hasContent = false @Volatile private var failed = false @@ -67,8 +60,8 @@ object DebugOverlayOffscreen { if (w <= 0 || h <= 0) return try { - if (!resolveTarget(w, h)) return - val rt = target ?: return + if (!offscreen.resolveTarget(w, h)) return + val rt = offscreen.target ?: return //? if >= 1.21.8 { renderRecorded(rt) //? } else if >= 1.21.5 { @@ -87,7 +80,7 @@ object DebugOverlayOffscreen { } //? if >= 1.21.8 { - private fun renderRecorded(rt: TextureTarget) { + private fun renderRecorded(rt: RenderTarget) { val guiRenderer = (client.gameRenderer as GameRendererAccessor).`oneconfig$getGuiRenderer`() val accessor = guiRenderer as GuiRendererAccessor @@ -95,7 +88,7 @@ object DebugOverlayOffscreen { //? if >= 1.21.11 { val ext = GuiGraphicsExtractor(client, state, Platform.screen().guiWidth(), Platform.screen().guiHeight()) //? } else - /*val ext = GuiGraphicsExtractor(client, state)*/ + //val ext = GuiGraphicsExtractor(client, state) capturing = true try { //~ if >= 26.1 'render' -> 'extractRenderState' @@ -123,9 +116,7 @@ object DebugOverlayOffscreen { } } //? } else if >= 1.21.5 { - - /* - private fun renderImmediate(rt: TextureTarget) { + /*private fun renderImmediate(rt: RenderTarget) { val graphics = GuiGraphicsExtractor(client, client.renderBuffers().bufferSource()) clearTarget(rt) capturing = true @@ -139,24 +130,24 @@ object DebugOverlayOffscreen { } } *///? } else { - - /* - private fun renderImmediateLegacy(rt: TextureTarget) { + /*private fun renderImmediateLegacy(rt: RenderTarget) { val graphics = GuiGraphicsExtractor(client, client.renderBuffers().bufferSource()) clearTarget(rt) capturing = true - rt.bindWrite(true) + GuiTargetRedirect.target = rt try { + rt.bindWrite(true) client.debugOverlay.render(graphics) graphics.flush() } finally { + GuiTargetRedirect.target = null client.mainRenderTarget.bindWrite(true) capturing = false } } *///? } - private fun clearTarget(rt: TextureTarget) { + private fun clearTarget(rt: RenderTarget) { //? if >= 26.2 { val colorTex = rt.colorTexture ?: return com.mojang.blaze3d.systems.RenderSystem.getDevice().createCommandEncoder() @@ -172,56 +163,9 @@ object DebugOverlayOffscreen { *///? } } - private fun resolveTarget(w: Int, h: Int): Boolean { - if (target != null && lastW == w && lastH == h && surface != null) return true - destroy() - try { - //? if >= 26.2 { - val rt = TextureTarget(null, w, h, true, com.mojang.blaze3d.GpuFormat.RGBA8_UNORM) - //? } else if >= 1.21.5 { - /*val rt = TextureTarget(null, w, h, true) - *///? } else if >= 1.21.4 { - /*val rt = TextureTarget(w, h, true) - *///? } else { - /*val rt = TextureTarget(w, h, true, Minecraft.ON_OSX) - *///? } - target = rt - //? if < 1.21.5 - /*rt.setClearColor(0f, 0f, 0f, 0f)*/ - val svc = SkiaCtx.vulkanService ?: return false - if (!SkiaCtx.isVulkanMode) { - //? if >= 1.21.5 { - val fboId = org.polyfrost.oneconfig.internal.ui.RenderTargetFbo.getFboId(rt) - //? } else - /*val fboId = rt.frameBufferId*/ - if (fboId <= 0) { - target = null - rt.destroyBuffers() - return false - } - } - val (b, colorFmt) = svc.makeOffscreenBRT(rt, w, h) - brt = b - val origin = if (SkiaCtx.isDeferredComposeBackend) SurfaceOrigin.TOP_LEFT else SurfaceOrigin.BOTTOM_LEFT - surface = Surface.makeFromBackendRenderTarget( - SkiaCtx.directContext, b, origin, colorFmt, ColorSpace.sRGB, null, - ) - if (surface == null) { - b.close(); brt = null - return false - } - lastW = w; lastH = h - return true - } catch (t: Throwable) { - LOG.warn("Failed to create debug overlay offscreen target", t) - destroy() - return false - } - } - private fun drawInto(canvas: org.jetbrains.skia.Canvas) { if (!hasContent) return - val s = surface ?: return + val s = offscreen.surface ?: return try { s.notifyContentWillChange(org.jetbrains.skia.ContentChangeMode.RETAIN) s.draw(canvas, 0, 0, blitPaint) @@ -229,16 +173,4 @@ object DebugOverlayOffscreen { LOG.debug("debug overlay blit failed", t) } } - - private fun destroy() { - surface?.close(); surface = null - brt?.close(); brt = null - target?.destroyBuffers(); target = null - lastW = -1; lastH = -1 - } - - fun invalidate() { - destroy() - hasContent = false - } } diff --git a/minecraft/src/main/kotlin/org/polyfrost/oneconfig/internal/ui/hud/LegacyHudOffscreen.kt b/minecraft/src/main/kotlin/org/polyfrost/oneconfig/internal/ui/hud/LegacyHudOffscreen.kt index 20916c74a..46c8d13f6 100644 --- a/minecraft/src/main/kotlin/org/polyfrost/oneconfig/internal/ui/hud/LegacyHudOffscreen.kt +++ b/minecraft/src/main/kotlin/org/polyfrost/oneconfig/internal/ui/hud/LegacyHudOffscreen.kt @@ -1,22 +1,23 @@ -//? if >= 26.1 { package org.polyfrost.oneconfig.internal.ui.hud -import com.mojang.blaze3d.pipeline.TextureTarget +import com.mojang.blaze3d.pipeline.RenderTarget import net.minecraft.client.Minecraft import net.minecraft.client.gui.GuiGraphicsExtractor -import net.minecraft.client.gui.render.GuiRenderer +//? if >= 26.1 { import net.minecraft.client.renderer.state.gui.GuiRenderState import org.polyfrost.oneconfig.internal.mixin.render.GameRendererAccessor import org.polyfrost.oneconfig.internal.mixin.render.GuiRendererAccessor -import org.jetbrains.skia.BackendRenderTarget -import org.jetbrains.skia.ColorSpace +//?} elif >= 1.21.8 { +/*import net.minecraft.client.gui.render.state.GuiRenderState +import org.polyfrost.oneconfig.internal.mixin.render.GameRendererAccessor +import org.polyfrost.oneconfig.internal.mixin.render.GuiRendererAccessor +*///?} import org.jetbrains.skia.Paint -import org.jetbrains.skia.Surface -import org.jetbrains.skia.SurfaceOrigin import org.polyfrost.oneconfig.api.hud.v1.Hud import org.polyfrost.oneconfig.api.hud.v1.HudManager import org.polyfrost.oneconfig.api.hud.v1.LegacyHud import org.polyfrost.oneconfig.api.platform.v1.Platform +import org.polyfrost.oneconfig.internal.ui.SkiaOffscreenTarget import org.polyfrost.oneconfig.internal.ui.compose.SkiaCtx import org.slf4j.LoggerFactory @@ -24,11 +25,7 @@ object LegacyHudOffscreen { private val LOG = LoggerFactory.getLogger("OneConfig/LegacyHudOffscreen") private val client get() = Minecraft.getInstance() - private var target: TextureTarget? = null - private var brt: BackendRenderTarget? = null - private var surface: Surface? = null - private var lastW = -1 - private var lastH = -1 + private val offscreen = SkiaOffscreenTarget() @Volatile private var hasContent = false @Volatile private var failed = false @@ -39,44 +36,6 @@ object LegacyHudOffscreen { LegacyHudOverlayBridge.painter = { c -> drawInto(c) } } - private fun resolveTarget(w: Int, h: Int): Boolean { - if (target != null && lastW == w && lastH == h && surface != null) return true - destroy() - try { - //? if >= 26.2 { - val rt = TextureTarget(null, w, h, true, com.mojang.blaze3d.GpuFormat.RGBA8_UNORM) - //? } else { - /*val rt = TextureTarget(null, w, h, true) - *///? } - target = rt - val svc = SkiaCtx.vulkanService ?: return false - if (!SkiaCtx.isVulkanMode) { - val fboId = org.polyfrost.oneconfig.internal.ui.RenderTargetFbo.getFboId(rt) - if (fboId <= 0) { - target = null - rt.destroyBuffers() - return false - } - } - val (b, colorFmt) = svc.makeOffscreenBRT(rt, w, h) - brt = b - val origin = if (SkiaCtx.isDeferredComposeBackend) SurfaceOrigin.TOP_LEFT else SurfaceOrigin.BOTTOM_LEFT - surface = Surface.makeFromBackendRenderTarget( - SkiaCtx.directContext, b, origin, colorFmt, ColorSpace.sRGB, null, - ) - if (surface == null) { - b.close(); brt = null - return false - } - lastW = w; lastH = h - return true - } catch (t: Throwable) { - LOG.warn("Failed to create legacy HUD offscreen target", t) - destroy() - return false - } - } - private fun activeLegacyHuds(): List = HudManager.activeInstances.mapNotNull { hud: Hud -> (hud as? LegacyHud)?.takeUnless { @@ -96,71 +55,138 @@ object LegacyHudOffscreen { if (w <= 0 || h <= 0) return try { - if (!resolveTarget(w, h)) return - val rt = target ?: return - val guiRenderer = (client.gameRenderer as GameRendererAccessor).`oneconfig$getGuiRenderer`() - val accessor = guiRenderer as GuiRendererAccessor + if (!offscreen.resolveTarget(w, h)) return + val rt = offscreen.target ?: return + //? if >= 1.21.8 { + renderRecorded(rt, huds) + //?} elif >= 1.21.5 { + /*renderImmediate(rt, huds) + *///?} else { + /*renderImmediateLegacy(rt, huds) + *///?} + hasContent = true + } catch (t: Throwable) { + LOG.warn("Legacy HUD offscreen render failed; disabling", t) + failed = true + //? if >= 1.21.5 + GuiTargetRedirect.target = null + } + } - val guiW = Platform.screen().guiWidth() - val guiH = Platform.screen().guiHeight() + //? if >= 1.21.8 { + private fun renderRecorded(rt: RenderTarget, huds: List) { + val guiRenderer = (client.gameRenderer as GameRendererAccessor).`oneconfig$getGuiRenderer`() + val accessor = guiRenderer as GuiRendererAccessor - val state = GuiRenderState() - val ext = GuiGraphicsExtractor(client, state, guiW, guiH) - for (hud in huds) { - try { - val scale = hud.effectiveScale - hud.renderedW = hud.width * scale - hud.renderedH = hud.height * scale - val pose = ext.pose() - pose.pushMatrix() - try { - pose.translate(hud.x, hud.y) - if (scale != 1f) pose.scale(scale, scale) - hud.render(ext) - } finally { - pose.popMatrix() - } - } catch (t: Throwable) { - LOG.debug("legacy hud render (record) failed", t) - } - } + val state = GuiRenderState() + //? if >= 1.21.11 { + val ext = GuiGraphicsExtractor(client, state, Platform.screen().guiWidth(), Platform.screen().guiHeight()) + //?} else + //val ext = GuiGraphicsExtractor(client, state) + renderHuds(ext, huds) - if (CompatOverlayRenderer.oneConfigScreenOpen()) CompatOverlayRenderer.render(ext) + clearTarget(rt) - val colorTex = rt.colorTexture ?: return - val encoder = com.mojang.blaze3d.systems.RenderSystem.getDevice().createCommandEncoder() + val prevState = accessor.`oneconfig$getRenderState`() + GuiTargetRedirect.target = rt + try { + accessor.`oneconfig$setRenderState`(state) //? if >= 26.2 { - encoder.clearColorTexture(colorTex, org.joml.Vector4f(0f, 0f, 0f, 0f)) - //? } else { - /*encoder.clearColorTexture(colorTex, 0) - *///? } + guiRenderer.render() + //?} else { + /*val fog = (client.gameRenderer as GameRendererAccessor).`oneconfig$getFogRenderer`() + .getBuffer(net.minecraft.client.renderer.fog.FogRenderer.FogMode.NONE) + guiRenderer.render(fog) + *///?} + } finally { + GuiTargetRedirect.target = null + accessor.`oneconfig$setRenderState`(prevState) + } + } + //?} elif >= 1.21.5 { + /*private fun renderImmediate(rt: RenderTarget, huds: List) { + val graphics = GuiGraphicsExtractor(client, client.renderBuffers().bufferSource()) + clearTarget(rt) + GuiTargetRedirect.target = rt + try { + renderHuds(graphics, huds) + graphics.flush() + } finally { + GuiTargetRedirect.target = null + } + } + *///?} else { + /*private fun renderImmediateLegacy(rt: RenderTarget, huds: List) { + val graphics = GuiGraphicsExtractor(client, client.renderBuffers().bufferSource()) + clearTarget(rt) + GuiTargetRedirect.target = rt + try { + rt.bindWrite(true) + renderHuds(graphics, huds) + graphics.flush() + } finally { + GuiTargetRedirect.target = null + client.mainRenderTarget.bindWrite(true) + } + } + *///?} - val prevState = accessor.`oneconfig$getRenderState`() - GuiTargetRedirect.target = rt + private fun renderHuds(ext: GuiGraphicsExtractor, huds: List) { + for (hud in huds) { try { - accessor.`oneconfig$setRenderState`(state) - //? if >= 26.2 { - guiRenderer.render() - //? } else { - /*val fog = (client.gameRenderer as GameRendererAccessor).`oneconfig$getFogRenderer`() - .getBuffer(net.minecraft.client.renderer.fog.FogRenderer.FogMode.NONE) - guiRenderer.render(fog) - *///? } - } finally { - GuiTargetRedirect.target = null - accessor.`oneconfig$setRenderState`(prevState) + val scale = hud.effectiveScale + hud.renderedW = hud.width * scale + hud.renderedH = hud.height * scale + val pose = ext.pose() + //? if >= 1.21.8 { + pose.pushMatrix() + try { + pose.translate(hud.x, hud.y) + if (scale != 1f) pose.scale(scale, scale) + hud.render(ext) + } finally { + pose.popMatrix() + } + //?} else { + /*pose.pushPose() + try { + pose.translate(hud.x.toDouble(), hud.y.toDouble(), 0.0) + if (scale != 1f) pose.scale(scale, scale, 1f) + hud.render(ext) + } finally { + pose.popPose() + } + *///?} + } catch (t: Throwable) { + LOG.debug("legacy hud render (record) failed", t) } - hasContent = true - } catch (t: Throwable) { - LOG.warn("Legacy HUD offscreen render failed; disabling", t) - failed = true - GuiTargetRedirect.target = null } + if (CompatOverlayRenderer.oneConfigScreenOpen()) CompatOverlayRenderer.render(ext) + } + + private fun clearTarget(rt: RenderTarget) { + //? if >= 26.2 { + val colorTex = rt.colorTexture ?: return + com.mojang.blaze3d.systems.RenderSystem.getDevice().createCommandEncoder() + .clearColorTexture(colorTex, org.joml.Vector4f(0f, 0f, 0f, 0f)) + //? } else if >= 1.21.5 { + /*val colorTex = rt.colorTexture ?: return + val encoder = com.mojang.blaze3d.systems.RenderSystem.getDevice().createCommandEncoder() + encoder.clearColorTexture(colorTex, 0) + //? if < 1.21.10 { + /*//1.21.5 does not clear depth, and 1.21.8 clears it only after rendering the before-blur range + rt.depthTexture?.let { encoder.clearDepthTexture(it, 1.0) } + *///?} + *///?} elif >= 1.21.4 { + /*rt.clear() + *///?} else { + /*rt.clear(Minecraft.ON_OSX) + *///?} } fun drawInto(canvas: org.jetbrains.skia.Canvas) { if (!hasContent) return - val s = surface ?: return + val s = offscreen.surface ?: return try { s.notifyContentWillChange(org.jetbrains.skia.ContentChangeMode.RETAIN) val surfaceRatio = Platform.screen().surfaceRatio().coerceAtLeast(0.0001f) @@ -172,17 +198,4 @@ object LegacyHudOffscreen { LOG.debug("legacy hud blit failed", t) } } - - private fun destroy() { - surface?.close(); surface = null - brt?.close(); brt = null - target?.destroyBuffers(); target = null - lastW = -1; lastH = -1 - } - - fun invalidate() { - destroy() - hasContent = false - } } -//? } From e4b50d119a37dba68e366b02e15f4d40da85ffea Mon Sep 17 00:00:00 2001 From: Julian Chang Date: Fri, 21 Aug 2026 15:27:00 +0700 Subject: [PATCH 4/4] misc fixes --- .../oneconfig/internal/OneConfig.java | 5 +- .../internal/ui/SkiaOffscreenTarget.kt | 54 ++++++--- .../oneconfig/internal/ui/compose/SkiaCtx.kt | 2 + .../ui/compose/impls/OneConfigUIScreen.kt | 1 + .../internal/ui/hud/DebugOverlayOffscreen.kt | 23 +--- .../internal/ui/hud/LegacyHudOffscreen.kt | 105 ++++-------------- .../internal/ui/hud/LegacyHudRenderer.kt | 19 ++-- .../oneconfig/api/hud/v1/HudManager.kt | 8 +- 8 files changed, 86 insertions(+), 131 deletions(-) diff --git a/minecraft/src/main/java/org/polyfrost/oneconfig/internal/OneConfig.java b/minecraft/src/main/java/org/polyfrost/oneconfig/internal/OneConfig.java index 778618dfc..ed4c8a16b 100644 --- a/minecraft/src/main/java/org/polyfrost/oneconfig/internal/OneConfig.java +++ b/minecraft/src/main/java/org/polyfrost/oneconfig/internal/OneConfig.java @@ -184,10 +184,9 @@ public static void render(GuiGraphicsExtractor graphics, float partial) { HudManager.targetPixelHeight = Platform.screen().viewportHeight(); //~ if < 1.21.8 '.suppressInGameHudRender' -> '.shouldSuppressInGameHudRender()' - if (!SkiaCtx.INSTANCE.suppressInGameHudRender) { + boolean hudRendersLive = !SkiaCtx.INSTANCE.suppressInGameHudRender; + if (hudRendersLive || !org.polyfrost.oneconfig.internal.ui.hud.LegacyHudOffscreen.INSTANCE.render()) { LegacyHudRenderer.INSTANCE.renderLive(graphics); - } else { - org.polyfrost.oneconfig.internal.ui.hud.LegacyHudOffscreen.INSTANCE.render(); } // records the F3 overlay offscreen so Skia can put it above the Compose UI instead of below the // blur and it must run every frame regardless of the HUD dirty gate diff --git a/minecraft/src/main/kotlin/org/polyfrost/oneconfig/internal/ui/SkiaOffscreenTarget.kt b/minecraft/src/main/kotlin/org/polyfrost/oneconfig/internal/ui/SkiaOffscreenTarget.kt index 15e65a29e..7741254de 100644 --- a/minecraft/src/main/kotlin/org/polyfrost/oneconfig/internal/ui/SkiaOffscreenTarget.kt +++ b/minecraft/src/main/kotlin/org/polyfrost/oneconfig/internal/ui/SkiaOffscreenTarget.kt @@ -11,7 +11,9 @@ import org.slf4j.LoggerFactory /** Owns a Minecraft render target and its Skia surface, cached by size. */ class SkiaOffscreenTarget { - private val LOG = LoggerFactory.getLogger("OneConfig/SkiaOffscreenTarget") + init { + live += this + } var target: RenderTarget? = null private set @@ -24,6 +26,7 @@ class SkiaOffscreenTarget { fun resolveTarget(w: Int, h: Int): Boolean { if (target != null && lastW == w && lastH == h && surface != null) return true destroy() + val svc = SkiaCtx.vulkanService ?: return false try { //? if >= 26.2 { val rt = TextureTarget(null, w, h, true, com.mojang.blaze3d.GpuFormat.RGBA8_UNORM) @@ -36,18 +39,10 @@ class SkiaOffscreenTarget { *///?} target = rt //? if < 1.21.5 - /*rt.setClearColor(0f, 0f, 0f, 0f)*/ - val svc = SkiaCtx.vulkanService ?: return false - if (!SkiaCtx.isVulkanMode) { - //? if >= 1.21.5 { - val fboId = RenderTargetFbo.getFboId(rt) - //? } else - /*val fboId = rt.frameBufferId*/ - if (fboId <= 0) { - target = null - rt.destroyBuffers() - return false - } + //rt.setClearColor(0f, 0f, 0f, 0f) + if (!SkiaCtx.isVulkanMode && RenderTargetFbo.getFboId(rt) <= 0) { + destroy() + return false } val (b, colorFmt) = svc.makeOffscreenBRT(rt, w, h) brt = b @@ -56,7 +51,7 @@ class SkiaOffscreenTarget { SkiaCtx.directContext, b, origin, colorFmt, ColorSpace.sRGB, null, ) if (surface == null) { - b.close(); brt = null + destroy() return false } lastW = w; lastH = h @@ -68,10 +63,41 @@ class SkiaOffscreenTarget { } } + fun clearTarget() { + val rt = target ?: return + //? if >= 26.2 { + val colorTex = rt.colorTexture ?: return + com.mojang.blaze3d.systems.RenderSystem.getDevice().createCommandEncoder() + .clearColorTexture(colorTex, org.joml.Vector4f(0f, 0f, 0f, 0f)) + //? } else if >= 1.21.5 { + /*val colorTex = rt.colorTexture ?: return + val encoder = com.mojang.blaze3d.systems.RenderSystem.getDevice().createCommandEncoder() + encoder.clearColorTexture(colorTex, 0) + //? if < 1.21.10 { + /*//1.21.5 does not clear depth, and 1.21.8 clears it only after rendering the before-blur range + rt.depthTexture?.let { encoder.clearDepthTexture(it, 1.0) } + *///?} + *///?} elif >= 1.21.4 { + /*rt.clear() + *///?} else { + /*rt.clear(net.minecraft.client.Minecraft.ON_OSX) + *///?} + } + fun destroy() { surface?.close(); surface = null brt?.close(); brt = null target?.destroyBuffers(); target = null lastW = -1; lastH = -1 } + + companion object { + private val LOG = LoggerFactory.getLogger("OneConfig/SkiaOffscreenTarget") + + private val live = ArrayList(2) + + fun destroyAll() { + for (t in live) t.destroy() + } + } } diff --git a/minecraft/src/main/kotlin/org/polyfrost/oneconfig/internal/ui/compose/SkiaCtx.kt b/minecraft/src/main/kotlin/org/polyfrost/oneconfig/internal/ui/compose/SkiaCtx.kt index 239e78d74..52e6346a2 100644 --- a/minecraft/src/main/kotlin/org/polyfrost/oneconfig/internal/ui/compose/SkiaCtx.kt +++ b/minecraft/src/main/kotlin/org/polyfrost/oneconfig/internal/ui/compose/SkiaCtx.kt @@ -572,6 +572,7 @@ object SkiaCtx { } destroyHudTarget() destroyComposeTarget() + org.polyfrost.oneconfig.internal.ui.SkiaOffscreenTarget.destroyAll() } private fun flushToTarget(draws: List<() -> Unit>, surface: Surface, flipY: Boolean = false) { @@ -762,6 +763,7 @@ object SkiaCtx { composeAllocFailedAt = System.currentTimeMillis() destroyComposeTarget() destroyHudTarget() + org.polyfrost.oneconfig.internal.ui.SkiaOffscreenTarget.destroyAll() if (isVulkanMode) invalidateVkSurfaces() runCatching { directContext.flush() } LOG.error("SkiaCtx: failed to allocate the {}x{} compose target; skipping compose frames", w, h, error) diff --git a/minecraft/src/main/kotlin/org/polyfrost/oneconfig/internal/ui/compose/impls/OneConfigUIScreen.kt b/minecraft/src/main/kotlin/org/polyfrost/oneconfig/internal/ui/compose/impls/OneConfigUIScreen.kt index 5045879e5..421319ae1 100644 --- a/minecraft/src/main/kotlin/org/polyfrost/oneconfig/internal/ui/compose/impls/OneConfigUIScreen.kt +++ b/minecraft/src/main/kotlin/org/polyfrost/oneconfig/internal/ui/compose/impls/OneConfigUIScreen.kt @@ -200,6 +200,7 @@ class OneConfigUIScreen @JvmOverloads constructor( SkiaCtx.suppressInGameHudRender = false HudManager.overrideShowInScreens = false HudManager.isConfigUiOpen = false + org.polyfrost.oneconfig.internal.ui.SkiaOffscreenTarget.destroyAll() UiSounds.releaseAmbience() // writing every registered tree hitches and Minecraft only re-grabs the cursor once this returns SAVE_EXECUTOR.execute { diff --git a/minecraft/src/main/kotlin/org/polyfrost/oneconfig/internal/ui/hud/DebugOverlayOffscreen.kt b/minecraft/src/main/kotlin/org/polyfrost/oneconfig/internal/ui/hud/DebugOverlayOffscreen.kt index c8d773bcf..4a4eec1df 100644 --- a/minecraft/src/main/kotlin/org/polyfrost/oneconfig/internal/ui/hud/DebugOverlayOffscreen.kt +++ b/minecraft/src/main/kotlin/org/polyfrost/oneconfig/internal/ui/hud/DebugOverlayOffscreen.kt @@ -74,7 +74,6 @@ object DebugOverlayOffscreen { LOG.warn("Debug overlay offscreen render failed; disabling", t) failed = true capturing = false - //? if >= 1.21.5 GuiTargetRedirect.target = null } } @@ -97,7 +96,7 @@ object DebugOverlayOffscreen { capturing = false } - clearTarget(rt) + offscreen.clearTarget() val prevState = accessor.`oneconfig$getRenderState`() GuiTargetRedirect.target = rt @@ -118,7 +117,7 @@ object DebugOverlayOffscreen { //? } else if >= 1.21.5 { /*private fun renderImmediate(rt: RenderTarget) { val graphics = GuiGraphicsExtractor(client, client.renderBuffers().bufferSource()) - clearTarget(rt) + offscreen.clearTarget() capturing = true GuiTargetRedirect.target = rt try { @@ -132,7 +131,7 @@ object DebugOverlayOffscreen { *///? } else { /*private fun renderImmediateLegacy(rt: RenderTarget) { val graphics = GuiGraphicsExtractor(client, client.renderBuffers().bufferSource()) - clearTarget(rt) + offscreen.clearTarget() capturing = true GuiTargetRedirect.target = rt try { @@ -147,22 +146,6 @@ object DebugOverlayOffscreen { } *///? } - private fun clearTarget(rt: RenderTarget) { - //? if >= 26.2 { - val colorTex = rt.colorTexture ?: return - com.mojang.blaze3d.systems.RenderSystem.getDevice().createCommandEncoder() - .clearColorTexture(colorTex, org.joml.Vector4f(0f, 0f, 0f, 0f)) - //? } else if >= 1.21.5 { - /*val colorTex = rt.colorTexture ?: return - com.mojang.blaze3d.systems.RenderSystem.getDevice().createCommandEncoder() - .clearColorTexture(colorTex, 0) - *///? } else if >= 1.21.4 { - /*rt.clear() - *///? } else { - /*rt.clear(Minecraft.ON_OSX) - *///? } - } - private fun drawInto(canvas: org.jetbrains.skia.Canvas) { if (!hasContent) return val s = offscreen.surface ?: return diff --git a/minecraft/src/main/kotlin/org/polyfrost/oneconfig/internal/ui/hud/LegacyHudOffscreen.kt b/minecraft/src/main/kotlin/org/polyfrost/oneconfig/internal/ui/hud/LegacyHudOffscreen.kt index 46c8d13f6..ceb98945c 100644 --- a/minecraft/src/main/kotlin/org/polyfrost/oneconfig/internal/ui/hud/LegacyHudOffscreen.kt +++ b/minecraft/src/main/kotlin/org/polyfrost/oneconfig/internal/ui/hud/LegacyHudOffscreen.kt @@ -13,7 +13,6 @@ import org.polyfrost.oneconfig.internal.mixin.render.GameRendererAccessor import org.polyfrost.oneconfig.internal.mixin.render.GuiRendererAccessor *///?} import org.jetbrains.skia.Paint -import org.polyfrost.oneconfig.api.hud.v1.Hud import org.polyfrost.oneconfig.api.hud.v1.HudManager import org.polyfrost.oneconfig.api.hud.v1.LegacyHud import org.polyfrost.oneconfig.api.platform.v1.Platform @@ -36,45 +35,38 @@ object LegacyHudOffscreen { LegacyHudOverlayBridge.painter = { c -> drawInto(c) } } - private fun activeLegacyHuds(): List = - HudManager.activeInstances.mapNotNull { hud: Hud -> - (hud as? LegacyHud)?.takeUnless { - it.hidden && !HudManager.isEditing && !SkiaCtx.suppressInGameHudRender - } - } - - fun render() { + fun render(): Boolean { hasContent = false - if (failed) return - if (java.lang.Boolean.getBoolean("oneconfig.disable.legacyHudOffscreen")) return - val huds = activeLegacyHuds() - if (huds.isEmpty() && !CompatOverlayRenderer.hasHooks()) return - if (!SkiaCtx.isReady) return + if (failed) return false + if (java.lang.Boolean.getBoolean("oneconfig.disable.legacyHudOffscreen")) return false + if (HudManager.activeInstances.none { it is LegacyHud } && !CompatOverlayRenderer.hasHooks()) return true + if (!SkiaCtx.isReady) return true val w = Platform.screen().viewportWidth() val h = Platform.screen().viewportHeight() - if (w <= 0 || h <= 0) return + if (w <= 0 || h <= 0) return true try { - if (!offscreen.resolveTarget(w, h)) return - val rt = offscreen.target ?: return + if (!offscreen.resolveTarget(w, h)) return true + val rt = offscreen.target ?: return true //? if >= 1.21.8 { - renderRecorded(rt, huds) + renderRecorded(rt) //?} elif >= 1.21.5 { - /*renderImmediate(rt, huds) + /*renderImmediate(rt) *///?} else { - /*renderImmediateLegacy(rt, huds) + /*renderImmediateLegacy(rt) *///?} hasContent = true + return true } catch (t: Throwable) { LOG.warn("Legacy HUD offscreen render failed; disabling", t) failed = true - //? if >= 1.21.5 GuiTargetRedirect.target = null + return false } } //? if >= 1.21.8 { - private fun renderRecorded(rt: RenderTarget, huds: List) { + private fun renderRecorded(rt: RenderTarget) { val guiRenderer = (client.gameRenderer as GameRendererAccessor).`oneconfig$getGuiRenderer`() val accessor = guiRenderer as GuiRendererAccessor @@ -83,9 +75,9 @@ object LegacyHudOffscreen { val ext = GuiGraphicsExtractor(client, state, Platform.screen().guiWidth(), Platform.screen().guiHeight()) //?} else //val ext = GuiGraphicsExtractor(client, state) - renderHuds(ext, huds) + LegacyHudRenderer.renderLive(ext) - clearTarget(rt) + offscreen.clearTarget() val prevState = accessor.`oneconfig$getRenderState`() GuiTargetRedirect.target = rt @@ -104,25 +96,25 @@ object LegacyHudOffscreen { } } //?} elif >= 1.21.5 { - /*private fun renderImmediate(rt: RenderTarget, huds: List) { + /*private fun renderImmediate(rt: RenderTarget) { val graphics = GuiGraphicsExtractor(client, client.renderBuffers().bufferSource()) - clearTarget(rt) + offscreen.clearTarget() GuiTargetRedirect.target = rt try { - renderHuds(graphics, huds) + LegacyHudRenderer.renderLive(graphics) graphics.flush() } finally { GuiTargetRedirect.target = null } } *///?} else { - /*private fun renderImmediateLegacy(rt: RenderTarget, huds: List) { + /*private fun renderImmediateLegacy(rt: RenderTarget) { val graphics = GuiGraphicsExtractor(client, client.renderBuffers().bufferSource()) - clearTarget(rt) + offscreen.clearTarget() GuiTargetRedirect.target = rt try { rt.bindWrite(true) - renderHuds(graphics, huds) + LegacyHudRenderer.renderLive(graphics) graphics.flush() } finally { GuiTargetRedirect.target = null @@ -131,59 +123,6 @@ object LegacyHudOffscreen { } *///?} - private fun renderHuds(ext: GuiGraphicsExtractor, huds: List) { - for (hud in huds) { - try { - val scale = hud.effectiveScale - hud.renderedW = hud.width * scale - hud.renderedH = hud.height * scale - val pose = ext.pose() - //? if >= 1.21.8 { - pose.pushMatrix() - try { - pose.translate(hud.x, hud.y) - if (scale != 1f) pose.scale(scale, scale) - hud.render(ext) - } finally { - pose.popMatrix() - } - //?} else { - /*pose.pushPose() - try { - pose.translate(hud.x.toDouble(), hud.y.toDouble(), 0.0) - if (scale != 1f) pose.scale(scale, scale, 1f) - hud.render(ext) - } finally { - pose.popPose() - } - *///?} - } catch (t: Throwable) { - LOG.debug("legacy hud render (record) failed", t) - } - } - if (CompatOverlayRenderer.oneConfigScreenOpen()) CompatOverlayRenderer.render(ext) - } - - private fun clearTarget(rt: RenderTarget) { - //? if >= 26.2 { - val colorTex = rt.colorTexture ?: return - com.mojang.blaze3d.systems.RenderSystem.getDevice().createCommandEncoder() - .clearColorTexture(colorTex, org.joml.Vector4f(0f, 0f, 0f, 0f)) - //? } else if >= 1.21.5 { - /*val colorTex = rt.colorTexture ?: return - val encoder = com.mojang.blaze3d.systems.RenderSystem.getDevice().createCommandEncoder() - encoder.clearColorTexture(colorTex, 0) - //? if < 1.21.10 { - /*//1.21.5 does not clear depth, and 1.21.8 clears it only after rendering the before-blur range - rt.depthTexture?.let { encoder.clearDepthTexture(it, 1.0) } - *///?} - *///?} elif >= 1.21.4 { - /*rt.clear() - *///?} else { - /*rt.clear(Minecraft.ON_OSX) - *///?} - } - fun drawInto(canvas: org.jetbrains.skia.Canvas) { if (!hasContent) return val s = offscreen.surface ?: return diff --git a/minecraft/src/main/kotlin/org/polyfrost/oneconfig/internal/ui/hud/LegacyHudRenderer.kt b/minecraft/src/main/kotlin/org/polyfrost/oneconfig/internal/ui/hud/LegacyHudRenderer.kt index 18a360668..7c09f48a1 100644 --- a/minecraft/src/main/kotlin/org/polyfrost/oneconfig/internal/ui/hud/LegacyHudRenderer.kt +++ b/minecraft/src/main/kotlin/org/polyfrost/oneconfig/internal/ui/hud/LegacyHudRenderer.kt @@ -38,17 +38,20 @@ object LegacyHudRenderer { } private fun renderLiveHuds(graphics: GuiGraphicsExtractor) { + if (!HudManager.masterHudEnabled && !HudManager.isEditing) return frame.clear() for (hud in HudManager.activeInstances) { if (hud !is LegacyHud) continue - if (hud.hidden && !HudManager.isEditing) continue - if (HudManager.isGuiHidden && !HudManager.isEditing) continue - if (HudManager.isDebugScreenVisible && !hud.showInF3) continue - if (HudManager.isTabListVisible && !hud.showInTab) continue - if (!HudManager.overrideShowInScreens && !HudManager.isEditing) { - if (HudManager.isChatScreenOpen) { - if (!hud.showInChat) continue - } else if (HudManager.isGuiScreenOpen && !hud.showInScreens) continue + if (!HudManager.isEditing) { + if (hud.hidden) continue + if (HudManager.isGuiHidden) continue + if (HudManager.isDebugScreenVisible && !hud.showInF3) continue + if (HudManager.isTabListVisible && !hud.showInTab) continue + if (!HudManager.overrideShowInScreens) { + if (HudManager.isChatScreenOpen) { + if (!hud.showInChat) continue + } else if (HudManager.isGuiScreenOpen && !hud.showInScreens) continue + } } frame.add(hud) } diff --git a/modules/hud/src/main/kotlin/org/polyfrost/oneconfig/api/hud/v1/HudManager.kt b/modules/hud/src/main/kotlin/org/polyfrost/oneconfig/api/hud/v1/HudManager.kt index 7ddea03c8..719bd1322 100644 --- a/modules/hud/src/main/kotlin/org/polyfrost/oneconfig/api/hud/v1/HudManager.kt +++ b/modules/hud/src/main/kotlin/org/polyfrost/oneconfig/api/hud/v1/HudManager.kt @@ -499,12 +499,13 @@ object HudManager { /** Everything [shouldDraw] checks apart from the HUD's own hidden flag */ private fun isShown(hud: Hud): Boolean { - if (!masterHudEnabled && !isEditing) return false if (hud is LegacyHudMarker) return false - if (isGuiHidden && !isEditing) return false + if (isEditing) return true + if (!masterHudEnabled) return false + if (isGuiHidden) return false if (isDebugScreenVisible && !hud.showInF3) return false if (isTabListVisible && !hud.showInTab) return false - if (!overrideShowInScreens && !isEditing) { + if (!overrideShowInScreens) { // chat has its own toggle so it is never governed by "Show in GUIs" if (isChatScreenOpen) { if (!hud.showInChat) return false @@ -698,6 +699,7 @@ object HudManager { key = key * 31L + (if (isChatScreenOpen) 1 else 0) key = key * 31L + (if (isGuiHidden) 1 else 0) key = key * 31L + (if (overrideShowInScreens) 1 else 0) + key = key * 31L + (if (masterHudEnabled) 1 else 0) key = key * 31L + (if (isEditing) 1 else 0) key = key * 31L + (if (inWorld) 1 else 0) key = key * 31L + targetPixelWidth