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

View file

@ -1,15 +1,14 @@
using System;
using OpenTK;
using OpenGL;
using System.Runtime.InteropServices;
using Khronos;
using System.Collections.Generic;
using System.Reflection;
namespace GLWidgetTestGTK3
namespace OpenTK
{
public class GTKBindingContext : IBindingsContext
{
private static bool _loaded;
public static bool Loaded;
private const string GlxLibrary = "libGL.so.1";
private const string WglLibrary = "opengl32.dll";
@ -20,20 +19,84 @@ namespace GLWidgetTestGTK3
/// Currently loaded libraries.
/// </summary>
private static readonly Dictionary<string, IntPtr> _LibraryHandles = new Dictionary<string, IntPtr>();
public bool IsGlxRequired { get; set; }
public IntPtr GetProcAddress(string procName)
{
switch (Platform.CurrentPlatformId)
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
case Platform.Id.WindowsNT:
return GetProcAddressWgl(procName);
case Platform.Id.Linux:
return GetProcAddressGlx(procName);
case Platform.Id.MacOS:
return !Glx.IsRequired ? GetProcAddressOSX(procName) : GetProcAddressGlx(procName);
default:
throw new NotSupportedException();
var addr = GetProcAddressWgl(procName);
if (addr == null || addr == IntPtr.Zero)
{
var library = UnsafeNativeMethods.LoadLibrary(WglLibrary);
addr = UnsafeNativeMethods.GetProcAddress(library, procName);
}
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)
@ -43,7 +106,7 @@ namespace GLWidgetTestGTK3
private static void LoadLibraries()
{
if (_loaded)
if (Loaded)
{
return;
}
@ -60,7 +123,7 @@ namespace GLWidgetTestGTK3
if (functionPtr != IntPtr.Zero)
Delegates.pglXGetProcAddress = (Delegates.glXGetProcAddress)Marshal.GetDelegateForFunctionPointer(functionPtr, typeof(Delegates.glXGetProcAddress));
_loaded = true;
Loaded = true;
}
internal static IntPtr GetLibraryHandle(string libraryPath, bool throws)
@ -104,6 +167,15 @@ namespace GLWidgetTestGTK3
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)]
public static extern IntPtr wglGetProcAddress(string lpszProc);

View file

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

View file

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

View file

@ -9,53 +9,11 @@ namespace GLWidgetTestGTK3
{
public static void Main(string[] args)
{
InitializeGlBindings();
// GTK
Application.Init();
MainWindow win = MainWindow.Create();
win.Show();
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");
}
}
}