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("static {0}()", Settings.OutputClass);
sw.WriteLine("{"); sw.WriteLine("{");
sw.Indent(); 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.WriteLine("{");
sw.Indent(); sw.Indent();
foreach (var d in delegates.Values.Select(d => d.First())) 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.Unindent();
sw.WriteLine("};"); 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.Unindent();
sw.WriteLine("}"); sw.WriteLine("}");
sw.WriteLine(); sw.WriteLine();

View file

@ -32,7 +32,7 @@ namespace Bind.ES
// overloads using the "All" enum in addition to strongly-typed enums. // 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. // This can be disabled by passing "-o:-keep_untyped_enums" as a cmdline parameter.
Settings.DefaultCompatibility |= Settings.Legacy.KeepUntypedEnums; 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. // 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. // This can be disabled by passing "-o:-keep_untyped_enums" as a cmdline parameter.
Settings.DefaultCompatibility |= Settings.Legacy.KeepUntypedEnums; 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. // 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. // This can be disabled by passing "-o:-keep_untyped_enums" as a cmdline parameter.
Settings.DefaultCompatibility |= Settings.Legacy.KeepUntypedEnums; 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) 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; int slot = -1;
foreach (var list in delegates.Values) 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++; slot++;
foreach (var d in list) foreach (var d in list)

View file

@ -1,4 +1,4 @@
#region License #region License
// //
// GL2Generator.cs // GL2Generator.cs
// //
@ -55,6 +55,9 @@ namespace Bind.GL2
Settings.DefaultWrappersFile = "GL.cs"; Settings.DefaultWrappersFile = "GL.cs";
Settings.DefaultDocPath = Path.Combine( Settings.DefaultDocPath = Path.Combine(
Settings.DefaultDocPath, "GL"); 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 // The Open Toolkit Library License
// //
@ -49,6 +49,9 @@ namespace Bind.GL2
Settings.DefaultDocPath, "GL"); Settings.DefaultDocPath, "GL");
Profile = "glcore"; Profile = "glcore";
//Settings.DefaultCompatibility |=
// Settings.Legacy.UseDllImports | Settings.Legacy.UseWindowsCompatibleGL;
} }
} }
} }

View file

@ -156,6 +156,13 @@ namespace Bind
AddDeprecationWarnings = 0x2000, AddDeprecationWarnings = 0x2000,
/// <summary>Use DllImport declaration for core functions (do not generate entry point slots)</summary> /// <summary>Use DllImport declaration for core functions (do not generate entry point slots)</summary>
UseDllImports = 0x4000, 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 | Tao = ConstIntEnums |
NoAdvancedEnumProcessing | NoAdvancedEnumProcessing |
NoPublicUnsafeFunctions | NoPublicUnsafeFunctions |

View file

@ -302,5 +302,19 @@ namespace Bind
} }
#endregion #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 })) using (Toolkit.Init(new ToolkitOptions { Backend = PlatformBackend.PreferNative }))
{ {
var window = Sdl2.CreateWindow("Test", 0, 0, 640, 480, WindowFlags.AllowHighDpi | WindowFlags.OpenGL); // Create a window and context using a third-party toolkit
var context = Sdl2.CreateContext(window); // (in this case SDL2)
Sdl2.MakeCurrent(window, context); 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++) 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.ClearColor(i / 100.0f, i / 100.0f, i / 100.0f, i / 100.0f);
GL.Clear(ClearBufferMask.ColorBufferBit); GL.Clear(ClearBufferMask.ColorBufferBit);
Sdl2.SwapWindow(window); SDL.GL.SwapWindow(window);
} }
Sdl2.DestroyWindow(window); SDL.DestroyWindow(window);
} }
} }
} }
@ -47,19 +74,24 @@ namespace Examples.Tests
AllowHighDpi = 0x00002000, AllowHighDpi = 0x00002000,
} }
static class Sdl2 static class SDL
{ {
const string lib = "SDL2.dll"; const string lib = "SDL2.dll";
[DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_CreateWindow", ExactSpelling = true)] [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); 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)] [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_DestroyWindow", ExactSpelling = true)]
public static extern void DestroyWindow(IntPtr window); public static extern void DestroyWindow(IntPtr window);
[DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_PumpEvents", ExactSpelling = true)]
public static extern void PumpEvents();
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)] [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GL_GetCurrentContext", ExactSpelling = true)]
public static extern IntPtr GetCurrentContext(); public static extern IntPtr GetCurrentContext();
@ -69,12 +101,10 @@ namespace Examples.Tests
[DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GL_MakeCurrent", ExactSpelling = true)] [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GL_MakeCurrent", ExactSpelling = true)]
public static extern int MakeCurrent(IntPtr window, IntPtr context); 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)] [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GL_SwapWindow", ExactSpelling = true)]
public static extern void SwapWindow(IntPtr window); public static extern void SwapWindow(IntPtr window);
} }
}
#endregion #endregion

View file

@ -44,17 +44,20 @@ namespace OpenTK
/// <summary> /// <summary>
/// A reflection handle to the nested type that contains the function delegates. /// A reflection handle to the nested type that contains the function delegates.
/// </summary> /// </summary>
[Obsolete("Not used")]
readonly protected Type DelegatesClass; readonly protected Type DelegatesClass;
/// <summary> /// <summary>
/// A refection handle to the nested type that contains core functions (i.e. not extensions). /// A refection handle to the nested type that contains core functions (i.e. not extensions).
/// </summary> /// </summary>
[Obsolete("Not used")]
readonly protected Type CoreClass; readonly protected Type CoreClass;
/// <summary> /// <summary>
/// A mapping of core function names to MethodInfo handles. /// A mapping of core function names to MethodInfo handles.
/// </summary> /// </summary>
readonly protected SortedList<string, MethodInfo> CoreFunctionMap = new SortedList<string, MethodInfo>(); [Obsolete("Not used")]
readonly protected SortedList<string, MethodInfo> CoreFunctionMap;
bool rebuildExtensionList = true; bool rebuildExtensionList = true;
@ -67,18 +70,6 @@ namespace OpenTK
/// </summary> /// </summary>
public BindingsBase() 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 #endregion
@ -238,107 +229,7 @@ namespace OpenTK
#region Internal Members #region Internal Members
#region LoadEntryPoints internal abstract void 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
#endregion #endregion
} }

View file

