using Silk.NET.OpenGL; namespace AcDream.App.Rendering; internal interface ITextRenderGlStateApi { bool IsEnabled(EnableCap capability); int GetInteger(GetPName parameter); bool GetBoolean(GetPName parameter); void SetCapability(EnableCap capability, bool enabled); void DepthMask(bool enabled); void BlendFuncSeparate( BlendingFactor sourceRgb, BlendingFactor destinationRgb, BlendingFactor sourceAlpha, BlendingFactor destinationAlpha); void UseProgram(uint program); void BindVertexArray(uint vertexArray); void BindBuffer(BufferTargetARB target, uint buffer); void ActiveTexture(TextureUnit unit); void BindTexture(TextureTarget target, uint texture); } internal sealed class SilkTextRenderGlStateApi : ITextRenderGlStateApi { private readonly GL _gl; public SilkTextRenderGlStateApi(GL gl) => _gl = gl ?? throw new ArgumentNullException(nameof(gl)); public bool IsEnabled(EnableCap capability) => _gl.IsEnabled(capability); public int GetInteger(GetPName parameter) => _gl.GetInteger(parameter); public bool GetBoolean(GetPName parameter) => _gl.GetBoolean(parameter); public void SetCapability(EnableCap capability, bool enabled) { if (enabled) _gl.Enable(capability); else _gl.Disable(capability); } public void DepthMask(bool enabled) => _gl.DepthMask(enabled); public void BlendFuncSeparate( BlendingFactor sourceRgb, BlendingFactor destinationRgb, BlendingFactor sourceAlpha, BlendingFactor destinationAlpha) => _gl.BlendFuncSeparate( sourceRgb, destinationRgb, sourceAlpha, destinationAlpha); public void UseProgram(uint program) => _gl.UseProgram(program); public void BindVertexArray(uint vertexArray) => _gl.BindVertexArray(vertexArray); public void BindBuffer(BufferTargetARB target, uint buffer) => _gl.BindBuffer(target, buffer); public void ActiveTexture(TextureUnit unit) => _gl.ActiveTexture(unit); public void BindTexture(TextureTarget target, uint texture) => _gl.BindTexture(target, texture); } /// /// Exact, focused state transaction for . It /// captures every GL value that Flush or DrawLayer mutates, while avoiding the /// dozens of unrelated synchronous reads made by the broad diagnostic scope. /// internal readonly struct TextRenderGlStateScope : IDisposable { private readonly ITextRenderGlStateApi _gl; private readonly bool _depthTest; private readonly bool _blend; private readonly bool _cullFace; private readonly bool _alphaToCoverage; private readonly bool _multisample; private readonly bool _depthWrite; private readonly int _blendSourceRgb; private readonly int _blendDestinationRgb; private readonly int _blendSourceAlpha; private readonly int _blendDestinationAlpha; private readonly int _program; private readonly int _vertexArray; private readonly int _arrayBuffer; private readonly int _activeTexture; private readonly int _texture0Binding2D; public TextRenderGlStateScope(ITextRenderGlStateApi gl) { _gl = gl ?? throw new ArgumentNullException(nameof(gl)); _depthTest = gl.IsEnabled(EnableCap.DepthTest); _blend = gl.IsEnabled(EnableCap.Blend); _cullFace = gl.IsEnabled(EnableCap.CullFace); _alphaToCoverage = gl.IsEnabled(EnableCap.SampleAlphaToCoverage); _multisample = gl.IsEnabled(EnableCap.Multisample); _depthWrite = gl.GetBoolean(GetPName.DepthWritemask); _blendSourceRgb = gl.GetInteger(GetPName.BlendSrcRgb); _blendDestinationRgb = gl.GetInteger(GetPName.BlendDstRgb); _blendSourceAlpha = gl.GetInteger(GetPName.BlendSrcAlpha); _blendDestinationAlpha = gl.GetInteger(GetPName.BlendDstAlpha); _program = gl.GetInteger(GetPName.CurrentProgram); _vertexArray = gl.GetInteger(GetPName.VertexArrayBinding); _arrayBuffer = gl.GetInteger(GetPName.ArrayBufferBinding); _activeTexture = gl.GetInteger(GetPName.ActiveTexture); try { gl.ActiveTexture(TextureUnit.Texture0); _texture0Binding2D = gl.GetInteger(GetPName.TextureBinding2D); } finally { gl.ActiveTexture((TextureUnit)_activeTexture); } } public void Dispose() { _gl.UseProgram((uint)_program); _gl.BindVertexArray((uint)_vertexArray); _gl.BindBuffer(BufferTargetARB.ArrayBuffer, (uint)_arrayBuffer); _gl.ActiveTexture(TextureUnit.Texture0); _gl.BindTexture(TextureTarget.Texture2D, (uint)_texture0Binding2D); _gl.ActiveTexture((TextureUnit)_activeTexture); _gl.DepthMask(_depthWrite); _gl.BlendFuncSeparate( (BlendingFactor)_blendSourceRgb, (BlendingFactor)_blendDestinationRgb, (BlendingFactor)_blendSourceAlpha, (BlendingFactor)_blendDestinationAlpha); _gl.SetCapability(EnableCap.DepthTest, _depthTest); _gl.SetCapability(EnableCap.Blend, _blend); _gl.SetCapability(EnableCap.CullFace, _cullFace); _gl.SetCapability(EnableCap.SampleAlphaToCoverage, _alphaToCoverage); _gl.SetCapability(EnableCap.Multisample, _multisample); } }