mirror of
https://github.com/GTNewHorizons/Angelica.git
synced 2026-10-25 20:22:22 +00:00
Fix HUD caching flicker and match non-cached GL state (#2201)
This commit is contained in:
1 parent
fe82cd320a
commit
7cd97d1216
33 files changed
+801
-175
No files matched your search
@@ -21,6 +21,7 @@ import com.gtnewhorizons.angelica.glsm.stacks.MaterialStateStack;
|
||||
import com.gtnewhorizons.angelica.glsm.stacks.MatrixModeStack;
|
||||
import com.gtnewhorizons.angelica.glsm.stacks.PointStateStack;
|
||||
import com.gtnewhorizons.angelica.glsm.stacks.PolygonStateStack;
|
||||
import com.gtnewhorizons.angelica.glsm.stacks.RetainedState;
|
||||
import com.gtnewhorizons.angelica.glsm.stacks.ScissorStateStack;
|
||||
import com.gtnewhorizons.angelica.glsm.stacks.StackIdAllocator;
|
||||
import com.gtnewhorizons.angelica.glsm.stacks.StencilStateStack;
|
||||
@@ -106,6 +107,7 @@ public class GLContextState {
|
||||
public int maxBoundTextureUnit = 0;
|
||||
public int maxBoundImageUnit = 0;
|
||||
public final StateSet[] attribSets = new StateSet[GLStateManager.MAX_ATTRIB_STACK_DEPTH];
|
||||
public RetainedState retainedOwner;
|
||||
public int attribDepth = 0;
|
||||
|
||||
public boolean savesState(int id) {
|
||||
|
||||
@@ -49,6 +49,7 @@ import com.gtnewhorizons.angelica.glsm.stacks.MaterialStateStack;
|
||||
import com.gtnewhorizons.angelica.glsm.stacks.MatrixModeStack;
|
||||
import com.gtnewhorizons.angelica.glsm.stacks.PointStateStack;
|
||||
import com.gtnewhorizons.angelica.glsm.stacks.PolygonStateStack;
|
||||
import com.gtnewhorizons.angelica.glsm.stacks.RetainedState;
|
||||
import com.gtnewhorizons.angelica.glsm.stacks.ScissorStateStack;
|
||||
import com.gtnewhorizons.angelica.glsm.stacks.StackIdAllocator;
|
||||
import com.gtnewhorizons.angelica.glsm.stacks.StencilStateStack;
|
||||
@@ -313,6 +314,8 @@ public class GLStateManager {
|
||||
|
||||
// Software stack depths for FFP emulation
|
||||
public static final int MAX_ATTRIB_STACK_DEPTH = 32;
|
||||
public static final int RETAINED_SLOT = MAX_ATTRIB_STACK_DEPTH;
|
||||
public static final int STATE_SLOTS = MAX_ATTRIB_STACK_DEPTH + 1;
|
||||
public static final int MAX_MODELVIEW_STACK_DEPTH = 32 + 2;
|
||||
public static final int MAX_PROJECTION_STACK_DEPTH = 4;
|
||||
public static final int MAX_TEXTURE_STACK_DEPTH = 4;
|
||||
@@ -542,6 +545,7 @@ public class GLStateManager {
|
||||
final GLContextState glCtx = ctx();
|
||||
DisplayListManager.abortCompilation();
|
||||
glCtx.attribDepth = 0;
|
||||
glCtx.retainedOwner = null;
|
||||
for (int i = 0; i < glCtx.attribSets.length; i++) {
|
||||
glCtx.attribSets[i] = null;
|
||||
}
|
||||
@@ -1604,58 +1608,25 @@ public class GLStateManager {
|
||||
}
|
||||
|
||||
public static void glBlendFunc(int srcFactor, int dstFactor) {
|
||||
final GLContextState glCtx = ctx();
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
DisplayListManager.recordBlendFunc(srcFactor, dstFactor, srcFactor, dstFactor);
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
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();
|
||||
tryBlendFuncSeparate(srcFactor, dstFactor, srcFactor, dstFactor);
|
||||
}
|
||||
|
||||
private static void issueBlendFunc(BlendStateStack blend) {
|
||||
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);
|
||||
if (GLSMHooks.BLEND_FUNC_CHANGE.hasListeners()) {
|
||||
GLSMHooks.blendFuncChangeEvent.srcRgb = srcFactor;
|
||||
GLSMHooks.blendFuncChangeEvent.dstRgb = dstFactor;
|
||||
GLSMHooks.blendFuncChangeEvent.srcAlpha = GL11.GL_ONE;
|
||||
GLSMHooks.blendFuncChangeEvent.dstAlpha = GL11.GL_ONE_MINUS_SRC_ALPHA;
|
||||
GLSMHooks.BLEND_FUNC_CHANGE.post(GLSMHooks.blendFuncChangeEvent);
|
||||
}
|
||||
postVanillaBlendChangeIfMoved(snapshotted);
|
||||
return;
|
||||
RENDER_BACKEND.blendFuncSeparate(blend.getSrcRgb(), blend.getDstRgb(), GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA);
|
||||
} else {
|
||||
RENDER_BACKEND.blendFuncSeparate(blend.getSrcRgb(), blend.getDstRgb(), blend.getSrcAlpha(), blend.getDstAlpha());
|
||||
}
|
||||
final boolean bypass = !caching;
|
||||
if (bypass
|
||||
|| glCtx.blendState.getSrcRgb() != srcFactor
|
||||
|| glCtx.blendState.getDstRgb() != dstFactor
|
||||
|| 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);
|
||||
if (GLSMHooks.BLEND_FUNC_CHANGE.hasListeners()) {
|
||||
GLSMHooks.blendFuncChangeEvent.srcRgb = srcFactor;
|
||||
GLSMHooks.blendFuncChangeEvent.dstRgb = dstFactor;
|
||||
GLSMHooks.blendFuncChangeEvent.srcAlpha = srcFactor;
|
||||
GLSMHooks.blendFuncChangeEvent.dstAlpha = dstFactor;
|
||||
GLSMHooks.BLEND_FUNC_CHANGE.post(GLSMHooks.blendFuncChangeEvent);
|
||||
}
|
||||
}
|
||||
postVanillaBlendChangeIfMoved(snapshotted);
|
||||
}
|
||||
|
||||
public static void setHudCacheOverride(boolean enabled) {
|
||||
if (GLSMConfig.hudCacheOverride == enabled) return;
|
||||
GLSMConfig.hudCacheOverride = enabled;
|
||||
final DeferredBlendHandler bh = GLSMHooks.blendHandler;
|
||||
if (bh != null && bh.isOverrideHeld()) return;
|
||||
final BlendStateStack blend = ctx().blendState;
|
||||
issueBlendFunc(blend);
|
||||
blend.clearFuncUnknownState();
|
||||
}
|
||||
|
||||
public static void glBlendEquation(int mode) {
|
||||
@@ -1707,22 +1678,19 @@ public class GLStateManager {
|
||||
postVanillaBlendChangeIfMoved(snapshotted);
|
||||
return;
|
||||
}
|
||||
if (GLSMConfig.hudCacheOverride && dstAlpha != GL11.GL_ONE_MINUS_SRC_ALPHA) {
|
||||
srcAlpha = GL11.GL_ONE;
|
||||
dstAlpha = GL11.GL_ONE_MINUS_SRC_ALPHA;
|
||||
}
|
||||
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);
|
||||
issueBlendFunc(glCtx.blendState);
|
||||
if (GLSMHooks.BLEND_FUNC_CHANGE.hasListeners()) {
|
||||
final boolean hudCache = GLSMConfig.hudCacheOverride;
|
||||
GLSMHooks.blendFuncChangeEvent.srcRgb = srcRgb;
|
||||
GLSMHooks.blendFuncChangeEvent.dstRgb = dstRgb;
|
||||
GLSMHooks.blendFuncChangeEvent.srcAlpha = srcAlpha;
|
||||
GLSMHooks.blendFuncChangeEvent.dstAlpha = dstAlpha;
|
||||
GLSMHooks.blendFuncChangeEvent.srcAlpha = hudCache ? GL11.GL_ONE : srcAlpha;
|
||||
GLSMHooks.blendFuncChangeEvent.dstAlpha = hudCache ? GL11.GL_ONE_MINUS_SRC_ALPHA : dstAlpha;
|
||||
GLSMHooks.BLEND_FUNC_CHANGE.post(GLSMHooks.blendFuncChangeEvent);
|
||||
}
|
||||
}
|
||||
@@ -4177,6 +4145,89 @@ public class GLStateManager {
|
||||
}
|
||||
}
|
||||
|
||||
public static void retainModifiedState(int depth, RetainedState out) {
|
||||
final GLContextState glCtx = ctx();
|
||||
if (depth < 0 || depth != glCtx.attribDepth - 1) {
|
||||
throw new IllegalStateException("retainModifiedState: depth " + depth + " is not the open push (attrib depth " + glCtx.attribDepth + ")");
|
||||
}
|
||||
glCtx.retainedOwner = out;
|
||||
final int count = glCtx.modifiedCount[depth];
|
||||
final int[] ids = glCtx.modifiedIds[depth];
|
||||
final CowStateStack<?>[] stackById = glCtx.stackById;
|
||||
out.ensureCapacity(count);
|
||||
for (int i = 0; i < count; i++) {
|
||||
final int id = ids[i];
|
||||
stackById[id].captureSlot(RETAINED_SLOT);
|
||||
out.ids[i] = id;
|
||||
}
|
||||
out.count = count;
|
||||
out.program = glCtx.activeProgram;
|
||||
out.programGen = programLifetimeGeneration;
|
||||
}
|
||||
|
||||
public static void applyRetainedState(RetainedState in) {
|
||||
final GLContextState glCtx = ctx();
|
||||
if (glCtx.retainedOwner != in) return;
|
||||
final CowStateStack<?>[] stackById = glCtx.stackById;
|
||||
final byte[] kindById = glCtx.kindById;
|
||||
final int[] ids = in.ids;
|
||||
final int count = in.count;
|
||||
int first = 0;
|
||||
while (first < count && !CowDispatch.slotChanged(kindById[ids[first]], stackById[ids[first]], RETAINED_SLOT)) first++;
|
||||
if (first < count) applyRetainedChanges(glCtx, in, first);
|
||||
if (in.program != glCtx.activeProgram && (in.program == 0 || in.programGen == programLifetimeGeneration)) glUseProgram(in.program);
|
||||
}
|
||||
|
||||
private static void applyRetainedChanges(GLContextState glCtx, RetainedState in, int first) {
|
||||
beforeUncapturedStateChange();
|
||||
final boolean blendSnapshotted = snapshotVanillaBlendFunc();
|
||||
final int alphaFuncId = glCtx.alphaState.stackId();
|
||||
final int alphaTestId = glCtx.alphaTest.stackId();
|
||||
boolean alphaChanged = false;
|
||||
final boolean prevPoppingAttributes = glCtx.poppingAttributes;
|
||||
glCtx.poppingAttributes = true;
|
||||
try {
|
||||
final CowStateStack<?>[] stackById = glCtx.stackById;
|
||||
final int[] restoreBitById = glCtx.restoreBitById;
|
||||
final int[] restoreUnitById = glCtx.restoreUnitById;
|
||||
final byte[] kindById = glCtx.kindById;
|
||||
int changed = 0;
|
||||
long unitsChanged = 0L;
|
||||
for (int i = first; i < in.count; i++) {
|
||||
final int id = in.ids[i];
|
||||
final CowStateStack<?> cow = stackById[id];
|
||||
final byte kind = kindById[id];
|
||||
if (!CowDispatch.slotChanged(kind, cow, RETAINED_SLOT)) continue;
|
||||
cow.beforeModify();
|
||||
final int bit = restoreBitById[id];
|
||||
if (bit != 0) {
|
||||
changed |= bit;
|
||||
final int unit = restoreUnitById[id];
|
||||
if (unit >= 0) unitsChanged |= 1L << Math.min(unit, 63);
|
||||
}
|
||||
CowDispatch.restoreSlot(kind, cow, RETAINED_SLOT);
|
||||
if (id == alphaFuncId || id == alphaTestId) alphaChanged = true;
|
||||
}
|
||||
glCtx.restoreChangedMask = changed;
|
||||
glCtx.restoreUnitChangedMask = unitsChanged;
|
||||
issueRestoredBackendState(glCtx, -1);
|
||||
glCtx.lightingGeneration++;
|
||||
glCtx.fragmentGeneration++;
|
||||
glCtx.colorGeneration++;
|
||||
glCtx.ffp.normalGeneration++;
|
||||
glCtx.ffp.texCoordGeneration++;
|
||||
glCtx.dirtyColorAttrib = true;
|
||||
glCtx.dirtyNormalAttrib = true;
|
||||
glCtx.dirtyTexCoordAttrib = true;
|
||||
postVanillaBlendChangeIfMoved(blendSnapshotted);
|
||||
} finally {
|
||||
glCtx.poppingAttributes = prevPoppingAttributes;
|
||||
}
|
||||
if (alphaChanged && GLSMHooks.ALPHA_STATE_CHANGE.hasListeners()) {
|
||||
GLSMHooks.ALPHA_STATE_CHANGE.post(GLSMHooks.alphaStateChangeEvent);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isDepthColorOverridden() {
|
||||
final DeferredDepthColorHandler dch = GLSMHooks.depthColorHandler;
|
||||
return dch != null && dch.isOverrideHeld();
|
||||
@@ -4195,7 +4246,7 @@ public class GLStateManager {
|
||||
RENDER_BACKEND.depthMask(glCtx.depthState.isEnabled());
|
||||
RENDER_BACKEND.clearDepth(glCtx.depthState.getClearValue());
|
||||
|
||||
RENDER_BACKEND.blendFuncSeparate(glCtx.blendState.getSrcRgb(), glCtx.blendState.getDstRgb(), glCtx.blendState.getSrcAlpha(), glCtx.blendState.getDstAlpha());
|
||||
issueBlendFunc(glCtx.blendState);
|
||||
glCtx.blendState.clearFuncUnknownState();
|
||||
RENDER_BACKEND.blendEquationSeparate(glCtx.blendState.getEquationRgb(), glCtx.blendState.getEquationAlpha());
|
||||
RENDER_BACKEND.blendColor(glCtx.blendState.getBlendColorR(), glCtx.blendState.getBlendColorG(), glCtx.blendState.getBlendColorB(), glCtx.blendState.getBlendColorA());
|
||||
@@ -4256,12 +4307,7 @@ public class GLStateManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* After popping GLSM stacks, apply restored state to the GL driver.
|
||||
*/
|
||||
private static void applyRestoredState(StateSet set, boolean blendSnapshotted) {
|
||||
final GLContextState glCtx = ctx();
|
||||
final int restore = set.restore;
|
||||
private static void issueRestoredBackendState(GLContextState glCtx, int restore) {
|
||||
final int changed = glCtx.restoreChangedMask;
|
||||
if ((restore & StateSet.R_DEPTH) != 0 && (changed & StateSet.R_DEPTH) != 0) {
|
||||
attribValueRestores++;
|
||||
@@ -4280,7 +4326,7 @@ public class GLStateManager {
|
||||
attribValueRestores++;
|
||||
final DeferredBlendHandler restoreBlendHandler = GLSMHooks.blendHandler;
|
||||
if (restoreBlendHandler == null || !restoreBlendHandler.isOverrideHeld()) {
|
||||
RENDER_BACKEND.blendFuncSeparate(blend.getSrcRgb(), blend.getDstRgb(), blend.getSrcAlpha(), blend.getDstAlpha());
|
||||
issueBlendFunc(blend);
|
||||
attribBackendCalls++;
|
||||
blend.clearFuncUnknownState();
|
||||
}
|
||||
@@ -4377,6 +4423,16 @@ public class GLStateManager {
|
||||
attribBackendCalls++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* After popping GLSM stacks, apply restored state to the GL driver.
|
||||
*/
|
||||
private static void applyRestoredState(StateSet set, boolean blendSnapshotted) {
|
||||
final GLContextState glCtx = ctx();
|
||||
final int restore = set.restore;
|
||||
final int changed = glCtx.restoreChangedMask;
|
||||
issueRestoredBackendState(glCtx, restore);
|
||||
|
||||
final int bump = set.bump;
|
||||
final int depth = glCtx.attribDepth;
|
||||
|
||||
@@ -14,8 +14,8 @@ public final class AlphaStateStack extends AlphaState implements CowStateStack<A
|
||||
|
||||
public AlphaStateStack(int id) {
|
||||
cow.id = id;
|
||||
stack = new AlphaState[GLStateManager.MAX_ATTRIB_STACK_DEPTH];
|
||||
for (int i = 0; i < GLStateManager.MAX_ATTRIB_STACK_DEPTH; i++) {
|
||||
stack = new AlphaState[GLStateManager.STATE_SLOTS];
|
||||
for (int i = 0; i < GLStateManager.STATE_SLOTS; i++) {
|
||||
stack[i] = new AlphaState();
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,11 @@ public final class AlphaStateStack extends AlphaState implements CowStateStack<A
|
||||
return cow;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean slotChanged(int slot) {
|
||||
return VanillaStateLayer.isHeld(vanillaLayer) || !sameAs(stack[slot]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void captureSlot(int s) {
|
||||
VanillaStateLayer.capture(vanillaLayer, stack[s].set(this));
|
||||
|
||||
@@ -17,8 +17,8 @@ public final class BlendStateStack extends BlendState implements CowStateStack<B
|
||||
|
||||
public BlendStateStack(int id) {
|
||||
cow.id = id;
|
||||
stack = new BlendState[GLStateManager.MAX_ATTRIB_STACK_DEPTH];
|
||||
for (int i = 0; i < GLStateManager.MAX_ATTRIB_STACK_DEPTH; i++) {
|
||||
stack = new BlendState[GLStateManager.STATE_SLOTS];
|
||||
for (int i = 0; i < GLStateManager.STATE_SLOTS; i++) {
|
||||
stack[i] = new BlendState();
|
||||
}
|
||||
}
|
||||
@@ -28,6 +28,11 @@ public final class BlendStateStack extends BlendState implements CowStateStack<B
|
||||
return cow;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean slotChanged(int slot) {
|
||||
return funcUnknown || VanillaStateLayer.isHeld(vanillaLayer) || !sameAs(stack[slot]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void captureSlot(int s) {
|
||||
VanillaStateLayer.capture(vanillaLayer, stack[s].set(this));
|
||||
|
||||
@@ -44,7 +44,7 @@ public class BooleanStateStack extends BooleanState implements CowStateStack<Boo
|
||||
public BooleanStateStack(int glCap, boolean initialState, boolean ffpStateOnly) {
|
||||
super(glCap, ffpStateOnly);
|
||||
this.enabled = initialState;
|
||||
stack = new boolean[GLStateManager.MAX_ATTRIB_STACK_DEPTH];
|
||||
stack = new boolean[GLStateManager.STATE_SLOTS];
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -52,6 +52,11 @@ public class BooleanStateStack extends BooleanState implements CowStateStack<Boo
|
||||
return cow;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean slotChanged(int slot) {
|
||||
return stateUnknown || (vanillaLayer != null && vanillaLayer.isOverrideHeld()) || enabled != stack[slot];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void captureSlot(int slot) {
|
||||
stack[slot] = vanillaValue();
|
||||
|
||||
@@ -10,8 +10,8 @@ public final class Color4Stack extends Color4 implements CowStateStack<Color4Sta
|
||||
|
||||
public Color4Stack(int id) {
|
||||
cow.id = id;
|
||||
stack = new Color4[GLStateManager.MAX_ATTRIB_STACK_DEPTH];
|
||||
for (int i = 0; i < GLStateManager.MAX_ATTRIB_STACK_DEPTH; i++) {
|
||||
stack = new Color4[GLStateManager.STATE_SLOTS];
|
||||
for (int i = 0; i < GLStateManager.STATE_SLOTS; i++) {
|
||||
stack[i] = new Color4();
|
||||
}
|
||||
}
|
||||
@@ -33,6 +33,11 @@ public final class Color4Stack extends Color4 implements CowStateStack<Color4Sta
|
||||
return cow;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean slotChanged(int slot) {
|
||||
return !sameAs(stack[slot]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void captureSlot(int s) {
|
||||
stack[s].set(this);
|
||||
|
||||
@@ -15,8 +15,8 @@ public final class ColorMaskStack extends ColorMask implements CowStateStack<Col
|
||||
|
||||
public ColorMaskStack(int id) {
|
||||
cow.id = id;
|
||||
stack = new ColorMask[GLStateManager.MAX_ATTRIB_STACK_DEPTH];
|
||||
for (int i = 0; i < GLStateManager.MAX_ATTRIB_STACK_DEPTH; i++) {
|
||||
stack = new ColorMask[GLStateManager.STATE_SLOTS];
|
||||
for (int i = 0; i < GLStateManager.STATE_SLOTS; i++) {
|
||||
stack[i] = new ColorMask();
|
||||
}
|
||||
}
|
||||
@@ -26,6 +26,11 @@ public final class ColorMaskStack extends ColorMask implements CowStateStack<Col
|
||||
return cow;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean slotChanged(int slot) {
|
||||
return VanillaStateLayer.isHeld(vanillaLayer) || !sameAs(stack[slot]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void captureSlot(int s) {
|
||||
VanillaStateLayer.capture(vanillaLayer, stack[s].set(this));
|
||||
|
||||
@@ -101,6 +101,36 @@ public final class CowDispatch {
|
||||
};
|
||||
}
|
||||
|
||||
public static boolean slotChanged(byte kind, CowStateStack<?> s, int slot) {
|
||||
return switch (kind) {
|
||||
case BLEND -> ((BlendStateStack) s).slotChanged(slot);
|
||||
case BOOLEAN -> ((BooleanStateStack) s).slotChanged(slot);
|
||||
case CLIP_PLANE_BOOLEAN -> ((ClipPlaneBooleanState) s).slotChanged(slot);
|
||||
case TEXTURE_UNIT_BOOLEAN -> ((TextureUnitBooleanStateStack) s).slotChanged(slot);
|
||||
case COLOR_MASK -> ((ColorMaskStack) s).slotChanged(slot);
|
||||
case LIGHT_STATE -> ((LightStateStack) s).slotChanged(slot);
|
||||
case MATERIAL -> ((MaterialStateStack) s).slotChanged(slot);
|
||||
case STENCIL -> ((StencilStateStack) s).slotChanged(slot);
|
||||
case MATRIX_MODE -> ((MatrixModeStack) s).slotChanged(slot);
|
||||
case LIGHT_MODEL -> ((LightModelStateStack) s).slotChanged(slot);
|
||||
case ALPHA -> ((AlphaStateStack) s).slotChanged(slot);
|
||||
case POINT -> ((PointStateStack) s).slotChanged(slot);
|
||||
case FOG -> ((FogStateStack) s).slotChanged(slot);
|
||||
case VEC4F -> ((Vec4fStack) s).slotChanged(slot);
|
||||
case VEC3F -> ((Vec3fStack) s).slotChanged(slot);
|
||||
case INTEGER -> ((IntegerStateStack) s).slotChanged(slot);
|
||||
case DEPTH -> ((DepthStateStack) s).slotChanged(slot);
|
||||
case VIEWPORT -> ((ViewPortStateStack) s).slotChanged(slot);
|
||||
case POLYGON -> ((PolygonStateStack) s).slotChanged(slot);
|
||||
case COLOR4 -> ((Color4Stack) s).slotChanged(slot);
|
||||
case LINE -> ((LineStateStack) s).slotChanged(slot);
|
||||
case TEXTURE_BINDING -> ((TextureBindingStack) s).slotChanged(slot);
|
||||
case TEX_ENV -> ((TexEnvState) s).slotChanged(slot);
|
||||
case SCISSOR -> ((ScissorStateStack) s).slotChanged(slot);
|
||||
default -> throw new IllegalStateException("Unknown kind: " + kind);
|
||||
};
|
||||
}
|
||||
|
||||
public static void restoreSlot(byte kind, CowStateStack<?> s, int slot) {
|
||||
switch (kind) {
|
||||
case BLEND -> ((BlendStateStack) s).restoreSlot(slot);
|
||||
|
||||
@@ -20,6 +20,8 @@ public interface CowStateStack<T> extends IStateStack<T> {
|
||||
|
||||
void restoreSlot(int slot);
|
||||
|
||||
boolean slotChanged(int slot);
|
||||
|
||||
default int stackId() {
|
||||
return cowDepths().id;
|
||||
}
|
||||
|
||||
@@ -17,8 +17,8 @@ public final class DepthStateStack extends DepthState implements CowStateStack<D
|
||||
|
||||
public DepthStateStack(int id) {
|
||||
cow.id = id;
|
||||
stack = new DepthState[GLStateManager.MAX_ATTRIB_STACK_DEPTH];
|
||||
for (int i = 0; i < GLStateManager.MAX_ATTRIB_STACK_DEPTH; i++) {
|
||||
stack = new DepthState[GLStateManager.STATE_SLOTS];
|
||||
for (int i = 0; i < GLStateManager.STATE_SLOTS; i++) {
|
||||
stack[i] = new DepthState();
|
||||
}
|
||||
}
|
||||
@@ -28,6 +28,11 @@ public final class DepthStateStack extends DepthState implements CowStateStack<D
|
||||
return cow;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean slotChanged(int slot) {
|
||||
return VanillaStateLayer.isHeld(vanillaLayer) || !sameAs(stack[slot]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void captureSlot(int s) {
|
||||
VanillaStateLayer.capture(vanillaLayer, stack[s].set(this));
|
||||
|
||||
@@ -10,8 +10,8 @@ public final class FogStateStack extends FogState implements CowStateStack<FogSt
|
||||
|
||||
public FogStateStack(int id) {
|
||||
cow.id = id;
|
||||
stack = new FogState[GLStateManager.MAX_ATTRIB_STACK_DEPTH];
|
||||
for (int i = 0; i < GLStateManager.MAX_ATTRIB_STACK_DEPTH; i++) {
|
||||
stack = new FogState[GLStateManager.STATE_SLOTS];
|
||||
for (int i = 0; i < GLStateManager.STATE_SLOTS; i++) {
|
||||
stack[i] = new FogState();
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,11 @@ public final class FogStateStack extends FogState implements CowStateStack<FogSt
|
||||
return cow;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean slotChanged(int slot) {
|
||||
return !sameAs(stack[slot]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void captureSlot(int s) {
|
||||
stack[s].set(this);
|
||||
|
||||
@@ -11,8 +11,8 @@ public final class IntegerStateStack extends IntegerState implements CowStateSta
|
||||
public IntegerStateStack(int val, int id) {
|
||||
cow.id = id;
|
||||
setValue(val);
|
||||
stack = new IntegerState[GLStateManager.MAX_ATTRIB_STACK_DEPTH];
|
||||
for (int i = 0; i < GLStateManager.MAX_ATTRIB_STACK_DEPTH; i++) {
|
||||
stack = new IntegerState[GLStateManager.STATE_SLOTS];
|
||||
for (int i = 0; i < GLStateManager.STATE_SLOTS; i++) {
|
||||
stack[i] = new IntegerState();
|
||||
stack[i].setValue(val);
|
||||
}
|
||||
@@ -30,6 +30,11 @@ public final class IntegerStateStack extends IntegerState implements CowStateSta
|
||||
return cow;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean slotChanged(int slot) {
|
||||
return !sameAs(stack[slot]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void captureSlot(int s) {
|
||||
stack[s].set(this);
|
||||
|
||||
@@ -11,8 +11,8 @@ public final class LightModelStateStack extends LightModelState implements CowSt
|
||||
public LightModelStateStack(int id) {
|
||||
super();
|
||||
cow.id = id;
|
||||
stack = new LightModelState[GLStateManager.MAX_ATTRIB_STACK_DEPTH];
|
||||
for (int i = 0; i < GLStateManager.MAX_ATTRIB_STACK_DEPTH; i++) {
|
||||
stack = new LightModelState[GLStateManager.STATE_SLOTS];
|
||||
for (int i = 0; i < GLStateManager.STATE_SLOTS; i++) {
|
||||
stack[i] = new LightModelState();
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,11 @@ public final class LightModelStateStack extends LightModelState implements CowSt
|
||||
return cow;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean slotChanged(int slot) {
|
||||
return !sameAs(stack[slot]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void captureSlot(int s) {
|
||||
stack[s].set(this);
|
||||
|
||||
@@ -11,8 +11,8 @@ public final class LightStateStack extends LightState implements CowStateStack<L
|
||||
public LightStateStack(int light, int id) {
|
||||
super(light);
|
||||
cow.id = id;
|
||||
stack = new LightState[GLStateManager.MAX_ATTRIB_STACK_DEPTH];
|
||||
for (int i = 0; i < GLStateManager.MAX_ATTRIB_STACK_DEPTH; i++) {
|
||||
stack = new LightState[GLStateManager.STATE_SLOTS];
|
||||
for (int i = 0; i < GLStateManager.STATE_SLOTS; i++) {
|
||||
stack[i] = new LightState(light);
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,11 @@ public final class LightStateStack extends LightState implements CowStateStack<L
|
||||
return cow;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean slotChanged(int slot) {
|
||||
return !sameAs(stack[slot]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void captureSlot(int s) {
|
||||
stack[s].set(this);
|
||||
|
||||
@@ -11,8 +11,8 @@ public final class LineStateStack extends LineState implements CowStateStack<Lin
|
||||
|
||||
public LineStateStack(int id) {
|
||||
cow.id = id;
|
||||
stack = new LineState[GLStateManager.MAX_ATTRIB_STACK_DEPTH];
|
||||
for (int i = 0; i < GLStateManager.MAX_ATTRIB_STACK_DEPTH; i++) {
|
||||
stack = new LineState[GLStateManager.STATE_SLOTS];
|
||||
for (int i = 0; i < GLStateManager.STATE_SLOTS; i++) {
|
||||
stack[i] = new LineState();
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,11 @@ public final class LineStateStack extends LineState implements CowStateStack<Lin
|
||||
return cow;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean slotChanged(int slot) {
|
||||
return !sameAs(stack[slot]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void captureSlot(int s) {
|
||||
stack[s].set(this);
|
||||
|
||||
@@ -11,8 +11,8 @@ public final class MaterialStateStack extends MaterialState implements CowStateS
|
||||
public MaterialStateStack(int face, int id) {
|
||||
super(face);
|
||||
cow.id = id;
|
||||
stack = new MaterialState[GLStateManager.MAX_ATTRIB_STACK_DEPTH];
|
||||
for (int i = 0; i < GLStateManager.MAX_ATTRIB_STACK_DEPTH; i++) {
|
||||
stack = new MaterialState[GLStateManager.STATE_SLOTS];
|
||||
for (int i = 0; i < GLStateManager.STATE_SLOTS; i++) {
|
||||
stack[i] = new MaterialState(face);
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,11 @@ public final class MaterialStateStack extends MaterialState implements CowStateS
|
||||
return cow;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean slotChanged(int slot) {
|
||||
return !sameAs(stack[slot]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void captureSlot(int s) {
|
||||
stack[s].set(this);
|
||||
|
||||
@@ -10,8 +10,8 @@ public final class MatrixModeStack extends MatrixMode implements CowStateStack<M
|
||||
|
||||
public MatrixModeStack(int id) {
|
||||
cow.id = id;
|
||||
stack = new MatrixMode[GLStateManager.MAX_ATTRIB_STACK_DEPTH];
|
||||
for (int i = 0; i < GLStateManager.MAX_ATTRIB_STACK_DEPTH; i++) {
|
||||
stack = new MatrixMode[GLStateManager.STATE_SLOTS];
|
||||
for (int i = 0; i < GLStateManager.STATE_SLOTS; i++) {
|
||||
stack[i] = new MatrixMode();
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,11 @@ public final class MatrixModeStack extends MatrixMode implements CowStateStack<M
|
||||
return cow;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean slotChanged(int slot) {
|
||||
return !sameAs(stack[slot]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void captureSlot(int s) {
|
||||
stack[s].set(this);
|
||||
|
||||
@@ -11,8 +11,8 @@ public final class PointStateStack extends PointState implements CowStateStack<P
|
||||
|
||||
public PointStateStack(int id) {
|
||||
cow.id = id;
|
||||
stack = new PointState[GLStateManager.MAX_ATTRIB_STACK_DEPTH];
|
||||
for (int i = 0; i < GLStateManager.MAX_ATTRIB_STACK_DEPTH; i++) {
|
||||
stack = new PointState[GLStateManager.STATE_SLOTS];
|
||||
for (int i = 0; i < GLStateManager.STATE_SLOTS; i++) {
|
||||
stack[i] = new PointState();
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,11 @@ public final class PointStateStack extends PointState implements CowStateStack<P
|
||||
return cow;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean slotChanged(int slot) {
|
||||
return !sameAs(stack[slot]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void captureSlot(int s) {
|
||||
stack[s].set(this);
|
||||
|
||||
@@ -11,8 +11,8 @@ public final class PolygonStateStack extends PolygonState implements CowStateSta
|
||||
|
||||
public PolygonStateStack(int id) {
|
||||
cow.id = id;
|
||||
stack = new PolygonState[GLStateManager.MAX_ATTRIB_STACK_DEPTH];
|
||||
for (int i = 0; i < GLStateManager.MAX_ATTRIB_STACK_DEPTH; i++) {
|
||||
stack = new PolygonState[GLStateManager.STATE_SLOTS];
|
||||
for (int i = 0; i < GLStateManager.STATE_SLOTS; i++) {
|
||||
stack[i] = new PolygonState();
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,11 @@ public final class PolygonStateStack extends PolygonState implements CowStateSta
|
||||
return cow;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean slotChanged(int slot) {
|
||||
return !sameAs(stack[slot]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void captureSlot(int s) {
|
||||
stack[s].set(this);
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.gtnewhorizons.angelica.glsm.stacks;
|
||||
|
||||
public final class RetainedState {
|
||||
public int[] ids = new int[64];
|
||||
public int count;
|
||||
public int program;
|
||||
public long programGen;
|
||||
|
||||
public void ensureCapacity(int capacity) {
|
||||
if (ids.length < capacity) ids = new int[capacity];
|
||||
}
|
||||
}
|
||||
@@ -11,8 +11,8 @@ public final class ScissorStateStack extends ScissorState implements CowStateSta
|
||||
|
||||
public ScissorStateStack(int id) {
|
||||
cow.id = id;
|
||||
stack = new ScissorState[GLStateManager.MAX_ATTRIB_STACK_DEPTH];
|
||||
for (int i = 0; i < GLStateManager.MAX_ATTRIB_STACK_DEPTH; i++) {
|
||||
stack = new ScissorState[GLStateManager.STATE_SLOTS];
|
||||
for (int i = 0; i < GLStateManager.STATE_SLOTS; i++) {
|
||||
stack[i] = new ScissorState();
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,11 @@ public final class ScissorStateStack extends ScissorState implements CowStateSta
|
||||
return cow;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean slotChanged(int slot) {
|
||||
return !sameAs(stack[slot]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void captureSlot(int s) {
|
||||
stack[s].set(this);
|
||||
|
||||
@@ -11,8 +11,8 @@ public final class StencilStateStack extends StencilState implements CowStateSta
|
||||
|
||||
public StencilStateStack(int id) {
|
||||
cow.id = id;
|
||||
stack = new StencilState[GLStateManager.MAX_ATTRIB_STACK_DEPTH];
|
||||
for (int i = 0; i < GLStateManager.MAX_ATTRIB_STACK_DEPTH; i++) {
|
||||
stack = new StencilState[GLStateManager.STATE_SLOTS];
|
||||
for (int i = 0; i < GLStateManager.STATE_SLOTS; i++) {
|
||||
stack[i] = new StencilState();
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,11 @@ public final class StencilStateStack extends StencilState implements CowStateSta
|
||||
return cow;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean slotChanged(int slot) {
|
||||
return !sameAs(stack[slot]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void captureSlot(int s) {
|
||||
stack[s].set(this);
|
||||
|
||||
@@ -12,8 +12,8 @@ public final class TextureBindingStack extends TextureBinding implements CowStat
|
||||
public TextureBindingStack(int id, int unit) {
|
||||
cow = new CowDepths(StateSet.R_TEXTURE, unit);
|
||||
cow.id = id;
|
||||
stack = new TextureBinding[GLStateManager.MAX_ATTRIB_STACK_DEPTH];
|
||||
for (int i = 0; i < GLStateManager.MAX_ATTRIB_STACK_DEPTH; i++) {
|
||||
stack = new TextureBinding[GLStateManager.STATE_SLOTS];
|
||||
for (int i = 0; i < GLStateManager.STATE_SLOTS; i++) {
|
||||
stack[i] = new TextureBinding();
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,11 @@ public final class TextureBindingStack extends TextureBinding implements CowStat
|
||||
return cow;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean slotChanged(int slot) {
|
||||
return !sameAs(stack[slot]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void captureSlot(int s) {
|
||||
stack[s].set(this);
|
||||
|
||||
@@ -15,7 +15,7 @@ public final class Vec3fStack implements CowStateStack<Vec3fStack> {
|
||||
public Vec3fStack(Vector3f value, int id) {
|
||||
this.value = value;
|
||||
cow.id = id;
|
||||
stack = new float[GLStateManager.MAX_ATTRIB_STACK_DEPTH][3];
|
||||
stack = new float[GLStateManager.STATE_SLOTS][3];
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -23,6 +23,11 @@ public final class Vec3fStack implements CowStateStack<Vec3fStack> {
|
||||
return cow;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean slotChanged(int slot) {
|
||||
return value.x != stack[slot][0] || value.y != stack[slot][1] || value.z != stack[slot][2];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void captureSlot(int s) {
|
||||
stack[s][0] = value.x;
|
||||
|
||||
@@ -15,7 +15,7 @@ public final class Vec4fStack implements CowStateStack<Vec4fStack> {
|
||||
public Vec4fStack(Vector4f value, int id) {
|
||||
this.value = value;
|
||||
cow.id = id;
|
||||
stack = new float[GLStateManager.MAX_ATTRIB_STACK_DEPTH][4];
|
||||
stack = new float[GLStateManager.STATE_SLOTS][4];
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -23,6 +23,11 @@ public final class Vec4fStack implements CowStateStack<Vec4fStack> {
|
||||
return cow;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean slotChanged(int slot) {
|
||||
return value.x != stack[slot][0] || value.y != stack[slot][1] || value.z != stack[slot][2] || value.w != stack[slot][3];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void captureSlot(int s) {
|
||||
stack[s][0] = value.x;
|
||||
|
||||
@@ -11,8 +11,8 @@ public final class ViewPortStateStack extends ViewportState implements CowStateS
|
||||
|
||||
public ViewPortStateStack(int id) {
|
||||
cow.id = id;
|
||||
stack = new ViewportState[GLStateManager.MAX_ATTRIB_STACK_DEPTH];
|
||||
for (int i = 0; i < GLStateManager.MAX_ATTRIB_STACK_DEPTH; i++) {
|
||||
stack = new ViewportState[GLStateManager.STATE_SLOTS];
|
||||
for (int i = 0; i < GLStateManager.STATE_SLOTS; i++) {
|
||||
stack[i] = new ViewportState();
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,11 @@ public final class ViewPortStateStack extends ViewportState implements CowStateS
|
||||
return cow;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean slotChanged(int slot) {
|
||||
return !sameAs(stack[slot]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void captureSlot(int s) {
|
||||
stack[s].set(this);
|
||||
|
||||
@@ -6,6 +6,8 @@ import com.gtnewhorizons.angelica.glsm.stacks.CowStateStack;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL13;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Per-texture-unit GL_TEXTURE_ENV state for FFP emulation. Tracks the simple texenv mode and all GL_COMBINE sub-parameters.
|
||||
*/
|
||||
@@ -45,8 +47,8 @@ public final class TexEnvState implements CowStateStack<TexEnvState> {
|
||||
stack = null;
|
||||
cow = null;
|
||||
} else {
|
||||
stack = new TexEnvState[GLStateManager.MAX_ATTRIB_STACK_DEPTH];
|
||||
for (int i = 0; i < GLStateManager.MAX_ATTRIB_STACK_DEPTH; i++) {
|
||||
stack = new TexEnvState[GLStateManager.STATE_SLOTS];
|
||||
for (int i = 0; i < GLStateManager.STATE_SLOTS; i++) {
|
||||
stack[i] = new TexEnvState(true);
|
||||
}
|
||||
cow = new CowDepths();
|
||||
@@ -70,6 +72,14 @@ public final class TexEnvState implements CowStateStack<TexEnvState> {
|
||||
this.envColorA = other.envColorA;
|
||||
}
|
||||
|
||||
private boolean sameAs(TexEnvState other) {
|
||||
return mode == other.mode && combineRgb == other.combineRgb && combineAlpha == other.combineAlpha
|
||||
&& Arrays.equals(sourceRgb, other.sourceRgb) && Arrays.equals(sourceAlpha, other.sourceAlpha)
|
||||
&& Arrays.equals(operandRgb, other.operandRgb) && Arrays.equals(operandAlpha, other.operandAlpha)
|
||||
&& scaleRgb == other.scaleRgb && scaleAlpha == other.scaleAlpha
|
||||
&& envColorR == other.envColorR && envColorG == other.envColorG && envColorB == other.envColorB && envColorA == other.envColorA;
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
mode = GL11.GL_MODULATE;
|
||||
combineRgb = GL11.GL_MODULATE;
|
||||
@@ -89,6 +99,11 @@ public final class TexEnvState implements CowStateStack<TexEnvState> {
|
||||
return cow;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean slotChanged(int slot) {
|
||||
return !sameAs(stack[slot]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void captureSlot(int s) {
|
||||
stack[s].copyFrom(this);
|
||||
|
||||
+83
@@ -0,0 +1,83 @@
|
||||
package com.gtnewhorizons.angelica.glsm;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL14;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
@GLCoreTest
|
||||
public class GLSM_HudCacheBlendOverride_GLTest {
|
||||
|
||||
private static void assertDriverFunc(int srcRgb, int dstRgb, int srcAlpha, int dstAlpha) {
|
||||
assertEquals(srcRgb, GL11.glGetInteger(GL14.GL_BLEND_SRC_RGB));
|
||||
assertEquals(dstRgb, GL11.glGetInteger(GL14.GL_BLEND_DST_RGB));
|
||||
assertEquals(srcAlpha, GL11.glGetInteger(GL14.GL_BLEND_SRC_ALPHA));
|
||||
assertEquals(dstAlpha, GL11.glGetInteger(GL14.GL_BLEND_DST_ALPHA));
|
||||
}
|
||||
|
||||
private static void assertCachedFunc(int srcRgb, int dstRgb, int srcAlpha, int dstAlpha) {
|
||||
assertEquals(srcRgb, GLStateManager.glGetInteger(GL14.GL_BLEND_SRC_RGB));
|
||||
assertEquals(dstRgb, GLStateManager.glGetInteger(GL14.GL_BLEND_DST_RGB));
|
||||
assertEquals(srcAlpha, GLStateManager.glGetInteger(GL14.GL_BLEND_SRC_ALPHA));
|
||||
assertEquals(dstAlpha, GLStateManager.glGetInteger(GL14.GL_BLEND_DST_ALPHA));
|
||||
}
|
||||
|
||||
@Test
|
||||
void overrideChangesTheDriverFuncButNotTheCache() {
|
||||
try {
|
||||
GLStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ZERO);
|
||||
assertDriverFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ZERO);
|
||||
|
||||
GLStateManager.setHudCacheOverride(true);
|
||||
assertCachedFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ZERO);
|
||||
assertDriverFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
GLStateManager.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE);
|
||||
assertCachedFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE, GL11.GL_SRC_ALPHA, GL11.GL_ONE);
|
||||
assertDriverFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
GLStateManager.tryBlendFuncSeparate(GL11.GL_DST_COLOR, GL11.GL_ZERO, GL11.GL_ZERO, GL11.GL_ONE);
|
||||
assertCachedFunc(GL11.GL_DST_COLOR, GL11.GL_ZERO, GL11.GL_ZERO, GL11.GL_ONE);
|
||||
assertDriverFunc(GL11.GL_DST_COLOR, GL11.GL_ZERO, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
GLStateManager.setHudCacheOverride(false);
|
||||
assertCachedFunc(GL11.GL_DST_COLOR, GL11.GL_ZERO, GL11.GL_ZERO, GL11.GL_ONE);
|
||||
assertDriverFunc(GL11.GL_DST_COLOR, GL11.GL_ZERO, GL11.GL_ZERO, GL11.GL_ONE);
|
||||
} finally {
|
||||
GLStateManager.setHudCacheOverride(false);
|
||||
GLStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ZERO);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void popUnderOverrideKeepsTheOverriddenAlphaOnTheDriver() {
|
||||
try {
|
||||
GLStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ZERO);
|
||||
final int d = GLStateManager.pushState(StateSet.BLEND);
|
||||
GLStateManager.setHudCacheOverride(true);
|
||||
GLStateManager.glBlendFunc(GL11.GL_ONE, GL11.GL_ONE);
|
||||
GLStateManager.popStateTo(d);
|
||||
assertCachedFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ZERO);
|
||||
assertDriverFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA);
|
||||
GLStateManager.setHudCacheOverride(false);
|
||||
assertDriverFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ZERO);
|
||||
} finally {
|
||||
GLStateManager.setHudCacheOverride(false);
|
||||
GLStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ZERO);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void separateAlphaIsForcedEvenWhenDstAlphaAlreadyMatches() {
|
||||
try {
|
||||
GLStateManager.setHudCacheOverride(true);
|
||||
GLStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ZERO, GL11.GL_ONE_MINUS_SRC_ALPHA);
|
||||
assertCachedFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ZERO, GL11.GL_ONE_MINUS_SRC_ALPHA);
|
||||
assertDriverFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA);
|
||||
} finally {
|
||||
GLStateManager.setHudCacheOverride(false);
|
||||
GLStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ZERO);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,256 @@
|
||||
package com.gtnewhorizons.angelica.glsm;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.stacks.RetainedState;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL13;
|
||||
import org.lwjgl.opengl.GL14;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
@GLCoreTest
|
||||
public class GLSM_RetainedState_GLTest {
|
||||
|
||||
private static final StateSet ALL = StateSet.forMask(GL11.GL_ALL_ATTRIB_BITS);
|
||||
|
||||
private static int driverTextureBinding(int unit) {
|
||||
final int saved = GL11.glGetInteger(GL13.GL_ACTIVE_TEXTURE);
|
||||
GL13.glActiveTexture(GL13.GL_TEXTURE0 + unit);
|
||||
final int binding = GL11.glGetInteger(GL11.GL_TEXTURE_BINDING_2D);
|
||||
GL13.glActiveTexture(saved);
|
||||
return binding;
|
||||
}
|
||||
|
||||
private static void baseline() {
|
||||
GLStateManager.enableCull();
|
||||
GLStateManager.disableBlend();
|
||||
GLStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ZERO);
|
||||
GLStateManager.glDepthMask(true);
|
||||
GLStateManager.glDepthFunc(GL11.GL_LEQUAL);
|
||||
GLStateManager.glAlphaFunc(GL11.GL_GREATER, 0.1F);
|
||||
GLStateManager.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
|
||||
GLStateManager.glActiveTexture(GL13.GL_TEXTURE0);
|
||||
GLStateManager.glBindTexture(GL11.GL_TEXTURE_2D, 0);
|
||||
}
|
||||
|
||||
private static void mutate(int texture) {
|
||||
GLStateManager.disableCull();
|
||||
GLStateManager.enableBlend();
|
||||
GLStateManager.tryBlendFuncSeparate(GL11.GL_DST_COLOR, GL11.GL_ZERO, GL11.GL_ONE, GL11.GL_ONE);
|
||||
GLStateManager.glDepthMask(false);
|
||||
GLStateManager.glDepthFunc(GL11.GL_ALWAYS);
|
||||
GLStateManager.glAlphaFunc(GL11.GL_GEQUAL, 0.5F);
|
||||
GLStateManager.glColor4f(0.25F, 0.5F, 0.75F, 0.5F);
|
||||
GLStateManager.glBindTexture(GL11.GL_TEXTURE_2D, texture);
|
||||
}
|
||||
|
||||
private static void assertBaseline() {
|
||||
assertTrue(GLStateManager.glIsEnabled(GL11.GL_CULL_FACE));
|
||||
assertTrue(GL11.glIsEnabled(GL11.GL_CULL_FACE));
|
||||
assertFalse(GLStateManager.glIsEnabled(GL11.GL_BLEND));
|
||||
assertFalse(GL11.glIsEnabled(GL11.GL_BLEND));
|
||||
assertEquals(GL11.GL_SRC_ALPHA, GL11.glGetInteger(GL14.GL_BLEND_SRC_RGB));
|
||||
assertEquals(GL11.GL_ZERO, GL11.glGetInteger(GL14.GL_BLEND_DST_ALPHA));
|
||||
assertTrue(GL11.glGetBoolean(GL11.GL_DEPTH_WRITEMASK));
|
||||
assertEquals(GL11.GL_LEQUAL, GL11.glGetInteger(GL11.GL_DEPTH_FUNC));
|
||||
assertEquals(GL11.GL_GREATER, GLStateManager.glGetInteger(GL11.GL_ALPHA_TEST_FUNC));
|
||||
assertEquals(1.0F, GLStateManager.getColor().getRed(), 0.0F);
|
||||
assertEquals(0, driverTextureBinding(0));
|
||||
}
|
||||
|
||||
private static void assertMutated(int texture) {
|
||||
assertFalse(GLStateManager.glIsEnabled(GL11.GL_CULL_FACE));
|
||||
assertFalse(GL11.glIsEnabled(GL11.GL_CULL_FACE));
|
||||
assertTrue(GLStateManager.glIsEnabled(GL11.GL_BLEND));
|
||||
assertTrue(GL11.glIsEnabled(GL11.GL_BLEND));
|
||||
assertEquals(GL11.GL_DST_COLOR, GL11.glGetInteger(GL14.GL_BLEND_SRC_RGB));
|
||||
assertEquals(GL11.GL_ZERO, GL11.glGetInteger(GL14.GL_BLEND_DST_RGB));
|
||||
assertEquals(GL11.GL_ONE, GL11.glGetInteger(GL14.GL_BLEND_SRC_ALPHA));
|
||||
assertEquals(GL11.GL_ONE, GL11.glGetInteger(GL14.GL_BLEND_DST_ALPHA));
|
||||
assertEquals(GL11.GL_DST_COLOR, GLStateManager.glGetInteger(GL14.GL_BLEND_SRC_RGB));
|
||||
assertFalse(GL11.glGetBoolean(GL11.GL_DEPTH_WRITEMASK));
|
||||
assertEquals(GL11.GL_ALWAYS, GL11.glGetInteger(GL11.GL_DEPTH_FUNC));
|
||||
assertEquals(GL11.GL_GEQUAL, GLStateManager.glGetInteger(GL11.GL_ALPHA_TEST_FUNC));
|
||||
assertEquals(0.25F, GLStateManager.getColor().getRed(), 0.0F);
|
||||
assertEquals(0.5F, GLStateManager.getColor().getAlpha(), 0.0F);
|
||||
assertEquals(texture, driverTextureBinding(0));
|
||||
assertEquals(texture, GLStateManager.getBoundTextureForServerState(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
void retainedDeltaReappliesAfterPop() {
|
||||
final int texture = GL11.glGenTextures();
|
||||
final RetainedState retained = new RetainedState();
|
||||
try {
|
||||
baseline();
|
||||
final int d = GLStateManager.pushState(ALL);
|
||||
mutate(texture);
|
||||
GLStateManager.retainModifiedState(d, retained);
|
||||
GLStateManager.popStateTo(d);
|
||||
assertBaseline();
|
||||
|
||||
GLStateManager.applyRetainedState(retained);
|
||||
assertMutated(texture);
|
||||
|
||||
baseline();
|
||||
assertBaseline();
|
||||
GLStateManager.applyRetainedState(retained);
|
||||
assertMutated(texture);
|
||||
} finally {
|
||||
baseline();
|
||||
GL11.glDeleteTextures(texture);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void appliedDeltaIsRestoredByAnEnclosingPush() {
|
||||
final int texture = GL11.glGenTextures();
|
||||
final RetainedState retained = new RetainedState();
|
||||
try {
|
||||
baseline();
|
||||
final int d = GLStateManager.pushState(ALL);
|
||||
mutate(texture);
|
||||
GLStateManager.retainModifiedState(d, retained);
|
||||
GLStateManager.popStateTo(d);
|
||||
|
||||
final int outer = GLStateManager.pushState(ALL);
|
||||
GLStateManager.applyRetainedState(retained);
|
||||
assertMutated(texture);
|
||||
GLStateManager.popStateTo(outer);
|
||||
assertBaseline();
|
||||
} finally {
|
||||
baseline();
|
||||
GL11.glDeleteTextures(texture);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void statesRestoredByANestedPushAreNotRetained() {
|
||||
final RetainedState retained = new RetainedState();
|
||||
try {
|
||||
baseline();
|
||||
final int d = GLStateManager.pushState(ALL);
|
||||
GLStateManager.enableBlend();
|
||||
final int nested = GLStateManager.pushState(ALL);
|
||||
GLStateManager.disableCull();
|
||||
GLStateManager.popStateTo(nested);
|
||||
GLStateManager.retainModifiedState(d, retained);
|
||||
GLStateManager.popStateTo(d);
|
||||
|
||||
GLStateManager.applyRetainedState(retained);
|
||||
assertTrue(GL11.glIsEnabled(GL11.GL_BLEND));
|
||||
assertTrue(GL11.glIsEnabled(GL11.GL_CULL_FACE));
|
||||
assertTrue(GLStateManager.glIsEnabled(GL11.GL_CULL_FACE));
|
||||
} finally {
|
||||
baseline();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void onlyDifferingStateIsReissued() {
|
||||
final int texture = GL11.glGenTextures();
|
||||
final RetainedState retained = new RetainedState();
|
||||
try {
|
||||
baseline();
|
||||
final int d = GLStateManager.pushState(ALL);
|
||||
mutate(texture);
|
||||
GLStateManager.retainModifiedState(d, retained);
|
||||
GLStateManager.popStateTo(d);
|
||||
GLStateManager.applyRetainedState(retained);
|
||||
|
||||
final GLContextState glCtx = GLStateManager.ctx();
|
||||
final long backendCalls = GLStateManager.attribBackendCalls;
|
||||
final int colorGen = glCtx.colorGeneration;
|
||||
final int fragmentGen = glCtx.fragmentGeneration;
|
||||
final int batchGen = glCtx.batchStateGeneration;
|
||||
GLStateManager.applyRetainedState(retained);
|
||||
assertEquals(backendCalls, GLStateManager.attribBackendCalls);
|
||||
assertEquals(colorGen, glCtx.colorGeneration);
|
||||
assertEquals(fragmentGen, glCtx.fragmentGeneration);
|
||||
assertEquals(batchGen, glCtx.batchStateGeneration);
|
||||
|
||||
GLStateManager.glDepthFunc(GL11.GL_LEQUAL);
|
||||
GLStateManager.applyRetainedState(retained);
|
||||
assertEquals(backendCalls + 3, GLStateManager.attribBackendCalls);
|
||||
assertMutated(texture);
|
||||
} finally {
|
||||
baseline();
|
||||
GL11.glDeleteTextures(texture);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void aSecondCaptureInvalidatesTheFirst() {
|
||||
final RetainedState first = new RetainedState();
|
||||
final RetainedState second = new RetainedState();
|
||||
try {
|
||||
baseline();
|
||||
int d = GLStateManager.pushState(ALL);
|
||||
GLStateManager.enableBlend();
|
||||
GLStateManager.retainModifiedState(d, first);
|
||||
GLStateManager.popStateTo(d);
|
||||
|
||||
d = GLStateManager.pushState(ALL);
|
||||
GLStateManager.disableCull();
|
||||
GLStateManager.retainModifiedState(d, second);
|
||||
GLStateManager.popStateTo(d);
|
||||
|
||||
GLStateManager.applyRetainedState(first);
|
||||
assertFalse(GL11.glIsEnabled(GL11.GL_BLEND));
|
||||
assertTrue(GL11.glIsEnabled(GL11.GL_CULL_FACE));
|
||||
GLStateManager.applyRetainedState(second);
|
||||
assertFalse(GL11.glIsEnabled(GL11.GL_BLEND));
|
||||
assertFalse(GL11.glIsEnabled(GL11.GL_CULL_FACE));
|
||||
} finally {
|
||||
baseline();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void writesInAnOuterPushAreNotRetained() {
|
||||
final RetainedState retained = new RetainedState();
|
||||
try {
|
||||
baseline();
|
||||
GLStateManager.glClearColor(0.25F, 0.5F, 0.75F, 1.0F);
|
||||
final int outer = GLStateManager.pushState(ALL);
|
||||
GLStateManager.glClearColor(0.0F, 0.0F, 0.0F, 0.0F);
|
||||
final int inner = GLStateManager.pushState(ALL);
|
||||
GLStateManager.enableBlend();
|
||||
GLStateManager.retainModifiedState(inner, retained);
|
||||
GLStateManager.popStateTo(outer);
|
||||
|
||||
GLStateManager.applyRetainedState(retained);
|
||||
assertTrue(GL11.glIsEnabled(GL11.GL_BLEND));
|
||||
assertEquals(0.25F, GLStateManager.getClearColor().getRed(), 0.0F);
|
||||
assertEquals(1.0F, GLStateManager.getClearColor().getAlpha(), 0.0F);
|
||||
} finally {
|
||||
baseline();
|
||||
GLStateManager.glClearColor(0.0F, 0.0F, 0.0F, 0.0F);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void aDeletedProgramIsNotRebound() {
|
||||
final RetainedState retained = new RetainedState();
|
||||
final int program = GLSM_StateSet_GLTest.linkTrivialProgram();
|
||||
try {
|
||||
baseline();
|
||||
final int d = GLStateManager.pushState(ALL);
|
||||
GLStateManager.glUseProgram(program);
|
||||
GLStateManager.retainModifiedState(d, retained);
|
||||
GLStateManager.popStateTo(d);
|
||||
GLStateManager.glUseProgram(0);
|
||||
GLStateManager.glDeleteProgram(program);
|
||||
while (GL11.glGetError() != GL11.GL_NO_ERROR) {}
|
||||
|
||||
GLStateManager.applyRetainedState(retained);
|
||||
assertEquals(0, GLStateManager.getActiveProgram());
|
||||
assertEquals(GL11.GL_NO_ERROR, GL11.glGetError());
|
||||
} finally {
|
||||
GLStateManager.glUseProgram(0);
|
||||
baseline();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -45,7 +45,7 @@ public class GLSM_StateSet_GLTest {
|
||||
private static final String TRIVIAL_VS = "#version 330 core\nvoid main(){ gl_Position = vec4(0.0); }\n";
|
||||
private static final String TRIVIAL_FS = "#version 330 core\nout vec4 o;\nvoid main(){ o = vec4(1.0); }\n";
|
||||
|
||||
private static int linkTrivialProgram() {
|
||||
static int linkTrivialProgram() {
|
||||
final int v = compileShader(GL20.GL_VERTEX_SHADER, TRIVIAL_VS);
|
||||
final int f = compileShader(GL20.GL_FRAGMENT_SHADER, TRIVIAL_FS);
|
||||
final int p = GL20.glCreateProgram();
|
||||
|
||||
@@ -1,32 +1,30 @@
|
||||
package com.gtnewhorizons.angelica.hudcaching;
|
||||
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.DirectTessellator;
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.TessellatorManager;
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.postprocessing.CustomFramebuffer;
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.postprocessing.SharedDepthFramebuffer;
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.vao.IVertexArrayObject;
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.vao.VertexBufferType;
|
||||
import com.gtnewhorizon.gtnhlib.client.renderer.vertex.DefaultVertexFormat;
|
||||
import com.gtnewhorizons.angelica.compat.ModStatus;
|
||||
import com.gtnewhorizons.angelica.compat.holoinventory.HoloInventoryReflectionCompat;
|
||||
import com.gtnewhorizons.angelica.config.AngelicaConfig;
|
||||
import com.gtnewhorizons.angelica.event.ClientEvent;
|
||||
import com.gtnewhorizons.angelica.event.ClientEventType;
|
||||
import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import com.gtnewhorizons.angelica.glsm.hooks.GLSMConfig;
|
||||
import com.gtnewhorizons.angelica.glsm.StateSet;
|
||||
import com.gtnewhorizons.angelica.glsm.profiling.Tracy;
|
||||
import com.gtnewhorizons.angelica.glsm.stacks.RetainedState;
|
||||
import com.gtnewhorizons.angelica.mixins.interfaces.GuiIngameAccessor;
|
||||
import com.gtnewhorizons.angelica.mixins.interfaces.GuiIngameForgeAccessor;
|
||||
import com.gtnewhorizons.angelica.mixins.interfaces.RenderGameOverlayEventAccessor;
|
||||
import com.gtnewhorizons.angelica.render.PanoramaRenderer;
|
||||
import com.kentington.thaumichorizons.common.ThaumicHorizons;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.Gui;
|
||||
import net.minecraft.client.gui.GuiIngame;
|
||||
import net.minecraft.client.gui.ScaledResolution;
|
||||
import net.minecraft.client.renderer.EntityRenderer;
|
||||
import net.minecraftforge.client.GuiIngameForge;
|
||||
import net.minecraftforge.client.event.RenderGameOverlayEvent;
|
||||
import org.embeddedt.embeddium.impl.gl.shader.GlProgram;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL13;
|
||||
import org.lwjgl.opengl.GL30;
|
||||
import thaumcraft.common.Thaumcraft;
|
||||
import xaero.common.core.XaeroMinimapCore;
|
||||
|
||||
@@ -35,13 +33,20 @@ import xaero.common.core.XaeroMinimapCore;
|
||||
public class HUDCaching {
|
||||
|
||||
private static final Minecraft mc = Minecraft.getMinecraft();
|
||||
public static SharedDepthFramebuffer framebuffer;
|
||||
public static CustomFramebuffer framebuffer;
|
||||
private static boolean dirty = true;
|
||||
private static long nextHudRefresh;
|
||||
|
||||
private static IVertexArrayObject quadVAO;
|
||||
private static float quadWidth;
|
||||
private static float quadHeight;
|
||||
private static final RetainedState hudExitState = new RetainedState();
|
||||
private static StateSet allState;
|
||||
private static GlProgram<Object> compositeProgram;
|
||||
private static int compositeVao;
|
||||
|
||||
private static final Tracy.ZoneId Z_CACHE_WRAP = Tracy.zoneId("hudCacheWrap", Tracy.COLOR_CLIENT);
|
||||
private static final Tracy.ZoneId Z_DRAW = Tracy.zoneId("hudDraw", Tracy.COLOR_CLIENT);
|
||||
private static final Tracy.ZoneId Z_CAPTURED_BITS = Tracy.zoneId("hudCapturedBits", Tracy.COLOR_CLIENT);
|
||||
private static final Tracy.ZoneId Z_COMPOSITE = Tracy.zoneId("hudComposite", Tracy.COLOR_CLIENT);
|
||||
private static final Tracy.ZoneId Z_APPLY_RETAINED = Tracy.zoneId("hudApplyRetained", Tracy.COLOR_CLIENT);
|
||||
|
||||
public static boolean renderingCacheOverride;
|
||||
|
||||
@@ -61,16 +66,79 @@ public class HUDCaching {
|
||||
private final static RenderGameOverlayEvent fakeTextEvent = new RenderGameOverlayEvent.Text(new RenderGameOverlayEvent(0, null, 0, 0), null, null);
|
||||
private final static RenderGameOverlayEvent.Post fakePostEvent = new RenderGameOverlayEvent.Post(new RenderGameOverlayEvent(0, null, 0, 0), RenderGameOverlayEvent.ElementType.HELMET);
|
||||
|
||||
private static ScaledResolution resolution;
|
||||
private static int resolutionWidth, resolutionHeight, resolutionGuiScale;
|
||||
private static boolean resolutionUnicode;
|
||||
|
||||
private static ScaledResolution resolution() {
|
||||
final int width = mc.displayWidth, height = mc.displayHeight, guiScale = mc.gameSettings.guiScale;
|
||||
final boolean unicode = mc.func_152349_b();
|
||||
if (resolution == null || width != resolutionWidth || height != resolutionHeight || guiScale != resolutionGuiScale || unicode != resolutionUnicode) {
|
||||
resolutionWidth = width;
|
||||
resolutionHeight = height;
|
||||
resolutionGuiScale = guiScale;
|
||||
resolutionUnicode = unicode;
|
||||
resolution = new ScaledResolution(mc, width, height);
|
||||
}
|
||||
return resolution;
|
||||
}
|
||||
|
||||
private static void setupOverlay(ScaledResolution scaled) {
|
||||
GLStateManager.glClear(GL11.GL_DEPTH_BUFFER_BIT);
|
||||
GLStateManager.glMatrixMode(GL11.GL_PROJECTION);
|
||||
GLStateManager.glLoadIdentity();
|
||||
GLStateManager.glOrtho(0.0D, scaled.getScaledWidth_double(), scaled.getScaledHeight_double(), 0.0D, 1000.0D, 3000.0D);
|
||||
GLStateManager.glMatrixMode(GL11.GL_MODELVIEW);
|
||||
GLStateManager.glLoadIdentity();
|
||||
GLStateManager.glTranslatef(0.0F, 0.0F, -2000.0F);
|
||||
}
|
||||
|
||||
public static void init() {
|
||||
framebuffer = new SharedDepthFramebuffer(CustomFramebuffer.STENCIL_BUFFER);
|
||||
framebuffer = new CustomFramebuffer(CustomFramebuffer.DEPTH_TEXTURE | CustomFramebuffer.STENCIL_BUFFER);
|
||||
}
|
||||
|
||||
public static void resetAfterCrash() {
|
||||
renderingCacheOverride = false;
|
||||
GLSMConfig.hudCacheOverride = false;
|
||||
GLStateManager.setHudCacheOverride(false);
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
private static void initComposite() {
|
||||
compositeProgram = PanoramaRenderer.loadProgram("angelica:hud_composite", "angelica:panorama_blur", "angelica:hud_composite", ctx -> ctx);
|
||||
compositeProgram.bind();
|
||||
GLStateManager.glUniform1i(GLStateManager.glGetUniformLocation(compositeProgram.handle(), "u_Depth"), 1);
|
||||
compositeProgram.unbind();
|
||||
compositeVao = GLStateManager.glGenVertexArrays();
|
||||
}
|
||||
|
||||
private static void composite() {
|
||||
if (compositeProgram == null) initComposite();
|
||||
final int program = GLStateManager.getActiveProgram();
|
||||
final int vao = GLStateManager.glGetInteger(GL30.GL_VERTEX_ARRAY_BINDING);
|
||||
final int stateDepth = GLStateManager.pushState(allState);
|
||||
try {
|
||||
GLStateManager.enableBlend();
|
||||
GLStateManager.tryBlendFuncSeparate(GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA);
|
||||
GLStateManager.enableDepthTest();
|
||||
GLStateManager.glDepthFunc(GL11.GL_ALWAYS);
|
||||
GLStateManager.glDepthMask(true);
|
||||
GLStateManager.glColorMask(true, true, true, true);
|
||||
GLStateManager.disableCull();
|
||||
GLStateManager.disableScissorTest();
|
||||
GLStateManager.glActiveTexture(GL13.GL_TEXTURE1);
|
||||
GLStateManager.glBindTexture(GL11.GL_TEXTURE_2D, framebuffer.depthAttachment);
|
||||
GLStateManager.glActiveTexture(GL13.GL_TEXTURE0);
|
||||
GLStateManager.glBindTexture(GL11.GL_TEXTURE_2D, framebuffer.framebufferTexture);
|
||||
compositeProgram.bind();
|
||||
GLStateManager.glBindVertexArray(compositeVao);
|
||||
GLStateManager.glDrawArrays(GL11.GL_TRIANGLES, 0, 3);
|
||||
} finally {
|
||||
GLStateManager.glBindVertexArray(vao);
|
||||
GLStateManager.glUseProgram(program);
|
||||
GLStateManager.popStateTo(stateDepth);
|
||||
}
|
||||
}
|
||||
|
||||
public static void renderCachedHud(EntityRenderer renderer, GuiIngame ingame, float partialTicks, boolean hasScreen, int mouseX, int mouseY) {
|
||||
ClientEvent.post(ClientEventType.PRE_RENDER_GUI, renderer, partialTicks);
|
||||
ClientEvent.post(ClientEventType.PRE_RENDER_HUD, renderer, partialTicks);
|
||||
@@ -94,31 +162,45 @@ public class HUDCaching {
|
||||
if (System.currentTimeMillis() > nextHudRefresh) {
|
||||
dirty = true;
|
||||
}
|
||||
if (allState == null) allState = StateSet.forMask(GL11.GL_ALL_ATTRIB_BITS);
|
||||
|
||||
if (dirty) {
|
||||
dirty = false;
|
||||
nextHudRefresh = System.currentTimeMillis() + (1000 / AngelicaConfig.hudCachingFPS);
|
||||
if (framebuffer.framebufferWidth != mc.displayWidth || framebuffer.framebufferHeight != mc.displayHeight) {
|
||||
framebuffer.createBindFramebuffer(mc.displayWidth, mc.displayHeight);
|
||||
} else {
|
||||
framebuffer.clearBindFramebuffer();
|
||||
}
|
||||
renderingCacheOverride = true;
|
||||
GLSMConfig.hudCacheOverride = true;
|
||||
if (Tracy.ENABLED) Tracy.beginZone(Z_CACHE_WRAP);
|
||||
final int outerDepth = GLStateManager.pushState(allState);
|
||||
try {
|
||||
ingame.renderGameOverlay(partialTicks, hasScreen, mouseX, mouseY);
|
||||
if (framebuffer.framebufferWidth != mc.displayWidth || framebuffer.framebufferHeight != mc.displayHeight) {
|
||||
framebuffer.createBindFramebuffer(mc.displayWidth, mc.displayHeight);
|
||||
} else {
|
||||
framebuffer.clearBindFramebuffer();
|
||||
}
|
||||
final int hudDepth = GLStateManager.pushState(allState);
|
||||
renderingCacheOverride = true;
|
||||
GLStateManager.setHudCacheOverride(true);
|
||||
if (Tracy.ENABLED) Tracy.beginZone(Z_DRAW);
|
||||
try {
|
||||
ingame.renderGameOverlay(partialTicks, hasScreen, mouseX, mouseY);
|
||||
} finally {
|
||||
if (Tracy.ENABLED) Tracy.endZone();
|
||||
}
|
||||
GLStateManager.setHudCacheOverride(false);
|
||||
GLStateManager.popStateTo(hudDepth + 1);
|
||||
GLStateManager.retainModifiedState(hudDepth, hudExitState);
|
||||
} finally {
|
||||
renderingCacheOverride = false;
|
||||
GLSMConfig.hudCacheOverride = false;
|
||||
GLStateManager.setHudCacheOverride(false);
|
||||
GLStateManager.popStateTo(outerDepth);
|
||||
mc.getFramebuffer().bindFramebuffer(false);
|
||||
if (Tracy.ENABLED) Tracy.endZone();
|
||||
}
|
||||
} else {
|
||||
renderer.setupOverlayRendering();
|
||||
}
|
||||
|
||||
ScaledResolution resolution = new ScaledResolution(mc, mc.displayWidth, mc.displayHeight);
|
||||
int width = resolution.getScaledWidth();
|
||||
int height = resolution.getScaledHeight();
|
||||
final ScaledResolution scaled = resolution();
|
||||
setupOverlay(scaled);
|
||||
int width = scaled.getScaledWidth();
|
||||
int height = scaled.getScaledHeight();
|
||||
if (Tracy.ENABLED) Tracy.beginZone(Z_CAPTURED_BITS);
|
||||
GLStateManager.enableBlend();
|
||||
|
||||
// reset the color that may be applied by some items
|
||||
@@ -135,7 +217,7 @@ public class HUDCaching {
|
||||
if (ingame instanceof GuiIngameForge) {
|
||||
GuiIngameForgeAccessor guiForge = ((GuiIngameForgeAccessor) ingame);
|
||||
if (renderHelmetCaptured) {
|
||||
guiForge.callRenderHelmet(resolution, partialTicks, hasScreen, mouseX, mouseY);
|
||||
guiForge.callRenderHelmet(scaled, partialTicks, hasScreen, mouseX, mouseY);
|
||||
if (ModStatus.isHoloInventoryLoaded) {
|
||||
HoloInventoryReflectionCompat.setAngelicaOverride(false);
|
||||
// only settings the partial ticks as mouseX and mouseY are not used in renderEvent
|
||||
@@ -155,7 +237,7 @@ public class HUDCaching {
|
||||
}
|
||||
if (ModStatus.isThaumcraftLoaded || ModStatus.isThaumicHorizonsLoaded) {
|
||||
((RenderGameOverlayEventAccessor) fakeTextEvent).setPartialTicks(partialTicks);
|
||||
((RenderGameOverlayEventAccessor) fakeTextEvent).setResolution(resolution);
|
||||
((RenderGameOverlayEventAccessor) fakeTextEvent).setResolution(scaled);
|
||||
((RenderGameOverlayEventAccessor) fakeTextEvent).setMouseX(mouseX);
|
||||
((RenderGameOverlayEventAccessor) fakeTextEvent).setMouseY(mouseY);
|
||||
if (ModStatus.isThaumcraftLoaded) {
|
||||
@@ -174,15 +256,14 @@ public class HUDCaching {
|
||||
}
|
||||
}
|
||||
|
||||
// render cached frame
|
||||
GLStateManager.enableBlend();
|
||||
GLStateManager.tryBlendFuncSeparate(GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA);
|
||||
GLStateManager.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
|
||||
framebuffer.bindFramebufferTexture();
|
||||
drawTexturedRect((float) resolution.getScaledWidth_double(), (float) resolution.getScaledHeight_double());
|
||||
if (Tracy.ENABLED) Tracy.endZone();
|
||||
|
||||
GLStateManager.tryBlendFuncSeparate(GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ZERO);
|
||||
mc.getTextureManager().bindTexture(Gui.icons);
|
||||
if (Tracy.ENABLED) Tracy.beginZone(Z_COMPOSITE);
|
||||
composite();
|
||||
if (Tracy.ENABLED) Tracy.endZone();
|
||||
if (Tracy.ENABLED) Tracy.beginZone(Z_APPLY_RETAINED);
|
||||
GLStateManager.applyRetainedState(hudExitState);
|
||||
if (Tracy.ENABLED) Tracy.endZone();
|
||||
|
||||
ClientEvent.post(ClientEventType.POST_RENDER_HUD, renderer, partialTicks);
|
||||
}
|
||||
@@ -200,35 +281,6 @@ public class HUDCaching {
|
||||
GLStateManager.disableBlend();
|
||||
}
|
||||
|
||||
private static void drawTexturedRect(float width, float height) {
|
||||
if (quadWidth != width || quadHeight != height) {
|
||||
quadWidth = width;
|
||||
quadHeight = height;
|
||||
rebuildVAO(width, height);
|
||||
}
|
||||
GLStateManager.disableDepthTest();
|
||||
GLStateManager.enableTexture();
|
||||
quadVAO.render();
|
||||
GLStateManager.enableDepthTest();
|
||||
}
|
||||
|
||||
|
||||
private static void rebuildVAO(float width, float height) {
|
||||
final DirectTessellator tessellator = TessellatorManager.startCapturingDirect(DefaultVertexFormat.POSITION_TEXTURE);
|
||||
tessellator.startDrawingQuads();
|
||||
tessellator.addVertexWithUV(0, height, 0.0, 0, 0);
|
||||
tessellator.addVertexWithUV(width, height, 0.0, 1, 0);
|
||||
tessellator.addVertexWithUV(width, 0, 0.0, 1, 1);
|
||||
tessellator.addVertexWithUV(0, 0, 0.0, 0, 1);
|
||||
tessellator.draw();
|
||||
if (quadVAO == null) {
|
||||
quadVAO = tessellator.uploadToVBO(VertexBufferType.MUTABLE);
|
||||
} else {
|
||||
tessellator.updateToVBO(quadVAO.getVBO());
|
||||
}
|
||||
TessellatorManager.stopCapturingDirect();
|
||||
}
|
||||
|
||||
public static void disableHoloInventory() {
|
||||
if (ModStatus.isHoloInventoryLoaded) {
|
||||
HoloInventoryReflectionCompat.setAngelicaOverride(true);
|
||||
|
||||
@@ -94,7 +94,7 @@ public class PanoramaRenderer {
|
||||
blurProgram.unbind();
|
||||
}
|
||||
|
||||
private static <T> GlProgram<T> loadProgram(String name, String vertBase, String fragBase, Function<ShaderBindingContext, T> factory) {
|
||||
public static <T> GlProgram<T> loadProgram(String name, String vertBase, String fragBase, Function<ShaderBindingContext, T> factory) {
|
||||
final GlShader vert = ShaderLoader.loadShader(ShaderType.VERTEX, vertBase + ".vert", ShaderConstants.EMPTY);
|
||||
final GlShader frag = ShaderLoader.loadShader(ShaderType.FRAGMENT, fragBase + ".frag", ShaderConstants.EMPTY);
|
||||
try {
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
#version 330 core
|
||||
|
||||
in vec2 v_TexCoord;
|
||||
|
||||
uniform sampler2D u_Texture;
|
||||
uniform sampler2D u_Depth;
|
||||
|
||||
out vec4 fragColor;
|
||||
|
||||
void main() {
|
||||
fragColor = texture(u_Texture, v_TexCoord);
|
||||
gl_FragDepth = texture(u_Depth, v_TexCoord).r;
|
||||
}
|
||||
Reference in new issue
Block a user