From e59894411d920b21b0033d7cdf90bca7e0d5cdeb Mon Sep 17 00:00:00 2001 From: Emmanuel Date: Fri, 4 Sep 2020 16:15:21 +0000 Subject: [PATCH] glxcontexts --- GLWidget/GLWidget.cs | 35 +++-- ...KBindingContext.cs => GTKBindingHelper.cs} | 76 ++++++++++- GLWidget/GraphicsContext.cs | 120 ++++++++++++++++++ 3 files changed, 211 insertions(+), 20 deletions(-) rename GLWidget/{GTKBindingContext.cs => GTKBindingHelper.cs} (67%) create mode 100644 GLWidget/GraphicsContext.cs diff --git a/GLWidget/GLWidget.cs b/GLWidget/GLWidget.cs index c4a327a..334f9fc 100644 --- a/GLWidget/GLWidget.cs +++ b/GLWidget/GLWidget.cs @@ -55,11 +55,13 @@ namespace OpenTK public bool HandleRendering { get; set; } = false; - #endregion + public IGraphicsContext NativeGraphicsContext { get; private set; } - #region Attributes + #endregion - private bool _initialized; + #region Attributes + + private bool _initialized; #endregion @@ -184,13 +186,13 @@ namespace OpenTK OnRenderFrame(); } - cr.SetSourceColor(new Color(0, 0, 0, 1)); + /*cr.SetSourceColor(new Color(0, 0, 0, 1)); cr.Paint(); var scale = this.ScaleFactor; Gdk.CairoHelper.DrawFromGl(cr, this.Window, _renderbuffer, (int)ObjectLabelIdentifier.Renderbuffer, scale, 0, 0, AllocatedWidth, AllocatedHeight); - +*/ return true; } @@ -198,11 +200,13 @@ namespace OpenTK { GL.Flush(); - QueueDraw(); + //QueueDraw(); - RecreateFramebuffer(); + OpenTK.GraphicsContext.GetCurrentContext(Window.Handle).SwapBuffers(); - if (HandleRendering) + //RecreateFramebuffer(); + + if (!HandleRendering) { ClearCurrent(); } @@ -210,8 +214,9 @@ namespace OpenTK public void MakeCurrent() { - GraphicsContext?.MakeCurrent(); - GL.BindFramebuffer(FramebufferTarget.Framebuffer, _framebuffer); + ClearCurrent(); + NativeGraphicsContext?.MakeCurrent(); + GL.BindFramebuffer(FramebufferTarget.Framebuffer, 0); } public void ClearCurrent() @@ -292,12 +297,16 @@ namespace OpenTK GraphicsContext.MakeCurrent(); - if (!GTKBindingContext.Loaded) + if (!GTKBindingHelper.Loaded) { - GTKBindingContext.InitializeGlBindings(); + GTKBindingHelper.InitializeGlBindings(); } - CreateFramebuffer(); + OpenTK.GraphicsContext.Display = this.Display.Handle; + + NativeGraphicsContext = OpenTK.GraphicsContext.GetCurrentContext(this.Window.Handle); + + // CreateFramebuffer(); OnInitialized(); diff --git a/GLWidget/GTKBindingContext.cs b/GLWidget/GTKBindingHelper.cs similarity index 67% rename from GLWidget/GTKBindingContext.cs rename to GLWidget/GTKBindingHelper.cs index c3ade44..5b6ca0a 100644 --- a/GLWidget/GTKBindingContext.cs +++ b/GLWidget/GTKBindingHelper.cs @@ -1,4 +1,4 @@ -using System; +using System; using OpenTK; using System.Runtime.InteropServices; using System.Collections.Generic; @@ -6,8 +6,29 @@ using System.Reflection; namespace OpenTK { - public class GTKBindingContext : IBindingsContext + public class GTKBindingHelper : IBindingsContext { + public static OSPlatform CurrentPlatform + { + get + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + return OSPlatform.Windows; + } + else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + return OSPlatform.Linux; + } + else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + { + return OSPlatform.OSX; + } + + return OSPlatform.Create("None"); + } + } + public static bool Loaded; private const string GlxLibrary = "libGL.so.1"; @@ -24,7 +45,7 @@ namespace OpenTK public IntPtr GetProcAddress(string procName) { - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + if (CurrentPlatform == OSPlatform.Windows) { var addr = GetProcAddressWgl(procName); if (addr == null || addr == IntPtr.Zero) @@ -40,11 +61,11 @@ namespace OpenTK } return addr; } - else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + else if (CurrentPlatform == OSPlatform.Linux) { return GetProcAddressGlx(procName); } - else if(RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + else if(CurrentPlatform == OSPlatform.OSX) { var osxAddr = !IsGlxRequired ? GetProcAddressOSX(procName) : GetProcAddressGlx(procName); if (osxAddr != IntPtr.Zero) @@ -78,7 +99,7 @@ namespace OpenTK return; } - var provider = new GTKBindingContext(); + var provider = new GTKBindingHelper(); void LoadBindings(string typeNamespace) { @@ -165,7 +186,7 @@ namespace OpenTK return symbol; } - private static class UnsafeNativeMethods + internal static class UnsafeNativeMethods { [DllImport("kernel32.dll", SetLastError = true)] internal static extern IntPtr GetProcAddress(IntPtr handle, string funcname); @@ -179,6 +200,18 @@ namespace OpenTK [DllImport(WglLibrary, EntryPoint = "wglGetProcAddress", ExactSpelling = true, SetLastError = true)] public static extern IntPtr wglGetProcAddress(string lpszProc); + [DllImport(WglLibrary, EntryPoint = "wglGetCurrentContext")] + public extern static IntPtr wglGetCurrentContext(); + + [DllImport(WglLibrary, EntryPoint = "wglGetCurrentDC")] + public static extern IntPtr wglGetCurrentDC(); + + [DllImport(WglLibrary, EntryPoint = "wglSwapBuffers", ExactSpelling = true)] + public static extern bool wglSwapBuffers(IntPtr hdc); + + [DllImport("opengl32.dll", SetLastError = true, EntryPoint = "wglMakeCurrent")] + public static extern bool WglMakeCurrent(IntPtr hdc, IntPtr hglrc); + [DllImport(OSXLibrary, EntryPoint = "NSIsSymbolNameDefined")] public static extern bool NSIsSymbolNameDefined(string s); @@ -188,6 +221,15 @@ namespace OpenTK [DllImport(OSXLibrary, EntryPoint = "NSAddressOfSymbol")] public static extern IntPtr NSAddressOfSymbol(IntPtr symbol); + [DllImport(GlxLibrary, EntryPoint = "glXGetCurrentContext")] + public static extern IntPtr glXGetCurrentContext(); + + [DllImport(GlxLibrary, EntryPoint = "glXMakeCurrent")] + public static extern bool glXMakeCurrent(IntPtr display, IntPtr drawable, IntPtr context); + + [DllImport(GlxLibrary, EntryPoint = "glXSwapBuffers")] + public static extern void glXSwapBuffers(IntPtr display, IntPtr drawable); + public const int RTLD_LAZY = 1; public const int RTLD_NOW = 2; @@ -200,6 +242,26 @@ namespace OpenTK [DllImport("dl")] public static extern string dlerror(); + + public const string GdkNativeDll = "libgdk-3-0.dll"; + + [DllImport(GdkNativeDll, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr gdk_win32_drawable_get_handle(IntPtr raw); + + [DllImport(GdkNativeDll, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr gdk_win32_hdc_get(IntPtr drawable, IntPtr gc, int usage); + + [DllImport(GdkNativeDll, CallingConvention = CallingConvention.Cdecl)] + public static extern void gdk_win32_hdc_release(IntPtr drawable, IntPtr gc, int usage); + + [DllImport("libgdk-3.so.0", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr gdk_x11_display_get_xdisplay(IntPtr raw); + + [DllImport("libgdk-3.so.0", CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr gdk_x11_window_get_xid(IntPtr raw); + + [DllImport(GdkNativeDll, CallingConvention = CallingConvention.Cdecl)] + public static extern void gdk_window_get_internal_paint_info(IntPtr raw, out IntPtr real_drawable, out int x, out int y); } private static class Delegates diff --git a/GLWidget/GraphicsContext.cs b/GLWidget/GraphicsContext.cs new file mode 100644 index 0000000..197ef2a --- /dev/null +++ b/GLWidget/GraphicsContext.cs @@ -0,0 +1,120 @@ +using System; +using System.Runtime.InteropServices; +using static OpenTK.GTKBindingHelper; + +namespace OpenTK +{ + public interface IGraphicsContext + { + void MakeCurrent(); + void SwapBuffers(); + + void ClearCurrent(); + } + + public abstract class GraphicsContext : IGraphicsContext + { + public static IntPtr Display{ get; set; } + + public abstract void MakeCurrent(); + + public abstract void SwapBuffers(); + + public static IGraphicsContext GetCurrentContext(IntPtr handle) + { + var currentPlatform = CurrentPlatform; + + if(currentPlatform == OSPlatform.Windows){ + return WglGraphicsContext.GetCurrent(handle); + } + else if(currentPlatform == OSPlatform.Linux){ + if (Display == null || Display == IntPtr.Zero) + { + throw new InvalidOperationException("No Display set"); + } + return GlxGraphicsContext.GetCurrent(handle, Display); + } + + return null; + } + + public abstract void ClearCurrent(); + } + + public class WglGraphicsContext : GraphicsContext + { + private IntPtr _windowHandle; + private IntPtr _deviceContext; + + public WglGraphicsContext(IntPtr deviceContext, IntPtr graphicsContext, IntPtr windowHandle = default) + { + _deviceContext = deviceContext; + _graphicsContext = graphicsContext; + _windowHandle = windowHandle; + } + + private IntPtr _graphicsContext; + + public static WglGraphicsContext GetCurrent(IntPtr windowHandle) + { + IntPtr dc = UnsafeNativeMethods.wglGetCurrentDC(); + IntPtr gc = UnsafeNativeMethods.wglGetCurrentContext(); + + return new WglGraphicsContext(dc, gc, windowHandle); + } + + public override void MakeCurrent() + { + UnsafeNativeMethods.WglMakeCurrent(_deviceContext, _graphicsContext); + } + + public override void SwapBuffers() + { + UnsafeNativeMethods.wglSwapBuffers(_deviceContext); + } + + public override void ClearCurrent() + { + throw new NotImplementedException(); + } + } + + public class GlxGraphicsContext : GraphicsContext + { + private IntPtr _windowHandle; + + private IntPtr _drawable; + + public static GlxGraphicsContext GetCurrent(IntPtr windowHandle, IntPtr display) + { + var gc = UnsafeNativeMethods.glXGetCurrentContext(); + + return new GlxGraphicsContext(windowHandle, gc, display); + } + + public GlxGraphicsContext(IntPtr windowHandle, IntPtr graphicsContext, IntPtr display) + { + _windowHandle = UnsafeNativeMethods.gdk_x11_window_get_xid(windowHandle); + _display = UnsafeNativeMethods.gdk_x11_display_get_xdisplay(display); + _graphicsContext = graphicsContext; + } + + private IntPtr _graphicsContext; + private IntPtr _display; + + public override void MakeCurrent() + { + UnsafeNativeMethods.glXMakeCurrent(_display, _windowHandle, _graphicsContext); + } + + public override void SwapBuffers() + { + UnsafeNativeMethods.glXSwapBuffers(_display, _windowHandle); + } + + public override void ClearCurrent() + { + UnsafeNativeMethods.glXMakeCurrent(_display, _windowHandle, IntPtr.Zero); + } + } +} \ No newline at end of file