Dashboard/Dashboard.OpenTK/PAL2/OpenGLDeviceContext.cs

118 lines
3.3 KiB
C#
Raw Normal View History

2025-02-02 19:58:49 +01:00
using System.Collections.Concurrent;
using System.Drawing;
using Dashboard.OpenGL;
using OpenTK.Mathematics;
using OpenTK.Platform;
using TK = OpenTK.Platform.Toolkit;
namespace Dashboard.OpenTK.PAL2
{
public class OpenGLDeviceContext : IGLContext, IGLDisposable
{
public OpenGLContextHandle ContextHandle { get; }
public WindowHandle WindowHandle { get; }
public ISwapGroup SwapGroup { get; }
public int ContextGroup { get; }
public Size FramebufferSize
{
get
{
TK.Window.GetFramebufferSize(WindowHandle, out Vector2i size);
return new Size(size.X, size.Y);
}
}
public event Action? Disposed;
public OpenGLDeviceContext(WindowHandle window, OpenGLContextHandle context, ISwapGroup? group = null)
{
WindowHandle = window;
ContextHandle = context;
SwapGroup = group ?? new DummySwapGroup(context);
ContextGroup = GetContextGroup(context);
}
public void MakeCurrent()
{
TK.OpenGL.SetCurrentContext(ContextHandle);
}
private bool _isDisposed = false;
public void Dispose() => Dispose(true);
public void Dispose(bool safeExit)
{
if (_isDisposed) return;
_isDisposed = true;
if (SwapGroup is IGLDisposable glDisposable)
{
glDisposable.Dispose(safeExit);
}
else if (SwapGroup is IDisposable disposable)
{
disposable.Dispose();
}
Disposed?.Invoke();
}
private static int _contextGroupId = 0;
private static ConcurrentDictionary<OpenGLContextHandle, int> _contextGroupRootContexts = new ConcurrentDictionary<OpenGLContextHandle, int>();
private static int GetContextGroup(OpenGLContextHandle handle)
{
OpenGLContextHandle? shared = TK.OpenGL.GetSharedContext(handle);
if (shared == null)
{
if (_contextGroupRootContexts.TryGetValue(handle, out int group))
return group;
group = Interlocked.Increment(ref _contextGroupId);
_contextGroupRootContexts.TryAdd(handle, group);
return GetContextGroup(handle);
}
else
{
if (_contextGroupRootContexts.TryGetValue(shared, out int group))
return group;
return GetContextGroup(shared);
}
}
public class DummySwapGroup : ISwapGroup
{
public OpenGLContextHandle ContextHandle { get; }
public int SwapInterval
{
get
{
TK.OpenGL.SetCurrentContext(ContextHandle);
return TK.OpenGL.GetSwapInterval();
}
set
{
TK.OpenGL.SetCurrentContext(ContextHandle);
TK.OpenGL.SetSwapInterval(value);
}
}
public DummySwapGroup(OpenGLContextHandle handle)
{
ContextHandle = handle;
}
public void Swap()
{
TK.OpenGL.SwapBuffers(ContextHandle);
}
}
}
}