diff --git a/glsm/src/main/java/com/gtnewhorizons/angelica/glsm/GLContextState.java b/glsm/src/main/java/com/gtnewhorizons/angelica/glsm/GLContextState.java index 81f5b6ab8..ddad05cc4 100644 --- a/glsm/src/main/java/com/gtnewhorizons/angelica/glsm/GLContextState.java +++ b/glsm/src/main/java/com/gtnewhorizons/angelica/glsm/GLContextState.java @@ -107,6 +107,14 @@ public class GLContextState { public int maxBoundImageUnit = 0; public final StateSet[] attribSets = new StateSet[GLStateManager.MAX_ATTRIB_STACK_DEPTH]; public int attribDepth = 0; + + public boolean savesState(int id) { + for (int i = attribDepth - 1; i >= 0; i--) { + if (attribSets[i].contains(id)) return true; + } + return false; + } + public int batchStateGeneration; public final int[] savedBatchStateGen = new int[GLStateManager.MAX_ATTRIB_STACK_DEPTH]; public CowStateStack[] stackById; diff --git a/glsm/src/main/java/com/gtnewhorizons/angelica/glsm/GLStateManager.java b/glsm/src/main/java/com/gtnewhorizons/angelica/glsm/GLStateManager.java index efcbb4c91..6a07d63ae 100644 --- a/glsm/src/main/java/com/gtnewhorizons/angelica/glsm/GLStateManager.java +++ b/glsm/src/main/java/com/gtnewhorizons/angelica/glsm/GLStateManager.java @@ -170,8 +170,7 @@ public class GLStateManager { beforeUncapturedStateChange(); } - private static void beforeMatrixChange() { - final GLContextState c = ctx(); + private static void beforeMatrixChange(GLContextState c) { if (c.matrixMode.getMode() == GL11.GL_PROJECTION || (c.matrixMode.getMode() == GL11.GL_TEXTURE && c.activeTextureUnit.getValue() != 0)) { beforeUncapturedStateChange(); @@ -188,12 +187,17 @@ public class GLStateManager { private static volatile GLContextState primaryContext; private static final ThreadLocal tlWorkerContext = new ThreadLocal<>(); + private static GLContextState mainCtx; private static volatile boolean workerContextsActive; private static int workerContextCount; private static final IdentityHashMap drawableContexts = new IdentityHashMap<>(); private static GLContextState[] drawableContextStates = new GLContextState[0]; public static GLContextState ctx() { + if (Thread.currentThread() == MainThread) { + final GLContextState c = mainCtx; + return c != null ? c : (mainCtx = primaryContext()); + } if (!workerContextsActive) return primaryContext(); final GLContextState st = tlWorkerContext.get(); return st != null ? st : primaryContext(); @@ -235,6 +239,7 @@ public class GLStateManager { workerContextsActive = workerContextCount != 0; } if (target == null) tlWorkerContext.remove(); else tlWorkerContext.set(target); + if (Thread.currentThread() == MainThread) mainCtx = target; return true; } @@ -1415,10 +1420,10 @@ public class GLStateManager { return; } } - mod(glCtx.blendState); final boolean caching = isCachingEnabled(); final boolean bypass = !caching; if (bypass || red != glCtx.blendState.getBlendColorR() || green != glCtx.blendState.getBlendColorG() || blue != glCtx.blendState.getBlendColorB() || alpha != glCtx.blendState.getBlendColorA()) { + mod(glCtx.blendState); beforeUncapturedStateChange(); glCtx.blendState.setBlendColorR(red); glCtx.blendState.setBlendColorG(green); @@ -1608,16 +1613,17 @@ public class GLStateManager { return; } } - mod(glCtx.blendState); final boolean snapshotted = snapshotVanillaBlendFunc(); final DeferredBlendHandler bh = GLSMHooks.blendHandler; if (bh != null && bh.isBlendLocked()) { + mod(glCtx.blendState); bh.deferBlendFunc(srcFactor, dstFactor, srcFactor, dstFactor); postVanillaBlendChangeIfMoved(snapshotted); return; } final boolean caching = isCachingEnabled(); if (GLSMConfig.hudCacheOverride) { + mod(glCtx.blendState); glCtx.blendState.setAll(srcFactor, dstFactor, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); glCtx.blendState.clearFuncUnknownState(); RENDER_BACKEND.blendFuncSeparate(srcFactor, dstFactor, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); @@ -1638,6 +1644,7 @@ public class GLStateManager { || glCtx.blendState.getSrcAlpha() != srcFactor || glCtx.blendState.getDstAlpha() != dstFactor || glCtx.blendState.isFuncUnknown()) { + mod(glCtx.blendState); glCtx.blendState.setAll(srcFactor, dstFactor, srcFactor, dstFactor); glCtx.blendState.clearFuncUnknownState(); RENDER_BACKEND.blendFunc(srcFactor, dstFactor); @@ -1657,10 +1664,10 @@ public class GLStateManager { if (DisplayListManager.isRecording()) { throw DisplayListManager.unsupportedInList("glBlendEquation"); } - mod(glCtx.blendState); final boolean caching = isCachingEnabled(); final boolean bypass = !caching; if (bypass || glCtx.blendState.getEquationRgb() != mode || glCtx.blendState.getEquationAlpha() != mode) { + mod(glCtx.blendState); beforeUncapturedStateChange(); glCtx.blendState.setEquationRgb(mode); glCtx.blendState.setEquationAlpha(mode); @@ -1673,10 +1680,10 @@ public class GLStateManager { if (DisplayListManager.isRecording()) { throw DisplayListManager.unsupportedInList("glBlendEquationSeparate"); } - mod(glCtx.blendState); final boolean caching = isCachingEnabled(); final boolean bypass = !caching; if (bypass || glCtx.blendState.getEquationRgb() != modeRGB || glCtx.blendState.getEquationAlpha() != modeAlpha) { + mod(glCtx.blendState); beforeUncapturedStateChange(); glCtx.blendState.setEquationRgb(modeRGB); glCtx.blendState.setEquationAlpha(modeAlpha); @@ -1693,10 +1700,10 @@ public class GLStateManager { return; } } - mod(glCtx.blendState); final boolean snapshotted = snapshotVanillaBlendFunc(); final DeferredBlendHandler bh = GLSMHooks.blendHandler; if (bh != null && bh.isBlendLocked()) { + mod(glCtx.blendState); bh.deferBlendFunc(srcRgb, dstRgb, srcAlpha, dstAlpha); postVanillaBlendChangeIfMoved(snapshotted); return; @@ -1708,6 +1715,7 @@ public class GLStateManager { final boolean caching = isCachingEnabled(); final boolean bypass = !caching; if (bypass || glCtx.blendState.getSrcRgb() != srcRgb || glCtx.blendState.getDstRgb() != dstRgb || glCtx.blendState.getSrcAlpha() != srcAlpha || glCtx.blendState.getDstAlpha() != dstAlpha || glCtx.blendState.isFuncUnknown()) { + mod(glCtx.blendState); glCtx.blendState.setAll(srcRgb, dstRgb, srcAlpha, dstAlpha); glCtx.blendState.clearFuncUnknownState(); RENDER_BACKEND.blendFuncSeparate(srcRgb, dstRgb, srcAlpha, dstAlpha); @@ -1791,9 +1799,9 @@ public class GLStateManager { return; } } - mod(glCtx.depthState); final boolean caching = isCachingEnabled(); if (!caching || func != glCtx.depthState.getFunc()) { + mod(glCtx.depthState); glCtx.depthState.setFunc(func); RENDER_BACKEND.depthFunc(func); } @@ -1808,14 +1816,15 @@ public class GLStateManager { return; } } - mod(glCtx.depthState); final DeferredDepthColorHandler dch = GLSMHooks.depthColorHandler; if (dch != null && dch.isDepthColorLocked()) { + mod(glCtx.depthState); dch.deferDepthEnable(mask); return; } final boolean caching = isCachingEnabled(); if (!caching || mask != glCtx.depthState.isEnabled()) { + mod(glCtx.depthState); glCtx.depthState.setEnabled(mask); RENDER_BACKEND.depthMask(mask); } @@ -2000,15 +2009,16 @@ public class GLStateManager { return; } } - mod(glCtx.colorMask); final DeferredDepthColorHandler dch = GLSMHooks.depthColorHandler; if (dch != null && dch.isDepthColorLocked()) { + mod(glCtx.colorMask); dch.deferColorMask(red, green, blue, alpha); return; } final boolean caching = isCachingEnabled(); final boolean bypass = !caching; if (bypass || red != glCtx.colorMask.red || green != glCtx.colorMask.green || blue != glCtx.colorMask.blue || alpha != glCtx.colorMask.alpha) { + mod(glCtx.colorMask); glCtx.colorMask.setAll(red, green, blue, alpha); RENDER_BACKEND.colorMask(red, green, blue, alpha); } @@ -2120,9 +2130,9 @@ public class GLStateManager { return; } } - mod(glCtx.alphaState); final DeferredAlphaHandler ah = GLSMHooks.alphaHandler; if (ah != null && ah.isAlphaTestLocked()) { + mod(glCtx.alphaState); if (ah.deferAlphaFunc(function, reference) && GLSMHooks.ALPHA_STATE_CHANGE.hasListeners()) { GLSMHooks.ALPHA_STATE_CHANGE.post(GLSMHooks.alphaStateChangeEvent); } @@ -2130,6 +2140,7 @@ public class GLStateManager { } if (isCachingEnabled() && (function != glCtx.alphaState.getFunction() || Float.compare(reference, glCtx.alphaState.getReference()) != 0)) { + mod(glCtx.alphaState); glCtx.alphaState.setFunction(function); glCtx.alphaState.setReference(reference); glCtx.fragmentGeneration++; @@ -4083,8 +4094,11 @@ public class GLStateManager { if (glCtx.attribDepth > 0 && glCtx.savedBatchStateGen[glCtx.attribDepth - 1] != glCtx.batchStateGeneration) { beforeUncapturedStateChange(); } - final StateSet set = glCtx.attribSets[glCtx.attribDepth - 1]; - final boolean inspectAlpha = GLSMHooks.ALPHA_STATE_CHANGE.hasListeners() && (set.contains(glCtx.alphaState.stackId()) || set.contains(glCtx.alphaTest.stackId())); + final int poppedDepth = glCtx.attribDepth; + final StateSet set = glCtx.attribSets[poppedDepth - 1]; + final boolean inspectAlpha = GLSMHooks.ALPHA_STATE_CHANGE.hasListeners() + && ((glCtx.alphaState.cowDepths().claimedAt(poppedDepth) && set.contains(glCtx.alphaState.stackId())) + || (glCtx.alphaTest.cowDepths().claimedAt(poppedDepth) && set.contains(glCtx.alphaTest.stackId()))); final AlphaState effectiveAlpha = inspectAlpha ? glCtx.alphaState.readEffective(glCtx.restoredAlphaScratch) : null; final boolean effectiveEnabled = inspectAlpha && glCtx.alphaTest.isEffectivelyEnabled(); final int effectiveFunction = inspectAlpha ? effectiveAlpha.getFunction() : 0; @@ -4098,8 +4112,9 @@ public class GLStateManager { glCtx.attribDepth--; final int restore = set.restore; - final boolean blendSnapshotted = set.blendSnapshot && snapshotVanillaBlendFunc(); - final int poppedDepth = glCtx.attribDepth + 1; + final boolean blendSnapshotted = set.blendSnapshot + && (glCtx.blendState.cowDepths().claimedAt(poppedDepth) || glCtx.blendMode.cowDepths().claimedAt(poppedDepth)) + && snapshotVanillaBlendFunc(); int changed = 0; long unitsChanged = 0L; @@ -4474,7 +4489,8 @@ public class GLStateManager { } public static void glLoadMatrix(FloatBuffer m) { - beforeMatrixChange(); + final GLContextState glCtx = ctx(); + beforeMatrixChange(glCtx); final RecordMode mode = DisplayListManager.getRecordMode(); if (mode != RecordMode.NONE) { final Matrix4f matrix = new Matrix4f().set(m); @@ -4485,14 +4501,14 @@ public class GLStateManager { } } if (isCachingEnabled()) { - getMatrixStack().set(m); - bumpMatrixGeneration(); + matrixStack(glCtx).set(m); + bumpMatrixGeneration(glCtx); } } public static void glLoadMatrix(DoubleBuffer m) { - beforeMatrixChange(); final GLContextState glCtx = ctx(); + beforeMatrixChange(glCtx); final RecordMode mode = DisplayListManager.getRecordMode(); if (mode != RecordMode.NONE) { // Convert double buffer to float buffer for recording @@ -4507,8 +4523,8 @@ public class GLStateManager { } if (isCachingEnabled()) { glCtx.conversionMatrix4d.set(m); - getMatrixStack().set(glCtx.conversionMatrix4d); - bumpMatrixGeneration(); + matrixStack(glCtx).set(glCtx.conversionMatrix4d); + bumpMatrixGeneration(glCtx); } } @@ -4539,7 +4555,10 @@ public class GLStateManager { } public static Matrix4fStack getMatrixStack() { - final GLContextState glCtx = ctx(); + return matrixStack(ctx()); + } + + private static Matrix4fStack matrixStack(GLContextState glCtx) { switch (glCtx.matrixMode.getMode()) { case GL11.GL_MODELVIEW -> { return glCtx.modelViewMatrix; @@ -4548,19 +4567,18 @@ public class GLStateManager { return glCtx.projectionMatrix; } case GL11.GL_TEXTURE -> { - return glCtx.textures.getTextureUnitMatrix(getActiveTextureUnit()); + return glCtx.textures.getTextureUnitMatrix(glCtx.activeTextureUnit.getValue()); } default -> throw new IllegalStateException("Unknown matrix mode: " + glCtx.matrixMode.getMode()); } } /** Bump the generation counter for the currently active matrix mode. */ - private static void bumpMatrixGeneration() { - bumpMatrixGeneration(true); + private static void bumpMatrixGeneration(GLContextState glCtx) { + bumpMatrixGeneration(glCtx, true); } - private static void bumpMatrixGeneration(boolean linearChanged) { - final GLContextState glCtx = ctx(); + private static void bumpMatrixGeneration(GLContextState glCtx, boolean linearChanged) { switch (glCtx.matrixMode.getMode()) { case GL11.GL_MODELVIEW -> { glCtx.mvGeneration++; @@ -4572,7 +4590,8 @@ public class GLStateManager { } public static void glLoadIdentity() { - beforeMatrixChange(); + final GLContextState glCtx = ctx(); + beforeMatrixChange(glCtx); final RecordMode mode = DisplayListManager.getRecordMode(); if (mode != RecordMode.NONE) { DisplayListManager.recordLoadIdentity(); @@ -4581,62 +4600,66 @@ public class GLStateManager { } } if (isCachingEnabled()) { - getMatrixStack().identity(); - bumpMatrixGeneration(); + matrixStack(glCtx).identity(); + bumpMatrixGeneration(glCtx); } } public static void glTranslatef(float x, float y, float z) { - beforeMatrixChange(); + final GLContextState glCtx = ctx(); + beforeMatrixChange(glCtx); if (DisplayListManager.isRecording()) { DisplayListManager.applyMatrixTranslation(x, y, z); return; } if (isCachingEnabled()) { - getMatrixStack().translate(x, y, z); - bumpMatrixGeneration(false); + matrixStack(glCtx).translate(x, y, z); + bumpMatrixGeneration(glCtx, false); } } public static void glTranslated(double x, double y, double z) { - beforeMatrixChange(); + final GLContextState glCtx = ctx(); + beforeMatrixChange(glCtx); if (DisplayListManager.isRecording()) { DisplayListManager.applyMatrixTranslation((float) x, (float) y, (float) z); return; } if (isCachingEnabled()) { - getMatrixStack().translate((float) x, (float) y, (float) z); - bumpMatrixGeneration(false); + matrixStack(glCtx).translate((float) x, (float) y, (float) z); + bumpMatrixGeneration(glCtx, false); } } public static void glScalef(float x, float y, float z) { - beforeMatrixChange(); + final GLContextState glCtx = ctx(); + beforeMatrixChange(glCtx); if (DisplayListManager.isRecording()) { DisplayListManager.applyMatrixScale(x, y, z); return; } if (isCachingEnabled()) { - getMatrixStack().scale(x, y, z); - bumpMatrixGeneration(); + matrixStack(glCtx).scale(x, y, z); + bumpMatrixGeneration(glCtx); } } public static void glScaled(double x, double y, double z) { - beforeMatrixChange(); + final GLContextState glCtx = ctx(); + beforeMatrixChange(glCtx); if (DisplayListManager.isRecording()) { DisplayListManager.applyMatrixScale((float) x, (float) y, (float) z); return; } if (isCachingEnabled()) { - getMatrixStack().scale((float) x, (float) y, (float) z); - bumpMatrixGeneration(); + matrixStack(glCtx).scale((float) x, (float) y, (float) z); + bumpMatrixGeneration(glCtx); } } public static void glMultMatrix(FloatBuffer floatBuffer) { - beforeMatrixChange(); final GLContextState glCtx = ctx(); + beforeMatrixChange(glCtx); glCtx.multMatrix.set(floatBuffer); final int currentMode = glCtx.matrixMode.getMode(); @@ -4645,22 +4668,23 @@ public class GLStateManager { return; } if (isCachingEnabled()) { - getMatrixStack().mul(glCtx.multMatrix); - bumpMatrixGeneration(); + matrixStack(glCtx).mul(glCtx.multMatrix); + bumpMatrixGeneration(glCtx); } } public static void applyMultMatrix(Matrix4f multMatrix) { - beforeMatrixChange(); + final GLContextState glCtx = ctx(); + beforeMatrixChange(glCtx); if (isCachingEnabled()) { - getMatrixStack().mul(multMatrix); - bumpMatrixGeneration(); + matrixStack(glCtx).mul(multMatrix); + bumpMatrixGeneration(glCtx); } } public static void glMultMatrix(DoubleBuffer matrix) { - beforeMatrixChange(); final GLContextState glCtx = ctx(); + beforeMatrixChange(glCtx); glCtx.conversionMatrix4d.set(matrix); glCtx.conversionMatrix4f.set(glCtx.conversionMatrix4d); @@ -4669,13 +4693,14 @@ public class GLStateManager { return; } if (isCachingEnabled()) { - getMatrixStack().mul(glCtx.conversionMatrix4f); - bumpMatrixGeneration(); + matrixStack(glCtx).mul(glCtx.conversionMatrix4f); + bumpMatrixGeneration(glCtx); } } public static void glRotatef(float angle, float x, float y, float z) { - beforeMatrixChange(); + final GLContextState glCtx = ctx(); + beforeMatrixChange(glCtx); final float lenSq = x * x + y * y + z * z; if (lenSq == 0.0f) return; @@ -4692,13 +4717,14 @@ public class GLStateManager { return; } if (isCachingEnabled()) { - getMatrixStack().rotate(angle, x, y, z); - bumpMatrixGeneration(); + matrixStack(glCtx).rotate(angle, x, y, z); + bumpMatrixGeneration(glCtx); } } public static void glRotated(double angle, double x, double y, double z) { - beforeMatrixChange(); + final GLContextState glCtx = ctx(); + beforeMatrixChange(glCtx); final double lenSq = x * x + y * y + z * z; if (lenSq == 0.0) return; @@ -4715,32 +4741,34 @@ public class GLStateManager { return; } if (isCachingEnabled()) { - getMatrixStack().rotate((float) angle, (float) x, (float) y, (float) z); - bumpMatrixGeneration(); + matrixStack(glCtx).rotate((float) angle, (float) x, (float) y, (float) z); + bumpMatrixGeneration(glCtx); } } public static void glOrtho(double left, double right, double bottom, double top, double zNear, double zFar) { - beforeMatrixChange(); + final GLContextState glCtx = ctx(); + beforeMatrixChange(glCtx); if (DisplayListManager.isRecording()) { DisplayListManager.updateRelativeTransformOrtho(left, right, bottom, top, zNear, zFar); return; } if (isCachingEnabled()) { - getMatrixStack().ortho((float) left, (float) right, (float) bottom, (float) top, (float) zNear, (float) zFar); - bumpMatrixGeneration(); + matrixStack(glCtx).ortho((float) left, (float) right, (float) bottom, (float) top, (float) zNear, (float) zFar); + bumpMatrixGeneration(glCtx); } } public static void glFrustum(double left, double right, double bottom, double top, double zNear, double zFar) { - beforeMatrixChange(); + final GLContextState glCtx = ctx(); + beforeMatrixChange(glCtx); if (DisplayListManager.isRecording()) { DisplayListManager.updateRelativeTransformFrustum(left, right, bottom, top, zNear, zFar); return; } if (isCachingEnabled()) { - getMatrixStack().frustum((float) left, (float) right, (float) bottom, (float) top, (float) zNear, (float) zFar); - bumpMatrixGeneration(); + matrixStack(glCtx).frustum((float) left, (float) right, (float) bottom, (float) top, (float) zNear, (float) zFar); + bumpMatrixGeneration(glCtx); } } @@ -4755,7 +4783,7 @@ public class GLStateManager { // Only track stack on main thread (splash thread has separate GL context) if (isCachingEnabled()) { try { - getMatrixStack().pushMatrix(); + matrixStack(ctx()).pushMatrix(); } catch (IllegalStateException ignored) { if (initConfig != null && initConfig.isLwjglDebug()) LOGGER.warn("Matrix stack overflow ", new Throwable()); } @@ -4763,7 +4791,8 @@ public class GLStateManager { } public static void glPopMatrix() { - beforeMatrixChange(); + final GLContextState glCtx = ctx(); + beforeMatrixChange(glCtx); final RecordMode mode = DisplayListManager.getRecordMode(); if (mode != RecordMode.NONE) { DisplayListManager.recordPopMatrix(); // Handles flush + relativeTransform stack + lastRecordedTransform sync @@ -4774,8 +4803,8 @@ public class GLStateManager { // Only track stack on main thread (splash thread has separate GL context) if (isCachingEnabled()) { try { - getMatrixStack().popMatrix(); - bumpMatrixGeneration(); + matrixStack(glCtx).popMatrix(); + bumpMatrixGeneration(glCtx); } catch (IllegalStateException ignored) { if (initConfig != null && initConfig.isLwjglDebug()) LOGGER.warn("Matrix stack underflow ", new Throwable()); } diff --git a/glsm/src/main/java/com/gtnewhorizons/angelica/glsm/stacks/CowDepths.java b/glsm/src/main/java/com/gtnewhorizons/angelica/glsm/stacks/CowDepths.java index 680c64eff..e30e3a4d9 100644 --- a/glsm/src/main/java/com/gtnewhorizons/angelica/glsm/stacks/CowDepths.java +++ b/glsm/src/main/java/com/gtnewhorizons/angelica/glsm/stacks/CowDepths.java @@ -35,12 +35,14 @@ public final class CowDepths { } public int claim(int depth) { - if (depth <= 0) return -1; - if (pointer > 0 && slotDepth[pointer - 1] == depth) return -1; slotDepth[pointer] = depth; return pointer++; } + public boolean claimedAt(int depth) { + return pointer > 0 && slotDepth[pointer - 1] == depth; + } + public int claimUnconditional() { slotDepth[pointer] = -1; return pointer++; diff --git a/glsm/src/main/java/com/gtnewhorizons/angelica/glsm/stacks/CowStateStack.java b/glsm/src/main/java/com/gtnewhorizons/angelica/glsm/stacks/CowStateStack.java index 44925b308..ae6280711 100644 --- a/glsm/src/main/java/com/gtnewhorizons/angelica/glsm/stacks/CowStateStack.java +++ b/glsm/src/main/java/com/gtnewhorizons/angelica/glsm/stacks/CowStateStack.java @@ -51,11 +51,10 @@ public interface CowStateStack extends IStateStack { final CowDepths d = cowDepths(); final GLContextState o = d.owner; if (o == null) return; - final int s = d.claim(o.attribDepth); - if (s >= 0) { - captureSlot(s); - GLStateManager.registerModifiedState(o, d.id); - } + final int depth = o.attribDepth; + if (depth == 0 || d.claimedAt(depth) || !o.savesState(d.id)) return; + captureSlot(d.claim(depth)); + GLStateManager.registerModifiedState(o, d.id); } @Override diff --git a/glsm/src/main/java/com/gtnewhorizons/angelica/glsm/stacks/TextureUnitBooleanStateStack.java b/glsm/src/main/java/com/gtnewhorizons/angelica/glsm/stacks/TextureUnitBooleanStateStack.java index 26d165aab..ffe064298 100644 --- a/glsm/src/main/java/com/gtnewhorizons/angelica/glsm/stacks/TextureUnitBooleanStateStack.java +++ b/glsm/src/main/java/com/gtnewhorizons/angelica/glsm/stacks/TextureUnitBooleanStateStack.java @@ -26,8 +26,8 @@ public final class TextureUnitBooleanStateStack extends BooleanStateStack { public void setEnabled(boolean enabled) { if (!GLStateManager.isCachingEnabled() || enabled != this.enabled) { GLStateManager.beforeUncapturedTextureUnitChange(glCap, unitIndex); + beforeModify(); } - beforeModify(); setEnabledWithUnitSwitch(enabled); } diff --git a/glsm/src/test/java/com/gtnewhorizons/angelica/glsm/GLSM_PerThread_UnitTest.java b/glsm/src/test/java/com/gtnewhorizons/angelica/glsm/GLSM_PerThread_UnitTest.java index 287e039c6..adb690c69 100644 --- a/glsm/src/test/java/com/gtnewhorizons/angelica/glsm/GLSM_PerThread_UnitTest.java +++ b/glsm/src/test/java/com/gtnewhorizons/angelica/glsm/GLSM_PerThread_UnitTest.java @@ -78,6 +78,22 @@ public class GLSM_PerThread_UnitTest { assertEquals(n + 1, distinct.size(), "every thread must own a distinct holder"); } + @Test + void ctxFollowsTheBindingOnTheMainThread() { + assertSame(GLStateManager.getMainThread(), Thread.currentThread(), "test must run on the GLSM main thread"); + final GLContextState primary = GLStateManager.ctx(); + assertSame(primary, GLStateManager.ctx()); + final GLContextState worker = GLStateManager.enterWorkerContext(); + try { + assertNotSame(primary, worker); + assertSame(worker, GLStateManager.ctx()); + assertSame(worker, GLStateManager.ctx()); + } finally { + GLStateManager.exitWorkerContext(); + } + assertSame(primary, GLStateManager.ctx()); + } + @Test void matrixStackAndMvGenerationArePerThread() throws Throwable { final int n = 6; diff --git a/glsm/src/test/java/com/gtnewhorizons/angelica/glsm/GLSM_StateSet_GLTest.java b/glsm/src/test/java/com/gtnewhorizons/angelica/glsm/GLSM_StateSet_GLTest.java index 2d93053dc..3838d8f62 100644 --- a/glsm/src/test/java/com/gtnewhorizons/angelica/glsm/GLSM_StateSet_GLTest.java +++ b/glsm/src/test/java/com/gtnewhorizons/angelica/glsm/GLSM_StateSet_GLTest.java @@ -358,6 +358,127 @@ public class GLSM_StateSet_GLTest { } } + @Test + void nonMemberMutationsInsideBracketSaveAndDiscardNothing() { + try { + GLStateManager.enableAlphaTest(); + GLStateManager.glAlphaFunc(GL11.GL_GREATER, 0.5f); + GLStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ZERO); + GLStateManager.glDepthFunc(GL11.GL_LEQUAL); + + final int d = GLStateManager.pushState(StateSet.CUTOUT); + final long discardsBefore = GLStateManager.attribDiscards; + try { + final long savedBefore = GLStateManager.attribSlotsSaved; + GLStateManager.tryBlendFuncSeparate(GL11.GL_DST_COLOR, GL11.GL_ZERO, GL11.GL_DST_COLOR, GL11.GL_ZERO); + GLStateManager.glDepthFunc(GL11.GL_ALWAYS); + GLStateManager.glActiveTexture(GL13.GL_TEXTURE2); + GLStateManager.glActiveTexture(GL13.GL_TEXTURE0); + assertEquals(savedBefore, GLStateManager.attribSlotsSaved, "non-member mutations must not save slots"); + } finally { + GLStateManager.popStateTo(d); + } + + assertEquals(discardsBefore, GLStateManager.attribDiscards, "non-member mutations must not leave slots to discard"); + assertEquals(GL11.GL_DST_COLOR, GLStateManager.getBlendState().getSrcRgb(), "cache blend src rgb - not a CUTOUT member, must stay toggled"); + } finally { + GLStateManager.disableAlphaTest(); + GLStateManager.glAlphaFunc(GL11.GL_ALWAYS, 0.0f); + GLStateManager.tryBlendFuncSeparate(GL11.GL_ONE, GL11.GL_ZERO, GL11.GL_ONE, GL11.GL_ZERO); + GLStateManager.glDepthFunc(GL11.GL_LESS); + GLStateManager.glActiveTexture(GL13.GL_TEXTURE0); + } + } + + @Test + void unchangedSettersSaveNothing() { + try { + GLStateManager.enableAlphaTest(); + GLStateManager.glAlphaFunc(GL11.GL_GREATER, 0.5f); + GLStateManager.glDepthFunc(GL11.GL_LEQUAL); + GLStateManager.glDepthMask(true); + GLStateManager.glColorMask(true, true, true, true); + GLStateManager.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); + GLStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ZERO); + GLStateManager.glBlendColor(0.1f, 0.2f, 0.3f, 0.4f); + GLStateManager.glBlendEquation(GL14.GL_FUNC_ADD); + GLStateManager.glActiveTexture(GL13.GL_TEXTURE1); + GLStateManager.enableTexture(); + GLStateManager.glActiveTexture(GL13.GL_TEXTURE0); + + final int d = GLStateManager.pushState(StateSet.forMask(GL11.GL_ALL_ATTRIB_BITS)); + try { + final long savedBefore = GLStateManager.attribSlotsSaved; + GLStateManager.glAlphaFunc(GL11.GL_GREATER, 0.5f); + GLStateManager.glDepthFunc(GL11.GL_LEQUAL); + GLStateManager.glDepthMask(true); + GLStateManager.glColorMask(true, true, true, true); + GLStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ZERO); + GLStateManager.glBlendColor(0.1f, 0.2f, 0.3f, 0.4f); + GLStateManager.glBlendEquation(GL14.GL_FUNC_ADD); + GLStateManager.glBlendEquationSeparate(GL14.GL_FUNC_ADD, GL14.GL_FUNC_ADD); + GLStateManager.glActiveTexture(GL13.GL_TEXTURE1); + GLStateManager.enableTexture(); + GLStateManager.glActiveTexture(GL13.GL_TEXTURE0); + assertEquals(1, GLStateManager.attribSlotsSaved - savedBefore, "only the active unit change may save a slot"); + } finally { + GLStateManager.popStateTo(d); + } + + GLStateManager.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); + final int d2 = GLStateManager.pushState(StateSet.forMask(GL11.GL_ALL_ATTRIB_BITS)); + try { + final long savedBefore = GLStateManager.attribSlotsSaved; + GLStateManager.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); + assertEquals(0, GLStateManager.attribSlotsSaved - savedBefore, "unchanged glBlendFunc must not save a slot"); + } finally { + GLStateManager.popStateTo(d2); + } + } finally { + GLStateManager.disableAlphaTest(); + GLStateManager.glAlphaFunc(GL11.GL_ALWAYS, 0.0f); + GLStateManager.disableBlend(); + GLStateManager.tryBlendFuncSeparate(GL11.GL_ONE, GL11.GL_ZERO, GL11.GL_ONE, GL11.GL_ZERO); + GLStateManager.glDepthFunc(GL11.GL_LESS); + GLStateManager.glDepthMask(true); + GLStateManager.glColorMask(true, true, true, true); + GLStateManager.glBlendColor(0.0f, 0.0f, 0.0f, 0.0f); + GLStateManager.glBlendEquation(GL14.GL_FUNC_ADD); + GLStateManager.glActiveTexture(GL13.GL_TEXTURE1); + GLStateManager.disableTexture(); + GLStateManager.glActiveTexture(GL13.GL_TEXTURE0); + } + } + + @Test + void bracketDoesNotInheritMembersOfAnEarlierBracketAtItsDepth() { + try { + for (boolean nested : new boolean[] {false, true}) { + GLStateManager.tryBlendFuncSeparate(GL11.GL_ONE, GL11.GL_ZERO, GL11.GL_ONE, GL11.GL_ZERO); + GLStateManager.glDepthFunc(GL11.GL_LESS); + final int outer = nested ? GLStateManager.pushState(StateSet.CULL) : GLStateManager.getAttribDepth(); + try { + GLStateManager.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS); + GLStateManager.glPopAttrib(); + final int d = GLStateManager.pushState(StateSet.CUTOUT); + try { + final long savedBefore = GLStateManager.attribSlotsSaved; + GLStateManager.tryBlendFuncSeparate(GL11.GL_DST_COLOR, GL11.GL_ZERO, GL11.GL_DST_COLOR, GL11.GL_ZERO); + GLStateManager.glDepthFunc(GL11.GL_ALWAYS); + assertEquals(savedBefore, GLStateManager.attribSlotsSaved, "nested=" + nested); + } finally { + GLStateManager.popStateTo(d); + } + } finally { + GLStateManager.popStateTo(outer); + } + } + } finally { + GLStateManager.tryBlendFuncSeparate(GL11.GL_ONE, GL11.GL_ZERO, GL11.GL_ONE, GL11.GL_ZERO); + GLStateManager.glDepthFunc(GL11.GL_LESS); + } + } + @Test void cullFaceModeRestoredThroughCullBracket() { try { diff --git a/src/main/java/com/gtnewhorizons/angelica/config/AngelicaConfig.java b/src/main/java/com/gtnewhorizons/angelica/config/AngelicaConfig.java index 9da56bb78..fb80eae85 100644 --- a/src/main/java/com/gtnewhorizons/angelica/config/AngelicaConfig.java +++ b/src/main/java/com/gtnewhorizons/angelica/config/AngelicaConfig.java @@ -176,11 +176,6 @@ public class AngelicaConfig { @Config.RequiresMcRestart public static boolean shaderParityFlip; - @Config.Comment("Skip the end-of-frame glFlush before the buffer swap [Experimental]") - @Config.DefaultBoolean(false) - @Config.RequiresMcRestart - public static boolean skipEndOfFrameFlush; - @Config.Comment("Cache the vanilla skull mesh per skull type/player skin and batch skull draws") @Config.DefaultBoolean(true) @Config.RequiresMcRestart diff --git a/src/main/java/com/gtnewhorizons/angelica/mixins/Mixins.java b/src/main/java/com/gtnewhorizons/angelica/mixins/Mixins.java index a3e5dcfe8..41fab590f 100644 --- a/src/main/java/com/gtnewhorizons/angelica/mixins/Mixins.java +++ b/src/main/java/com/gtnewhorizons/angelica/mixins/Mixins.java @@ -206,9 +206,8 @@ public enum Mixins implements IMixins { ) ), - ANGELICA_SKIP_END_FRAME_FLUSH(new MixinBuilder("Skip the end-of-frame glFlush before the buffer swap") + ANGELICA_SKIP_END_FRAME_FLUSH(new MixinBuilder("Skip vanilla's end-of-frame glFlush; the buffer swap flushes") .setPhase(Phase.EARLY) - .setApplyIf(() -> AngelicaConfig.skipEndOfFrameFlush) .addClientMixins( "angelica.MixinMinecraft_SkipEndFrameFlush" ) diff --git a/src/main/java/net/coderbot/iris/layer/GbufferPrograms.java b/src/main/java/net/coderbot/iris/layer/GbufferPrograms.java index 35efa2587..85f824c68 100644 --- a/src/main/java/net/coderbot/iris/layer/GbufferPrograms.java +++ b/src/main/java/net/coderbot/iris/layer/GbufferPrograms.java @@ -4,6 +4,7 @@ import lombok.Getter; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import net.coderbot.iris.Iris; import net.coderbot.iris.gbuffer_overrides.matching.SpecialCondition; +import com.gtnewhorizons.angelica.glsm.DisplayListManager; import com.gtnewhorizons.angelica.glsm.GLStateManager; import com.gtnewhorizons.angelica.glsm.ffp.FfpExtendedAttribs; import com.gtnewhorizons.angelica.iris.IrisDisplayListState; @@ -150,6 +151,10 @@ public class GbufferPrograms { GLStateManager.enableAlphaTest(); GLStateManager.glAlphaFunc(GL11.GL_GREATER, 0.1F); + if (DisplayListManager.getRecordMode() == DisplayListManager.RecordMode.NONE) { + GLStateManager.getTextures().getTextureUnitStates(1).enable(); + return; + } final int previousUnit = GLStateManager.getActiveTextureUnitForServerState(); GLStateManager.glActiveTexture(GL13.GL_TEXTURE1); GLStateManager.enableTexture(); diff --git a/src/test/java/com/gtnewhorizons/angelica/iris/IrisDisplayListStateTest.java b/src/test/java/com/gtnewhorizons/angelica/iris/IrisDisplayListStateTest.java index 7388a35b6..6024ffd1c 100644 --- a/src/test/java/com/gtnewhorizons/angelica/iris/IrisDisplayListStateTest.java +++ b/src/test/java/com/gtnewhorizons/angelica/iris/IrisDisplayListStateTest.java @@ -133,6 +133,31 @@ class IrisDisplayListStateTest { } } + @Test + void cutoutDefaultsOutsideListEnableLightmapWithoutSwitchingUnit() { + GLStateManager.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS); + try { + GLStateManager.enableAlphaTest(); + GLStateManager.glAlphaFunc(GL11.GL_GREATER, 0.1f); + GLStateManager.glActiveTexture(GL13.GL_TEXTURE1); + GLStateManager.disableTexture(); + GLStateManager.glActiveTexture(GL13.GL_TEXTURE3); + final int d = GLStateManager.pushState(StateSet.CUTOUT); + try { + final long savedBefore = GLStateManager.attribSlotsSaved; + GbufferPrograms.setCutoutDefaults(); + assertEquals(1, GLStateManager.attribSlotsSaved - savedBefore); + assertTrue(GLStateManager.getTextures().getTextureUnitStates(1).isEnabled()); + assertEquals(3, GLStateManager.getActiveTextureUnit()); + } finally { + GLStateManager.popStateTo(d); + } + assertFalse(GLStateManager.getTextures().getTextureUnitStates(1).isEnabled()); + } finally { + GLStateManager.glPopAttrib(); + } + } + @Test void nestedBlendScopesRestorePlaybackValuesEvenIfCompileTimePopWasANoop() { GLStateManager.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS);