This commit is contained in:
emmaus 2020-09-03 21:28:26 +00:00
parent f7b22649c6
commit 6fed327bc6
5 changed files with 139 additions and 81 deletions

View file

@ -40,6 +40,7 @@ using OpenTK.Graphics.OpenGL;
using Gtk; using Gtk;
using Cairo; using Cairo;
using GLib;
namespace OpenTK namespace OpenTK
{ {
@ -52,7 +53,7 @@ namespace OpenTK
private static int _graphicsContextCount; private static int _graphicsContextCount;
private static bool _sharedContextInitialized; private static bool _sharedContextInitialized;
public bool IsRenderHandler { get; set; } = false; public bool HandleRendering { get; set; } = false;
#endregion #endregion
@ -73,6 +74,7 @@ namespace OpenTK
private int _framebuffer; private int _framebuffer;
private int _renderbuffer; private int _renderbuffer;
private int _stencilbuffer; private int _stencilbuffer;
private bool _recreateFramebuffer;
public Gdk.GLContext GraphicsContext { get; set; } public Gdk.GLContext GraphicsContext { get; set; }
public bool ForwardCompatible { get; } public bool ForwardCompatible { get; }
@ -173,10 +175,13 @@ namespace OpenTK
protected override bool OnDrawn(Cairo.Context cr) protected override bool OnDrawn(Cairo.Context cr)
{ {
if (!_initialized) if (!_initialized)
Initialize(); System.Threading.Tasks.Task.Run(Initialize).Wait();
else if (!IsRenderHandler)
if (HandleRendering)
{ {
MakeCurrent(); MakeCurrent();
OnRenderFrame();
} }
cr.SetSourceColor(new Color(0, 0, 0, 1)); cr.SetSourceColor(new Color(0, 0, 0, 1));
@ -194,6 +199,13 @@ namespace OpenTK
GL.Flush(); GL.Flush();
QueueDraw(); QueueDraw();
RecreateFramebuffer();
if (HandleRendering)
{
ClearCurrent();
}
} }
public void MakeCurrent() public void MakeCurrent()
@ -212,18 +224,28 @@ namespace OpenTK
{ {
if (GraphicsContext != null) if (GraphicsContext != null)
{ {
MakeCurrent(); _recreateFramebuffer = true;
GraphicsContext.Window.Resize(evnt.X, evnt.Y);
DeleteBuffers();
CreateFramebuffer();
} }
return true; return true;
} }
public void RecreateFramebuffer()
{
if (!_recreateFramebuffer)
{
return;
}
_recreateFramebuffer = false;
GraphicsContext.Window.Resize(AllocatedWidth, AllocatedHeight);
DeleteBuffers();
CreateFramebuffer();
}
private void DeleteBuffers() private void DeleteBuffers()
{ {
if (_framebuffer != 0) if (_framebuffer != 0)
@ -258,8 +280,6 @@ namespace OpenTK
{ {
_initialized = true; _initialized = true;
this.Window.EnsureNative();
GraphicsContext = Window.CreateGlContext(); GraphicsContext = Window.CreateGlContext();
GraphicsContext.SetRequiredVersion(GLVersionMajor, GLVersionMinor); GraphicsContext.SetRequiredVersion(GLVersionMajor, GLVersionMinor);
@ -272,9 +292,16 @@ namespace OpenTK
GraphicsContext.MakeCurrent(); GraphicsContext.MakeCurrent();
if (!GTKBindingContext.Loaded)
{
GTKBindingContext.InitializeGlBindings();
}
CreateFramebuffer(); CreateFramebuffer();
OnInitialized(); OnInitialized();
ClearCurrent();
} }
} }
} }

View file

@ -1,15 +1,14 @@
using System; using System;
using OpenTK; using OpenTK;
using OpenGL;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using Khronos;
using System.Collections.Generic; using System.Collections.Generic;
using System.Reflection;
namespace GLWidgetTestGTK3 namespace OpenTK
{ {
public class GTKBindingContext : IBindingsContext public class GTKBindingContext : IBindingsContext
{ {
private static bool _loaded; public static bool Loaded;
private const string GlxLibrary = "libGL.so.1"; private const string GlxLibrary = "libGL.so.1";
private const string WglLibrary = "opengl32.dll"; private const string WglLibrary = "opengl32.dll";
@ -20,20 +19,84 @@ namespace GLWidgetTestGTK3
/// Currently loaded libraries. /// Currently loaded libraries.
/// </summary> /// </summary>
private static readonly Dictionary<string, IntPtr> _LibraryHandles = new Dictionary<string, IntPtr>(); private static readonly Dictionary<string, IntPtr> _LibraryHandles = new Dictionary<string, IntPtr>();
public bool IsGlxRequired { get; set; }
public IntPtr GetProcAddress(string procName) public IntPtr GetProcAddress(string procName)
{ {
switch (Platform.CurrentPlatformId) if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{ {
case Platform.Id.WindowsNT: var addr = GetProcAddressWgl(procName);
return GetProcAddressWgl(procName); if (addr == null || addr == IntPtr.Zero)
case Platform.Id.Linux: {
return GetProcAddressGlx(procName); var library = UnsafeNativeMethods.LoadLibrary(WglLibrary);
case Platform.Id.MacOS:
return !Glx.IsRequired ? GetProcAddressOSX(procName) : GetProcAddressGlx(procName); addr = UnsafeNativeMethods.GetProcAddress(library, procName);
default: }
throw new NotSupportedException();
if (addr != IntPtr.Zero)
{
Loaded = true;
}
return addr;
} }
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
return GetProcAddressGlx(procName);
}
else if(RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
var osxAddr = !IsGlxRequired ? GetProcAddressOSX(procName) : GetProcAddressGlx(procName);
if (osxAddr != IntPtr.Zero)
{
Loaded = true;
}
return osxAddr;
}
else
{
throw new NotSupportedException();
}
}
public static void InitializeGlBindings()
{
// We don't put a hard dependency on OpenTK.Graphics here.
// So we need to use reflection to initialize the GL bindings, so users don't have to.
// Try to load OpenTK.Graphics assembly.
Assembly assembly;
try
{
assembly = Assembly.Load("OpenTK.Graphics");
}
catch
{
// Failed to load graphics, oh well.
// Up to the user I guess?
// TODO: Should we expose this load failure to the user better?
return;
}
var provider = new GTKBindingContext();
void LoadBindings(string typeNamespace)
{
var type = assembly.GetType($"OpenTK.Graphics.{typeNamespace}.GL");
if (type == null)
{
return;
}
var load = type.GetMethod("LoadBindings");
load.Invoke(null, new object[] { provider });
}
LoadBindings("ES11");
LoadBindings("ES20");
LoadBindings("ES30");
LoadBindings("OpenGL");
LoadBindings("OpenGL4");
} }
private static IntPtr GetProcAddressWgl(string function) private static IntPtr GetProcAddressWgl(string function)
@ -43,7 +106,7 @@ namespace GLWidgetTestGTK3
private static void LoadLibraries() private static void LoadLibraries()
{ {
if (_loaded) if (Loaded)
{ {
return; return;
} }
@ -60,7 +123,7 @@ namespace GLWidgetTestGTK3
if (functionPtr != IntPtr.Zero) if (functionPtr != IntPtr.Zero)
Delegates.pglXGetProcAddress = (Delegates.glXGetProcAddress)Marshal.GetDelegateForFunctionPointer(functionPtr, typeof(Delegates.glXGetProcAddress)); Delegates.pglXGetProcAddress = (Delegates.glXGetProcAddress)Marshal.GetDelegateForFunctionPointer(functionPtr, typeof(Delegates.glXGetProcAddress));
_loaded = true; Loaded = true;
} }
internal static IntPtr GetLibraryHandle(string libraryPath, bool throws) internal static IntPtr GetLibraryHandle(string libraryPath, bool throws)
@ -104,6 +167,15 @@ namespace GLWidgetTestGTK3
private static class UnsafeNativeMethods private static class UnsafeNativeMethods
{ {
[DllImport("kernel32.dll", SetLastError = true)]
internal static extern IntPtr GetProcAddress(IntPtr handle, string funcname);
[DllImport("kernel32.dll", SetLastError = true)]
internal static extern IntPtr GetProcAddress(IntPtr handle, IntPtr funcname);
[DllImport("kernel32.dll", SetLastError = true)]
internal static extern IntPtr LoadLibrary(string dllName);
[DllImport(WglLibrary, EntryPoint = "wglGetProcAddress", ExactSpelling = true, SetLastError = true)] [DllImport(WglLibrary, EntryPoint = "wglGetProcAddress", ExactSpelling = true, SetLastError = true)]
public static extern IntPtr wglGetProcAddress(string lpszProc); public static extern IntPtr wglGetProcAddress(string lpszProc);

View file

@ -11,28 +11,31 @@
<AssemblyName>GLWidgetTestGTK3</AssemblyName> <AssemblyName>GLWidgetTestGTK3</AssemblyName>
<ReleaseVersion>1.1</ReleaseVersion> <ReleaseVersion>1.1</ReleaseVersion>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<PlatformTarget>x64</PlatformTarget>
</PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="GtkSharp" Version="3.22.25.56"/> <PackageReference Include="GtkSharp" Version="3.22.25.56" />
<PackageReference Include="OpenTK" Version="4.0.0-pre9.4"/> <PackageReference Include="OpenTK" Version="4.0.0-pre9.4" />
<PackageReference Include="OpenGL.Net" Version="1.0.304"/> <PackageReference Include="OpenGL.Net" Version="1.0.304" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<EmbeddedResource Include="interfaces\MainWindow.glade"/> <EmbeddedResource Include="interfaces\MainWindow.glade" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<EmbeddedResource Include="Shaders\FragmentShader.glsl"/> <EmbeddedResource Include="Shaders\FragmentShader.glsl" />
<EmbeddedResource Include="Shaders\VertexShader.glsl"/> <EmbeddedResource Include="Shaders\VertexShader.glsl" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="packages.config"/> <None Include="packages.config" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\GLWidget\GLWidget.csproj"/> <ProjectReference Include="..\GLWidget\GLWidget.csproj" />
</ItemGroup> </ItemGroup>
<ProjectExtensions> <ProjectExtensions>
<MonoDevelop> <MonoDevelop>
<Properties> <Properties>
<GtkDesignInfo generateGettext="False"/> <GtkDesignInfo generateGettext="False" />
</Properties> </Properties>
</MonoDevelop> </MonoDevelop>
</ProjectExtensions> </ProjectExtensions>

View file

@ -465,8 +465,6 @@ namespace GLWidgetTestGTK3
//RenderFrame(); //RenderFrame();
MainGLWidget.ClearCurrent();
// End delta time calculation // End delta time calculation
deltaTimeWatcher.Stop(); deltaTimeWatcher.Stop();
this.deltaTime = (float)(deltaTimeWatcher.ElapsedMilliseconds * 0.001f); this.deltaTime = (float)(deltaTimeWatcher.ElapsedMilliseconds * 0.001f);

View file

@ -9,53 +9,11 @@ namespace GLWidgetTestGTK3
{ {
public static void Main(string[] args) public static void Main(string[] args)
{ {
InitializeGlBindings();
// GTK // GTK
Application.Init(); Application.Init();
MainWindow win = MainWindow.Create(); MainWindow win = MainWindow.Create();
win.Show(); win.Show();
Application.Run(); Application.Run();
} }
private static void InitializeGlBindings()
{
// We don't put a hard dependency on OpenTK.Graphics here.
// So we need to use reflection to initialize the GL bindings, so users don't have to.
// Try to load OpenTK.Graphics assembly.
Assembly assembly;
try
{
assembly = Assembly.Load("OpenTK.Graphics");
}
catch
{
// Failed to load graphics, oh well.
// Up to the user I guess?
// TODO: Should we expose this load failure to the user better?
return;
}
var provider = new GTKBindingContext();
void LoadBindings(string typeNamespace)
{
var type = assembly.GetType($"OpenTK.Graphics.{typeNamespace}.GL");
if (type == null)
{
return;
}
var load = type.GetMethod("LoadBindings");
load.Invoke(null, new object[] { provider });
}
LoadBindings("ES11");
LoadBindings("ES20");
LoadBindings("ES30");
LoadBindings("OpenGL");
LoadBindings("OpenGL4");
}
} }
} }