Add new demo application template.
This commit is contained in:
parent
2bcac4a83e
commit
d65bb8ad0a
@ -1,6 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using static StbTrueTypeSharp.StbTrueType;
|
|
||||||
using Quik.Media.Color;
|
using Quik.Media.Color;
|
||||||
|
|
||||||
namespace Quik.Media.Stb
|
namespace Quik.Media.Stb
|
||||||
|
@ -1,189 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
using System.Reflection;
|
|
||||||
using Quik.OpenGL;
|
|
||||||
using Quik.VertexGenerator;
|
|
||||||
using Matrix4 = OpenTK.Mathematics.Matrix4;
|
|
||||||
using static Quik.OpenGL.GLEnum;
|
|
||||||
|
|
||||||
namespace Quik.OpenTK
|
|
||||||
{
|
|
||||||
public class GL30Driver : IDisposable
|
|
||||||
{
|
|
||||||
public GL30Driver()
|
|
||||||
{
|
|
||||||
Assembly asm = typeof(GL30Driver).Assembly;
|
|
||||||
|
|
||||||
using (StreamReader vert = new StreamReader(asm.GetManifestResourceStream("Quik.OpenTK.glsl.glsl130.vert")))
|
|
||||||
using (StreamReader frag = new StreamReader(asm.GetManifestResourceStream("Quik.OpenTK.glsl.glsl130.frag")))
|
|
||||||
{
|
|
||||||
int vs;
|
|
||||||
int fs;
|
|
||||||
|
|
||||||
vs = GL.CreateShader(GL_VERTEX_SHADER);
|
|
||||||
fs = GL.CreateShader(GL_FRAGMENT_SHADER);
|
|
||||||
|
|
||||||
_sp = GL.CreateProgram();
|
|
||||||
|
|
||||||
GL.ShaderSource(vs, vert.ReadToEnd());
|
|
||||||
GL.ShaderSource(fs, frag.ReadToEnd());
|
|
||||||
|
|
||||||
GL.CompileShader(vs);
|
|
||||||
GL.CompileShader(fs);
|
|
||||||
|
|
||||||
#if DEBUG
|
|
||||||
int status;
|
|
||||||
|
|
||||||
GL.GetShader(vs, GL_COMPILE_STATUS, out status);
|
|
||||||
if (status == 0)
|
|
||||||
{
|
|
||||||
throw new Exception(GL.GetShaderInfoLog(vs));
|
|
||||||
}
|
|
||||||
|
|
||||||
GL.GetShader(fs, GL_COMPILE_STATUS, out status);
|
|
||||||
if (status == 0)
|
|
||||||
{
|
|
||||||
throw new Exception(GL.GetShaderInfoLog(fs));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
GL.AttachShader(_sp, vs);
|
|
||||||
GL.AttachShader(_sp, fs);
|
|
||||||
|
|
||||||
GL.LinkProgram(_sp);
|
|
||||||
|
|
||||||
#if DEBUG
|
|
||||||
GL.GetProgram(_sp, GL_LINK_STATUS, out status);
|
|
||||||
if (status == 0)
|
|
||||||
{
|
|
||||||
throw new Exception(GL.GetProgramInfoLog(_sp));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
GL.DetachShader(_sp, vs);
|
|
||||||
GL.DetachShader(_sp, fs);
|
|
||||||
GL.DeleteShader(vs);
|
|
||||||
GL.DeleteShader(fs);
|
|
||||||
}
|
|
||||||
|
|
||||||
LoadUniform(_nameM4View, out _locM4View);
|
|
||||||
LoadUniform(_nameM4Model, out _locM4Model);
|
|
||||||
LoadUniform(_nameIFlags, out _locIFlags);
|
|
||||||
LoadUniform(_nameFSdfThreshold, out _locFSdfThreshold);
|
|
||||||
LoadUniform(_nameFSdfAuxilliaryThreshold, out _locFSdfAuxilliaryThreshold);
|
|
||||||
LoadUniform(_nameV4SdfAuxilliaryColor, out _locV4SdfAuxilliaryColor);
|
|
||||||
LoadUniform(_nameX2Texture, out _locX2Texture);
|
|
||||||
LoadUniform(_nameV2TextureOffset, out _locV2TextureOffset);
|
|
||||||
|
|
||||||
LoadAttribute(_nameV2Postion, out _locV2Position);
|
|
||||||
LoadAttribute(_nameV2Texture, out _locV2Texture);
|
|
||||||
LoadAttribute(_nameV4Color, out _locV4Color);
|
|
||||||
|
|
||||||
void LoadUniform(string name, out int location)
|
|
||||||
{
|
|
||||||
location = GL.GetUniformLocation(_sp, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
void LoadAttribute(string name, out int location)
|
|
||||||
{
|
|
||||||
location = GL.GetAttribLocation(_sp, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
_vbo = GL.GenBuffer();
|
|
||||||
_ebo = GL.GenBuffer();
|
|
||||||
_vao = GL.GenVertexArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
private readonly int _sp;
|
|
||||||
private readonly int _vao;
|
|
||||||
private readonly int _vbo;
|
|
||||||
private readonly int _ebo;
|
|
||||||
|
|
||||||
private const string _nameM4View = "m4View";
|
|
||||||
private readonly int _locM4View;
|
|
||||||
private const string _nameM4Model = "m4Model";
|
|
||||||
private readonly int _locM4Model;
|
|
||||||
private const string _nameV2Postion = "v2Position";
|
|
||||||
private readonly int _locV2Position;
|
|
||||||
private const string _nameV2Texture = "v2Texture";
|
|
||||||
private readonly int _locV2Texture;
|
|
||||||
private const string _nameV4Color = "v4Color";
|
|
||||||
private readonly int _locV4Color;
|
|
||||||
private const string _nameIFlags = "iFlags";
|
|
||||||
private readonly int _locIFlags;
|
|
||||||
private const string _nameFSdfThreshold = "fSdfThreshold";
|
|
||||||
private readonly int _locFSdfThreshold;
|
|
||||||
private const string _nameFSdfAuxilliaryThreshold = "fSdfAuxilliaryThreshold";
|
|
||||||
private readonly int _locFSdfAuxilliaryThreshold;
|
|
||||||
private const string _nameV4SdfAuxilliaryColor = "v4SdfAuxilliaryColor";
|
|
||||||
private readonly int _locV4SdfAuxilliaryColor;
|
|
||||||
private const string _nameX2Texture = "x2Texture";
|
|
||||||
private readonly int _locX2Texture;
|
|
||||||
private const string _nameV2TextureOffset = "v2TextureOffset";
|
|
||||||
private readonly int _locV2TextureOffset;
|
|
||||||
|
|
||||||
[Flags]
|
|
||||||
private enum Flags : int
|
|
||||||
{
|
|
||||||
Texture = 1 << 0,
|
|
||||||
DiscardEnable = 1 << 1,
|
|
||||||
Sdf = 1 << 2,
|
|
||||||
SdfAuxEnable = 1 << 3,
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Draw(DrawQueue queue)
|
|
||||||
{
|
|
||||||
GL.UseProgram(_sp);
|
|
||||||
GL.BindVertexArray(_vao);
|
|
||||||
|
|
||||||
GL.BindBuffer(GL_ARRAY_BUFFER, _vbo);
|
|
||||||
GL.BufferData(GL_ARRAY_BUFFER, queue.VertexCount * QuikVertex.Stride, queue.VertexArray, GL_STREAM_DRAW);
|
|
||||||
GL.BindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ebo);
|
|
||||||
GL.BufferData(GL_ELEMENT_ARRAY_BUFFER, queue.ElementCount * sizeof(int), queue.ElementArray, GL_STREAM_DRAW);
|
|
||||||
|
|
||||||
GL.VertexAttribPointer(_locV2Position, 2, GL_FLOAT, false, QuikVertex.Stride, QuikVertex.PositionOffset);
|
|
||||||
GL.VertexAttribPointer(_locV2Texture, 2, GL_FLOAT, false, QuikVertex.Stride, QuikVertex.TextureCoordinatesOffset);
|
|
||||||
GL.VertexAttribPointer(_locV4Color, 4, GL_UNSIGNED_BYTE, false, QuikVertex.Stride, QuikVertex.ColorOffset);
|
|
||||||
GL.EnableVertexAttribArray(_locV2Position);
|
|
||||||
GL.EnableVertexAttribArray(_locV2Texture);
|
|
||||||
GL.EnableVertexAttribArray(_locV4Color);
|
|
||||||
|
|
||||||
GL.Enable(GL_BLEND);
|
|
||||||
GL.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
||||||
|
|
||||||
Matrix4 m = Matrix4.Identity;
|
|
||||||
GL.UniformMatrix4(_locM4Model, false, ref m.Row0.X);
|
|
||||||
|
|
||||||
foreach (DrawCall call in queue)
|
|
||||||
{
|
|
||||||
GL.BindTexture(GL_TEXTURE_2D, 0);
|
|
||||||
m = Matrix4.CreateOrthographicOffCenter(0, call.Bounds.Right, 0, call.Bounds.Top, 1.0f, -1.0f);
|
|
||||||
GL.UniformMatrix4(_locM4View, false, ref m.Row0.X);
|
|
||||||
GL.DrawElements(GL_TRIANGLES, call.Count, GL_UNSIGNED_INT, call.Start);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool _isDisposed = false;
|
|
||||||
private void Dispose(bool disposing)
|
|
||||||
{
|
|
||||||
if (_isDisposed) return;
|
|
||||||
|
|
||||||
if (disposing)
|
|
||||||
{
|
|
||||||
GL.DeleteProgram(_sp);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new Exception("OpenGL resource is leaked. Dispose unreferenced OpenGL objects in the context thread.");
|
|
||||||
}
|
|
||||||
|
|
||||||
_isDisposed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose() => Dispose(true);
|
|
||||||
~GL30Driver()
|
|
||||||
{
|
|
||||||
Dispose(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
59
Quik.OpenTK/OpenTKPlatform.cs
Normal file
59
Quik.OpenTK/OpenTKPlatform.cs
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using OpenTK.Windowing.Desktop;
|
||||||
|
using OpenTK.Windowing.GraphicsLibraryFramework;
|
||||||
|
using Quik.Media;
|
||||||
|
using Quik.OpenGL;
|
||||||
|
using Quik.PAL;
|
||||||
|
|
||||||
|
namespace Quik.OpenTK
|
||||||
|
{
|
||||||
|
public class OpenTKPlatform : IQuikPlatform
|
||||||
|
{
|
||||||
|
private readonly List<OpenTKPort> _ports = new List<OpenTKPort>();
|
||||||
|
|
||||||
|
// These shall remain a sad nop for now.
|
||||||
|
public string Title { get; set; }
|
||||||
|
public QImage Icon { get; set; }
|
||||||
|
|
||||||
|
public event EventHandler EventRaised;
|
||||||
|
|
||||||
|
public NativeWindowSettings DefaultSettings { get; set; } = NativeWindowSettings.Default;
|
||||||
|
|
||||||
|
public IReadOnlyList<OpenTKPort> Ports => _ports;
|
||||||
|
|
||||||
|
private bool IsGLInitialized = false;
|
||||||
|
|
||||||
|
public IQuikPort CreatePort()
|
||||||
|
{
|
||||||
|
NativeWindow window = new NativeWindow(DefaultSettings);
|
||||||
|
OpenTKPort port = new OpenTKPort(window);
|
||||||
|
_ports.Add(port);
|
||||||
|
|
||||||
|
if (!IsGLInitialized)
|
||||||
|
{
|
||||||
|
window.Context.MakeCurrent();
|
||||||
|
GL.LoadBindings((string proc) => GLFW.GetProcAddress(proc));
|
||||||
|
IsGLInitialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return port;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
// FIXME: dispose pattern here!
|
||||||
|
|
||||||
|
// Copy the array to prevent collection modification exceptions.
|
||||||
|
foreach (OpenTKPort port in _ports.ToArray())
|
||||||
|
{
|
||||||
|
port.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ProcessEvents(bool block)
|
||||||
|
{
|
||||||
|
NativeWindow.ProcessWindowEvents(block);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
105
Quik.OpenTK/OpenTKPort.cs
Normal file
105
Quik.OpenTK/OpenTKPort.cs
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
using System;
|
||||||
|
using OpenTK.Mathematics;
|
||||||
|
using OpenTK.Windowing.Desktop;
|
||||||
|
using Quik.OpenGL;
|
||||||
|
using Quik.CommandMachine;
|
||||||
|
using Quik.PAL;
|
||||||
|
using Quik.VertexGenerator;
|
||||||
|
|
||||||
|
namespace Quik.OpenTK
|
||||||
|
{
|
||||||
|
public class OpenTKPort : IQuikPort
|
||||||
|
{
|
||||||
|
private readonly NativeWindow _window;
|
||||||
|
private readonly GL21Driver _glDriver;
|
||||||
|
private readonly VertexGeneratorEngine _vertexEngine;
|
||||||
|
|
||||||
|
public string Title
|
||||||
|
{
|
||||||
|
get => _window.Title;
|
||||||
|
set => _window.Title = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public QVec2 Size
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
Vector2i size = _window.ClientSize;
|
||||||
|
return new QVec2(size.X, size.Y);
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
// OpenTK being OpenTK as usual, you can't set the client size.
|
||||||
|
Vector2i extents = _window.Size - _window.ClientSize;
|
||||||
|
Vector2i size = extents + new Vector2i((int)value.X, (int)value.Y);
|
||||||
|
_window.Size = size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public QVec2 Position
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
Vector2i location = _window.Location;
|
||||||
|
return new QVec2(location.X, location.Y);
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
Vector2i location = new Vector2i((int)value.X, (int)value.Y);
|
||||||
|
_window.Location = location;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsValid => !isDisposed;
|
||||||
|
|
||||||
|
public event EventHandler EventRaised;
|
||||||
|
|
||||||
|
public OpenTKPort(NativeWindow window)
|
||||||
|
{
|
||||||
|
_window = window;
|
||||||
|
_glDriver = new GL21Driver();
|
||||||
|
_vertexEngine = new VertexGeneratorEngine();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Focus()
|
||||||
|
{
|
||||||
|
_window.Focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Paint(CommandQueue queue)
|
||||||
|
{
|
||||||
|
QRectangle view = new QRectangle(Size, new QVec2(0, 0));
|
||||||
|
|
||||||
|
_vertexEngine.Reset();
|
||||||
|
_vertexEngine.ProcessCommands(new QRectangle(), queue);
|
||||||
|
|
||||||
|
_window.Context.MakeCurrent();
|
||||||
|
|
||||||
|
if (!_glDriver.IsInit)
|
||||||
|
_glDriver.Init();
|
||||||
|
|
||||||
|
_glDriver.Draw(_vertexEngine.DrawQueue, view);
|
||||||
|
|
||||||
|
_window.Context.SwapBuffers();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Show(bool shown = true)
|
||||||
|
{
|
||||||
|
_window.IsVisible = shown;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool isDisposed;
|
||||||
|
private void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (isDisposed) return;
|
||||||
|
|
||||||
|
if (disposing)
|
||||||
|
{
|
||||||
|
_window?.Dispose();
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
isDisposed = true;
|
||||||
|
}
|
||||||
|
public void Dispose() => Dispose(true);
|
||||||
|
}
|
||||||
|
}
|
@ -1,61 +0,0 @@
|
|||||||
#version 130
|
|
||||||
|
|
||||||
#define F_TEXTURE (1 << 0)
|
|
||||||
#define F_DISCARD_EN (1 << 1)
|
|
||||||
#define F_SDF (1 << 2)
|
|
||||||
#define F_SDF_AUX_EN (1 << 3)
|
|
||||||
|
|
||||||
uniform int iFlags;
|
|
||||||
uniform float fSdfThreshold;
|
|
||||||
uniform float fSdfAuxilliaryThreshold;
|
|
||||||
uniform vec4 v4SdfAuxilliaryColor;
|
|
||||||
uniform sampler2D x2Texture;
|
|
||||||
uniform vec2 v2TextureOffset;
|
|
||||||
|
|
||||||
in vec2 fv2Texture;
|
|
||||||
out vec4 fv4Color;
|
|
||||||
|
|
||||||
vec4 v4Color()
|
|
||||||
{
|
|
||||||
vec4 color = fv4Color;
|
|
||||||
|
|
||||||
if ((iFlags & F_TEXTURE) != 0)
|
|
||||||
{
|
|
||||||
if ((iFlags & F_SDF) != 0)
|
|
||||||
{
|
|
||||||
float a = texture(x2Texture, fv2Texture + v2TextureOffset).a;
|
|
||||||
|
|
||||||
if ((iFlags & F_SDF_AUX_EN) != 0)
|
|
||||||
{
|
|
||||||
color =
|
|
||||||
(a > fSdfThreshold)
|
|
||||||
? color
|
|
||||||
: (a > fSdfAuxilliaryThreshold)
|
|
||||||
? v4SdfAuxilliaryColor
|
|
||||||
: vec4(0, 0, 0, 0);
|
|
||||||
}
|
|
||||||
else if (a < fSdfThreshold)
|
|
||||||
{
|
|
||||||
color = vec4(0, 0, 0, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
color *= texture(x2Texture, fv2Texture + v2TextureOffset);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return color;
|
|
||||||
}
|
|
||||||
|
|
||||||
void main()
|
|
||||||
{
|
|
||||||
vec4 color = v4Color();
|
|
||||||
|
|
||||||
if ((iFlags & F_DISCARD_EN) != 0 && color.a <= 0)
|
|
||||||
{
|
|
||||||
discard;
|
|
||||||
}
|
|
||||||
|
|
||||||
fv4Color = color;
|
|
||||||
}
|
|
@ -1,19 +0,0 @@
|
|||||||
#version 130
|
|
||||||
|
|
||||||
uniform mat4 m4View;
|
|
||||||
uniform mat4 m4Model;
|
|
||||||
|
|
||||||
in vec2 v2Position;
|
|
||||||
in vec2 v2Texture;
|
|
||||||
in vec4 v4Color;
|
|
||||||
|
|
||||||
out vec2 fv2Texture;
|
|
||||||
out vec4 fv4Color;
|
|
||||||
|
|
||||||
void main()
|
|
||||||
{
|
|
||||||
fv4Color = v4Color;
|
|
||||||
fv2Texture = v2Texture;
|
|
||||||
|
|
||||||
gl_Position = m4View * m4Model * vec4(v2Position.xy, 1, 1);
|
|
||||||
}
|
|
15
Quik.sln
15
Quik.sln
@ -15,6 +15,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{AE05ADE5
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Quik.Stb.Tests", "tests\Quik.Stb.Tests\Quik.Stb.Tests.csproj", "{BC7D3002-B79B-4141-B6CC-74FB2175B474}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Quik.Stb.Tests", "tests\Quik.Stb.Tests\Quik.Stb.Tests.csproj", "{BC7D3002-B79B-4141-B6CC-74FB2175B474}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "QuikDemo", "tests\QuikDemo\QuikDemo.csproj", "{79CBF97F-4884-4692-94FB-75DDEB61E26F}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
@ -97,8 +99,21 @@ Global
|
|||||||
{BC7D3002-B79B-4141-B6CC-74FB2175B474}.Release|x64.Build.0 = Release|Any CPU
|
{BC7D3002-B79B-4141-B6CC-74FB2175B474}.Release|x64.Build.0 = Release|Any CPU
|
||||||
{BC7D3002-B79B-4141-B6CC-74FB2175B474}.Release|x86.ActiveCfg = Release|Any CPU
|
{BC7D3002-B79B-4141-B6CC-74FB2175B474}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
{BC7D3002-B79B-4141-B6CC-74FB2175B474}.Release|x86.Build.0 = Release|Any CPU
|
{BC7D3002-B79B-4141-B6CC-74FB2175B474}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{79CBF97F-4884-4692-94FB-75DDEB61E26F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{79CBF97F-4884-4692-94FB-75DDEB61E26F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{79CBF97F-4884-4692-94FB-75DDEB61E26F}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{79CBF97F-4884-4692-94FB-75DDEB61E26F}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{79CBF97F-4884-4692-94FB-75DDEB61E26F}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{79CBF97F-4884-4692-94FB-75DDEB61E26F}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{79CBF97F-4884-4692-94FB-75DDEB61E26F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{79CBF97F-4884-4692-94FB-75DDEB61E26F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{79CBF97F-4884-4692-94FB-75DDEB61E26F}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{79CBF97F-4884-4692-94FB-75DDEB61E26F}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{79CBF97F-4884-4692-94FB-75DDEB61E26F}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{79CBF97F-4884-4692-94FB-75DDEB61E26F}.Release|x86.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(NestedProjects) = preSolution
|
GlobalSection(NestedProjects) = preSolution
|
||||||
{BC7D3002-B79B-4141-B6CC-74FB2175B474} = {AE05ADE5-A809-479F-97D5-BEAFE7604285}
|
{BC7D3002-B79B-4141-B6CC-74FB2175B474} = {AE05ADE5-A809-479F-97D5-BEAFE7604285}
|
||||||
|
{79CBF97F-4884-4692-94FB-75DDEB61E26F} = {AE05ADE5-A809-479F-97D5-BEAFE7604285}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
EndGlobal
|
EndGlobal
|
||||||
|
@ -80,9 +80,10 @@ namespace Quik.OpenGL
|
|||||||
{
|
{
|
||||||
AssertInit();
|
AssertInit();
|
||||||
|
|
||||||
if (data.TryGetValue(queue, out DrawData draw))
|
if (!data.TryGetValue(queue, out DrawData draw))
|
||||||
{
|
{
|
||||||
draw = new DrawData(this, queue);
|
draw = new DrawData(this, queue);
|
||||||
|
data.Add(queue, draw);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This already binds the vertex array for me.
|
// This already binds the vertex array for me.
|
||||||
@ -206,12 +207,18 @@ namespace Quik.OpenGL
|
|||||||
|
|
||||||
GL.DeleteProgram(program);
|
GL.DeleteProgram(program);
|
||||||
|
|
||||||
|
foreach (DrawData datum in data.Values)
|
||||||
|
{
|
||||||
|
datum.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
isDiposed = true;
|
isDiposed = true;
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose() => Dispose(true);
|
public void Dispose() => Dispose(true);
|
||||||
|
|
||||||
private struct DrawData : IDisposable
|
private class DrawData : IDisposable
|
||||||
{
|
{
|
||||||
public DrawQueue Queue { get; }
|
public DrawQueue Queue { get; }
|
||||||
public int VertexArray { get; }
|
public int VertexArray { get; }
|
||||||
@ -240,6 +247,9 @@ namespace Quik.OpenGL
|
|||||||
vbo = Swap(ref vbo1, ref vbo2);
|
vbo = Swap(ref vbo1, ref vbo2);
|
||||||
ebo = Swap(ref ebo1, ref ebo2);
|
ebo = Swap(ref ebo1, ref ebo2);
|
||||||
|
|
||||||
|
if (Queue.VertexCount == 0 || Queue.ElementCount == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
GL.BindVertexArray(VertexArray);
|
GL.BindVertexArray(VertexArray);
|
||||||
GL.BindBuffer(GL_ARRAY_BUFFER, vbo);
|
GL.BindBuffer(GL_ARRAY_BUFFER, vbo);
|
||||||
GL.BufferData(GL_ARRAY_BUFFER, QuikVertex.Stride * Queue.VertexCount, Queue.VertexArray, GL_STREAM_DRAW);
|
GL.BufferData(GL_ARRAY_BUFFER, QuikVertex.Stride * Queue.VertexCount, Queue.VertexArray, GL_STREAM_DRAW);
|
||||||
|
38
Quik/PAL/IQuikHost.cs
Normal file
38
Quik/PAL/IQuikHost.cs
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
using System;
|
||||||
|
using Quik.Media;
|
||||||
|
|
||||||
|
namespace Quik.PAL
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The primary primary platform abstraction interface for Quik hosts.
|
||||||
|
/// </summary>
|
||||||
|
public interface IQuikPlatform : IDisposable
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The title of the application.
|
||||||
|
/// </summary>
|
||||||
|
string Title { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The default icon for the application.
|
||||||
|
/// </summary>
|
||||||
|
QImage Icon { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The event raised when an event is received.
|
||||||
|
/// </summary>
|
||||||
|
event EventHandler EventRaised;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create a window.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The window instance.</returns>
|
||||||
|
IQuikPort CreatePort();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Raise the events that have been enqueued.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="block">True to block until a new event arrives.</param>
|
||||||
|
void ProcessEvents(bool block);
|
||||||
|
}
|
||||||
|
}
|
49
Quik/PAL/IQuikPort.cs
Normal file
49
Quik/PAL/IQuikPort.cs
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
using System;
|
||||||
|
using Quik.CommandMachine;
|
||||||
|
|
||||||
|
namespace Quik.PAL
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An abstraction over the a window or a rendering context.
|
||||||
|
/// </summary>
|
||||||
|
public interface IQuikPort : IDisposable
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Title of the window, if applicable.
|
||||||
|
/// </summary>
|
||||||
|
string Title { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Size of the window.
|
||||||
|
/// </summary>
|
||||||
|
QVec2 Size { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Position of the window in the coordinate system.
|
||||||
|
/// </summary>
|
||||||
|
QVec2 Position { get; set; }
|
||||||
|
bool IsValid { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called when an event for this port is raised.
|
||||||
|
/// </summary>
|
||||||
|
event EventHandler EventRaised;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Focus the window, bringing it to the front.
|
||||||
|
/// </summary>
|
||||||
|
void Focus();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Show or hide the window.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="shown">True to show the window, false to hide.</param>
|
||||||
|
void Show(bool shown = true);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Paint the given command queue onto the port.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="queue">The command queue to paint.</param>
|
||||||
|
void Paint(CommandQueue queue);
|
||||||
|
}
|
||||||
|
}
|
@ -7,4 +7,8 @@
|
|||||||
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<EmbeddedResource Include="res/**" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -1,10 +1,70 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using Quik.CommandMachine;
|
||||||
|
using Quik.Controls;
|
||||||
|
using Quik.Media;
|
||||||
|
using Quik.PAL;
|
||||||
|
|
||||||
namespace Quik
|
namespace Quik
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Main class for Quik applications.
|
||||||
|
/// </summary>
|
||||||
public class QuikApplication
|
public class QuikApplication
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The application platform driver.
|
||||||
|
/// </summary>
|
||||||
|
public IQuikPlatform Platform { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Title of the application.
|
||||||
|
/// </summary>
|
||||||
|
public string Title
|
||||||
|
{
|
||||||
|
get => Platform.Title;
|
||||||
|
set => Platform.Title = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Application icon.
|
||||||
|
/// </summary>
|
||||||
|
public QImage Icon
|
||||||
|
{
|
||||||
|
get => Platform.Icon;
|
||||||
|
set => Platform.Icon = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public View MainView { get; private set; } = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// List of media loaders, drivers that load media such as images and fonts.
|
||||||
|
/// </summary>
|
||||||
|
public List<MediaLoader> MediaLoaders { get; } = new List<MediaLoader>();
|
||||||
|
|
||||||
|
public QuikApplication(IQuikPlatform platform)
|
||||||
|
{
|
||||||
|
Platform = platform;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Run(View mainView)
|
||||||
|
{
|
||||||
|
IQuikPort port = Platform.CreatePort();
|
||||||
|
CommandQueue cmd = new CommandQueue();
|
||||||
|
|
||||||
|
MainView = mainView;
|
||||||
|
|
||||||
|
port.EventRaised += (sender, ea) => mainView.NotifyEvent(sender, ea);
|
||||||
|
|
||||||
|
while (port.IsValid)
|
||||||
|
{
|
||||||
|
Platform.ProcessEvents(false);
|
||||||
|
if (port.IsValid)
|
||||||
|
{
|
||||||
|
MainView.Paint(cmd);
|
||||||
|
port.Paint(cmd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
15
tests/QuikDemo/Program.cs
Normal file
15
tests/QuikDemo/Program.cs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
using Quik;
|
||||||
|
using Quik.OpenTK;
|
||||||
|
|
||||||
|
namespace QuikDemo
|
||||||
|
{
|
||||||
|
public static class Program
|
||||||
|
{
|
||||||
|
public static readonly QuikApplication Application = new QuikApplication(new OpenTKPlatform());
|
||||||
|
|
||||||
|
public static void Main(string[] args)
|
||||||
|
{
|
||||||
|
Application.Run(new Quik.Controls.View());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
16
tests/QuikDemo/QuikDemo.csproj
Normal file
16
tests/QuikDemo/QuikDemo.csproj
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\Quik\Quik.csproj" />
|
||||||
|
<ProjectReference Include="..\..\Quik.Media.Stb\Quik.Media.Stb.csproj" />
|
||||||
|
<ProjectReference Include="..\..\Quik.OpenTK\Quik.OpenTK.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
|
<ImplicitUsings>disable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
</Project>
|
Loading…
Reference in New Issue
Block a user