acdream/tests/AcDream.App.Tests/Rendering/RenderFrameGlStateControllerTests.cs
Erik 28e1cf8029 refactor(render): extract world scene frame owner
Move fallback and PView world drawing, shared alpha, particles, visibility, selection, and diagnostics behind focused frame owners. Make exceptional frames failure-atomic by restoring the shared GL baseline and preserving primary alpha failures through cleanup.

Co-authored-by: Codex <codex@openai.com>
2026-07-22 07:22:09 +02:00

106 lines
3.6 KiB
C#

using AcDream.App.Rendering;
using Silk.NET.OpenGL;
namespace AcDream.App.Tests.Rendering;
public sealed class RenderFrameGlStateControllerTests
{
[Fact]
public void RestoreFrameDefaults_ReestablishesTheCompleteFrameGlobalContract()
{
var api = new RecordingApi();
var state = new RenderFrameGlStateController(api);
state.RestoreFrameDefaults();
Assert.Equal(
[
"cap:ScissorTest:False",
"cap:StencilTest:False",
"cap:Blend:False",
"cap:SampleAlphaToMaskSgis:False",
"cap:ClipDistance0:False",
"cap:ClipDistance1:False",
"cap:ClipDistance2:False",
"cap:ClipDistance3:False",
"cap:ClipDistance4:False",
"cap:ClipDistance5:False",
"cap:ClipDistance6:False",
"cap:ClipDistance7:False",
"color-mask:True:True:True:True",
"stencil-mask:255",
"depth-mask:True",
"depth-func:Less",
"cap:DepthTest:True",
"cap:CullFace:False",
"cull:Back",
"front:CW",
"program:0",
"vao:0",
"buffer:ArrayBuffer:0",
],
api.Calls);
}
[Fact]
public void PortalDepthMask_SuccessExitRestoresTheSameCullOffConvention()
{
string source = File.ReadAllText(Path.Combine(
FindRepoRoot(),
"src",
"AcDream.App",
"Rendering",
"PortalDepthMaskRenderer.cs"));
int restore = source.IndexOf(
"// ---- restore the frame-global convention ----",
StringComparison.Ordinal);
Assert.True(restore >= 0, "Missing portal-depth state restore block.");
string restoreBlock = source[restore..];
Assert.Contains("_gl.Disable(EnableCap.CullFace);", restoreBlock);
Assert.DoesNotContain("_gl.Enable(EnableCap.CullFace);", restoreBlock);
}
private static string FindRepoRoot()
{
DirectoryInfo? directory = new(AppContext.BaseDirectory);
while (directory is not null)
{
if (File.Exists(Path.Combine(directory.FullName, "AcDream.slnx")))
return directory.FullName;
directory = directory.Parent;
}
throw new DirectoryNotFoundException("Could not find AcDream.slnx.");
}
private sealed class RecordingApi : IRenderFrameGlStateApi
{
public List<string> Calls { get; } = [];
public void SetCapability(EnableCap capability, bool enabled) =>
Calls.Add($"cap:{capability}:{enabled}");
public void ColorMask(bool red, bool green, bool blue, bool alpha) =>
Calls.Add($"color-mask:{red}:{green}:{blue}:{alpha}");
public void StencilMask(uint mask) => Calls.Add($"stencil-mask:{mask}");
public void DepthMask(bool enabled) => Calls.Add($"depth-mask:{enabled}");
public void DepthFunc(DepthFunction function) =>
Calls.Add($"depth-func:{function}");
public void CullFace(TriangleFace face) => Calls.Add($"cull:{face}");
public void FrontFace(FrontFaceDirection direction) =>
Calls.Add($"front:{direction}");
public void UseProgram(uint program) => Calls.Add($"program:{program}");
public void BindVertexArray(uint vertexArray) => Calls.Add($"vao:{vertexArray}");
public void BindBuffer(BufferTargetARB target, uint buffer) =>
Calls.Add($"buffer:{target}:{buffer}");
}
}