diff --git a/Source/Examples/Main.cs b/Source/Examples/Main.cs
index 84dba6d7..eb86bd06 100644
--- a/Source/Examples/Main.cs
+++ b/Source/Examples/Main.cs
@@ -101,6 +101,15 @@ namespace Examples
public static void Main(string[] args)
{
Trace.Listeners.Add(new ConsoleTraceListener());
+ Tests.GameWindowStates.Main();
+ return;
+
+ using (var gw = new GameWindow())
+ {
+ gw.KeyDown += (sender, e) => gw.Exit();
+ gw.Run(60);
+ }
+ return;
if (args.Length > 0)
{
diff --git a/Source/OpenTK/OpenTK.csproj b/Source/OpenTK/OpenTK.csproj
index d931c244..794abfa5 100644
--- a/Source/OpenTK/OpenTK.csproj
+++ b/Source/OpenTK/OpenTK.csproj
@@ -343,9 +343,6 @@
Code
-
- Code
-
Code
@@ -809,8 +806,13 @@
-
+
+
+ Code
+
+
+
diff --git a/Source/OpenTK/Platform/Factory.cs b/Source/OpenTK/Platform/Factory.cs
index 9a701844..5cc0bfe1 100644
--- a/Source/OpenTK/Platform/Factory.cs
+++ b/Source/OpenTK/Platform/Factory.cs
@@ -53,6 +53,7 @@ namespace OpenTK.Platform
// Create regular platform backend
if (Configuration.RunningOnSdl2) Default = new SDL2.Sdl2Factory();
+ else if (Configuration.RunningOnLinux) Default = new Linux.LinuxFactory();
else if (Configuration.RunningOnX11) Default = new X11.X11Factory();
else if (Configuration.RunningOnWindows) Default = new Windows.WinFactory();
else if (Configuration.RunningOnMacOS) Default = new MacOS.MacOSFactory();
@@ -70,7 +71,8 @@ namespace OpenTK.Platform
}
else if (Egl.Egl.IsSupported)
{
- if (Configuration.RunningOnX11) Embedded = new Egl.EglX11PlatformFactory();
+ if (Configuration.RunningOnLinux) Embedded = Default;
+ else if (Configuration.RunningOnX11) Embedded = new Egl.EglX11PlatformFactory();
else if (Configuration.RunningOnWindows) Embedded = new Egl.EglWinPlatformFactory();
else if (Configuration.RunningOnMacOS) Embedded = new Egl.EglMacPlatformFactory();
else Embedded = new UnsupportedPlatform();
diff --git a/Source/OpenTK/Platform/Linux/Bindings/Drm.cs b/Source/OpenTK/Platform/Linux/Bindings/Drm.cs
index 3f4bddb7..7f2bf590 100644
--- a/Source/OpenTK/Platform/Linux/Bindings/Drm.cs
+++ b/Source/OpenTK/Platform/Linux/Bindings/Drm.cs
@@ -36,20 +36,115 @@ namespace OpenTK.Platform.Linux
{
const string lib = "libdrm";
+ [DllImport(lib, EntryPoint = "drmModeGetCrtc", CallingConvention = CallingConvention.Cdecl)]
+ public static extern IntPtr ModeGetCrtc(int fd, uint crtcId);
+
+ [DllImport(lib, EntryPoint = "drmModeFreeConnector", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void ModeFreeConnector(IntPtr ptr);
+
+ [DllImport(lib, EntryPoint = "drmModeFreeEncoder", CallingConvention = CallingConvention.Cdecl)]
+ public static extern void ModeFreeEncoder(IntPtr ptr);
+
+ [DllImport(lib, EntryPoint = "drmModeGetConnector", CallingConvention = CallingConvention.Cdecl)]
+ public static extern IntPtr ModeGetConnector(int fd, uint connector_id);
+
+ [DllImport(lib, EntryPoint = "drmModeGetEncoder", CallingConvention = CallingConvention.Cdecl)]
+ public static extern IntPtr ModeGetEncoder(int fd, uint encoder_id);
+
[DllImport(lib, EntryPoint = "drmModeGetResources", CallingConvention = CallingConvention.Cdecl)]
- static extern IntPtr ModeGetResources(int fd);
+ public static extern IntPtr ModeGetResources(int fd);
+
+ [DllImport(lib, EntryPoint = "drmModeSetCrtc", CallingConvention = CallingConvention.Cdecl)]
+ unsafe public static extern int ModeSetCrtc(int fd, uint crtcId, uint bufferId,
+ uint x, uint y, uint* connectors, int count, ModeInfo* mode);
}
- struct ModeRes
+ enum ModeConnection : byte
+ {
+ Connected = 1,
+ Disconnected = 2,
+ Unknown = 3
+ }
+
+ enum ModeSubPixel : byte
+ {
+ Unknown = 1,
+ HorizontalRgb = 2,
+ HorizontalBgr = 3,
+ VerticalRgb = 4,
+ VerticalBgr = 5,
+ None = 6
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ unsafe struct ModeConnector
+ {
+ public uint connector_id;
+ public uint encoder_id;
+ public uint connector_type;
+ public uint connector_type_id;
+ public ModeConnection connection;
+ public uint mmWidth, mmHeight;
+ public ModeSubPixel subpixel;
+
+ public int count_modes;
+ public ModeInfo* modes;
+
+ public int count_props;
+ public uint *props;
+ public ulong *prop_values;
+
+ public int count_encoders;
+ public uint *encoders;
+ }
+
+ struct ModeCrtc
+ {
+ public uint crtc_id;
+ public uint buffer_id;
+
+ public uint x, y;
+ public uint width, height;
+ public int mode_valid;
+ public ModeInfo mode;
+
+ public int gamma_size;
+ }
+
+ struct ModeEncoder
+ {
+ public uint encoder_id;
+ public uint encoder_type;
+ public uint crtc_id;
+ public uint possible_crtcs;
+ public uint possible_clones;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ unsafe struct ModeInfo
+ {
+ public uint clock;
+ public ushort hdisplay, hsync_start, hsync_end, htotal, hskew;
+ public ushort vdisplay, vsync_start, vsync_end, vtotal, vscan;
+
+ public uint vrefresh; // refresh rate * 1000
+
+ public uint flags;
+ public uint type;
+ public fixed sbyte name[32];
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ unsafe struct ModeRes
{
public int count_fbs;
- public IntPtr fbs; //uint*
+ public uint* fbs;
public int count_crtcs;
- public IntPtr crtcs; //uint*
+ public uint* crtcs;
public int count_connectors;
- public IntPtr connectors; //uint*
+ public uint* connectors;
public int count_encoders;
- public IntPtr encoders; //uint*
+ public uint* encoders;
public int min_width, max_width;
public int min_height, max_height;
}
diff --git a/Source/OpenTK/Platform/Linux/Bindings/Linux.cs b/Source/OpenTK/Platform/Linux/Bindings/Libc.cs
similarity index 53%
rename from Source/OpenTK/Platform/Linux/Bindings/Linux.cs
rename to Source/OpenTK/Platform/Linux/Bindings/Libc.cs
index 2640115d..c571e6d8 100644
--- a/Source/OpenTK/Platform/Linux/Bindings/Linux.cs
+++ b/Source/OpenTK/Platform/Linux/Bindings/Libc.cs
@@ -29,22 +29,62 @@
using System;
using System.Runtime.InteropServices;
+using System.Text;
namespace OpenTK.Platform.Linux
{
- class Linux
+ class Libc
{
- [DllImport("glib", EntryPoint = "open", CallingConvention = CallingConvention.Cdecl)]
- public static extern int Open(string pathname, OpenFlags flags);
+ const string lib = "libc";
+
+ [DllImport(lib)]
+ public static extern int ioctl(int d, JoystickIoctlCode request, ref int data);
+
+ [DllImport(lib)]
+ public static extern int ioctl(int d, JoystickIoctlCode request, StringBuilder data);
+
+ [DllImport(lib)]
+ public static extern int ioctl(int d, EvdevIoctlCode request, out EvdevInputId data);
+
+ [DllImport(lib)]
+ public static extern int open([MarshalAs(UnmanagedType.LPStr)]string pathname, OpenFlags flags);
+
+ [DllImport(lib)]
+ public static extern int close(int fd);
+
+ [DllImport(lib)]
+ unsafe public static extern IntPtr read(int fd, void* buffer, UIntPtr count);
}
[Flags]
enum OpenFlags
{
- ReadOnly = 0,
- WriteOnly = 1,
- ReadWrite = 2,
- CloseOnExec = 4096
+ ReadOnly = 0x0000,
+ WriteOnly = 0x0001,
+ ReadWrite = 0x0002,
+ NonBlock = 0x0800,
+ CloseOnExec = 0x0080000
+ }
+
+ enum EvdevIoctlCode : uint
+ {
+ Id = ((byte)'E' << 8) | (0x02 << 0) //EVIOCGID, which is _IOR('E', 0x02, struct input_id)
+ }
+
+ [Flags]
+ enum JoystickEventType : byte
+ {
+ Button = 0x01, // button pressed/released
+ Axis = 0x02, // joystick moved
+ Init = 0x80 // initial state of device
+ }
+
+ enum JoystickIoctlCode : uint
+ {
+ Version = 0x80046a01,
+ Axes = 0x80016a11,
+ Buttons = 0x80016a12,
+ Name128 = (2u << 30) | (0x6A << 8) | (0x13 << 0) | (128 << 16) //JSIOCGNAME(128), which is _IOC(_IO_READ, 'j', 0x13, len)
}
[StructLayout(LayoutKind.Sequential)]
@@ -64,5 +104,21 @@ namespace OpenTK.Platform.Linux
public IntPtr mtime; /* time of last modification */
public IntPtr ctime; /* time of last status change */
}
+
+ struct EvdevInputId
+ {
+ public ushort BusType;
+ public ushort Vendor;
+ public ushort Product;
+ public ushort Version;
+ }
+
+ struct JoystickEvent
+ {
+ public uint Time; // (u32) event timestamp in milliseconds
+ public short Value; // (s16) value
+ public JoystickEventType Type; // (u8) event type
+ public byte Number; // (u8) axis/button number
+ }
}
diff --git a/Source/OpenTK/Platform/Linux/LinuxDisplayDriver.cs b/Source/OpenTK/Platform/Linux/LinuxDisplayDriver.cs
new file mode 100644
index 00000000..8feefe42
--- /dev/null
+++ b/Source/OpenTK/Platform/Linux/LinuxDisplayDriver.cs
@@ -0,0 +1,282 @@
+#region License
+//
+// LinuxDisplayDriver.cs
+//
+// Author:
+// Stefanos A.
+//
+// Copyright (c) 2006-2014 Stefanos Apostolopoulos
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using OpenTK;
+using OpenTK.Graphics;
+
+namespace OpenTK.Platform.Linux
+{
+ class LinuxDisplayDriver : DisplayDeviceBase
+ {
+ unsafe class LinuxDisplay
+ {
+ public ModeConnector* Connector;
+ public ModeEncoder* Encoder;
+ public ModeCrtc* Crtc;
+ public ModeInfo Mode
+ {
+ get
+ {
+ if (Crtc == null)
+ throw new InvalidOperationException();
+
+ return Crtc->mode;
+ }
+ }
+ public ModeInfo OriginalMode;
+
+ public int Id
+ {
+ get
+ {
+ if (Crtc == null)
+ throw new InvalidOperationException();
+
+ return (int)Crtc->crtc_id;
+ }
+ }
+
+ public LinuxDisplay(ModeConnector* c, ModeEncoder* e, ModeCrtc* r)
+ {
+ Connector = c;
+ Encoder = e;
+ Crtc = r;
+ OriginalMode = Crtc->mode; // in case we change resolution later on
+ }
+ }
+
+ readonly int FD;
+ readonly GbmDevice Device;
+ readonly Dictionary DisplayIds =
+ new Dictionary();
+
+ public LinuxDisplayDriver(int fd)
+ {
+ FD = fd;
+ QueryDisplays();
+ }
+
+ void QueryDisplays()
+ {
+ unsafe
+ {
+ lock (this)
+ {
+ AvailableDevices.Clear();
+ DisplayIds.Clear();
+
+ ModeRes* resources = (ModeRes*)Drm.ModeGetResources(FD);
+ if (resources == null)
+ {
+ throw new NotSupportedException("[KMS] DRM ModeGetResources failed");
+ }
+ Debug.Print("[KMS] DRM found {0} connectors", resources->count_connectors);
+
+ // Search for a valid connector
+ ModeConnector* connector = null;
+ for (int i = 0; i < resources->count_connectors; i++)
+ {
+ connector = (ModeConnector*)Drm.ModeGetConnector(FD,
+ *(resources->connectors + i));
+ if (connector != null)
+ {
+ if (connector->connection == ModeConnection.Connected &&
+ connector->count_modes > 0)
+ {
+ // Connector found!
+ AddDisplay(connector);
+ }
+ else
+ {
+ // This is not the display we are looking for
+ Drm.ModeFreeConnector((IntPtr)connector);
+ connector = null;
+ }
+ }
+ }
+
+ if (AvailableDevices.Count == 0)
+ {
+ Debug.Print("[KMS] Failed to find any active displays");
+ }
+ }
+ }
+ }
+
+ unsafe void AddDisplay(ModeConnector* c)
+ {
+ // Find corresponding encoder
+ ModeEncoder* encoder = null;
+ for (int i = 0; i < c->count_encoders && encoder == null; i++)
+ {
+ ModeEncoder* e = (ModeEncoder*)Drm.ModeGetEncoder(
+ FD, *(c->encoders + i));
+ if (e != null)
+ {
+ if (e->encoder_id == c->encoder_id)
+ {
+ encoder = e;
+ }
+ else
+ {
+ Drm.ModeFreeEncoder((IntPtr)e);
+ }
+ }
+ }
+
+ if (encoder != null)
+ {
+ Debug.Print("[KMS] Encoder {0} found for connector {1}",
+ encoder->encoder_id, c->connector_id);
+ }
+ else
+ {
+ Debug.Print("[KMS] Failed to find encoder for connector {0}", c->connector_id);
+ return;
+ }
+
+ ModeCrtc* crtc = (ModeCrtc*)Drm.ModeGetCrtc(FD, encoder->crtc_id);
+ if (crtc != null)
+ {
+ Debug.Print("[KMS] CRTC {0} found for encoder {1}",
+ encoder->crtc_id, encoder->encoder_id);
+ }
+ else
+ {
+ Debug.Print("[KMS] Failed to find crtc {0} for encoder {1}",
+ encoder->crtc_id, encoder->encoder_id);
+ return;
+ }
+
+ LinuxDisplay display = new LinuxDisplay(c, encoder, crtc);
+ if (!DisplayIds.ContainsKey(display.Id))
+ {
+ DisplayIds.Add(display.Id, AvailableDevices.Count);
+ }
+
+ List modes = new List();
+ for (int i = 0; i < display.Connector->count_modes; i++)
+ {
+ ModeInfo* mode = display.Connector->modes + i;
+ DisplayResolution res = GetDisplayResolution(mode);
+ modes.Add(res);
+ }
+ ModeInfo current_mode = display.Mode;
+ DisplayResolution current = GetDisplayResolution(¤t_mode);
+
+ // Note: since we are not running a display manager, we are free
+ // to choose the display layout for multiple displays ourselves.
+ // We choose the simplest layout: displays are laid out side-by-side
+ // from left to right. Primary display is the first display we encounter.
+ System.Drawing.Rectangle bounds =
+ new System.Drawing.Rectangle(
+ AvailableDevices.Count == 0 ? 0 : AvailableDevices[0].Bounds.Right,
+ 0,
+ current.Width,
+ current.Height);
+
+ DisplayDevice device = new DisplayDevice(
+ current,
+ AvailableDevices.Count == 0,
+ modes,
+ bounds,
+ display);
+
+ if (AvailableDevices.Count == 0)
+ {
+ Primary = device;
+ }
+
+ AvailableDevices.Add(device);
+ }
+
+ unsafe static DisplayResolution GetDisplayResolution(ModeInfo* mode)
+ {
+ if (mode == null)
+ throw new ArgumentNullException();
+
+ return new DisplayResolution(
+ 0, 0,
+ mode->htotal, mode->vtotal,
+ 32, // This is actually part of the framebuffer, not the DisplayResolution
+ mode->vrefresh / 1000.0f);
+ }
+
+ unsafe static ModeInfo* GetModeInfo(LinuxDisplay display, DisplayResolution resolution)
+ {
+ for (int i = 0; i < display.Connector->count_modes; i++)
+ {
+ ModeInfo* mode = display.Connector->modes + i;
+ if (mode != null &&
+ mode->htotal == resolution.Width &&
+ mode->vtotal == resolution.Height)
+ {
+ return mode;
+ }
+ }
+ return null;
+ }
+
+ #region IDisplayDeviceDriver
+
+ public override bool TryChangeResolution(DisplayDevice device, DisplayResolution resolution)
+ {
+ unsafe
+ {
+ LinuxDisplay display = (LinuxDisplay)device.Id;
+ ModeInfo* mode = GetModeInfo(display, resolution);
+ uint connector_id = display.Connector->connector_id;
+ if (mode != null)
+ {
+ return Drm.ModeSetCrtc(FD, (uint)display.Id, 0, 0, 0,
+ &connector_id, 1, mode) == 0;
+ }
+ return false;
+ }
+ }
+
+ public override bool TryRestoreResolution(DisplayDevice device)
+ {
+ unsafe
+ {
+ LinuxDisplay display = (LinuxDisplay)device.Id;
+ uint connector_id = display.Connector->connector_id;
+ ModeInfo mode = display.OriginalMode;
+ return Drm.ModeSetCrtc(FD, (uint)display.Id, 0, 0, 0,
+ &connector_id, 1, &mode) == 0;
+ }
+ }
+
+ #endregion
+ }
+}
+
diff --git a/Source/OpenTK/Platform/Linux/LinuxFactory.cs b/Source/OpenTK/Platform/Linux/LinuxFactory.cs
index f998a071..f8b1096d 100644
--- a/Source/OpenTK/Platform/Linux/LinuxFactory.cs
+++ b/Source/OpenTK/Platform/Linux/LinuxFactory.cs
@@ -32,70 +32,93 @@ using System.Diagnostics;
using System.Runtime.InteropServices;
using OpenTK.Graphics;
using OpenTK.Input;
+using OpenTK.Platform.Egl;
namespace OpenTK.Platform.Linux
{
+ using Egl = OpenTK.Platform.Egl.Egl;
+
// Linux KMS platform
class LinuxFactory : PlatformFactoryBase
{
int fd;
- GbmDevice device;
+ GbmDevice gbm_device;
IntPtr display;
+ IJoystickDriver2 JoystickDriver;
+ IDisplayDeviceDriver DisplayDriver;
+
public LinuxFactory()
+ {
+ SetupEgl();
+ }
+
+ #region Private Members
+
+ void SetupEgl()
{
// Todo: support multi-GPU systems
string gpu = "/dev/dri/card0";
- fd = Linux.Open(gpu, OpenFlags.ReadOnly | OpenFlags.CloseOnExec);
+ fd = Libc.open(gpu, OpenFlags.ReadWrite | OpenFlags.CloseOnExec);
if (fd < 0)
{
- throw new NotSupportedException("No KMS-capable GPU available");
+ throw new NotSupportedException("[KMS] No KMS-capable GPU available");
}
- Debug.Print("GPU {0} opened as fd:{1}", gpu, fd);
+ Debug.Print("[KMS] GPU '{0}' opened as fd:{1}", gpu, fd);
IntPtr dev = Gbm.CreateDevice(fd);
if (dev == IntPtr.Zero)
{
- throw new NotSupportedException("Failed to create GBM device");
+ throw new NotSupportedException("[KMS] Failed to create GBM device");
}
- device = (GbmDevice)Marshal.PtrToStructure(dev, typeof(GbmDevice));
- Debug.Print("GBM {0:x} '{1}' created successfully",
- dev, Marshal.PtrToStringAnsi(device.name));
+ gbm_device = (GbmDevice)Marshal.PtrToStructure(dev, typeof(GbmDevice));
+ Debug.Print("[KMS] GBM {0:x} created successfully", dev);
- display = Egl.Egl.GetDisplay(dev);
+ display = Egl.GetDisplay(dev);
if (display == IntPtr.Zero)
{
- throw new NotSupportedException("Failed to create EGL display");
+ throw new NotSupportedException("[KMS] Failed to create EGL display");
}
- Debug.Print("EGL display {0:x} created successfully", display);
+ Debug.Print("[KMS] EGL display {0:x} created successfully", display);
int major, minor;
- if (!Egl.Egl.Initialize(display, out major, out minor))
+ if (!Egl.Initialize(display, out major, out minor))
{
- int error = Egl.Egl.GetError();
- throw new NotSupportedException("Failed to initialize EGL display. Error code: " + error);
+ int error = Egl.GetError();
+ throw new NotSupportedException("[KMS] Failed to initialize EGL display. Error code: " + error);
}
- Debug.Print("EGL {0}.{1} initialized successfully on display {2:x}", major, minor, display);
+ Debug.Print("[KMS] EGL {0}.{1} initialized successfully on display {2:x}", major, minor, display);
}
- public override INativeWindow CreateNativeWindow(int x, int y, int width, int height, string title, GraphicsMode mode, GameWindowFlags options, DisplayDevice device)
+ #endregion
+
+ #region IPlatformFactory Members
+
+ public override INativeWindow CreateNativeWindow(int x, int y, int width, int height, string title, GraphicsMode mode, GameWindowFlags options, DisplayDevice display_device)
{
- return new LinuxNativeWindow(x, y, width, height, title, mode, options, device);
+ return new LinuxNativeWindow(display, gbm_device, width, height, title, mode, options, display_device);
}
public override IDisplayDeviceDriver CreateDisplayDeviceDriver()
{
- throw new NotImplementedException();
+ lock (this)
+ {
+ DisplayDriver = DisplayDriver ?? new LinuxDisplayDriver(fd);
+ return DisplayDriver;
+ }
}
public override IGraphicsContext CreateGLContext(GraphicsMode mode, IWindowInfo window, IGraphicsContext shareContext, bool directRendering, int major, int minor, GraphicsContextFlags flags)
{
- throw new NotImplementedException();
+ return new EglUnixContext(mode, (EglWindowInfo)window, shareContext, major, minor, flags);
}
public override GraphicsContext.GetCurrentContextDelegate CreateGetCurrentGraphicsContext()
{
- throw new NotImplementedException();
+ return (GraphicsContext.GetCurrentContextDelegate)delegate
+ {
+ return new ContextHandle(Egl.GetCurrentContext());
+ };
}
public override IKeyboardDriver2 CreateKeyboardDriver()
@@ -110,8 +133,14 @@ namespace OpenTK.Platform.Linux
public override IJoystickDriver2 CreateJoystickDriver()
{
- throw new NotImplementedException();
+ lock (this)
+ {
+ JoystickDriver = JoystickDriver ?? new LinuxJoystick();
+ return JoystickDriver;
+ }
}
+
+ #endregion
}
}
diff --git a/Source/OpenTK/Platform/X11/X11Joystick.cs b/Source/OpenTK/Platform/Linux/LinuxJoystick.cs
similarity index 75%
rename from Source/OpenTK/Platform/X11/X11Joystick.cs
rename to Source/OpenTK/Platform/Linux/LinuxJoystick.cs
index 4b3fdc8c..51992797 100644
--- a/Source/OpenTK/Platform/X11/X11Joystick.cs
+++ b/Source/OpenTK/Platform/Linux/LinuxJoystick.cs
@@ -33,9 +33,9 @@ using System.Runtime.InteropServices;
using System.Text;
using OpenTK.Input;
-namespace OpenTK.Platform.X11
+namespace OpenTK.Platform.Linux
{
- struct X11JoyDetails
+ struct LinuxJoyDetails
{
public Guid Guid;
public int FileDescriptor;
@@ -43,7 +43,7 @@ namespace OpenTK.Platform.X11
}
// Note: despite what the name says, this class is Linux-specific.
- sealed class X11Joystick : IJoystickDriver2
+ sealed class LinuxJoystick : IJoystickDriver2
{
#region Fields
@@ -52,7 +52,7 @@ namespace OpenTK.Platform.X11
readonly FileSystemWatcher watcher = new FileSystemWatcher();
readonly Dictionary index_to_stick = new Dictionary();
- List> sticks = new List>();
+ List> sticks = new List>();
bool disposed;
@@ -60,7 +60,7 @@ namespace OpenTK.Platform.X11
#region Constructors
- public X11Joystick()
+ public LinuxJoystick()
{
string path =
Directory.Exists(JoystickPath) ? JoystickPath :
@@ -89,7 +89,7 @@ namespace OpenTK.Platform.X11
{
foreach (string file in Directory.GetFiles(path))
{
- JoystickDevice stick = OpenJoystick(file);
+ JoystickDevice stick = OpenJoystick(file);
if (stick != null)
{
//stick.Description = String.Format("USB Joystick {0} ({1} axes, {2} buttons, {3}{0})",
@@ -155,7 +155,7 @@ namespace OpenTK.Platform.X11
#region Private Members
- Guid CreateGuid(JoystickDevice js, string path, int number)
+ Guid CreateGuid(JoystickDevice js, string path, int number)
{
byte[] bytes = new byte[16];
for (int i = 0; i < Math.Min(bytes.Length, js.Description.Length); i++)
@@ -221,9 +221,9 @@ namespace OpenTK.Platform.X11
#endif
}
- JoystickDevice OpenJoystick(string path)
+ JoystickDevice OpenJoystick(string path)
{
- JoystickDevice stick = null;
+ JoystickDevice stick = null;
int number = GetJoystickNumber(Path.GetFileName(path));
if (number >= 0)
@@ -231,28 +231,28 @@ namespace OpenTK.Platform.X11
int fd = -1;
try
{
- fd = UnsafeNativeMethods.open(path, OpenFlags.NonBlock);
+ fd = Libc.open(path, OpenFlags.NonBlock);
if (fd == -1)
return null;
// Check joystick driver version (must be 1.0+)
int driver_version = 0x00000800;
- UnsafeNativeMethods.ioctl(fd, JoystickIoctlCode.Version, ref driver_version);
+ Libc.ioctl(fd, JoystickIoctlCode.Version, ref driver_version);
if (driver_version < 0x00010000)
return null;
// Get number of joystick axes
int axes = 0;
- UnsafeNativeMethods.ioctl(fd, JoystickIoctlCode.Axes, ref axes);
+ Libc.ioctl(fd, JoystickIoctlCode.Axes, ref axes);
// Get number of joystick buttons
int buttons = 0;
- UnsafeNativeMethods.ioctl(fd, JoystickIoctlCode.Buttons, ref buttons);
+ Libc.ioctl(fd, JoystickIoctlCode.Buttons, ref buttons);
- stick = new JoystickDevice(number, axes, buttons);
+ stick = new JoystickDevice(number, axes, buttons);
StringBuilder sb = new StringBuilder(128);
- UnsafeNativeMethods.ioctl(fd, JoystickIoctlCode.Name128, sb);
+ Libc.ioctl(fd, JoystickIoctlCode.Name128, sb);
stick.Description = sb.ToString();
stick.Details.FileDescriptor = fd;
@@ -287,16 +287,16 @@ namespace OpenTK.Platform.X11
finally
{
if (stick == null && fd != -1)
- UnsafeNativeMethods.close(fd);
+ Libc.close(fd);
}
}
return stick;
}
- void CloseJoystick(JoystickDevice js)
+ void CloseJoystick(JoystickDevice js)
{
- UnsafeNativeMethods.close(js.Details.FileDescriptor);
+ Libc.close(js.Details.FileDescriptor);
js.Details.State = new JoystickState(); // clear joystick state
js.Details.FileDescriptor = -1;
@@ -317,13 +317,13 @@ namespace OpenTK.Platform.X11
}
}
- void PollJoystick(JoystickDevice js)
+ void PollJoystick(JoystickDevice js)
{
JoystickEvent e;
unsafe
{
- while ((long)UnsafeNativeMethods.read(js.Details.FileDescriptor, (void*)&e, (UIntPtr)sizeof(JoystickEvent)) > 0)
+ while ((long)Libc.read(js.Details.FileDescriptor, (void*)&e, (UIntPtr)sizeof(JoystickEvent)) > 0)
{
e.Type &= ~JoystickEventType.Init;
@@ -352,78 +352,9 @@ namespace OpenTK.Platform.X11
return index_to_stick.ContainsKey(index);
}
- #region UnsafeNativeMethods
-
- struct EvdevInputId
- {
- public ushort BusType;
- public ushort Vendor;
- public ushort Product;
- public ushort Version;
- }
-
- enum EvdevIoctlCode : uint
- {
- Id = ((byte)'E' << 8) | (0x02 << 0) //EVIOCGID, which is _IOR('E', 0x02, struct input_id)
- }
-
-
- struct JoystickEvent
- {
- public uint Time; // (u32) event timestamp in milliseconds
- public short Value; // (s16) value
- public JoystickEventType Type; // (u8) event type
- public byte Number; // (u8) axis/button number
- }
-
- [Flags]
- enum JoystickEventType : byte
- {
- Button = 0x01, // button pressed/released
- Axis = 0x02, // joystick moved
- Init = 0x80 // initial state of device
- }
-
- enum JoystickIoctlCode : uint
- {
- Version = 0x80046a01,
- Axes = 0x80016a11,
- Buttons = 0x80016a12,
- Name128 = (2u << 30) | (0x6A << 8) | (0x13 << 0) | (128 << 16) //JSIOCGNAME(128), which is _IOC(_IO_READ, 'j', 0x13, len)
- }
-
static readonly string JoystickPath = "/dev/input";
static readonly string JoystickPathLegacy = "/dev";
- [Flags]
- enum OpenFlags
- {
- NonBlock = 0x00000800
- }
-
- static class UnsafeNativeMethods
- {
- [DllImport("libc", SetLastError = true)]
- public static extern int ioctl(int d, JoystickIoctlCode request, ref int data);
-
- [DllImport("libc", SetLastError = true)]
- public static extern int ioctl(int d, JoystickIoctlCode request, StringBuilder data);
-
- [DllImport("libc", SetLastError = true)]
- public static extern int ioctl(int d, EvdevIoctlCode request, out EvdevInputId data);
-
- [DllImport("libc", SetLastError = true)]
- public static extern int open([MarshalAs(UnmanagedType.LPStr)]string pathname, OpenFlags flags);
-
- [DllImport("libc", SetLastError = true)]
- public static extern int close(int fd);
-
- [DllImport("libc", SetLastError = true)]
- unsafe public static extern IntPtr read(int fd, void* buffer, UIntPtr count);
- }
-
- #endregion
-
#endregion
#region IDisposable Members
@@ -443,7 +374,7 @@ namespace OpenTK.Platform.X11
}
watcher.Dispose();
- foreach (JoystickDevice js in sticks)
+ foreach (JoystickDevice js in sticks)
{
CloseJoystick(js);
}
@@ -452,7 +383,7 @@ namespace OpenTK.Platform.X11
}
}
- ~X11Joystick()
+ ~LinuxJoystick()
{
Dispose(false);
}
@@ -465,7 +396,7 @@ namespace OpenTK.Platform.X11
{
if (IsValid(index))
{
- JoystickDevice js =
+ JoystickDevice js =
sticks[index_to_stick[index]];
PollJoystick(js);
return js.Details.State;
@@ -478,7 +409,7 @@ namespace OpenTK.Platform.X11
JoystickCapabilities caps = new JoystickCapabilities();
if (IsValid(index))
{
- JoystickDevice js = sticks[index_to_stick[index]];
+ JoystickDevice js = sticks[index_to_stick[index]];
caps = new JoystickCapabilities(
js.Axis.Count,
js.Button.Count,
@@ -492,7 +423,7 @@ namespace OpenTK.Platform.X11
{
if (IsValid(index))
{
- JoystickDevice js = sticks[index_to_stick[index]];
+ JoystickDevice js = sticks[index_to_stick[index]];
return js.Details.Guid;
}
return new Guid();
diff --git a/Source/OpenTK/Platform/Linux/LinuxNativeWindow.cs b/Source/OpenTK/Platform/Linux/LinuxNativeWindow.cs
index a44cb9bb..6d926923 100644
--- a/Source/OpenTK/Platform/Linux/LinuxNativeWindow.cs
+++ b/Source/OpenTK/Platform/Linux/LinuxNativeWindow.cs
@@ -28,42 +28,74 @@
#endregion
using System;
+using System.Drawing;
+using OpenTK.Graphics;
+using OpenTK.Platform.Egl;
namespace OpenTK.Platform.Linux
{
+ using Egl = OpenTK.Platform.Egl.Egl;
+
class LinuxNativeWindow : NativeWindowBase
{
+ LinuxWindowInfo window_info;
+ string title;
+ Icon icon;
+ bool exists;
+ Rectangle bounds;
+ Size client_size;
+
+ public LinuxNativeWindow(IntPtr display, GbmDevice device,
+ int width, int height, string title, GraphicsMode mode, GameWindowFlags options,
+ DisplayDevice display_device)
+ {
+ Title = title;
+ bounds = new Rectangle(0, 0, width, height);
+ client_size = bounds.Size;
+
+ //window_info = new LinuxWindowInfo(
+ // Egl.CreateWindowSurface(
+
+ exists = true;
+ }
+
#region INativeWindow Members
public override void Close()
{
- throw new NotImplementedException();
+ exists = false;
}
- public override System.Drawing.Point PointToClient(System.Drawing.Point point)
+ public override Point PointToClient(Point point)
{
- throw new NotImplementedException();
+ // Todo
+ return point;
}
- public override System.Drawing.Point PointToScreen(System.Drawing.Point point)
+ public override Point PointToScreen(Point point)
{
- throw new NotImplementedException();
+ // Todo
+ return point;
}
protected override void Dispose(bool disposing)
{
- throw new NotImplementedException();
+ // Todo
}
- public override System.Drawing.Icon Icon
+ public override Icon Icon
{
get
{
- throw new NotImplementedException();
+ return icon;
}
set
{
- throw new NotImplementedException();
+ if (icon != value)
+ {
+ icon = value;
+ OnIconChanged(EventArgs.Empty);
+ }
}
}
@@ -71,11 +103,15 @@ namespace OpenTK.Platform.Linux
{
get
{
- throw new NotImplementedException();
+ return title;
}
set
{
- throw new NotImplementedException();
+ if (title != value)
+ {
+ title = value;
+ OnTitleChanged(EventArgs.Empty);
+ }
}
}
@@ -83,7 +119,7 @@ namespace OpenTK.Platform.Linux
{
get
{
- throw new NotImplementedException();
+ return true;
}
}
@@ -91,11 +127,10 @@ namespace OpenTK.Platform.Linux
{
get
{
- throw new NotImplementedException();
+ return true;
}
set
{
- throw new NotImplementedException();
}
}
@@ -103,7 +138,7 @@ namespace OpenTK.Platform.Linux
{
get
{
- throw new NotImplementedException();
+ return exists;
}
}
@@ -111,7 +146,7 @@ namespace OpenTK.Platform.Linux
{
get
{
- throw new NotImplementedException();
+ return window_info;
}
}
@@ -119,11 +154,10 @@ namespace OpenTK.Platform.Linux
{
get
{
- throw new NotImplementedException();
+ return WindowState.Fullscreen;
}
set
{
- throw new NotImplementedException();
}
}
@@ -131,35 +165,32 @@ namespace OpenTK.Platform.Linux
{
get
{
- throw new NotImplementedException();
+ return WindowBorder.Hidden;
}
set
{
- throw new NotImplementedException();
}
}
- public override System.Drawing.Rectangle Bounds
+ public override Rectangle Bounds
{
get
{
- throw new NotImplementedException();
+ return bounds;
}
set
{
- throw new NotImplementedException();
}
}
- public override System.Drawing.Size ClientSize
+ public override Size ClientSize
{
get
{
- throw new NotImplementedException();
+ return client_size;
}
set
{
- throw new NotImplementedException();
}
}
@@ -167,11 +198,10 @@ namespace OpenTK.Platform.Linux
{
get
{
- throw new NotImplementedException();
+ return false;
}
set
{
- throw new NotImplementedException();
}
}
@@ -179,18 +209,14 @@ namespace OpenTK.Platform.Linux
{
get
{
- throw new NotImplementedException();
+ return MouseCursor.Empty;
}
set
{
- throw new NotImplementedException();
}
}
#endregion
-
-
-
}
}
diff --git a/Source/OpenTK/Platform/Linux/LinuxWindowInfo.cs b/Source/OpenTK/Platform/Linux/LinuxWindowInfo.cs
new file mode 100644
index 00000000..df564285
--- /dev/null
+++ b/Source/OpenTK/Platform/Linux/LinuxWindowInfo.cs
@@ -0,0 +1,43 @@
+#region License
+//
+// LinuxWindowInfo.cs
+//
+// Author:
+// Stefanos A.
+//
+// Copyright (c) 2006-2014 Stefanos Apostolopoulos
+//
+// 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 OpenTK.Platform.Egl;
+
+namespace OpenTK.Platform.Linux
+{
+ class LinuxWindowInfo : EglWindowInfo
+ {
+ public LinuxWindowInfo(IntPtr handle, IntPtr display, IntPtr surface)
+ : base(handle, display, surface)
+ {
+ }
+ }
+}
+
diff --git a/Source/OpenTK/Platform/X11/X11Input.cs b/Source/OpenTK/Platform/X11/X11Input.cs
index 50bdf4a3..246501c7 100644
--- a/Source/OpenTK/Platform/X11/X11Input.cs
+++ b/Source/OpenTK/Platform/X11/X11Input.cs
@@ -37,7 +37,7 @@ namespace OpenTK.Platform.X11
{
readonly X11Mouse mouse = new X11Mouse();
readonly X11Keyboard keyboard = new X11Keyboard();
- readonly X11Joystick joystick = new X11Joystick();
+ readonly Linux.LinuxJoystick joystick = new Linux.LinuxJoystick();
readonly IGamePadDriver gamepad = new MappedGamePadDriver();
internal X11Input()
diff --git a/Source/OpenTK/Platform/X11/XI2Input.cs b/Source/OpenTK/Platform/X11/XI2Input.cs
index c2e8528e..d91d2c07 100644
--- a/Source/OpenTK/Platform/X11/XI2Input.cs
+++ b/Source/OpenTK/Platform/X11/XI2Input.cs
@@ -36,7 +36,7 @@ namespace OpenTK.Platform.X11
class XI2Input : IInputDriver2
{
readonly XI2MouseKeyboard mouse_keyboard = new XI2MouseKeyboard();
- readonly X11Joystick joystick = new X11Joystick();
+ readonly Linux.LinuxJoystick joystick = new Linux.LinuxJoystick();
readonly IGamePadDriver gamepad = new MappedGamePadDriver();
internal XI2Input()