mirror of
https://github.com/Ryujinx/Opentk.git
synced 2024-12-23 02:55:31 +00:00
New bindings. Now support all extensions. Renamed ./GL.cs to ./GLHelper.cs and added many useful functions.
This commit is contained in:
parent
3ff2b848e2
commit
d0a6d86bb9
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -1,39 +0,0 @@
|
|||
#region --- License ---
|
||||
/* This source file is released under the MIT license. See License.txt for more information.
|
||||
* Coded by Stephen Apostolopoulos.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace OpenTK.OpenGL
|
||||
{
|
||||
public static partial class GL
|
||||
{
|
||||
private static Delegate WindowsGetAddress(string function_string, Type function_type)
|
||||
{
|
||||
IntPtr address = Wgl.GetProcAddress(function_string);
|
||||
if (address == IntPtr.Zero)
|
||||
return null;
|
||||
else
|
||||
return Marshal.GetDelegateForFunctionPointer(address, function_type);
|
||||
}
|
||||
|
||||
private static Delegate X11GetAddress(string function_string, Type function_type)
|
||||
{
|
||||
IntPtr address = Glx.GetProcAddress(function_string);
|
||||
if (address == IntPtr.Zero)
|
||||
return null;
|
||||
else
|
||||
return Marshal.GetDelegateForFunctionPointer(address, function_type);
|
||||
}
|
||||
|
||||
private static Delegate MacOSGetAddress(string function_string, Type function_type)
|
||||
{
|
||||
throw new NotImplementedException("This platform is not supported yet. Sorry for the inconvenience.");
|
||||
}
|
||||
}
|
||||
}
|
460
Source/OpenGL/OpenGL/GLHelper.cs
Normal file
460
Source/OpenGL/OpenGL/GLHelper.cs
Normal file
|
@ -0,0 +1,460 @@
|
|||
#region --- License ---
|
||||
/* This source file is released under the MIT license. See License.txt for more information.
|
||||
* Coded by Stephen Apostolopoulos.
|
||||
*/
|
||||
#endregion
|
||||
|
||||
#region --- Using Directives ---
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Reflection;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace OpenTK.OpenGL
|
||||
{
|
||||
/// <summary>
|
||||
/// OpenGL binding for .NET, implementing OpenGL 2.1, plus extensions.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// Tao.OpenGl.Gl contains all OpenGL enums and functions defined in the 2.1 specification.
|
||||
/// The official .spec files can be found at: http://opengl.org/registry/.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Tao.OpenGl.Gl relies on static initialization to obtain the entry points for OpenGL functions.
|
||||
/// Please ensure that a valid OpenGL context has been made current in the pertinent thread <b>before</b>
|
||||
/// any OpenGL functions are called (toolkits like GLUT, SDL or GLFW will automatically take care of
|
||||
/// the context initialization process). Without a valid OpenGL context, Tao.OpenGl.Gl will only be able
|
||||
/// to retrieve statically exported entry points (typically corresponding to OpenGL version 1.1 under Windows,
|
||||
/// 1.3 under Linux and 1.4 under Windows Vista), and extension methods will need to be loaded manually.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// If you prefer not to rely on static initialisation for the Gl class, you can use the
|
||||
/// ReloadFunctions or ReloadFunction methods to manually force the initialisation of OpenGL entry points.
|
||||
/// The ReloadFunctions method should be called whenever you change an existing visual or pixelformat. This
|
||||
/// generally happens when you change the color/stencil/depth buffer associated with a window (but probably
|
||||
/// not the resolution). This may or may not be necessary under Linux/MacOS, but is generally required for
|
||||
/// Windows.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// You can use the Gl.IsExtensionSupported method to check whether any given category of extension functions
|
||||
/// exists in the current OpenGL context. The results can be cached to speed up future searches.
|
||||
/// Keep in mind that different OpenGL contexts may support different extensions, and under different entry
|
||||
/// points. Always check if all required extensions are still supported when changing visuals or pixel
|
||||
/// formats.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// You may retrieve the entry point for an OpenGL extension using the Gl.GetDelegateForExtensionMethod
|
||||
/// and Gl.GetFunctionPointerForExtensionMethod methods. You may retrieve the entry point for an OpenGL
|
||||
/// function using the Gl.GetDelegateForMethod method. All three methods are cross-platform.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// <see href="http://opengl.org/registry/"/>
|
||||
/// <seealso cref="Gl.IsExtensionSupported(string, bool)"/>
|
||||
/// <seealso cref="Gl.GetDelegateForExtensionMethod"/>
|
||||
/// <seealso cref="Gl.GetFunctionPointerForExtensionMethod"/>
|
||||
/// <seealso cref="Gl.GetDelegateForMethod"/>
|
||||
/// <seealso cref="Gl.ReloadFunctions"/>
|
||||
/// <seealso cref="Gl.ReloadFunction"/>
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public static partial class GL
|
||||
{
|
||||
#region private enum Platform
|
||||
|
||||
/// <summary>
|
||||
/// Enumerates the platforms Tao can run on.
|
||||
/// </summary>
|
||||
private enum Platform
|
||||
{
|
||||
Unknown,
|
||||
Windows,
|
||||
X11,
|
||||
X11_ARB,
|
||||
OSX
|
||||
};
|
||||
|
||||
#endregion private enum Platform
|
||||
|
||||
private static Platform platform = Platform.Unknown;
|
||||
private static System.Collections.Generic.Dictionary<string, bool> AvailableExtensions;
|
||||
|
||||
#region internal static extern IntPtr glxGetProcAddressARB(string s);
|
||||
// also linux, for our ARB-y friends
|
||||
[DllImport(GL_NATIVE_LIBRARY, EntryPoint = "glXGetProcAddressARB")]
|
||||
internal static extern IntPtr glxGetProcAddressARB(string s);
|
||||
#endregion
|
||||
|
||||
#region internal static IntPtr aglGetProcAddress(string s)
|
||||
// osx gets complicated
|
||||
[DllImport(GL_NATIVE_LIBRARY, EntryPoint = "NSIsSymbolNameDefined")]
|
||||
internal static extern bool NSIsSymbolNameDefined(string s);
|
||||
[DllImport(GL_NATIVE_LIBRARY, EntryPoint = "NSLookupAndBindSymbol")]
|
||||
internal static extern IntPtr NSLookupAndBindSymbol(string s);
|
||||
[DllImport(GL_NATIVE_LIBRARY, EntryPoint = "NSAddressOfSymbol")]
|
||||
internal static extern IntPtr NSAddressOfSymbol(IntPtr symbol);
|
||||
|
||||
internal static IntPtr aglGetProcAddress(string s)
|
||||
{
|
||||
string fname = "_" + s;
|
||||
if (!NSIsSymbolNameDefined(fname))
|
||||
return IntPtr.Zero;
|
||||
|
||||
IntPtr symbol = NSLookupAndBindSymbol(fname);
|
||||
if (symbol != IntPtr.Zero)
|
||||
symbol = NSAddressOfSymbol(symbol);
|
||||
|
||||
return symbol;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region public static IntPtr GetFunctionPointerForExtensionMethod(string name)
|
||||
/// <summary>
|
||||
/// Retrieves the entry point for a dynamically exported OpenGL function.
|
||||
/// </summary>
|
||||
/// <param name="name">The function string for the OpenGL function (eg. "glNewList")</param>
|
||||
/// <returns>
|
||||
/// An IntPtr contaning the address for the entry point, or IntPtr.Zero if the specified
|
||||
/// OpenGL function is not dynamically exported.
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// The Marshal.GetDelegateForFunctionPointer method can be used to turn the return value
|
||||
/// into a call-able delegate.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// This function is cross-platform. It determines the underlying platform and uses the
|
||||
/// correct wgl, glx or agl GetAddress function to retrieve the function pointer.
|
||||
/// </para>
|
||||
/// <see cref="Marshal.GetDelegateForFunctionPointer"/>
|
||||
/// <seealso cref="Gl.GetDelegateForExtensionMethod"/>
|
||||
/// </remarks>
|
||||
public static IntPtr GetFunctionPointerForExtensionMethod(string name)
|
||||
{
|
||||
IntPtr result = IntPtr.Zero;
|
||||
|
||||
switch (platform)
|
||||
{
|
||||
case Platform.Unknown:
|
||||
// WGL?
|
||||
try
|
||||
{
|
||||
result = Wgl.GetProcAddress(name);
|
||||
platform = Platform.Windows;
|
||||
return result;
|
||||
}
|
||||
catch (Exception)
|
||||
{ }
|
||||
|
||||
// AGL? (before X11, since GLX might exist on OSX)
|
||||
try
|
||||
{
|
||||
result = aglGetProcAddress(name);
|
||||
platform = Platform.OSX;
|
||||
return result;
|
||||
}
|
||||
catch (Exception)
|
||||
{ }
|
||||
|
||||
// X11?
|
||||
try
|
||||
{
|
||||
result = Glx.GetProcAddress(name);
|
||||
platform = Platform.X11;
|
||||
return result;
|
||||
}
|
||||
catch (Exception)
|
||||
{ }
|
||||
|
||||
// X11 ARB?
|
||||
try
|
||||
{
|
||||
result = glxGetProcAddressARB(name);
|
||||
platform = Platform.X11_ARB;
|
||||
return result;
|
||||
}
|
||||
catch (Exception)
|
||||
{ }
|
||||
|
||||
// Ack!
|
||||
throw new NotSupportedException("Unknown platform - cannot get function pointer.");
|
||||
|
||||
case Platform.Windows:
|
||||
return Wgl.GetProcAddress(name);
|
||||
|
||||
case Platform.OSX:
|
||||
return aglGetProcAddress(name);
|
||||
|
||||
case Platform.X11:
|
||||
return Glx.GetProcAddress(name);
|
||||
|
||||
case Platform.X11_ARB:
|
||||
return glxGetProcAddressARB(name);
|
||||
}
|
||||
|
||||
throw new NotSupportedException("Internal error - please report.");
|
||||
}
|
||||
#endregion public static IntPtr GetFunctionPointerForExtensionMethod(string s)
|
||||
|
||||
#region public static Delegate GetDelegateForExtensionMethod(string name, Type signature)
|
||||
/// <summary>
|
||||
/// Creates a System.Delegate that can be used to call a dynamically exported OpenGL function.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the OpenGL function (eg. "glNewList")</param>
|
||||
/// <param name="signature">The signature of the OpenGL function.</param>
|
||||
/// <returns>
|
||||
/// A System.Delegate that can be used to call this OpenGL function or null
|
||||
/// if the function is not available in the current OpenGL context.
|
||||
/// </returns>
|
||||
public static Delegate GetDelegateForExtensionMethod(string name, Type signature)
|
||||
{
|
||||
IntPtr address = GetFunctionPointerForExtensionMethod(name);
|
||||
|
||||
if (address == IntPtr.Zero)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
return Marshal.GetDelegateForFunctionPointer(address, signature);
|
||||
}
|
||||
}
|
||||
#endregion public static Delegate GetAddress(string name, Type signature)
|
||||
|
||||
#region public static Delegate GetDelegateForMethod(string name, Type signature)
|
||||
/// <summary>
|
||||
/// Creates a System.Delegate that can be used to call an OpenGL function, core or extension.
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the OpenGL function (eg. "glNewList")</param>
|
||||
/// <param name="signature">The signature of the OpenGL function.</param>
|
||||
/// <returns>
|
||||
/// A System.Delegate that can be used to call this OpenGL function, or null if the specified
|
||||
/// function name did not correspond to an OpenGL function.
|
||||
/// </returns>
|
||||
public static Delegate GetDelegateForMethod(string name, Type signature)
|
||||
{
|
||||
Delegate d;
|
||||
|
||||
if (Assembly.Load("Tao.OpenGl").GetType("Tao.OpenGl.Imports").GetMethod(name.Substring(2)) != null)
|
||||
{
|
||||
d = GetDelegateForExtensionMethod(name, signature) ??
|
||||
Delegate.CreateDelegate(signature, typeof(Imports), name.Substring(2));
|
||||
}
|
||||
else
|
||||
{
|
||||
d = GetDelegateForExtensionMethod(name, signature);
|
||||
}
|
||||
|
||||
return d;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region public static bool IsExtensionSupported(string name)
|
||||
/// <summary>
|
||||
/// Determines whether the specified OpenGL extension category is available in
|
||||
/// the current OpenGL context. Equivalent to IsExtensionSupported(name, true)
|
||||
/// </summary>
|
||||
/// <param name="name">The string for the OpenGL extension category (eg. "GL_ARB_multitexture")</param>
|
||||
/// <returns>True if the specified extension is available, false otherwise.</returns>
|
||||
public static bool IsExtensionSupported(string name)
|
||||
{
|
||||
return IsExtensionSupported(name, true);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region public static bool IsExtensionSupported(string name, bool useCache)
|
||||
/// <summary>
|
||||
/// Determines whether the specified OpenGL extension category is available in
|
||||
/// the current OpenGL context.
|
||||
/// </summary>
|
||||
/// <param name="name">The string for the OpenGL extension category (eg. "GL_ARB_multitexture")</param>
|
||||
/// <param name="useCache">If true, the results will be cached to speed up future results.</param>
|
||||
/// <returns>True if the specified extension is available, false otherwise.</returns>
|
||||
public static bool IsExtensionSupported(string name, bool useCache)
|
||||
{
|
||||
// Use cached results
|
||||
if (useCache)
|
||||
{
|
||||
// Build cache if it is not available
|
||||
if (AvailableExtensions == null)
|
||||
{
|
||||
ParseAvailableExtensions();
|
||||
}
|
||||
|
||||
// Search the cache for the string. Note that the cache substitutes
|
||||
// strings "1.0" to "2.1" with "GL_VERSION_1_0" to "GL_VERSION_2_1"
|
||||
if (AvailableExtensions.ContainsKey(name))
|
||||
return AvailableExtensions[name];
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
// Do not use cached results
|
||||
string extension_string = GL.GetString(Enums.StringName.EXTENSIONS);
|
||||
if (String.IsNullOrEmpty(extension_string))
|
||||
return false; // no extensions are available
|
||||
|
||||
// Check if the user searches for GL_VERSION_X_X and search glGetString(GL_VERSION) instead.
|
||||
if (name.Contains("GL_VERSION_"))
|
||||
{
|
||||
return GL.GetString(OpenTK.OpenGL.Enums.StringName.VERSION).Trim().StartsWith(name.Replace("GL_VERSION_", String.Empty).Replace('_', '.'));
|
||||
}
|
||||
|
||||
// Search for the string given.
|
||||
string[] extensions = extension_string.Split(' ');
|
||||
foreach (string s in extensions)
|
||||
{
|
||||
if (name == s)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region private static void ParseAvailableExtensions()
|
||||
/// <summary>
|
||||
/// Builds a cache of the supported extensions to speed up searches.
|
||||
/// </summary>
|
||||
private static void ParseAvailableExtensions()
|
||||
{
|
||||
// Assumes there is a current context.
|
||||
|
||||
AvailableExtensions = new Dictionary<string, bool>();
|
||||
|
||||
string version_string = GL.GetString(OpenTK.OpenGL.Enums.StringName.VERSION);
|
||||
if (String.IsNullOrEmpty(version_string))
|
||||
return; // this shoudn't happen
|
||||
|
||||
string version = version_string.Trim(' ');
|
||||
|
||||
if (version.StartsWith("1.2"))
|
||||
{
|
||||
AvailableExtensions.Add("GL_VERSION_1_2", true);
|
||||
}
|
||||
else if (version.StartsWith("1.3"))
|
||||
{
|
||||
AvailableExtensions.Add("GL_VERSION_1_2", true);
|
||||
AvailableExtensions.Add("GL_VERSION_1_3", true);
|
||||
}
|
||||
else if (version.StartsWith("1.4"))
|
||||
{
|
||||
AvailableExtensions.Add("GL_VERSION_1_2", true);
|
||||
AvailableExtensions.Add("GL_VERSION_1_3", true);
|
||||
AvailableExtensions.Add("GL_VERSION_1_4", true);
|
||||
}
|
||||
else if (version.StartsWith("1.5"))
|
||||
{
|
||||
AvailableExtensions.Add("GL_VERSION_1_2", true);
|
||||
AvailableExtensions.Add("GL_VERSION_1_3", true);
|
||||
AvailableExtensions.Add("GL_VERSION_1_4", true);
|
||||
AvailableExtensions.Add("GL_VERSION_1_5", true);
|
||||
}
|
||||
else if (version.StartsWith("2.0"))
|
||||
{
|
||||
AvailableExtensions.Add("GL_VERSION_1_2", true);
|
||||
AvailableExtensions.Add("GL_VERSION_1_3", true);
|
||||
AvailableExtensions.Add("GL_VERSION_1_4", true);
|
||||
AvailableExtensions.Add("GL_VERSION_1_5", true);
|
||||
AvailableExtensions.Add("GL_VERSION_2_0", true);
|
||||
}
|
||||
else if (version.StartsWith("2.1"))
|
||||
{
|
||||
AvailableExtensions.Add("GL_VERSION_1_2", true);
|
||||
AvailableExtensions.Add("GL_VERSION_1_3", true);
|
||||
AvailableExtensions.Add("GL_VERSION_1_4", true);
|
||||
AvailableExtensions.Add("GL_VERSION_1_5", true);
|
||||
AvailableExtensions.Add("GL_VERSION_2_0", true);
|
||||
AvailableExtensions.Add("GL_VERSION_2_1", true);
|
||||
}
|
||||
|
||||
string extension_string = GL.GetString(OpenTK.OpenGL.Enums.StringName.EXTENSIONS);
|
||||
if (String.IsNullOrEmpty(extension_string))
|
||||
return; // no extensions are available
|
||||
|
||||
string[] extensions = extension_string.Split(' ');
|
||||
foreach (string ext in extensions)
|
||||
{
|
||||
AvailableExtensions.Add(ext, true);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region public static void ReloadFunctions()
|
||||
/// <summary>
|
||||
/// Reloads all OpenGL functions (core and extensions).
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// Call this function to reload all OpenGL entry points. This should be done
|
||||
/// whenever you change the pixelformat/visual, or in the case you cannot (or do not want)
|
||||
/// to use the automatic initialisation.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Calling this function before the automatic initialisation has taken place will result
|
||||
/// in the Gl class being initialised twice. This is harmless, but given the automatic
|
||||
/// initialisation should be preferred.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public static void ReloadFunctions()
|
||||
{
|
||||
Assembly asm = Assembly.Load("Tao.OpenGl");
|
||||
Type delegates_class = asm.GetType("Tao.OpenGl.Delegates");
|
||||
Type imports_class = asm.GetType("Tao.OpenGl.Imports");
|
||||
|
||||
FieldInfo[] v = delegates_class.GetFields();
|
||||
foreach (FieldInfo f in v)
|
||||
{
|
||||
f.SetValue(null, GetDelegateForMethod(f.Name, f.FieldType));
|
||||
}
|
||||
|
||||
ParseAvailableExtensions();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region public static bool ReloadFunction(string name)
|
||||
/// <summary>
|
||||
/// Tries to reload the given OpenGL function (core or extension).
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the OpenGL function (i.e. glShaderSource)</param>
|
||||
/// <returns>True if the function was found and reloaded, false otherwise.</returns>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// Use this function if you require greater granularity when loading OpenGL entry points.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// While the automatic initialisation will load all OpenGL entry points, in some cases
|
||||
/// the initialisation can take place before an OpenGL Context has been established.
|
||||
/// In this case, use this function to load the entry points for the OpenGL functions
|
||||
/// you will need, or use ReloadFunctions() to load all available entry points.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// This function will return true if the given OpenGL function exists, false otherwise.
|
||||
/// A return value of "true" does not mean that any specific OpenGL function is supported;
|
||||
/// rather it means that the string passed to this function denotes a known OpenGL function.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// To query supported extensions use the IsExtensionSupported() function instead.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public static bool ReloadFunction(string name)
|
||||
{
|
||||
Assembly asm = Assembly.Load("Tao.OpenGl");
|
||||
Type delegates_class = asm.GetType("Tao.OpenGl.Delegates");
|
||||
Type imports_class = asm.GetType("Tao.OpenGl.Imports");
|
||||
|
||||
FieldInfo f = delegates_class.GetField(name);
|
||||
if (f == null)
|
||||
return false;
|
||||
|
||||
f.SetValue(null, GetDelegateForMethod(f.Name, f.FieldType));
|
||||
|
||||
return true;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue