From 6fed327bc6a3ee63b5838d1a98923553268557ee Mon Sep 17 00:00:00 2001 From: emmaus Date: Thu, 3 Sep 2020 21:28:26 +0000 Subject: [PATCH] wip --- GLWidget/GLWidget.cs | 51 +++++++-- .../GTKBindingContext.cs | 104 +++++++++++++++--- GLWidgetTestGTK3/GLWidgetTestGTK3.csproj | 21 ++-- GLWidgetTestGTK3/MainWindow.cs | 2 - GLWidgetTestGTK3/Program.cs | 42 ------- 5 files changed, 139 insertions(+), 81 deletions(-) rename {GLWidgetTestGTK3 => GLWidget}/GTKBindingContext.cs (57%) diff --git a/GLWidget/GLWidget.cs b/GLWidget/GLWidget.cs index 22d5bb3..c4a327a 100644 --- a/GLWidget/GLWidget.cs +++ b/GLWidget/GLWidget.cs @@ -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(); } } } \ No newline at end of file diff --git a/GLWidgetTestGTK3/GTKBindingContext.cs b/GLWidget/GTKBindingContext.cs similarity index 57% rename from GLWidgetTestGTK3/GTKBindingContext.cs rename to GLWidget/GTKBindingContext.cs index 5775da8..c3ade44 100644 --- a/GLWidgetTestGTK3/GTKBindingContext.cs +++ b/GLWidget/GTKBindingContext.cs @@ -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. /// private static readonly Dictionary _LibraryHandles = new Dictionary(); - + + 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); diff --git a/GLWidgetTestGTK3/GLWidgetTestGTK3.csproj b/GLWidgetTestGTK3/GLWidgetTestGTK3.csproj index 60dcc92..8fe5f05 100644 --- a/GLWidgetTestGTK3/GLWidgetTestGTK3.csproj +++ b/GLWidgetTestGTK3/GLWidgetTestGTK3.csproj @@ -11,28 +11,31 @@ GLWidgetTestGTK3 1.1 + + x64 + - - - + + + - + - - + + - + - + - + diff --git a/GLWidgetTestGTK3/MainWindow.cs b/GLWidgetTestGTK3/MainWindow.cs index 176ccba..7876af5 100644 --- a/GLWidgetTestGTK3/MainWindow.cs +++ b/GLWidgetTestGTK3/MainWindow.cs @@ -465,8 +465,6 @@ namespace GLWidgetTestGTK3 //RenderFrame(); - MainGLWidget.ClearCurrent(); - // End delta time calculation deltaTimeWatcher.Stop(); this.deltaTime = (float)(deltaTimeWatcher.ElapsedMilliseconds * 0.001f); diff --git a/GLWidgetTestGTK3/Program.cs b/GLWidgetTestGTK3/Program.cs index dc9e588..af8641a 100644 --- a/GLWidgetTestGTK3/Program.cs +++ b/GLWidgetTestGTK3/Program.cs @@ -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"); - } } } \ No newline at end of file