mirror of
https://github.com/GTNewHorizons/Angelica.git
synced 2026-11-08 12:35:01 +00:00
Properly handle display lists with the push/pop optimizations (#2126)
This commit is contained in:
1 parent
9dd60f6a75
commit
53776684c8
5 files changed
+361
-23
No files matched your search
@@ -79,6 +79,8 @@ public class DisplayListManager {
|
||||
// Display list compilation state (current/active context)
|
||||
private static int glListMode = 0;
|
||||
private static int glListId = -1;
|
||||
private static int recordedStatePushes;
|
||||
private static final DisplayListCommand POP_STATE = GLStateManager::popState;
|
||||
private static CommandRecorder currentRecorder = null; // Command recorder (null when not recording)
|
||||
private static volatile Thread recordingThread = null; // Thread that started recording (for thread-safety)
|
||||
private static List<AccumulatedDraw> accumulatedDraws = null; // Accumulates quad draws for batching
|
||||
@@ -114,6 +116,7 @@ public class DisplayListManager {
|
||||
List<AccumulatedDraw> draws,
|
||||
DisplayListCallback callback,
|
||||
StackTraceElement[] stackTrace,
|
||||
int recordedStatePushes,
|
||||
|
||||
// Debug logging fields (only used when LOG_DISPLAY_LIST_COMPILATION)
|
||||
List<String> pendingOps,
|
||||
@@ -451,6 +454,25 @@ public class DisplayListManager {
|
||||
currentRecorder.writePopAttrib();
|
||||
}
|
||||
|
||||
public static int virtualStateDepth(RecordMode mode) {
|
||||
return mode == RecordMode.COMPILE ? recordedStatePushes : 0;
|
||||
}
|
||||
|
||||
public static void recordPushState(StateSet set) {
|
||||
currentRecorder.writeComplexCommand(set.pushCommand);
|
||||
recordedStatePushes++;
|
||||
}
|
||||
|
||||
public static boolean recordPopStateIfPending() {
|
||||
if (recordedStatePushes > 0) {
|
||||
drawBarrier();
|
||||
currentRecorder.writeComplexCommand(POP_STATE);
|
||||
recordedStatePushes--;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void recordFogf(int pname, float param) {
|
||||
drawBarrier();
|
||||
currentRecorder.writeFogf(pname, param);
|
||||
@@ -775,7 +797,7 @@ public class DisplayListManager {
|
||||
// Save current compilation context and start fresh for nested list
|
||||
final CompilationContext parentContext = new CompilationContext(
|
||||
glListId, glListMode, currentRecorder, accumulatedDraws, transformCallback,
|
||||
compilationStackTrace, pendingTransformOps, multMatrixSources, drawRangeSources
|
||||
compilationStackTrace, recordedStatePushes, pendingTransformOps, multMatrixSources, drawRangeSources
|
||||
);
|
||||
compilationStack.push(parentContext);
|
||||
}
|
||||
@@ -787,6 +809,7 @@ public class DisplayListManager {
|
||||
currentRecorder = new CommandRecorder(); // Create command recorder
|
||||
accumulatedDraws = new ArrayList<>(8); // Fewer draws than commands typically
|
||||
transformCallback = new DisplayListCallback();
|
||||
recordedStatePushes = 0;
|
||||
compilationStackTrace = SystemProperties.LOG_DISPLAY_LIST_COMPILATION ? Thread.currentThread().getStackTrace() : null;
|
||||
|
||||
// Initialize debug logging fields (only when logging enabled)
|
||||
@@ -831,6 +854,12 @@ public class DisplayListManager {
|
||||
// Stop compiling mode (works for both root and nested lists now)
|
||||
TessellatorManager.stopCapturingDirect();
|
||||
|
||||
boolean unbalancedStatePush = false;
|
||||
while (recordPopStateIfPending()) unbalancedStatePush = true;
|
||||
if (unbalancedStatePush) {
|
||||
GLStateManager.warnOnce("unbalanced-state-push", "Display list {} ended with unpopped internal state pushes - closing them", glListId);
|
||||
}
|
||||
|
||||
flushAll();
|
||||
|
||||
// Reset back to MODELVIEW (default state)
|
||||
@@ -921,6 +950,7 @@ public class DisplayListManager {
|
||||
accumulatedDraws = parentContext.draws;
|
||||
transformCallback = parentContext.callback;
|
||||
compilationStackTrace = parentContext.stackTrace;
|
||||
recordedStatePushes = parentContext.recordedStatePushes;
|
||||
pendingTransformOps = parentContext.pendingOps;
|
||||
multMatrixSources = parentContext.matrixSources;
|
||||
drawRangeSources = parentContext.drawSources;
|
||||
@@ -946,6 +976,7 @@ public class DisplayListManager {
|
||||
drawRangeSources = null;
|
||||
glListId = -1;
|
||||
glListMode = 0;
|
||||
recordedStatePushes = 0;
|
||||
}
|
||||
|
||||
public static void abortCompilation() {
|
||||
|
||||
@@ -233,7 +233,7 @@ public class GLStateManager {
|
||||
public static ContextCapabilities capabilities;
|
||||
|
||||
// Software stack depths for FFP emulation
|
||||
public static final int MAX_ATTRIB_STACK_DEPTH = 16 + 2;
|
||||
public static final int MAX_ATTRIB_STACK_DEPTH = 32;
|
||||
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;
|
||||
@@ -3731,15 +3731,27 @@ public class GLStateManager {
|
||||
}
|
||||
|
||||
public static void pushState(int mask) {
|
||||
pushState(StateSet.forMask(mask));
|
||||
pushStateLive(StateSet.forMask(mask));
|
||||
}
|
||||
|
||||
public static int pushState(StateSet set) {
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
if (mode != RecordMode.NONE) {
|
||||
final int token = ctx().attribDepth + DisplayListManager.virtualStateDepth(mode);
|
||||
if (token >= MAX_ATTRIB_STACK_DEPTH) {
|
||||
throw new IllegalStateException("Attrib stack overflow: max depth " + MAX_ATTRIB_STACK_DEPTH + " reached");
|
||||
}
|
||||
DisplayListManager.recordPushState(set);
|
||||
if (mode == RecordMode.COMPILE) {
|
||||
return token;
|
||||
}
|
||||
}
|
||||
return pushStateLive(set);
|
||||
}
|
||||
|
||||
static int pushStateLive(StateSet set) {
|
||||
attribPushes++;
|
||||
final GLContextState glCtx = ctx();
|
||||
if (set.glMask == 0 && DisplayListManager.getRecordMode() == RecordMode.COMPILE) {
|
||||
throw new IllegalStateException("Internal state set pushed while compiling a display list");
|
||||
}
|
||||
if (glCtx.attribDepth >= MAX_ATTRIB_STACK_DEPTH) {
|
||||
throw new IllegalStateException("Attrib stack overflow: max depth " + MAX_ATTRIB_STACK_DEPTH + " reached");
|
||||
}
|
||||
@@ -3783,7 +3795,10 @@ public class GLStateManager {
|
||||
|
||||
public static void popStateTo(int depth) {
|
||||
final GLContextState glCtx = ctx();
|
||||
while (glCtx.attribDepth > depth) {
|
||||
final RecordMode mode = DisplayListManager.getRecordMode();
|
||||
while (glCtx.attribDepth + DisplayListManager.virtualStateDepth(mode) > depth) {
|
||||
if (mode == RecordMode.COMPILE && DisplayListManager.recordPopStateIfPending()) continue;
|
||||
if (mode == RecordMode.COMPILE_AND_EXECUTE) DisplayListManager.recordPopStateIfPending();
|
||||
popState();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.gtnewhorizons.angelica.glsm;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.recording.commands.DisplayListCommand;
|
||||
import com.gtnewhorizons.angelica.glsm.stacks.CowStateStack;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
@@ -38,6 +39,7 @@ public final class StateSet {
|
||||
public final int restore;
|
||||
public final int bump;
|
||||
public final boolean blendSnapshot;
|
||||
public final DisplayListCommand pushCommand;
|
||||
|
||||
StateSet(int glMask, long[] members, int restore, int bump, boolean blendSnapshot) {
|
||||
this.glMask = glMask;
|
||||
@@ -45,6 +47,7 @@ public final class StateSet {
|
||||
this.restore = restore;
|
||||
this.bump = bump;
|
||||
this.blendSnapshot = blendSnapshot;
|
||||
this.pushCommand = () -> GLStateManager.pushStateLive(this);
|
||||
}
|
||||
|
||||
public boolean contains(int id) {
|
||||
|
||||
+305
@@ -0,0 +1,305 @@
|
||||
package com.gtnewhorizons.angelica.glsm;
|
||||
|
||||
import com.gtnewhorizons.angelica.glsm.recording.CompiledDisplayList;
|
||||
import com.gtnewhorizons.angelica.glsm.recording.GLCommand;
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntMap;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL13;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static com.gtnewhorizons.angelica.util.GLSMUtil.verifyIsEnabled;
|
||||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
@GLCoreTest
|
||||
public class GLSM_DisplayList_StateSet_GLTest {
|
||||
|
||||
private final List<Integer> listsToDelete = new ArrayList<>();
|
||||
|
||||
@AfterEach
|
||||
void cleanup() {
|
||||
DisplayListManager.abortCompilation();
|
||||
while (GLStateManager.getAttribDepth() > 0) {
|
||||
GLStateManager.popState();
|
||||
}
|
||||
for (int id : listsToDelete) {
|
||||
GLStateManager.glDeleteLists(id, 1);
|
||||
}
|
||||
listsToDelete.clear();
|
||||
GLStateManager.disableBlend();
|
||||
GLStateManager.disableCull();
|
||||
GLStateManager.glCullFace(GL11.GL_BACK);
|
||||
GLStateManager.disableAlphaTest();
|
||||
GLStateManager.glAlphaFunc(GL11.GL_ALWAYS, 0.0f);
|
||||
GLStateManager.glActiveTexture(GL13.GL_TEXTURE1);
|
||||
GLStateManager.disableTexture();
|
||||
GLStateManager.glActiveTexture(GL13.GL_TEXTURE0);
|
||||
}
|
||||
|
||||
private int newList() {
|
||||
final int id = GLStateManager.glGenLists(1);
|
||||
listsToDelete.add(id);
|
||||
return id;
|
||||
}
|
||||
|
||||
private static Int2IntMap commandCounts(int listId) {
|
||||
final CompiledDisplayList compiled = DisplayListManager.getDisplayList(listId);
|
||||
assertNotNull(compiled, "compiled display list must exist for id " + listId);
|
||||
return compiled.getCommandCounts();
|
||||
}
|
||||
|
||||
@Test
|
||||
void compileBracketDoesNotThrowAndLeavesLiveStateUntouched() {
|
||||
GLStateManager.enableAlphaTest();
|
||||
GLStateManager.glAlphaFunc(GL11.GL_GREATER, 0.5f);
|
||||
GLStateManager.glActiveTexture(GL13.GL_TEXTURE0);
|
||||
|
||||
final int func0 = GLStateManager.getAlphaState().getFunction();
|
||||
final float ref0 = GLStateManager.getAlphaState().getReference();
|
||||
final int unit0 = GLStateManager.getActiveTextureUnit();
|
||||
final int depth0 = GLStateManager.getAttribDepth();
|
||||
|
||||
final int list = newList();
|
||||
GLStateManager.glNewList(list, GL11.GL_COMPILE);
|
||||
final int d = GLStateManager.pushState(StateSet.CUTOUT);
|
||||
GLStateManager.enableAlphaTest();
|
||||
GLStateManager.glAlphaFunc(GL11.GL_GREATER, 0.1f);
|
||||
GLStateManager.glActiveTexture(GL13.GL_TEXTURE1);
|
||||
GLStateManager.enableTexture();
|
||||
GLStateManager.glActiveTexture(GL13.GL_TEXTURE0);
|
||||
GLStateManager.popStateTo(d);
|
||||
GLStateManager.glEndList();
|
||||
|
||||
verifyIsEnabled(GL11.GL_ALPHA_TEST, true, "cache alpha test enable unchanged after COMPILE-only bracket");
|
||||
assertEquals(func0, GLStateManager.getAlphaState().getFunction(), "cache alpha func unchanged after COMPILE-only bracket");
|
||||
assertEquals(ref0, GLStateManager.getAlphaState().getReference(), 0.0001f, "cache alpha ref unchanged after COMPILE-only bracket");
|
||||
assertEquals(unit0, GLStateManager.getActiveTextureUnit(), "cache active unit unchanged after COMPILE-only bracket");
|
||||
assertEquals(depth0, GLStateManager.getAttribDepth(), "live attrib depth unchanged after COMPILE-only bracket");
|
||||
assertEquals(2, commandCounts(list).getOrDefault(GLCommand.COMPLEX_REF, 0), "push and pop each record one COMPLEX_REF");
|
||||
}
|
||||
|
||||
@Test
|
||||
void compiledBracketReplayRestoresState() {
|
||||
final int list = newList();
|
||||
GLStateManager.glNewList(list, GL11.GL_COMPILE);
|
||||
final int d = GLStateManager.pushState(StateSet.CUTOUT);
|
||||
GLStateManager.enableAlphaTest();
|
||||
GLStateManager.glAlphaFunc(GL11.GL_GREATER, 0.1f);
|
||||
GLStateManager.glActiveTexture(GL13.GL_TEXTURE1);
|
||||
GLStateManager.enableTexture();
|
||||
GLStateManager.glActiveTexture(GL13.GL_TEXTURE0);
|
||||
GLStateManager.popStateTo(d);
|
||||
GLStateManager.glEndList();
|
||||
|
||||
GLStateManager.glAlphaFunc(GL11.GL_LESS, 0.9f);
|
||||
GLStateManager.disableAlphaTest();
|
||||
GLStateManager.glActiveTexture(GL13.GL_TEXTURE0);
|
||||
final int depth0 = GLStateManager.getAttribDepth();
|
||||
|
||||
GLStateManager.glCallList(list);
|
||||
|
||||
assertEquals(GL11.GL_LESS, GLStateManager.getAlphaState().getFunction(), "cache alpha func restored by replay");
|
||||
assertEquals(0.9f, GLStateManager.getAlphaState().getReference(), 0.0001f, "cache alpha ref restored by replay");
|
||||
verifyIsEnabled(GL11.GL_ALPHA_TEST, false, "cache alpha test restored disabled by replay");
|
||||
assertEquals(0, GLStateManager.getActiveTextureUnit(), "cache active unit restored by replay");
|
||||
assertEquals(GL13.GL_TEXTURE0, GL11.glGetInteger(GL13.GL_ACTIVE_TEXTURE), "driver active unit restored by replay");
|
||||
assertEquals(depth0, GLStateManager.getAttribDepth(), "live attrib depth unchanged by balanced replay");
|
||||
}
|
||||
|
||||
@Test
|
||||
void compileAndExecuteBracketIsBalanced() {
|
||||
GLStateManager.glAlphaFunc(GL11.GL_LESS, 0.9f);
|
||||
GLStateManager.disableAlphaTest();
|
||||
GLStateManager.glActiveTexture(GL13.GL_TEXTURE0);
|
||||
final int depth0 = GLStateManager.getAttribDepth();
|
||||
|
||||
final int list = newList();
|
||||
GLStateManager.glNewList(list, GL11.GL_COMPILE_AND_EXECUTE);
|
||||
final int d = GLStateManager.pushState(StateSet.CUTOUT);
|
||||
GLStateManager.enableAlphaTest();
|
||||
GLStateManager.glAlphaFunc(GL11.GL_GREATER, 0.1f);
|
||||
GLStateManager.glActiveTexture(GL13.GL_TEXTURE1);
|
||||
GLStateManager.enableTexture();
|
||||
GLStateManager.glActiveTexture(GL13.GL_TEXTURE0);
|
||||
GLStateManager.popStateTo(d);
|
||||
GLStateManager.glEndList();
|
||||
|
||||
assertEquals(GL11.GL_LESS, GLStateManager.getAlphaState().getFunction(), "cache alpha func restored after GL_COMPILE_AND_EXECUTE bracket");
|
||||
assertEquals(0.9f, GLStateManager.getAlphaState().getReference(), 0.0001f, "cache alpha ref restored after GL_COMPILE_AND_EXECUTE bracket");
|
||||
verifyIsEnabled(GL11.GL_ALPHA_TEST, false, "cache alpha test restored disabled after GL_COMPILE_AND_EXECUTE bracket");
|
||||
assertEquals(0, GLStateManager.getActiveTextureUnit(), "cache active unit restored after GL_COMPILE_AND_EXECUTE bracket");
|
||||
assertEquals(depth0, GLStateManager.getAttribDepth(), "live attrib depth unchanged after balanced GL_COMPILE_AND_EXECUTE bracket");
|
||||
|
||||
GLStateManager.glCallList(list);
|
||||
GLStateManager.glCallList(list);
|
||||
|
||||
assertEquals(GL11.GL_LESS, GLStateManager.getAlphaState().getFunction(), "cache alpha func restored after replay");
|
||||
assertEquals(0.9f, GLStateManager.getAlphaState().getReference(), 0.0001f, "cache alpha ref restored after replay");
|
||||
verifyIsEnabled(GL11.GL_ALPHA_TEST, false, "cache alpha test restored disabled after replay");
|
||||
assertEquals(0, GLStateManager.getActiveTextureUnit(), "cache active unit restored after replay");
|
||||
assertEquals(depth0, GLStateManager.getAttribDepth(), "live attrib depth unchanged after replay");
|
||||
}
|
||||
|
||||
@Test
|
||||
void nestedListsPushInBothLevels() {
|
||||
GLStateManager.enableBlend();
|
||||
GLStateManager.enableCull();
|
||||
GLStateManager.glCullFace(GL11.GL_BACK);
|
||||
final boolean cull0 = GLStateManager.glIsEnabled(GL11.GL_CULL_FACE);
|
||||
final int depth0 = GLStateManager.getAttribDepth();
|
||||
|
||||
final int parent = newList();
|
||||
final int child = newList();
|
||||
|
||||
GLStateManager.glNewList(parent, GL11.GL_COMPILE);
|
||||
final int dParent = GLStateManager.pushState(StateSet.BLEND);
|
||||
GLStateManager.glNewList(child, GL11.GL_COMPILE);
|
||||
final int dChild = GLStateManager.pushState(StateSet.CULL);
|
||||
if (cull0) {
|
||||
GLStateManager.disableCull();
|
||||
} else {
|
||||
GLStateManager.enableCull();
|
||||
}
|
||||
GLStateManager.popStateTo(dChild);
|
||||
GLStateManager.glEndList();
|
||||
GLStateManager.disableBlend();
|
||||
GLStateManager.popStateTo(dParent);
|
||||
GLStateManager.glEndList();
|
||||
|
||||
assertEquals(depth0, GLStateManager.getAttribDepth(), "live attrib depth unchanged by nested COMPILE-only bracket");
|
||||
|
||||
GLStateManager.glCallList(parent);
|
||||
verifyIsEnabled(GL11.GL_BLEND, true, "blend enable restored by the parent BLEND bracket after parent replay");
|
||||
verifyIsEnabled(GL11.GL_CULL_FACE, cull0, "cull enable restored after parent replay");
|
||||
|
||||
GLStateManager.glCallList(child);
|
||||
verifyIsEnabled(GL11.GL_CULL_FACE, cull0, "cull enable restored after child replay");
|
||||
}
|
||||
|
||||
@Test
|
||||
void nestedCompileAndExecuteChildInsideCompileParent() {
|
||||
GLStateManager.enableCull();
|
||||
GLStateManager.glCullFace(GL11.GL_BACK);
|
||||
final boolean cull0 = GLStateManager.glIsEnabled(GL11.GL_CULL_FACE);
|
||||
final int depth0 = GLStateManager.getAttribDepth();
|
||||
|
||||
final int parent = newList();
|
||||
final int child = newList();
|
||||
|
||||
GLStateManager.glNewList(parent, GL11.GL_COMPILE);
|
||||
final int dParent = GLStateManager.pushState(StateSet.BLEND);
|
||||
|
||||
GLStateManager.glNewList(child, GL11.GL_COMPILE_AND_EXECUTE);
|
||||
final int dChild = GLStateManager.pushState(StateSet.CULL);
|
||||
if (cull0) {
|
||||
GLStateManager.disableCull();
|
||||
} else {
|
||||
GLStateManager.enableCull();
|
||||
}
|
||||
GLStateManager.popStateTo(dChild);
|
||||
GLStateManager.glEndList();
|
||||
|
||||
verifyIsEnabled(GL11.GL_CULL_FACE, cull0, "cull enable restored live immediately after the COMPILE_AND_EXECUTE child bracket closes");
|
||||
|
||||
GLStateManager.popStateTo(dParent);
|
||||
GLStateManager.glEndList();
|
||||
|
||||
assertEquals(depth0, GLStateManager.getAttribDepth(), "live attrib depth unchanged after balanced nested bracket");
|
||||
assertEquals(2, commandCounts(parent).getOrDefault(GLCommand.COMPLEX_REF, 0), "parent list records exactly the BLEND push and pop");
|
||||
assertEquals(2, commandCounts(child).getOrDefault(GLCommand.COMPLEX_REF, 0), "child list records exactly the CULL push and pop");
|
||||
}
|
||||
|
||||
@Test
|
||||
void unbalancedBracketIsClosedAtEndList() {
|
||||
GLStateManager.enableBlend();
|
||||
final boolean blend0 = GLStateManager.glIsEnabled(GL11.GL_BLEND);
|
||||
final int depth0 = GLStateManager.getAttribDepth();
|
||||
|
||||
final int list = newList();
|
||||
GLStateManager.glNewList(list, GL11.GL_COMPILE);
|
||||
GLStateManager.pushState(StateSet.BATCH);
|
||||
GLStateManager.disableBlend();
|
||||
GLStateManager.glEndList();
|
||||
|
||||
assertEquals(2, commandCounts(list).getOrDefault(GLCommand.COMPLEX_REF, 0), "glEndList closes the unbalanced push, recording a matching pop");
|
||||
|
||||
GLStateManager.glCallList(list);
|
||||
assertEquals(depth0, GLStateManager.getAttribDepth(), "live attrib depth unchanged after replaying an auto-closed bracket");
|
||||
verifyIsEnabled(GL11.GL_BLEND, blend0, "blend enable unchanged after replaying an auto-closed bracket");
|
||||
|
||||
final int other = newList();
|
||||
assertDoesNotThrow(() -> {
|
||||
GLStateManager.glNewList(other, GL11.GL_COMPILE);
|
||||
GLStateManager.glEndList();
|
||||
}, "an unrelated list must compile normally after an auto-closed bracket");
|
||||
}
|
||||
|
||||
@Test
|
||||
void glPushAttribRecordsExactlyOnce() {
|
||||
final int list = newList();
|
||||
GLStateManager.glNewList(list, GL11.GL_COMPILE);
|
||||
GLStateManager.glPushAttrib(GL11.GL_ENABLE_BIT);
|
||||
GLStateManager.glPopAttrib();
|
||||
GLStateManager.glEndList();
|
||||
|
||||
final Int2IntMap counts = commandCounts(list);
|
||||
assertEquals(1, counts.getOrDefault(GLCommand.PUSH_ATTRIB, 0), "glPushAttrib records exactly one PUSH_ATTRIB opcode");
|
||||
assertEquals(1, counts.getOrDefault(GLCommand.POP_ATTRIB, 0), "glPopAttrib records exactly one POP_ATTRIB opcode");
|
||||
assertEquals(0, counts.getOrDefault(GLCommand.COMPLEX_REF, 0), "glPushAttrib/glPopAttrib never record a COMPLEX_REF");
|
||||
}
|
||||
|
||||
@Test
|
||||
void livePushStraddlesOpenList() {
|
||||
GLStateManager.enableBlend();
|
||||
final int d = GLStateManager.pushState(StateSet.BLEND);
|
||||
GLStateManager.disableBlend();
|
||||
|
||||
final int list = newList();
|
||||
GLStateManager.glNewList(list, GL11.GL_COMPILE);
|
||||
GLStateManager.glEndList();
|
||||
|
||||
GLStateManager.popStateTo(d);
|
||||
|
||||
assertEquals(d, GLStateManager.getAttribDepth(), "live attrib depth restored to the pre-bracket value");
|
||||
verifyIsEnabled(GL11.GL_BLEND, true, "blend enable restored by the live pop that straddled the open-then-closed list");
|
||||
}
|
||||
|
||||
@Test
|
||||
void livePopInsideOpenListPopsLiveAndRecordsNothing() {
|
||||
GLStateManager.enableBlend();
|
||||
final int d = GLStateManager.pushState(StateSet.BLEND);
|
||||
GLStateManager.disableBlend();
|
||||
|
||||
final int list = newList();
|
||||
GLStateManager.glNewList(list, GL11.GL_COMPILE);
|
||||
GLStateManager.popStateTo(d);
|
||||
GLStateManager.glEndList();
|
||||
|
||||
assertEquals(d, GLStateManager.getAttribDepth(), "live attrib depth restored by the live pop performed inside the open list");
|
||||
verifyIsEnabled(GL11.GL_BLEND, true, "blend enable restored live by the pop of a pre-list push");
|
||||
assertEquals(0, commandCounts(list).getOrDefault(GLCommand.COMPLEX_REF, 0), "popping a pre-existing live push records nothing into the list");
|
||||
}
|
||||
|
||||
@Test
|
||||
void virtualDepthOverflowThrowsAtRecordTime() {
|
||||
final int startDepth = GLStateManager.getAttribDepth();
|
||||
final int list = newList();
|
||||
GLStateManager.glNewList(list, GL11.GL_COMPILE);
|
||||
|
||||
final int pushes = GLStateManager.MAX_ATTRIB_STACK_DEPTH - startDepth;
|
||||
for (int i = 0; i < pushes; i++) {
|
||||
GLStateManager.pushState(StateSet.CUTOUT);
|
||||
}
|
||||
assertThrows(IllegalStateException.class, () -> GLStateManager.pushState(StateSet.CUTOUT), "virtual depth overflow beyond MAX_ATTRIB_STACK_DEPTH must throw at record time");
|
||||
|
||||
DisplayListManager.abortCompilation();
|
||||
|
||||
assertEquals(startDepth, GLStateManager.getAttribDepth(), "aborting the overflowed compilation leaves live attrib depth untouched");
|
||||
}
|
||||
}
|
||||
@@ -495,22 +495,6 @@ public class GLSM_StateSet_GLTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void internalPushDuringDisplayListCompileThrowsAndLeavesDepthUnchanged() {
|
||||
final int list = GLStateManager.glGenLists(1);
|
||||
final int depthBefore = GLStateManager.getAttribDepth();
|
||||
try {
|
||||
GLStateManager.glNewList(list, GL11.GL_COMPILE);
|
||||
assertThrows(IllegalStateException.class, () -> GLStateManager.pushState(StateSet.BLEND));
|
||||
GLStateManager.pushState(StateSet.forMask(GL11.GL_COLOR_BUFFER_BIT));
|
||||
GLStateManager.popState();
|
||||
assertEquals(depthBefore, GLStateManager.getAttribDepth(), "mask-based push/pop is recorded, not executed, and leaves live depth unchanged");
|
||||
} finally {
|
||||
GLStateManager.glEndList();
|
||||
GLStateManager.glDeleteLists(list, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void allAttribBitsNestedInsideInternalBracketRestoresBothLevels() {
|
||||
try {
|
||||
|
||||
Reference in new issue
Block a user