From 1f499158d0d296a7733390be4d69030185e9ddc1 Mon Sep 17 00:00:00 2001 From: emmaus Date: Sun, 16 Feb 2020 12:19:05 +0000 Subject: [PATCH] initial commit --- .gitignore | 166 ++++++++++++ GLWidget.sln | 37 +++ GLWidget/GLWidget.cs | 553 +++++++++++++++++++++++++++++++++++++++ GLWidget/GLWidget.csproj | 16 ++ 4 files changed, 772 insertions(+) create mode 100644 .gitignore create mode 100644 GLWidget.sln create mode 100644 GLWidget/GLWidget.cs create mode 100644 GLWidget/GLWidget.csproj diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c0af260 --- /dev/null +++ b/.gitignore @@ -0,0 +1,166 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.sln.docstates +.vs +.vscode + +# Build results + +[Dd]ebug/ +[Rr]elease/ +x64/ +build/ +[Bb]in/ +[Oo]bj/ + +# Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets +!packages/*/build/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +*_i.c +*_p.c +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.log +*.scc + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opensdf +*.sdf +*.cachefile + +# Visual Studio profiler +*.psess +*.vsp +*.vspx + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +*.ncrunch* +.*crunch*.local.xml + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.Publish.xml + +# NuGet Packages Directory +## TODO: If you have NuGet Package Restore enabled, uncomment the next line +#packages/ + +# Windows Azure Build Output +csx +*.build.csdef + +# Windows Store app package directory +AppPackages/ + +# Others +sql/ +*.Cache +ClientBin/ +[Ss]tyle[Cc]op.* +~$* +*~ +*.dbmdl +*.[Pp]ublish.xml +*.pfx +*.publishsettings +packages/* +*.config + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file to a newer +# Visual Studio version. Backup files are not needed, because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +App_Data/*.mdf +App_Data/*.ldf + + +#LightSwitch generated files +GeneratedArtifacts/ +_Pvt_Extensions/ +ModelManifest.xml + +# ========================= +# Windows detritus +# ========================= + +# Windows image file caches +Thumbs.db +ehthumbs.db + +# Folder config file +Desktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Mac desktop service store files +.DS_Store + +# VS Launch Settings +launchSettings.json + +# NetCore Publishing Profiles +PublishProfiles/ diff --git a/GLWidget.sln b/GLWidget.sln new file mode 100644 index 0000000..cf6713c --- /dev/null +++ b/GLWidget.sln @@ -0,0 +1,37 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29709.97 +MinimumVisualStudioVersion = 15.0.26124.0 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GLWidget", "GLWidget\GLWidget.csproj", "{2F1DF6C0-67E9-4ADF-B2DA-F3E1504CF57B}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {2F1DF6C0-67E9-4ADF-B2DA-F3E1504CF57B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2F1DF6C0-67E9-4ADF-B2DA-F3E1504CF57B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2F1DF6C0-67E9-4ADF-B2DA-F3E1504CF57B}.Debug|x64.ActiveCfg = Debug|Any CPU + {2F1DF6C0-67E9-4ADF-B2DA-F3E1504CF57B}.Debug|x64.Build.0 = Debug|Any CPU + {2F1DF6C0-67E9-4ADF-B2DA-F3E1504CF57B}.Debug|x86.ActiveCfg = Debug|Any CPU + {2F1DF6C0-67E9-4ADF-B2DA-F3E1504CF57B}.Debug|x86.Build.0 = Debug|Any CPU + {2F1DF6C0-67E9-4ADF-B2DA-F3E1504CF57B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2F1DF6C0-67E9-4ADF-B2DA-F3E1504CF57B}.Release|Any CPU.Build.0 = Release|Any CPU + {2F1DF6C0-67E9-4ADF-B2DA-F3E1504CF57B}.Release|x64.ActiveCfg = Release|Any CPU + {2F1DF6C0-67E9-4ADF-B2DA-F3E1504CF57B}.Release|x64.Build.0 = Release|Any CPU + {2F1DF6C0-67E9-4ADF-B2DA-F3E1504CF57B}.Release|x86.ActiveCfg = Release|Any CPU + {2F1DF6C0-67E9-4ADF-B2DA-F3E1504CF57B}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {BD6439D8-336C-493E-B5DB-8D6BEFF51EFC} + EndGlobalSection +EndGlobal diff --git a/GLWidget/GLWidget.cs b/GLWidget/GLWidget.cs new file mode 100644 index 0000000..03bb00d --- /dev/null +++ b/GLWidget/GLWidget.cs @@ -0,0 +1,553 @@ +//https://github.com/Nihlus/GLWidgetTest/blob/master/GLWidget/GLWidgetGTK3/GLWidget.cs +#region License +// +// The Open Toolkit Library License +// +// Copyright (c) 2006 - 2009 the Open Toolkit library, except where noted. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do +// so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// +#endregion + +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Security; +using System.Threading; +using System.ComponentModel; + + +using OpenTK.Graphics; +using OpenTK.Platform; + +using Gtk; + +namespace OpenTK +{ + [ToolboxItem(true)] + public class GLWidget : DrawingArea + { + + #region Static attrs. + + private static int _graphicsContextCount; + private static bool _sharedContextInitialized; + + public bool IsRenderHandler { get; set; } = false; + + #endregion + + #region Attributes + + private IGraphicsContext _graphicsContext; + private IWindowInfo _windowInfo; + private bool _initialized; + + #endregion + + #region Properties + + /// Use a single buffer versus a double buffer. + [Browsable(true)] + public bool SingleBuffer { get; set; } + + /// Color Buffer Bits-Per-Pixel + public int ColorBPP { get; set; } + + /// Accumulation Buffer Bits-Per-Pixel + public int AccumulatorBPP { get; set; } + + /// Depth Buffer Bits-Per-Pixel + public int DepthBPP { get; set; } + + /// Stencil Buffer Bits-Per-Pixel + public int StencilBPP { get; set; } + + /// Number of samples + public int Samples { get; set; } + + /// Indicates if steropic renderering is enabled + public bool Stereo { get; set; } + + /// The major version of OpenGL to use. + public int GLVersionMajor { get; set; } + + /// The minor version of OpenGL to use. + public int GLVersionMinor { get; set; } + + public GraphicsContextFlags GraphicsContextFlags + { + get; + set; + } + + #endregion + + #region Construction/Destruction + + /// Constructs a new GLWidget. + public GLWidget() + : this(GraphicsMode.Default) + { + } + + /// Constructs a new GLWidget using a given GraphicsMode + public GLWidget(GraphicsMode graphicsMode) + : this(graphicsMode, 1, 0, GraphicsContextFlags.Default) + { + } + + /// Constructs a new GLWidget + public GLWidget(GraphicsMode graphicsMode, int glVersionMajor, int glVersionMinor, GraphicsContextFlags graphicsContextFlags) + { + SingleBuffer = graphicsMode.Buffers == 1; + ColorBPP = graphicsMode.ColorFormat.BitsPerPixel; + AccumulatorBPP = graphicsMode.AccumulatorFormat.BitsPerPixel; + DepthBPP = graphicsMode.Depth; + StencilBPP = graphicsMode.Stencil; + Samples = graphicsMode.Samples; + Stereo = graphicsMode.Stereo; + + GLVersionMajor = glVersionMajor; + GLVersionMinor = glVersionMinor; + GraphicsContextFlags = graphicsContextFlags; + } + + ~GLWidget() + { + Dispose(false); + } + + protected override void Dispose(bool disposing) + { + if (disposing) + { + try + { + GraphicsContext.MakeCurrent(WindowInfo); + }catch(Exception ex) + { + + } + + OnShuttingDown(); + + if (OpenTK.Graphics.GraphicsContext.ShareContexts && (Interlocked.Decrement(ref _graphicsContextCount) == 0)) + { + OnGraphicsContextShuttingDown(); + _sharedContextInitialized = false; + } + + GraphicsContext.Dispose(); + } + } + + #endregion + + #region New Events + + // Called when the first GraphicsContext is created in the case of GraphicsContext.ShareContexts == True; + public static event EventHandler GraphicsContextInitialized; + + private static void OnGraphicsContextInitialized() + { + if (GraphicsContextInitialized != null) + { + GraphicsContextInitialized(null, EventArgs.Empty); + } + } + + // Called when the first GraphicsContext is being destroyed in the case of GraphicsContext.ShareContexts == True; + public static event EventHandler GraphicsContextShuttingDown; + + private static void OnGraphicsContextShuttingDown() + { + if (GraphicsContextShuttingDown != null) + { + GraphicsContextShuttingDown(null, EventArgs.Empty); + } + } + + // Called when this GLWidget has a valid GraphicsContext + public event EventHandler Initialized; + + protected virtual void OnInitialized() + { + if (Initialized != null) + { + Initialized(this, EventArgs.Empty); + } + } + + // Called when this GLWidget needs to render a frame + public event EventHandler RenderFrame; + + protected virtual void OnRenderFrame() + { + if (RenderFrame != null) + { + RenderFrame(this, EventArgs.Empty); + } + } + + // Called when this GLWidget is being Disposed + public event EventHandler ShuttingDown; + + protected virtual void OnShuttingDown() + { + if (ShuttingDown != null) + { + ShuttingDown(this, EventArgs.Empty); + } + } + + #endregion + + // Called when a widget is realized. (window handles and such are valid) + // protected override void OnRealized() { base.OnRealized(); } + + // Called when the widget needs to be (fully or partially) redrawn. + + protected override bool OnDrawn(Cairo.Context cr) + { + if (!_initialized) + Initialize(); + else if(!IsRenderHandler) + GraphicsContext.MakeCurrent(WindowInfo); + + return true; + } + + // Called on Resize + protected override bool OnConfigureEvent(Gdk.EventConfigure evnt) + { + if (GraphicsContext != null) + { + GraphicsContext.Update(WindowInfo); + } + + return true; + } + + private void Initialize() + { + _initialized = true; + + // If this looks uninitialized... initialize. + if (ColorBPP == 0) + { + ColorBPP = 32; + + if (DepthBPP == 0) + { + DepthBPP = 16; + } + } + + ColorFormat colorBufferColorFormat = new ColorFormat(ColorBPP); + + ColorFormat accumulationColorFormat = new ColorFormat(AccumulatorBPP); + + int buffers = 2; + if (SingleBuffer) + { + buffers--; + } + + GraphicsMode graphicsMode = new GraphicsMode(colorBufferColorFormat, DepthBPP, StencilBPP, Samples, accumulationColorFormat, buffers, Stereo); + + this.Window.EnsureNative(); + + // IWindowInfo + if (OpenTK.Configuration.RunningOnWindows) + { + WindowInfo = InitializeWindows(); + } + else if (OpenTK.Configuration.RunningOnMacOS) + { + WindowInfo = InitializeOSX(); + } + else + { + WindowInfo = InitializeX(graphicsMode); + } + + // GraphicsContext + GraphicsContext = new GraphicsContext(graphicsMode, WindowInfo, GLVersionMajor, GLVersionMinor, GraphicsContextFlags); + GraphicsContext.MakeCurrent(WindowInfo); + + if (OpenTK.Graphics.GraphicsContext.ShareContexts) + { + Interlocked.Increment(ref _graphicsContextCount); + + if (!_sharedContextInitialized) + { + _sharedContextInitialized = true; + ((IGraphicsContextInternal)GraphicsContext).LoadAll(); + OnGraphicsContextInitialized(); + } + } + else + { + ((IGraphicsContextInternal)GraphicsContext).LoadAll(); + OnGraphicsContextInitialized(); + } + + OnInitialized(); + } + + #region Windows Specific initalization + + IWindowInfo InitializeWindows() + { + IntPtr windowHandle = gdk_win32_window_get_handle(this.Window.Handle); + return Utilities.CreateWindowsWindowInfo(windowHandle); + } + + [SuppressUnmanagedCodeSecurity, DllImport("libgdk-3-0.dll")] + public static extern IntPtr gdk_win32_window_get_handle(IntPtr d); + + #endregion + + #region OSX Specific Initialization + + IWindowInfo InitializeOSX() + { + IntPtr windowHandle = gdk_quartz_window_get_nswindow(this.Window.Handle); + //IntPtr viewHandle = gdk_quartz_window_get_nsview(this.GdkWindow.Handle); + return Utilities.CreateMacOSCarbonWindowInfo(windowHandle, true, true); + } + + [SuppressUnmanagedCodeSecurity, DllImport("libgdk-quartz-2.0.0.dylib")] + static extern IntPtr gdk_quartz_window_get_nswindow(IntPtr handle); + + [SuppressUnmanagedCodeSecurity, DllImport("libgdk-quartz-2.0.0.dylib")] + static extern IntPtr gdk_quartz_window_get_nsview(IntPtr handle); + + #endregion + + #region X Specific Initialization + + const string UnixLibGdkName = "libgdk-3.so.0"; + + const string UnixLibX11Name = "libX11.so.6"; + const string UnixLibGLName = "libGL.so.1"; + + const int GLX_NONE = 0; + const int GLX_USE_GL = 1; + const int GLX_BUFFER_SIZE = 2; + const int GLX_LEVEL = 3; + const int GLX_RGBA = 4; + const int GLX_DOUBLEBUFFER = 5; + const int GLX_STEREO = 6; + const int GLX_AUX_BUFFERS = 7; + const int GLX_RED_SIZE = 8; + const int GLX_GREEN_SIZE = 9; + const int GLX_BLUE_SIZE = 10; + const int GLX_ALPHA_SIZE = 11; + const int GLX_DEPTH_SIZE = 12; + const int GLX_STENCIL_SIZE = 13; + const int GLX_ACCUM_RED_SIZE = 14; + const int GLX_ACCUM_GREEN_SIZE = 15; + const int GLX_ACCUM_BLUE_SIZE = 16; + const int GLX_ACCUM_ALPHA_SIZE = 17; + + public enum XVisualClass + { + StaticGray = 0, + GrayScale = 1, + StaticColor = 2, + PseudoColor = 3, + TrueColor = 4, + DirectColor = 5, + } + + [StructLayout(LayoutKind.Sequential)] + struct XVisualInfo + { + public IntPtr Visual; + public IntPtr VisualID; + public int Screen; + public int Depth; + public XVisualClass Class; + public long RedMask; + public long GreenMask; + public long blueMask; + public int ColormapSize; + public int BitsPerRgb; + + public override string ToString() + { + return $"id ({VisualID}), screen ({Screen}), depth ({Depth}), class ({Class})"; + } + } + + [Flags] + internal enum XVisualInfoMask + { + No = 0x0, + ID = 0x1, + Screen = 0x2, + Depth = 0x4, + Class = 0x8, + Red = 0x10, + Green = 0x20, + Blue = 0x40, + ColormapSize = 0x80, + BitsPerRGB = 0x100, + All = 0x1FF, + } + + private IWindowInfo InitializeX(GraphicsMode mode) + { + IntPtr display = gdk_x11_display_get_xdisplay(Display.Handle); + int screen = Screen.Number; + + IntPtr windowHandle = gdk_x11_window_get_xid(Window.Handle); + IntPtr rootWindow = gdk_x11_window_get_xid(RootWindow.Handle); + + IntPtr visualInfo; + + if (mode.Index.HasValue) + { + XVisualInfo info = new XVisualInfo(); + info.VisualID = mode.Index.Value; + int dummy; + visualInfo = XGetVisualInfo(display, XVisualInfoMask.ID, ref info, out dummy); + } + else + { + visualInfo = GetVisualInfo(display); + } + + IWindowInfo retval = Utilities.CreateX11WindowInfo(display, screen, windowHandle, rootWindow, visualInfo); + XFree(visualInfo); + + return retval; + } + + private static IntPtr XGetVisualInfo(IntPtr display, XVisualInfoMask vinfo_mask, ref XVisualInfo template, out int nitems) + { + return XGetVisualInfoInternal(display, (IntPtr)(int)vinfo_mask, ref template, out nitems); + } + + private IntPtr GetVisualInfo(IntPtr display) + { + try + { + int[] attributes = AttributeList.ToArray(); + return glXChooseVisual(display, Screen.Number, attributes); + } + catch (DllNotFoundException e) + { + throw new DllNotFoundException("OpenGL dll not found!", e); + } + catch (EntryPointNotFoundException enf) + { + throw new EntryPointNotFoundException("Glx entry point not found!", enf); + } + } + + private List AttributeList + { + get + { + List attributeList = new List(24); + + attributeList.Add(GLX_RGBA); + + if (!SingleBuffer) + attributeList.Add(GLX_DOUBLEBUFFER); + + if (Stereo) + attributeList.Add(GLX_STEREO); + + attributeList.Add(GLX_RED_SIZE); + attributeList.Add(ColorBPP / 4); // TODO support 16-bit + + attributeList.Add(GLX_GREEN_SIZE); + attributeList.Add(ColorBPP / 4); // TODO support 16-bit + + attributeList.Add(GLX_BLUE_SIZE); + attributeList.Add(ColorBPP / 4); // TODO support 16-bit + + attributeList.Add(GLX_ALPHA_SIZE); + attributeList.Add(ColorBPP / 4); // TODO support 16-bit + + attributeList.Add(GLX_DEPTH_SIZE); + attributeList.Add(DepthBPP); + + attributeList.Add(GLX_STENCIL_SIZE); + attributeList.Add(StencilBPP); + + attributeList.Add(GLX_ACCUM_RED_SIZE); + attributeList.Add(AccumulatorBPP / 4);// TODO support 16-bit + + attributeList.Add(GLX_ACCUM_GREEN_SIZE); + attributeList.Add(AccumulatorBPP / 4);// TODO support 16-bit + + attributeList.Add(GLX_ACCUM_BLUE_SIZE); + attributeList.Add(AccumulatorBPP / 4);// TODO support 16-bit + + attributeList.Add(GLX_ACCUM_ALPHA_SIZE); + attributeList.Add(AccumulatorBPP / 4);// TODO support 16-bit + + attributeList.Add(GLX_NONE); + + return attributeList; + } + } + + public IGraphicsContext GraphicsContext { get => _graphicsContext; set => _graphicsContext = value; } + public IWindowInfo WindowInfo { get => _windowInfo; set => _windowInfo = value; } + + [DllImport(UnixLibX11Name, EntryPoint = "XGetVisualInfo")] + private static extern IntPtr XGetVisualInfoInternal(IntPtr display, IntPtr vinfo_mask, ref XVisualInfo template, out int nitems); + + [SuppressUnmanagedCodeSecurity, DllImport(UnixLibX11Name)] + private static extern void XFree(IntPtr handle); + + /// Returns the X resource (window or pixmap) belonging to a GdkDrawable. + /// XID gdk_x11_drawable_get_xid(GdkDrawable *drawable); + /// The GdkDrawable. + /// The ID of drawable's X resource. + [SuppressUnmanagedCodeSecurity, DllImport(UnixLibGdkName)] + private static extern IntPtr gdk_x11_drawable_get_xid(IntPtr gdkDisplay); + + /// Returns the X resource (window or pixmap) belonging to a GdkDrawable. + /// XID gdk_x11_drawable_get_xid(GdkDrawable *drawable); + /// The GdkDrawable. + /// The ID of drawable's X resource. + [SuppressUnmanagedCodeSecurity, DllImport(UnixLibGdkName)] + private static extern IntPtr gdk_x11_window_get_xid(IntPtr gdkDisplay); + + /// Returns the X display of a GdkDisplay. + /// Display* gdk_x11_display_get_xdisplay(GdkDisplay *display); + /// The GdkDrawable. + /// The X Display of the GdkDisplay. + [SuppressUnmanagedCodeSecurity, DllImport(UnixLibGdkName)] + private static extern IntPtr gdk_x11_display_get_xdisplay(IntPtr gdkDisplay); + + [SuppressUnmanagedCodeSecurity, DllImport(UnixLibGLName)] + private static extern IntPtr glXChooseVisual(IntPtr display, int screen, int[] attr); + + #endregion + } +} \ No newline at end of file diff --git a/GLWidget/GLWidget.csproj b/GLWidget/GLWidget.csproj new file mode 100644 index 0000000..8b59567 --- /dev/null +++ b/GLWidget/GLWidget.csproj @@ -0,0 +1,16 @@ + + + + netstandard2.1 + true + GLWigdet for GTKSharp, using Opentk. + 1.0.1 + https://github.com/Ryujinx/GLWidget + + + + + + + +