118 lines
3.3 KiB
C#
118 lines
3.3 KiB
C#
|
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);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|