156 lines
5.0 KiB
C#
156 lines
5.0 KiB
C#
using System.Drawing;
|
|
using System.Numerics;
|
|
using Dashboard.Drawing;
|
|
using Dashboard.Pal;
|
|
using Dashboard.Windowing;
|
|
using OpenTK.Graphics.OpenGL;
|
|
using OpenTK.Graphics.Wgl;
|
|
using OpenTK.Mathematics;
|
|
using ColorBuffer = OpenTK.Graphics.OpenGL.ColorBuffer;
|
|
|
|
namespace Dashboard.OpenGL.Drawing
|
|
{
|
|
public class DeviceContextBase : IDeviceContextBase
|
|
{
|
|
private readonly Stack<Matrix4x4> _transforms = new Stack<Matrix4x4>();
|
|
private readonly Stack<RectangleF> _clipRegions = new Stack<RectangleF>();
|
|
private readonly Stack<RectangleF> _scissorRegions = new Stack<RectangleF>();
|
|
|
|
public DeviceContext Context { get; private set; } = null!;
|
|
IContextBase IContextExtensionBase.Context => Context;
|
|
public string DriverName => "Dashboard OpenGL Device Context";
|
|
public string DriverVendor => "Dashboard";
|
|
public Version DriverVersion => new Version(0, 1);
|
|
|
|
public RectangleF ClipRegion => _clipRegions.Peek();
|
|
public RectangleF ScissorRegion => _scissorRegions.Peek();
|
|
public Matrix4x4 Transforms => _transforms.Peek();
|
|
public float Scale => ScaleOverride > 0 ? ScaleOverride : (Context.Window as IDpiAwareWindow)?.Scale ?? 1;
|
|
public float ScaleOverride { get; set; } = -1f;
|
|
|
|
|
|
public void Dispose()
|
|
{
|
|
}
|
|
|
|
|
|
public void Require(DeviceContext context)
|
|
{
|
|
Context = context;
|
|
|
|
ResetClip();
|
|
ResetScissor();
|
|
ResetTransforms();
|
|
}
|
|
|
|
|
|
void IContextExtensionBase.Require(IContextBase context) => Require((DeviceContext)context);
|
|
|
|
public void ResetClip()
|
|
{
|
|
_clipRegions.Clear();
|
|
|
|
SizeF size = ((GLDeviceContext)Context).GLContext.FramebufferSize;
|
|
_clipRegions.Push(new RectangleF(0,0, size.Width, size.Height));
|
|
|
|
SetClip(ClipRegion);
|
|
}
|
|
|
|
public void PushClip(RectangleF clipRegion)
|
|
{
|
|
clipRegion = new RectangleF(ClipRegion.X + clipRegion.X, ClipRegion.Y + clipRegion.Y,
|
|
Math.Min(ClipRegion.Right - clipRegion.X, clipRegion.Width),
|
|
Math.Min(ClipRegion.Bottom - clipRegion.Y, clipRegion.Height));
|
|
_clipRegions.Push(clipRegion);
|
|
|
|
SetClip(clipRegion);
|
|
}
|
|
|
|
public void PopClip()
|
|
{
|
|
_clipRegions.Pop();
|
|
SetClip(ClipRegion);
|
|
}
|
|
|
|
public void ResetScissor()
|
|
{
|
|
GL.Disable(EnableCap.ScissorTest);
|
|
_scissorRegions.Clear();
|
|
SizeF size = ((GLDeviceContext)Context).GLContext.FramebufferSize;
|
|
_scissorRegions.Push(new RectangleF(0,0, size.Width, size.Height));
|
|
}
|
|
|
|
public void PushScissor(RectangleF scissorRegion)
|
|
{
|
|
GL.Enable(EnableCap.ScissorTest);
|
|
|
|
// scissorRegion = new RectangleF(scissorRegion.X + scissorRegion.X, scissorRegion.Y + scissorRegion.Y,
|
|
// Math.Min(ScissorRegion.Right - scissorRegion.X, scissorRegion.Width),
|
|
// Math.Min(ScissorRegion.Bottom - scissorRegion.Y, scissorRegion.Height));
|
|
_scissorRegions.Push(scissorRegion);
|
|
|
|
SetScissor(scissorRegion);
|
|
}
|
|
|
|
public void PopScissor()
|
|
{
|
|
if (_scissorRegions.Count == 1)
|
|
GL.Disable(EnableCap.ScissorTest);
|
|
|
|
_scissorRegions.Pop();
|
|
SetScissor(ClipRegion);
|
|
}
|
|
|
|
private void SetClip(RectangleF rect)
|
|
{
|
|
SizeF size = ((GLDeviceContext)Context).GLContext.FramebufferSize;
|
|
GL.Viewport(
|
|
(int)Math.Round(rect.X),
|
|
(int)Math.Round(size.Height - rect.Y - rect.Height),
|
|
(int)Math.Round(rect.Width),
|
|
(int)Math.Round(rect.Height));
|
|
}
|
|
|
|
void SetScissor(RectangleF rect)
|
|
{
|
|
SizeF size = ((GLDeviceContext)Context).GLContext.FramebufferSize;
|
|
GL.Scissor(
|
|
(int)Math.Round(rect.X),
|
|
(int)Math.Round(size.Height - rect.Y - rect.Height),
|
|
(int)Math.Round(rect.Width),
|
|
(int)Math.Round(rect.Height));
|
|
}
|
|
|
|
public void ResetTransforms()
|
|
{
|
|
SizeF size = ((GLDeviceContext)Context).GLContext.FramebufferSize;
|
|
Matrix4x4 m = Matrix4x4.CreateOrthographicOffCenterLeftHanded(0, size.Width, size.Height, 0, 1, -1);
|
|
|
|
_transforms.Clear();
|
|
_transforms.Push(m);
|
|
}
|
|
|
|
public void PushTransforms(in Matrix4x4 matrix)
|
|
{
|
|
Matrix4x4 result = matrix * Transforms;
|
|
_transforms.Push(result);
|
|
}
|
|
|
|
public void PopTransforms()
|
|
{
|
|
_transforms.Pop();
|
|
}
|
|
|
|
public void ClearColor(Color color)
|
|
{
|
|
GL.ClearColor(color.R / 255f, color.G / 255f, color.B / 255f, color.A / 255f);
|
|
GL.Clear(ClearBufferMask.ColorBufferBit);
|
|
}
|
|
|
|
public void ClearDepth()
|
|
{
|
|
GL.Clear(ClearBufferMask.DepthBufferBit);
|
|
}
|
|
}
|
|
}
|