mirror of
https://github.com/GTNewHorizons/Angelica.git
synced 2026-10-26 14:24:30 +00:00
Add unknown blend state and BufferBlendOverride handling from modern Iris (#1408)
This commit is contained in:
1 parent
ad123d0bd5
commit
0325a96bc2
8 files changed
+224
-21
No files matched your search
@@ -1788,6 +1788,7 @@ public class GLStateManager {
|
||||
if (DisplayListManager.isRecording()) {
|
||||
throw new UnsupportedOperationException("glDrawElements in display lists not yet implemented - if you see this, please report!");
|
||||
}
|
||||
BlendModeStorage.flushDeferredBlend();
|
||||
GL11.glDrawElements(mode, indices);
|
||||
}
|
||||
|
||||
@@ -1795,6 +1796,7 @@ public class GLStateManager {
|
||||
if (DisplayListManager.isRecording()) {
|
||||
throw new UnsupportedOperationException("glDrawElements in display lists not yet implemented - if you see this, please report!");
|
||||
}
|
||||
BlendModeStorage.flushDeferredBlend();
|
||||
GL11.glDrawElements(mode, indices);
|
||||
}
|
||||
|
||||
@@ -1802,6 +1804,7 @@ public class GLStateManager {
|
||||
if (DisplayListManager.isRecording()) {
|
||||
throw new UnsupportedOperationException("glDrawElements in display lists not yet implemented - if you see this, please report!");
|
||||
}
|
||||
BlendModeStorage.flushDeferredBlend();
|
||||
GL11.glDrawElements(mode, indices);
|
||||
}
|
||||
|
||||
@@ -1809,6 +1812,7 @@ public class GLStateManager {
|
||||
if (DisplayListManager.isRecording()) {
|
||||
throw new UnsupportedOperationException("glDrawElements in display lists not yet implemented - if you see this, please report!");
|
||||
}
|
||||
BlendModeStorage.flushDeferredBlend();
|
||||
GL11.glDrawElements(mode, count, type, indices);
|
||||
}
|
||||
|
||||
@@ -1824,6 +1828,7 @@ public class GLStateManager {
|
||||
return;
|
||||
}
|
||||
}
|
||||
BlendModeStorage.flushDeferredBlend();
|
||||
GL11.glDrawElements(mode, indices_count, type, indices_buffer_offset);
|
||||
}
|
||||
|
||||
@@ -1850,6 +1855,7 @@ public class GLStateManager {
|
||||
}
|
||||
return;
|
||||
}
|
||||
BlendModeStorage.flushDeferredBlend();
|
||||
GL11.glDrawArrays(mode, first, count);
|
||||
}
|
||||
|
||||
|
||||
@@ -347,10 +347,12 @@ public class RenderSystem {
|
||||
|
||||
public static void disableBufferBlend(int buffer) {
|
||||
GL30.glDisablei(GL11.GL_BLEND, buffer);
|
||||
GLStateManager.getBlendMode().setUnknownState();
|
||||
}
|
||||
|
||||
public static void enableBufferBlend(int buffer) {
|
||||
GL30.glEnablei(GL11.GL_BLEND, buffer);
|
||||
GLStateManager.getBlendMode().setUnknownState();
|
||||
}
|
||||
|
||||
public static void blendFuncSeparatei(int buffer, int srcRGB, int dstRGB, int srcAlpha, int dstAlpha) {
|
||||
|
||||
@@ -8,11 +8,16 @@ public class BooleanState implements ISettableState<BooleanState> {
|
||||
protected final int glCap;
|
||||
|
||||
@Getter protected boolean enabled;
|
||||
protected boolean stateUnknown;
|
||||
|
||||
public BooleanState(int glCap) {
|
||||
this.glCap = glCap;
|
||||
}
|
||||
|
||||
public void setUnknownState() {
|
||||
stateUnknown = true;
|
||||
}
|
||||
|
||||
public void disable() {
|
||||
this.setEnabled(false);
|
||||
}
|
||||
@@ -23,7 +28,8 @@ public class BooleanState implements ISettableState<BooleanState> {
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
final boolean bypass = GLStateManager.shouldBypassCache();
|
||||
if (bypass || enabled != this.enabled || (this.glCap == GL11.GL_BLEND && GLStateManager.vendorIsAMD() && GLStateManager.isPoppingAttributes())) {
|
||||
if (stateUnknown || bypass || enabled != this.enabled || (this.glCap == GL11.GL_BLEND && GLStateManager.vendorIsAMD() && GLStateManager.isPoppingAttributes())) {
|
||||
stateUnknown = false;
|
||||
if (!bypass) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
package net.coderbot.iris.celeritas;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.primitives.Ints;
|
||||
import lombok.Getter;
|
||||
import lombok.experimental.Accessors;
|
||||
import net.coderbot.iris.Iris;
|
||||
import net.coderbot.iris.gl.blending.BlendModeOverride;
|
||||
import net.coderbot.iris.gl.blending.BufferBlendOverride;
|
||||
import net.coderbot.iris.gl.framebuffer.GlFramebuffer;
|
||||
import net.coderbot.iris.shaderpack.loading.ProgramId;
|
||||
import net.coderbot.iris.gl.program.ProgramImages;
|
||||
import net.coderbot.iris.gl.program.ProgramSamplers;
|
||||
import net.coderbot.iris.gl.program.ProgramUniforms;
|
||||
@@ -19,7 +22,10 @@ import net.coderbot.iris.shaderpack.ProgramSource;
|
||||
import net.coderbot.iris.uniforms.custom.CustomUniforms;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
@@ -43,6 +49,7 @@ public class CeleritasTerrainPipeline {
|
||||
private final EnumMap<PatchShaderType, Optional<String>> sources = new EnumMap<>(PatchShaderType.class);
|
||||
private GlFramebuffer framebuffer;
|
||||
private BlendModeOverride blendModeOverride;
|
||||
private List<BufferBlendOverride> bufferBlendOverrides;
|
||||
private float alphaReference;
|
||||
|
||||
private PassInfo() {
|
||||
@@ -91,21 +98,41 @@ public class CeleritasTerrainPipeline {
|
||||
PassInfo passInfo = new PassInfo();
|
||||
passInfoMap.put(pass, passInfo);
|
||||
|
||||
// Set up framebuffer
|
||||
// Set up framebuffer, blend mode, and buffer blend overrides
|
||||
final ProgramId programId = switch (pass) {
|
||||
case GBUFFER_TRANSLUCENT -> ProgramId.Water;
|
||||
case SHADOW, SHADOW_CUTOUT -> ProgramId.Shadow;
|
||||
default -> ProgramId.Terrain;
|
||||
};
|
||||
|
||||
if (pass == IrisTerrainPass.SHADOW || pass == IrisTerrainPass.SHADOW_CUTOUT) {
|
||||
passInfo.framebuffer = shadowFramebuffer;
|
||||
passInfo.blendModeOverride = programId.getBlendModeOverride();
|
||||
passInfo.bufferBlendOverrides = Collections.emptyList();
|
||||
} else if (renderTargets != null) {
|
||||
ImmutableSet<Integer> flipped = pass == IrisTerrainPass.GBUFFER_TRANSLUCENT ? flippedAfterTranslucent : flippedAfterPrepare;
|
||||
|
||||
Optional<ProgramSource> programSource = gbufferProgramSource.get(pass);
|
||||
programSource.ifPresentOrElse(source -> passInfo.framebuffer = renderTargets.createGbufferFramebuffer(flipped, source.getDirectives().getDrawBuffers()), () -> passInfo.framebuffer = renderTargets.createGbufferFramebuffer(flipped, new int[] {0}));
|
||||
}
|
||||
programSource.ifPresentOrElse(source -> {
|
||||
passInfo.framebuffer = renderTargets.createGbufferFramebuffer(flipped, source.getDirectives().getDrawBuffers());
|
||||
passInfo.blendModeOverride = source.getDirectives().getBlendModeOverride().orElse(programId.getBlendModeOverride());
|
||||
|
||||
// Set blend mode override
|
||||
passInfo.blendModeOverride = switch (pass) {
|
||||
case GBUFFER_TRANSLUCENT -> null; // Default blending
|
||||
default -> BlendModeOverride.OFF;
|
||||
};
|
||||
passInfo.bufferBlendOverrides = new ArrayList<>();
|
||||
source.getDirectives().getBufferBlendOverrides().forEach(information -> {
|
||||
int index = Ints.indexOf(source.getDirectives().getDrawBuffers(), information.getIndex());
|
||||
if (index > -1) {
|
||||
passInfo.bufferBlendOverrides.add(new BufferBlendOverride(index, information.getBlendMode()));
|
||||
}
|
||||
});
|
||||
}, () -> {
|
||||
passInfo.framebuffer = renderTargets.createGbufferFramebuffer(flipped, new int[] {0});
|
||||
passInfo.blendModeOverride = programId.getBlendModeOverride();
|
||||
passInfo.bufferBlendOverrides = Collections.emptyList();
|
||||
});
|
||||
} else {
|
||||
passInfo.blendModeOverride = programId.getBlendModeOverride();
|
||||
passInfo.bufferBlendOverrides = Collections.emptyList();
|
||||
}
|
||||
|
||||
// Set alpha reference
|
||||
passInfo.alphaReference = switch (pass) {
|
||||
|
||||
@@ -2,6 +2,7 @@ package net.coderbot.iris.celeritas;
|
||||
|
||||
import net.coderbot.iris.Iris;
|
||||
import net.coderbot.iris.gl.blending.BlendModeOverride;
|
||||
import net.coderbot.iris.gl.blending.BufferBlendOverride;
|
||||
import net.coderbot.iris.pipeline.WorldRenderingPipeline;
|
||||
import net.coderbot.iris.pipeline.transform.PatchShaderType;
|
||||
import net.coderbot.iris.shadows.ShadowRenderingState;
|
||||
@@ -15,6 +16,7 @@ import org.embeddedt.embeddium.impl.render.chunk.terrain.TerrainRenderPass;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.EnumMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Optional;
|
||||
|
||||
@@ -82,11 +84,11 @@ public class IrisCeleritasChunkProgramOverrides {
|
||||
builder.bindAttribute(attr.getName(), attrIndex++);
|
||||
}
|
||||
|
||||
// Get blend from PassInfo
|
||||
final CeleritasTerrainPipeline.PassInfo passInfo = pipeline.getPassInfo(pass);
|
||||
final BlendModeOverride blendOverride = passInfo.blendModeOverride();
|
||||
final List<BufferBlendOverride> bufferOverrides = passInfo.bufferBlendOverrides();
|
||||
|
||||
return builder.link(context -> new IrisCeleritasChunkShaderInterface(((GlObject) context).handle(), context, pipeline, pass.isShadow(), blendOverride, pipeline.getCustomUniforms()));
|
||||
return builder.link(context -> new IrisCeleritasChunkShaderInterface(((GlObject) context).handle(), context, pipeline, pass.isShadow(), blendOverride, bufferOverrides, pipeline.getCustomUniforms()));
|
||||
} finally {
|
||||
vertShader.delete();
|
||||
if (geomShader != null) geomShader.delete();
|
||||
|
||||
@@ -4,6 +4,7 @@ import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import com.gtnewhorizons.angelica.mixins.interfaces.EntityRendererAccessor;
|
||||
import net.coderbot.iris.Iris;
|
||||
import net.coderbot.iris.gl.blending.BlendModeOverride;
|
||||
import net.coderbot.iris.gl.blending.BufferBlendOverride;
|
||||
import net.coderbot.iris.gl.framebuffer.GlFramebuffer;
|
||||
import net.coderbot.iris.pipeline.WorldRenderingPipeline;
|
||||
import net.coderbot.iris.samplers.IrisSamplers;
|
||||
@@ -16,6 +17,7 @@ import net.coderbot.iris.gl.program.ProgramSamplers;
|
||||
import net.coderbot.iris.gl.program.ProgramUniforms;
|
||||
import net.coderbot.iris.shadows.ShadowRenderingState;
|
||||
import net.coderbot.iris.uniforms.custom.CustomUniforms;
|
||||
import java.util.List;
|
||||
import org.embeddedt.embeddium.impl.gl.shader.ShaderBindingContext;
|
||||
import org.embeddedt.embeddium.impl.gl.shader.uniform.GlUniformFloat3v;
|
||||
import org.embeddedt.embeddium.impl.gl.shader.uniform.GlUniformMatrix3f;
|
||||
@@ -51,13 +53,15 @@ public class IrisCeleritasChunkShaderInterface implements ChunkShaderInterface {
|
||||
|
||||
// Rendering state
|
||||
private final BlendModeOverride blendModeOverride;
|
||||
private final List<BufferBlendOverride> bufferBlendOverrides;
|
||||
private final boolean hasOverrides;
|
||||
|
||||
// Stored matrices for inverse and normal matrix computation
|
||||
private final Matrix4f projectionMatrixInverse = new Matrix4f();
|
||||
private final Matrix4f modelViewMatrixInverse = new Matrix4f();
|
||||
private final Matrix3f normalMatrix = new Matrix3f();
|
||||
|
||||
public IrisCeleritasChunkShaderInterface(int handle, ShaderBindingContext context, CeleritasTerrainPipeline pipeline, boolean isShadowPass, BlendModeOverride blendModeOverride, CustomUniforms customUniforms) {
|
||||
public IrisCeleritasChunkShaderInterface(int handle, ShaderBindingContext context, CeleritasTerrainPipeline pipeline, boolean isShadowPass, BlendModeOverride blendModeOverride, List<BufferBlendOverride> bufferBlendOverrides, CustomUniforms customUniforms) {
|
||||
this.uniformModelViewMatrix = context.bindUniformIfPresent("iris_ModelViewMatrix", GlUniformMatrix4f::new);
|
||||
this.uniformModelViewMatrixInverse = context.bindUniformIfPresent("iris_ModelViewMatrixInverse", GlUniformMatrix4f::new);
|
||||
this.uniformProjectionMatrix = context.bindUniformIfPresent("iris_ProjectionMatrix", GlUniformMatrix4f::new);
|
||||
@@ -66,6 +70,8 @@ public class IrisCeleritasChunkShaderInterface implements ChunkShaderInterface {
|
||||
this.uniformRegionOffset = context.bindUniformIfPresent("u_RegionOffset", GlUniformFloat3v::new);
|
||||
|
||||
this.blendModeOverride = blendModeOverride;
|
||||
this.bufferBlendOverrides = bufferBlendOverrides;
|
||||
this.hasOverrides = bufferBlendOverrides != null && !bufferBlendOverrides.isEmpty();
|
||||
this.customUniforms = customUniforms;
|
||||
|
||||
final ProgramUniforms.Builder builder = pipeline.initUniforms(handle);
|
||||
@@ -94,6 +100,10 @@ public class IrisCeleritasChunkShaderInterface implements ChunkShaderInterface {
|
||||
blendModeOverride.apply();
|
||||
}
|
||||
|
||||
if (hasOverrides) {
|
||||
bufferBlendOverrides.forEach(BufferBlendOverride::apply);
|
||||
}
|
||||
|
||||
if (irisProgramUniforms != null) {
|
||||
irisProgramUniforms.update();
|
||||
}
|
||||
@@ -109,7 +119,7 @@ public class IrisCeleritasChunkShaderInterface implements ChunkShaderInterface {
|
||||
|
||||
@Override
|
||||
public void restoreState() {
|
||||
if (blendModeOverride != null) {
|
||||
if (blendModeOverride != null || hasOverrides) {
|
||||
BlendModeOverride.restore();
|
||||
}
|
||||
|
||||
|
||||
@@ -4,29 +4,41 @@ import com.gtnewhorizons.angelica.glsm.GLStateManager;
|
||||
import com.gtnewhorizons.angelica.glsm.RenderSystem;
|
||||
import com.gtnewhorizons.angelica.glsm.states.BlendState;
|
||||
import lombok.Getter;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL14;
|
||||
|
||||
public class BlendModeStorage {
|
||||
private static final int MAX_DRAW_BUFFERS = 8;
|
||||
|
||||
private static boolean originalBlendEnable;
|
||||
private static final BlendState originalBlend = new BlendState();
|
||||
@Getter private static boolean blendLocked;
|
||||
@Getter private static boolean hasDeferredChanges;
|
||||
private static final int[] bufferOverrideIndices = new int[MAX_DRAW_BUFFERS];
|
||||
private static final boolean[] bufferOverrideIsDisable = new boolean[MAX_DRAW_BUFFERS];
|
||||
private static final BlendState[] bufferOverrideStates = new BlendState[MAX_DRAW_BUFFERS];
|
||||
private static int bufferOverrideCount;
|
||||
|
||||
static {
|
||||
for (int i = 0; i < MAX_DRAW_BUFFERS; i++) {
|
||||
bufferOverrideStates[i] = new BlendState();
|
||||
}
|
||||
}
|
||||
|
||||
public static void overrideBlend(BlendState override) {
|
||||
if (!blendLocked) {
|
||||
// Only save the previous state if the blend mode wasn't already locked
|
||||
originalBlendEnable = GL11.glGetBoolean(GL11.GL_BLEND);
|
||||
originalBlendEnable = GLStateManager.getBlendMode().isEnabled();
|
||||
originalBlend.set(GLStateManager.getBlendState());
|
||||
}
|
||||
|
||||
bufferOverrideCount = 0;
|
||||
hasDeferredChanges = false;
|
||||
blendLocked = false;
|
||||
|
||||
if (override == null) {
|
||||
GL11.glDisable(GL11.GL_BLEND);
|
||||
GLStateManager.disableBlend();
|
||||
} else {
|
||||
GL11.glEnable(GL11.GL_BLEND);
|
||||
|
||||
GL14.glBlendFuncSeparate(override.getSrcRgb(), override.getDstRgb(), override.getSrcAlpha(), override.getDstAlpha());
|
||||
GLStateManager.enableBlend();
|
||||
GLStateManager.tryBlendFuncSeparate(override.getSrcRgb(), override.getDstRgb(), override.getSrcAlpha(), override.getDstAlpha());
|
||||
}
|
||||
|
||||
blendLocked = true;
|
||||
@@ -35,7 +47,7 @@ public class BlendModeStorage {
|
||||
public static void overrideBufferBlend(int index, BlendState override) {
|
||||
if (!blendLocked) {
|
||||
// Only save the previous state if the blend mode wasn't already locked
|
||||
originalBlendEnable = GL11.glGetBoolean(GL11.GL_BLEND);
|
||||
originalBlendEnable = GLStateManager.getBlendMode().isEnabled();
|
||||
originalBlend.set(GLStateManager.getBlendState());
|
||||
}
|
||||
|
||||
@@ -46,15 +58,53 @@ public class BlendModeStorage {
|
||||
RenderSystem.blendFuncSeparatei(index, override.getSrcRgb(), override.getDstRgb(), override.getSrcAlpha(), override.getDstAlpha());
|
||||
}
|
||||
|
||||
if (bufferOverrideCount < MAX_DRAW_BUFFERS) {
|
||||
final int slot = bufferOverrideCount++;
|
||||
bufferOverrideIndices[slot] = index;
|
||||
bufferOverrideIsDisable[slot] = (override == null);
|
||||
if (override != null) {
|
||||
bufferOverrideStates[slot].setAll(override.getSrcRgb(), override.getDstRgb(), override.getSrcAlpha(), override.getDstAlpha());
|
||||
}
|
||||
}
|
||||
blendLocked = true;
|
||||
}
|
||||
|
||||
public static void deferBlendModeToggle(boolean enabled) {
|
||||
originalBlendEnable = enabled;
|
||||
hasDeferredChanges = true;
|
||||
}
|
||||
|
||||
public static void deferBlendFunc(int srcRgb, int dstRgb, int srcAlpha, int dstAlpha) {
|
||||
originalBlend.setAll(srcRgb, dstRgb, srcAlpha, dstAlpha);
|
||||
hasDeferredChanges = true;
|
||||
}
|
||||
|
||||
public static void flushDeferredBlend() {
|
||||
if (!blendLocked || !hasDeferredChanges) return;
|
||||
hasDeferredChanges = false;
|
||||
blendLocked = false;
|
||||
|
||||
if (originalBlendEnable) {
|
||||
GLStateManager.enableBlend();
|
||||
} else {
|
||||
GLStateManager.disableBlend();
|
||||
}
|
||||
GLStateManager.tryBlendFuncSeparate(
|
||||
originalBlend.getSrcRgb(), originalBlend.getDstRgb(),
|
||||
originalBlend.getSrcAlpha(), originalBlend.getDstAlpha());
|
||||
|
||||
blendLocked = true;
|
||||
|
||||
for (int i = 0; i < bufferOverrideCount; i++) {
|
||||
final int idx = bufferOverrideIndices[i];
|
||||
if (bufferOverrideIsDisable[i]) {
|
||||
RenderSystem.disableBufferBlend(idx);
|
||||
} else {
|
||||
final BlendState s = bufferOverrideStates[i];
|
||||
RenderSystem.enableBufferBlend(idx);
|
||||
RenderSystem.blendFuncSeparatei(idx, s.getSrcRgb(), s.getDstRgb(), s.getSrcAlpha(), s.getDstAlpha());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void restoreBlend() {
|
||||
@@ -63,6 +113,8 @@ public class BlendModeStorage {
|
||||
}
|
||||
|
||||
blendLocked = false;
|
||||
hasDeferredChanges = false;
|
||||
bufferOverrideCount = 0;
|
||||
|
||||
if (originalBlendEnable) {
|
||||
GLStateManager.enableBlend();
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
package com.gtnewhorizons.angelica.glsm;
|
||||
|
||||
import com.gtnewhorizons.angelica.AngelicaExtension;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL30;
|
||||
|
||||
import static com.gtnewhorizons.angelica.util.GLSMUtil.resetGLState;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
/**
|
||||
* Tests for {@link com.gtnewhorizons.angelica.glsm.states.BooleanState#setUnknownState()}.
|
||||
* Verifies that per-buffer blend operations (glEnablei/glDisablei) properly invalidate
|
||||
* the GLSM blend cache so subsequent global blend enable/disable calls are not skipped.
|
||||
*/
|
||||
@ExtendWith(AngelicaExtension.class)
|
||||
class GLSM_BlendUnknownState_UnitTest {
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
resetGLState();
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void tearDown() {
|
||||
resetGLState();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSetUnknownStateForcesCacheBypass() {
|
||||
// Enable blend via GLSM — both cache and GL should agree
|
||||
GLStateManager.enableBlend();
|
||||
assertTrue(GL11.glIsEnabled(GL11.GL_BLEND), "GL blend should be enabled");
|
||||
assertTrue(GLStateManager.getBlendMode().isEnabled(), "GLSM blend cache should be enabled");
|
||||
|
||||
// Simulate a per-buffer disable that bypasses the cache (as glDisablei does)
|
||||
GL30.glDisablei(GL11.GL_BLEND, 0);
|
||||
GLStateManager.getBlendMode().setUnknownState();
|
||||
|
||||
// Cache still says enabled, but GL state for buffer 0 is now disabled
|
||||
assertTrue(GLStateManager.getBlendMode().isEnabled(), "GLSM cache should still say enabled");
|
||||
|
||||
// Re-enable blend via GLSM — without setUnknownState, this would be a no-op
|
||||
// because the cache thinks blend is already enabled
|
||||
GLStateManager.enableBlend();
|
||||
|
||||
// Per GL spec, glEnable(GL_BLEND) enables blend for ALL draw buffers,
|
||||
// overriding any per-buffer disables
|
||||
assertTrue(GL11.glIsEnabled(GL11.GL_BLEND), "GL blend should be re-enabled after setUnknownState");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDisableBufferBlendInvalidatesCache() {
|
||||
GLStateManager.enableBlend();
|
||||
assertTrue(GL11.glIsEnabled(GL11.GL_BLEND));
|
||||
|
||||
// Use RenderSystem which should call setUnknownState internally
|
||||
RenderSystem.disableBufferBlend(0);
|
||||
|
||||
// Now re-enable via GLSM — should issue the GL call
|
||||
GLStateManager.enableBlend();
|
||||
assertTrue(GL11.glIsEnabled(GL11.GL_BLEND), "Blend should be re-enabled after disableBufferBlend");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testEnableBufferBlendInvalidatesCache() {
|
||||
// Start with blend disabled
|
||||
GLStateManager.disableBlend();
|
||||
assertFalse(GL11.glIsEnabled(GL11.GL_BLEND));
|
||||
|
||||
// Per-buffer enable bypasses cache
|
||||
RenderSystem.enableBufferBlend(0);
|
||||
|
||||
// Disable via GLSM — should issue the GL call despite cache saying disabled
|
||||
GLStateManager.disableBlend();
|
||||
assertFalse(GL11.glIsEnabled(GL11.GL_BLEND), "Blend should be disabled after enableBufferBlend + disableBlend");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testUnknownStateClearedAfterSetEnabled() {
|
||||
GLStateManager.enableBlend();
|
||||
|
||||
// Mark unknown
|
||||
GLStateManager.getBlendMode().setUnknownState();
|
||||
|
||||
// First setEnabled clears the unknown flag
|
||||
GLStateManager.enableBlend();
|
||||
|
||||
// Second setEnabled should use normal caching (no redundant GL call)
|
||||
// Verify state is consistent
|
||||
assertTrue(GL11.glIsEnabled(GL11.GL_BLEND));
|
||||
assertTrue(GLStateManager.getBlendMode().isEnabled());
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user