Merge pull request #103 from thefiddler/memopt

Memory optimizations. Memory consumption reduced by up to 80% and memory allocations reduced by up to 70%, depending on the platform.
This commit is contained in:
thefiddler 2014-04-26 19:26:07 +02:00
commit 47ffbe3501
52 changed files with 90017 additions and 141738 deletions

View file

@ -168,19 +168,42 @@ namespace Bind
sw.WriteLine("static {0}()", Settings.OutputClass);
sw.WriteLine("{");
sw.Indent();
sw.WriteLine("EntryPointNames = new string[]", delegates.Count);
// Write entry point names.
// Instead of strings, which are costly to construct,
// we use a 1d array of ASCII bytes. Names are laid out
// sequentially, with a nul-terminator between them.
sw.WriteLine("EntryPointNames = new byte[]", delegates.Count);
sw.WriteLine("{");
sw.Indent();
foreach (var d in delegates.Values.Select(d => d.First()))
{
if (!Settings.IsEnabled(Settings.Legacy.UseDllImports) || d.Extension != "Core")
if (d.RequiresSlot(Settings))
{
sw.WriteLine("\"{0}{1}\",", Settings.FunctionPrefix, d.Name);
var name = Settings.FunctionPrefix + d.Name;
sw.WriteLine("{0}, 0,", String.Join(", ",
System.Text.Encoding.ASCII.GetBytes(name).Select(b => b.ToString()).ToArray()));
}
}
sw.Unindent();
sw.WriteLine("};");
sw.WriteLine("EntryPoints = new IntPtr[EntryPointNames.Length];");
// Write entry point name offsets.
// This is an array of offsets into the EntryPointNames[] array above.
sw.WriteLine("EntryPointNameOffsets = new int[]", delegates.Count);
sw.WriteLine("{");
sw.Indent();
int offset = 0;
foreach (var d in delegates.Values.Select(d => d.First()))
{
if (d.RequiresSlot(Settings))
{
sw.WriteLine("{0},", offset);
var name = Settings.FunctionPrefix + d.Name;
offset += name.Length + 1;
}
}
sw.Unindent();
sw.WriteLine("};");
sw.WriteLine("EntryPoints = new IntPtr[EntryPointNameOffsets.Length];");
sw.Unindent();
sw.WriteLine("}");
sw.WriteLine();

View file

@ -32,7 +32,7 @@ namespace Bind.ES
// overloads using the "All" enum in addition to strongly-typed enums.
// This can be disabled by passing "-o:-keep_untyped_enums" as a cmdline parameter.
Settings.DefaultCompatibility |= Settings.Legacy.KeepUntypedEnums;
Settings.DefaultCompatibility |= Settings.Legacy.UseDllImports;
//Settings.DefaultCompatibility |= Settings.Legacy.UseDllImports;
}
}
}

View file

@ -32,7 +32,7 @@ namespace Bind.ES
// overloads using the "All" enum in addition to strongly-typed enums.
// This can be disabled by passing "-o:-keep_untyped_enums" as a cmdline parameter.
Settings.DefaultCompatibility |= Settings.Legacy.KeepUntypedEnums;
Settings.DefaultCompatibility |= Settings.Legacy.UseDllImports;
//Settings.DefaultCompatibility |= Settings.Legacy.UseDllImports;
}
}
}

View file

@ -35,7 +35,7 @@ namespace Bind.ES
// overloads using the "All" enum in addition to strongly-typed enums.
// This can be disabled by passing "-o:-keep_untyped_enums" as a cmdline parameter.
Settings.DefaultCompatibility |= Settings.Legacy.KeepUntypedEnums;
Settings.DefaultCompatibility |= Settings.Legacy.UseDllImports;
//Settings.DefaultCompatibility |= Settings.Legacy.UseDllImports;
}
}
}

View file

@ -154,10 +154,20 @@ namespace Bind
void GenerateAddressTable(DelegateCollection delegates)
{
// We allocate one slot per entry point. Rules:
// - All extensions get a slot
// - Core functions get a slot, unless UseDllImports is enabled
// - On Windows, core functions with version > 1.1 must be treated as extensions.
// This is controlled via the UseWindowsCompatibleGL setting.
// Entry points without a slot are assigned the magic slot index -1.
// Generator.Rewrite detects this and generates a static DllImport call
// instead of a calli instruction for these functions.
int slot = -1;
foreach (var list in delegates.Values)
{
if (!Settings.IsEnabled(Settings.Legacy.UseDllImports) || list.First().Extension != "Core")
var func = list.First();
if (func.RequiresSlot(Settings))
{
slot++;
foreach (var d in list)

View file

@ -1,4 +1,4 @@
#region License
#region License
//
// GL2Generator.cs
//
@ -55,6 +55,9 @@ namespace Bind.GL2
Settings.DefaultWrappersFile = "GL.cs";
Settings.DefaultDocPath = Path.Combine(
Settings.DefaultDocPath, "GL");
//Settings.DefaultCompatibility |=
// Settings.Legacy.UseDllImports | Settings.Legacy.UseWindowsCompatibleGL;
}
}
}

View file

@ -1,4 +1,4 @@
#region License
#region License
//
// The Open Toolkit Library License
//
@ -49,6 +49,9 @@ namespace Bind.GL2
Settings.DefaultDocPath, "GL");
Profile = "glcore";
//Settings.DefaultCompatibility |=
// Settings.Legacy.UseDllImports | Settings.Legacy.UseWindowsCompatibleGL;
}
}
}

View file

@ -156,6 +156,13 @@ namespace Bind
AddDeprecationWarnings = 0x2000,
/// <summary>Use DllImport declaration for core functions (do not generate entry point slots)</summary>
UseDllImports = 0x4000,
/// <summary>
/// Use in conjuction with UseDllImports, to create
/// bindings that are compatible with opengl32.dll on Windows.
/// This uses DllImports up to GL 1.1 and function pointers
/// for higher versions.
/// </summary>
UseWindowsCompatibleGL = 0x8000,
Tao = ConstIntEnums |
NoAdvancedEnumProcessing |
NoPublicUnsafeFunctions |

View file

@ -302,5 +302,19 @@ namespace Bind
}
#endregion
public static bool RequiresSlot(this Delegate d, Settings settings)
{
double version;
Double.TryParse(
d.Version,
System.Globalization.NumberStyles.Float,
System.Globalization.CultureInfo.InvariantCulture,
out version);
return
!settings.IsEnabled(Settings.Legacy.UseDllImports) ||
(settings.IsEnabled(Settings.Legacy.UseWindowsCompatibleGL) && version > 1.1) ||
d.Extension != "Core";
}
}
}

View file

@ -17,22 +17,49 @@ namespace Examples.Tests
{
using (Toolkit.Init(new ToolkitOptions { Backend = PlatformBackend.PreferNative }))
{
var window = Sdl2.CreateWindow("Test", 0, 0, 640, 480, WindowFlags.AllowHighDpi | WindowFlags.OpenGL);
var context = Sdl2.CreateContext(window);
Sdl2.MakeCurrent(window, context);
// Create a window and context using a third-party toolkit
// (in this case SDL2)
var window = SDL.CreateWindow("Test", 0, 0, 640, 480,
WindowFlags.AllowHighDpi | WindowFlags.OpenGL);
var context = SDL.GL.CreateContext(window);
using (var dummy = new GraphicsContext(new ContextHandle(context), OpenTK.Platform.Utilities.CreateDummyWindowInfo()))
// The external context must be made current,
// in order to correctly initialize OpenTK.Graphics
SDL.GL.MakeCurrent(window, context);
// Now we need to initialize OpenTK.Graphics using
// the external context. This can be achieved in
// two ways:
//
// var dummy = new GraphicsContext(ContextHandle.Zero, null);
// -- or --
// var dummy = new GraphicsContext(
// new ContextHandle(context),
// (name) => SDL.GL.GetAddress(name),
// () => new ContextHandle(SDL.GL.GetCurrentContext()));
//
// The first approach works only on Windows, Mac and Linux/X11.
//
// The second approach will work on all platforms supported
// by the external toolkit. This means that you can use
// OpenTK.Graphics everywhere, even on platforms not directly
// supported by OpenTK.
using (var dummy = new GraphicsContext(
new ContextHandle(context),
SDL.GL.GetAddress,
() => new ContextHandle(SDL.GL.GetCurrentContext())))
{
for (int i = 0; i < 100; i++)
{
Sdl2.PumpEvents();
SDL.PumpEvents();
GL.ClearColor(i / 100.0f, i / 100.0f, i / 100.0f, i / 100.0f);
GL.Clear(ClearBufferMask.ColorBufferBit);
Sdl2.SwapWindow(window);
SDL.GL.SwapWindow(window);
}
Sdl2.DestroyWindow(window);
SDL.DestroyWindow(window);
}
}
}
@ -47,33 +74,36 @@ namespace Examples.Tests
AllowHighDpi = 0x00002000,
}
static class Sdl2
static class SDL
{
const string lib = "SDL2.dll";
[DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_CreateWindow", ExactSpelling = true)]
public static extern IntPtr CreateWindow(string title, int x, int y, int w, int h, WindowFlags flags);
[DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GL_CreateContext", ExactSpelling = true)]
public static extern IntPtr CreateContext(IntPtr window);
[DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_DestroyWindow", ExactSpelling = true)]
public static extern void DestroyWindow(IntPtr window);
[DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GL_GetCurrentContext", ExactSpelling = true)]
public static extern IntPtr GetCurrentContext();
[DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GL_GetProcAddress", ExactSpelling = true)]
public static extern IntPtr GetAddress(string name);
[DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GL_MakeCurrent", ExactSpelling = true)]
public static extern int MakeCurrent(IntPtr window, IntPtr context);
[DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_PumpEvents", ExactSpelling = true)]
public static extern void PumpEvents();
[DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GL_SwapWindow", ExactSpelling = true)]
public static extern void SwapWindow(IntPtr window);
public static class GL
{
[DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GL_CreateContext", ExactSpelling = true)]
public static extern IntPtr CreateContext(IntPtr window);
[DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GL_GetCurrentContext", ExactSpelling = true)]
public static extern IntPtr GetCurrentContext();
[DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GL_GetProcAddress", ExactSpelling = true)]
public static extern IntPtr GetAddress(string name);
[DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GL_MakeCurrent", ExactSpelling = true)]
public static extern int MakeCurrent(IntPtr window, IntPtr context);
[DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GL_SwapWindow", ExactSpelling = true)]
public static extern void SwapWindow(IntPtr window);
}
}
#endregion

View file

@ -44,17 +44,20 @@ namespace OpenTK
/// <summary>
/// A reflection handle to the nested type that contains the function delegates.
/// </summary>
[Obsolete("Not used")]
readonly protected Type DelegatesClass;
/// <summary>
/// A refection handle to the nested type that contains core functions (i.e. not extensions).
/// </summary>
[Obsolete("Not used")]
readonly protected Type CoreClass;
/// <summary>
/// A mapping of core function names to MethodInfo handles.
/// </summary>
readonly protected SortedList<string, MethodInfo> CoreFunctionMap = new SortedList<string, MethodInfo>();
[Obsolete("Not used")]
readonly protected SortedList<string, MethodInfo> CoreFunctionMap;
bool rebuildExtensionList = true;
@ -67,18 +70,6 @@ namespace OpenTK
/// </summary>
public BindingsBase()
{
DelegatesClass = this.GetType().GetNestedType("Delegates", BindingFlags.Static | BindingFlags.NonPublic);
CoreClass = this.GetType().GetNestedType("Core", BindingFlags.Static | BindingFlags.NonPublic);
if (CoreClass != null)
{
MethodInfo[] methods = CoreClass.GetMethods(BindingFlags.Static | BindingFlags.NonPublic);
CoreFunctionMap = new SortedList<string, MethodInfo>(methods.Length); // Avoid resizing
foreach (MethodInfo m in methods)
{
CoreFunctionMap.Add(m.Name, m);
}
}
}
#endregion
@ -122,7 +113,7 @@ namespace OpenTK
/// <summary>
/// Marshals a pointer to a null-terminated byte array to the specified <c>StringBuilder</c>.
/// This method supports OpenTK and is not intended to be called by user code.
/// </summary>
/// </summary>
/// <param name="ptr">A pointer to a null-terminated byte array.</param>
/// <param name="sb">The StringBuilder to receive the contents of the pointer.</param>
protected static void MarshalPtrToStringBuilder(IntPtr ptr, StringBuilder sb)
@ -238,107 +229,7 @@ namespace OpenTK
#region Internal Members
#region LoadEntryPoints
internal virtual void LoadEntryPoints()
{
// Using reflection is more than 3 times faster than directly loading delegates on the first
// run, probably due to code generation overhead. Subsequent runs are faster with direct loading
// than with reflection, but the first time is more significant.
int supported = 0;
FieldInfo[] delegates = DelegatesClass.GetFields(BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);
if (delegates == null)
throw new InvalidOperationException("The specified type does not have any loadable extensions.");
Debug.Write("Loading extensions for " + this.GetType().FullName + "... ");
Stopwatch time = new Stopwatch();
time.Reset();
time.Start();
foreach (FieldInfo f in delegates)
{
Delegate d = LoadDelegate(f.Name, f.FieldType);
if (d != null)
++supported;
lock (SyncRoot)
{
f.SetValue(null, d);
}
}
rebuildExtensionList = true;
time.Stop();
Debug.Print("{0} extensions loaded in {1} ms.", supported, time.Elapsed.TotalMilliseconds);
time.Reset();
}
#endregion
#region LoadEntryPoint
internal virtual bool LoadEntryPoint(string function)
{
FieldInfo f = DelegatesClass.GetField(function, BindingFlags.Static | BindingFlags.NonPublic);
if (f == null)
return false;
Delegate old = f.GetValue(null) as Delegate;
Delegate @new = LoadDelegate(f.Name, f.FieldType);
lock (SyncRoot)
{
if (old.Target != @new.Target)
{
f.SetValue(null, @new);
}
}
return @new != null;
}
#endregion
#region GetExtensionDelegate
// Creates a System.Delegate that can be used to call a dynamically exported OpenGL function.
internal virtual Delegate GetExtensionDelegate(string name, Type signature)
{
IntPtr address = GetAddress(name);
if (address == IntPtr.Zero ||
address == new IntPtr(1) || // Workaround for buggy nvidia drivers which return
address == new IntPtr(2)) // 1 or 2 instead of IntPtr.Zero for some extensions.
{
return null;
}
else
{
return Marshal.GetDelegateForFunctionPointer(address, signature);
}
}
#endregion
#endregion
#region Private Members
#region LoadDelegate
// Tries to load the specified core or extension function.
Delegate LoadDelegate(string name, Type signature)
{
MethodInfo m;
return
GetExtensionDelegate(name, signature) ??
(CoreFunctionMap.TryGetValue((name.Substring(2)), out m) ?
Delegate.CreateDelegate(signature, m) : null);
}
#endregion
internal abstract void LoadEntryPoints();
#endregion
}

View file

@ -7,31 +7,8 @@ namespace OpenTK.Graphics.ES10
/// <summary>
/// Provides access to OpenGL ES 1.0 methods.
/// </summary>
public sealed partial class GL : GraphicsBindingsBase
public sealed partial class GL
{
const string Library = "libGLES.dll";
static readonly object sync_root = new object();
#region --- Protected Members ---
/// <summary>
/// Returns a synchronization token unique for the GL class.
/// </summary>
protected override object SyncRoot
{
get { return sync_root; }
}
#endregion
internal override void LoadEntryPoints()
{
// nothing to do
}
internal override bool LoadEntryPoint(string function)
{
return true; // nothing to do
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -16,7 +16,8 @@ namespace OpenTK.Graphics.ES11
static readonly object sync_root = new object();
static IntPtr[] EntryPoints;
static string[] EntryPointNames;
static byte[] EntryPointNames;
static int[] EntryPointNameOffsets;
#region Constructors
@ -25,8 +26,9 @@ namespace OpenTK.Graphics.ES11
/// </summary>
public GL()
{
EntryPointsInstance = EntryPoints;
EntryPointNamesInstance = EntryPointNames;
_EntryPointsInstance = EntryPoints;
_EntryPointNamesInstance = EntryPointNames;
_EntryPointNameOffsetsInstance = EntryPointNameOffsets;
}
#endregion

File diff suppressed because it is too large Load diff

View file

@ -44,7 +44,8 @@ namespace OpenTK.Graphics.ES20
static readonly object sync_root = new object();
static IntPtr[] EntryPoints;
static string[] EntryPointNames;
static byte[] EntryPointNames;
static int[] EntryPointNameOffsets;
#region Constructors
@ -53,8 +54,9 @@ namespace OpenTK.Graphics.ES20
/// </summary>
public GL()
{
EntryPointsInstance = EntryPoints;
EntryPointNamesInstance = EntryPointNames;
_EntryPointsInstance = EntryPoints;
_EntryPointNamesInstance = EntryPointNames;
_EntryPointNameOffsetsInstance = EntryPointNameOffsets;
}
#endregion

File diff suppressed because it is too large Load diff

View file

@ -44,7 +44,8 @@ namespace OpenTK.Graphics.ES30
static readonly object sync_root = new object();
static IntPtr[] EntryPoints;
static string[] EntryPointNames;
static byte[] EntryPointNames;
static int[] EntryPointNameOffsets;
#region Constructors
@ -53,8 +54,9 @@ namespace OpenTK.Graphics.ES30
/// </summary>
public GL()
{
EntryPointsInstance = EntryPoints;
EntryPointNamesInstance = EntryPointNames;
_EntryPointsInstance = EntryPoints;
_EntryPointNamesInstance = EntryPointNames;
_EntryPointNameOffsetsInstance = EntryPointNameOffsets;
}
#endregion

View file

@ -39,14 +39,22 @@ namespace OpenTK.Graphics
/// Contains the list of API entry points (function pointers).
/// This field must be set by an inheriting class.
/// </summary>
[Obsolete("Not used - this field remains for 1.1 API compatibility")]
protected IntPtr[] EntryPointsInstance;
/// <summary>
/// with the 1.1 API.
/// Contains the list of API entry point names.
/// This field must be set by an inheriting class.
/// </summary>
[Obsolete("Not used - this field remains for 1.1 API compatibility")]
protected string[] EntryPointNamesInstance;
internal protected IntPtr[] _EntryPointsInstance;
internal protected byte[] _EntryPointNamesInstance;
internal protected int[] _EntryPointNameOffsetsInstance;
/// <summary>
/// Retrieves an unmanaged function pointer to the specified function.
/// </summary>
@ -81,9 +89,16 @@ namespace OpenTK.Graphics
throw new GraphicsContextMissingException();
IGraphicsContextInternal context_internal = context as IGraphicsContextInternal;
for (int i = 0; i < EntryPointsInstance.Length; i++)
unsafe
{
EntryPointsInstance[i] = context_internal.GetAddress(EntryPointNamesInstance[i]);
fixed (byte* name = _EntryPointNamesInstance)
{
for (int i = 0; i < _EntryPointsInstance.Length; i++)
{
_EntryPointsInstance[i] = context_internal.GetAddress(
new IntPtr(name + _EntryPointNameOffsetsInstance[i]));
}
}
}
}
}

View file

@ -601,7 +601,10 @@ namespace OpenTK.Graphics
/// </returns>
IntPtr IGraphicsContextInternal.GetAddress(string function)
{
return (implementation as IGraphicsContextInternal).GetAddress(function);
IntPtr name = System.Runtime.InteropServices.Marshal.StringToHGlobalAnsi(function);
IntPtr address = (implementation as IGraphicsContextInternal).GetAddress(name);
System.Runtime.InteropServices.Marshal.FreeHGlobal(name);
return address;
}
/// <summary>

View file

@ -92,7 +92,13 @@ namespace OpenTK.Graphics
public ContextHandle Context { get { return Handle; } }
public abstract IntPtr GetAddress(string function);
// This function is no longer used.
// The GraphicsContext facade will
// always call the IntPtr overload.
public IntPtr GetAddress(string function)
{
throw new NotImplementedException();
}
public abstract IntPtr GetAddress(IntPtr function);

File diff suppressed because it is too large Load diff

View file

@ -75,11 +75,11 @@ namespace OpenTK.Graphics.OpenGL
internal const string Library = "opengl32.dll";
static SortedList<string, bool> AvailableExtensions = new SortedList<string, bool>();
static readonly object sync_root = new object();
static IntPtr[] EntryPoints;
static string[] EntryPointNames;
static byte[] EntryPointNames;
static int[] EntryPointNameOffsets;
#endregion
@ -90,8 +90,9 @@ namespace OpenTK.Graphics.OpenGL
/// </summary>
public GL()
{
EntryPointsInstance = EntryPoints;
EntryPointNamesInstance = EntryPointNames;
_EntryPointsInstance = EntryPoints;
_EntryPointNamesInstance = EntryPointNames;
_EntryPointNameOffsetsInstance = EntryPointNameOffsets;
}
#endregion

File diff suppressed because it is too large Load diff

View file

@ -44,7 +44,8 @@ namespace OpenTK.Graphics.OpenGL4
static readonly object sync_root = new object();
static IntPtr[] EntryPoints;
static string[] EntryPointNames;
static byte[] EntryPointNames;
static int[] EntryPointNameOffsets;
#region Constructors
@ -53,8 +54,9 @@ namespace OpenTK.Graphics.OpenGL4
/// </summary>
public GL()
{
EntryPointsInstance = EntryPoints;
EntryPointNamesInstance = EntryPointNames;
_EntryPointsInstance = EntryPoints;
_EntryPointNamesInstance = EntryPointNames;
_EntryPointNameOffsetsInstance = EntryPointNameOffsets;
}
#endregion

View file

@ -21,7 +21,7 @@ namespace OpenTK.Input
public sealed class KeyboardDevice : IInputDevice
{
//private IKeyboard keyboard;
private bool[] keys = new bool[Enum.GetValues(typeof(Key)).Length];
private bool[] keys = new bool[(int)Key.LastKey];
private bool[] scancodes = new bool[256];
private string description;
private int numKeys, numFKeys, numLeds;

View file

@ -345,9 +345,6 @@
<Compile Include="Platform\X11\Functions.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Platform\X11\GlxHelper.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Platform\X11\API.cs">
<SubType>Code</SubType>
</Compile>

View file

@ -7,6 +7,7 @@
<dllmap os="linux" dll="libX11" target="libX11.so.6"/>
<dllmap os="linux" dll="libXi" target="libXi.so.6"/>
<dllmap os="linux" dll="SDL2.dll" target="libSDL2-2.0.so.0"/>
<dllmap os="osx" dll="opengl32.dll" target="/System/Library/Frameworks/OpenGL.framework/OpenGL"/>
<dllmap os="osx" dll="openal32.dll" target="/System/Library/Frameworks/OpenAL.framework/OpenAL" />
<dllmap os="osx" dll="alut.dll" target="/System/Library/Frameworks/OpenAL.framework/OpenAL" />
<dllmap os="osx" dll="libGLES.dll" target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES" />

View file

@ -40,12 +40,11 @@ namespace OpenTK.Platform
new OpenTK.Graphics.OpenGL.GL().LoadEntryPoints();
new OpenTK.Graphics.OpenGL4.GL().LoadEntryPoints();
new OpenTK.Graphics.ES10.GL().LoadEntryPoints();
new OpenTK.Graphics.ES11.GL().LoadEntryPoints();
new OpenTK.Graphics.ES20.GL().LoadEntryPoints();
new OpenTK.Graphics.ES30.GL().LoadEntryPoints();
Debug.Print("Bindings loaded in {0} ms.", time.Elapsed.TotalMilliseconds);
Debug.WriteLine(String.Format("Bindings loaded in {0} ms.", time.Elapsed.TotalMilliseconds));
}
}
}

View file

@ -79,14 +79,10 @@ namespace OpenTK.Platform.Dummy
get { return current_thread != null && current_thread == Thread.CurrentThread; }
}
public override IntPtr GetAddress(string function)
{
return Loader(function);
}
public override IntPtr GetAddress(IntPtr function)
{
return IntPtr.Zero;
string str = System.Runtime.InteropServices.Marshal.PtrToStringAnsi(function);
return Loader(str);
}
public override int SwapInterval
@ -108,7 +104,6 @@ namespace OpenTK.Platform.Dummy
{
new OpenTK.Graphics.OpenGL.GL().LoadEntryPoints();
new OpenTK.Graphics.OpenGL4.GL().LoadEntryPoints();
new OpenTK.Graphics.ES10.GL().LoadEntryPoints();
new OpenTK.Graphics.ES11.GL().LoadEntryPoints();
new OpenTK.Graphics.ES20.GL().LoadEntryPoints();
new OpenTK.Graphics.ES30.GL().LoadEntryPoints();

View file

@ -136,11 +136,6 @@ namespace OpenTK.Platform.Egl
#region IGraphicsContextInternal Members
public override IntPtr GetAddress(string function)
{
return Egl.GetProcAddress(function);
}
public override IntPtr GetAddress(IntPtr function)
{
return Egl.GetProcAddress(function);

View file

@ -38,7 +38,6 @@ namespace OpenTK.Platform
{
Stopwatch time = Stopwatch.StartNew();
new OpenTK.Graphics.ES10.GL().LoadEntryPoints();
new OpenTK.Graphics.ES11.GL().LoadEntryPoints();
new OpenTK.Graphics.ES20.GL().LoadEntryPoints();
new OpenTK.Graphics.ES30.GL().LoadEntryPoints();

File diff suppressed because it is too large Load diff

View file

@ -47,6 +47,12 @@ namespace OpenTK
static readonly IntPtr selFlushBuffer = Selector.Get("flushBuffer");
static readonly IntPtr selMakeCurrentContext = Selector.Get("makeCurrentContext");
static readonly IntPtr selUpdate = Selector.Get("update");
static readonly IntPtr opengl = NS.AddImage(
"/System/Library/Frameworks/OpenGL.framework/OpenGL",
AddImageFlags.ReturnOnError);
static readonly IntPtr opengles = NS.AddImage(
"/System/Library/Frameworks/OpenGL.framework/OpenGLES",
AddImageFlags.ReturnOnError);
static CocoaContext()
{
@ -292,14 +298,49 @@ namespace OpenTK
#region IGraphicsContextInternal Members
public override IntPtr GetAddress(string function)
{
return NS.GetAddress(function);
}
public override IntPtr GetAddress(IntPtr function)
{
return NS.GetAddress(function);
unsafe
{
// Add a leading underscore to the function name
// As of OpenGL 4.4, all functions are < 64 bytes
// in length. Double that just to be sure.
const int max = 128;
byte* fun = stackalloc byte[max];
byte* ptr = fun;
byte* cur = (byte*)function.ToPointer();
int i = 0;
*ptr++ = (byte)'_';
while (*cur != 0 && ++i < max)
{
*ptr++ = *cur++;
}
if (i >= max - 1)
{
Debug.Print("Function {0} too long. Loading will fail.",
Marshal.PtrToStringAnsi(function));
}
IntPtr address = IntPtr.Zero;
IntPtr symbol = IntPtr.Zero;
if (opengl != IntPtr.Zero)
{
symbol = NS.LookupSymbolInImage(opengl, new IntPtr(fun),
SymbolLookupFlags.Bind | SymbolLookupFlags.ReturnOnError);
}
if (symbol == IntPtr.Zero && opengles != IntPtr.Zero)
{
symbol = NS.LookupSymbolInImage(opengles, new IntPtr(fun),
SymbolLookupFlags.Bind | SymbolLookupFlags.ReturnOnError);
}
if (symbol != IntPtr.Zero)
{
address = NS.AddressOfSymbol(symbol);
}
return address;
}
}
#endregion

View file

@ -135,7 +135,6 @@ namespace OpenTK.Platform.MacOS
private Nullable<WindowBorder> deferredWindowBorder;
private Nullable<WindowBorder> previousWindowBorder;
private WindowState windowState = WindowState.Normal;
private MacOSKeyMap keyMap = new MacOSKeyMap();
private OpenTK.Input.KeyboardKeyEventArgs keyArgs = new OpenTK.Input.KeyboardKeyEventArgs();
private KeyPressEventArgs keyPressArgs = new KeyPressEventArgs((char)0);
private string title;
@ -337,13 +336,7 @@ namespace OpenTK.Platform.MacOS
private void GetKey(ushort keyCode, NSEventModifierMask modifierFlags, OpenTK.Input.KeyboardKeyEventArgs args)
{
OpenTK.Input.Key key;
if (!keyMap.TryGetValue((OpenTK.Platform.MacOS.Carbon.MacOSKeyCode)keyCode, out key))
{
key = OpenTK.Input.Key.Unknown;
}
args.Key = key;
args.Key = MacOSKeyMap.GetKey((Carbon.MacOSKeyCode)keyCode);
args.Modifiers = GetModifiers(modifierFlags);
args.ScanCode = (uint)keyCode;
}

View file

@ -36,127 +36,229 @@ namespace OpenTK.Platform.MacOS
using Carbon;
using Input;
class MacOSKeyMap : Dictionary<MacOSKeyCode, Key>
static class MacOSKeyMap
{
public MacOSKeyMap()
public static Key GetKey(MacOSKeyCode code)
{
// comments indicate members of the Key enum that are missing
Add(MacOSKeyCode.A, Key.A);
Add(MacOSKeyCode.OptionAlt, Key.AltLeft);
// AltRight
Add(MacOSKeyCode.B, Key.B);
Add(MacOSKeyCode.Backslash, Key.BackSlash);
Add(MacOSKeyCode.Backspace, Key.BackSpace);
Add(MacOSKeyCode.BracketLeft, Key.BracketLeft);
Add(MacOSKeyCode.BracketRight, Key.BracketRight);
Add(MacOSKeyCode.C, Key.C);
// Capslock
// Clear
Add(MacOSKeyCode.Comma, Key.Comma);
Add(MacOSKeyCode.Control, Key.ControlLeft);
// ControlRight
Add(MacOSKeyCode.D, Key.D);
Add(MacOSKeyCode.Del, Key.Delete);
Add(MacOSKeyCode.Down, Key.Down);
Add(MacOSKeyCode.E, Key.E);
Add(MacOSKeyCode.End, Key.End);
Add(MacOSKeyCode.Enter, Key.Enter);
Add(MacOSKeyCode.Return, Key.Enter);
Add(MacOSKeyCode.Esc, Key.Escape);
Add(MacOSKeyCode.F, Key.F);
Add(MacOSKeyCode.F1, Key.F1);
Add(MacOSKeyCode.F2, Key.F2);
Add(MacOSKeyCode.F3, Key.F3);
Add(MacOSKeyCode.F4, Key.F4);
Add(MacOSKeyCode.F5, Key.F5);
Add(MacOSKeyCode.F6, Key.F6);
Add(MacOSKeyCode.F7, Key.F7);
Add(MacOSKeyCode.F8, Key.F8);
Add(MacOSKeyCode.F9, Key.F9);
Add(MacOSKeyCode.F10, Key.F10);
Add(MacOSKeyCode.F11, Key.F11);
Add(MacOSKeyCode.F12, Key.F12);
Add(MacOSKeyCode.F13, Key.F13);
Add(MacOSKeyCode.F14, Key.F14);
Add(MacOSKeyCode.F15, Key.F15);
// F16-F35
Add(MacOSKeyCode.G, Key.G);
Add(MacOSKeyCode.H, Key.H);
Add(MacOSKeyCode.Home, Key.Home);
Add(MacOSKeyCode.I, Key.I);
Add(MacOSKeyCode.Insert, Key.Insert);
Add(MacOSKeyCode.J, Key.J);
Add(MacOSKeyCode.K, Key.K);
Add(MacOSKeyCode.KeyPad_0, Key.Keypad0);
Add(MacOSKeyCode.KeyPad_1, Key.Keypad1);
Add(MacOSKeyCode.KeyPad_2, Key.Keypad2);
Add(MacOSKeyCode.KeyPad_3, Key.Keypad3);
Add(MacOSKeyCode.KeyPad_4, Key.Keypad4);
Add(MacOSKeyCode.KeyPad_5, Key.Keypad5);
Add(MacOSKeyCode.KeyPad_6, Key.Keypad6);
Add(MacOSKeyCode.KeyPad_7, Key.Keypad7);
Add(MacOSKeyCode.KeyPad_8, Key.Keypad8);
Add(MacOSKeyCode.KeyPad_9, Key.Keypad9);
Add(MacOSKeyCode.KeyPad_Add, Key.KeypadAdd);
Add(MacOSKeyCode.KeyPad_Decimal, Key.KeypadDecimal);
Add(MacOSKeyCode.KeyPad_Divide, Key.KeypadDivide);
Add(MacOSKeyCode.KeyPad_Enter, Key.KeypadEnter);
Add(MacOSKeyCode.KeyPad_Multiply, Key.KeypadMultiply);
Add(MacOSKeyCode.KeyPad_Subtract, Key.KeypadSubtract);
//Add(MacOSKeyCode.KeyPad_Equal);
Add(MacOSKeyCode.L, Key.L);
Add(MacOSKeyCode.Left, Key.Left);
Add(MacOSKeyCode.M, Key.M);
//Key.MaxKeys
Add(MacOSKeyCode.Menu, Key.Menu);
Add(MacOSKeyCode.Minus, Key.Minus);
Add(MacOSKeyCode.N, Key.N);
Add(MacOSKeyCode.Key_0, Key.Number0);
Add(MacOSKeyCode.Key_1, Key.Number1);
Add(MacOSKeyCode.Key_2, Key.Number2);
Add(MacOSKeyCode.Key_3, Key.Number3);
Add(MacOSKeyCode.Key_4, Key.Number4);
Add(MacOSKeyCode.Key_5, Key.Number5);
Add(MacOSKeyCode.Key_6, Key.Number6);
Add(MacOSKeyCode.Key_7, Key.Number7);
Add(MacOSKeyCode.Key_8, Key.Number8);
Add(MacOSKeyCode.Key_9, Key.Number9);
// Numlock
Add(MacOSKeyCode.O, Key.O);
Add(MacOSKeyCode.P, Key.P);
Add(MacOSKeyCode.Pagedown, Key.PageDown);
Add(MacOSKeyCode.Pageup, Key.PageUp);
// Pause
Add(MacOSKeyCode.Period, Key.Period);
Add(MacOSKeyCode.Equals, Key.Plus);
// PrintScreen
Add(MacOSKeyCode.Q, Key.Q);
Add(MacOSKeyCode.Quote, Key.Quote);
Add(MacOSKeyCode.R, Key.R);
Add(MacOSKeyCode.Right, Key.Right);
Add(MacOSKeyCode.S, Key.S);
// ScrollLock
Add(MacOSKeyCode.Semicolon, Key.Semicolon);
Add(MacOSKeyCode.Shift, Key.ShiftLeft);
//Key.ShiftRight
Add(MacOSKeyCode.Slash, Key.Slash);
// Key.Sleep
Add(MacOSKeyCode.Space, Key.Space);
Add(MacOSKeyCode.T, Key.T);
Add(MacOSKeyCode.Tab, Key.Tab);
Add(MacOSKeyCode.Tilde, Key.Tilde);
Add(MacOSKeyCode.U, Key.U);
Add(MacOSKeyCode.Up, Key.Up);
Add(MacOSKeyCode.V, Key.V);
Add(MacOSKeyCode.W, Key.W);
Add(MacOSKeyCode.Command, Key.WinLeft);
// WinKeyRight
Add(MacOSKeyCode.X, Key.X);
Add(MacOSKeyCode.Y, Key.Y);
Add(MacOSKeyCode.Z, Key.Z);
switch (code)
{
case MacOSKeyCode.A:
return Key.A;
case MacOSKeyCode.OptionAlt:
return Key.AltLeft;
// AltRight
case MacOSKeyCode.B:
return Key.B;
case MacOSKeyCode.Backslash:
return Key.BackSlash;
case MacOSKeyCode.Backspace:
return Key.BackSpace;
case MacOSKeyCode.BracketLeft:
return Key.BracketLeft;
case MacOSKeyCode.BracketRight:
return Key.BracketRight;
case MacOSKeyCode.C:
return Key.C;
// Capslock
// Clear
case MacOSKeyCode.Comma:
return Key.Comma;
case MacOSKeyCode.Control:
return Key.ControlLeft;
// ControlRight
case MacOSKeyCode.D:
return Key.D;
case MacOSKeyCode.Del:
return Key.Delete;
case MacOSKeyCode.Down:
return Key.Down;
case MacOSKeyCode.E:
return Key.E;
case MacOSKeyCode.End:
return Key.End;
case MacOSKeyCode.Enter:
return Key.Enter;
case MacOSKeyCode.Return:
return Key.Enter;
case MacOSKeyCode.Esc:
return Key.Escape;
case MacOSKeyCode.F:
return Key.F;
case MacOSKeyCode.F1:
return Key.F1;
case MacOSKeyCode.F2:
return Key.F2;
case MacOSKeyCode.F3:
return Key.F3;
case MacOSKeyCode.F4:
return Key.F4;
case MacOSKeyCode.F5:
return Key.F5;
case MacOSKeyCode.F6:
return Key.F6;
case MacOSKeyCode.F7:
return Key.F7;
case MacOSKeyCode.F8:
return Key.F8;
case MacOSKeyCode.F9:
return Key.F9;
case MacOSKeyCode.F10:
return Key.F10;
case MacOSKeyCode.F11:
return Key.F11;
case MacOSKeyCode.F12:
return Key.F12;
case MacOSKeyCode.F13:
return Key.F13;
case MacOSKeyCode.F14:
return Key.F14;
case MacOSKeyCode.F15:
return Key.F15;
// F16-F35
case MacOSKeyCode.G:
return Key.G;
case MacOSKeyCode.H:
return Key.H;
case MacOSKeyCode.Home:
return Key.Home;
case MacOSKeyCode.I:
return Key.I;
case MacOSKeyCode.Insert:
return Key.Insert;
case MacOSKeyCode.J:
return Key.J;
case MacOSKeyCode.K:
return Key.K;
case MacOSKeyCode.KeyPad_0:
return Key.Keypad0;
case MacOSKeyCode.KeyPad_1:
return Key.Keypad1;
case MacOSKeyCode.KeyPad_2:
return Key.Keypad2;
case MacOSKeyCode.KeyPad_3:
return Key.Keypad3;
case MacOSKeyCode.KeyPad_4:
return Key.Keypad4;
case MacOSKeyCode.KeyPad_5:
return Key.Keypad5;
case MacOSKeyCode.KeyPad_6:
return Key.Keypad6;
case MacOSKeyCode.KeyPad_7:
return Key.Keypad7;
case MacOSKeyCode.KeyPad_8:
return Key.Keypad8;
case MacOSKeyCode.KeyPad_9:
return Key.Keypad9;
case MacOSKeyCode.KeyPad_Add:
return Key.KeypadAdd;
case MacOSKeyCode.KeyPad_Decimal:
return Key.KeypadDecimal;
case MacOSKeyCode.KeyPad_Divide:
return Key.KeypadDivide;
case MacOSKeyCode.KeyPad_Enter:
return Key.KeypadEnter;
case MacOSKeyCode.KeyPad_Multiply:
return Key.KeypadMultiply;
case MacOSKeyCode.KeyPad_Subtract:
return Key.KeypadSubtract;
//case MacOSKeyCode.KeyPad_Equal;
case MacOSKeyCode.L:
return Key.L;
case MacOSKeyCode.Left:
return Key.Left;
case MacOSKeyCode.M:
return Key.M;
//Key.MaxKeys
case MacOSKeyCode.Menu:
return Key.Menu;
case MacOSKeyCode.Minus:
return Key.Minus;
case MacOSKeyCode.N:
return Key.N;
case MacOSKeyCode.Key_0:
return Key.Number0;
case MacOSKeyCode.Key_1:
return Key.Number1;
case MacOSKeyCode.Key_2:
return Key.Number2;
case MacOSKeyCode.Key_3:
return Key.Number3;
case MacOSKeyCode.Key_4:
return Key.Number4;
case MacOSKeyCode.Key_5:
return Key.Number5;
case MacOSKeyCode.Key_6:
return Key.Number6;
case MacOSKeyCode.Key_7:
return Key.Number7;
case MacOSKeyCode.Key_8:
return Key.Number8;
case MacOSKeyCode.Key_9:
return Key.Number9;
// Numlock
case MacOSKeyCode.O:
return Key.O;
case MacOSKeyCode.P:
return Key.P;
case MacOSKeyCode.Pagedown:
return Key.PageDown;
case MacOSKeyCode.Pageup:
return Key.PageUp;
// Pause
case MacOSKeyCode.Period:
return Key.Period;
case MacOSKeyCode.Equals:
return Key.Plus;
// PrintScreen
case MacOSKeyCode.Q:
return Key.Q;
case MacOSKeyCode.Quote:
return Key.Quote;
case MacOSKeyCode.R:
return Key.R;
case MacOSKeyCode.Right:
return Key.Right;
case MacOSKeyCode.S:
return Key.S;
// ScrollLock
case MacOSKeyCode.Semicolon:
return Key.Semicolon;
case MacOSKeyCode.Shift:
return Key.ShiftLeft;
//Key.ShiftRight
case MacOSKeyCode.Slash:
return Key.Slash;
// Key.Sleep
case MacOSKeyCode.Space:
return Key.Space;
case MacOSKeyCode.T:
return Key.T;
case MacOSKeyCode.Tab:
return Key.Tab;
case MacOSKeyCode.Tilde:
return Key.Tilde;
case MacOSKeyCode.U:
return Key.U;
case MacOSKeyCode.Up:
return Key.Up;
case MacOSKeyCode.V:
return Key.V;
case MacOSKeyCode.W:
return Key.W;
case MacOSKeyCode.Command:
return Key.WinLeft;
// WinKeyRight
case MacOSKeyCode.X:
return Key.X;
case MacOSKeyCode.Y:
return Key.Y;
case MacOSKeyCode.Z:
return Key.Z;
default:
return Key.Unknown;
}
}
}
}

View file

@ -33,27 +33,52 @@ using System.Runtime.InteropServices;
namespace OpenTK.Platform.MacOS
{
[Flags]
enum AddImageFlags
{
ReturnOnError = 1,
WithSearching = 2,
ReturnOnlyIfLoaded = 4
}
[Flags]
enum SymbolLookupFlags
{
Bind = 0,
BindNow = 1,
BindFully = 2,
ReturnOnError = 4
}
internal class NS
{
const string Library = "libdl.dylib";
[DllImport(Library, EntryPoint = "NSIsSymbolNameDefined")]
static extern bool NSIsSymbolNameDefined(string s);
[DllImport(Library, EntryPoint = "NSIsSymbolNameDefined")]
static extern bool NSIsSymbolNameDefined(IntPtr s);
[DllImport(Library, EntryPoint = "NSLookupAndBindSymbol")]
static extern IntPtr NSLookupAndBindSymbol(string s);
[DllImport(Library, EntryPoint = "NSLookupAndBindSymbol")]
static extern IntPtr NSLookupAndBindSymbol(IntPtr s);
[DllImport(Library, EntryPoint = "NSAddImage")]
internal static extern IntPtr AddImage(string s, AddImageFlags flags);
[DllImport(Library, EntryPoint = "NSAddressOfSymbol")]
static extern IntPtr NSAddressOfSymbol(IntPtr symbol);
internal static extern IntPtr AddressOfSymbol(IntPtr symbol);
[DllImport(Library, EntryPoint = "NSIsSymbolNameDefined")]
internal static extern bool IsSymbolNameDefined(string s);
[DllImport(Library, EntryPoint = "NSIsSymbolNameDefined")]
internal static extern bool IsSymbolNameDefined(IntPtr s);
[DllImport(Library, EntryPoint = "NSLookupAndBindSymbol")]
internal static extern IntPtr LookupAndBindSymbol(string s);
[DllImport(Library, EntryPoint = "NSLookupAndBindSymbol")]
internal static extern IntPtr LookupAndBindSymbol(IntPtr s);
[DllImport(Library, EntryPoint = "NSLookupSymbolInImage")]
internal static extern IntPtr LookupSymbolInImage(IntPtr image, IntPtr symbolName, SymbolLookupFlags options);
// Unfortunately, these are slower even if they are more
// portable and simpler to use.
[DllImport(Library)]
private static extern IntPtr dlopen(String fileName, int flags);
internal static extern IntPtr dlopen(String fileName, int flags);
[DllImport(Library)]
private static extern int dlclose(IntPtr handle);
internal static extern int dlclose(IntPtr handle);
[DllImport (Library)]
private static extern IntPtr dlsym (IntPtr handle, string symbol);
internal static extern IntPtr dlsym (IntPtr handle, string symbol);
[DllImport (Library)]
internal static extern IntPtr dlsym (IntPtr handle, IntPtr symbol);
public static IntPtr GetAddress(string function)
{
@ -73,7 +98,7 @@ namespace OpenTK.Platform.MacOS
}
Marshal.WriteByte(ptr, function.Length + 1, 0); // null-terminate
IntPtr symbol = GetAddress(ptr);
IntPtr symbol = GetAddressInternal(ptr);
return symbol;
}
finally
@ -84,12 +109,39 @@ namespace OpenTK.Platform.MacOS
public static IntPtr GetAddress(IntPtr function)
{
IntPtr symbol = IntPtr.Zero;
if (NSIsSymbolNameDefined(function))
unsafe
{
symbol = NSLookupAndBindSymbol(function);
const int max = 64;
byte* symbol = stackalloc byte[max];
byte* ptr = symbol;
byte* cur = (byte*)function.ToPointer();
int i = 0;
*ptr++ = (byte)'_';
while (*cur != 0 && ++i < max)
{
*ptr++ = *cur++;
}
if (i >= max - 1)
{
throw new NotSupportedException(String.Format(
"Function {0} is too long. Please report a bug at https://github.com/opentk/issues/issues",
Marshal.PtrToStringAnsi(function)));
}
return GetAddressInternal(new IntPtr(symbol));
}
}
static IntPtr GetAddressInternal(IntPtr function)
{
IntPtr symbol = IntPtr.Zero;
if (IsSymbolNameDefined(function))
{
symbol = LookupAndBindSymbol(function);
if (symbol != IntPtr.Zero)
symbol = NSAddressOfSymbol(symbol);
symbol = AddressOfSymbol(symbol);
}
return symbol;
}
@ -99,6 +151,11 @@ namespace OpenTK.Platform.MacOS
return dlsym(handle, symbol);
}
public static IntPtr GetSymbol(IntPtr handle, IntPtr symbol)
{
return dlsym(handle, symbol);
}
public static IntPtr LoadLibrary(string fileName)
{
const int RTLD_NOW = 2;

View file

@ -344,11 +344,6 @@ namespace OpenTK.Platform.SDL2
}
}
public override IntPtr GetAddress(string function)
{
return SDL.GL.GetProcAddress(function);
}
public override IntPtr GetAddress(IntPtr function)
{
return SDL.GL.GetProcAddress(function);

View file

@ -33,91 +33,270 @@ namespace OpenTK.Platform.SDL2
{
using Code = Scancode;
class Sdl2KeyMap : Dictionary<Scancode, Key>
class Sdl2KeyMap
{
public Sdl2KeyMap()
public static Key GetKey(Code code)
{
Add(Code.ESCAPE, Key.Escape);
// Function keys
for (int i = 0; i < 12; i++)
switch (code)
{
Add(Code.F1 + i, Key.F1 + i);
case Code.ESCAPE:
return Key.Escape;
// Function keys
case Code.F1:
return Key.F1;
case Code.F2:
return Key.F2;
case Code.F3:
return Key.F3;
case Code.F4:
return Key.F4;
case Code.F5:
return Key.F5;
case Code.F6:
return Key.F6;
case Code.F7:
return Key.F7;
case Code.F8:
return Key.F8;
case Code.F9:
return Key.F9;
case Code.F10:
return Key.F10;
case Code.F11:
return Key.F11;
case Code.F12:
return Key.F12;
case Code.F13:
return Key.F13;
case Code.F14:
return Key.F14;
case Code.F15:
return Key.F15;
case Code.F16:
return Key.F16;
case Code.F17:
return Key.F17;
case Code.F18:
return Key.F18;
case Code.F19:
return Key.F19;
case Code.F20:
return Key.F20;
case Code.F21:
return Key.F21;
case Code.F22:
return Key.F22;
case Code.F23:
return Key.F23;
case Code.F24:
return Key.F24;
// Number keys (0-9)
case Code.Num0:
return Key.Number0;
case Code.Num1:
return Key.Number1;
case Code.Num2:
return Key.Number2;
case Code.Num3:
return Key.Number3;
case Code.Num4:
return Key.Number4;
case Code.Num5:
return Key.Number5;
case Code.Num6:
return Key.Number6;
case Code.Num7:
return Key.Number7;
case Code.Num8:
return Key.Number8;
case Code.Num9:
return Key.Number9;
// Letters (A-Z)
case Code.A:
return Key.A;
case Code.B:
return Key.B;
case Code.C:
return Key.C;
case Code.D:
return Key.D;
case Code.E:
return Key.E;
case Code.F:
return Key.F;
case Code.G:
return Key.G;
case Code.H:
return Key.H;
case Code.I:
return Key.I;
case Code.J:
return Key.J;
case Code.K:
return Key.K;
case Code.L:
return Key.L;
case Code.M:
return Key.M;
case Code.N:
return Key.N;
case Code.O:
return Key.O;
case Code.P:
return Key.P;
case Code.Q:
return Key.Q;
case Code.R:
return Key.R;
case Code.S:
return Key.S;
case Code.T:
return Key.T;
case Code.U:
return Key.U;
case Code.V:
return Key.V;
case Code.W:
return Key.W;
case Code.X:
return Key.X;
case Code.Y:
return Key.Y;
case Code.Z:
return Key.Z;
case Code.TAB:
return Key.Tab;
case Code.CAPSLOCK:
return Key.CapsLock;
case Code.LCTRL:
return Key.ControlLeft;
case Code.LSHIFT:
return Key.ShiftLeft;
case Code.LALT:
return Key.AltLeft;
case Code.MENU:
return Key.Menu;
case Code.LGUI:
return Key.WinLeft;
case Code.RGUI:
return Key.WinRight;
case Code.SPACE:
return Key.Space;
case Code.RALT:
return Key.AltRight;
//case Code.:
// return Key.WinRight;
case Code.APPLICATION:
return Key.Menu;
case Code.RCTRL:
return Key.ControlRight;
case Code.RSHIFT:
return Key.ShiftRight;
case Code.RETURN:
return Key.Enter;
case Code.BACKSPACE:
return Key.BackSpace;
case Code.SEMICOLON:
return Key.Semicolon; // Varies by keyboard: return ;: on Win2K/US
case Code.SLASH:
return Key.Slash; // Varies by keyboard: return /? on Win2K/US
case Code.GRAVE:
return Key.Tilde; // Varies by keyboard: return `~ on Win2K/US
case Code.LEFTBRACKET:
return Key.BracketLeft; // Varies by keyboard: return [{ on Win2K/US
case Code.BACKSLASH:
return Key.BackSlash; // Varies by keyboard: return \| on Win2K/US
case Code.RIGHTBRACKET:
return Key.BracketRight; // Varies by keyboard: return ]} on Win2K/US
case Code.APOSTROPHE:
return Key.Quote; // Varies by keyboard: return '" on Win2K/US
case Code.EQUALS:
return Key.Plus;
case Code.COMMA:
return Key.Comma; // Invariant: : return
case Code.MINUS:
return Key.Minus; // Invariant: -
case Code.PERIOD:
return Key.Period; // Invariant: .
case Code.HOME:
return Key.Home;
case Code.END:
return Key.End;
case Code.DELETE:
return Key.Delete;
case Code.PAGEUP:
return Key.PageUp;
case Code.PAGEDOWN:
return Key.PageDown;
case Code.PAUSE:
return Key.Pause;
case Code.NUMLOCKCLEAR:
return Key.NumLock;
case Code.SCROLLLOCK:
return Key.ScrollLock;
case Code.PRINTSCREEN:
return Key.PrintScreen;
case Code.CLEAR:
return Key.Clear;
case Code.INSERT:
return Key.Insert;
case Code.SLEEP:
return Key.Sleep;
// Keypad
case Code.KP_0:
return Key.Keypad0;
case Code.KP_1:
return Key.Keypad1;
case Code.KP_2:
return Key.Keypad2;
case Code.KP_3:
return Key.Keypad3;
case Code.KP_4:
return Key.Keypad4;
case Code.KP_5:
return Key.Keypad5;
case Code.KP_6:
return Key.Keypad6;
case Code.KP_7:
return Key.Keypad7;
case Code.KP_8:
return Key.Keypad8;
case Code.KP_9:
return Key.Keypad9;
case Code.KP_DECIMAL:
return Key.KeypadDecimal;
case Code.KP_PLUS:
return Key.KeypadAdd;
case Code.KP_MINUS:
return Key.KeypadSubtract;
case Code.KP_DIVIDE:
return Key.KeypadDivide;
case Code.KP_MULTIPLY:
return Key.KeypadMultiply;
// Navigation
case Code.UP:
return Key.Up;
case Code.DOWN:
return Key.Down;
case Code.LEFT:
return Key.Left;
case Code.RIGHT:
return Key.Right;
default:
return Key.Unknown;
}
// Number keys (0-9)
Add(Code.Num0, Key.Number0);
for (int i = 0; i < 9; i++)
{
Add(Code.Num1 + i, Key.Number1 + i);
}
// Letters (A-Z)
for (int i = 0; i < 26; i++)
{
Add(Code.A + i, Key.A + i);
}
Add(Code.TAB, Key.Tab);
Add(Code.CAPSLOCK, Key.CapsLock);
Add(Code.LCTRL, Key.ControlLeft);
Add(Code.LSHIFT, Key.ShiftLeft);
Add(Code.LALT, Key.AltLeft);
Add(Code.MENU, Key.WinLeft);
Add(Code.SPACE, Key.Space);
Add(Code.RALT, Key.AltRight);
//Add(Code., Key.WinRight);
Add(Code.APPLICATION, Key.Menu);
Add(Code.RCTRL, Key.ControlRight);
Add(Code.RSHIFT, Key.ShiftRight);
Add(Code.RETURN, Key.Enter);
Add(Code.BACKSPACE, Key.BackSpace);
Add(Code.SEMICOLON, Key.Semicolon); // Varies by keyboard, ;: on Win2K/US
Add(Code.SLASH, Key.Slash); // Varies by keyboard, /? on Win2K/US
Add(Code.GRAVE, Key.Tilde); // Varies by keyboard, `~ on Win2K/US
Add(Code.LEFTBRACKET, Key.BracketLeft); // Varies by keyboard, [{ on Win2K/US
Add(Code.BACKSLASH, Key.BackSlash); // Varies by keyboard, \| on Win2K/US
Add(Code.RIGHTBRACKET, Key.BracketRight); // Varies by keyboard, ]} on Win2K/US
Add(Code.APOSTROPHE, Key.Quote); // Varies by keyboard, '" on Win2K/US
Add(Code.EQUALS, Key.Plus);
Add(Code.COMMA, Key.Comma); // Invariant: ,
Add(Code.MINUS, Key.Minus); // Invariant: -
Add(Code.PERIOD, Key.Period); // Invariant: .
Add(Code.HOME, Key.Home);
Add(Code.END, Key.End);
Add(Code.DELETE, Key.Delete);
Add(Code.PAGEUP, Key.PageUp);
Add(Code.PAGEDOWN, Key.PageDown);
Add(Code.PAUSE, Key.Pause);
Add(Code.NUMLOCKCLEAR, Key.NumLock);
Add(Code.SCROLLLOCK, Key.ScrollLock);
Add(Code.PRINTSCREEN, Key.PrintScreen);
Add(Code.CLEAR, Key.Clear);
Add(Code.INSERT, Key.Insert);
Add(Code.SLEEP, Key.Sleep);
// Keypad
for (int i = 0; i < 9; i++)
{
Add(Code.KP_1 + i, Key.Keypad1 + i);
}
Add(Code.KP_0, Key.Keypad0); // Note: SDL2 goes KP_1..KP_9, then KP_0
Add(Code.KP_DECIMAL, Key.KeypadDecimal);
Add(Code.KP_PLUS, Key.KeypadAdd);
Add(Code.KP_MINUS, Key.KeypadSubtract);
Add(Code.KP_DIVIDE, Key.KeypadDivide);
Add(Code.KP_MULTIPLY, Key.KeypadMultiply);
// Navigation
Add(Code.UP, Key.Up);
Add(Code.DOWN, Key.Down);
Add(Code.LEFT, Key.Left);
Add(Code.RIGHT, Key.Right);
}
}
}

View file

@ -33,7 +33,6 @@ namespace OpenTK.Platform.SDL2
{
class Sdl2Keyboard : IKeyboardDriver2, IKeyboardDriver
{
static readonly Sdl2KeyMap KeyMap = new Sdl2KeyMap();
KeyboardState state;
readonly List<KeyboardDevice> keyboards =
@ -84,10 +83,10 @@ namespace OpenTK.Platform.SDL2
internal void ProcessKeyboardEvent(KeyboardEvent e)
{
Key key;
bool pressed = e.State != 0;
var scancode = e.Keysym.Scancode;
if (KeyMap.TryGetValue(scancode, out key))
Key key = Sdl2KeyMap.GetKey(scancode);
if (key != Key.Unknown)
{
state.SetKeyState(key, (byte)scancode, pressed);
keyboards[0].SetKey(key, (byte)scancode, pressed);

View file

@ -75,8 +75,6 @@ namespace OpenTK.Platform.SDL2
static readonly Dictionary<uint, Sdl2NativeWindow> windows =
new Dictionary<uint, Sdl2NativeWindow>();
static readonly Sdl2KeyMap map = new Sdl2KeyMap();
public Sdl2NativeWindow(int x, int y, int width, int height,
string title, GameWindowFlags options, DisplayDevice device,
IInputDriver input_driver)
@ -132,12 +130,7 @@ namespace OpenTK.Platform.SDL2
static Key TranslateKey(Scancode scan)
{
Key result = Key.Unknown;
if (map.ContainsKey(scan))
{
result = map[scan];
}
return result;
return Sdl2KeyMap.GetKey(scan);
}
static Key TranslateKey(Keycode key)

View file

@ -15,7 +15,7 @@ using OpenTK.Graphics;
namespace OpenTK.Platform.Windows
{
internal partial class Wgl : GraphicsBindingsBase
internal partial class Wgl
{
static IntPtr[] EntryPoints;
static string[] EntryPointNames;
@ -29,8 +29,6 @@ namespace OpenTK.Platform.Windows
public Wgl()
{
EntryPointsInstance = EntryPoints;
EntryPointNamesInstance = EntryPointNames;
}
#region Public Members
@ -43,8 +41,8 @@ namespace OpenTK.Platform.Windows
/// <summary>
/// Checks if a Wgl extension is supported by the given context.
/// </summary>
/// <param name="context">The device context.</param>
/// <param name="ext">The extension to check.</param>
/// <param name="dc">The device context.</param>
/// <param name="name">The extension to check.</param>
/// <returns>True if the extension is supported by the given context, false otherwise</returns>
public static bool SupportsExtension(IntPtr dc, string name)
{
@ -102,12 +100,12 @@ namespace OpenTK.Platform.Windows
#region Protected Members
protected override object SyncRoot
object SyncRoot
{
get { return sync; }
}
protected override IntPtr GetAddress(string function_string)
IntPtr GetAddress(string function_string)
{
IntPtr address = Wgl.GetProcAddress(function_string);
if (!IsValid(address))
@ -133,15 +131,15 @@ namespace OpenTK.Platform.Windows
#region Internal Members
internal override void LoadEntryPoints()
internal void LoadEntryPoints()
{
lock (SyncRoot)
{
if (Wgl.GetCurrentContext() != IntPtr.Zero)
{
for (int i = 0; i < EntryPointsInstance.Length; i++)
for (int i = 0; i < EntryPointNames.Length; i++)
{
EntryPointsInstance[i] = GetAddress(EntryPointNamesInstance[i]);
EntryPoints[i] = GetAddress(EntryPointNames[i]);
}
extensions.Clear();
}

View file

@ -374,16 +374,6 @@ namespace OpenTK.Platform.Windows
#region GetAddress
public override IntPtr GetAddress(string function_string)
{
IntPtr address = Wgl.GetProcAddress(function_string);
if (!IsValid(address))
{
address = Functions.GetProcAddress(WinFactory.OpenGLHandle, function_string);
}
return address;
}
public override IntPtr GetAddress(IntPtr function_string)
{
IntPtr address = Wgl.GetProcAddress(function_string);

View file

@ -51,7 +51,6 @@ namespace OpenTK.Platform.Windows
const ExtendedWindowStyle ParentStyleEx = ExtendedWindowStyle.WindowEdge | ExtendedWindowStyle.ApplicationWindow;
const ExtendedWindowStyle ChildStyleEx = 0;
static readonly WinKeyMap KeyMap = new WinKeyMap();
readonly IntPtr Instance = Marshal.GetHINSTANCE(typeof(WinGLNative).Module);
readonly IntPtr ClassName = Marshal.StringToHGlobalAuto(Guid.NewGuid().ToString());
readonly WindowProcedure WindowProcedureDelegate;
@ -578,7 +577,7 @@ namespace OpenTK.Platform.Windows
short scancode = (short)((lParam.ToInt64() >> 16) & 0xFF);
VirtualKeys vkey = (VirtualKeys)wParam;
bool is_valid;
Key key = KeyMap.TranslateKey(scancode, vkey, extended, false, out is_valid);
Key key = WinKeyMap.TranslateKey(scancode, vkey, extended, false, out is_valid);
if (is_valid)
{

View file

@ -32,163 +32,142 @@ using OpenTK.Input;
namespace OpenTK.Platform.Windows
{
class WinKeyMap
static class WinKeyMap
{
readonly Dictionary<int, Key> ScanMap = new Dictionary<int, Key>();
public WinKeyMap()
public static Key GetKey(int code)
{
// 0 - 15
Append(Key.Unknown);
Append(Key.Escape);
switch (code)
{
// 0 - 15
case 0: return Key.Unknown;
case 1: return Key.Escape;
case 2: return Key.Number1;
case 3: return Key.Number2;
case 4: return Key.Number3;
case 5: return Key.Number4;
case 6: return Key.Number5;
case 7: return Key.Number6;
case 8: return Key.Number7;
case 9: return Key.Number8;
case 10: return Key.Number9;
case 11: return Key.Number0;
case 12: return Key.Minus;
case 13: return Key.Plus;
case 14: return Key.BackSpace;
case 15: return Key.Tab;
for (int i = 0; i < 9; i++)
Append(Key.Number1 + i);
Append(Key.Number0);
// 16-31
case 16: return Key.Q;
case 17: return Key.W;
case 18: return Key.E;
case 19: return Key.R;
case 20: return Key.T;
case 21: return Key.Y;
case 22: return Key.U;
case 23: return Key.I;
case 24: return Key.O;
case 25: return Key.P;
case 26: return Key.BracketLeft;
case 27: return Key.BracketRight;
case 28: return Key.Enter;
case 29: return Key.ControlLeft;
case 30: return Key.A;
case 31: return Key.S;
Append(Key.Minus);
Append(Key.Plus);
Append(Key.BackSpace);
Append(Key.Tab);
// 32 - 47
case 32: return Key.D;
case 33: return Key.F;
case 34: return Key.G;
case 35: return Key.H;
case 36: return Key.J;
case 37: return Key.K;
case 38: return Key.L;
case 39: return Key.Semicolon;
case 40: return Key.Quote;
case 41: return Key.Grave;
case 42: return Key.ShiftLeft;
case 43: return Key.BackSlash;
case 44: return Key.Z;
case 45: return Key.X;
case 46: return Key.C;
case 47: return Key.V;
// 16-31
Append(Key.Q);
Append(Key.W);
Append(Key.E);
Append(Key.R);
Append(Key.T);
Append(Key.Y);
Append(Key.U);
Append(Key.I);
Append(Key.O);
Append(Key.P);
Append(Key.BracketLeft);
Append(Key.BracketRight);
Append(Key.Enter);
Append(Key.ControlLeft);
Append(Key.A);
Append(Key.S);
// 48 - 63
case 48: return Key.B;
case 49: return Key.N;
case 50: return Key.M;
case 51: return Key.Comma;
case 52: return Key.Period;
case 53: return Key.Slash;
case 54: return Key.ShiftRight;
case 55: return Key.PrintScreen;
case 56: return Key.AltLeft;
case 57: return Key.Space;
case 58: return Key.CapsLock;
case 59: return Key.F1;
case 60: return Key.F2;
case 61: return Key.F3;
case 62: return Key.F4;
case 63: return Key.F5;
// 32 - 47
Append(Key.D);
Append(Key.F);
Append(Key.G);
Append(Key.H);
Append(Key.J);
Append(Key.K);
Append(Key.L);
Append(Key.Semicolon);
Append(Key.Quote);
Append(Key.Grave);
Append(Key.ShiftLeft);
Append(Key.BackSlash);
Append(Key.Z);
Append(Key.X);
Append(Key.C);
Append(Key.V);
// 64 - 79
case 64: return Key.F6;
case 65: return Key.F7;
case 66: return Key.F8;
case 67: return Key.F9;
case 68: return Key.F10;
case 69: return Key.NumLock;
case 70: return Key.ScrollLock;
case 71: return Key.Home;
case 72: return Key.Up;
case 73: return Key.PageUp;
case 74: return Key.KeypadMinus;
case 75: return Key.Left;
case 76: return Key.Keypad5;
case 77: return Key.Right;
case 78: return Key.KeypadPlus;
case 79: return Key.End;
// 48 - 63
Append(Key.B);
Append(Key.N);
Append(Key.M);
Append(Key.Comma);
Append(Key.Period);
Append(Key.Slash);
Append(Key.ShiftRight);
Append(Key.PrintScreen);
Append(Key.AltLeft);
Append(Key.Space);
Append(Key.CapsLock);
Append(Key.F1);
Append(Key.F2);
Append(Key.F3);
Append(Key.F4);
Append(Key.F5);
// 80 - 95
case 80: return Key.Down;
case 81: return Key.PageDown;
case 82: return Key.Insert;
case 83: return Key.Delete;
case 84: return Key.Unknown;
case 85: return Key.Unknown;
case 86: return Key.NonUSBackSlash;
case 87: return Key.F11;
case 88: return Key.F12;
case 89: return Key.Pause;
case 90: return Key.Unknown;
case 91: return Key.WinLeft;
case 92: return Key.WinRight;
case 93: return Key.Menu;
case 94: return Key.Unknown;
case 95: return Key.Unknown;
// 64 - 79
Append(Key.F6);
Append(Key.F7);
Append(Key.F8);
Append(Key.F9);
Append(Key.F10);
Append(Key.NumLock);
Append(Key.ScrollLock);
Append(Key.Home);
Append(Key.Up);
Append(Key.PageUp);
Append(Key.KeypadMinus);
Append(Key.Left);
Append(Key.Keypad5);
Append(Key.Right);
Append(Key.KeypadPlus);
Append(Key.End);
// 96 - 106
case 96: return Key.Unknown;
case 97: return Key.Unknown;
case 98: return Key.Unknown;
case 99: return Key.Unknown;
case 100: return Key.F13;
case 101: return Key.F14;
case 102: return Key.F15;
case 103: return Key.F16;
case 104: return Key.F17;
case 105: return Key.F18;
case 106: return Key.F19;
// 80 - 95
Append(Key.Down);
Append(Key.PageDown);
Append(Key.Insert);
Append(Key.Delete);
Append(Key.Unknown);
Append(Key.Unknown);
Append(Key.NonUSBackSlash);
Append(Key.F11);
Append(Key.F12);
Append(Key.Pause);
Append(Key.Unknown);
Append(Key.WinLeft);
Append(Key.WinRight);
Append(Key.Menu);
Append(Key.Unknown);
Append(Key.Unknown);
// 96 - 111
Append(Key.Unknown);
Append(Key.Unknown);
Append(Key.Unknown);
Append(Key.Unknown);
Append(Key.F13);
Append(Key.F14);
Append(Key.F15);
Append(Key.F16);
Append(Key.F17);
Append(Key.F18);
Append(Key.F19);
Append(Key.Unknown);
Append(Key.Unknown);
Append(Key.Unknown);
Append(Key.Unknown);
Append(Key.Unknown);
// 112 - 127
Append(Key.Unknown);
Append(Key.Unknown);
Append(Key.Unknown);
Append(Key.Unknown);
Append(Key.Unknown);
Append(Key.Unknown);
Append(Key.Unknown);
Append(Key.Unknown);
Append(Key.Unknown);
Append(Key.Unknown);
Append(Key.Unknown);
Append(Key.Unknown);
Append(Key.Unknown);
Append(Key.Unknown);
Append(Key.Unknown);
Append(Key.Unknown);
default: return Key.Unknown;
}
}
void Append(Key key)
{
ScanMap.Add(ScanMap.Count, key);
}
public Key TranslateKey(short scancode, VirtualKeys vkey, bool extended0, bool extended1, out bool is_valid)
public static Key TranslateKey(short scancode, VirtualKeys vkey, bool extended0, bool extended1, out bool is_valid)
{
is_valid = true;
Key key;
ScanMap.TryGetValue(scancode, out key);
Key key = GetKey(scancode);
if (!extended0)
{

View file

@ -38,7 +38,6 @@ namespace OpenTK.Platform.Windows
{
sealed class WinRawKeyboard : IKeyboardDriver2
{
static readonly WinKeyMap KeyMap = new WinKeyMap();
readonly List<KeyboardState> keyboards = new List<KeyboardState>();
readonly List<string> names = new List<string>();
readonly Dictionary<ContextHandle, int> rawids = new Dictionary<ContextHandle, int>();
@ -185,7 +184,7 @@ namespace OpenTK.Platform.Windows
int keyboard_handle = rawids.ContainsKey(handle) ? rawids[handle] : 0;
keyboard = keyboards[keyboard_handle];
Key key = KeyMap.TranslateKey(scancode, vkey, extended0, extended1, out is_valid);
Key key = WinKeyMap.TranslateKey(scancode, vkey, extended0, extended1, out is_valid);
if (is_valid)
{

View file

@ -259,8 +259,38 @@ namespace OpenTK.Platform.X11
/// <summary>
/// Provides access to GLX functions.
/// </summary>
partial class Glx
class Glx
{
const string Library = "libGL.so.1";
static string[] EntryPointNames = new string[]
{
"glXCreateContextAttribs",
"glXSwapIntervalSGI",
};
static IntPtr[] EntryPoints = new IntPtr[EntryPointNames.Length];
static Glx()
{
// GLX entry points are not bound to a context.
// This means we can load them without creating
// a context first! (unlike WGL)
for (int i = 0; i < EntryPointNames.Length; i++)
{
EntryPoints[i] = Arb.GetProcAddress(EntryPointNames[i]);
}
}
internal static bool SupportsFunction(string name)
{
int index = Array.IndexOf(EntryPointNames, name);
if (index >= 0)
{
return EntryPoints[index] != IntPtr.Zero;
}
return false;
}
#region GLX functions
[DllImport(Library, EntryPoint = "glXIsDirect")]
@ -343,40 +373,26 @@ namespace OpenTK.Platform.X11
#endregion
#region Extensions
public partial class Sgi
{
public static ErrorCode SwapInterval(int interval)
{
return (ErrorCode)Delegates.glXSwapIntervalSGI(interval);
}
}
public partial class Arb
{
#region CreateContextAttri
#region CreateContextAttribs
[AutoGenerated(EntryPoint = "glXCreateContextAttribsARB")]
unsafe public static IntPtr CreateContextAttribs(IntPtr display, IntPtr fbconfig, IntPtr share_context, bool direct, int* attribs)
{
return Delegates.glXCreateContextAttribsARB(display, fbconfig, share_context, direct, attribs);
throw new NotImplementedException();
}
[AutoGenerated(EntryPoint = "glXCreateContextAttribsARB")]
public static IntPtr CreateContextAttribs(IntPtr display, IntPtr fbconfig, IntPtr share_context, bool direct, int[] attribs)
{
unsafe
{
fixed (int* attribs_ptr = attribs)
{
return Delegates.glXCreateContextAttribsARB(display, fbconfig, share_context, direct, attribs_ptr);
}
}
throw new NotImplementedException();
}
#endregion
#region GetProcAddress
// The linux OpenGL ABI 3.6 (1999) requires
// that glXGetProcAddressARB be available as
// a static export. The same is *not* true
@ -385,22 +401,25 @@ namespace OpenTK.Platform.X11
// See http://www.opengl.org/registry/ABI/
[DllImport(Library, EntryPoint = "glXGetProcAddressARB")]
public static extern IntPtr GetProcAddress([MarshalAs(UnmanagedType.LPTStr)] string procName);
#endregion
}
internal static partial class Delegates
public partial class Sgi
{
[SuppressUnmanagedCodeSecurity]
public delegate int SwapIntervalSGI(int interval);
public static SwapIntervalSGI glXSwapIntervalSGI = null;
[SuppressUnmanagedCodeSecurity]
unsafe public delegate IntPtr CreateContextAttribsARB(IntPtr display, IntPtr fbconfig, IntPtr share_context, bool direct, int* attribs);
unsafe public static CreateContextAttribsARB glXCreateContextAttribsARB = null;
[AutoGenerated(EntryPoint = "glXSwapIntervalSGI")]
public static ErrorCode SwapInterval(int interval)
{
throw new NotImplementedException();
}
}
#endregion
[Slot(0)]
[DllImport(Library, ExactSpelling = true, CallingConvention = CallingConvention.Winapi)]
internal unsafe static extern IntPtr glXCreateContextAttribsARB(IntPtr display, IntPtr fbconfig, IntPtr share_context, bool direct, int* attribs);
[Slot(1)]
[DllImport(Library, ExactSpelling = true, CallingConvention = CallingConvention.Winapi)]
internal static extern IntPtr glXSwapIntervalSGI(int interval);
#endregion
}

View file

@ -1,111 +0,0 @@
#region --- License ---
/* Copyright (c) 2006, 2007 Stefanos Apostolopoulos
* See license.txt for license info
*/
#endregion
using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Diagnostics;
using OpenTK.Graphics;
namespace OpenTK.Platform.X11
{
partial class Glx : BindingsBase
{
const string Library = "libGL.so.1";
static readonly object sync_root = new object();
static Glx()
{
// GLX entry points are not bound to a context.
// This means we can load them without creating
// a context first! (unlike WGL)
// See
// for more details.
Debug.WriteLine("Loading GLX entry points.");
new Glx().LoadEntryPoints();
}
protected override object SyncRoot
{
get { return sync_root; }
}
protected override IntPtr GetAddress(string funcname)
{
// We must use glXGetProcAddressARB, *not*
// glXGetProcAddress. See comment on function
// signature.
return Glx.Arb.GetProcAddress(funcname);
}
#if false
#region static Delegate LoadDelegate(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 Wgl function (eg. "wglNewList")</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>
static Delegate LoadDelegate(string name, Type signature)
{
Delegate d;
string realName = name.ToLower().StartsWith("glx") ? name.Substring(3) : name;
if (typeof(Glx).GetMethod(realName,
BindingFlags.NonPublic | BindingFlags.Static) != null)
d = GetExtensionDelegate(name, signature) ??
Delegate.CreateDelegate(signature, typeof(Glx), realName);
else
d = GetExtensionDelegate(name, signature);
return d;
}
#endregion
#region private static Delegate GetExtensionDelegate(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>
private static Delegate GetExtensionDelegate(string name, Type signature)
{
IntPtr address = Glx.GetProcAddress(name);
if (address == IntPtr.Zero ||
address == new IntPtr(1) || // Workaround for buggy nvidia drivers which return
address == new IntPtr(2)) // 1 or 2 instead of IntPtr.Zero for some extensions.
return null;
else
return Marshal.GetDelegateForFunctionPointer(address, signature);
}
#endregion
#region internal static void LoadAll
public static void LoadAll()
{
OpenTK.Platform.Utilities.LoadExtensions(typeof(Glx));
}
#endregion
#endif
}
}

View file

@ -253,7 +253,7 @@ namespace OpenTK.Platform.X11
return
SupportsExtension(display, window, "GLX_ARB_create_context") &&
SupportsExtension(display, window, "GLX_ARB_create_context_profile") &&
Glx.Delegates.glXCreateContextAttribsARB != null;
Glx.SupportsFunction("glXCreateContextAttribsARB");
}
#endregion
@ -380,8 +380,7 @@ namespace OpenTK.Platform.X11
public override void LoadAll()
{
new Glx().LoadEntryPoints();
vsync_supported = this.GetAddress("glXSwapIntervalSGI") != IntPtr.Zero;
vsync_supported = Glx.SupportsFunction("glXSwapIntervalSGI");
Debug.Print("Context supports vsync: {0}.", vsync_supported);
base.LoadAll();
@ -395,14 +394,6 @@ namespace OpenTK.Platform.X11
#region GetAddress
public override IntPtr GetAddress(string function)
{
using (new XLock(Display))
{
return Glx.GetProcAddress(function);
}
}
public override IntPtr GetAddress(IntPtr function)
{
using (new XLock(Display))

View file

@ -29,7 +29,6 @@ namespace OpenTK.Platform.X11
List<KeyboardDevice> dummy_keyboard_list = new List<KeyboardDevice>(1);
List<MouseDevice> dummy_mice_list = new List<MouseDevice>(1);
X11KeyMap keymap = new X11KeyMap();
int firstKeyCode, lastKeyCode; // The smallest and largest KeyCode supported by the X server.
int keysyms_per_keycode; // The number of KeySyms for each KeyCode.
IntPtr[] keysyms;
@ -100,17 +99,12 @@ namespace OpenTK.Platform.X11
{
XKey keysym = (XKey)API.LookupKeysym(ref e, 0);
XKey keysym2 = (XKey)API.LookupKeysym(ref e, 1);
key = Key.Unknown;
if (keymap.ContainsKey(keysym))
key = X11KeyMap.GetKey(keysym);
if (key == Key.Unknown)
{
key = keymap[keysym];
key = X11KeyMap.GetKey(keysym2);
}
else if (keymap.ContainsKey(keysym2))
{
key = keymap[keysym2];
}
else
if (key == Key.Unknown)
{
Debug.Print("KeyCode {0} (Keysym: {1}, {2}) not mapped.", e.keycode, (XKey)keysym, (XKey)keysym2);
}

View file

@ -10,129 +10,364 @@ using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using OpenTK.Input;
namespace OpenTK.Platform.X11
{
internal class X11KeyMap : Dictionary<XKey, Key>
static class X11KeyMap
{
internal X11KeyMap()
public static Key GetKey(XKey key)
{
try
switch (key)
{
this.Add(XKey.Escape, Key.Escape);
this.Add(XKey.Return, Key.Enter);
this.Add(XKey.space, Key.Space);
this.Add(XKey.BackSpace, Key.BackSpace);
case XKey.Escape:
return Key.Escape;
case XKey.Return:
return Key.Enter;
case XKey.space:
return Key.Space;
case XKey.BackSpace:
return Key.BackSpace;
this.Add(XKey.Shift_L, Key.ShiftLeft);
this.Add(XKey.Shift_R, Key.ShiftRight);
this.Add(XKey.Alt_L, Key.AltLeft);
this.Add(XKey.Alt_R, Key.AltRight);
this.Add(XKey.Control_L, Key.ControlLeft);
this.Add(XKey.Control_R, Key.ControlRight);
this.Add(XKey.Super_L, Key.WinLeft);
this.Add(XKey.Super_R, Key.WinRight);
this.Add(XKey.Meta_L, Key.WinLeft);
this.Add(XKey.Meta_R, Key.WinRight);
this.Add(XKey.ISO_Level3_Shift, Key.AltRight); // Normally AltGr
case XKey.Shift_L:
return Key.ShiftLeft;
case XKey.Shift_R:
return Key.ShiftRight;
case XKey.Alt_L:
return Key.AltLeft;
case XKey.Alt_R:
return Key.AltRight;
case XKey.Control_L:
return Key.ControlLeft;
case XKey.Control_R:
return Key.ControlRight;
case XKey.Super_L:
return Key.WinLeft;
case XKey.Super_R:
return Key.WinRight;
case XKey.Meta_L:
return Key.WinLeft;
case XKey.Meta_R:
return Key.WinRight;
case XKey.ISO_Level3_Shift:
return Key.AltRight; // Normally AltGr
this.Add(XKey.Menu, Key.Menu);
this.Add(XKey.Tab, Key.Tab);
this.Add(XKey.minus, Key.Minus);
this.Add(XKey.plus, Key.Plus);
this.Add(XKey.equal, Key.Plus);
case XKey.Menu:
return Key.Menu;
case XKey.Tab:
return Key.Tab;
case XKey.minus:
return Key.Minus;
case XKey.plus:
return Key.Plus;
case XKey.equal:
return Key.Plus;
this.Add(XKey.Caps_Lock, Key.CapsLock);
this.Add(XKey.Num_Lock, Key.NumLock);
case XKey.Caps_Lock:
return Key.CapsLock;
case XKey.Num_Lock:
return Key.NumLock;
for (int i = (int)XKey.F1; i <= (int)XKey.F35; i++)
{
this.Add((XKey)i, (Key)((int)Key.F1 + (i - (int)XKey.F1)));
}
case XKey.F1:
return Key.F1;
case XKey.F2:
return Key.F2;
case XKey.F3:
return Key.F3;
case XKey.F4:
return Key.F4;
case XKey.F5:
return Key.F5;
case XKey.F6:
return Key.F6;
case XKey.F7:
return Key.F7;
case XKey.F8:
return Key.F8;
case XKey.F9:
return Key.F9;
case XKey.F10:
return Key.F10;
case XKey.F11:
return Key.F11;
case XKey.F12:
return Key.F12;
case XKey.F13:
return Key.F13;
case XKey.F14:
return Key.F14;
case XKey.F15:
return Key.F15;
case XKey.F16:
return Key.F16;
case XKey.F17:
return Key.F17;
case XKey.F18:
return Key.F18;
case XKey.F19:
return Key.F19;
case XKey.F20:
return Key.F20;
case XKey.F21:
return Key.F21;
case XKey.F22:
return Key.F22;
case XKey.F23:
return Key.F23;
case XKey.F24:
return Key.F24;
case XKey.F25:
return Key.F25;
case XKey.F26:
return Key.F26;
case XKey.F27:
return Key.F27;
case XKey.F28:
return Key.F28;
case XKey.F29:
return Key.F29;
case XKey.F30:
return Key.F30;
case XKey.F31:
return Key.F31;
case XKey.F32:
return Key.F32;
case XKey.F33:
return Key.F33;
case XKey.F34:
return Key.F34;
case XKey.F35:
return Key.F35;
for (int i = (int)XKey.a; i <= (int)XKey.z; i++)
{
this.Add((XKey)i, (Key)((int)Key.A + (i - (int)XKey.a)));
}
case XKey.a:
case XKey.A:
return Key.A;
case XKey.b:
case XKey.B:
return Key.B;
case XKey.c:
case XKey.C:
return Key.C;
case XKey.d:
case XKey.D:
return Key.D;
case XKey.e:
case XKey.E:
return Key.E;
case XKey.f:
case XKey.F:
return Key.F;
case XKey.g:
case XKey.G:
return Key.G;
case XKey.h:
case XKey.H:
return Key.H;
case XKey.i:
case XKey.I:
return Key.I;
case XKey.j:
case XKey.J:
return Key.J;
case XKey.k:
case XKey.K:
return Key.K;
case XKey.l:
case XKey.L:
return Key.L;
case XKey.m:
case XKey.M:
return Key.M;
case XKey.n:
case XKey.N:
return Key.N;
case XKey.o:
case XKey.O:
return Key.O;
case XKey.p:
case XKey.P:
return Key.P;
case XKey.q:
case XKey.Q:
return Key.Q;
case XKey.r:
case XKey.R:
return Key.R;
case XKey.s:
case XKey.S:
return Key.S;
case XKey.t:
case XKey.T:
return Key.T;
case XKey.u:
case XKey.U:
return Key.U;
case XKey.v:
case XKey.V:
return Key.V;
case XKey.w:
case XKey.W:
return Key.W;
case XKey.x:
case XKey.X:
return Key.X;
case XKey.y:
case XKey.Y:
return Key.Y;
case XKey.z:
case XKey.Z:
return Key.Z;
for (int i = (int)XKey.A; i <= (int)XKey.Z; i++)
{
this.Add((XKey)i, (Key)((int)Key.A + (i - (int)XKey.A)));
}
case XKey.Number0:
return Key.Number0;
case XKey.Number1:
return Key.Number1;
case XKey.Number2:
return Key.Number2;
case XKey.Number3:
return Key.Number3;
case XKey.Number4:
return Key.Number4;
case XKey.Number5:
return Key.Number5;
case XKey.Number6:
return Key.Number6;
case XKey.Number7:
return Key.Number7;
case XKey.Number8:
return Key.Number8;
case XKey.Number9:
return Key.Number9;
for (int i = (int)XKey.Number0; i <= (int)XKey.Number9; i++)
{
this.Add((XKey)i, (Key)((int)Key.Number0 + (i - (int)XKey.Number0)));
}
case XKey.KP_0:
return Key.Keypad0;
case XKey.KP_1:
return Key.Keypad1;
case XKey.KP_2:
return Key.Keypad2;
case XKey.KP_3:
return Key.Keypad3;
case XKey.KP_4:
return Key.Keypad4;
case XKey.KP_5:
return Key.Keypad5;
case XKey.KP_6:
return Key.Keypad6;
case XKey.KP_7:
return Key.Keypad7;
case XKey.KP_8:
return Key.Keypad8;
case XKey.KP_9:
return Key.Keypad9;
for (int i = (int)XKey.KP_0; i <= (int)XKey.KP_9; i++)
{
this.Add((XKey)i, (Key)((int)Key.Keypad0 + (i - (int)XKey.KP_0)));
}
case XKey.Pause:
return Key.Pause;
case XKey.Break:
return Key.Pause;
case XKey.Scroll_Lock:
return Key.Pause;
case XKey.Insert:
return Key.PrintScreen;
case XKey.Print:
return Key.PrintScreen;
case XKey.Sys_Req:
return Key.PrintScreen;
this.Add(XKey.Pause, Key.Pause);
this.Add(XKey.Break, Key.Pause);
this.Add(XKey.Scroll_Lock, Key.Pause);
this.Add(XKey.Insert, Key.PrintScreen);
this.Add(XKey.Print, Key.PrintScreen);
this.Add(XKey.Sys_Req, Key.PrintScreen);
case XKey.backslash:
return Key.BackSlash;
case XKey.bar:
return Key.BackSlash;
case XKey.braceleft:
return Key.BracketLeft;
case XKey.bracketleft:
return Key.BracketLeft;
case XKey.braceright:
return Key.BracketRight;
case XKey.bracketright:
return Key.BracketRight;
case XKey.colon:
return Key.Semicolon;
case XKey.semicolon:
return Key.Semicolon;
case XKey.quoteright:
return Key.Quote;
case XKey.quotedbl:
return Key.Quote;
case XKey.quoteleft:
return Key.Tilde;
case XKey.asciitilde:
return Key.Tilde;
this.Add(XKey.backslash, Key.BackSlash);
this.Add(XKey.bar, Key.BackSlash);
this.Add(XKey.braceleft, Key.BracketLeft);
this.Add(XKey.bracketleft, Key.BracketLeft);
this.Add(XKey.braceright, Key.BracketRight);
this.Add(XKey.bracketright, Key.BracketRight);
this.Add(XKey.colon, Key.Semicolon);
this.Add(XKey.semicolon, Key.Semicolon);
this.Add(XKey.quoteright, Key.Quote);
this.Add(XKey.quotedbl, Key.Quote);
this.Add(XKey.quoteleft, Key.Tilde);
this.Add(XKey.asciitilde, Key.Tilde);
case XKey.comma:
return Key.Comma;
case XKey.less:
return Key.Comma;
case XKey.period:
return Key.Period;
case XKey.greater:
return Key.Period;
case XKey.slash:
return Key.Slash;
case XKey.question:
return Key.Slash;
this.Add(XKey.comma, Key.Comma);
this.Add(XKey.less, Key.Comma);
this.Add(XKey.period, Key.Period);
this.Add(XKey.greater, Key.Period);
this.Add(XKey.slash, Key.Slash);
this.Add(XKey.question, Key.Slash);
case XKey.Left:
return Key.Left;
case XKey.Down:
return Key.Down;
case XKey.Right:
return Key.Right;
case XKey.Up:
return Key.Up;
this.Add(XKey.Left, Key.Left);
this.Add(XKey.Down, Key.Down);
this.Add(XKey.Right, Key.Right);
this.Add(XKey.Up, Key.Up);
case XKey.Delete:
return Key.Delete;
case XKey.Home:
return Key.Home;
case XKey.End:
return Key.End;
//case XKey.Prior: return Key.PageUp; // XKey.Prior == XKey.Page_Up
case XKey.Page_Up:
return Key.PageUp;
case XKey.Page_Down:
return Key.PageDown;
//case XKey.Next: return Key.PageDown; // XKey.Next == XKey.Page_Down
this.Add(XKey.Delete, Key.Delete);
this.Add(XKey.Home, Key.Home);
this.Add(XKey.End, Key.End);
//this.Add(XKey.Prior, Key.PageUp); // XKey.Prior == XKey.Page_Up
this.Add(XKey.Page_Up, Key.PageUp);
this.Add(XKey.Page_Down, Key.PageDown);
//this.Add(XKey.Next, Key.PageDown); // XKey.Next == XKey.Page_Down
case XKey.KP_Add:
return Key.KeypadAdd;
case XKey.KP_Subtract:
return Key.KeypadSubtract;
case XKey.KP_Multiply:
return Key.KeypadMultiply;
case XKey.KP_Divide:
return Key.KeypadDivide;
case XKey.KP_Decimal:
return Key.KeypadDecimal;
case XKey.KP_Insert:
return Key.Keypad0;
case XKey.KP_End:
return Key.Keypad1;
case XKey.KP_Down:
return Key.Keypad2;
case XKey.KP_Page_Down:
return Key.Keypad3;
case XKey.KP_Left:
return Key.Keypad4;
case XKey.KP_Right:
return Key.Keypad6;
case XKey.KP_Home:
return Key.Keypad7;
case XKey.KP_Up:
return Key.Keypad8;
case XKey.KP_Page_Up:
return Key.Keypad9;
case XKey.KP_Delete:
return Key.KeypadDecimal;
case XKey.KP_Enter:
return Key.KeypadEnter;
this.Add(XKey.KP_Add, Key.KeypadAdd);
this.Add(XKey.KP_Subtract, Key.KeypadSubtract);
this.Add(XKey.KP_Multiply, Key.KeypadMultiply);
this.Add(XKey.KP_Divide, Key.KeypadDivide);
this.Add(XKey.KP_Decimal, Key.KeypadDecimal);
this.Add(XKey.KP_Insert, Key.Keypad0);
this.Add(XKey.KP_End, Key.Keypad1);
this.Add(XKey.KP_Down, Key.Keypad2);
this.Add(XKey.KP_Page_Down, Key.Keypad3);
this.Add(XKey.KP_Left, Key.Keypad4);
this.Add(XKey.KP_Right, Key.Keypad6);
this.Add(XKey.KP_Home, Key.Keypad7);
this.Add(XKey.KP_Up, Key.Keypad8);
this.Add(XKey.KP_Page_Up, Key.Keypad9);
this.Add(XKey.KP_Delete, Key.KeypadDecimal);
this.Add(XKey.KP_Enter, Key.KeypadEnter);
}
catch (ArgumentException e)
{
Debug.Print("Exception while creating keymap: '{0}'.", e.ToString());
default:
return Key.Unknown;
}
}
}

View file

@ -1,29 +1,29 @@
#region License
//
// The Open Toolkit Library License
//
// Copyright (c) 2006 - 2010 the Open Toolkit library.
//
// 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
#region License
//
// The Open Toolkit Library License
//
// Copyright (c) 2006 - 2010 the Open Toolkit library.
//
// 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;
@ -36,7 +36,6 @@ namespace OpenTK.Platform.X11
// Only one keyboard supported.
sealed class X11Keyboard : IKeyboardDriver2
{
readonly static X11KeyMap keymap = new X11KeyMap();
readonly static string name = "Core X11 keyboard";
readonly byte[] keys = new byte[32];
readonly int KeysymsPerKeycode;
@ -53,8 +52,11 @@ namespace OpenTK.Platform.X11
// Find the number of keysyms per keycode.
int first = 0, last = 0;
API.DisplayKeycodes(display, ref first, ref last);
IntPtr keysym_ptr = API.GetKeyboardMapping(display, (byte)first, last - first + 1,
ref KeysymsPerKeycode);
IntPtr keysym_ptr =
API.GetKeyboardMapping(display,
(byte)first,
last - first + 1,
ref KeysymsPerKeycode);
Functions.XFree(keysym_ptr);
try
@ -66,7 +68,9 @@ namespace OpenTK.Platform.X11
bool supported;
Functions.XkbSetDetectableAutoRepeat(display, true, out supported);
}
catch { }
catch
{
}
}
}
@ -108,8 +112,9 @@ namespace OpenTK.Platform.X11
for (int mod = 0; mod < KeysymsPerKeycode; mod++)
{
IntPtr keysym = Functions.XKeycodeToKeysym(display, (byte)keycode, mod);
if (keysym != IntPtr.Zero && keymap.TryGetValue((XKey)keysym, out key))
if (keysym != IntPtr.Zero)
{
key = X11KeyMap.GetKey((XKey)keysym);
if (pressed)
state.EnableBit((int)key);
else