@ -7,31 +7,8 @@ namespace OpenTK.Graphics.ES10
/// <summary> /// <summary>
/// Provides access to OpenGL ES 1.0 methods. /// Provides access to OpenGL ES 1.0 methods.
/// </summary> /// </summary>
public sealed partial class GL : GraphicsBindingsBase public sealed partial class GL
{ {
const string Library = "libGLES.dll"; 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 readonly object sync_root = new object();
static IntPtr[] EntryPoints; static IntPtr[] EntryPoints;
static string[] EntryPointNames; static byte[] EntryPointNames;
static int[] EntryPointNameOffsets;
#region Constructors #region Constructors
@ -25,8 +26,9 @@ namespace OpenTK.Graphics.ES11
/// </summary> /// </summary>
public GL() public GL()
{ {
EntryPointsInstance = EntryPoints; _EntryPointsInstance = EntryPoints;
EntryPointNamesInstance = EntryPointNames; _EntryPointNamesInstance = EntryPointNames;
_EntryPointNameOffsetsInstance = EntryPointNameOffsets;
} }
#endregion #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 readonly object sync_root = new object();
static IntPtr[] EntryPoints; static IntPtr[] EntryPoints;
static string[] EntryPointNames; static byte[] EntryPointNames;
static int[] EntryPointNameOffsets;
#region Constructors #region Constructors
@ -53,8 +54,9 @@ namespace OpenTK.Graphics.ES20
/// </summary> /// </summary>
public GL() public GL()
{ {
EntryPointsInstance = EntryPoints; _EntryPointsInstance = EntryPoints;
EntryPointNamesInstance = EntryPointNames; _EntryPointNamesInstance = EntryPointNames;
_EntryPointNameOffsetsInstance = EntryPointNameOffsets;
} }
#endregion #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 readonly object sync_root = new object();
static IntPtr[] EntryPoints; static IntPtr[] EntryPoints;
static string[] EntryPointNames; static byte[] EntryPointNames;
static int[] EntryPointNameOffsets;
#region Constructors #region Constructors
@ -53,8 +54,9 @@ namespace OpenTK.Graphics.ES30
/// </summary> /// </summary>
public GL() public GL()
{ {
EntryPointsInstance = EntryPoints; _EntryPointsInstance = EntryPoints;
EntryPointNamesInstance = EntryPointNames; _EntryPointNamesInstance = EntryPointNames;
_EntryPointNameOffsetsInstance = EntryPointNameOffsets;
} }
#endregion #endregion

View file

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

View file

@ -92,7 +92,13 @@ namespace OpenTK.Graphics
public ContextHandle Context { get { return Handle; } } 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); 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"; internal const string Library = "opengl32.dll";
static SortedList<string, bool> AvailableExtensions = new SortedList<string, bool>();
static readonly object sync_root = new object(); static readonly object sync_root = new object();
static IntPtr[] EntryPoints; static IntPtr[] EntryPoints;
static string[] EntryPointNames; static byte[] EntryPointNames;
static int[] EntryPointNameOffsets;
#endregion #endregion
@ -90,8 +90,9 @@ namespace OpenTK.Graphics.OpenGL
/// </summary> /// </summary>
public GL() public GL()
{ {
EntryPointsInstance = EntryPoints; _EntryPointsInstance = EntryPoints;
EntryPointNamesInstance = EntryPointNames; _EntryPointNamesInstance = EntryPointNames;
_EntryPointNameOffsetsInstance = EntryPointNameOffsets;
} }
#endregion #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 readonly object sync_root = new object();
static IntPtr[] EntryPoints; static IntPtr[] EntryPoints;
static string[] EntryPointNames; static byte[] EntryPointNames;
static int[] EntryPointNameOffsets;
#region Constructors #region Constructors
@ -53,8 +54,9 @@ namespace OpenTK.Graphics.OpenGL4
/// </summary> /// </summary>
public GL() public GL()
{ {
EntryPointsInstance = EntryPoints; _EntryPointsInstance = EntryPoints;
EntryPointNamesInstance = EntryPointNames; _EntryPointNamesInstance = EntryPointNames;
_EntryPointNameOffsetsInstance = EntryPointNameOffsets;
} }
#endregion #endregion

View file

@ -21,7 +21,7 @@ namespace OpenTK.Input
public sealed class KeyboardDevice : IInputDevice public sealed class KeyboardDevice : IInputDevice
{ {
//private IKeyboard keyboard; //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 bool[] scancodes = new bool[256];
private string description; private string description;
private int numKeys, numFKeys, numLeds; private int numKeys, numFKeys, numLeds;

View file

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

View file

@ -7,6 +7,7 @@
<dllmap os="linux" dll="libX11" target="libX11.so.6"/> <dllmap os="linux" dll="libX11" target="libX11.so.6"/>
<dllmap os="linux" dll="libXi" target="libXi.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="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="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="alut.dll" target="/System/Library/Frameworks/OpenAL.framework/OpenAL" />
<dllmap os="osx" dll="libGLES.dll" target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES" /> <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.OpenGL.GL().LoadEntryPoints();
new OpenTK.Graphics.OpenGL4.GL().LoadEntryPoints(); new OpenTK.Graphics.OpenGL4.GL().LoadEntryPoints();
new OpenTK.Graphics.ES10.GL().LoadEntryPoints();
new OpenTK.Graphics.ES11.GL().LoadEntryPoints(); new OpenTK.Graphics.ES11.GL().LoadEntryPoints();
new OpenTK.Graphics.ES20.GL().LoadEntryPoints(); new OpenTK.Graphics.ES20.GL().LoadEntryPoints();
new OpenTK.Graphics.ES30.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; } get { return current_thread != null && current_thread == Thread.CurrentThread; }
} }
public override IntPtr GetAddress(string function)
{
return Loader(function);
}
public override IntPtr GetAddress(IntPtr 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 public override int SwapInterval
@ -108,7 +104,6 @@ namespace OpenTK.Platform.Dummy
{ {
new OpenTK.Graphics.OpenGL.GL().LoadEntryPoints(); new OpenTK.Graphics.OpenGL.GL().LoadEntryPoints();
new OpenTK.Graphics.OpenGL4.GL().LoadEntryPoints(); new OpenTK.Graphics.OpenGL4.GL().LoadEntryPoints();
new OpenTK.Graphics.ES10.GL().LoadEntryPoints();
new OpenTK.Graphics.ES11.GL().LoadEntryPoints(); new OpenTK.Graphics.ES11.GL().LoadEntryPoints();
new OpenTK.Graphics.ES20.GL().LoadEntryPoints(); new OpenTK.Graphics.ES20.GL().LoadEntryPoints();
new OpenTK.Graphics.ES30.GL().LoadEntryPoints(); new OpenTK.Graphics.ES30.GL().LoadEntryPoints();

View file

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

View file

@ -38,7 +38,6 @@ namespace OpenTK.Platform
{ {
Stopwatch time = Stopwatch.StartNew(); Stopwatch time = Stopwatch.StartNew();
new OpenTK.Graphics.ES10.GL().LoadEntryPoints();
new OpenTK.Graphics.ES11.GL().LoadEntryPoints(); new OpenTK.Graphics.ES11.GL().LoadEntryPoints();
new OpenTK.Graphics.ES20.GL().LoadEntryPoints(); new OpenTK.Graphics.ES20.GL().LoadEntryPoints();
new OpenTK.Graphics.ES30.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 selFlushBuffer = Selector.Get("flushBuffer");
static readonly IntPtr selMakeCurrentContext = Selector.Get("makeCurrentContext"); static readonly IntPtr selMakeCurrentContext = Selector.Get("makeCurrentContext");
static readonly IntPtr selUpdate = Selector.Get("update"); 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() static CocoaContext()
{ {
@ -292,14 +298,49 @@ namespace OpenTK
#region IGraphicsContextInternal Members #region IGraphicsContextInternal Members
public override IntPtr GetAddress(string function)
{
return NS.GetAddress(function);
}
public override IntPtr GetAddress(IntPtr 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 #endregion

View file

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

View file

@ -36,127 +36,229 @@ namespace OpenTK.Platform.MacOS
using Carbon; using Carbon;
using Input; 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 // comments indicate members of the Key enum that are missing
switch (code)
Add(MacOSKeyCode.A, Key.A); {
Add(MacOSKeyCode.OptionAlt, Key.AltLeft); case MacOSKeyCode.A:
return Key.A;
case MacOSKeyCode.OptionAlt:
return Key.AltLeft;
// AltRight // AltRight
Add(MacOSKeyCode.B, Key.B); case MacOSKeyCode.B:
return Key.B;
Add(MacOSKeyCode.Backslash, Key.BackSlash); case MacOSKeyCode.Backslash:
Add(MacOSKeyCode.Backspace, Key.BackSpace); return Key.BackSlash;
Add(MacOSKeyCode.BracketLeft, Key.BracketLeft); case MacOSKeyCode.Backspace:
Add(MacOSKeyCode.BracketRight, Key.BracketRight); return Key.BackSpace;
Add(MacOSKeyCode.C, Key.C); case MacOSKeyCode.BracketLeft:
return Key.BracketLeft;
case MacOSKeyCode.BracketRight:
return Key.BracketRight;
case MacOSKeyCode.C:
return Key.C;
// Capslock // Capslock
// Clear // Clear
Add(MacOSKeyCode.Comma, Key.Comma); case MacOSKeyCode.Comma:
Add(MacOSKeyCode.Control, Key.ControlLeft); return Key.Comma;
case MacOSKeyCode.Control:
return Key.ControlLeft;
// ControlRight // ControlRight
Add(MacOSKeyCode.D, Key.D); case MacOSKeyCode.D:
Add(MacOSKeyCode.Del, Key.Delete); return Key.D;
Add(MacOSKeyCode.Down, Key.Down); case MacOSKeyCode.Del:
Add(MacOSKeyCode.E, Key.E); return Key.Delete;
Add(MacOSKeyCode.End, Key.End); case MacOSKeyCode.Down:
Add(MacOSKeyCode.Enter, Key.Enter); return Key.Down;
Add(MacOSKeyCode.Return, Key.Enter); case MacOSKeyCode.E:
Add(MacOSKeyCode.Esc, Key.Escape); return Key.E;
Add(MacOSKeyCode.F, Key.F); case MacOSKeyCode.End:
Add(MacOSKeyCode.F1, Key.F1); return Key.End;
Add(MacOSKeyCode.F2, Key.F2); case MacOSKeyCode.Enter:
Add(MacOSKeyCode.F3, Key.F3); return Key.Enter;
Add(MacOSKeyCode.F4, Key.F4); case MacOSKeyCode.Return:
Add(MacOSKeyCode.F5, Key.F5); return Key.Enter;
Add(MacOSKeyCode.F6, Key.F6); case MacOSKeyCode.Esc:
Add(MacOSKeyCode.F7, Key.F7); return Key.Escape;
Add(MacOSKeyCode.F8, Key.F8); case MacOSKeyCode.F:
Add(MacOSKeyCode.F9, Key.F9); return Key.F;
Add(MacOSKeyCode.F10, Key.F10); case MacOSKeyCode.F1:
Add(MacOSKeyCode.F11, Key.F11); return Key.F1;
Add(MacOSKeyCode.F12, Key.F12); case MacOSKeyCode.F2:
Add(MacOSKeyCode.F13, Key.F13); return Key.F2;
Add(MacOSKeyCode.F14, Key.F14); case MacOSKeyCode.F3:
Add(MacOSKeyCode.F15, Key.F15); 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 // F16-F35
Add(MacOSKeyCode.G, Key.G); case MacOSKeyCode.G:
Add(MacOSKeyCode.H, Key.H); return Key.G;
Add(MacOSKeyCode.Home, Key.Home); case MacOSKeyCode.H:
Add(MacOSKeyCode.I, Key.I); return Key.H;
Add(MacOSKeyCode.Insert, Key.Insert); case MacOSKeyCode.Home:
Add(MacOSKeyCode.J, Key.J); return Key.Home;
Add(MacOSKeyCode.K, Key.K); case MacOSKeyCode.I:
Add(MacOSKeyCode.KeyPad_0, Key.Keypad0); return Key.I;
Add(MacOSKeyCode.KeyPad_1, Key.Keypad1); case MacOSKeyCode.Insert:
Add(MacOSKeyCode.KeyPad_2, Key.Keypad2); return Key.Insert;
Add(MacOSKeyCode.KeyPad_3, Key.Keypad3); case MacOSKeyCode.J:
Add(MacOSKeyCode.KeyPad_4, Key.Keypad4); return Key.J;
Add(MacOSKeyCode.KeyPad_5, Key.Keypad5); case MacOSKeyCode.K:
Add(MacOSKeyCode.KeyPad_6, Key.Keypad6); return Key.K;
Add(MacOSKeyCode.KeyPad_7, Key.Keypad7); case MacOSKeyCode.KeyPad_0:
Add(MacOSKeyCode.KeyPad_8, Key.Keypad8); return Key.Keypad0;
Add(MacOSKeyCode.KeyPad_9, Key.Keypad9); case MacOSKeyCode.KeyPad_1:
Add(MacOSKeyCode.KeyPad_Add, Key.KeypadAdd); return Key.Keypad1;
Add(MacOSKeyCode.KeyPad_Decimal, Key.KeypadDecimal); case MacOSKeyCode.KeyPad_2:
Add(MacOSKeyCode.KeyPad_Divide, Key.KeypadDivide); return Key.Keypad2;
Add(MacOSKeyCode.KeyPad_Enter, Key.KeypadEnter); case MacOSKeyCode.KeyPad_3:
Add(MacOSKeyCode.KeyPad_Multiply, Key.KeypadMultiply); return Key.Keypad3;
Add(MacOSKeyCode.KeyPad_Subtract, Key.KeypadSubtract); case MacOSKeyCode.KeyPad_4:
//Add(MacOSKeyCode.KeyPad_Equal); return Key.Keypad4;
Add(MacOSKeyCode.L, Key.L); case MacOSKeyCode.KeyPad_5:
Add(MacOSKeyCode.Left, Key.Left); return Key.Keypad5;
Add(MacOSKeyCode.M, Key.M); 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 //Key.MaxKeys
Add(MacOSKeyCode.Menu, Key.Menu); case MacOSKeyCode.Menu:
Add(MacOSKeyCode.Minus, Key.Minus); return Key.Menu;
Add(MacOSKeyCode.N, Key.N); case MacOSKeyCode.Minus:
Add(MacOSKeyCode.Key_0, Key.Number0); return Key.Minus;
Add(MacOSKeyCode.Key_1, Key.Number1); case MacOSKeyCode.N:
Add(MacOSKeyCode.Key_2, Key.Number2); return Key.N;
Add(MacOSKeyCode.Key_3, Key.Number3); case MacOSKeyCode.Key_0:
Add(MacOSKeyCode.Key_4, Key.Number4); return Key.Number0;
Add(MacOSKeyCode.Key_5, Key.Number5); case MacOSKeyCode.Key_1:
Add(MacOSKeyCode.Key_6, Key.Number6); return Key.Number1;
Add(MacOSKeyCode.Key_7, Key.Number7); case MacOSKeyCode.Key_2:
Add(MacOSKeyCode.Key_8, Key.Number8); return Key.Number2;
Add(MacOSKeyCode.Key_9, Key.Number9); 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 // Numlock
Add(MacOSKeyCode.O, Key.O); case MacOSKeyCode.O:
Add(MacOSKeyCode.P, Key.P); return Key.O;
Add(MacOSKeyCode.Pagedown, Key.PageDown); case MacOSKeyCode.P:
Add(MacOSKeyCode.Pageup, Key.PageUp); return Key.P;
case MacOSKeyCode.Pagedown:
return Key.PageDown;
case MacOSKeyCode.Pageup:
return Key.PageUp;
// Pause // Pause
Add(MacOSKeyCode.Period, Key.Period); case MacOSKeyCode.Period:
Add(MacOSKeyCode.Equals, Key.Plus); return Key.Period;
case MacOSKeyCode.Equals:
return Key.Plus;
// PrintScreen // PrintScreen
Add(MacOSKeyCode.Q, Key.Q); case MacOSKeyCode.Q:
Add(MacOSKeyCode.Quote, Key.Quote); return Key.Q;
Add(MacOSKeyCode.R, Key.R); case MacOSKeyCode.Quote:
Add(MacOSKeyCode.Right, Key.Right); return Key.Quote;
Add(MacOSKeyCode.S, Key.S); case MacOSKeyCode.R:
return Key.R;
case MacOSKeyCode.Right:
return Key.Right;
case MacOSKeyCode.S:
return Key.S;
// ScrollLock // ScrollLock
Add(MacOSKeyCode.Semicolon, Key.Semicolon); case MacOSKeyCode.Semicolon:
Add(MacOSKeyCode.Shift, Key.ShiftLeft); return Key.Semicolon;
case MacOSKeyCode.Shift:
return Key.ShiftLeft;
//Key.ShiftRight //Key.ShiftRight
Add(MacOSKeyCode.Slash, Key.Slash); case MacOSKeyCode.Slash:
return Key.Slash;
// Key.Sleep // Key.Sleep
Add(MacOSKeyCode.Space, Key.Space); case MacOSKeyCode.Space:
Add(MacOSKeyCode.T, Key.T); return Key.Space;
Add(MacOSKeyCode.Tab, Key.Tab); case MacOSKeyCode.T:
Add(MacOSKeyCode.Tilde, Key.Tilde); return Key.T;
Add(MacOSKeyCode.U, Key.U); case MacOSKeyCode.Tab:
Add(MacOSKeyCode.Up, Key.Up); return Key.Tab;
Add(MacOSKeyCode.V, Key.V); case MacOSKeyCode.Tilde:
Add(MacOSKeyCode.W, Key.W); return Key.Tilde;
Add(MacOSKeyCode.Command, Key.WinLeft); 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 // WinKeyRight
Add(MacOSKeyCode.X, Key.X); case MacOSKeyCode.X:
Add(MacOSKeyCode.Y, Key.Y); return Key.X;
Add(MacOSKeyCode.Z, Key.Z); 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 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 internal class NS
{ {
const string Library = "libdl.dylib"; const string Library = "libdl.dylib";
[DllImport(Library, EntryPoint = "NSIsSymbolNameDefined")] [DllImport(Library, EntryPoint = "NSAddImage")]
static extern bool NSIsSymbolNameDefined(string s); internal static extern IntPtr AddImage(string s, AddImageFlags flags);
[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 = "NSAddressOfSymbol")] [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)] [DllImport(Library)]
private static extern IntPtr dlopen(String fileName, int flags); internal static extern IntPtr dlopen(String fileName, int flags);
[DllImport(Library)] [DllImport(Library)]
private static extern int dlclose(IntPtr handle); internal static extern int dlclose(IntPtr handle);
[DllImport (Library)] [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) public static IntPtr GetAddress(string function)
{ {
@ -73,7 +98,7 @@ namespace OpenTK.Platform.MacOS
} }
Marshal.WriteByte(ptr, function.Length + 1, 0); // null-terminate Marshal.WriteByte(ptr, function.Length + 1, 0); // null-terminate
IntPtr symbol = GetAddress(ptr); IntPtr symbol = GetAddressInternal(ptr);
return symbol; return symbol;
} }
finally finally
@ -84,12 +109,39 @@ namespace OpenTK.Platform.MacOS
public static IntPtr GetAddress(IntPtr function) public static IntPtr GetAddress(IntPtr function)
{ {
IntPtr symbol = IntPtr.Zero; unsafe
if (NSIsSymbolNameDefined(function))
{ {
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) if (symbol != IntPtr.Zero)
symbol = NSAddressOfSymbol(symbol); symbol = AddressOfSymbol(symbol);
} }
return symbol; return symbol;
} }
@ -99,6 +151,11 @@ namespace OpenTK.Platform.MacOS
return dlsym(handle, symbol); return dlsym(handle, symbol);
} }
public static IntPtr GetSymbol(IntPtr handle, IntPtr symbol)
{
return dlsym(handle, symbol);
}
public static IntPtr LoadLibrary(string fileName) public static IntPtr LoadLibrary(string fileName)
{ {
const int RTLD_NOW = 2; 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) public override IntPtr GetAddress(IntPtr function)
{ {
return SDL.GL.GetProcAddress(function); return SDL.GL.GetProcAddress(function);

View file

@ -33,91 +33,270 @@ namespace OpenTK.Platform.SDL2
{ {
using Code = Scancode; using Code = Scancode;
class Sdl2KeyMap : Dictionary<Scancode, Key> class Sdl2KeyMap
{ {
public Sdl2KeyMap() public static Key GetKey(Code code)
{ {
Add(Code.ESCAPE, Key.Escape); switch (code)
{
case Code.ESCAPE:
return Key.Escape;
// Function keys // Function keys
for (int i = 0; i < 12; i++) case Code.F1:
{ return Key.F1;
Add(Code.F1 + i, Key.F1 + i); 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) // Number keys (0-9)
Add(Code.Num0, Key.Number0); case Code.Num0:
for (int i = 0; i < 9; i++) return Key.Number0;
{ case Code.Num1:
Add(Code.Num1 + i, Key.Number1 + i); 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) // Letters (A-Z)
for (int i = 0; i < 26; i++) case Code.A:
{ return Key.A;
Add(Code.A + i, Key.A + i); 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;
Add(Code.TAB, Key.Tab); case Code.TAB:
Add(Code.CAPSLOCK, Key.CapsLock); return Key.Tab;
Add(Code.LCTRL, Key.ControlLeft); case Code.CAPSLOCK:
Add(Code.LSHIFT, Key.ShiftLeft); return Key.CapsLock;
Add(Code.LALT, Key.AltLeft); case Code.LCTRL:
Add(Code.MENU, Key.WinLeft); return Key.ControlLeft;
Add(Code.SPACE, Key.Space); case Code.LSHIFT:
Add(Code.RALT, Key.AltRight); return Key.ShiftLeft;
//Add(Code., Key.WinRight); case Code.LALT:
Add(Code.APPLICATION, Key.Menu); return Key.AltLeft;
Add(Code.RCTRL, Key.ControlRight); case Code.MENU:
Add(Code.RSHIFT, Key.ShiftRight); return Key.Menu;
Add(Code.RETURN, Key.Enter); case Code.LGUI:
Add(Code.BACKSPACE, Key.BackSpace); 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;
Add(Code.SEMICOLON, Key.Semicolon); // Varies by keyboard, ;: on Win2K/US case Code.SEMICOLON:
Add(Code.SLASH, Key.Slash); // Varies by keyboard, /? on Win2K/US return Key.Semicolon; // Varies by keyboard: return ;: on Win2K/US
Add(Code.GRAVE, Key.Tilde); // Varies by keyboard, `~ on Win2K/US case Code.SLASH:
Add(Code.LEFTBRACKET, Key.BracketLeft); // Varies by keyboard, [{ on Win2K/US return Key.Slash; // Varies by keyboard: return /? on Win2K/US
Add(Code.BACKSLASH, Key.BackSlash); // Varies by keyboard, \| on Win2K/US case Code.GRAVE:
Add(Code.RIGHTBRACKET, Key.BracketRight); // Varies by keyboard, ]} on Win2K/US return Key.Tilde; // Varies by keyboard: return `~ on Win2K/US
Add(Code.APOSTROPHE, Key.Quote); // Varies by keyboard, '" on Win2K/US case Code.LEFTBRACKET:
Add(Code.EQUALS, Key.Plus); return Key.BracketLeft; // Varies by keyboard: return [{ on Win2K/US
Add(Code.COMMA, Key.Comma); // Invariant: , case Code.BACKSLASH:
Add(Code.MINUS, Key.Minus); // Invariant: - return Key.BackSlash; // Varies by keyboard: return \| on Win2K/US
Add(Code.PERIOD, Key.Period); // Invariant: . 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: .
Add(Code.HOME, Key.Home); case Code.HOME:
Add(Code.END, Key.End); return Key.Home;
Add(Code.DELETE, Key.Delete); case Code.END:
Add(Code.PAGEUP, Key.PageUp); return Key.End;
Add(Code.PAGEDOWN, Key.PageDown); case Code.DELETE:
Add(Code.PAUSE, Key.Pause); return Key.Delete;
Add(Code.NUMLOCKCLEAR, Key.NumLock); case Code.PAGEUP:
return Key.PageUp;
case Code.PAGEDOWN:
return Key.PageDown;
case Code.PAUSE:
return Key.Pause;
case Code.NUMLOCKCLEAR:
return Key.NumLock;
Add(Code.SCROLLLOCK, Key.ScrollLock); case Code.SCROLLLOCK:
Add(Code.PRINTSCREEN, Key.PrintScreen); return Key.ScrollLock;
Add(Code.CLEAR, Key.Clear); case Code.PRINTSCREEN:
Add(Code.INSERT, Key.Insert); return Key.PrintScreen;
case Code.CLEAR:
return Key.Clear;
case Code.INSERT:
return Key.Insert;
Add(Code.SLEEP, Key.Sleep); case Code.SLEEP:
return Key.Sleep;
// Keypad // Keypad
for (int i = 0; i < 9; i++) case Code.KP_0:
{ return Key.Keypad0;
Add(Code.KP_1 + i, Key.Keypad1 + i); case Code.KP_1:
} return Key.Keypad1;
Add(Code.KP_0, Key.Keypad0); // Note: SDL2 goes KP_1..KP_9, then KP_0 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;
Add(Code.KP_DECIMAL, Key.KeypadDecimal); case Code.KP_DECIMAL:
Add(Code.KP_PLUS, Key.KeypadAdd); return Key.KeypadDecimal;
Add(Code.KP_MINUS, Key.KeypadSubtract); case Code.KP_PLUS:
Add(Code.KP_DIVIDE, Key.KeypadDivide); return Key.KeypadAdd;
Add(Code.KP_MULTIPLY, Key.KeypadMultiply); case Code.KP_MINUS:
return Key.KeypadSubtract;
case Code.KP_DIVIDE:
return Key.KeypadDivide;
case Code.KP_MULTIPLY:
return Key.KeypadMultiply;
// Navigation // Navigation
Add(Code.UP, Key.Up); case Code.UP:
Add(Code.DOWN, Key.Down); return Key.Up;
Add(Code.LEFT, Key.Left); case Code.DOWN:
Add(Code.RIGHT, Key.Right); return Key.Down;
case Code.LEFT:
return Key.Left;
case Code.RIGHT:
return Key.Right;
default:
return Key.Unknown;
}
} }
} }
} }

View file

@ -33,7 +33,6 @@ namespace OpenTK.Platform.SDL2
{ {
class Sdl2Keyboard : IKeyboardDriver2, IKeyboardDriver class Sdl2Keyboard : IKeyboardDriver2, IKeyboardDriver
{ {
static readonly Sdl2KeyMap KeyMap = new Sdl2KeyMap();
KeyboardState state; KeyboardState state;
readonly List<KeyboardDevice> keyboards = readonly List<KeyboardDevice> keyboards =
@ -84,10 +83,10 @@ namespace OpenTK.Platform.SDL2
internal void ProcessKeyboardEvent(KeyboardEvent e) internal void ProcessKeyboardEvent(KeyboardEvent e)
{ {
Key key;
bool pressed = e.State != 0; bool pressed = e.State != 0;
var scancode = e.Keysym.Scancode; 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); state.SetKeyState(key, (byte)scancode, pressed);
keyboards[0].SetKey(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 = static readonly Dictionary<uint, Sdl2NativeWindow> windows =
new Dictionary<uint, Sdl2NativeWindow>(); new Dictionary<uint, Sdl2NativeWindow>();
static readonly Sdl2KeyMap map = new Sdl2KeyMap();
public Sdl2NativeWindow(int x, int y, int width, int height, public Sdl2NativeWindow(int x, int y, int width, int height,
string title, GameWindowFlags options, DisplayDevice device, string title, GameWindowFlags options, DisplayDevice device,
IInputDriver input_driver) IInputDriver input_driver)
@ -132,12 +130,7 @@ namespace OpenTK.Platform.SDL2
static Key TranslateKey(Scancode scan) static Key TranslateKey(Scancode scan)
{ {
Key result = Key.Unknown; return Sdl2KeyMap.GetKey(scan);
if (map.ContainsKey(scan))
{
result = map[scan];
}
return result;
} }
static Key TranslateKey(Keycode key) static Key TranslateKey(Keycode key)

View file

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

View file

@ -374,16 +374,6 @@ namespace OpenTK.Platform.Windows
#region GetAddress #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) public override IntPtr GetAddress(IntPtr function_string)
{ {
IntPtr address = Wgl.GetProcAddress(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 ParentStyleEx = ExtendedWindowStyle.WindowEdge | ExtendedWindowStyle.ApplicationWindow;
const ExtendedWindowStyle ChildStyleEx = 0; const ExtendedWindowStyle ChildStyleEx = 0;
static readonly WinKeyMap KeyMap = new WinKeyMap();
readonly IntPtr Instance = Marshal.GetHINSTANCE(typeof(WinGLNative).Module); readonly IntPtr Instance = Marshal.GetHINSTANCE(typeof(WinGLNative).Module);
readonly IntPtr ClassName = Marshal.StringToHGlobalAuto(Guid.NewGuid().ToString()); readonly IntPtr ClassName = Marshal.StringToHGlobalAuto(Guid.NewGuid().ToString());
readonly WindowProcedure WindowProcedureDelegate; readonly WindowProcedure WindowProcedureDelegate;
@ -578,7 +577,7 @@ namespace OpenTK.Platform.Windows
short scancode = (short)((lParam.ToInt64() >> 16) & 0xFF); short scancode = (short)((lParam.ToInt64() >> 16) & 0xFF);
VirtualKeys vkey = (VirtualKeys)wParam; VirtualKeys vkey = (VirtualKeys)wParam;
bool is_valid; 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) if (is_valid)
{ {

View file

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

View file

@ -38,7 +38,6 @@ namespace OpenTK.Platform.Windows
{ {
sealed class WinRawKeyboard : IKeyboardDriver2 sealed class WinRawKeyboard : IKeyboardDriver2
{ {
static readonly WinKeyMap KeyMap = new WinKeyMap();
readonly List<KeyboardState> keyboards = new List<KeyboardState>(); readonly List<KeyboardState> keyboards = new List<KeyboardState>();
readonly List<string> names = new List<string>(); readonly List<string> names = new List<string>();
readonly Dictionary<ContextHandle, int> rawids = new Dictionary<ContextHandle, int>(); 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; int keyboard_handle = rawids.ContainsKey(handle) ? rawids[handle] : 0;
keyboard = keyboards[keyboard_handle]; 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) if (is_valid)
{ {

View file

@ -259,8 +259,38 @@ namespace OpenTK.Platform.X11
/// <summary> /// <summary>
/// Provides access to GLX functions. /// Provides access to GLX functions.
/// </summary> /// </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 #region GLX functions
[DllImport(Library, EntryPoint = "glXIsDirect")] [DllImport(Library, EntryPoint = "glXIsDirect")]
@ -343,34 +373,20 @@ namespace OpenTK.Platform.X11
#endregion #endregion
#region Extensions
public partial class Sgi
{
public static ErrorCode SwapInterval(int interval)
{
return (ErrorCode)Delegates.glXSwapIntervalSGI(interval);
}
}
public partial class Arb 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) 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) public static IntPtr CreateContextAttribs(IntPtr display, IntPtr fbconfig, IntPtr share_context, bool direct, int[] attribs)
{ {
unsafe throw new NotImplementedException();
{
fixed (int* attribs_ptr = attribs)
{
return Delegates.glXCreateContextAttribsARB(display, fbconfig, share_context, direct, attribs_ptr);
}
}
} }
#endregion #endregion
@ -389,18 +405,21 @@ namespace OpenTK.Platform.X11
#endregion #endregion
} }
internal static partial class Delegates public partial class Sgi
{ {
[SuppressUnmanagedCodeSecurity] [AutoGenerated(EntryPoint = "glXSwapIntervalSGI")]
public delegate int SwapIntervalSGI(int interval); public static ErrorCode SwapInterval(int interval)
public static SwapIntervalSGI glXSwapIntervalSGI = null; {
throw new NotImplementedException();
[SuppressUnmanagedCodeSecurity] }
unsafe public delegate IntPtr CreateContextAttribsARB(IntPtr display, IntPtr fbconfig, IntPtr share_context, bool direct, int* attribs);
unsafe public static CreateContextAttribsARB glXCreateContextAttribsARB = null;
} }
#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 #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 return
SupportsExtension(display, window, "GLX_ARB_create_context") && SupportsExtension(display, window, "GLX_ARB_create_context") &&
SupportsExtension(display, window, "GLX_ARB_create_context_profile") && SupportsExtension(display, window, "GLX_ARB_create_context_profile") &&
Glx.Delegates.glXCreateContextAttribsARB != null; Glx.SupportsFunction("glXCreateContextAttribsARB");
} }
#endregion #endregion
@ -380,8 +380,7 @@ namespace OpenTK.Platform.X11
public override void LoadAll() public override void LoadAll()
{ {
new Glx().LoadEntryPoints(); vsync_supported = Glx.SupportsFunction("glXSwapIntervalSGI");
vsync_supported = this.GetAddress("glXSwapIntervalSGI") != IntPtr.Zero;
Debug.Print("Context supports vsync: {0}.", vsync_supported); Debug.Print("Context supports vsync: {0}.", vsync_supported);
base.LoadAll(); base.LoadAll();
@ -395,14 +394,6 @@ namespace OpenTK.Platform.X11
#region GetAddress #region GetAddress
public override IntPtr GetAddress(string function)
{
using (new XLock(Display))
{
return Glx.GetProcAddress(function);
}
}
public override IntPtr GetAddress(IntPtr function) public override IntPtr GetAddress(IntPtr function)
{ {
using (new XLock(Display)) using (new XLock(Display))

View file

@ -29,7 +29,6 @@ namespace OpenTK.Platform.X11
List<KeyboardDevice> dummy_keyboard_list = new List<KeyboardDevice>(1); List<KeyboardDevice> dummy_keyboard_list = new List<KeyboardDevice>(1);
List<MouseDevice> dummy_mice_list = new List<MouseDevice>(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 firstKeyCode, lastKeyCode; // The smallest and largest KeyCode supported by the X server.
int keysyms_per_keycode; // The number of KeySyms for each KeyCode. int keysyms_per_keycode; // The number of KeySyms for each KeyCode.
IntPtr[] keysyms; IntPtr[] keysyms;
@ -100,17 +99,12 @@ namespace OpenTK.Platform.X11
{ {
XKey keysym = (XKey)API.LookupKeysym(ref e, 0); XKey keysym = (XKey)API.LookupKeysym(ref e, 0);
XKey keysym2 = (XKey)API.LookupKeysym(ref e, 1); XKey keysym2 = (XKey)API.LookupKeysym(ref e, 1);
key = Key.Unknown; key = X11KeyMap.GetKey(keysym);
if (key == Key.Unknown)
if (keymap.ContainsKey(keysym))
{ {
key = keymap[keysym]; key = X11KeyMap.GetKey(keysym2);
} }
else if (keymap.ContainsKey(keysym2)) if (key == Key.Unknown)
{
key = keymap[keysym2];
}
else
{ {
Debug.Print("KeyCode {0} (Keysym: {1}, {2}) not mapped.", e.keycode, (XKey)keysym, (XKey)keysym2); 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.Collections.Generic;
using System.Text; using System.Text;
using System.Diagnostics; using System.Diagnostics;
using OpenTK.Input; using OpenTK.Input;
namespace OpenTK.Platform.X11 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); case XKey.Escape:
this.Add(XKey.Return, Key.Enter); return Key.Escape;
this.Add(XKey.space, Key.Space); case XKey.Return:
this.Add(XKey.BackSpace, Key.BackSpace); return Key.Enter;
case XKey.space:
return Key.Space;
case XKey.BackSpace:
return Key.BackSpace;
this.Add(XKey.Shift_L, Key.ShiftLeft); case XKey.Shift_L:
this.Add(XKey.Shift_R, Key.ShiftRight); return Key.ShiftLeft;
this.Add(XKey.Alt_L, Key.AltLeft); case XKey.Shift_R:
this.Add(XKey.Alt_R, Key.AltRight); return Key.ShiftRight;
this.Add(XKey.Control_L, Key.ControlLeft); case XKey.Alt_L:
this.Add(XKey.Control_R, Key.ControlRight); return Key.AltLeft;
this.Add(XKey.Super_L, Key.WinLeft); case XKey.Alt_R:
this.Add(XKey.Super_R, Key.WinRight); return Key.AltRight;
this.Add(XKey.Meta_L, Key.WinLeft); case XKey.Control_L:
this.Add(XKey.Meta_R, Key.WinRight); return Key.ControlLeft;
this.Add(XKey.ISO_Level3_Shift, Key.AltRight); // Normally AltGr 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); case XKey.Menu:
this.Add(XKey.Tab, Key.Tab); return Key.Menu;
this.Add(XKey.minus, Key.Minus); case XKey.Tab:
this.Add(XKey.plus, Key.Plus); return Key.Tab;
this.Add(XKey.equal, Key.Plus); 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); case XKey.Caps_Lock:
this.Add(XKey.Num_Lock, Key.NumLock); return Key.CapsLock;
case XKey.Num_Lock:
return Key.NumLock;
for (int i = (int)XKey.F1; i <= (int)XKey.F35; i++) case XKey.F1:
{ return Key.F1;
this.Add((XKey)i, (Key)((int)Key.F1 + (i - (int)XKey.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++) case XKey.a:
{ case XKey.A:
this.Add((XKey)i, (Key)((int)Key.A + (i - (int)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++) case XKey.Number0:
{ return Key.Number0;
this.Add((XKey)i, (Key)((int)Key.A + (i - (int)XKey.A))); 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++) case XKey.KP_0:
{ return Key.Keypad0;
this.Add((XKey)i, (Key)((int)Key.Number0 + (i - (int)XKey.Number0))); 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++) case XKey.Pause:
{ return Key.Pause;
this.Add((XKey)i, (Key)((int)Key.Keypad0 + (i - (int)XKey.KP_0))); 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); case XKey.backslash:
this.Add(XKey.Break, Key.Pause); return Key.BackSlash;
this.Add(XKey.Scroll_Lock, Key.Pause); case XKey.bar:
this.Add(XKey.Insert, Key.PrintScreen); return Key.BackSlash;
this.Add(XKey.Print, Key.PrintScreen); case XKey.braceleft:
this.Add(XKey.Sys_Req, Key.PrintScreen); 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); case XKey.comma:
this.Add(XKey.bar, Key.BackSlash); return Key.Comma;
this.Add(XKey.braceleft, Key.BracketLeft); case XKey.less:
this.Add(XKey.bracketleft, Key.BracketLeft); return Key.Comma;
this.Add(XKey.braceright, Key.BracketRight); case XKey.period:
this.Add(XKey.bracketright, Key.BracketRight); return Key.Period;
this.Add(XKey.colon, Key.Semicolon); case XKey.greater:
this.Add(XKey.semicolon, Key.Semicolon); return Key.Period;
this.Add(XKey.quoteright, Key.Quote); case XKey.slash:
this.Add(XKey.quotedbl, Key.Quote); return Key.Slash;
this.Add(XKey.quoteleft, Key.Tilde); case XKey.question:
this.Add(XKey.asciitilde, Key.Tilde); return Key.Slash;
this.Add(XKey.comma, Key.Comma); case XKey.Left:
this.Add(XKey.less, Key.Comma); return Key.Left;
this.Add(XKey.period, Key.Period); case XKey.Down:
this.Add(XKey.greater, Key.Period); return Key.Down;
this.Add(XKey.slash, Key.Slash); case XKey.Right:
this.Add(XKey.question, Key.Slash); return Key.Right;
case XKey.Up:
return Key.Up;
this.Add(XKey.Left, Key.Left); case XKey.Delete:
this.Add(XKey.Down, Key.Down); return Key.Delete;
this.Add(XKey.Right, Key.Right); case XKey.Home:
this.Add(XKey.Up, Key.Up); 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); case XKey.KP_Add:
this.Add(XKey.Home, Key.Home); return Key.KeypadAdd;
this.Add(XKey.End, Key.End); case XKey.KP_Subtract:
//this.Add(XKey.Prior, Key.PageUp); // XKey.Prior == XKey.Page_Up return Key.KeypadSubtract;
this.Add(XKey.Page_Up, Key.PageUp); case XKey.KP_Multiply:
this.Add(XKey.Page_Down, Key.PageDown); return Key.KeypadMultiply;
//this.Add(XKey.Next, Key.PageDown); // XKey.Next == XKey.Page_Down 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); default:
this.Add(XKey.KP_Subtract, Key.KeypadSubtract); return Key.Unknown;
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());
} }
} }
} }

View file

@ -1,29 +1,29 @@
#region License #region License
// //
// The Open Toolkit Library License // The Open Toolkit Library License
// //
// Copyright (c) 2006 - 2010 the Open Toolkit library. // Copyright (c) 2006 - 2010 the Open Toolkit library.
// //
// Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal // of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights to // in the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of // 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 // the Software, and to permit persons to whom the Software is furnished to do
// so, subject to the following conditions: // so, subject to the following conditions:
// //
// The above copyright notice and this permission notice shall be included in all // The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software. // copies or substantial portions of the Software.
// //
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE. // OTHER DEALINGS IN THE SOFTWARE.
// //
#endregion #endregion
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@ -36,7 +36,6 @@ namespace OpenTK.Platform.X11
// Only one keyboard supported. // Only one keyboard supported.
sealed class X11Keyboard : IKeyboardDriver2 sealed class X11Keyboard : IKeyboardDriver2
{ {
readonly static X11KeyMap keymap = new X11KeyMap();
readonly static string name = "Core X11 keyboard"; readonly static string name = "Core X11 keyboard";
readonly byte[] keys = new byte[32]; readonly byte[] keys = new byte[32];
readonly int KeysymsPerKeycode; readonly int KeysymsPerKeycode;
@ -53,7 +52,10 @@ namespace OpenTK.Platform.X11
// Find the number of keysyms per keycode. // Find the number of keysyms per keycode.
int first = 0, last = 0; int first = 0, last = 0;
API.DisplayKeycodes(display, ref first, ref last); API.DisplayKeycodes(display, ref first, ref last);
IntPtr keysym_ptr = API.GetKeyboardMapping(display, (byte)first, last - first + 1, IntPtr keysym_ptr =
API.GetKeyboardMapping(display,
(byte)first,
last - first + 1,
ref KeysymsPerKeycode); ref KeysymsPerKeycode);
Functions.XFree(keysym_ptr); Functions.XFree(keysym_ptr);
@ -66,7 +68,9 @@ namespace OpenTK.Platform.X11
bool supported; bool supported;
Functions.XkbSetDetectableAutoRepeat(display, true, out supported); Functions.XkbSetDetectableAutoRepeat(display, true, out supported);
} }
catch { } catch
{
}
} }
} }
@ -108,8 +112,9 @@ namespace OpenTK.Platform.X11
for (int mod = 0; mod < KeysymsPerKeycode; mod++) for (int mod = 0; mod < KeysymsPerKeycode; mod++)
{ {
IntPtr keysym = Functions.XKeycodeToKeysym(display, (byte)keycode, 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) if (pressed)
state.EnableBit((int)key); state.EnableBit((int)key);
else else