]> O.S.I.I.S - jp/crow.git/commitdiff
first tests with KMS, Mono.Cairo is embeded
authorjpbruyere <jp.bruyere@hotmail.com>
Sat, 6 May 2017 07:52:22 +0000 (09:52 +0200)
committerjpbruyere <jp.bruyere@hotmail.com>
Sat, 6 May 2017 07:52:22 +0000 (09:52 +0200)
97 files changed:
Crow.sln
Tests/BasicTests.cs
Tests/CrowWindow.cs
Tests/OpenGL/Shader.cs
Tests/Tests.csproj
Tests/test.cs [new file with mode: 0644]
src/GraphicObjects/GraphicObject.cs
src/GraphicObjects/Group.cs
src/GraphicObjects/Popper.cs
src/GraphicObjects/ScrollBar.cs
src/Input/Buttons.cs
src/XCursor.cs
testDrm/Main.cs [new file with mode: 0644]
testDrm/Mono.Cairo/Antialias.cs [new file with mode: 0644]
testDrm/Mono.Cairo/Cairo.cs [new file with mode: 0644]
testDrm/Mono.Cairo/CairoDebug.cs [new file with mode: 0644]
testDrm/Mono.Cairo/Color.cs [new file with mode: 0644]
testDrm/Mono.Cairo/Content.cs [new file with mode: 0644]
testDrm/Mono.Cairo/Context.cs [new file with mode: 0644]
testDrm/Mono.Cairo/Device.cs [new file with mode: 0644]
testDrm/Mono.Cairo/DirectFBSurface.cs [new file with mode: 0644]
testDrm/Mono.Cairo/Distance.cs [new file with mode: 0644]
testDrm/Mono.Cairo/EGLDevice.cs [new file with mode: 0644]
testDrm/Mono.Cairo/Extend.cs [new file with mode: 0644]
testDrm/Mono.Cairo/FillRule.cs [new file with mode: 0644]
testDrm/Mono.Cairo/Filter.cs [new file with mode: 0644]
testDrm/Mono.Cairo/FontExtents.cs [new file with mode: 0644]
testDrm/Mono.Cairo/FontFace.cs [new file with mode: 0644]
testDrm/Mono.Cairo/FontOptions.cs [new file with mode: 0644]
testDrm/Mono.Cairo/FontSlant.cs [new file with mode: 0644]
testDrm/Mono.Cairo/FontType.cs [new file with mode: 0644]
testDrm/Mono.Cairo/FontWeight.cs [new file with mode: 0644]
testDrm/Mono.Cairo/Format.cs [new file with mode: 0644]
testDrm/Mono.Cairo/GLSurface.cs [new file with mode: 0644]
testDrm/Mono.Cairo/GLXDevice.cs [new file with mode: 0644]
testDrm/Mono.Cairo/GlitzSurface.cs [new file with mode: 0644]
testDrm/Mono.Cairo/Glyph.cs [new file with mode: 0644]
testDrm/Mono.Cairo/Gradient.cs [new file with mode: 0644]
testDrm/Mono.Cairo/HintMetrics.cs [new file with mode: 0644]
testDrm/Mono.Cairo/HintStyle.cs [new file with mode: 0644]
testDrm/Mono.Cairo/ImageSurface.cs [new file with mode: 0644]
testDrm/Mono.Cairo/LineCap.cs [new file with mode: 0644]
testDrm/Mono.Cairo/LineJoin.cs [new file with mode: 0644]
testDrm/Mono.Cairo/LinearGradient.cs [new file with mode: 0644]
testDrm/Mono.Cairo/Matrix.cs [new file with mode: 0644]
testDrm/Mono.Cairo/NativeMethods.cs [new file with mode: 0644]
testDrm/Mono.Cairo/Operator.cs [new file with mode: 0644]
testDrm/Mono.Cairo/PSSurface.cs [new file with mode: 0644]
testDrm/Mono.Cairo/Path.cs [new file with mode: 0644]
testDrm/Mono.Cairo/Pattern.cs [new file with mode: 0644]
testDrm/Mono.Cairo/PatternType.cs [new file with mode: 0644]
testDrm/Mono.Cairo/PdfSurface.cs [new file with mode: 0644]
testDrm/Mono.Cairo/Point.cs [new file with mode: 0644]
testDrm/Mono.Cairo/PointD.cs [new file with mode: 0644]
testDrm/Mono.Cairo/RadialGradient.cs [new file with mode: 0644]
testDrm/Mono.Cairo/Rectangle.cs [new file with mode: 0644]
testDrm/Mono.Cairo/Region.cs [new file with mode: 0644]
testDrm/Mono.Cairo/ScaledFont.cs [new file with mode: 0644]
testDrm/Mono.Cairo/SolidPattern.cs [new file with mode: 0644]
testDrm/Mono.Cairo/Status.cs [new file with mode: 0644]
testDrm/Mono.Cairo/SubpixelOrder.cs [new file with mode: 0644]
testDrm/Mono.Cairo/Surface.cs [new file with mode: 0644]
testDrm/Mono.Cairo/SurfacePattern.cs [new file with mode: 0644]
testDrm/Mono.Cairo/SurfaceType.cs [new file with mode: 0644]
testDrm/Mono.Cairo/SvgSurface.cs [new file with mode: 0644]
testDrm/Mono.Cairo/SvgVersion.cs [new file with mode: 0644]
testDrm/Mono.Cairo/TextExtents.cs [new file with mode: 0644]
testDrm/Mono.Cairo/WGLDevice.cs [new file with mode: 0644]
testDrm/Mono.Cairo/Win32Surface.cs [new file with mode: 0644]
testDrm/Mono.Cairo/XcbSurface.cs [new file with mode: 0644]
testDrm/Mono.Cairo/XlibSurface.cs [new file with mode: 0644]
testDrm/src/BlittableValueType.cs [new file with mode: 0644]
testDrm/src/DisplayDevice.cs [new file with mode: 0644]
testDrm/src/DisplayResolution.cs [new file with mode: 0644]
testDrm/src/DrmDevice.cs [new file with mode: 0644]
testDrm/src/Egl.cs [new file with mode: 0644]
testDrm/src/Linux/Bindings/Drm.cs [new file with mode: 0644]
testDrm/src/Linux/Bindings/Evdev.cs [new file with mode: 0644]
testDrm/src/Linux/Bindings/Gbm.cs [new file with mode: 0644]
testDrm/src/Linux/Bindings/Kms.cs [new file with mode: 0644]
testDrm/src/Linux/Bindings/LibInput.cs [new file with mode: 0644]
testDrm/src/Linux/Bindings/Libc.cs [new file with mode: 0644]
testDrm/src/Linux/Bindings/Poll.cs [new file with mode: 0644]
testDrm/src/Linux/Bindings/Terminal.cs [new file with mode: 0644]
testDrm/src/Linux/Bindings/Udev.cs [new file with mode: 0644]
testDrm/src/Linux/DefaultCursor.cs [new file with mode: 0644]
testDrm/src/Linux/LinuxDisplayDriver.cs [new file with mode: 0644]
testDrm/src/Linux/LinuxFactory.cs [new file with mode: 0644]
testDrm/src/Linux/LinuxGraphicsContext.cs [new file with mode: 0644]
testDrm/src/Linux/LinuxInput.cs [new file with mode: 0644]
testDrm/src/Linux/LinuxJoystick.cs [new file with mode: 0644]
testDrm/src/Linux/LinuxKeyboardTTY.cs [new file with mode: 0644]
testDrm/src/Linux/LinuxNativeWindow.cs [new file with mode: 0644]
testDrm/src/Linux/LinuxWindowInfo.cs [new file with mode: 0644]
testDrm/src/MouseCursor.cs [new file with mode: 0644]
testDrm/src/WindowIcon.cs [new file with mode: 0644]
testDrm/testDrm.csproj [new file with mode: 0644]

index ba1b6741b6a2d5bc901c956b1837cf9c96a33e1a..9edb890b302137b2404c0f244f50fe6f411404d7 100644 (file)
--- a/Crow.sln
+++ b/Crow.sln
@@ -7,16 +7,26 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests", "Tests\Tests.csproj
 EndProject
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CrowIDE", "CrowIDE\CrowIDE.csproj", "{B6D911CD-1D09-42FC-B300-9187190F2AE1}"
 EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenTK", "..\..\src\opentk-git\src\OpenTK\OpenTK.csproj", "{A37A7E14-0000-0000-0000-000000000000}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "testDrm", "testDrm\testDrm.csproj", "{4B57740A-75FB-4978-A8E8-8B1793B7474F}"
+EndProject
 Global
        GlobalSection(SolutionConfigurationPlatforms) = preSolution
                Debug|Any CPU = Debug|Any CPU
                Release|Any CPU = Release|Any CPU
        EndGlobalSection
        GlobalSection(ProjectConfigurationPlatforms) = postSolution
+               {4B57740A-75FB-4978-A8E8-8B1793B7474F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+               {4B57740A-75FB-4978-A8E8-8B1793B7474F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+               {4B57740A-75FB-4978-A8E8-8B1793B7474F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+               {4B57740A-75FB-4978-A8E8-8B1793B7474F}.Release|Any CPU.Build.0 = Release|Any CPU
                {74289092-9F70-4941-AFCB-DFD7BE2140B6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
                {74289092-9F70-4941-AFCB-DFD7BE2140B6}.Debug|Any CPU.Build.0 = Debug|Any CPU
                {74289092-9F70-4941-AFCB-DFD7BE2140B6}.Release|Any CPU.ActiveCfg = Release|Any CPU
                {74289092-9F70-4941-AFCB-DFD7BE2140B6}.Release|Any CPU.Build.0 = Release|Any CPU
+               {A37A7E14-0000-0000-0000-000000000000}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+               {A37A7E14-0000-0000-0000-000000000000}.Release|Any CPU.ActiveCfg = Release|Any CPU
                {B6D911CD-1D09-42FC-B300-9187190F2AE1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
                {B6D911CD-1D09-42FC-B300-9187190F2AE1}.Debug|Any CPU.Build.0 = Debug|Any CPU
                {B6D911CD-1D09-42FC-B300-9187190F2AE1}.Release|Any CPU.ActiveCfg = Release|Any CPU
index 3e8bb71678494979d06967103fd2c1860ea36c13..44c33fd3c9545d62bc615400ecfcb6a9488a4472 100644 (file)
@@ -39,7 +39,7 @@ namespace Tests
        class BasicTests : CrowWindow
        {
                public BasicTests ()
-                       : base(800, 600,"test: press <F3> to toogle test files")
+                       : base(1600, 900,"test: press <F3> to toogle test files")
                {
                }
 
index b1308d1eae512b231f69d02f8562e28f9a135f92..c5a544ac48f7b3622985e394b268064fd9a974da 100644 (file)
@@ -89,7 +89,7 @@ namespace Crow
                #endregion
 
                #region ctor
-               public CrowWindow(int _width = 800, int _height = 600, string _title="Crow",
+               public CrowWindow(int _width = 1600, int _height = 900, string _title="Crow",
                        int colors = 32, int depth = 24, int stencil = 0, int samples = 1,
                        int major=3, int minor=3)
                        : this(_width, _height, new OpenTK.Graphics.GraphicsMode(colors, depth, stencil, samples),
index 6ae99b8910b3d47d6f94d8114176df738982ef8e..e77230d87f3738b681b42b3a50d3e79743e64c70 100644 (file)
@@ -51,7 +51,7 @@ namespace Crow
                                                GeomSourcePath;
                #region Sources
                protected string _vertSource = @"
-                       #version 330
+                       #version 300 es
                        precision lowp float;
 
                        uniform mat4 mvp;
@@ -68,7 +68,7 @@ namespace Crow
                        }";
 
                protected string _fragSource = @"
-                       #version 330
+                       #version 300 es
                        precision lowp float;
 
                        uniform sampler2D tex;
@@ -209,8 +209,8 @@ namespace Crow
                        GL.GetProgramInfoLog(pgmId, out info);
 
                        if (!string.IsNullOrEmpty (info)) {
-                               Debug.WriteLine ("Linkage:");
-                               Debug.WriteLine (info);
+                               Console.WriteLine ("Linkage:");
+                               Console.WriteLine (info);
                        }
 
                        info = null;
@@ -218,8 +218,8 @@ namespace Crow
                        GL.ValidateProgram(pgmId);
                        GL.GetProgramInfoLog(pgmId, out info);
                        if (!string.IsNullOrEmpty (info)) {
-                               Debug.WriteLine ("Validation:");
-                               Debug.WriteLine (info);
+                               Console.WriteLine ("Validation:");
+                               Console.WriteLine (info);
                        }
 
                        GL.UseProgram (pgmId);
@@ -302,14 +302,14 @@ namespace Crow
 
                        string info;
                        GL.GetShaderInfoLog(shader, out info);
-                       Debug.WriteLine(info);
+                       Console.WriteLine(info);
 
                        int compileResult;
                        GL.GetShader(shader, ShaderParameter.CompileStatus, out compileResult);
                        if (compileResult != 1)
                        {
-                               Debug.WriteLine("Compile Error!");
-                               Debug.WriteLine(source);
+                               Console.WriteLine("Compile Error!");
+                               Console.WriteLine(source);
                        }
                }
                public override string ToString ()
index 16c851a3d5094c57cce45451b47bb1af3496ea7a..04344a40e3b76949110f59e29e198d9b3d088f6f 100644 (file)
@@ -8,7 +8,7 @@
     <OutputType>Exe</OutputType>
     <RootNamespace>Tests</RootNamespace>
     <AssemblyName>Tests</AssemblyName>
-    <StartupObject>Tests.Showcase</StartupObject>
+    <StartupObject>Tests.BasicTests</StartupObject>
     <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
     <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
     <ReleaseVersion>0.5</ReleaseVersion>
     <WarningLevel>4</WarningLevel>
     <ConsolePause>false</ConsolePause>
     <DefineConstants>DEBUG;TRACE;MEASURE_TIME</DefineConstants>
+    <IntermediateOutputPath>$(SolutionDir)build\obj\$(Configuration)</IntermediateOutputPath>
+    <OutputPath>$(SolutionDir)build\$(Configuration)</OutputPath>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
     <DebugType>none</DebugType>
     <Optimize>true</Optimize>
     <WarningLevel>0</WarningLevel>
     <ConsolePause>false</ConsolePause>
+    <IntermediateOutputPath>$(SolutionDir)build\obj\$(Configuration)</IntermediateOutputPath>
+    <OutputPath>$(SolutionDir)build\$(Configuration)</OutputPath>
   </PropertyGroup>
   <ItemGroup>
     <Reference Include="System" />
@@ -43,9 +47,8 @@
     <Reference Include="cairo-sharp">
       <Package>gtk-sharp-3.0</Package>
     </Reference>
-    <Reference Include="OpenTK">
-      <HintPath>$(SolutionDir)packages\OpenTK.2.0.0\lib\net20\OpenTK.dll</HintPath>
-      <Package>opentk</Package>
+    <Reference Include="OpenTK, Version=2.0.6332.25999, Culture=neutral, PublicKeyToken=bad199fe84eb3df4">
+      <HintPath>..\..\..\src\opentk-git\src\OpenTK\bin\Release\OpenTK.dll</HintPath>
     </Reference>
   </ItemGroup>
   <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
diff --git a/Tests/test.cs b/Tests/test.cs
new file mode 100644 (file)
index 0000000..436fa67
--- /dev/null
@@ -0,0 +1,81 @@
+//
+// HelloWorld.cs
+//
+// Author:
+//       Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
+//
+// Copyright (c) 2013-2017 Jean-Philippe Bruyère
+//
+// 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.
+
+using System;
+using Crow;
+using Cairo;
+using System.Diagnostics;
+
+namespace Tests2
+{
+       static class Test
+       {
+               const int H = 600;
+               const int W = 800;
+               [STAThread]
+               static void Main ()
+               {
+                       Console.WriteLine ("Single Surface Instance");
+                       Stopwatch sw = Stopwatch.StartNew ();
+                       Surface surf = new ImageSurface (Format.Argb32, W, H);
+                       for (int i = 0; i < 1000; i++) {
+                               using (Context ctx = new Context (surf)) {
+                                       clearSurf (ctx);
+                                       ctx.Rectangle (50, 50, 50, 50);
+                                       ctx.SetSourceRGB (1, 0, 0);
+                                       ctx.Fill ();
+                               }
+                       }
+                       sw.Stop ();
+                       Console.WriteLine ("elapse: {0} ticks, {1} ms", sw.ElapsedTicks, sw.ElapsedMilliseconds);
+
+                       Console.WriteLine ("Multiple Surface Instances");
+                       sw = Stopwatch.StartNew ();
+                       for (int i = 0; i < 1000; i++) {
+                               byte[] bmp = new byte[W * H * 4];
+                               using (Surface s = new ImageSurface (bmp, Format.Argb32, W, H, W * 4)){
+                                       using (Context ctx = new Context (s)) {
+                                               //clearSurf (ctx);
+                                               ctx.Rectangle (50, 50, 50, 50);
+                                               ctx.SetSourceRGB (1, 0, 0);
+                                               ctx.Fill ();
+                                       }
+                               }
+                       }
+                       sw.Stop ();
+                       Console.WriteLine ("elapse: {0} ticks, {1} ms", sw.ElapsedTicks, sw.ElapsedMilliseconds);
+
+               }
+
+               static void clearSurf(Context ctx){
+                       ctx.Operator = Operator.Clear;
+                       ctx.SetSourceRGB (1, 1, 1);
+                       ctx.Rectangle (0, 0, W, H);
+                       ctx.Fill ();
+                       ctx.Operator = Operator.Over;
+               }
+       }
+}
\ No newline at end of file
index 0db8fb54e4ca83d4aa279baba8c6c15c235150f1..bfed68b42500e77cea4453b9cf10f47f6d642f00 100644 (file)
@@ -136,8 +136,9 @@ namespace Crow
                public Rectangle LastPaintedSlot;
                /// <summary>Prevent requeuing multiple times the same widget</summary>
                public bool IsQueueForRedraw = false;
-               /// <summary>drawing Cache, if null, a redraw is done, cached or not</summary>
+               /// <summary>drawing Cache bitmap</summary>
                public byte[] bmp;
+               /// <summary>if true, content has to be recreated</summary>
                public bool IsDirty = true;
                /// <summary>
                /// This size is computed on each child' layout changes.
index 549ca2194d0b959e78245303c0362521e07524a9..a71c53a01fa6d3900958e2078bcc2d9b1bc234e3 100644 (file)
@@ -29,7 +29,6 @@ using System.Collections.Generic;
 using System.ComponentModel;
 using System.Xml.Serialization;
 using Cairo;
-using OpenTK.Input;
 using System.Diagnostics;
 using System.Reflection;
 
index d3f2e7c829d4391235441153164be048aa342dfd..0e5364d6c8ca56809639ce38773c1ebedd596c70 100644 (file)
@@ -27,7 +27,6 @@
 using System;
 using System.Xml.Serialization;
 using System.ComponentModel;
-using OpenTK.Input;
 
 namespace Crow
 {
index 91ce50efbca214155c64d6d2924d8b8ced6ce355..ca258aaed821cf2627a0d4124331fe4f24a5cc6c 100644 (file)
@@ -27,7 +27,6 @@
 using System;
 using System.Xml.Serialization;
 using System.ComponentModel;
-using OpenTK.Input;
 
 namespace Crow
 {
index a80f5040b3093b30988c0740468247634eb7c251..ebf3bc42f4ef0654e109daeace5bbafd4de80a96 100644 (file)
@@ -25,7 +25,7 @@
 // THE SOFTWARE.
 using System;
 
-namespace OpenTK.Input
+namespace Crow
 {
     /// <summary>
     /// Enumerates available buttons for a <c>GamePad</c> device.
index 0d7c244eca6f2986fd07a8027a9621e237f5096c..627e2afdd473aa1cd70bc0580537b3a99fc3672c 100644 (file)
@@ -27,7 +27,6 @@
 using System;
 using System.IO;
 using System.Diagnostics;
-using OpenTK;
 using System.Collections.Generic;
 
 namespace Crow
diff --git a/testDrm/Main.cs b/testDrm/Main.cs
new file mode 100644 (file)
index 0000000..77e0d40
--- /dev/null
@@ -0,0 +1,363 @@
+//
+// Main.cs
+//
+// Author:
+//       Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
+//
+// Copyright (c) 2013-2017 Jean-Philippe Bruyère
+//
+// 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.
+using System;
+using System.Diagnostics;
+using System.IO;
+using OpenTK.Platform.Linux;
+using System.Collections.Generic;
+using OpenTK;
+using OpenTK.Platform.Egl;
+using Cairo;
+
+namespace testDrm
+{
+       // Stores platform-specific information about a display
+       class LinuxDisplay
+       {
+               public int FD;
+               public IntPtr Connector;
+               public IntPtr Crtc;
+               public IntPtr Encoder;
+
+               unsafe public ModeConnector* pConnector { get { return (ModeConnector*)Connector; } }
+               unsafe public ModeCrtc* pCrtc { get { return (ModeCrtc*)Crtc; } }
+               unsafe public ModeEncoder* pEncoder { get { return (ModeEncoder*)Encoder; } }
+               /*
+        public ModeInfo Mode
+        {
+            get
+            {
+                if (Crtc == IntPtr.Zero)
+                    throw new InvalidOperationException();
+
+                unsafe
+                {
+                    return pCrtc->mode;
+                }
+            }
+        }
+        */
+
+               public ModeInfo OriginalMode;
+
+               public int Id
+               {
+                       get
+                       {
+                               if (Crtc == IntPtr.Zero)
+                                       throw new InvalidOperationException();
+
+                               unsafe
+                               {
+                                       return (int)pCrtc->crtc_id;
+                               }
+                       }
+               }
+
+               public LinuxDisplay(int fd, IntPtr c, IntPtr e, IntPtr r)
+               {
+                       FD = fd;
+                       Connector = c;
+                       Encoder = e;
+                       Crtc = r;
+                       unsafe
+                       {
+                               OriginalMode = pCrtc->mode; // in case we change resolution later on
+                       }
+               }
+       }
+       static class TestDrm
+       {
+               const string gpu_path = "/dev/dri"; // card0, card1, ...
+
+               [STAThread]
+               static void Main ()
+               {
+                       
+
+//                     using (Surface s = new ImageSurface (Format.Argb32,800,600)) {
+//                             
+//                     }
+//                     IntPtr gbm_device;
+//                     IntPtr egl_display;
+//
+//                     int gpu_fd = CreateDisplay(out gbm_device, out egl_display);
+                       using (DrmDevice drm = new DrmDevice ()) {
+                               drm.RenderingLoop ();
+                       }
+               }
+
+               static int CreateDisplay(out IntPtr gbm_device, out IntPtr egl_display)
+               {
+                       // Query all GPUs until we find one that has a connected display.
+                       // This is necessary in multi-gpu systems, where only one GPU
+                       // can output a signal.
+                       // Todo: allow OpenTK to drive multiple GPUs
+                       // Todo: allow OpenTK to run on an offscreen GPU
+                       // Todo: allow the user to pick a GPU
+                       int fd = 0;
+                       gbm_device = IntPtr.Zero;
+                       egl_display = IntPtr.Zero;
+
+                       var files = Directory.GetFiles(gpu_path);
+                       foreach (var gpu in files)
+                       {
+                               if (System.IO.Path.GetFileName(gpu).StartsWith("card"))
+                               {
+                                       int test_fd = SetupDisplay(gpu, out gbm_device, out egl_display);
+                                       if (test_fd >= 0)
+                                       {
+                                               try
+                                               {
+                                                       if (QueryDisplays(test_fd, null))
+                                                       {
+                                                               fd = test_fd;
+                                                               break;
+                                                       }
+                                               }
+                                               catch (Exception e)
+                                               {
+                                                       Debug.WriteLine(e.ToString());
+                                               }
+
+                                               Console.WriteLine("[KMS] GPU '{0}' is not connected, skipping.", gpu);
+                                               Libc.close(test_fd);
+                                       }
+                               }
+                       }
+
+                       if (fd == 0)
+                       {
+                               Console.WriteLine("[Error] No valid GPU found, bailing out.");
+                               throw new PlatformNotSupportedException();
+                       }
+
+                       return fd;
+               }
+               static bool QueryDisplays(int fd, List<LinuxDisplay> displays)
+               {
+                       unsafe
+                       {
+                               bool has_displays = false;
+                               if (displays != null)
+                               {
+                                       displays.Clear();
+                               }
+
+                               ModeRes* resources = (ModeRes*)Drm.ModeGetResources(fd);
+                               if (resources == null)
+                               {
+                                       Console.WriteLine("[KMS] Drm.ModeGetResources failed.");
+                                       return false;
+                               }
+                               Console.WriteLine("[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)
+                                       {
+                                               bool success = false;
+                                               LinuxDisplay display = null;
+                                               try
+                                               {
+                                                       if (connector->connection == ModeConnection.Connected && connector->count_modes > 0)
+                                                       {
+                                                               success = QueryDisplay(fd, connector, out display);
+                                                               has_displays |= success;
+                                                       }
+                                               }
+                                               catch (Exception e)
+                                               {
+                                                       Console.WriteLine("[KMS] Failed to add display. Error: {0}", e);
+                                               }
+
+                                               if (success && displays != null)
+                                               {
+                                                       displays.Add(display);
+                                               }
+                                               else
+                                               {
+                                                       Drm.ModeFreeConnector((IntPtr)connector);
+                                                       connector = null;
+                                               }
+                                       }
+                               }
+
+                               return has_displays;
+                       }
+               }
+               unsafe static bool QueryDisplay(int fd, ModeConnector* c, out LinuxDisplay display)
+               {
+                       display = null;
+
+                       // Find corresponding encoder
+                       ModeEncoder* encoder = GetEncoder(fd, c);
+                       if (encoder == null)
+                               return false;
+
+                       ModeCrtc* crtc = GetCrtc(fd, encoder);
+                       if (crtc == null)
+                               return false;
+
+                       display = new LinuxDisplay(fd, (IntPtr)c, (IntPtr)encoder, (IntPtr)crtc);
+                       return true;
+               }
+               unsafe static ModeEncoder* GetEncoder(int fd, ModeConnector* c)
+               {
+                       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)
+                                       continue;
+                               
+                               if (e->encoder_id == c->encoder_id)
+                                       encoder = e;                                    
+                               else
+                                       Drm.ModeFreeEncoder((IntPtr)e);                                 
+                       }
+
+                       if (encoder != null)
+                               Console.WriteLine("[KMS] Encoder {0} found for connector {1}", encoder->encoder_id, c->connector_id);
+                       else
+                               Console.WriteLine("[KMS] Failed to find encoder for connector {0}", c->connector_id);
+
+                       return encoder;
+               }
+
+               unsafe static ModeCrtc* GetCrtc(int fd, ModeEncoder* encoder)
+               {
+                       ModeCrtc* crtc = (ModeCrtc*)Drm.ModeGetCrtc(fd, encoder->crtc_id);
+                       if (crtc != null)
+                       {
+                               Console.WriteLine("[KMS] CRTC {0} found for encoder {1}",
+                                       encoder->crtc_id, encoder->encoder_id);
+                       }
+                       else
+                       {
+                               Console.WriteLine("[KMS] Failed to find crtc {0} for encoder {1}",
+                                       encoder->crtc_id, encoder->encoder_id);
+                       }
+                       return crtc;
+               }
+
+               unsafe static void GetModes(LinuxDisplay display, DisplayResolution[] modes, out DisplayResolution current)
+               {
+                       int mode_count = display.pConnector->count_modes;
+                       Console.WriteLine("[KMS] Display supports {0} mode(s)", mode_count);
+                       for (int i = 0; i < mode_count; i++)
+                       {
+                               ModeInfo* mode = display.pConnector->modes + i;
+                               if (mode != null)
+                               {
+                                       Console.WriteLine("Mode {0}: {1}x{2} @{3}", i,
+                                               mode->hdisplay, mode->vdisplay, mode->vrefresh);
+                                       DisplayResolution res = GetDisplayResolution(mode);
+                                       modes[i] = res;
+                               }
+                       }
+
+                       if (display.pCrtc->mode_valid != 0)
+                       {
+                               ModeInfo cmode = display.pCrtc->mode;
+                               current = GetDisplayResolution(&cmode);
+                       }
+                       else
+                       {
+                               current = GetDisplayResolution(display.pConnector->modes);
+                       }
+                       Console.WriteLine("Current mode: {0}", current.ToString());
+               }
+               unsafe static DisplayResolution GetDisplayResolution(ModeInfo* mode)
+               {
+                       return new DisplayResolution(
+                               0, 0,
+                               mode->hdisplay, mode->vdisplay,
+                               32, // This is actually part of the framebuffer, not the DisplayResolution
+                               mode->vrefresh);
+               }
+
+               unsafe static ModeInfo* GetModeInfo(LinuxDisplay display, DisplayResolution resolution)
+               {
+                       for (int i = 0; i < display.pConnector->count_modes; i++)
+                       {
+                               ModeInfo* mode = display.pConnector->modes + i;
+                               if (mode != null &&
+                                       mode->hdisplay == resolution.Width &&
+                                       mode->vdisplay == resolution.Height)
+                               {
+                                       return mode;
+                               }
+                       }
+                       return null;
+               }
+
+               static int SetupDisplay(string gpu, out IntPtr gbm_device, out IntPtr egl_display)
+               {
+                       Console.WriteLine("[KMS] Attempting to use gpu '{0}'.", gpu);
+
+                       gbm_device = IntPtr.Zero;
+                       egl_display = IntPtr.Zero;
+
+                       int fd = Libc.open(gpu, OpenFlags.ReadWrite | OpenFlags.CloseOnExec);
+                       if (fd < 0)
+                       {
+                               Console.WriteLine("[KMS] Failed to open gpu");
+                               return fd;
+                       }
+                       Console.WriteLine("[KMS] GPU '{0}' opened as fd:{1}", gpu, fd);
+
+                       gbm_device = Gbm.CreateDevice(fd);
+                       if (gbm_device == IntPtr.Zero)
+                       {
+                               throw new NotSupportedException("[KMS] Failed to create GBM device");
+                       }
+                       Console.WriteLine("[KMS] GBM {0:x} created successfully; ", gbm_device);
+
+                       egl_display = Egl.GetDisplay(gbm_device);
+                       if (egl_display == IntPtr.Zero)
+                       {
+                               throw new NotSupportedException("[KMS] Failed to create EGL display");
+                       }
+                       Console.WriteLine("[KMS] EGL display {0:x} created successfully", egl_display);
+
+                       int major, minor;
+                       if (!Egl.Initialize(egl_display, out major, out minor))
+                       {
+                               ErrorCode error = Egl.GetError();
+                               throw new NotSupportedException("[KMS] Failed to initialize EGL display. Error code: " + error);
+                       }
+                       Console.WriteLine("[KMS] EGL {0}.{1} initialized successfully on display {2:x}", major, minor, egl_display);
+
+                       return fd;
+               }
+       }
+}
+
diff --git a/testDrm/Mono.Cairo/Antialias.cs b/testDrm/Mono.Cairo/Antialias.cs
new file mode 100644 (file)
index 0000000..9ea64f7
--- /dev/null
@@ -0,0 +1,43 @@
+//
+// Mono.Cairo.Antialias.cs
+//
+// Authors:
+//   Duncan Mak (duncan@ximian.com)
+//   Hisham Mardam Bey (hisham.mardambey@gmail.com)
+//
+// (C) Ximian, Inc. 2003
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// 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.
+//
+
+using System;
+
+namespace Cairo
+{
+       [Serializable]
+       public enum Antialias
+       {
+               Default,
+               None,
+               Gray,
+               Subpixel,
+       }
+}
diff --git a/testDrm/Mono.Cairo/Cairo.cs b/testDrm/Mono.Cairo/Cairo.cs
new file mode 100644 (file)
index 0000000..c0a5f2a
--- /dev/null
@@ -0,0 +1,53 @@
+//
+// Cairo.cs - a simplistic binding of the Cairo API to C#.
+//
+// Authors: Duncan Mak (duncan@ximian.com)
+//          Hisham Mardam Bey (hisham.mardambey@gmail.com)
+//          John Luke (john.luke@gmail.com)
+//          Alp Toker (alp@atoker.com)
+//
+// (C) Ximian, Inc. 2003
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+// Copyright (C) 2005 John Luke
+// Copyright (C) 2006 Alp Toker
+//
+// 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.
+//
+
+using System;
+using System.Runtime.InteropServices;
+
+namespace Cairo
+{
+       public static class CairoAPI {
+               static public int Version {
+                       get {
+                               return Cairo.NativeMethods.cairo_version ();
+                       }
+               }
+
+               static public string VersionString {
+                       get {
+                               IntPtr x = Cairo.NativeMethods.cairo_version_string ();
+                               return Marshal.PtrToStringAnsi (x);
+                       }
+               }
+       }
+}
diff --git a/testDrm/Mono.Cairo/CairoDebug.cs b/testDrm/Mono.Cairo/CairoDebug.cs
new file mode 100644 (file)
index 0000000..d694bbb
--- /dev/null
@@ -0,0 +1,82 @@
+//
+// CairoDebug.cs
+//
+// Author:
+//   Michael Hutchinson (mhutch@xamarin.com)
+//
+// Copyright (C) 2013 Xamarin Inc. (http://www.xamarin.com)
+//
+// 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.
+//
+
+using System;
+
+namespace Cairo {
+
+       static class CairoDebug
+       {
+               static System.Collections.Generic.Dictionary<IntPtr,string> traces;
+
+               public static readonly bool Enabled;
+
+               static CairoDebug ()
+               {
+                       var dbg = Environment.GetEnvironmentVariable ("MONO_CAIRO_DEBUG_DISPOSE");
+                       if (dbg == null)
+                               return;
+                       Enabled = true;
+                       traces = new System.Collections.Generic.Dictionary<IntPtr,string> ();
+               }
+
+               public static void OnAllocated (IntPtr obj)
+               {
+                       if (!Enabled)
+                               throw new InvalidOperationException ();
+
+                       traces[obj] = Environment.StackTrace;
+               }
+
+               public static void OnDisposed<T> (IntPtr obj, bool disposing)
+               {
+                       if (disposing && !Enabled)
+                               throw new InvalidOperationException ();
+
+                       if (Environment.HasShutdownStarted)
+                               return;
+
+                       if (!disposing) {
+                               Console.Error.WriteLine ("{0} is leaking, programmer is missing a call to Dispose", typeof(T).FullName);
+                               if (Enabled) {
+                                       string val;
+                                       if (traces.TryGetValue (obj, out val)) {
+                                               Console.Error.WriteLine ("Allocated from:");
+                                               Console.Error.WriteLine (val);
+                                       }
+                               } else {
+                                       Console.Error.WriteLine ("Set MONO_CAIRO_DEBUG_DISPOSE to track allocation traces");
+                               }
+                       }
+
+                       if (Enabled)
+                               traces.Remove (obj);
+               }
+       }
+
+}
diff --git a/testDrm/Mono.Cairo/Color.cs b/testDrm/Mono.Cairo/Color.cs
new file mode 100644 (file)
index 0000000..030089e
--- /dev/null
@@ -0,0 +1,75 @@
+//
+// Mono.Cairo.Context.cs
+//
+// Author:
+//   Duncan Mak (duncan@ximian.com)
+//   Miguel de Icaza (miguel@novell.com)
+//   Hisham Mardam Bey (hisham.mardambey@gmail.com)
+//   Alp Toker (alp@atoker.com)
+//
+// (C) Ximian Inc, 2003.
+// (C) Novell Inc, 2003.
+//
+// This is an OO wrapper API for the Cairo API.
+//
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// 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.
+//
+
+namespace Cairo {
+
+       public struct Color
+       {
+               public Color(double r, double g, double b) : this (r, g, b, 1.0)
+               {
+               }
+
+               public Color(double r, double g, double b, double a)
+               {
+                       this.r = r;
+                       this.g = g;
+                       this.b = b;
+                       this.a = a;
+               }
+
+               double r, g, b, a;
+
+               public double R {
+                       get { return r; }
+                       set { r = value; }
+               }
+
+               public double G {
+                       get { return g; }
+                       set { g = value; }
+               }
+
+               public double B {
+                       get { return b; }
+                       set { b = value; }
+               }
+
+               public double A {
+                       get { return a; }
+                       set { a = value; }
+               }
+       }
+}
diff --git a/testDrm/Mono.Cairo/Content.cs b/testDrm/Mono.Cairo/Content.cs
new file mode 100644 (file)
index 0000000..a88d35a
--- /dev/null
@@ -0,0 +1,43 @@
+//
+// Mono.Cairo.Content.cs
+//
+// Authors:
+//   Duncan Mak (duncan@ximian.com)
+//   Hisham Mardam Bey (hisham.mardambey@gmail.com)
+//
+// (C) Ximian, Inc. 2003
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// 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.
+//
+
+using System;
+
+namespace Cairo
+{
+       //[Flags]
+       [Serializable]
+       public enum Content
+       {
+               Color = 0x1000,
+               Alpha = 0x2000,
+               ColorAlpha = 0x3000,
+       }
+}
diff --git a/testDrm/Mono.Cairo/Context.cs b/testDrm/Mono.Cairo/Context.cs
new file mode 100644 (file)
index 0000000..7ca0dee
--- /dev/null
@@ -0,0 +1,911 @@
+//
+// Mono.Cairo.Context.cs
+//
+// Author:
+//   Duncan Mak (duncan@ximian.com)
+//   Miguel de Icaza (miguel@novell.com)
+//   Hisham Mardam Bey (hisham.mardambey@gmail.com)
+//   Alp Toker (alp@atoker.com)
+//
+// (C) Ximian Inc, 2003.
+// (C) Novell Inc, 2003.
+//
+// This is an OO wrapper API for the Cairo API.
+//
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// 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.
+//
+
+using System;
+using System.Runtime.InteropServices;
+using System.Text;
+using Cairo;
+
+namespace Cairo {
+
+       [Obsolete ("Renamed Cairo.Context per suggestion from cairo binding guidelines.")]
+       public class Graphics : Context {
+               public Graphics (IntPtr state) : base (state) {}
+               public Graphics (Surface surface) : base (surface) {}
+       }
+
+       public class Context : IDisposable
+       {
+               IntPtr handle = IntPtr.Zero;
+
+               static int native_glyph_size, c_compiler_long_size;
+
+               static Context ()
+               {
+                       //
+                       // This is used to determine what kind of structure
+                       // we should use to marshal Glyphs, as the public
+                       // definition in Cairo uses `long', which can be
+                       // 32 bits or 64 bits depending on the platform.
+                       //
+                       // We assume that sizeof(long) == sizeof(void*)
+                       // except in the case of Win64 where sizeof(long)
+                       // is 32 bits
+                       //
+                       int ptr_size = Marshal.SizeOf (typeof (IntPtr));
+
+                       PlatformID platform = Environment.OSVersion.Platform;
+                       if (platform == PlatformID.Win32NT ||
+                           platform == PlatformID.Win32S ||
+                           platform == PlatformID.Win32Windows ||
+                           platform == PlatformID.WinCE ||
+                           ptr_size == 4){
+                               c_compiler_long_size = 4;
+                               native_glyph_size = Marshal.SizeOf (typeof (NativeGlyph_4byte_longs));
+                       } else {
+                               c_compiler_long_size = 8;
+                               native_glyph_size = Marshal.SizeOf (typeof (Glyph));
+                       }
+               }
+
+               public Context (Surface surface) : this (NativeMethods.cairo_create (surface.Handle), true)
+               {
+               }
+
+
+               public Context (IntPtr handle, bool owner)
+               {
+                       this.handle = handle;
+                       if (!owner)
+                               NativeMethods.cairo_reference (handle);
+                       if (CairoDebug.Enabled)
+                               CairoDebug.OnAllocated (handle);
+               }
+
+               [Obsolete]
+               public Context (IntPtr state) : this (state, true)
+               {
+               }
+
+               ~Context ()
+               {
+                       Dispose (false);
+               }
+
+               public void Dispose ()
+               {
+                       Dispose (true);
+                       GC.SuppressFinalize (this);
+               }
+
+               protected virtual void Dispose (bool disposing)
+               {
+                       if (!disposing || CairoDebug.Enabled)
+                               CairoDebug.OnDisposed<Context> (handle, disposing);
+
+                       if (!disposing|| handle == IntPtr.Zero)
+                               return;
+
+                       NativeMethods.cairo_destroy (handle);
+                       handle = IntPtr.Zero;
+
+               }
+
+               public void Save ()
+               {
+                       NativeMethods.cairo_save (handle);
+               }
+
+               public void Restore ()
+               {
+                       NativeMethods.cairo_restore (handle);
+               }
+
+               public Antialias Antialias {
+                       get { return NativeMethods.cairo_get_antialias (handle); }
+                       set { NativeMethods.cairo_set_antialias (handle, value); }
+               }
+
+               public Cairo.Status Status {
+                       get {
+                               return NativeMethods.cairo_status (handle);
+                       }
+               }
+
+               public IntPtr Handle {
+                       get {
+                               return handle;
+                       }
+               }
+
+               public Operator Operator {
+                       set {
+                               NativeMethods.cairo_set_operator (handle, value);
+                       }
+
+                       get {
+                               return NativeMethods.cairo_get_operator (handle);
+                       }
+               }
+
+               [Obsolete ("Use SetSourceColor method")]
+               public Color Color {
+                       set {
+                               SetSourceColor (value);
+                       }
+               }
+
+               [Obsolete ("Use SetSourceRGBA method")]
+               public Cairo.Color ColorRgb {
+                       set {
+                               Color = new Color (value.R, value.G, value.B);
+                       }
+               }
+
+               public double Tolerance {
+                       get {
+                               return NativeMethods.cairo_get_tolerance (handle);
+                       }
+
+                       set {
+                               NativeMethods.cairo_set_tolerance (handle, value);
+                       }
+               }
+
+               public Cairo.FillRule FillRule {
+                       set {
+                               NativeMethods.cairo_set_fill_rule (handle, value);
+                       }
+
+                       get {
+                               return NativeMethods.cairo_get_fill_rule (handle);
+                       }
+               }
+
+               public double LineWidth {
+                       set {
+                               NativeMethods.cairo_set_line_width (handle, value);
+                       }
+
+                       get {
+                               return NativeMethods.cairo_get_line_width (handle);
+                       }
+               }
+
+               public Cairo.LineCap LineCap {
+                       set {
+                               NativeMethods.cairo_set_line_cap (handle, value);
+                       }
+
+                       get {
+                               return NativeMethods.cairo_get_line_cap (handle);
+                       }
+               }
+
+               public Cairo.LineJoin LineJoin {
+                       set {
+                               NativeMethods.cairo_set_line_join (handle, value);
+                       }
+
+                       get {
+                               return NativeMethods.cairo_get_line_join (handle);
+                       }
+               }
+
+               public void SetDash (double [] dashes, double offset)
+               {
+                       NativeMethods.cairo_set_dash (handle, dashes, dashes.Length, offset);
+               }
+
+               [Obsolete("Use GetSource/SetSource")]
+               public Pattern Pattern {
+                       set {
+                               SetSource (value);
+                       }
+                       get {
+                               return GetSource ();
+                       }
+               }
+
+               //This is obsolete because it wasn't obvious it needed to be disposed
+               [Obsolete("Use GetSource/SetSource")]
+               public Pattern Source {
+                       set {
+                               SetSource (value);
+                       }
+                       get {
+                               return GetSource ();
+                       }
+               }
+
+               public void SetSource (Pattern source)
+               {
+                       NativeMethods.cairo_set_source (handle, source.Handle);
+               }
+
+               public Pattern GetSource ()
+               {
+                       var ptr = NativeMethods.cairo_get_source (handle);
+                       return Cairo.Pattern.Lookup (ptr, false);
+               }
+
+               public double MiterLimit {
+                       set {
+                               NativeMethods.cairo_set_miter_limit (handle, value);
+                       }
+
+                       get {
+                               return NativeMethods.cairo_get_miter_limit (handle);
+                       }
+               }
+
+               public PointD CurrentPoint {
+                       get {
+                               double x, y;
+                               NativeMethods.cairo_get_current_point (handle, out x, out y);
+                               return new PointD (x, y);
+                       }
+               }
+
+               public bool HasCurrentPoint {
+                       get {
+                               return NativeMethods.cairo_has_current_point (handle);
+                       }
+               }
+
+               [Obsolete ("Use GetTarget/SetTarget")]
+               public Cairo.Surface Target {
+                       set {
+                               if (handle != IntPtr.Zero)
+                                       NativeMethods.cairo_destroy (handle);
+
+                               handle = NativeMethods.cairo_create (value.Handle);
+                       }
+
+                       get {
+                               return GetTarget ();
+                       }
+               }
+
+               public Surface GetTarget ()
+               {
+                       return Surface.Lookup (NativeMethods.cairo_get_target (handle), false);
+               }
+
+               public void SetTarget (Surface target)
+               {
+                       if (handle != IntPtr.Zero)
+                               NativeMethods.cairo_destroy (handle);
+                       handle = NativeMethods.cairo_create (target.Handle);
+               }
+
+               [Obsolete("Use GetScaledFont/SetScaledFont")]
+               public ScaledFont ScaledFont {
+                       set {
+                               SetScaledFont (value);
+                       }
+
+                       get {
+                               return GetScaledFont ();
+                       }
+               }
+
+               public ScaledFont GetScaledFont ()
+               {
+                       return new ScaledFont (NativeMethods.cairo_get_scaled_font (handle), false);
+               }
+
+               public void SetScaledFont (ScaledFont font)
+               {
+                       NativeMethods.cairo_set_scaled_font (handle, font.Handle);
+               }
+
+               public uint ReferenceCount {
+                       get { return NativeMethods.cairo_get_reference_count (handle); }
+               }
+
+               public void SetSourceColor (Color color)
+               {
+                       NativeMethods.cairo_set_source_rgba (handle, color.R, color.G, color.B, color.A);
+               }
+
+               public void SetSourceRGB (double r, double g, double b)
+               {
+                       NativeMethods.cairo_set_source_rgb (handle, r, g, b);
+               }
+
+               public void SetSourceRGBA (double r, double g, double b, double a)
+               {
+                       NativeMethods.cairo_set_source_rgba (handle, r, g, b, a);
+               }
+
+               //[Obsolete ("Use SetSource method (with double parameters)")]
+               public void SetSourceSurface (Surface source, int x, int y)
+               {
+                       NativeMethods.cairo_set_source_surface (handle, source.Handle, x, y);
+               }
+
+               public void SetSource (Surface source, double x, double y)
+               {
+                       NativeMethods.cairo_set_source_surface (handle, source.Handle, x, y);
+               }
+
+               public void SetSource (Surface source)
+               {
+                       NativeMethods.cairo_set_source_surface (handle, source.Handle, 0, 0);
+               }
+
+#region Path methods
+
+               public void NewPath ()
+               {
+                       NativeMethods.cairo_new_path (handle);
+               }
+
+               public void NewSubPath ()
+               {
+                       NativeMethods.cairo_new_sub_path (handle);
+               }
+
+               public void MoveTo (PointD p)
+               {
+                       MoveTo (p.X, p.Y);
+               }
+
+               public void MoveTo (double x, double y)
+               {
+                       NativeMethods.cairo_move_to (handle, x, y);
+               }
+
+               public void LineTo (PointD p)
+               {
+                       LineTo (p.X, p.Y);
+               }
+
+               public void LineTo (double x, double y)
+               {
+                       NativeMethods.cairo_line_to (handle, x, y);
+               }
+
+               public void CurveTo (PointD p1, PointD p2, PointD p3)
+               {
+                       CurveTo (p1.X, p1.Y, p2.X, p2.Y, p3.X, p3.Y);
+               }
+
+               public void CurveTo (double x1, double y1, double x2, double y2, double x3, double y3)
+               {
+                       NativeMethods.cairo_curve_to (handle, x1, y1, x2, y2, x3, y3);
+               }
+
+               public void RelMoveTo (Distance d)
+               {
+                       RelMoveTo (d.Dx, d.Dy);
+               }
+
+               public void RelMoveTo (double dx, double dy)
+               {
+                       NativeMethods.cairo_rel_move_to (handle, dx, dy);
+               }
+
+               public void RelLineTo (Distance d)
+               {
+                       RelLineTo (d.Dx, d.Dy);
+               }
+
+               public void RelLineTo (double dx, double dy)
+               {
+                       NativeMethods.cairo_rel_line_to (handle, dx, dy);
+               }
+
+               public void RelCurveTo (Distance d1, Distance d2, Distance d3)
+               {
+                       RelCurveTo (d1.Dx, d1.Dy, d2.Dx, d2.Dy, d3.Dx, d3.Dy);
+               }
+
+               public void RelCurveTo (double dx1, double dy1, double dx2, double dy2, double dx3, double dy3)
+               {
+                       NativeMethods.cairo_rel_curve_to (handle, dx1, dy1, dx2, dy2, dx3, dy3);
+               }
+
+               public void Arc (double xc, double yc, double radius, double angle1, double angle2)
+               {
+                       NativeMethods.cairo_arc (handle, xc, yc, radius, angle1, angle2);
+               }
+
+               public void ArcNegative (double xc, double yc, double radius, double angle1, double angle2)
+               {
+                       NativeMethods.cairo_arc_negative (handle, xc, yc, radius, angle1, angle2);
+               }
+
+               public void Rectangle (Rectangle rectangle)
+               {
+                       Rectangle (rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height);
+               }
+
+               public void Rectangle (PointD p, double width, double height)
+               {
+                       Rectangle (p.X, p.Y, width, height);
+               }
+
+               public void Rectangle (double x, double y, double width, double height)
+               {
+                       NativeMethods.cairo_rectangle (handle, x, y, width, height);
+               }
+
+               public void ClosePath ()
+               {
+                       NativeMethods.cairo_close_path (handle);
+               }
+
+               public Path CopyPath ()
+               {
+                       return new Path (NativeMethods.cairo_copy_path (handle));
+               }
+
+               public Path CopyPathFlat ()
+               {
+                       return new Path (NativeMethods.cairo_copy_path_flat (handle));
+               }
+
+               public void AppendPath (Path path)
+               {
+                       NativeMethods.cairo_append_path (handle, path.Handle);
+               }
+
+#endregion
+
+#region Painting Methods
+               public void Paint ()
+               {
+                       NativeMethods.cairo_paint (handle);
+               }
+
+               public void PaintWithAlpha (double alpha)
+               {
+                       NativeMethods.cairo_paint_with_alpha (handle, alpha);
+               }
+
+               public void Mask (Pattern pattern)
+               {
+                       NativeMethods.cairo_mask (handle, pattern.Handle);
+               }
+
+               public void MaskSurface (Surface surface, double surface_x, double surface_y)
+               {
+                       NativeMethods.cairo_mask_surface (handle, surface.Handle, surface_x, surface_y);
+               }
+
+               public void Stroke ()
+               {
+                       NativeMethods.cairo_stroke (handle);
+               }
+
+               public void StrokePreserve ()
+               {
+                       NativeMethods.cairo_stroke_preserve (handle);
+               }
+
+               public Rectangle StrokeExtents ()
+               {
+                       double x1, y1, x2, y2;
+                       NativeMethods.cairo_stroke_extents (handle, out x1, out y1, out x2, out y2);
+                       return new Rectangle (x1, y1, x2 - x1, y2 - y1);
+               }
+
+               public void Fill ()
+               {
+                       NativeMethods.cairo_fill (handle);
+               }
+
+               public Rectangle FillExtents ()
+               {
+                       double x1, y1, x2, y2;
+                       NativeMethods.cairo_fill_extents (handle, out x1, out y1, out x2, out y2);
+                       return new Rectangle (x1, y1, x2 - x1, y2 - y1);
+               }
+
+               public void FillPreserve ()
+               {
+                       NativeMethods.cairo_fill_preserve (handle);
+               }
+
+#endregion
+
+               public void Clip ()
+               {
+                       NativeMethods.cairo_clip (handle);
+               }
+
+               public void ClipPreserve ()
+               {
+                       NativeMethods.cairo_clip_preserve (handle);
+               }
+
+               public void ResetClip ()
+               {
+                       NativeMethods.cairo_reset_clip (handle);
+               }
+
+               public bool InClip (double x, double y)
+               {
+                       return NativeMethods.cairo_in_clip (handle, x, y);
+               }
+
+               public bool InStroke (double x, double y)
+               {
+                       return NativeMethods.cairo_in_stroke (handle, x, y);
+               }
+
+               public bool InFill (double x, double y)
+               {
+                       return NativeMethods.cairo_in_fill (handle, x, y);
+               }
+
+               public Pattern PopGroup ()
+               {
+                       return Pattern.Lookup (NativeMethods.cairo_pop_group (handle), true);
+               }
+
+               public void PopGroupToSource ()
+               {
+                       NativeMethods.cairo_pop_group_to_source (handle);
+               }
+
+               public void PushGroup ()
+               {
+                       NativeMethods.cairo_push_group (handle);
+               }
+
+               public void PushGroup (Content content)
+               {
+                       NativeMethods.cairo_push_group_with_content (handle, content);
+               }
+
+               [Obsolete ("Use GetGroupTarget()")]
+               public Surface GroupTarget {
+                       get {
+                               return GetGroupTarget ();
+                       }
+               }
+
+               public Surface GetGroupTarget ()
+               {
+                       IntPtr surface = NativeMethods.cairo_get_group_target (handle);
+                       return Surface.Lookup (surface, false);
+               }
+
+               public void Rotate (double angle)
+               {
+                       NativeMethods.cairo_rotate (handle, angle);
+               }
+
+               public void Scale (double sx, double sy)
+               {
+                       NativeMethods.cairo_scale (handle, sx, sy);
+               }
+
+               public void Translate (double tx, double ty)
+               {
+                       NativeMethods.cairo_translate (handle, tx, ty);
+               }
+
+               public void Transform (Matrix m)
+               {
+                       NativeMethods.cairo_transform (handle, m);
+               }
+
+               [Obsolete("Use UserToDevice instead")]
+               public void TransformPoint (ref double x, ref double y)
+               {
+                       NativeMethods.cairo_user_to_device (handle, ref x, ref y);
+               }
+
+               [Obsolete("Use UserToDeviceDistance instead")]
+               public void TransformDistance (ref double dx, ref double dy)
+               {
+                       NativeMethods.cairo_user_to_device_distance (handle, ref dx, ref dy);
+               }
+
+               [Obsolete("Use InverseTransformPoint instead")]
+               public void InverseTransformPoint (ref double x, ref double y)
+               {
+                       NativeMethods.cairo_device_to_user (handle, ref x, ref y);
+               }
+
+               [Obsolete("Use DeviceToUserDistance instead")]
+               public void InverseTransformDistance (ref double dx, ref double dy)
+               {
+                       NativeMethods.cairo_device_to_user_distance (handle, ref dx, ref dy);
+               }
+
+               public void UserToDevice (ref double x, ref double y)
+               {
+                       NativeMethods.cairo_user_to_device (handle, ref x, ref y);
+               }
+
+               public void UserToDeviceDistance (ref double dx, ref double dy)
+               {
+                       NativeMethods.cairo_user_to_device_distance (handle, ref dx, ref dy);
+               }
+
+               public void DeviceToUser (ref double x, ref double y)
+               {
+                       NativeMethods.cairo_device_to_user (handle, ref x, ref y);
+               }
+
+               public void DeviceToUserDistance (ref double dx, ref double dy)
+               {
+                       NativeMethods.cairo_device_to_user_distance (handle, ref dx, ref dy);
+               }
+
+               public Matrix Matrix {
+                       set {
+                               NativeMethods.cairo_set_matrix (handle, value);
+                       }
+
+                       get {
+                               Matrix m = new Matrix();
+                               NativeMethods.cairo_get_matrix (handle, m);
+                               return m;
+                       }
+               }
+
+               public void SetFontSize (double scale)
+               {
+                       NativeMethods.cairo_set_font_size (handle, scale);
+               }
+
+               public void IdentityMatrix ()
+               {
+                       NativeMethods.cairo_identity_matrix (handle);
+               }
+
+               [Obsolete ("Use SetFontSize() instead.")]
+               public void FontSetSize (double scale)
+               {
+                       SetFontSize (scale);
+               }
+
+               [Obsolete ("Use SetFontSize() instead.")]
+               public double FontSize {
+                       set { SetFontSize (value); }
+               }
+
+               public Matrix FontMatrix {
+                       get {
+                               Matrix m;
+                               NativeMethods.cairo_get_font_matrix (handle, out m);
+                               return m;
+                       }
+                       set { NativeMethods.cairo_set_font_matrix (handle, value); }
+               }
+
+               public FontOptions FontOptions {
+                       get {
+                               FontOptions options = new FontOptions ();
+                               NativeMethods.cairo_get_font_options (handle, options.Handle);
+                               return options;
+                       }
+                       set { NativeMethods.cairo_set_font_options (handle, value.Handle); }
+               }
+
+               [StructLayout(LayoutKind.Sequential)]
+               internal struct NativeGlyph_4byte_longs {
+                       public int index;
+                       public double x;
+                       public double y;
+
+                       public NativeGlyph_4byte_longs (Glyph source)
+                       {
+                               index = (int) source.index;
+                               x = source.x;
+                               y = source.y;
+                       }
+               }
+
+               static internal IntPtr FromGlyphToUnManagedMemory(Glyph [] glyphs)
+               {
+                       IntPtr dest = Marshal.AllocHGlobal (native_glyph_size * glyphs.Length);
+                       long pos = dest.ToInt64();
+
+                       if (c_compiler_long_size == 8){
+                               foreach (Glyph g in glyphs){
+                                       Marshal.StructureToPtr (g, (IntPtr)pos, false);
+                                       pos += native_glyph_size;
+                               }
+                       } else {
+                               foreach (Glyph g in glyphs){
+                                       NativeGlyph_4byte_longs n = new NativeGlyph_4byte_longs (g);
+
+                                       Marshal.StructureToPtr (n, (IntPtr)pos, false);
+                                       pos += native_glyph_size;
+                               }
+                       }
+
+                       return dest;
+               }
+
+               public void ShowGlyphs (Glyph[] glyphs)
+               {
+                       IntPtr ptr;
+
+                       ptr = FromGlyphToUnManagedMemory (glyphs);
+
+                       NativeMethods.cairo_show_glyphs (handle, ptr, glyphs.Length);
+
+                       Marshal.FreeHGlobal (ptr);
+               }
+
+               [Obsolete("The matrix argument was never used, use ShowGlyphs(Glyphs []) instead")]
+               public void ShowGlyphs (Matrix matrix, Glyph[] glyphs)
+               {
+                       ShowGlyphs (glyphs);
+               }
+
+               [Obsolete("The matrix argument was never used, use GlyphPath(Glyphs []) instead")]
+               public void GlyphPath (Matrix matrix, Glyph[] glyphs)
+               {
+                       GlyphPath (glyphs);
+               }
+
+               public void GlyphPath (Glyph[] glyphs)
+               {
+                       IntPtr ptr;
+
+                       ptr = FromGlyphToUnManagedMemory (glyphs);
+
+                       NativeMethods.cairo_glyph_path (handle, ptr, glyphs.Length);
+
+                       Marshal.FreeHGlobal (ptr);
+
+               }
+
+               public FontExtents FontExtents {
+                       get {
+                               FontExtents f_extents;
+                               NativeMethods.cairo_font_extents (handle, out f_extents);
+                               return f_extents;
+                       }
+               }
+
+               public void CopyPage ()
+               {
+                       NativeMethods.cairo_copy_page (handle);
+               }
+
+               [Obsolete ("Use SelectFontFace() instead.")]
+               public void FontFace (string family, FontSlant slant, FontWeight weight)
+               {
+                       SelectFontFace (family, slant, weight);
+               }
+
+               [Obsolete("Use GetFontFace/SetFontFace")]
+               public FontFace ContextFontFace {
+                       get {
+                               return GetContextFontFace ();
+                       }
+                       set {
+                               SetContextFontFace (value);
+                       }
+               }
+
+               public FontFace GetContextFontFace ()
+               {
+                       return Cairo.FontFace.Lookup (NativeMethods.cairo_get_font_face (handle), false);
+               }
+
+               public void SetContextFontFace (FontFace value)
+               {
+                       NativeMethods.cairo_set_font_face (handle, value == null ? IntPtr.Zero : value.Handle);
+               }
+
+               public void SelectFontFace (string family, FontSlant slant, FontWeight weight)
+               {
+                       NativeMethods.cairo_select_font_face (handle, family, slant, weight);
+               }
+
+               public void ShowPage ()
+               {
+                       NativeMethods.cairo_show_page (handle);
+               }
+
+               private static byte[] TerminateUtf8(byte[] utf8)
+               {
+                       if (utf8.Length > 0 && utf8[utf8.Length - 1] == 0)
+                               return utf8;
+                       var termedArray = new byte[utf8.Length + 1];
+                       Array.Copy(utf8, termedArray, utf8.Length);
+                       termedArray[utf8.Length] = 0;
+                       return termedArray;
+               }
+
+               private static byte[] TerminateUtf8(string s)
+               {
+                       // compute the byte count including the trailing \0
+                       var byteCount = Encoding.UTF8.GetMaxByteCount(s.Length + 1);
+                       var bytes = new byte[byteCount];
+                       Encoding.UTF8.GetBytes(s, 0, s.Length, bytes, 0);
+                       return bytes;
+               }
+
+               public void ShowText(string str)
+               {
+                       NativeMethods.cairo_show_text (handle, TerminateUtf8(str));
+               }
+
+               public void ShowText(byte[] utf8)
+               {
+                       NativeMethods.cairo_show_text (handle, TerminateUtf8(utf8));
+               }
+
+               public void TextPath(string str)
+               {
+                       NativeMethods.cairo_text_path (handle, TerminateUtf8(str));
+               }
+
+               public void TextPath(byte[] utf8)
+               {
+                       NativeMethods.cairo_text_path (handle, TerminateUtf8(utf8));
+               }
+
+               public TextExtents TextExtents(string s)
+               {
+                       TextExtents extents;
+                       NativeMethods.cairo_text_extents (handle, TerminateUtf8(s), out extents);
+                       return extents;
+               }
+
+               public TextExtents TextExtents(byte[] utf8)
+               {
+                       TextExtents extents;
+                       NativeMethods.cairo_text_extents (handle, TerminateUtf8(utf8), out extents);
+                       return extents;
+               }
+
+               public TextExtents GlyphExtents (Glyph[] glyphs)
+               {
+                       IntPtr ptr = FromGlyphToUnManagedMemory (glyphs);
+
+                       TextExtents extents;
+
+                       NativeMethods.cairo_glyph_extents (handle, ptr, glyphs.Length, out extents);
+
+                       Marshal.FreeHGlobal (ptr);
+
+                       return extents;
+               }
+       }
+}
diff --git a/testDrm/Mono.Cairo/Device.cs b/testDrm/Mono.Cairo/Device.cs
new file mode 100644 (file)
index 0000000..06715bc
--- /dev/null
@@ -0,0 +1,101 @@
+//
+// Mono.Cairo.Device.cs
+//
+// Authors:
+//                     JP Bruyère (jp_bruyere@hotmail.com)
+//
+// This is an OO wrapper API for the Cairo API
+//
+// Copyright (C) 2016 JP Bruyère
+//
+// 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.
+//
+using System;
+
+namespace Cairo
+{
+       public class Device : IDisposable
+       {
+               IntPtr handle = IntPtr.Zero;
+
+               protected Device()
+               {
+               }
+
+               protected Device (IntPtr ptr) : this (ptr, true)
+               {
+               }
+
+               protected Device (IntPtr handle, bool owner)
+               {
+                       this.handle = handle;
+                       if (!owner)
+                               NativeMethods.cairo_device_reference (handle);
+                       if (CairoDebug.Enabled)
+                               CairoDebug.OnAllocated (handle);
+               }
+
+               ~Device ()
+               {
+                       Dispose (false);
+               }
+
+               public IntPtr Handle {
+                       get {
+                               return handle;
+                       }
+               }
+               public string Status {
+                       get {
+                               return  System.Runtime.InteropServices.Marshal.PtrToStringAuto(NativeMethods.cairo_status_to_string (NativeMethods.cairo_device_status (handle)));
+                       }
+               }
+               public void SetThreadAware (bool value){
+                       NativeMethods.cairo_gl_device_set_thread_aware (handle, value ? 1 : 0);
+               }
+               public Status Acquire()
+               {
+                       return NativeMethods.cairo_device_acquire (handle);
+               }
+               public void Release()
+               {
+                       NativeMethods.cairo_device_release (handle);
+               }
+
+               public void Dispose ()
+               {
+                       Dispose (true);
+                       GC.SuppressFinalize (this);
+               }
+
+               protected virtual void Dispose (bool disposing)
+               {
+                       if (!disposing || CairoDebug.Enabled)
+                               CairoDebug.OnDisposed<Device> (handle, disposing);
+
+                       if (!disposing || handle == IntPtr.Zero)
+                               return;
+
+                       NativeMethods.cairo_device_destroy (handle);
+                       handle = IntPtr.Zero;
+               }
+       }
+}
+
diff --git a/testDrm/Mono.Cairo/DirectFBSurface.cs b/testDrm/Mono.Cairo/DirectFBSurface.cs
new file mode 100644 (file)
index 0000000..afa57b7
--- /dev/null
@@ -0,0 +1,43 @@
+//
+// Mono.Cairo.DirectFBSurface.cs
+//
+// Authors:
+//    Alp Toker
+//
+// (C) Alp Toker, 2006.
+//
+// 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.
+//
+
+using System;
+
+namespace Cairo {
+       public class DirectFBSurface : Surface
+       {
+               internal DirectFBSurface (IntPtr handle, bool owns) : base (handle, owns)
+               {
+               }
+
+               public DirectFBSurface (IntPtr dfb, IntPtr dfb_surface)
+                       : base (NativeMethods.cairo_directfb_surface_create (dfb, dfb_surface), true)
+               {
+               }
+       }
+}
diff --git a/testDrm/Mono.Cairo/Distance.cs b/testDrm/Mono.Cairo/Distance.cs
new file mode 100644 (file)
index 0000000..7cba372
--- /dev/null
@@ -0,0 +1,58 @@
+//
+// Mono.Cairo.Context.cs
+//
+// Author:
+//   Duncan Mak (duncan@ximian.com)
+//   Miguel de Icaza (miguel@novell.com)
+//   Hisham Mardam Bey (hisham.mardambey@gmail.com)
+//   Alp Toker (alp@atoker.com)
+//
+// (C) Ximian Inc, 2003.
+// (C) Novell Inc, 2003.
+//
+// This is an OO wrapper API for the Cairo API.
+//
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// 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.
+//
+
+namespace Cairo {
+
+       public struct Distance
+       {
+               public Distance (double dx, double dy)
+               {
+                       this.dx = dx;
+                       this.dy = dy;
+               }
+
+               double dx, dy;
+               public double Dx {
+                       get { return dx; }
+                       set { dx = value; }
+               }
+
+               public double Dy {
+                       get { return dy; }
+                       set { dy = value; }
+               }
+       }
+}
diff --git a/testDrm/Mono.Cairo/EGLDevice.cs b/testDrm/Mono.Cairo/EGLDevice.cs
new file mode 100644 (file)
index 0000000..45c988a
--- /dev/null
@@ -0,0 +1,41 @@
+//
+// Mono.Cairo.Device.cs
+//
+// Authors:
+//                     JP Bruyère (jp_bruyere@hotmail.com)
+//
+// This is an OO wrapper API for the Cairo API
+//
+// Copyright (C) 2016 JP Bruyère
+//
+// 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.
+//
+using System;
+
+namespace Cairo
+{
+       public class EGLDevice : Device
+       {
+               public EGLDevice (IntPtr dpy, IntPtr gl_ctx) : base (NativeMethods.cairo_egl_device_create (dpy, gl_ctx), true)
+               {
+               }
+       }
+}
+
diff --git a/testDrm/Mono.Cairo/Extend.cs b/testDrm/Mono.Cairo/Extend.cs
new file mode 100644 (file)
index 0000000..0ffee3f
--- /dev/null
@@ -0,0 +1,45 @@
+//
+// Mono.Cairo.Extend.cs
+//
+// Authors:
+//   Duncan Mak (duncan@ximian.com)
+//   Hisham Mardam Bey (hisham.mardambey@gmail.com)
+//   John Luke (john.luke@gmail.com)
+//
+// (C) Ximian, Inc. 2003
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+// Copyright (C) 2005 John Luke
+//
+// 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.
+//
+
+using System;
+
+namespace Cairo
+{
+       [Serializable]
+       public enum Extend
+       {
+               None,
+               Repeat,
+               Reflect,
+               Pad,
+       }
+}
diff --git a/testDrm/Mono.Cairo/FillRule.cs b/testDrm/Mono.Cairo/FillRule.cs
new file mode 100644 (file)
index 0000000..6d8c062
--- /dev/null
@@ -0,0 +1,41 @@
+//
+// Mono.Cairo.FillRule.cs
+//
+// Authors:
+//   Duncan Mak (duncan@ximian.com)
+//   Hisham Mardam Bey (hisham.mardambey@gmail.com)
+//
+// (C) Ximian, Inc. 2003
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// 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.
+//
+
+using System;
+
+namespace Cairo
+{
+       [Serializable]
+       public enum FillRule
+       {
+               Winding,
+               EvenOdd
+       }
+}
diff --git a/testDrm/Mono.Cairo/Filter.cs b/testDrm/Mono.Cairo/Filter.cs
new file mode 100644 (file)
index 0000000..d602ed7
--- /dev/null
@@ -0,0 +1,45 @@
+//
+// Mono.Cairo.Filter.cs
+//
+// Authors:
+//   Duncan Mak (duncan@ximian.com)
+//   Hisham Mardam Bey (hisham.mardambey@gmail.com)
+//
+// (C) Ximian, Inc. 2003
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// 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.
+//
+
+using System;
+
+namespace Cairo
+{
+       [Serializable]
+       public enum Filter
+       {
+               Fast,
+               Good,
+               Best,
+               Nearest,
+               Bilinear,
+               Gaussian,
+       }
+}
diff --git a/testDrm/Mono.Cairo/FontExtents.cs b/testDrm/Mono.Cairo/FontExtents.cs
new file mode 100644 (file)
index 0000000..76c7e65
--- /dev/null
@@ -0,0 +1,104 @@
+//
+// Mono.Cairo.FontExtents.cs
+//
+// Authors: Duncan Mak (duncan@ximian.com)
+//          Hisham Mardam Bey (hisham.mardambey@gmail.com)
+//
+// (C) Ximian, Inc. 2003
+//
+// This is a simplistic binding of the Cairo API to C#. All functions
+// in cairo.h are transcribed into their C# equivelants
+//
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// 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.
+//
+
+using System;
+using System.Runtime.InteropServices;
+
+namespace Cairo
+{
+       [StructLayout (LayoutKind.Sequential)]
+       public struct FontExtents
+       {
+               double ascent;
+               double descent;
+               double height;
+               double maxXAdvance;
+               double maxYAdvance;
+               
+               public double Ascent {
+                       get { return ascent; }
+                       set { ascent = value; }
+               }
+               
+               public double Descent {
+                       get { return descent; }
+                       set { descent = value; }
+               }
+               
+               public double Height {
+                       get { return height; }
+                       set { height = value; }
+               }
+               
+               public double MaxXAdvance {
+                       get { return maxXAdvance; }
+                       set { maxXAdvance = value; }
+               }
+               
+               public double MaxYAdvance {
+                       get { return maxYAdvance; }
+                       set { maxYAdvance = value; }
+               }
+
+               public FontExtents (double ascent, double descent, double height, double maxXAdvance, double maxYAdvance)
+               {
+                       this.ascent = ascent;
+                       this.descent = descent;
+                       this.height = height;
+                       this.maxXAdvance = maxXAdvance;
+                       this.maxYAdvance = maxYAdvance;
+               }
+
+               public override bool Equals (object obj)
+               {
+                       if (obj is FontExtents)
+                               return this == (FontExtents) obj;
+                       return false;
+               }
+
+               public override int GetHashCode ()
+               {
+                       return (int) Ascent ^ (int) Descent ^ (int) Height ^ (int) MaxXAdvance ^ (int) MaxYAdvance;
+               }
+
+               public static bool operator == (FontExtents extents, FontExtents other)
+               {
+                       return extents.Ascent == other.Ascent && extents.Descent == other.Descent && extents.Height == other.Height && extents.MaxXAdvance == other.MaxXAdvance && extents.MaxYAdvance == other.MaxYAdvance;
+               }
+
+               public static bool operator != (FontExtents extents, FontExtents other)
+               {
+                       return !(extents == other);
+               }
+       }
+}
diff --git a/testDrm/Mono.Cairo/FontFace.cs b/testDrm/Mono.Cairo/FontFace.cs
new file mode 100644 (file)
index 0000000..19d8163
--- /dev/null
@@ -0,0 +1,108 @@
+//
+// Mono.Cairo.FontFace.cs
+//
+// Author:
+//   Alp Toker (alp@atoker.com)
+//   Miguel de Icaza (miguel@novell.com)
+//
+// (C) Ximian Inc, 2003.
+//
+// This is an OO wrapper API for the Cairo API.
+//
+// Copyright (C) 2004, 2007 Novell, Inc (http://www.novell.com)
+//
+// 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.
+//
+using System;
+
+namespace Cairo
+{
+       public class FontFace : IDisposable
+       {
+               IntPtr handle;
+
+               internal static FontFace Lookup (IntPtr handle, bool owner)
+               {
+                       if (handle == IntPtr.Zero)
+                               return null;
+                       return new FontFace (handle, owner);
+               }
+
+               ~FontFace ()
+               {
+                       Dispose (false);
+               }
+
+               public void Dispose ()
+               {
+                       Dispose (true);
+                       GC.SuppressFinalize (this);
+               }
+
+               protected virtual void Dispose (bool disposing)
+               {
+                       if (!disposing || CairoDebug.Enabled)
+                               CairoDebug.OnDisposed<FontFace> (handle, disposing);
+
+                       if (!disposing|| handle == IntPtr.Zero)
+                               return;
+
+                       NativeMethods.cairo_font_face_destroy (handle);
+                       handle = IntPtr.Zero;
+               }
+
+               [Obsolete]
+               public FontFace (IntPtr handle) : this (handle, true)
+               {
+               }
+
+               public FontFace (IntPtr handle, bool owned)
+               {
+                       this.handle = handle;
+                       if (!owned)
+                               NativeMethods.cairo_font_face_reference (handle);
+                       if (CairoDebug.Enabled)
+                               CairoDebug.OnAllocated (handle);
+               }
+
+               public IntPtr Handle {
+                       get {
+                               return handle;
+                       }
+               }
+
+               public Status Status {
+                       get {
+                               return NativeMethods.cairo_font_face_status (handle);
+                       }
+               }
+               
+               public FontType FontType {
+                       get {
+                               return NativeMethods.cairo_font_face_get_type (handle);
+                       }
+               }
+
+               public uint ReferenceCount {
+                       get { return NativeMethods.cairo_font_face_get_reference_count (handle); }
+               }
+       }
+}
+
diff --git a/testDrm/Mono.Cairo/FontOptions.cs b/testDrm/Mono.Cairo/FontOptions.cs
new file mode 100644 (file)
index 0000000..5269d54
--- /dev/null
@@ -0,0 +1,143 @@
+//
+// Mono.Cairo.FontOptions.cs
+//
+// Author:
+//   John Luke (john.luke@gmail.com)
+//
+// (C) John Luke 2005.
+//
+// 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.
+//
+
+using System;
+
+namespace Cairo
+{
+       public class FontOptions : IDisposable
+       {
+               IntPtr handle;
+
+               public FontOptions () : this (NativeMethods.cairo_font_options_create ())
+               {
+               }
+
+               ~FontOptions ()
+               {
+                       Dispose (false);
+               }
+
+               internal FontOptions (IntPtr handle)
+               {
+                       this.handle = handle;
+                       if (CairoDebug.Enabled)
+                               CairoDebug.OnAllocated (handle);
+               }
+
+               public FontOptions Copy ()
+               {
+                       return new FontOptions (NativeMethods.cairo_font_options_copy (handle));
+               }
+
+               [Obsolete ("Use Dispose()")]
+               public void Destroy ()
+               {
+                       Dispose ();
+               }
+
+               public void Dispose ()
+               {
+                       Dispose (true);
+                       GC.SuppressFinalize (this);
+               }
+
+               protected virtual void Dispose (bool disposing)
+               {
+                       if (!disposing || CairoDebug.Enabled)
+                               CairoDebug.OnDisposed<FontOptions> (handle, disposing);
+
+                       if (!disposing|| handle == IntPtr.Zero)
+                               return;
+
+                       NativeMethods.cairo_font_options_destroy (handle);
+                       handle = IntPtr.Zero;
+               }
+
+               public static bool operator == (FontOptions options, FontOptions other)
+               {
+                       return Equals (options, other);
+               }
+
+               public static bool operator != (FontOptions options, FontOptions other)
+               {
+                       return !(options == other);
+               }
+
+               public override bool Equals (object other)
+               {
+                       return Equals (other as FontOptions);
+               }
+
+               bool Equals (FontOptions options)
+               {
+                       return options != null && NativeMethods.cairo_font_options_equal (Handle, options.Handle);
+               }
+
+               public IntPtr Handle {
+                       get { return handle; }
+               }
+
+               public override int GetHashCode ()
+               {
+                       return (int) NativeMethods.cairo_font_options_hash (handle);
+               }
+               
+               public void Merge (FontOptions other)
+               {
+                       if (other == null)
+                               throw new ArgumentNullException ("other");
+                       NativeMethods.cairo_font_options_merge (handle, other.Handle);
+               }
+
+               public Antialias Antialias {
+                       get { return NativeMethods.cairo_font_options_get_antialias (handle); }
+                       set { NativeMethods.cairo_font_options_set_antialias (handle, value); }
+               }
+
+               public HintMetrics HintMetrics {
+                       get { return NativeMethods.cairo_font_options_get_hint_metrics (handle);}
+                       set { NativeMethods.cairo_font_options_set_hint_metrics (handle, value); }
+               }
+
+               public HintStyle HintStyle {
+                       get { return NativeMethods.cairo_font_options_get_hint_style (handle);}
+                       set { NativeMethods.cairo_font_options_set_hint_style (handle, value); }
+               }
+
+               public Status Status {
+                       get { return NativeMethods.cairo_font_options_status (handle); }
+               }
+
+               public SubpixelOrder SubpixelOrder {
+                       get { return NativeMethods.cairo_font_options_get_subpixel_order (handle);}
+                       set { NativeMethods.cairo_font_options_set_subpixel_order (handle, value); }
+               }
+       }
+}
+
diff --git a/testDrm/Mono.Cairo/FontSlant.cs b/testDrm/Mono.Cairo/FontSlant.cs
new file mode 100644 (file)
index 0000000..c4e1af7
--- /dev/null
@@ -0,0 +1,42 @@
+//
+// Mono.Cairo.FontSlant.cs
+//
+// Authors:
+//   Duncan Mak (duncan@ximian.com)
+//   Hisham Mardam Bey (hisham.mardambey@gmail.com)
+//
+// (C) Ximian, Inc. 2003
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// 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.
+//
+
+using System;
+
+namespace Cairo
+{
+       [Serializable]
+       public enum FontSlant
+       {
+               Normal,
+               Italic,
+               Oblique
+       }
+}
diff --git a/testDrm/Mono.Cairo/FontType.cs b/testDrm/Mono.Cairo/FontType.cs
new file mode 100644 (file)
index 0000000..0c71fcb
--- /dev/null
@@ -0,0 +1,41 @@
+//
+// Mono.Cairo.FontType.cs
+//
+// Authors:
+//    John Luke
+//
+// (C) John Luke, 2006.
+//
+// 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.
+//
+
+using System;
+
+namespace Cairo {
+
+       [Serializable]
+       public enum FontType
+       {
+               Toy,
+               FreeType,
+               Win32,
+               Atsui,
+       }
+}
diff --git a/testDrm/Mono.Cairo/FontWeight.cs b/testDrm/Mono.Cairo/FontWeight.cs
new file mode 100644 (file)
index 0000000..9d1927d
--- /dev/null
@@ -0,0 +1,41 @@
+//
+// Mono.Cairo.FontWeight.cs
+//
+// Authors:
+//   Duncan Mak (duncan@ximian.com)
+//   Hisham Mardam Bey (hisham.mardambey@gmail.com)
+//
+// (C) Ximian, Inc. 2003
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// 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.
+//
+
+using System;
+
+namespace Cairo
+{
+       [Serializable]
+       public enum FontWeight
+       {
+               Normal,
+               Bold,
+       }
+}
diff --git a/testDrm/Mono.Cairo/Format.cs b/testDrm/Mono.Cairo/Format.cs
new file mode 100644 (file)
index 0000000..f0bded3
--- /dev/null
@@ -0,0 +1,48 @@
+//
+// Mono.Cairo.Format.cs
+//
+// Authors: Duncan Mak (duncan@ximian.com)
+//          Hisham Mardam Bey (hisham.mardambey@gmail.com)
+//
+// (C) Ximian, Inc. 2003
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// 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.
+//
+
+using System;
+
+namespace Cairo
+{
+       [Serializable]
+       public enum Format
+       {
+               Argb32  = 0,
+               Rgb24   = 1,
+               A8      = 2,
+               A1      = 3,
+               Rgb16565 = 4,
+
+               //[Obsolete ("Use Argb32")]
+               ARGB32 = Argb32,
+               //[Obsolete ("Use Rgb24")]
+               RGB24   = Rgb24,
+       }
+}
diff --git a/testDrm/Mono.Cairo/GLSurface.cs b/testDrm/Mono.Cairo/GLSurface.cs
new file mode 100644 (file)
index 0000000..9486c9c
--- /dev/null
@@ -0,0 +1,61 @@
+//
+// Mono.Cairo.GLSurface.cs
+//
+// Authors:
+//                     JP Bruyère (jp_bruyere@hotmail.com)
+//
+// This is an OO wrapper API for the Cairo API
+//
+// Copyright (C) 2016 JP Bruyère
+//
+// 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.
+//
+
+using System;
+
+namespace Cairo {
+
+       public class GLSurface : Surface
+       {
+               
+               public GLSurface (IntPtr ptr, bool own) : base (ptr, own)
+               {}
+
+               public GLSurface (Device device, Cairo.Content content, uint tex, int width, int height)
+                       : base (NativeMethods.cairo_gl_surface_create_for_texture (device.Handle, (uint)content, tex, width, height), true)
+               {}
+
+               public GLSurface (EGLDevice device, IntPtr eglSurf, int width, int height)
+                       : base (NativeMethods.cairo_gl_surface_create_for_egl (device.Handle, eglSurf, width, height), true)
+               {}
+
+               public GLSurface (GLXDevice device, IntPtr window, int width, int height)
+                       : base (NativeMethods.cairo_gl_surface_create_for_window (device.Handle, window, width, height),true)
+               {}
+
+               public GLSurface (WGLDevice device, IntPtr hdc, int width, int height)
+                       : base (NativeMethods.cairo_gl_surface_create_for_dc (device.Handle, hdc, width, height), true)
+               {}
+
+               public void SwapBuffers(){
+                       NativeMethods.cairo_gl_surface_swapbuffers (this.Handle);
+               }
+       }
+}
diff --git a/testDrm/Mono.Cairo/GLXDevice.cs b/testDrm/Mono.Cairo/GLXDevice.cs
new file mode 100644 (file)
index 0000000..189872a
--- /dev/null
@@ -0,0 +1,49 @@
+//
+// Mono.Cairo.Device.cs
+//
+// Authors:
+//                     JP Bruyère (jp_bruyere@hotmail.com)
+//
+// This is an OO wrapper API for the Cairo API
+//
+// Copyright (C) 2016 JP Bruyère
+//
+// 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.
+//
+using System;
+
+namespace Cairo
+{
+       public class GLXDevice : Device
+       {
+               public GLXDevice (IntPtr dpy, IntPtr gl_ctx) : base (NativeMethods.cairo_glx_device_create (dpy, gl_ctx), true)
+               {
+               }
+
+               public IntPtr Display {
+                       get { return NativeMethods.cairo_glx_device_get_display (Handle); }
+               }
+
+               public IntPtr Context {
+                       get { return NativeMethods.cairo_glx_device_get_context (Handle); }
+               }
+       }
+}
+
diff --git a/testDrm/Mono.Cairo/GlitzSurface.cs b/testDrm/Mono.Cairo/GlitzSurface.cs
new file mode 100644 (file)
index 0000000..6da1ac6
--- /dev/null
@@ -0,0 +1,43 @@
+//
+// Mono.Cairo.GlitzSurface.cs
+//
+// Authors:
+//    Alp Toker
+//
+// (C) Alp Toker, 2006.
+//
+// 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.
+//
+
+using System;
+
+namespace Cairo {
+       public class GlitzSurface : Surface
+       {
+               internal GlitzSurface (IntPtr handle, bool owns) : base (handle, owns)
+               {
+               }
+
+               public GlitzSurface (IntPtr glitz_surface)
+                       : base (NativeMethods.cairo_glitz_surface_create (glitz_surface), true)
+               {
+               }
+       }
+}
diff --git a/testDrm/Mono.Cairo/Glyph.cs b/testDrm/Mono.Cairo/Glyph.cs
new file mode 100644 (file)
index 0000000..ec9c2ff
--- /dev/null
@@ -0,0 +1,96 @@
+//
+// Mono.Cairo.Glyph.cs
+//
+// Authors: Duncan Mak (duncan@ximian.com)
+//          Hisham Mardam Bey (hisham.mardambey@gmail.com)
+//
+// (C) Ximian, Inc. 2003
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// 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.
+//
+
+using System;
+using System.Runtime.InteropServices;
+
+namespace Cairo
+{
+       [StructLayout(LayoutKind.Sequential)]
+       public struct Glyph
+       {
+               internal long index;
+               internal double x;
+               internal double y;
+               
+               public Glyph (long index, double x, double y)
+               {
+                       this.index = index;
+                       this.x = x;
+                       this.y = y;
+               }
+               
+               public long Index {
+                       get { return index; }
+                       set { index = value; }
+               }
+               
+               public double X {
+                       get { return x; }
+                       set { x = value; }
+               }
+               
+               public double Y {
+                       get { return y; }
+                       set { y = value; }
+               }
+
+               public override bool Equals (object obj)
+               {
+                       if (obj is Glyph)
+                               return this == (Glyph)obj;
+                       return false;
+               }
+
+               public override int GetHashCode ()
+               {
+                       return (int) Index ^ (int) X ^ (int) Y;
+               }
+
+               internal static IntPtr GlyphsToIntPtr (Glyph[] glyphs)
+               {
+                       int size = Marshal.SizeOf (glyphs[0]);
+                       IntPtr dest = Marshal.AllocHGlobal (size * glyphs.Length);
+                       long pos = dest.ToInt64 ();
+                       for (int i = 0; i < glyphs.Length; i++, pos += size)
+                               Marshal.StructureToPtr (glyphs[i], (IntPtr) pos, false);
+                       return dest;
+               }
+
+               public static bool operator == (Glyph glyph, Glyph other)
+               {
+                       return glyph.Index == other.Index && glyph.X == other.X && glyph.Y == other.Y;
+               }
+
+               public static bool operator != (Glyph glyph, Glyph other)
+               {
+                       return !(glyph == other);
+               }
+       }
+}
diff --git a/testDrm/Mono.Cairo/Gradient.cs b/testDrm/Mono.Cairo/Gradient.cs
new file mode 100644 (file)
index 0000000..0fb617e
--- /dev/null
@@ -0,0 +1,66 @@
+//
+// Mono.Cairo.Gradient.cs
+//
+// Author: Jordi Mas (jordi@ximian.com)
+//         Hisham Mardam Bey (hisham.mardambey@gmail.com)
+// (C) Ximian Inc, 2004.
+//
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// 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.
+//
+
+using System;
+
+namespace Cairo {
+
+       public class Gradient : Pattern
+       {
+               protected Gradient (IntPtr handle, bool owned) : base (handle, owned)
+               {
+               }
+
+               [Obsolete]
+               protected Gradient ()
+               {
+               }
+
+               public int ColorStopCount {
+                       get {
+                               int cnt;
+                               NativeMethods.cairo_pattern_get_color_stop_count (Handle, out cnt);
+                               return cnt;
+                       }
+               }
+
+               public Status AddColorStop (double offset, Color c)
+               {
+                       NativeMethods.cairo_pattern_add_color_stop_rgba (Handle, offset, c.R, c.G, c.B, c.A);
+                       return Status;
+               }
+
+               public Status AddColorStopRgb (double offset, Color c)
+               {
+                       NativeMethods.cairo_pattern_add_color_stop_rgb (Handle, offset, c.R, c.G, c.B);
+                       return Status;
+               }
+       }
+}
+
diff --git a/testDrm/Mono.Cairo/HintMetrics.cs b/testDrm/Mono.Cairo/HintMetrics.cs
new file mode 100644 (file)
index 0000000..d434142
--- /dev/null
@@ -0,0 +1,41 @@
+//
+// Mono.Cairo.HintMetrics.cs
+//
+// Authors: Duncan Mak (duncan@ximian.com)
+//          Hisham Mardam Bey (hisham.mardambey@gmail.com)
+//
+// (C) Ximian, Inc. 2003
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// 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.
+//
+
+using System;
+
+namespace Cairo
+{
+       [Serializable]
+       public enum HintMetrics
+       {
+               Default,
+               Off,
+               On,
+       }
+}
diff --git a/testDrm/Mono.Cairo/HintStyle.cs b/testDrm/Mono.Cairo/HintStyle.cs
new file mode 100644 (file)
index 0000000..bb84820
--- /dev/null
@@ -0,0 +1,43 @@
+//
+// Mono.Cairo.HintStyle.cs
+//
+// Authors: Duncan Mak (duncan@ximian.com)
+//          Hisham Mardam Bey (hisham.mardambey@gmail.com)
+//
+// (C) Ximian, Inc. 2003
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// 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.
+//
+
+using System;
+
+namespace Cairo
+{
+       [Serializable]
+       public enum HintStyle
+       {
+               Default,
+               None,
+               Slight,
+               Medium,
+               Full,
+       }
+}
diff --git a/testDrm/Mono.Cairo/ImageSurface.cs b/testDrm/Mono.Cairo/ImageSurface.cs
new file mode 100644 (file)
index 0000000..98143fe
--- /dev/null
@@ -0,0 +1,104 @@
+//
+// Mono.Cairo.ImageSurface.cs
+//
+// Authors:
+//    Duncan Mak
+//    Miguel de Icaza.
+//
+// (C) Ximian Inc, 2003.
+// (C) Novell, Inc. 2003.
+//
+// This is an OO wrapper API for the Cairo API
+//
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// 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.
+//
+
+using System;
+using System.Runtime.InteropServices;
+
+namespace Cairo {
+
+       public class ImageSurface : Surface
+       {
+               internal ImageSurface (IntPtr handle, bool owns) : base (handle, owns)
+               {
+               }
+
+               public ImageSurface (Format format, int width, int height)
+                       : base (NativeMethods.cairo_image_surface_create (format, width, height), true)
+               {
+               }
+
+               [Obsolete ("Use ImageSurface (byte[] data, Cairo.Format format, int width, int height, int stride)")]
+               public ImageSurface (ref byte[] data, Cairo.Format format, int width, int height, int stride)
+                       : this (data, format, width, height, stride)
+               {
+               }
+
+               public ImageSurface (byte[] data, Format format, int width, int height, int stride)
+                       : base (NativeMethods.cairo_image_surface_create_for_data (data, format, width, height, stride), true)
+               {
+               }
+
+               public ImageSurface (IntPtr data, Format format, int width, int height, int stride)
+                       : base (NativeMethods.cairo_image_surface_create_for_data (data, format, width, height, stride), true)
+               {
+               }
+
+               public ImageSurface (string filename)
+                       : base (NativeMethods.cairo_image_surface_create_from_png (filename), true)
+               {
+               }
+
+               public int Width {
+                       get { return NativeMethods.cairo_image_surface_get_width (Handle); }
+               }
+
+               public int Height {
+                       get { return NativeMethods.cairo_image_surface_get_height (Handle); }
+               }
+
+               public byte[] Data {
+                       get {
+                               IntPtr ptr = NativeMethods.cairo_image_surface_get_data (Handle);
+                               int length = Height * Stride;
+                               byte[] data = new byte[length];
+                               Marshal.Copy (ptr, data, 0, length);
+                               return data;
+                       }
+               }
+
+               public IntPtr DataPtr {
+                       get {
+                               return NativeMethods.cairo_image_surface_get_data (Handle);
+                       }
+               }
+
+               public Format Format {
+                       get { return NativeMethods.cairo_image_surface_get_format (Handle); }
+               }
+
+               public int Stride {
+                       get { return NativeMethods.cairo_image_surface_get_stride (Handle); }
+               }
+       }
+}
diff --git a/testDrm/Mono.Cairo/LineCap.cs b/testDrm/Mono.Cairo/LineCap.cs
new file mode 100644 (file)
index 0000000..57cfdec
--- /dev/null
@@ -0,0 +1,41 @@
+//
+// Mono.Cairo.LineCap.cs
+//
+// Authors: Duncan Mak (duncan@ximian.com)
+//          Hisham Mardam Bey (hisham.mardambey@gmail.com)
+//
+// (C) Ximian, Inc. 2003
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// 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.
+//
+
+using System;
+
+namespace Cairo
+{
+       [Serializable]
+       public enum LineCap
+       {
+               Butt,
+               Round,
+               Square,
+       }
+}
diff --git a/testDrm/Mono.Cairo/LineJoin.cs b/testDrm/Mono.Cairo/LineJoin.cs
new file mode 100644 (file)
index 0000000..439b2a5
--- /dev/null
@@ -0,0 +1,42 @@
+//
+// Mono.Cairo.LineJoin.cs
+//
+// Authors: Duncan Mak (duncan@ximian.com)
+//          Hisham Mardam Bey (hisham.mardambey@gmail.com)
+//
+// (C) Ximian, Inc. 2003
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// 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.
+//
+
+using System;
+
+namespace Cairo
+{
+       [Serializable]
+       public enum LineJoin
+       {
+               Miter,
+               Round,
+               Bevel
+       }
+}
+
diff --git a/testDrm/Mono.Cairo/LinearGradient.cs b/testDrm/Mono.Cairo/LinearGradient.cs
new file mode 100644 (file)
index 0000000..85fdea8
--- /dev/null
@@ -0,0 +1,59 @@
+//
+// Mono.Cairo.LinearGradient.cs
+//
+// Author: Jordi Mas (jordi@ximian.com)
+//         Hisham Mardam Bey (hisham.mardambey@gmail.com)
+// (C) Ximian Inc, 2004.
+//
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// 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.
+//
+
+using System;
+
+namespace Cairo {
+
+       public class LinearGradient : Gradient
+       {
+               internal LinearGradient (IntPtr handle, bool owned) : base (handle, owned)
+               {
+               }
+
+               public LinearGradient (double x0, double y0, double x1, double y1)
+                       : base (NativeMethods.cairo_pattern_create_linear (x0, y0, x1, y1), true)
+               {
+               }
+
+               public PointD[] LinearPoints {
+                       get {
+                               double x0, y0, x1, y1;
+                               PointD[] points = new PointD [2];
+
+                               NativeMethods.cairo_pattern_get_linear_points (Handle, out x0, out y0, out x1, out y1);
+
+                               points[0] = new PointD (x0, y0);
+                               points[1] = new PointD (x1, y1);
+                               return points;
+                       }
+               }
+       }
+}
+
diff --git a/testDrm/Mono.Cairo/Matrix.cs b/testDrm/Mono.Cairo/Matrix.cs
new file mode 100644 (file)
index 0000000..83ffce4
--- /dev/null
@@ -0,0 +1,193 @@
+//
+// Mono.Cairo.Matrix.cs
+//
+// Author: Duncan Mak
+//         Hisham Mardam Bey (hisham.mardambey@gmail.com)
+//         Idan Gazit (idan@fastmail.fm)
+//
+// (C) Ximian Inc, 2003 - 2005.
+//
+// This is an OO wrapper API for the Cairo API
+//
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// 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.
+//
+
+using System;
+using System.Runtime.InteropServices;
+
+namespace Cairo {
+
+       [StructLayout(LayoutKind.Sequential)]
+       public class Matrix : ICloneable
+       {
+               public double Xx;
+               public double Yx;
+               public double Xy;
+               public double Yy;
+               public double X0;
+               public double Y0;
+
+               public Matrix (double xx, double yx, double xy, double yy,
+                               double x0, double y0)
+               {
+                       this.Xx = xx; this.Yx = yx; this.Xy = xy;
+                       this.Yy = yy; this.X0 = x0; this.Y0 = y0;
+               }
+
+               public Matrix ()
+               {
+                       this.InitIdentity ();
+               }
+
+               public bool IsIdentity ()
+               {
+                       return (this == new Matrix ());
+               }
+
+               public void InitIdentity ()
+               {
+                       // this.Init(1,0,0,1,0,0);
+                       NativeMethods.cairo_matrix_init_identity (this);
+               }
+
+               public void Init (double xx, double yx, double xy, double yy,
+                                 double x0, double y0)
+               {
+                       this.Xx = xx; this.Yx = yx; this.Xy = xy;
+                       this.Yy = yy; this.X0 = x0; this.Y0 = y0;
+               }
+
+               public void InitTranslate (double tx, double ty)
+               {
+                       //this.Init (1, 0, 0, 1, tx, ty);
+                       NativeMethods.cairo_matrix_init_translate (this, tx, ty);
+               }
+
+               public void Translate (double tx, double ty)
+               {
+                       NativeMethods.cairo_matrix_translate (this, tx, ty);
+               }
+
+               public void InitScale (double sx, double sy)
+               {
+                       //this.Init (sx, 0, 0, sy, 0, 0);
+                       NativeMethods.cairo_matrix_init_scale (this, sx, sy);
+               }
+
+               public void Scale (double sx, double sy)
+               {
+                       NativeMethods.cairo_matrix_scale (this, sx, sy);
+               }
+
+               public void InitRotate (double radians)
+               {
+                       /*
+                       double s, c;
+                       s = Math.Sin (radians);
+                       c = Math.Cos (radians);
+                       this.Init (c, s, -s, c, 0, 0);
+                       */
+                       NativeMethods.cairo_matrix_init_rotate (this, radians);
+               }
+
+               public void Rotate (double radians)
+               {
+                       NativeMethods.cairo_matrix_rotate (this, radians);
+               }
+
+               public Cairo.Status Invert ()
+               {
+                       return NativeMethods.cairo_matrix_invert (this);
+               }
+
+               public void Multiply (Matrix b)
+               {
+                       Matrix a = (Matrix) this.Clone ();
+                       NativeMethods.cairo_matrix_multiply (this, a, b);
+               }
+
+               public static Matrix Multiply (Matrix a, Matrix b) {
+                       Matrix result = new Matrix ();
+                       NativeMethods.cairo_matrix_multiply (result, a, b);
+                       return result;
+               }
+
+
+               public void TransformDistance (ref double dx, ref double dy)
+               {
+                       NativeMethods.cairo_matrix_transform_distance (this, ref dx, ref dy);
+               }
+
+               public void TransformPoint (ref double x, ref double y)
+               {
+                       NativeMethods.cairo_matrix_transform_point (this, ref x, ref y);
+               }
+
+               public override String ToString ()
+               {
+                       String s = String.Format ("xx:{0:##0.0#} yx:{1:##0.0#} xy:{2:##0.0#} yy:{3:##0.0#} x0:{4:##0.0#} y0:{5:##0.0#}",
+                               this.Xx, this.Yx, this.Xy, this.Yy, this.X0, this.Y0);
+                       return s;
+               }
+
+               public static bool operator == (Matrix lhs, Matrix rhs)
+               {
+                       return (lhs.Xx == rhs.Xx &&
+                               lhs.Xy == rhs.Xy &&
+                               lhs.Yx == rhs.Yx &&
+                               lhs.Yy == rhs.Yy &&
+                               lhs.X0 == rhs.X0 &&
+                               lhs.Y0 == rhs.Y0 );
+               }
+
+               public static bool operator != (Matrix lhs, Matrix rhs)
+               {
+                       return !(lhs==rhs);
+               }
+
+
+
+               public override bool Equals(object o)
+               {
+                       if (! (o is Matrix))
+                               return false;
+                       else
+                               return (this == (Matrix) o);
+               }
+
+               public override int GetHashCode()
+               {
+                       return  (int)this.Xx ^ (int)this.Xx>>32 ^
+                               (int)this.Xy ^ (int)this.Xy>>32 ^
+                               (int)this.Yx ^ (int)this.Yx>>32 ^
+                               (int)this.Yy ^ (int)this.Yy>>32 ^
+                               (int)this.X0 ^ (int)this.X0>>32 ^
+                               (int)this.Y0 ^ (int)this.Y0>>32;
+               }
+
+               public object Clone()
+               {
+                       return this.MemberwiseClone ();
+               }
+
+       }
+}
diff --git a/testDrm/Mono.Cairo/NativeMethods.cs b/testDrm/Mono.Cairo/NativeMethods.cs
new file mode 100644 (file)
index 0000000..9726cb8
--- /dev/null
@@ -0,0 +1,948 @@
+//
+// Cairo.cs - a simplistic binding of the Cairo API to C#.
+//
+// Authors: Duncan Mak (duncan@ximian.com)
+//          Hisham Mardam Bey (hisham.mardambey@gmail.com)
+//          John Luke (john.luke@gmail.com)
+//          Alp Toker (alp@atoker.com)
+//
+// (C) Ximian, Inc. 2003
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+// Copyright (C) 2005 John Luke
+// Copyright (C) 2006 Alp Toker
+//
+// 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.
+//
+
+using System;
+using System.Runtime.InteropServices;
+
+namespace Cairo
+{
+       // sort the functions like in the following page so it is easier to find what is missing
+       // http://cairographics.org/manual/index-all.html
+
+       internal static class NativeMethods
+       {
+#if MONOTOUCH
+               const string cairo = "__Internal";
+#else
+               const string cairo = "libcairo-2.dll";
+#endif
+               
+               //[DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               //internal static extern void cairo_append_path (IntPtr cr, Path path);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_arc (IntPtr cr, double xc, double yc, double radius, double angle1, double angle2);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_arc_negative (IntPtr cr, double xc, double yc, double radius, double angle1, double angle2);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern IntPtr cairo_atsui_font_face_create_for_atsu_font_id (IntPtr font_id);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_clip (IntPtr cr);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_clip_preserve (IntPtr cr);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_clip_extents (IntPtr cr, out double x1, out double y1, out double x2, out double y2);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_close_path (IntPtr cr);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_copy_page (IntPtr cr);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern IntPtr cairo_copy_path (IntPtr cr);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern IntPtr cairo_copy_path_flat (IntPtr cr);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern IntPtr cairo_append_path (IntPtr cr, IntPtr path);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern IntPtr cairo_create (IntPtr target);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_curve_to (IntPtr cr, double x1, double y1, double x2, double y2, double x3, double y3);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_debug_reset_static_data ();
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_destroy (IntPtr cr);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_device_to_user (IntPtr cr, ref double x, ref double y);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_device_to_user_distance (IntPtr cr, ref double dx, ref double dy);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_fill (IntPtr cr);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_fill_extents (IntPtr cr, out double x1, out double y1, out double x2, out double y2);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_fill_preserve (IntPtr cr);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_font_extents (IntPtr cr, out FontExtents extents);
+               
+               // FontFace
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_font_face_destroy (IntPtr font_face);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern FontType cairo_font_face_get_type (IntPtr font_face);
+
+               //[DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               //internal static extern void cairo_font_face_get_user_data (IntPtr font_face);
+               
+               //[DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               //internal static extern void cairo_font_face_set_user_data (IntPtr font_face);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern IntPtr cairo_font_face_reference (IntPtr font_face);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern Status cairo_font_face_status (IntPtr font_face);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern uint cairo_font_face_get_reference_count (IntPtr surface);
+               
+               // FontOptions
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern IntPtr cairo_font_options_copy (IntPtr original);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern IntPtr cairo_font_options_create ();
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_font_options_destroy (IntPtr options);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               [return: MarshalAs (UnmanagedType.U1)]
+               internal static extern bool cairo_font_options_equal (IntPtr options, IntPtr other);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern Antialias cairo_font_options_get_antialias (IntPtr options);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern HintMetrics cairo_font_options_get_hint_metrics (IntPtr options);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern HintStyle cairo_font_options_get_hint_style (IntPtr options);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern SubpixelOrder cairo_font_options_get_subpixel_order (IntPtr options);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern long cairo_font_options_hash (IntPtr options);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_font_options_merge (IntPtr options, IntPtr other);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_font_options_set_antialias (IntPtr options, Antialias aa);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_font_options_set_hint_metrics (IntPtr options, HintMetrics metrics);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_font_options_set_hint_style (IntPtr options, HintStyle style);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_font_options_set_subpixel_order (IntPtr options, SubpixelOrder order);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern Status cairo_font_options_status (IntPtr options);
+               
+               // Freetype / FontConfig 
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern IntPtr cairo_ft_font_face_create_for_ft_face (IntPtr face, int load_flags);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern IntPtr cairo_ft_font_face_create_for_pattern (IntPtr fc_pattern);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_ft_font_options_substitute (FontOptions options, IntPtr pattern);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern IntPtr cairo_ft_scaled_font_lock_face (IntPtr scaled_font);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_ft_scaled_font_unlock_face (IntPtr scaled_font);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern Antialias cairo_get_antialias (IntPtr cr);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_get_current_point (IntPtr cr, out double x, out double y);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern FillRule cairo_get_fill_rule (IntPtr cr);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern IntPtr cairo_get_font_face (IntPtr cr);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_get_font_matrix (IntPtr cr, out Matrix matrix);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_get_font_options (IntPtr cr, IntPtr options);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern IntPtr cairo_get_group_target (IntPtr cr);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern LineCap cairo_get_line_cap (IntPtr cr);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern LineJoin cairo_get_line_join (IntPtr cr);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern double cairo_get_line_width (IntPtr cr);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_get_matrix (IntPtr cr, Matrix matrix);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern double cairo_get_miter_limit (IntPtr cr);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern Operator cairo_get_operator (IntPtr cr);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern uint cairo_get_reference_count (IntPtr surface);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern IntPtr cairo_get_source (IntPtr cr);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern IntPtr cairo_get_target (IntPtr cr);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern double cairo_get_tolerance (IntPtr cr);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern IntPtr cairo_glitz_surface_create (IntPtr surface);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_glyph_extents (IntPtr cr, IntPtr glyphs, int num_glyphs, out TextExtents extents);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_glyph_path (IntPtr cr, IntPtr glyphs, int num_glyphs);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               [return: MarshalAs (UnmanagedType.U1)]
+               internal static extern bool cairo_has_current_point (IntPtr cr);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_identity_matrix (IntPtr cr);
+               
+               // ImageSurface
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern IntPtr cairo_image_surface_create (Cairo.Format format, int width, int height);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern IntPtr cairo_image_surface_create_for_data (byte[] data, Cairo.Format format, int width, int height, int stride);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern IntPtr cairo_image_surface_create_for_data (IntPtr data, Cairo.Format format, int width, int height, int stride);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern IntPtr cairo_image_surface_create_from_png  (string filename);
+               
+               //[DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               //internal static extern IntPtr cairo_image_surface_create_from_png_stream  (string filename);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern IntPtr cairo_image_surface_get_data (IntPtr surface);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern Format cairo_image_surface_get_format (IntPtr surface);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern int cairo_image_surface_get_height (IntPtr surface);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern int cairo_image_surface_get_stride (IntPtr surface);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern int cairo_image_surface_get_width  (IntPtr surface);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               [return: MarshalAs (UnmanagedType.U1)]
+               internal static extern bool cairo_in_clip (IntPtr cr, double x, double y);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               [return: MarshalAs (UnmanagedType.U1)]
+               internal static extern bool cairo_in_fill (IntPtr cr, double x, double y);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               [return: MarshalAs (UnmanagedType.U1)]
+               internal static extern bool cairo_in_stroke (IntPtr cr, double x, double y);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_line_to (IntPtr cr, double x, double y);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_mask (IntPtr cr, IntPtr pattern);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_mask_surface (IntPtr cr, IntPtr surface, double x, double y);
+               
+               // Matrix
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_matrix_init (Matrix matrix, double xx, double yx, double xy, double yy, double x0, double y0);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_matrix_init_identity (Matrix matrix);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_matrix_init_rotate (Matrix matrix, double radians);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_matrix_init_scale (Matrix matrix, double sx, double sy);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_matrix_init_translate (Matrix matrix, double tx, double ty);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern Status cairo_matrix_invert (Matrix matrix);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_matrix_multiply (Matrix result, Matrix a, Matrix b);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_matrix_scale (Matrix matrix, double sx, double sy);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_matrix_rotate (Matrix matrix, double radians);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_matrix_transform_distance (Matrix matrix, ref double dx, ref double dy);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_matrix_transform_point (Matrix matrix, ref double x, ref double y);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_matrix_translate (Matrix matrix, double tx, double ty);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_move_to (IntPtr cr, double x, double y);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_new_path (IntPtr cr);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_new_sub_path (IntPtr cr);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_paint (IntPtr cr);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_paint_with_alpha (IntPtr cr, double alpha);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_path_destroy (IntPtr path);
+               
+               // Pattern
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_pattern_add_color_stop_rgb (IntPtr pattern, double offset, double red, double green, double blue);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_pattern_add_color_stop_rgba (IntPtr pattern, double offset, double red, double green, double blue, double alpha);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern Status cairo_pattern_get_color_stop_count (IntPtr pattern, out int count);
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern Status cairo_pattern_get_color_stop_rgba (IntPtr pattern, int index, out double offset, out double red, out double green, out double blue, out double alpha);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern IntPtr cairo_pattern_create_for_surface (IntPtr surface);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern Status cairo_pattern_get_surface (IntPtr pattern, out IntPtr surface);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern IntPtr cairo_pattern_create_linear (double x0, double y0, double x1, double y1);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern Status cairo_pattern_get_linear_points (IntPtr pattern, out double x0, out double y0, out double x1, out double y1);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern IntPtr cairo_pattern_create_radial (double cx0, double cy0, double radius0, double cx1, double cy1, double radius1);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern Status cairo_pattern_get_radial_circles (IntPtr pattern, out double x0, out double y0, out double r0, out double x1, out double y1, out double r1);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern IntPtr cairo_pattern_create_rgb (double r, double g, double b);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern IntPtr cairo_pattern_create_rgba (double r, double g, double b, double a);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern Status cairo_pattern_get_rgba (IntPtr pattern, out double red, out double green, out double blue, out double alpha);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_pattern_destroy (IntPtr pattern);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern Extend cairo_pattern_get_extend (IntPtr pattern);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern Filter cairo_pattern_get_filter (IntPtr pattern);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_pattern_get_matrix (IntPtr pattern, Matrix matrix);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern PatternType cairo_pattern_get_type (IntPtr pattern);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern IntPtr cairo_pattern_reference (IntPtr pattern);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_pattern_set_extend (IntPtr pattern, Extend extend);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_pattern_set_filter (IntPtr pattern, Filter filter);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_pattern_set_matrix (IntPtr pattern, Matrix matrix);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern Status cairo_pattern_status (IntPtr pattern);
+       
+               // PdfSurface
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern IntPtr cairo_pdf_surface_create (string filename, double width, double height);
+               
+               //[DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               //internal static extern IntPtr cairo_pdf_surface_create_for_stream (string filename, double width, double height);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_pdf_surface_set_size (IntPtr surface, double x, double y);
+               
+               // PostscriptSurface
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern IntPtr cairo_ps_surface_create (string filename, double width, double height);
+               
+               //[DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               //internal static extern IntPtr cairo_ps_surface_create_for_stream (string filename, double width, double height);
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_ps_surface_dsc_begin_page_setup (IntPtr surface);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_ps_surface_dsc_begin_setup (IntPtr surface);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_ps_surface_dsc_comment (IntPtr surface, string comment);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_ps_surface_set_size (IntPtr surface, double x, double y);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern IntPtr cairo_pop_group (IntPtr cr);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_pop_group_to_source (IntPtr cr);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_push_group (IntPtr cr);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_push_group_with_content (IntPtr cr, Content content);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern IntPtr cairo_quartz_surface_create (IntPtr context, bool flipped, int width, int height);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_rectangle (IntPtr cr, double x, double y, double width, double height);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_reference (IntPtr cr);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern bool cairo_region_contains_point (IntPtr region, int x, int y);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern RegionOverlap cairo_region_contains_rectangle (IntPtr region, ref RectangleInt rectangle);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern IntPtr cairo_region_copy (IntPtr original);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern IntPtr cairo_region_create ();
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern IntPtr cairo_region_create_rectangle (ref RectangleInt rect);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern IntPtr cairo_region_create_rectangles (RectangleInt[] rects, int count);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_region_destroy (IntPtr region);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern bool cairo_region_equal (IntPtr a, IntPtr b);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_region_get_extents (IntPtr region, out RectangleInt extents);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_region_get_rectangle (IntPtr region, int nth, out RectangleInt rectangle);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern Status cairo_region_intersect (IntPtr dst, IntPtr other);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern Status cairo_region_intersect_rectangle (IntPtr dst, ref RectangleInt rectangle);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern bool cairo_region_is_empty (IntPtr region);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern int cairo_region_num_rectangles (IntPtr region);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern IntPtr cairo_region_reference (IntPtr region);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern Status cairo_region_status (IntPtr region);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern Status cairo_region_subtract (IntPtr dst, IntPtr other);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern Status cairo_region_subtract_rectangle (IntPtr dst, ref RectangleInt rectangle);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_region_translate (IntPtr region, int dx, int dy);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern Status cairo_region_union (IntPtr dst, IntPtr other);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern Status cairo_region_union_rectangle (IntPtr dst, ref RectangleInt rectangle);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern Status cairo_region_xor (IntPtr dst, IntPtr other);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern Status cairo_region_xor_rectangle (IntPtr dst, ref RectangleInt rectangle);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_rel_curve_to (IntPtr cr, double dx1, double dy1, double dx2, double dy2, double dx3, double dy3);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_rel_line_to (IntPtr cr, double dx, double dy);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_rel_move_to (IntPtr cr, double dx, double dy);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_reset_clip (IntPtr cr);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_restore (IntPtr cr);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_rotate (IntPtr cr, double angle);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_save (IntPtr cr);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_scale (IntPtr cr, double sx, double sy);
+               
+               // ScaledFont
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern IntPtr cairo_scaled_font_create (IntPtr fontFace, Matrix matrix, Matrix ctm, IntPtr options);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern IntPtr cairo_scaled_font_destroy (IntPtr scaled_font);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_scaled_font_extents (IntPtr scaled_font, out FontExtents extents);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_scaled_font_get_ctm (IntPtr scaled_font, out Matrix matrix);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern IntPtr cairo_scaled_font_get_font_face (IntPtr scaled_font);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_scaled_font_get_font_matrix (IntPtr scaled_font, out Matrix matrix);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern IntPtr cairo_scaled_font_get_font_options (IntPtr scaled_font);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern FontType cairo_scaled_font_get_type (IntPtr scaled_font);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_scaled_font_glyph_extents (IntPtr scaled_font, IntPtr glyphs, int num_glyphs, out TextExtents extents);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern IntPtr cairo_scaled_font_reference (IntPtr scaled_font);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern Status cairo_scaled_font_status (IntPtr scaled_font);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_set_scaled_font (IntPtr cr, IntPtr scaled_font);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern IntPtr cairo_get_scaled_font (IntPtr cr);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_scaled_font_text_extents (IntPtr scaled_font, byte[] utf8, out TextExtents extents);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_select_font_face (IntPtr cr, string family, FontSlant slant, FontWeight weight);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_set_antialias (IntPtr cr, Antialias antialias);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_set_dash (IntPtr cr, double [] dashes, int ndash, double offset);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_get_dash (IntPtr cr, IntPtr dashes, out double offset);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern int cairo_get_dash_count (IntPtr cr);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_set_fill_rule (IntPtr cr, Cairo.FillRule fill_rule);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_set_font_face (IntPtr cr, IntPtr fontFace);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_set_font_matrix (IntPtr cr, Matrix matrix);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_set_font_options (IntPtr cr, IntPtr options);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_set_font_size (IntPtr cr, double size);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_set_line_cap (IntPtr cr, LineCap line_cap);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_set_line_join (IntPtr cr, LineJoin line_join);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_set_line_width (IntPtr cr, double width);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_set_matrix (IntPtr cr, Matrix matrix);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_set_miter_limit (IntPtr cr, double limit);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_set_operator (IntPtr cr, Cairo.Operator op);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_set_source (IntPtr cr, IntPtr pattern);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_set_source_rgb (IntPtr cr, double red, double green, double blue);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_set_source_rgba (IntPtr cr, double red, double green, double blue, double alpha);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_set_source_surface (IntPtr cr, IntPtr surface, double x, double y);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_set_tolerance (IntPtr cr, double tolerance);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_show_glyphs (IntPtr ct, IntPtr glyphs, int num_glyphs);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_show_page (IntPtr cr);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_show_text (IntPtr cr, byte[] utf8);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern Status cairo_status (IntPtr cr);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern IntPtr cairo_status_to_string (Status status);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_stroke (IntPtr cr);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_stroke_extents (IntPtr cr, out double x1, out double y1, out double x2, out double y2);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_stroke_preserve (IntPtr cr);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_rectangle_list_destroy (IntPtr rectangle_list);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern IntPtr cairo_copy_clip_rectangle_list (IntPtr cr);
+
+               // Surface
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern IntPtr cairo_surface_create_similar (IntPtr surface, Cairo.Content content, int width, int height);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_surface_destroy (IntPtr surface);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_surface_finish (IntPtr surface);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_surface_flush (IntPtr surface);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern Content cairo_surface_get_content (IntPtr surface);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_surface_get_device_offset (IntPtr surface, out double x, out double y);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_surface_get_font_options (IntPtr surface, IntPtr FontOptions);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern uint cairo_surface_get_reference_count (IntPtr surface);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern SurfaceType cairo_surface_get_type (IntPtr surface);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_surface_mark_dirty (IntPtr surface);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_surface_mark_dirty_rectangle (IntPtr surface, int x, int y, int width, int height);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern IntPtr cairo_surface_reference (IntPtr surface);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_surface_set_device_offset (IntPtr surface, double x, double y);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_surface_set_fallback_resolution (IntPtr surface, double x, double y);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern Status cairo_surface_status (IntPtr surface);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_surface_write_to_png (IntPtr surface, string filename);
+               
+               //[DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               //internal static extern void cairo_surface_write_to_png_stream (IntPtr surface, WriteFunc writeFunc);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern IntPtr cairo_svg_surface_create (string fileName, double width, double height);
+               
+               //[DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               //internal static extern IntPtr cairo_svg_surface_create_for_stream (double width, double height);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern IntPtr cairo_svg_surface_restrict_to_version (IntPtr surface, SvgVersion version);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_text_extents (IntPtr cr, byte[] utf8, out TextExtents extents);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_text_path (IntPtr ct, byte[] utf8);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_transform (IntPtr cr, Matrix matrix);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_translate (IntPtr cr, double tx, double ty);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_user_to_device (IntPtr cr, ref double x, ref double y);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_user_to_device_distance (IntPtr cr, ref double dx, ref double dy);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern int cairo_version ();
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern IntPtr cairo_version_string ();
+               
+               // DirectFBSurface
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern IntPtr cairo_directfb_surface_create (IntPtr dfb, IntPtr surface);
+               
+               // win32 fonts
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern IntPtr cairo_win32_font_face_create_for_logfontw (IntPtr logfontw);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_win32_scaled_font_done_font (IntPtr scaled_font);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern double cairo_win32_scaled_font_get_metrics_factor (IntPtr scaled_font);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern Status cairo_win32_scaled_font_select_font (IntPtr scaled_font, IntPtr hdc);
+               
+               // win32 surface
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern IntPtr cairo_win32_surface_create (IntPtr hdc);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern IntPtr cairo_win32_surface_create_with_ddb (IntPtr hdc, Format format, int width, int height);
+
+               // XcbSurface
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern IntPtr cairo_xcb_surface_create (IntPtr connection, uint drawable, IntPtr visual, int width, int height);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern IntPtr cairo_xcb_surface_create_for_bitmap (IntPtr connection, uint bitmap, IntPtr screen, int width, int height);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_xcb_surface_set_size (IntPtr surface, int width, int height);
+               
+               // XlibSurface
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern IntPtr cairo_xlib_surface_create (IntPtr display, IntPtr drawable, IntPtr visual, int width, int height);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern IntPtr cairo_xlib_surface_create_for_bitmap (IntPtr display, IntPtr bitmap, IntPtr screen, int width, int height);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern int cairo_xlib_surface_get_depth (IntPtr surface);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern IntPtr cairo_xlib_surface_get_display (IntPtr surface);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern IntPtr cairo_xlib_surface_get_drawable (IntPtr surface);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern int cairo_xlib_surface_get_height (IntPtr surface);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern IntPtr cairo_xlib_surface_get_screen (IntPtr surface);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern IntPtr cairo_xlib_surface_get_visual (IntPtr surface);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern int cairo_xlib_surface_get_width (IntPtr surface);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_xlib_surface_set_drawable (IntPtr surface, IntPtr drawable, int width, int height);
+               
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_xlib_surface_set_size (IntPtr surface, int width, int height);
+
+               #region GLSurface
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern IntPtr cairo_gl_surface_create (IntPtr device, uint content, int width, int height);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern IntPtr cairo_gl_surface_create_for_texture (IntPtr device, uint content, uint tex, int width, int height);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_gl_surface_set_size (IntPtr surface, int width, int height);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern int cairo_gl_surface_get_width (IntPtr surface);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern int cairo_gl_surface_get_height (IntPtr surface);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_gl_surface_swapbuffers (IntPtr surf);
+               #endregion
+
+               #region GLX Functions
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern IntPtr cairo_glx_device_create (IntPtr dpy, IntPtr gl_ctx);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern IntPtr cairo_glx_device_get_display (IntPtr device);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern IntPtr cairo_glx_device_get_context (IntPtr device);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern IntPtr cairo_gl_surface_create_for_window (IntPtr device, IntPtr window, int width, int height);
+               #endregion
+
+               #region WGL Fucntions
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern IntPtr cairo_wgl_device_create (IntPtr hglrc);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern IntPtr cairo_wgl_device_get_context (IntPtr device);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern IntPtr cairo_gl_surface_create_for_dc (IntPtr device, IntPtr hdc, int width, int height);
+               #endregion
+
+               #region EGL Functions
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern IntPtr cairo_egl_device_create (IntPtr dpy, IntPtr gl_ctx);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern IntPtr cairo_gl_surface_create_for_egl (IntPtr device, IntPtr eglSurface, int width, int height);
+               #endregion
+
+               #region Device
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern IntPtr cairo_device_reference (IntPtr device);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern Status cairo_device_status(IntPtr device);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_device_destroy (IntPtr device);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern Status cairo_device_acquire(IntPtr device);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_device_release(IntPtr device);
+
+               [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)]
+               internal static extern void cairo_gl_device_set_thread_aware(IntPtr device, int value);
+               #endregion
+       }
+}
\ No newline at end of file
diff --git a/testDrm/Mono.Cairo/Operator.cs b/testDrm/Mono.Cairo/Operator.cs
new file mode 100644 (file)
index 0000000..c1ced71
--- /dev/null
@@ -0,0 +1,56 @@
+//
+// Mono.Cairo.Operator.cs
+//
+// Authors: Duncan Mak (duncan@ximian.com)
+//          Hisham Mardam Bey (hisham.mardambey@gmail.com)
+//          John Luke (john.luke@gmail.com)
+//
+// (C) Ximian, Inc. 2003
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+// Copyright (C) 2005 John Luke
+//
+// 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.
+//
+
+using System;
+
+namespace Cairo
+{
+       [Serializable]
+       public enum Operator
+       {
+               Clear,
+               Source,
+               Over,
+               In,
+               Out,
+               Atop,
+
+               Dest,
+               DestOver,
+               DestIn,
+               DestOut,
+               DestAtop,
+               
+               Xor,
+               Add,
+               Saturate,
+       }
+}
diff --git a/testDrm/Mono.Cairo/PSSurface.cs b/testDrm/Mono.Cairo/PSSurface.cs
new file mode 100644 (file)
index 0000000..9d6b73b
--- /dev/null
@@ -0,0 +1,64 @@
+//
+// Mono.Cairo.PostscriptSurface.cs
+//
+// Authors:
+//    John Luke
+//
+// (C) John Luke, 2006.
+//
+// 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.
+//
+
+using System;
+
+namespace Cairo {
+
+       public class PSSurface : Surface
+       {
+               internal PSSurface (IntPtr handle, bool owns) : base (handle, owns)
+               {
+               }
+
+               public PSSurface (string filename, double width, double height)
+                       : base (NativeMethods.cairo_ps_surface_create (filename, width, height), true)
+               {
+               }
+
+               public void BeginPageSetup ()
+               {
+                       NativeMethods.cairo_ps_surface_dsc_begin_page_setup (Handle);
+               }
+
+               public void BeginSetup ()
+               {
+                       NativeMethods.cairo_ps_surface_dsc_begin_setup (Handle);
+               }
+
+               public void DscComment (string comment)
+               {
+                       NativeMethods.cairo_ps_surface_dsc_comment (Handle, comment);
+               }
+
+               public void SetSize (double width, double height)
+               {
+                       NativeMethods.cairo_ps_surface_set_size (Handle, width, height);
+               }
+       }
+}
diff --git a/testDrm/Mono.Cairo/Path.cs b/testDrm/Mono.Cairo/Path.cs
new file mode 100644 (file)
index 0000000..184c606
--- /dev/null
@@ -0,0 +1,73 @@
+//
+// Mono.Cairo.Context.cs
+//
+// Author:
+//   Miguel de Icaza (miguel@novell.com)
+//
+// This is an OO wrapper API for the Cairo API.
+//
+// Copyright 2007 Novell, Inc (http://www.novell.com)
+//
+// 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.
+//
+
+using System;
+using System.Runtime.InteropServices;
+using Cairo;
+
+namespace Cairo {
+
+       public class Path : IDisposable
+       {
+               IntPtr handle = IntPtr.Zero;
+
+               internal Path (IntPtr handle)
+               {
+                       this.handle = handle;
+                       if (CairoDebug.Enabled)
+                               CairoDebug.OnAllocated (handle);
+               }
+
+               ~Path ()
+               {
+                       Dispose (false);
+               }
+
+               public IntPtr Handle { get { return handle; } }
+
+               public void Dispose ()
+               {
+                       Dispose (true);
+                       GC.SuppressFinalize (this);
+               }
+
+               protected virtual void Dispose (bool disposing)
+               {
+                       if (!disposing || CairoDebug.Enabled)
+                               CairoDebug.OnDisposed<Path> (handle, disposing);
+
+                       if (!disposing|| handle == IntPtr.Zero)
+                               return;
+
+                       NativeMethods.cairo_path_destroy (handle);
+                       handle = IntPtr.Zero;
+               }
+       }
+}
diff --git a/testDrm/Mono.Cairo/Pattern.cs b/testDrm/Mono.Cairo/Pattern.cs
new file mode 100644 (file)
index 0000000..bc0a962
--- /dev/null
@@ -0,0 +1,155 @@
+//
+// Mono.Cairo.Pattern.cs
+//
+// Author: Jordi Mas (jordi@ximian.com)
+//         Hisham Mardam Bey (hisham.mardambey@gmail.com)
+// (C) Ximian Inc, 2004.
+//
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// 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.
+//
+
+using System;
+using System.Collections;
+
+namespace Cairo {
+   
+       public class Pattern : IDisposable
+       {
+               [Obsolete]
+               protected IntPtr pattern = IntPtr.Zero;
+
+               public static Pattern Lookup (IntPtr pattern, bool owner)
+               {
+                       if (pattern == IntPtr.Zero)
+                               return null;
+                       
+                       PatternType pt = NativeMethods.cairo_pattern_get_type (pattern);
+                       switch (pt) {
+                       case PatternType.Solid:
+                               return new SolidPattern (pattern, owner);
+                       case PatternType.Surface:
+                               return new SurfacePattern (pattern, owner);
+                       case PatternType.Linear:
+                               return new LinearGradient (pattern, owner);
+                       case PatternType.Radial:
+                               return new RadialGradient (pattern, owner);
+                       default:
+                               return new Pattern (pattern, owner);
+                       }
+               }
+
+               [Obsolete]
+               protected Pattern ()
+               {
+               }
+               
+               internal Pattern (IntPtr handle, bool owned)
+               {
+                       Handle = handle;
+                       if (!owned)
+                               NativeMethods.cairo_pattern_reference (handle);
+                       if (CairoDebug.Enabled)
+                               CairoDebug.OnAllocated (handle);
+               }
+
+               ~Pattern ()
+               {
+                       Dispose (false);
+               }
+               
+               [Obsolete ("Use the SurfacePattern constructor")]
+               public Pattern (Surface surface)
+                       : this ( NativeMethods.cairo_pattern_create_for_surface (surface.Handle), true)
+               {
+               }
+               
+               [Obsolete]
+               protected void Reference ()
+               {
+                       NativeMethods.cairo_pattern_reference (pattern);
+               }
+
+               public void Dispose ()
+               {
+                       Dispose (true);
+                       GC.SuppressFinalize (this);
+               }
+
+               protected virtual void Dispose (bool disposing)
+               {
+                       if (!disposing || CairoDebug.Enabled)
+                               CairoDebug.OnDisposed<Pattern> (Handle, disposing);
+
+                       if (!disposing|| Handle == IntPtr.Zero)
+                               return;
+
+                       NativeMethods.cairo_pattern_destroy (Handle);
+                       Handle = IntPtr.Zero;
+               }
+
+               [Obsolete ("Use Dispose()")]
+               public void Destroy ()
+               {
+                       Dispose ();
+               }
+
+               public Status Status
+               {
+                       get { return NativeMethods.cairo_pattern_status (Handle); }
+               }
+
+               public Extend Extend
+               {
+                       get { return NativeMethods.cairo_pattern_get_extend (Handle); }
+                       set { NativeMethods.cairo_pattern_set_extend (Handle, value); }
+               }
+
+               public Matrix Matrix {
+                       set {
+                               NativeMethods.cairo_pattern_set_matrix (Handle, value);
+                       }
+
+                       get {
+                               Matrix m = new Matrix ();
+                               NativeMethods.cairo_pattern_get_matrix (Handle, m);
+                               return m;
+                       }
+               }
+
+#pragma warning disable 612
+               public IntPtr Handle {
+                       get { return pattern; }
+                       private set { pattern = value; }
+               }
+#pragma warning restore 612
+
+               [Obsolete]
+               public IntPtr Pointer {
+                       get { return pattern; }
+               }
+
+               public PatternType PatternType {
+                       get { return NativeMethods.cairo_pattern_get_type (Handle); }
+               }
+       }
+}
+
diff --git a/testDrm/Mono.Cairo/PatternType.cs b/testDrm/Mono.Cairo/PatternType.cs
new file mode 100644 (file)
index 0000000..002469f
--- /dev/null
@@ -0,0 +1,42 @@
+//
+// Mono.Cairo.PatternType.cs
+//
+// Authors:
+//    John Luke
+//
+// (C) John Luke, 2006.
+//
+// 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.
+//
+
+using System;
+
+namespace Cairo {
+
+       [Serializable]
+       public enum PatternType
+       {
+               Solid,
+               Surface,
+               Linear,
+               Radial,
+       }
+}
+
diff --git a/testDrm/Mono.Cairo/PdfSurface.cs b/testDrm/Mono.Cairo/PdfSurface.cs
new file mode 100644 (file)
index 0000000..c980f24
--- /dev/null
@@ -0,0 +1,50 @@
+//
+// Mono.Cairo.PdfSurface.cs
+//
+// Authors:
+//    John Luke
+//
+// (C) John Luke, 2006.
+//
+// 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.
+//
+
+using System;
+
+namespace Cairo {
+
+       public class PdfSurface : Surface
+       {
+               internal PdfSurface (IntPtr handle, bool owns) : base (handle, owns)
+               {
+               }
+
+               public PdfSurface (string filename, double width, double height)
+                       : base (NativeMethods.cairo_pdf_surface_create (filename, width, height), true)
+               {
+               }
+
+               public void SetSize (double width, double height)
+               {
+                       NativeMethods.cairo_pdf_surface_set_size (Handle, width, height);
+               }
+       }
+}
+
diff --git a/testDrm/Mono.Cairo/Point.cs b/testDrm/Mono.Cairo/Point.cs
new file mode 100644 (file)
index 0000000..e72ca6c
--- /dev/null
@@ -0,0 +1,57 @@
+//
+// Mono.Cairo.Context.cs
+//
+// Author:
+//   Duncan Mak (duncan@ximian.com)
+//   Miguel de Icaza (miguel@novell.com)
+//   Hisham Mardam Bey (hisham.mardambey@gmail.com)
+//   Alp Toker (alp@atoker.com)
+//
+// (C) Ximian Inc, 2003.
+// (C) Novell Inc, 2003.
+//
+// This is an OO wrapper API for the Cairo API.
+//
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// 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.
+//
+
+namespace Cairo {
+       public struct Point
+       {
+               public Point (int x, int y)
+               {
+                       this.x = x;
+                       this.y = y;
+               }
+
+               int x, y;
+               public int X {
+                       get { return x; }
+                       set { x = value; }
+               }
+
+               public int Y {
+                       get { return y; }
+                       set { y = value; }
+               }
+       }
+}
diff --git a/testDrm/Mono.Cairo/PointD.cs b/testDrm/Mono.Cairo/PointD.cs
new file mode 100644 (file)
index 0000000..c2e3587
--- /dev/null
@@ -0,0 +1,58 @@
+//
+// Mono.Cairo.Context.cs
+//
+// Author:
+//   Duncan Mak (duncan@ximian.com)
+//   Miguel de Icaza (miguel@novell.com)
+//   Hisham Mardam Bey (hisham.mardambey@gmail.com)
+//   Alp Toker (alp@atoker.com)
+//
+// (C) Ximian Inc, 2003.
+// (C) Novell Inc, 2003.
+//
+// This is an OO wrapper API for the Cairo API.
+//
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// 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.
+//
+
+namespace Cairo {
+
+       public struct PointD
+       {
+               public PointD (double x, double y)
+               {
+                       this.x = x;
+                       this.y = y;
+               }
+
+               double x, y;
+               public double X {
+                       get { return x; }
+                       set { x = value; }
+               }
+
+               public double Y {
+                       get { return y; }
+                       set { y = value; }
+               }
+       }
+}
diff --git a/testDrm/Mono.Cairo/RadialGradient.cs b/testDrm/Mono.Cairo/RadialGradient.cs
new file mode 100644 (file)
index 0000000..6422e00
--- /dev/null
@@ -0,0 +1,46 @@
+//
+// Mono.Cairo.Pattern.cs
+//
+// Author: Jordi Mas (jordi@ximian.com)
+//         Hisham Mardam Bey (hisham.mardambey@gmail.com)
+// (C) Ximian Inc, 2004.
+//
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// 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.
+//
+
+using System;
+
+namespace Cairo {
+
+       public class RadialGradient : Gradient
+       {
+               internal RadialGradient (IntPtr handle, bool owned) : base (handle, owned)
+               {
+               }
+
+               public RadialGradient (double cx0, double cy0, double radius0, double cx1, double cy1, double radius1)
+                       : base (NativeMethods.cairo_pattern_create_radial (cx0, cy0, radius0, cx1, cy1, radius1), true)
+               {
+               }
+       }
+}
+
diff --git a/testDrm/Mono.Cairo/Rectangle.cs b/testDrm/Mono.Cairo/Rectangle.cs
new file mode 100644 (file)
index 0000000..233a1ba
--- /dev/null
@@ -0,0 +1,99 @@
+//
+// Mono.Cairo.Rectangle.cs
+//
+// Author:
+//   John Luke (john.luke@gmail.com)
+//
+// (C) John Luke 2005.
+//
+// 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.
+//
+
+using System;
+
+namespace Cairo
+{
+       public struct Rectangle
+       {
+               double x;
+               double y;
+               double width;
+               double height;
+               
+               public Rectangle (double x, double y, double width, double height)
+               {
+                       this.x = x;
+                       this.y = y;
+                       this.width = width;
+                       this.height = height;
+               }
+               
+               public Rectangle (Point point, double width, double height)
+               {
+                       x = point.X;
+                       y = point.Y;
+                       this.width = width;
+                       this.height = height;
+               }
+               
+               public double X {
+                       get { return x; }
+               }
+               
+               public double Y {
+                       get { return y; }
+               }
+               
+               public double Width {
+                       get { return width; }
+               }
+               
+               public double Height {
+                       get { return height; }
+               }
+               
+               public override bool Equals (object obj)
+               {
+                       if (obj is Rectangle)
+                               return this == (Rectangle)obj;
+                       return false;
+               }
+               
+               public override int GetHashCode ()
+               {
+                       return (int) (x + y + width + height);
+               }
+
+               public override string ToString ()
+               {
+                       return String.Format ("x:{0} y:{1} w:{2} h:{3}", x, y, width, height);
+               }
+               
+               public static bool operator == (Rectangle rectangle, Rectangle other)
+               {
+                       return rectangle.X == other.X && rectangle.Y == other.Y && rectangle.Width == other.Width && rectangle.Height == other.Height;
+               }
+               
+               public static bool operator != (Rectangle rectangle, Rectangle other)
+               {
+                       return !(rectangle == other);
+               }
+       }
+}
diff --git a/testDrm/Mono.Cairo/Region.cs b/testDrm/Mono.Cairo/Region.cs
new file mode 100644 (file)
index 0000000..cd0ba33
--- /dev/null
@@ -0,0 +1,196 @@
+// Copyright (C) 2011 Novell, Inc (http://www.novell.com)
+//
+// 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.
+//
+
+using System;
+using System.Runtime.InteropServices;
+
+namespace Cairo
+{
+
+       [StructLayout(LayoutKind.Sequential)]
+       public struct RectangleInt {
+               public int X;
+               public int Y;
+               public int Width;
+               public int Height;
+       }
+
+       public enum RegionOverlap {
+               In,
+               Out,
+               Part,
+       }
+
+       public class Region : IDisposable {
+
+               IntPtr handle;
+               public IntPtr Handle {
+                       get { return handle; }
+               }
+
+               [Obsolete]
+               public Region (IntPtr handle) : this (handle, false) {}
+
+               public Region (IntPtr handle, bool owned)
+               {
+                       this.handle = handle;
+                       if (!owned)
+                               NativeMethods.cairo_region_reference (handle);
+                       if (CairoDebug.Enabled)
+                               CairoDebug.OnAllocated (handle);
+               }
+
+               public Region () : this (NativeMethods.cairo_region_create () , true)
+               {
+               }
+
+               public Region (RectangleInt rect)
+               {
+                       handle = NativeMethods.cairo_region_create_rectangle (ref rect);
+               }
+
+               public Region (RectangleInt[] rects)
+               {
+                       handle = NativeMethods.cairo_region_create_rectangles (rects, rects.Length);
+               }
+
+               public Region Copy ()
+               {
+                       return new Region (NativeMethods.cairo_region_copy (Handle), true);
+               }
+
+               ~Region ()
+               {
+                       Dispose (false);
+               }
+
+               public void Dispose ()
+               {
+                       Dispose (true);
+                       GC.SuppressFinalize (this);
+               }
+
+               protected virtual void Dispose (bool disposing)
+               {
+                       if (!disposing || CairoDebug.Enabled)
+                               CairoDebug.OnDisposed<Region> (handle, disposing);
+
+                       if (!disposing|| handle == IntPtr.Zero)
+                               return;
+
+                       NativeMethods.cairo_region_destroy (Handle);
+                       handle = IntPtr.Zero;
+               }
+
+               public override bool Equals (object obj)
+               {
+                       return (obj is Region) && NativeMethods.cairo_region_equal (Handle, (obj as Region).Handle);
+               }
+
+               public override int GetHashCode ()
+               {
+                       return Handle.GetHashCode ();
+               }
+
+               public Status Status {
+                       get { return NativeMethods.cairo_region_status (Handle); }
+               }
+
+               public RectangleInt Extents {
+                       get {
+                               RectangleInt result;
+                               NativeMethods.cairo_region_get_extents (Handle, out result);
+                               return result;
+                       }
+               }
+
+               public int NumRectangles {
+                       get { return NativeMethods.cairo_region_num_rectangles (Handle); }
+               }
+
+               public RectangleInt GetRectangle (int nth)
+               {
+                       RectangleInt val;
+                       NativeMethods.cairo_region_get_rectangle (Handle, nth, out val);
+                       return val;
+               }
+
+               public bool IsEmpty {
+                       get { return NativeMethods.cairo_region_is_empty (Handle); }
+               }
+
+               public RegionOverlap ContainsPoint (RectangleInt rectangle)
+               {
+                       return NativeMethods.cairo_region_contains_rectangle (Handle, ref rectangle);
+               }
+
+               public bool ContainsPoint (int x, int y)
+               {
+                       return NativeMethods.cairo_region_contains_point (Handle, x, y);
+               }
+
+               public void Translate (int dx, int dy)
+               {
+                       NativeMethods.cairo_region_translate (Handle, dx, dy);
+               }
+
+               public Status Subtract (Region other)
+               {
+                       return NativeMethods.cairo_region_subtract (Handle, other.Handle);
+               }
+
+               public Status SubtractRectangle (RectangleInt rectangle)
+               {
+                       return NativeMethods.cairo_region_subtract_rectangle (Handle, ref rectangle);
+               }
+
+               public Status Intersect (Region other)
+               {
+                       return NativeMethods.cairo_region_intersect (Handle, other.Handle);
+               }
+
+               public Status IntersectRectangle (RectangleInt rectangle)
+               {
+                       return NativeMethods.cairo_region_intersect_rectangle (Handle, ref rectangle);
+               }
+
+               public Status Union (Region other)
+               {
+                       return NativeMethods.cairo_region_union (Handle, other.Handle);
+               }
+
+               public Status UnionRectangle (RectangleInt rectangle)
+               {
+                       return NativeMethods.cairo_region_union_rectangle (Handle, ref rectangle);
+               }
+
+               public Status Xor (Region other)
+               {
+                       return NativeMethods.cairo_region_xor (Handle, other.Handle);
+               }
+
+               public Status XorRectangle (RectangleInt rectangle)
+               {
+                       return NativeMethods.cairo_region_xor_rectangle (Handle, ref rectangle);
+               }
+       }
+}
diff --git a/testDrm/Mono.Cairo/ScaledFont.cs b/testDrm/Mono.Cairo/ScaledFont.cs
new file mode 100644 (file)
index 0000000..9371946
--- /dev/null
@@ -0,0 +1,123 @@
+//
+// Mono.Cairo.ScaledFont.cs
+//
+// (c) 2008 Jordi Mas i Hernandez (jordimash@gmail.com)
+//
+// 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.
+//
+
+using System;
+using System.Runtime.InteropServices;
+
+namespace Cairo {
+   
+       public class ScaledFont : IDisposable
+       {
+               protected IntPtr handle = IntPtr.Zero;
+
+               internal ScaledFont (IntPtr handle, bool owner)
+               {
+                       this.handle = handle;
+                       if (!owner)
+                               NativeMethods.cairo_scaled_font_reference (handle);
+                       if (CairoDebug.Enabled)
+                               CairoDebug.OnAllocated (handle);
+               }
+
+               public ScaledFont (FontFace fontFace, Matrix matrix, Matrix ctm, FontOptions options)
+                       : this (NativeMethods.cairo_scaled_font_create (fontFace.Handle, matrix, ctm, options.Handle), true)
+               {
+               }
+
+               ~ScaledFont ()
+               {
+                       Dispose (false);
+               }
+
+               public IntPtr Handle {
+                       get {
+                               return handle;
+                       }
+               }
+
+               public FontExtents FontExtents {
+                       get {
+                               FontExtents extents;
+                               NativeMethods.cairo_scaled_font_extents (handle, out extents);
+                               return extents;
+                       }
+               }
+
+               public Matrix FontMatrix {
+                       get {
+                               Matrix m;
+                               NativeMethods.cairo_scaled_font_get_font_matrix (handle, out m);
+                               return m;
+                       }
+               }
+
+               public FontType FontType {
+                       get {
+                               return NativeMethods.cairo_scaled_font_get_type (handle);
+                       }
+               }
+
+               public TextExtents GlyphExtents (Glyph[] glyphs)
+               {
+                       IntPtr ptr = Context.FromGlyphToUnManagedMemory (glyphs);
+                       TextExtents extents;
+
+                       NativeMethods.cairo_scaled_font_glyph_extents (handle, ptr, glyphs.Length, out extents);
+
+                       Marshal.FreeHGlobal (ptr);
+                       return extents;
+               }
+       
+               public Status Status
+               {
+                       get { return NativeMethods.cairo_scaled_font_status (handle); }
+               }
+
+               public void Dispose ()
+               {
+                       Dispose (true);
+                       GC.SuppressFinalize (this);
+               }
+
+               protected virtual void Dispose (bool disposing)
+               {
+                       if (!disposing || CairoDebug.Enabled)
+                               CairoDebug.OnDisposed<ScaledFont> (handle, disposing);
+
+                       if (!disposing|| handle == IntPtr.Zero)
+                               return;
+
+                       NativeMethods.cairo_scaled_font_destroy (handle);
+                       handle = IntPtr.Zero;
+               }
+
+               [Obsolete]
+               protected void Reference ()
+               {
+                       NativeMethods.cairo_scaled_font_reference (handle);
+               }
+       }
+}
+
diff --git a/testDrm/Mono.Cairo/SolidPattern.cs b/testDrm/Mono.Cairo/SolidPattern.cs
new file mode 100644 (file)
index 0000000..875b3fb
--- /dev/null
@@ -0,0 +1,72 @@
+//
+// Mono.Cairo.Pattern.cs
+//
+// Author: Jordi Mas (jordi@ximian.com)
+//         Hisham Mardam Bey (hisham.mardambey@gmail.com)
+// (C) Ximian Inc, 2004.
+//
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// 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.
+//
+
+using System;
+
+namespace Cairo {
+
+       public class SolidPattern : Pattern
+       {
+               internal SolidPattern (IntPtr handle, bool owned) : base (handle, owned)
+               {
+               }
+
+               public SolidPattern (Color color)
+                       : base (NativeMethods.cairo_pattern_create_rgba (color.R, color.G, color.B, color.A), true)
+               {
+               }
+
+               public SolidPattern (double r, double g, double b)
+                       : base (NativeMethods.cairo_pattern_create_rgb (r, g, b), true)
+               {
+               }
+
+               public SolidPattern (double r, double g, double b, double a)
+                       : base (NativeMethods.cairo_pattern_create_rgba (r, g, b, a), true)
+               {
+               }
+
+               public SolidPattern (Color color, bool solid)
+                       : base (solid
+                                       ? NativeMethods.cairo_pattern_create_rgb (color.R, color.G, color.B)
+                                       : NativeMethods.cairo_pattern_create_rgba (color.R, color.G, color.B, color.A),
+                               true)
+               {
+               }
+
+               public Color Color {
+                       get {
+                               double red, green, blue, alpha;
+                               NativeMethods.cairo_pattern_get_rgba  (Handle, out red, out green, out blue, out alpha);
+                               return new Color (red, green, blue, alpha);
+                       }
+               }
+       }
+}
+
diff --git a/testDrm/Mono.Cairo/Status.cs b/testDrm/Mono.Cairo/Status.cs
new file mode 100644 (file)
index 0000000..6e5fbe0
--- /dev/null
@@ -0,0 +1,64 @@
+//
+// Mono.Cairo.Status.cs
+//
+// Authors:
+//   Duncan Mak (duncan@ximian.com)
+//   Hisham Mardam Bey (hisham.mardambey@gmail.com)
+//   John Luke (john.luke@gmail.com)
+//   Alp Toker (alp@atoker.com)
+//
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+// Copyright (C) 2005 John Luke
+//
+// 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.
+//
+
+using System;
+
+namespace Cairo
+{
+       [Serializable]
+       public enum Status
+       {
+               Success = 0,
+               NoMemory,
+               InvalidRestore,
+               InvalidPopGroup,
+               NoCurrentPoint,
+               InvalidMatrix,
+               InvalidStatus,
+               NullPointer,
+               InvalidString,
+               InvalidPathData,
+               ReadError,
+               WriteError,
+               SurfaceFinished,
+               SurfaceTypeMismatch,
+               PatternTypeMismatch,
+               InvalidContent,
+               InvalidFormat,
+               InvalidVisual,
+               FileNotFound,
+               InvalidDash,
+               InvalidDscComment,
+               InvalidIndex,
+               ClipNotRepresentable,
+       }
+}
diff --git a/testDrm/Mono.Cairo/SubpixelOrder.cs b/testDrm/Mono.Cairo/SubpixelOrder.cs
new file mode 100644 (file)
index 0000000..e8ab658
--- /dev/null
@@ -0,0 +1,42 @@
+//
+// Mono.Cairo.Cairo.cs
+//
+// Authors:
+//   John Luke (john.luke@gmail.com)
+//
+// Copyright (C) John Luke 2005
+//
+// 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.
+//
+
+using System;
+
+namespace Cairo
+{
+       [Serializable]
+       public enum SubpixelOrder
+       {
+               Default,
+               Rgb,
+               Bgr,
+               Vrgb,
+               Vbgr,
+       }
+}
diff --git a/testDrm/Mono.Cairo/Surface.cs b/testDrm/Mono.Cairo/Surface.cs
new file mode 100644 (file)
index 0000000..d38b755
--- /dev/null
@@ -0,0 +1,234 @@
+//
+// Mono.Cairo.Surface.cs
+//
+// Authors:
+//    Duncan Mak
+//    Miguel de Icaza.
+//    Alp Toker
+//
+// (C) Ximian Inc, 2003.
+// (C) Novell, Inc. 2003.
+//
+// This is an OO wrapper API for the Cairo API
+//
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// 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.
+//
+
+using System;
+using System.Collections;
+
+namespace Cairo {
+
+       public class Surface : IDisposable
+       {
+               [Obsolete]
+               protected static Hashtable surfaces = new Hashtable ();
+
+               IntPtr handle = IntPtr.Zero;
+
+               [Obsolete]
+               protected Surface()
+               {
+               }
+
+               [Obsolete]
+               protected Surface (IntPtr ptr) : this (ptr, true)
+               {
+               }
+
+               protected Surface (IntPtr handle, bool owner)
+               {
+                       this.handle = handle;
+                       if (!owner)
+                               NativeMethods.cairo_surface_reference (handle);
+                       if (CairoDebug.Enabled)
+                               CairoDebug.OnAllocated (handle);
+               }
+
+               public static Surface Lookup (IntPtr surface, bool owned)
+               {
+                       SurfaceType st = NativeMethods.cairo_surface_get_type (surface);
+                       switch (st) {
+                       case SurfaceType.Image:
+                               return new ImageSurface (surface, owned);
+                       case SurfaceType.Xlib:
+                               return new XlibSurface (surface, owned);
+                       case SurfaceType.Xcb:
+                               return new XcbSurface (surface, owned);
+                       case SurfaceType.Glitz:
+                               return new GlitzSurface (surface, owned);
+                       case SurfaceType.Win32:
+                               return new Win32Surface (surface, owned);
+                       case SurfaceType.Pdf:
+                               return new PdfSurface (surface, owned);
+                       case SurfaceType.PS:
+                               return new PSSurface (surface, owned);
+                       case SurfaceType.DirectFB:
+                               return new DirectFBSurface (surface, owned);
+                       case SurfaceType.Svg:
+                               return new SvgSurface (surface, owned);
+                       case SurfaceType.GL:
+                               return new GLSurface (surface, owned);
+                       default:
+                               return new Surface (surface, owned);
+                       }
+               }
+
+               [Obsolete ("Use an ImageSurface constructor instead.")]
+               public static Cairo.Surface CreateForImage (
+                       ref byte[] data, Cairo.Format format, int width, int height, int stride)
+               {
+                       IntPtr p = NativeMethods.cairo_image_surface_create_for_data (
+                               data, format, width, height, stride);
+
+                       return new Cairo.Surface (p, true);
+               }
+
+               [Obsolete ("Use an ImageSurface constructor instead.")]
+               public static Cairo.Surface CreateForImage (
+                       Cairo.Format format, int width, int height)
+               {
+                       IntPtr p = NativeMethods.cairo_image_surface_create (
+                               format, width, height);
+
+                       return new Cairo.Surface (p, true);
+               }
+
+
+               public Cairo.Surface CreateSimilar (
+                       Cairo.Content content, int width, int height)
+               {
+                       IntPtr p = NativeMethods.cairo_surface_create_similar (
+                               this.Handle, content, width, height);
+
+                       return new Cairo.Surface (p, true);
+               }
+
+               ~Surface ()
+               {
+                       Dispose (false);
+               }
+
+               //[Obsolete ("Use Context.SetSource() followed by Context.Paint()")]
+               public void Show (Context gr, double x, double y)
+               {
+                       NativeMethods.cairo_set_source_surface (gr.Handle, handle, x, y);
+                       NativeMethods.cairo_paint (gr.Handle);
+               }
+
+               public void Dispose ()
+               {
+                       Dispose (true);
+                       GC.SuppressFinalize (this);
+               }
+
+               protected virtual void Dispose (bool disposing)
+               {
+                       if (!disposing || CairoDebug.Enabled)
+                               CairoDebug.OnDisposed<Surface> (handle, disposing);
+
+                       if (!disposing|| handle == IntPtr.Zero)
+                               return;
+
+                       NativeMethods.cairo_surface_destroy (handle);
+                       handle = IntPtr.Zero;
+               }
+
+               public Status Finish ()
+               {
+                       NativeMethods.cairo_surface_finish (handle);
+                       return Status;
+               }
+
+               public void Flush ()
+               {
+                       NativeMethods.cairo_surface_flush (handle);
+               }
+
+               public void MarkDirty ()
+               {
+                       NativeMethods.cairo_surface_mark_dirty (Handle);
+               }
+
+               public void MarkDirty (Rectangle rectangle)
+               {
+                       NativeMethods.cairo_surface_mark_dirty_rectangle (Handle, (int)rectangle.X, (int)rectangle.Y, (int)rectangle.Width, (int)rectangle.Height);
+               }
+
+               public IntPtr Handle {
+                       get {
+                               return handle;
+                       }
+               }
+
+               public PointD DeviceOffset {
+                       get {
+                               double x, y;
+                               NativeMethods.cairo_surface_get_device_offset (handle, out x, out y);
+                               return new PointD (x, y);
+                       }
+
+                       set {
+                               NativeMethods.cairo_surface_set_device_offset (handle, value.X, value.Y);
+                       }
+               }
+
+               [Obsolete ("Use Dispose()")]
+               public void Destroy()
+               {
+                       Dispose ();
+               }
+
+               public void SetFallbackResolution (double x, double y)
+               {
+                       NativeMethods.cairo_surface_set_fallback_resolution (handle, x, y);
+               }
+
+               public void WriteToPng (string filename)
+               {
+                       NativeMethods.cairo_surface_write_to_png (handle, filename);
+               }
+
+               [Obsolete ("Use Handle instead.")]
+               public IntPtr Pointer {
+                       get {
+                               return handle;
+                       }
+               }
+
+               public Status Status {
+                       get { return NativeMethods.cairo_surface_status (handle); }
+               }
+
+               public Content Content {
+                       get { return NativeMethods.cairo_surface_get_content (handle); }
+               }
+
+               public SurfaceType SurfaceType {
+                       get { return NativeMethods.cairo_surface_get_type (handle); }
+               }
+
+               public uint ReferenceCount {
+                       get { return NativeMethods.cairo_surface_get_reference_count (handle); }
+               }
+       }
+}
diff --git a/testDrm/Mono.Cairo/SurfacePattern.cs b/testDrm/Mono.Cairo/SurfacePattern.cs
new file mode 100644 (file)
index 0000000..4422b11
--- /dev/null
@@ -0,0 +1,57 @@
+//
+// Mono.Cairo.Pattern.cs
+//
+// Author: Jordi Mas (jordi@ximian.com)
+//         Hisham Mardam Bey (hisham.mardambey@gmail.com)
+// (C) Ximian Inc, 2004.
+//
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// 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.
+//
+
+using System;
+
+namespace Cairo {
+
+       public class SurfacePattern : Pattern
+       {
+               internal SurfacePattern (IntPtr handle, bool owned) : base (handle, owned)
+               {
+               }
+
+               public SurfacePattern (Surface surface)
+                       : base (NativeMethods.cairo_pattern_create_for_surface (surface.Handle), true)
+               {
+               }
+
+               //no idea why this is here, the base one is identical, but we can't remove it now
+               public new Extend Extend {
+                       set { NativeMethods.cairo_pattern_set_extend (Handle, value); }
+                       get { return NativeMethods.cairo_pattern_get_extend (Handle); }
+               }
+
+               public Filter Filter {
+                       set { NativeMethods.cairo_pattern_set_filter (Handle, value); }
+                       get { return NativeMethods.cairo_pattern_get_filter (Handle); }
+               }
+       }
+}
+
diff --git a/testDrm/Mono.Cairo/SurfaceType.cs b/testDrm/Mono.Cairo/SurfaceType.cs
new file mode 100644 (file)
index 0000000..ae86d13
--- /dev/null
@@ -0,0 +1,61 @@
+//
+// Mono.Cairo.SurfaceType.cs
+//
+// Authors:
+//    John Luke
+//
+// (C) John Luke, 2006.
+//
+// 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.
+//
+
+using System;
+
+namespace Cairo {
+
+       [Serializable]
+       public enum SurfaceType
+       {
+               Image,
+               Pdf,
+               PS,
+               Xlib,
+               Xcb,
+               Glitz,
+               Quartz,
+               Win32,
+               BeOS,
+               DirectFB,
+               Svg,
+               OS2,
+               Win32Printing,
+               QuartzImage,
+               Script,
+               Qt,
+               Recording,
+               VG,
+               GL,
+               Drm,
+               Tee,
+               Xml,
+               Skia,
+               SubSurface
+       }
+}
diff --git a/testDrm/Mono.Cairo/SvgSurface.cs b/testDrm/Mono.Cairo/SvgSurface.cs
new file mode 100644 (file)
index 0000000..4182950
--- /dev/null
@@ -0,0 +1,50 @@
+//
+// Mono.Cairo.SvgSurface.cs
+//
+// Authors:
+//    John Luke
+//
+// (C) John Luke, 2006.
+//
+// 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.
+//
+
+using System;
+
+namespace Cairo {
+
+       public class SvgSurface : Surface
+       {
+               internal SvgSurface (IntPtr handle, bool owns) : base (handle, owns)
+               {
+               }
+
+               public SvgSurface (string filename, double width, double height)
+                       : base (NativeMethods.cairo_svg_surface_create (filename, width, height), true)
+               {
+               }
+
+               public void RestrictToVersion (SvgVersion version)
+               {
+                       NativeMethods.cairo_svg_surface_restrict_to_version (Handle, version);
+               }
+       }
+}
+
diff --git a/testDrm/Mono.Cairo/SvgVersion.cs b/testDrm/Mono.Cairo/SvgVersion.cs
new file mode 100644 (file)
index 0000000..99cee28
--- /dev/null
@@ -0,0 +1,41 @@
+//
+// Mono.Cairo.SvgVersion.cs
+//
+// Authors:
+//    John Luke
+//
+// (C) John Luke, 2006.
+//
+// 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.
+//
+
+using System;
+
+namespace Cairo {
+
+       [Serializable]
+       public enum SvgVersion
+       {
+               // FIXME: yuck
+               OnePointOne = 0,
+               OnePointTwo,
+       }
+}
+
diff --git a/testDrm/Mono.Cairo/TextExtents.cs b/testDrm/Mono.Cairo/TextExtents.cs
new file mode 100644 (file)
index 0000000..f9cd560
--- /dev/null
@@ -0,0 +1,98 @@
+//
+// Mono.Cairo.TextExtents.cs
+//
+// Authors:
+//   Duncan Mak (duncan@ximian.com)
+//   Hisham Mardam Bey (hisham.mardambey@gmail.com)
+//
+// (C) Ximian, Inc. 2003
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// 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.
+//
+
+using System;
+using System.Runtime.InteropServices;
+
+namespace Cairo
+{
+       [StructLayout (LayoutKind.Sequential)]
+       public struct TextExtents
+       {
+               double xbearing;
+               double ybearing;
+               double width;
+               double height;
+               double xadvance;
+               double yadvance;
+               
+               public double XBearing {
+                       get { return xbearing; }
+                       set { xbearing = value; }
+               }
+               
+               public double YBearing {
+                       get { return ybearing; }
+                       set { ybearing = value; }
+               }
+               
+               public double Width {
+                       get { return width; }
+                       set { width = value; }
+               }
+               
+               public double Height {
+                       get { return height; }
+                       set { height = value; }
+               }
+               
+               public double XAdvance {
+                       get { return xadvance; }
+                       set { xadvance = value; }
+               }
+               
+               public double YAdvance {
+                       get { return yadvance; }
+                       set { yadvance = value; }
+               }
+
+               public override bool Equals (object obj)
+               {
+                       if (obj is TextExtents)
+                               return this == (TextExtents)obj;
+                       return false;
+               }
+
+               public override int GetHashCode ()
+               {
+                       return (int)XBearing ^ (int)YBearing ^ (int)Width ^ (int)Height ^ (int)XAdvance ^ (int)YAdvance;
+               }
+
+               public static bool operator == (TextExtents extents, TextExtents other)
+               {
+                       return extents.XBearing == other.XBearing && extents.YBearing == other.YBearing && extents.Width == other.Width && extents.Height == other.Height && extents.XAdvance == other.XAdvance && extents.YAdvance == other.YAdvance;
+               }
+
+               public static bool operator != (TextExtents extents, TextExtents other)
+               {
+                       return !(extents == other);
+               }
+       }
+}
diff --git a/testDrm/Mono.Cairo/WGLDevice.cs b/testDrm/Mono.Cairo/WGLDevice.cs
new file mode 100644 (file)
index 0000000..03f7e3a
--- /dev/null
@@ -0,0 +1,45 @@
+//
+// Mono.Cairo.Device.cs
+//
+// Authors:
+//                     JP Bruyère (jp_bruyere@hotmail.com)
+//
+// This is an OO wrapper API for the Cairo API
+//
+// Copyright (C) 2016 JP Bruyère
+//
+// 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.
+//
+using System;
+
+namespace Cairo
+{
+       public class WGLDevice : Device
+       {
+               public WGLDevice (IntPtr hglrc) : base (NativeMethods.cairo_wgl_device_create (hglrc), true)
+               {
+               }
+
+               public IntPtr Context {
+                       get { return NativeMethods.cairo_wgl_device_get_context (Handle); }
+               }
+       }
+}
+
diff --git a/testDrm/Mono.Cairo/Win32Surface.cs b/testDrm/Mono.Cairo/Win32Surface.cs
new file mode 100644 (file)
index 0000000..dd24428
--- /dev/null
@@ -0,0 +1,44 @@
+//
+// Mono.Cairo.Win32Surface.cs
+//
+// Authors:
+//    John Luke
+//
+// (C) John Luke, 2006.
+//
+// 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.
+//
+
+using System;
+
+namespace Cairo {
+       
+       public class Win32Surface : Surface
+       {
+               internal Win32Surface (IntPtr handle, bool owns) : base (handle, owns)
+               {
+               }
+               
+               public Win32Surface (IntPtr hdc)
+                       : base (NativeMethods.cairo_win32_surface_create (hdc), true)
+               {
+               }
+       }
+}
diff --git a/testDrm/Mono.Cairo/XcbSurface.cs b/testDrm/Mono.Cairo/XcbSurface.cs
new file mode 100644 (file)
index 0000000..142ebf9
--- /dev/null
@@ -0,0 +1,54 @@
+//
+// Mono.Cairo.XcbSurface.cs
+//
+// Authors:
+//    Alp Toker
+//
+// (C) Alp Toker, 2006.
+//
+// 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.
+//
+
+using System;
+
+namespace Cairo {
+       public class XcbSurface : Surface
+       {
+               internal XcbSurface (IntPtr handle, bool owns) : base (handle, owns)
+               {
+               }
+
+               public XcbSurface (IntPtr connection, uint drawable, IntPtr visual, int width, int height)
+                       : base (NativeMethods.cairo_xcb_surface_create (connection, drawable, visual, width, height), true)
+               {
+               }
+
+               public static XcbSurface FromBitmap (IntPtr connection, uint bitmap, IntPtr screen, int width, int height)
+               {
+                       IntPtr ptr = NativeMethods.cairo_xcb_surface_create_for_bitmap (connection, bitmap, screen, width, height);
+                       return new XcbSurface (ptr, true);
+               }
+
+               public void SetSize (int width, int height)
+               {
+                       NativeMethods.cairo_xcb_surface_set_size (Handle, width, height);
+               }
+       }
+}
diff --git a/testDrm/Mono.Cairo/XlibSurface.cs b/testDrm/Mono.Cairo/XlibSurface.cs
new file mode 100644 (file)
index 0000000..c0003a4
--- /dev/null
@@ -0,0 +1,95 @@
+//
+// Mono.Cairo.XlibSurface.cs
+//
+// Authors:
+//    Duncan Mak
+//    Miguel de Icaza.
+//
+// (C) Ximian Inc, 2003.
+// (C) Novell, Inc. 2003.
+//
+// This is an OO wrapper API for the Cairo API
+//
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// 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.
+//
+
+using System;
+
+namespace Cairo {
+
+       public class XlibSurface : Surface
+       {
+               public XlibSurface (IntPtr display, IntPtr drawable, IntPtr visual, int width, int height)
+                       : base (NativeMethods.cairo_xlib_surface_create (display, drawable, visual, width, height), true)
+               {
+               }
+
+               public XlibSurface (IntPtr ptr, bool own) : base (ptr, own)
+               {
+               }
+
+               public static XlibSurface FromBitmap (IntPtr display, IntPtr bitmap, IntPtr screen, int width, int height)
+               {
+                       IntPtr ptr = NativeMethods.cairo_xlib_surface_create_for_bitmap (display, bitmap, screen, width, height);
+                       return new XlibSurface(ptr, true);
+               }
+
+               public void SetDrawable (IntPtr drawable, int width, int height)
+               {
+                       NativeMethods.cairo_xlib_surface_set_drawable (Handle, drawable, width, height);
+               }
+
+               public void SetSize (int width, int height)
+               {
+                       NativeMethods.cairo_xlib_surface_set_size (Handle, width, height);
+               }
+
+               public int Depth {
+                       get { return NativeMethods.cairo_xlib_surface_get_depth (Handle); }
+               }
+               
+               public IntPtr Display {
+                       get { return NativeMethods.cairo_xlib_surface_get_display (Handle); }
+               }
+
+               public IntPtr Drawable {
+                       get { return NativeMethods.cairo_xlib_surface_get_drawable (Handle); }
+               }
+
+               public int Height {
+                       get { return NativeMethods.cairo_xlib_surface_get_height (Handle); }
+               }
+
+               public IntPtr Screen {
+                       get { return NativeMethods.cairo_xlib_surface_get_screen (Handle); }
+               }
+
+               public IntPtr Visual {
+                       get { return NativeMethods.cairo_xlib_surface_get_visual (Handle); }
+               }
+
+               public int Width {
+                       get { return NativeMethods.cairo_xlib_surface_get_width (Handle); }
+               }
+
+       }
+}
diff --git a/testDrm/src/BlittableValueType.cs b/testDrm/src/BlittableValueType.cs
new file mode 100644 (file)
index 0000000..1c3e121
--- /dev/null
@@ -0,0 +1,291 @@
+#region License
+//
+// The Open Toolkit Library License
+//
+// Copyright (c) 2006 - 2010 the Open Toolkit library.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights to 
+// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+// the Software, and to permit persons to whom the Software is furnished to do
+// so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Runtime.InteropServices;
+using System.Diagnostics;
+using System.Reflection;
+
+namespace OpenTK
+{
+    #region BlittableValueType<T>
+
+    /// <summary>
+    /// Checks whether the specified type parameter is a blittable value type.
+    /// </summary>
+    /// <remarks>
+    /// A blittable value type is a struct that only references other value types recursively,
+    /// which allows it to be passed to unmanaged code directly.
+    /// </remarks>
+    public static class BlittableValueType<T>
+    {
+        #region Fields
+
+        static readonly Type Type;
+        static readonly int stride;
+
+        #endregion
+
+        #region Constructors
+
+        static BlittableValueType()
+        {
+            Type = typeof(T);
+            if (Type.IsValueType && !Type.IsGenericType)
+            {
+                // Does this support generic types? On Mono 2.4.3 it does
+                // On .Net it doesn't.
+                // http://msdn.microsoft.com/en-us/library/5s4920fa.aspx
+                stride = Marshal.SizeOf(typeof(T));
+            }
+        }
+
+        #endregion
+
+        #region Public Members
+
+        /// <summary>
+        /// Gets the size of the type in bytes or 0 for non-blittable types.
+        /// </summary>
+        /// <remarks>
+        /// This property returns 0 for non-blittable types.
+        /// </remarks>
+        public static int Stride { get { return stride; } }
+
+        #region Check
+
+        /// <summary>
+        /// Checks whether the current typename T is blittable.
+        /// </summary>
+        /// <returns>True if T is blittable; false otherwise.</returns>
+        public static bool Check()
+        {
+            return Check(Type);
+        }
+
+        /// <summary>
+        /// Checks whether type is a blittable value type.
+        /// </summary>
+        /// <param name="type">A System.Type to check.</param>
+        /// <returns>True if T is blittable; false otherwise.</returns>
+        public static bool Check(Type type)
+        {
+            if (!CheckStructLayoutAttribute(type))
+                Debug.Print("Warning: type {0} does not specify a StructLayoutAttribute with Pack=1. The memory layout of the struct may change between platforms.", type.Name);
+
+            return CheckType(type);
+        }
+
+        #endregion
+
+        #endregion
+
+        #region Private Members
+
+        // Checks whether the parameter is a primitive type or consists of primitive types recursively.
+        // Throws a NotSupportedException if it is not.
+        static bool CheckType(Type type)
+        {
+            //Debug.Print("Checking type {0} (size: {1} bytes).", type.Name, Marshal.SizeOf(type));
+            if (type.IsPrimitive)
+                return true;
+
+            if (!type.IsValueType)
+                return false;
+
+            FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
+            Debug.Indent();
+            foreach (FieldInfo field in fields)
+            {
+                if (!CheckType(field.FieldType))
+                    return false;
+            }
+            Debug.Unindent();
+
+            return Stride != 0;
+        }
+
+        // Checks whether the specified struct defines [StructLayout(LayoutKind.Sequential, Pack=1)]
+        // or [StructLayout(LayoutKind.Explicit)]
+        static bool CheckStructLayoutAttribute(Type type)
+        {
+            StructLayoutAttribute[] attr = (StructLayoutAttribute[])
+                type.GetCustomAttributes(typeof(StructLayoutAttribute), true);
+
+            if ((attr == null) ||
+                (attr != null && attr.Length > 0 && attr[0].Value != LayoutKind.Explicit && attr[0].Pack != 1))
+                return false;
+
+            return true;
+        }
+
+        #endregion
+    }
+
+    #endregion
+
+    #region BlittableValueType
+
+    /// <summary>
+    /// Checks whether the specified type parameter is a blittable value type.
+    /// </summary>
+    /// <remarks>
+    /// A blittable value type is a struct that only references other value types recursively,
+    /// which allows it to be passed to unmanaged code directly.
+    /// </remarks>
+    public static class BlittableValueType
+    {
+        #region Check
+
+        /// <summary>
+        /// Checks whether type is a blittable value type.
+        /// </summary>
+        /// <param name="type">An instance of the type to check.</param>
+        /// <returns>True if T is blittable; false otherwise.</returns>
+        public static bool Check<T>(T type)
+        {
+            return BlittableValueType<T>.Check();
+        }
+
+        /// <summary>
+        /// Checks whether type is a blittable value type.
+        /// </summary>
+        /// <param name="type">An instance of the type to check.</param>
+        /// <returns>True if T is blittable; false otherwise.</returns>
+        [CLSCompliant(false)]
+        public static bool Check<T>(T[] type)
+        {
+            return BlittableValueType<T>.Check();
+        }
+
+        /// <summary>
+        /// Checks whether type is a blittable value type.
+        /// </summary>
+        /// <param name="type">An instance of the type to check.</param>
+        /// <returns>True if T is blittable; false otherwise.</returns>
+        [CLSCompliant(false)]
+        public static bool Check<T>(T[,] type)
+        {
+            return BlittableValueType<T>.Check();
+        }
+
+        /// <summary>
+        /// Checks whether type is a blittable value type.
+        /// </summary>
+        /// <param name="type">An instance of the type to check.</param>
+        /// <returns>True if T is blittable; false otherwise.</returns>
+        [CLSCompliant(false)]
+        public static bool Check<T>(T[, ,] type)
+        {
+            return BlittableValueType<T>.Check();
+        }
+
+        /// <summary>
+        /// Checks whether type is a blittable value type.
+        /// </summary>
+        /// <param name="type">An instance of the type to check.</param>
+        /// <returns>True if T is blittable; false otherwise.</returns>
+        [CLSCompliant(false)]
+        public static bool Check<T>(T[][] type)
+        {
+            return BlittableValueType<T>.Check();
+        }
+
+        #endregion
+
+        #region StrideOf
+
+        /// <summary>
+        /// Returns the size of the specified value type in bytes or 0 if the type is not blittable.
+        /// </summary>
+        /// <typeparam name="T">The value type. Must be blittable.</typeparam>
+        /// <param name="type">An instance of the value type.</param>
+        /// <returns>An integer, specifying the size of the type in bytes.</returns>
+        /// <exception cref="System.ArgumentException">Occurs when type is not blittable.</exception>
+        public static int StrideOf<T>(T type)
+        {
+            if (!Check(type))
+                throw new ArgumentException("type");
+
+            return BlittableValueType<T>.Stride;
+        }
+
+        /// <summary>
+        /// Returns the size of a single array element in bytes  or 0 if the element is not blittable.
+        /// </summary>
+        /// <typeparam name="T">The value type.</typeparam>
+        /// <param name="type">An instance of the value type.</param>
+        /// <returns>An integer, specifying the size of the type in bytes.</returns>
+        /// <exception cref="System.ArgumentException">Occurs when type is not blittable.</exception>
+        [CLSCompliant(false)]
+        public static int StrideOf<T>(T[] type)
+        {
+            if (!Check(type))
+                throw new ArgumentException("type");
+
+            return BlittableValueType<T>.Stride;
+        }
+
+        /// <summary>
+        /// Returns the size of a single array element in bytes or 0 if the element is not blittable.
+        /// </summary>
+        /// <typeparam name="T">The value type.</typeparam>
+        /// <param name="type">An instance of the value type.</param>
+        /// <returns>An integer, specifying the size of the type in bytes.</returns>
+        /// <exception cref="System.ArgumentException">Occurs when type is not blittable.</exception>
+        [CLSCompliant(false)]
+        public static int StrideOf<T>(T[,] type)
+        {
+            if (!Check(type))
+                throw new ArgumentException("type");
+
+            return BlittableValueType<T>.Stride;
+        }
+
+        /// <summary>
+        /// Returns the size of a single array element in bytes or 0 if the element is not blittable.
+        /// </summary>
+        /// <typeparam name="T">The value type.</typeparam>
+        /// <param name="type">An instance of the value type.</param>
+        /// <returns>An integer, specifying the size of the type in bytes.</returns>
+        /// <exception cref="System.ArgumentException">Occurs when type is not blittable.</exception>
+        [CLSCompliant(false)]
+        public static int StrideOf<T>(T[, ,] type)
+        {
+            if (!Check(type))
+                throw new ArgumentException("type");
+
+            return BlittableValueType<T>.Stride;
+        }
+
+        #endregion
+    }
+
+    #endregion
+}
diff --git a/testDrm/src/DisplayDevice.cs b/testDrm/src/DisplayDevice.cs
new file mode 100644 (file)
index 0000000..bfd3960
--- /dev/null
@@ -0,0 +1,565 @@
+#region License
+//
+// The Open Toolkit Library License
+//
+// Copyright (c) 2006 - 2010 the Open Toolkit library.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights to 
+// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+// the Software, and to permit persons to whom the Software is furnished to do
+// so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+#if !MINIMAL
+using System.Drawing;
+#endif
+
+namespace OpenTK
+{
+    /// <summary>
+    /// Defines a display device on the underlying system, and provides
+    /// methods to query and change its display parameters.
+    /// </summary>
+    public class DisplayDevice
+    {
+        // TODO: Add properties that describe the 'usable' size of the Display, i.e. the maximized size without the taskbar etc.
+        // TODO: Does not detect changes to primary device.
+
+        #region Fields
+
+        bool primary;
+        Rectangle bounds;
+        DisplayResolution current_resolution = new DisplayResolution();
+        DisplayResolution original_resolution;
+        List<DisplayResolution> available_resolutions = new List<DisplayResolution>();
+        IList<DisplayResolution> available_resolutions_readonly;
+        
+        internal object Id; // A platform-specific id for this monitor
+
+        static readonly object display_lock = new object();
+        static DisplayDevice primary_display;
+
+        static Platform.IDisplayDeviceDriver implementation;
+
+        #endregion
+
+        #region Constructors
+
+        static DisplayDevice()
+        {
+            implementation = Platform.Factory.Default.CreateDisplayDeviceDriver();
+        }
+
+        internal DisplayDevice()
+        {
+            available_resolutions_readonly = available_resolutions.AsReadOnly();
+        }
+
+        internal DisplayDevice(DisplayResolution currentResolution, bool primary,
+            IEnumerable<DisplayResolution> availableResolutions, Rectangle bounds,
+            object id)
+            : this()
+        {
+            // Todo: Consolidate current resolution with bounds? Can they fall out of sync right now?
+            this.current_resolution = currentResolution;
+            IsPrimary = primary;
+            this.available_resolutions.AddRange(availableResolutions);
+            #pragma warning disable 612,618
+            this.bounds = bounds == Rectangle.Empty ? currentResolution.Bounds : bounds;
+            #pragma warning restore 612,618
+            this.Id = id;
+        }
+
+        #endregion
+
+        #region --- Public Methods ---
+
+        #region public Rectangle Bounds
+
+        /// <summary>
+        /// Gets the bounds of this instance in pixel coordinates..
+        /// </summary>
+        public Rectangle Bounds
+        {
+            get { return bounds; }
+            internal set
+            {
+                bounds = value;
+                current_resolution.Height = bounds.Height;
+                current_resolution.Width = bounds.Width;
+            }
+        }
+
+        #endregion
+
+        #region public int Width
+
+        /// <summary>Gets a System.Int32 that contains the width of this display in pixels.</summary>
+        public int Width { get { return current_resolution.Width; } }
+
+        #endregion
+
+        #region public int Height
+
+        /// <summary>Gets a System.Int32 that contains the height of this display in pixels.</summary>
+        public int Height { get { return current_resolution.Height; } }
+
+        #endregion
+
+        #region public int BitsPerPixel
+
+        /// <summary>Gets a System.Int32 that contains number of bits per pixel of this display. Typical values include 8, 16, 24 and 32.</summary>
+        public int BitsPerPixel
+        {
+            get { return current_resolution.BitsPerPixel; }
+            internal set { current_resolution.BitsPerPixel = value; }
+        }
+
+        #endregion
+
+        #region public float RefreshRate
+
+        /// <summary>
+        /// Gets a System.Single representing the vertical refresh rate of this display.
+        /// </summary>
+        public float RefreshRate
+        {
+            get { return current_resolution.RefreshRate; }
+            internal set { current_resolution.RefreshRate = value; }
+        }
+
+        #endregion
+
+        #region public bool IsPrimary
+
+        /// <summary>Gets a System.Boolean that indicates whether this Display is the primary Display in systems with multiple Displays.</summary>
+        public bool IsPrimary
+        {
+            get { return primary; }
+            internal set
+            {
+                if (value && primary_display != null && primary_display != this)
+                    primary_display.IsPrimary = false;
+
+                lock (display_lock)
+                {
+                    primary = value;
+                    if (value)
+                        primary_display = this;
+                }
+            }
+        }
+
+        #endregion
+
+        #region public DisplayResolution SelectResolution(int width, int height, int bitsPerPixel, float refreshRate)
+
+        /// <summary>
+        /// Selects an available resolution that matches the specified parameters.
+        /// </summary>
+        /// <param name="width">The width of the requested resolution in pixels.</param>
+        /// <param name="height">The height of the requested resolution in pixels.</param>
+        /// <param name="bitsPerPixel">The bits per pixel of the requested resolution.</param>
+        /// <param name="refreshRate">The refresh rate of the requested resolution in hertz.</param>
+        /// <returns>The requested DisplayResolution or null if the parameters cannot be met.</returns>
+        /// <remarks>
+        /// <para>If a matching resolution is not found, this function will retry ignoring the specified refresh rate,
+        /// bits per pixel and resolution, in this order. If a matching resolution still doesn't exist, this function will
+        /// return the current resolution.</para>
+        /// <para>A parameter set to 0 or negative numbers will not be used in the search (e.g. if refreshRate is 0,
+        /// any refresh rate will be considered valid).</para>
+        /// <para>This function allocates memory.</para>
+        /// </remarks>
+        public DisplayResolution SelectResolution(int width, int height, int bitsPerPixel, float refreshRate)
+        {
+            DisplayResolution resolution = FindResolution(width, height, bitsPerPixel, refreshRate);
+            if (resolution == null)
+                resolution = FindResolution(width, height, bitsPerPixel, 0);
+            if (resolution == null)
+                resolution = FindResolution(width, height, 0, 0);
+            if (resolution == null)
+                return current_resolution;
+            return resolution;
+        }
+
+        #endregion
+
+        #region public IList<DisplayResolution> AvailableResolutions
+
+        /// <summary>
+        /// Gets the list of <see cref="DisplayResolution"/> objects available on this device.
+        /// </summary>
+        public IList<DisplayResolution> AvailableResolutions
+        {
+            get { return available_resolutions_readonly; }
+            internal set
+            {
+                available_resolutions = (List<DisplayResolution>)value;
+                available_resolutions_readonly = available_resolutions.AsReadOnly();
+            }
+        }
+
+        #endregion
+
+        #region public void ChangeResolution(DisplayResolution resolution)
+
+        /// <summary>Changes the resolution of the DisplayDevice.</summary>
+        /// <param name="resolution">The resolution to set. <see cref="DisplayDevice.SelectResolution"/></param>
+        /// <exception cref="Graphics.GraphicsModeException">Thrown if the requested resolution could not be set.</exception>
+        /// <remarks>If the specified resolution is null, this function will restore the original DisplayResolution.</remarks>
+        public void ChangeResolution(DisplayResolution resolution)
+        {
+            if (resolution == null)
+                this.RestoreResolution();
+
+            if (resolution == current_resolution)
+                return;
+
+            //effect.FadeOut();
+
+            if (implementation.TryChangeResolution(this, resolution))
+            {
+                if (original_resolution == null)
+                    original_resolution = current_resolution;
+                current_resolution = resolution;
+            }
+            else throw new Graphics.GraphicsModeException(String.Format("Device {0}: Failed to change resolution to {1}.",
+                    this, resolution));
+
+            //effect.FadeIn();
+        }
+
+        #endregion
+
+        #region public void ChangeResolution(int width, int height, int bitsPerPixel, float refreshRate)
+
+        /// <summary>Changes the resolution of the DisplayDevice.</summary>
+        /// <param name="width">The new width of the DisplayDevice.</param>
+        /// <param name="height">The new height of the DisplayDevice.</param>
+        /// <param name="bitsPerPixel">The new bits per pixel of the DisplayDevice.</param>
+        /// <param name="refreshRate">The new refresh rate of the DisplayDevice.</param>
+        /// <exception cref="Graphics.GraphicsModeException">Thrown if the requested resolution could not be set.</exception>
+        public void ChangeResolution(int width, int height, int bitsPerPixel, float refreshRate)
+        {
+            this.ChangeResolution(this.SelectResolution(width, height, bitsPerPixel, refreshRate));
+        }
+
+        #endregion
+
+        #region public void RestoreResolution()
+
+        /// <summary>Restores the original resolution of the DisplayDevice.</summary>
+        /// <exception cref="Graphics.GraphicsModeException">Thrown if the original resolution could not be restored.</exception>
+        public void RestoreResolution()
+        {
+            if (original_resolution != null)
+            {
+                //effect.FadeOut();
+
+                if (implementation.TryRestoreResolution(this))
+                {
+                    current_resolution = original_resolution;
+                    original_resolution = null;
+                }
+                else throw new Graphics.GraphicsModeException(String.Format("Device {0}: Failed to restore resolution.", this));
+
+                //effect.FadeIn();
+            }
+        }
+
+        #endregion
+
+        #region public static IList<DisplayDevice> AvailableDisplays
+
+        /// <summary>
+        /// Gets the list of available <see cref="DisplayDevice"/> objects.
+        /// This function allocates memory.
+        /// </summary>
+        [Obsolete("Use GetDisplay(DisplayIndex) instead.")]
+        public static IList<DisplayDevice> AvailableDisplays
+        {
+            get
+            {
+                List<DisplayDevice> displays = new List<DisplayDevice>();
+                for (int i = 0; i < 6; i++)
+                {
+                    DisplayDevice dev = GetDisplay(DisplayIndex.First + i);
+                    if (dev != null)
+                        displays.Add(dev);
+                }
+
+                return displays.AsReadOnly();
+            }
+        }
+
+        #endregion
+
+        #region public static DisplayDevice Default
+
+        /// <summary>Gets the default (primary) display of this system.</summary>
+        public static DisplayDevice Default
+        {
+            get { return implementation.GetDisplay(DisplayIndex.Primary); }
+        }
+
+        #endregion
+
+        #region GetDisplay
+
+        /// <summary>
+        /// Gets the <see cref="DisplayDevice"/> for the specified <see cref="DisplayIndex"/>.
+        /// </summary>
+        /// <param name="index">The <see cref="DisplayIndex"/> that defines the desired display.</param>
+        /// <returns>A <see cref="DisplayDevice"/> or null, if no device corresponds to the specified index.</returns>
+        public static DisplayDevice GetDisplay(DisplayIndex index)
+        {
+            return implementation.GetDisplay(index);
+        }
+
+        #endregion
+
+        #endregion
+
+        #region --- Internal Methods ---
+
+        #region internal DisplayResolution OriginalResolution
+
+        /// <summary>
+        /// Gets the original resolution of this instance.
+        /// </summary>
+        internal DisplayResolution OriginalResolution
+        {
+            get { return original_resolution; }
+            set { original_resolution = value; }
+        }
+
+        #endregion
+
+        #region FromPoint
+
+        internal static DisplayDevice FromPoint(int x, int y)
+        {
+            for (DisplayIndex i = DisplayIndex.First; i < DisplayIndex.Sixth; i++)
+            {
+                DisplayDevice display = DisplayDevice.GetDisplay(i);
+                if (display != null)
+                {
+                    if (display.Bounds.Contains(x, y))
+                    {
+                        return display;
+                    }
+                }
+            }
+            return null;
+        }
+
+        #endregion
+
+        #endregion
+
+        #region --- Private Methods ---
+
+        #region DisplayResolution FindResolution(int width, int height, int bitsPerPixel, float refreshRate)
+
+        DisplayResolution FindResolution(int width, int height, int bitsPerPixel, float refreshRate)
+        {
+            return available_resolutions.Find(delegate(DisplayResolution test)
+            {
+                return
+                    ((width > 0 && width == test.Width) || width == 0) &&
+                    ((height > 0 && height == test.Height) || height == 0) &&
+                    ((bitsPerPixel > 0 && bitsPerPixel == test.BitsPerPixel) || bitsPerPixel == 0) &&
+                    ((refreshRate > 0 && System.Math.Abs(refreshRate - test.RefreshRate) < 1.0) || refreshRate == 0);
+            });
+        }
+
+        #endregion
+
+        #endregion
+
+        #region --- Overrides ---
+
+        #region public override string ToString()
+
+        /// <summary>
+        /// Returns a System.String representing this DisplayDevice.
+        /// </summary>
+        /// <returns>A System.String representing this DisplayDevice.</returns>
+        public override string ToString()
+        {
+            return String.Format("{0}: {1} ({2} modes available)", IsPrimary ? "Primary" : "Secondary",
+                Bounds.ToString(), available_resolutions.Count);
+        }
+
+        #endregion
+
+        #region public override bool Equals(object obj)
+
+        ///// <summary>Determines whether the specified DisplayDevices are equal.</summary>
+        ///// <param name="obj">The System.Object to check against.</param>
+        ///// <returns>True if the System.Object is an equal DisplayDevice; false otherwise.</returns>
+        //public override bool Equals(object obj)
+        //{
+        //    if (obj is DisplayDevice)
+        //    {
+        //        DisplayDevice dev = (DisplayDevice)obj;
+        //        return
+        //            IsPrimary == dev.IsPrimary &&
+        //            current_resolution == dev.current_resolution &&
+        //            available_resolutions.Count == dev.available_resolutions.Count;
+        //    }
+
+        //    return false;
+        //}
+
+        #endregion
+
+        #region public override int GetHashCode()
+
+        ///// <summary>Returns a unique hash representing this DisplayDevice.</summary>
+        ///// <returns>A System.Int32 that may serve as a hash code for this DisplayDevice.</returns>
+        ////public override int GetHashCode()
+        //{
+        //    return current_resolution.GetHashCode() ^ IsPrimary.GetHashCode() ^ available_resolutions.Count;
+        //}
+
+        #endregion
+
+        #endregion
+    }
+
+    #region --- FadeEffect ---
+#if false
+    class FadeEffect : IDisposable
+    {
+        List<Form> forms = new List<Form>();
+        double opacity_step = 0.04;
+        int sleep_step;
+
+        internal FadeEffect()
+        {
+            foreach (Screen s in Screen.AllScreens)
+            {
+                Form form = new Form();
+                form.ShowInTaskbar = false;
+                form.StartPosition = FormStartPosition.Manual;
+                form.WindowState = FormWindowState.Maximized;
+                form.FormBorderStyle = FormBorderStyle.None;
+                form.TopMost = true;
+
+                form.BackColor = System.Drawing.Color.Black;
+                forms.Add(form);
+            }
+
+            sleep_step = 10 / forms.Count;
+            MoveToStartPositions();
+        }
+
+        void MoveToStartPositions()
+        {
+            int count = 0;
+            foreach (Screen s in Screen.AllScreens)
+            {
+            //    forms[count++].Location = new System.Drawing.Point(s.Bounds.X, s.Bounds.Y);
+                //forms[count].Size = new System.Drawing.Size(4096, 4096);
+                count++;
+            }
+        }
+
+        bool FadedOut
+        {
+            get
+            {
+                bool ready = true;
+                foreach (Form form in forms)
+                    ready = ready && form.Opacity >= 1.0;
+
+                return ready;
+            }
+        }
+
+        bool FadedIn
+        {
+            get
+            {
+                bool ready = true;
+                foreach (Form form in forms)
+                    ready = ready && form.Opacity <= 0.0;
+
+                return ready;
+            }
+        }
+
+        internal void FadeOut()
+        {
+            MoveToStartPositions();
+
+            foreach (Form form in forms)
+            {
+                form.Opacity = 0.0;
+                form.Visible = true;
+            }
+
+            while (!FadedOut)
+            {
+                foreach (Form form in forms)
+                {
+                    form.Opacity += opacity_step;
+                    form.Refresh();
+                }
+                Thread.Sleep(sleep_step);
+            }
+        }
+
+        internal void FadeIn()
+        {
+            MoveToStartPositions();
+
+            foreach (Form form in forms)
+                form.Opacity = 1.0;
+
+            while (!FadedIn)
+            {
+                foreach (Form form in forms)
+                {
+                    form.Opacity -= opacity_step;
+                    form.Refresh();
+                }
+                Thread.Sleep(sleep_step);
+            }
+
+            foreach (Form form in forms)
+                form.Visible = false;
+        }
+
+        #region IDisposable Members
+
+        public void Dispose()
+        {
+            foreach (Form form in forms)
+                form.Dispose();
+        }
+
+        #endregion
+    }
+#endif
+    #endregion
+}
diff --git a/testDrm/src/DisplayResolution.cs b/testDrm/src/DisplayResolution.cs
new file mode 100644 (file)
index 0000000..4341940
--- /dev/null
@@ -0,0 +1,232 @@
+#region --- License ---
+/* Licensed under the MIT/X11 license.
+ * Copyright (c) 2006-2008 the OpenTK team.
+ * This notice may not be removed.
+ * See license.txt for licensing detailed licensing details.
+ */
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Diagnostics;
+#if !MINIMAL
+using System.Drawing;
+#endif
+
+namespace OpenTK
+{
+    /// <summary>Contains information regarding a monitor's display resolution.</summary>
+    public class DisplayResolution
+    {
+        Rectangle bounds;
+        int bits_per_pixel;
+        float refresh_rate;
+
+        #region --- Constructors ---
+
+        internal DisplayResolution() { }
+
+        #region public DisplayResolution(int width, int height, int bitsPerPixel, float refreshRate)
+
+        // Creates a new DisplayResolution object for the primary DisplayDevice.
+        internal DisplayResolution(int x, int y, int width, int height, int bitsPerPixel, float refreshRate)
+        {
+            // Refresh rate may be zero, since this information may not be available on some platforms.
+            if (width <= 0) throw new ArgumentOutOfRangeException("width", "Must be greater than zero.");
+            if (height <= 0) throw new ArgumentOutOfRangeException("height", "Must be greater than zero.");
+            if (bitsPerPixel <= 0) throw new ArgumentOutOfRangeException("bitsPerPixel", "Must be greater than zero.");
+            if (refreshRate < 0) throw new ArgumentOutOfRangeException("refreshRate", "Must be greater than, or equal to zero.");
+
+            this.bounds = new Rectangle(x, y, width, height);
+            this.bits_per_pixel = bitsPerPixel;
+            this.refresh_rate = refreshRate;
+        }
+
+        #endregion
+
+        #region public DisplayResolution(int width, int height, int bitsPerPixel, float refreshRate, DisplayDevice device)
+
+#if false
+
+        /// <summary>
+        /// Creates a new DisplayResolution object for the specified DisplayDevice.
+        /// </summary>
+        /// <param name="width">The requested width in pixels.</param>
+        /// <param name="height">The requested height in pixels.</param>
+        /// <param name="bitsPerPixel">The requested bits per pixel in bits.</param>
+        /// <param name="refreshRate">The requested refresh rate in hertz.</param>
+        /// <remarks>OpenTK will select the closest match between all available resolutions on the specified DisplayDevice.</remarks>
+        /// 
+        public DisplayResolution(int width, int height, int bitsPerPixel, float refreshRate, DisplayDevice device)
+        {
+            // Refresh rate may be zero, since this information may not be available on some platforms.
+            if (width <= 0) throw new ArgumentOutOfRangeException("width", "Must be greater than zero.");
+            if (height <= 0) throw new ArgumentOutOfRangeException("height", "Must be greater than zero.");
+            if (bitsPerPixel <= 0) throw new ArgumentOutOfRangeException("bitsPerPixel", "Must be greater than zero.");
+            if (refreshRate < 0) throw new ArgumentOutOfRangeException("refreshRate", "Must be greater than, or equal to zero.");
+            if (device == null) throw new ArgumentNullException("DisplayDevice", "Must be a valid DisplayDevice");
+
+            DisplayResolution res = device.SelectResolution(width, height, bitsPerPixel, refreshRate);
+
+            this.width = res.width;
+            this.height = res.height;
+            this.bits_per_pixel = res.bits_per_pixel;
+            this.refresh_rate = res.refresh_rate;
+        }
+#endif
+        #endregion
+
+        #endregion
+
+        #region --- Public Methods ---
+
+        #region Bounds
+
+        /// <summary>
+        /// Gets a System.Drawing.Rectangle that contains the bounds of this display device.
+        /// </summary>
+        [Obsolete("This property will return invalid results if a monitor changes resolution. Use DisplayDevice.Bounds instead.")]
+        [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
+        public Rectangle Bounds
+        {
+            get { return bounds; }
+        }
+
+        #endregion
+
+        #region public int Width
+
+        /// <summary>Gets a System.Int32 that contains the width of this display in pixels.</summary>
+        public int Width
+        {
+            get { return bounds.Width; }
+            internal set { bounds.Width = value; }
+        }
+
+        #endregion
+
+        #region public int Height
+
+        /// <summary>Gets a System.Int32 that contains the height of this display in pixels.</summary>
+        public int Height
+        {
+            get { return bounds.Height; }
+            internal set { bounds.Height = value; }
+        }
+
+        #endregion
+
+        #region public int BitsPerPixel
+
+        /// <summary>Gets a System.Int32 that contains number of bits per pixel of this display. Typical values include 8, 16, 24 and 32.</summary>
+        public int BitsPerPixel
+        {
+            get { return bits_per_pixel; }
+            internal set { bits_per_pixel = value; }
+        }
+
+        #endregion
+
+        #region public float RefreshRate
+
+        /// <summary>
+        /// Gets a System.Single representing the vertical refresh rate of this display.
+        /// </summary>
+        public float RefreshRate
+        {
+            get { return refresh_rate; }
+            internal set { refresh_rate = value; }
+        }
+
+        #endregion
+
+        #endregion
+
+        #region --- Overrides ---
+
+        #region public override string ToString()
+
+        /// <summary>
+        /// Returns a System.String representing this DisplayResolution.
+        /// </summary>
+        /// <returns>A System.String representing this DisplayResolution.</returns>
+        public override string ToString()
+        {
+            #pragma warning disable 612,618
+            return String.Format("{0}x{1}@{2}Hz", Bounds, bits_per_pixel, refresh_rate);
+            #pragma warning restore 612,618
+        }
+
+        #endregion
+
+        #region public override bool Equals(object obj)
+
+        /// <summary>Determines whether the specified resolutions are equal.</summary>
+        /// <param name="obj">The System.Object to check against.</param>
+        /// <returns>True if the System.Object is an equal DisplayResolution; false otherwise.</returns>
+        public override bool Equals(object obj)
+        {
+            if (obj == null) return false;
+            if (this.GetType() == obj.GetType())
+            {
+                DisplayResolution res = (DisplayResolution)obj;
+                return
+                    Width == res.Width &&
+                    Height == res.Height &&
+                    BitsPerPixel == res.BitsPerPixel &&
+                    RefreshRate == res.RefreshRate;
+            }
+
+            return false;
+        }
+
+        #endregion
+
+        #region public override int GetHashCode()
+
+        /// <summary>Returns a unique hash representing this resolution.</summary>
+        /// <returns>A System.Int32 that may serve as a hash code for this resolution.</returns>
+        public override int GetHashCode()
+        {
+            #pragma warning disable 612,618
+            return Bounds.GetHashCode() ^ bits_per_pixel ^ refresh_rate.GetHashCode();
+            #pragma warning restore 612,618
+        }
+
+        #endregion
+
+        #endregion
+
+        #region --- Operator Overloads ---
+
+        /// <summary>
+        /// Compares two instances for equality.
+        /// </summary>
+        /// <param name="left">The first instance.</param>
+        /// <param name="right">The second instance.</param>
+        /// <returns>True, if left equals right; false otherwise.</returns>
+        public static bool operator== (DisplayResolution left, DisplayResolution right)
+        {
+            if (((object)left) == null && ((object)right) == null)
+                return true;
+            else if ((((object)left) == null && ((object)right) != null) ||
+                     (((object)left) != null && ((object)right) == null))
+                return false;
+            return left.Equals(right);
+        }
+
+        /// <summary>
+        /// Compares two instances for inequality.
+        /// </summary>
+        /// <param name="left">The first instance.</param>
+        /// <param name="right">The second instance.</param>
+        /// <returns>True, if left does not equal right; false otherwise.</returns>
+        public static bool operator !=(DisplayResolution left, DisplayResolution right)
+        {
+            return !(left == right);
+        }
+
+        #endregion
+    }
+}
diff --git a/testDrm/src/DrmDevice.cs b/testDrm/src/DrmDevice.cs
new file mode 100644 (file)
index 0000000..82697ba
--- /dev/null
@@ -0,0 +1,927 @@
+//
+// DrmKms.cs
+//
+// Author:
+//       Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
+//
+// Copyright (c) 2013-2017 Jean-Philippe Bruyère
+//
+// 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.
+using System;
+using OpenTK.Platform.Linux;
+using OpenTK;
+using System.IO;
+using System.Collections.Generic;
+using System.Diagnostics;
+using OpenTK.Platform.Egl;
+using System.Runtime.InteropServices;
+using System.Threading;
+
+namespace testDrm
+{
+       public class DrmDevice : IDisposable
+       {
+               volatile bool run = true;
+
+               int fd = 0;
+               int major, minor;
+               IntPtr gbm_device, gbm_surface, egl_display, egl_config, egl_surface, egl_ctx;
+
+               int r, g, b, a;
+
+               BufferObject cursor_custom;
+               BufferObject cursor_default;
+               BufferObject cursor_empty;
+
+
+               ModeInfo originalMode;
+
+               public IntPtr Connector;
+               public IntPtr Crtc;
+               public IntPtr Encoder;
+               unsafe ModeConnector* pConnector { get { return (ModeConnector*)Connector; } }
+               unsafe ModeCrtc* pCrtc { get { return (ModeCrtc*)Crtc; } }
+               unsafe ModeEncoder* pEncoder { get { return (ModeEncoder*)Encoder; } }
+
+               Cairo.EGLDevice cairoDev;
+               Cairo.GLSurface cairoSurf;
+
+               public DrmDevice(string gpu_path = "/dev/dri/card0"){
+
+                       PageFlip = HandlePageFlip;
+                       PageFlipPtr = Marshal.GetFunctionPointerForDelegate(PageFlip);          
+
+                       gbm_device = IntPtr.Zero;
+                       egl_display = IntPtr.Zero;
+
+                       fd = Libc.open(gpu_path, OpenFlags.ReadWrite | OpenFlags.CloseOnExec);
+                       if (fd < 0)
+                               throw new NotSupportedException("[KMS] Failed to open gpu");                    
+                       Console.WriteLine("[KMS] GPU '{0}' opened as fd:{1}", gpu_path, fd);
+
+                       initDrm ();
+
+                       initGbm ();
+
+                       initEgl ();
+
+                       initCairo ();
+
+                       initInput ();
+               }
+
+               #region init
+               unsafe void initDrm(){                  
+                       ModeRes* resources = (ModeRes*)Drm.ModeGetResources(fd);
+                       if (resources == null)
+                               throw new NotSupportedException("[KMS] Drm.ModeGetResources failed.");
+
+                       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_encoders > 0)
+                                               break;
+                                       Drm.ModeFreeConnector ((IntPtr)connector);
+                                       connector = null;
+                               }
+                       }
+                       if (connector == null)
+                               throw new NotSupportedException("[KMS] No connected screen found");
+
+                       Connector = (IntPtr)connector;
+                       Encoder = Drm.ModeGetEncoder (fd, connector->encoder_id);
+                       Crtc = Drm.ModeGetCrtc(fd, pEncoder->crtc_id);
+
+                       originalMode = pCrtc->mode;
+                       Console.WriteLine ("[DRM]: current mode = {0} X {1} at {2} Hz", originalMode.hdisplay, originalMode.vdisplay, originalMode.vrefresh);
+               }
+               void initGbm (){
+                       gbm_device = Gbm.CreateDevice(fd);
+                       if (gbm_device == IntPtr.Zero)
+                               throw new NotSupportedException("[GBM] Failed to create GBM device");                   
+
+                       gbm_surface =  Gbm.CreateSurface(gbm_device, originalMode.hdisplay, originalMode.vdisplay, SurfaceFormat.ARGB8888, SurfaceFlags.Rendering | SurfaceFlags.Scanout);
+                       if (gbm_surface == IntPtr.Zero)
+                               throw new NotSupportedException("[GBM] Failed to create GBM surface for rendering");                                            
+               }
+
+               unsafe void initEgl () {
+                       IntPtr[] configs = new IntPtr[1];
+                       int[] contextAttrib = new int[] {
+                               Egl.CONTEXT_CLIENT_VERSION, 2,
+                               Egl.NONE
+                       };
+                       int[] attribList = new int[] 
+                       {                               
+                               Egl.SURFACE_TYPE, Egl.WINDOW_BIT,
+                               Egl.RENDERABLE_TYPE, Egl.OPENGL_BIT,
+                               Egl.RED_SIZE, 1, 
+                               Egl.GREEN_SIZE, 1, 
+                               Egl.BLUE_SIZE, 1,
+                               Egl.ALPHA_SIZE, 0,
+
+                               //Egl.DEPTH_SIZE, 24,
+                               //Egl.STENCIL_SIZE, 0,
+
+                               //Egl.SAMPLE_BUFFERS, 2,
+                               //Egl.SAMPLES, 0,
+                               Egl.NONE
+                       };
+                       int num_configs;
+
+                       egl_display = Egl.GetDisplay(gbm_device);
+                       if (egl_display == IntPtr.Zero)
+                               throw new NotSupportedException("[KMS] Failed to create EGL display");
+                       Console.WriteLine("[EGL] EGL display {0:x} created successfully", egl_display);
+
+                       if (!Egl.Initialize(egl_display, out major, out minor))
+                               throw new NotSupportedException("[EGL] Failed to initialize EGL display. Error code: " + Egl.GetError());
+
+                       if (!Egl.BindAPI (RenderApi.GL))
+                               throw new NotSupportedException("[EGL] Failed to bind EGL Api: " + Egl.GetError());
+
+                       Console.WriteLine ("[EGL] Version: " +  Marshal.PtrToStringAuto (Egl.QueryString (egl_display, Egl.VERSION)));
+                       Console.WriteLine ("[EGL] Vendor: " + Marshal.PtrToStringAuto (Egl.QueryString (egl_display, Egl.VENDOR)));
+                       Console.WriteLine ("[EGL] Extensions: " + Marshal.PtrToStringAuto (Egl.QueryString (egl_display, Egl.EXTENSIONS)));
+
+                       if (!Egl.ChooseConfig(egl_display, attribList, configs, configs.Length, out num_configs) || num_configs == 0)
+                               throw new NotSupportedException(String.Format("Failed to retrieve GraphicsMode, error {0}", Egl.GetError()));
+
+
+                       // See what we really got
+                       int d, s, sample_buffers, samples;
+                       IntPtr active_config = configs[0];
+                       Egl.GetConfigAttrib(egl_display, active_config, Egl.RED_SIZE, out r);
+                       Egl.GetConfigAttrib(egl_display, active_config, Egl.GREEN_SIZE, out g);
+                       Egl.GetConfigAttrib(egl_display, active_config, Egl.BLUE_SIZE, out b);
+                       Egl.GetConfigAttrib(egl_display, active_config, Egl.ALPHA_SIZE, out a);
+                       //Egl.GetConfigAttrib(egl_display, active_config, Egl.DEPTH_SIZE, out d);
+                       //Egl.GetConfigAttrib(egl_display, active_config, Egl.STENCIL_SIZE, out s);
+                       //Egl.GetConfigAttrib(egl_display, active_config, Egl.SAMPLE_BUFFERS, out sample_buffers);
+                       //Egl.GetConfigAttrib(egl_display, active_config, Egl.SAMPLES, out samples);
+//                     Console.WriteLine ("EGL context: {0},{1},{2},{3} depth={4} stencil={5} samples={6} sample buffers={7}",
+//                             r, g, b, a, d, s, samples, sample_buffers);
+                       egl_config = active_config;
+
+                       egl_ctx = Egl.CreateContext(egl_display, egl_config, IntPtr.Zero, contextAttrib);
+
+                       egl_surface = Egl.CreateWindowSurface(egl_display, egl_config, gbm_surface, IntPtr.Zero);
+
+                       if (egl_surface==IntPtr.Zero)
+                               throw new NotSupportedException(String.Format("[EGL] Failed to create window surface, error {0}.", Egl.GetError()));
+
+                       if (!Egl.MakeCurrent(egl_display, egl_surface, egl_surface, egl_ctx))
+                               throw new NotSupportedException(string.Format("Failed to make context {0} current. Error: {1}", gbm_surface, Egl.GetError()));
+                       
+                       cursor_default = CreateCursor(gbm_device, Cursors.Default);
+                       cursor_empty = CreateCursor(gbm_device, Cursors.Empty);
+
+                       SetCursor(MouseCursor.Default);
+                       unsafe {                                
+                               Drm.MoveCursor (fd, pEncoder->crtc_id, 50, 50);
+                       }
+               }
+
+               void initCairo (){
+                       cairoDev = new Cairo.EGLDevice (egl_display, egl_ctx);
+
+                       cairoSurf = new Cairo.GLSurface (cairoDev, egl_surface, originalMode.hdisplay, originalMode.vdisplay);
+                       //cairoSurf = new Cairo.EGLSurface (cairoDev, egl_surface, 1600, 900);
+
+                       cairoDev.SetThreadAware (false);
+
+                       if (cairoDev.Acquire () != Cairo.Status.Success)
+                               Console.WriteLine ("[Cairo]: Failed to acquire egl device.");
+               }
+               #endregion
+
+               #region cursor
+               static BufferObject CreateCursor(IntPtr gbm, MouseCursor cursor)
+               {
+                       if (cursor.Width > 64 || cursor.Height > 64)
+                       {
+                               Debug.Print("[KMS] Cursor size {0}x{1} unsupported. Maximum is 64x64.",
+                                       cursor.Width, cursor.Height);
+                               return default(BufferObject);
+                       }
+
+                       int width = 64;
+                       int height = 64;
+                       SurfaceFormat format = SurfaceFormat.ARGB8888;
+                       SurfaceFlags usage = SurfaceFlags.Cursor64x64 | SurfaceFlags.Write;
+
+                       Debug.Print("[KMS] Gbm.CreateBuffer({0:X}, {1}, {2}, {3}, {4}).",
+                               gbm, width, height, format, usage);
+
+                       BufferObject bo = Gbm.CreateBuffer(
+                               gbm, width, height, format, usage);
+
+                       if (bo == BufferObject.Zero)
+                       {
+                               Debug.Print("[KMS] Failed to create buffer.");
+                               return bo;
+                       }
+
+                       // Copy cursor.Data into a new buffer of the correct size
+                       byte[] cursor_data = new byte[width * height * 4];
+                       for (int y = 0; y < cursor.Height; y++)
+                       {
+                               int dst_offset = y * width * 4;
+                               int src_offset = y * cursor.Width * 4;
+                               int src_length = cursor.Width * 4;
+                               Array.Copy(
+                                       cursor.Data, src_offset,
+                                       cursor_data, dst_offset,
+                                       src_length);
+                       }
+                       bo.Write(cursor_data);
+
+                       return bo;
+               }
+               void SetCursor(MouseCursor cursor)
+               {
+                       BufferObject bo = default(BufferObject);
+                       if (cursor == MouseCursor.Default)
+                       {
+                               bo = cursor_default;
+                       }
+                       else if (cursor == MouseCursor.Empty)
+                       {
+                               bo = cursor_empty;
+                       }
+                       else
+                       {
+                               if (cursor_custom != BufferObject.Zero)
+                                       cursor_custom.Dispose();
+                               cursor_custom = CreateCursor(gbm_device, cursor);
+                               bo = cursor_custom;
+                       }
+
+                       // If we failed to create a proper cursor, try falling back
+                       // to the empty cursor. We do not want to crash here!
+                       if (bo == BufferObject.Zero)
+                       {
+                               bo = cursor_empty;
+                       }
+
+                       if (bo != BufferObject.Zero)
+                       {
+                               unsafe {
+                                       Drm.SetCursor (fd, pEncoder->crtc_id,
+                                               bo.Handle, bo.Width, bo.Height, cursor.X, cursor.Y);
+                               }
+                       }
+               }
+               #endregion
+               int x, y;
+
+               void drawR (Cairo.Context ctx, int inc, double r, double g, double b){
+                       ctx.Rectangle (x+inc, y+inc, 200, 200);
+                       ctx.SetSourceRGB (r, g, b);
+                       ctx.Fill ();
+               }
+               public void RenderingLoop(){
+                       while (run){
+                               if (updateMousePos) {
+                                       lock (Sync) {
+                                               updateMousePos = false;
+                                               unsafe {        
+                                                       Drm.MoveCursor (fd, pEncoder->crtc_id, MouseX, MouseY);
+                                               }
+                                       }
+                               }
+
+                               if (x > 700) {
+                                       x = y = 0;
+                               } else {
+                                       x+=1;
+                                       y+=1;
+                               }
+                               using (Cairo.Context ctx = new Cairo.Context (cairoSurf)) {
+                                       ctx.Rectangle (0, 0, 1024, 780);
+                                       ctx.SetSourceRGB (0, 0, 1);
+                                       ctx.Fill ();
+                                       drawR (ctx, 0, 0, 1, 0);
+                               }
+                               cairoSurf.Flush ();
+
+                               cairoSurf.SwapBuffers ();
+
+//                             if (!Egl.SwapBuffers(egl_display, egl_surface))
+//                                     throw new NotSupportedException(string.Format("Failed to swap buffers for context {0} current. Error: {1}", gbm_device, Egl.GetError()));
+
+                               if (Gbm.HasFreeBuffers (gbm_surface) == 0)
+                                       throw new Exception ("[GBM]: Out of free buffers.");
+
+                               next_bo = Gbm.LockFrontBuffer (gbm_surface);
+                               if (next_bo == BufferObject.Zero)
+                                       throw new Exception ("[GBM]: Failed to lock front buffer.");
+
+                               int width = next_bo.Width;
+                               int height = next_bo.Height;
+                               int bpp = 32;
+                               int depth = 24;
+                               int stride = next_bo.Stride;
+                               int hndBO = next_bo.Handle;
+
+                               int next_fb;
+                               int ret = Drm.ModeAddFB (fd, width, height,(byte)depth, (byte)bpp, stride, hndBO, out next_fb);
+                               if (ret != 0)
+                                       throw new Exception ("[DRM]: ModeAddFB failed.");
+
+                               SetScanoutRegion (next_fb);
+
+                               is_flip_queued = true;
+                               unsafe{
+                                       ret = Drm.ModePageFlip (fd, pEncoder->crtc_id, next_fb, PageFlipFlags.FlipEvent, IntPtr.Zero);
+                               }
+                               if (ret < 0)
+                                       throw new Exception ("[DRM] Failed to enqueue framebuffer flip.");
+
+                               PollFD fds = new PollFD();
+                               fds.fd = fd;
+                               fds.events = PollFlags.In;
+
+                               EventContext evctx = new EventContext();
+                               evctx.version = EventContext.Version;
+                               evctx.page_flip_handler = PageFlipPtr;
+
+                               int timeout = -1;//block ? -1 : 0;
+
+                               while (is_flip_queued)
+                               {
+                                       fds.revents = 0;
+                                       if (Libc.poll(ref fds, 1, timeout) < 0)
+                                               break;
+
+                                       if ((fds.revents & (PollFlags.Hup | PollFlags.Error)) != 0)
+                                               break;
+
+                                       if ((fds.revents & PollFlags.In) != 0)
+                                               Drm.HandleEvent(fd, ref evctx);
+                                       else
+                                               break;
+                               }
+                       }
+               }
+
+               #region rendering
+               BufferObject bo, next_bo;
+               int fb, next_fb;
+               bool is_flip_queued;
+               // We only support a SwapInterval of 0 (immediate)
+               // or 1 (vsynced).
+               // Todo: add support for SwapInterval of -1 (adaptive).
+               // This requires a small change in WaitFlip().
+               int swap_interval=0;
+
+               readonly IntPtr PageFlipPtr;
+               readonly PageFlipCallback PageFlip;
+
+               void HandlePageFlip(int fd,     int sequence, int tv_sec, int tv_usec, IntPtr user_data)
+               {
+                       is_flip_queued = false;
+                       if (fb != 0)
+                               Drm.ModeRmFB (fd, fb);
+                       fb = next_fb;
+                       next_fb = 0;
+                       if (bo != BufferObject.Zero)
+                               Gbm.ReleaseBuffer (gbm_surface, bo);
+                       bo = next_bo;
+                       next_bo = BufferObject.Zero;
+               }
+
+               static readonly DestroyUserDataCallback DestroyFB = HandleDestroyFB;
+               static void HandleDestroyFB(BufferObject bo, IntPtr data)
+               {
+                       IntPtr gbm = bo.Device;
+                       int fb = data.ToInt32();
+                       Debug.Print("[KMS] Destroying framebuffer {0}", fb);
+
+                       if (fb != 0)
+                               Drm.ModeRmFB(Gbm.DeviceGetFD(gbm), fb);
+               }
+
+               public void SwapBuffers()
+               {
+                       if (!Egl.SwapBuffers(egl_display, egl_surface))
+                               throw new NotSupportedException(string.Format("Failed to swap buffers for context {0} current. Error: {1}", gbm_device, Egl.GetError()));
+                       
+                       if (is_flip_queued)
+                       {
+                               // Todo: if we don't wait for the page flip,
+                               // we drop all rendering buffers and get a crash
+                               // in Egl.SwapBuffers(). We need to fix that
+                               // before we can disable vsync.
+                               WaitFlip(true); // WaitFlip(SwapInterval > 0)
+                               if (is_flip_queued)
+                               {
+                                       Debug.Print("[KMS] Dropping frame");
+                                       return;
+                               }
+                       }
+
+                       next_bo = Gbm.LockFrontBuffer (gbm_surface);
+                       int fb = GetFramebuffer(next_bo);
+                       QueueFlip(fb);
+               }
+
+               public void Update()
+               {
+                       WaitFlip(true);
+
+                       if (!Egl.SwapBuffers(egl_display, egl_surface))
+                               throw new NotSupportedException(string.Format("Failed to swap buffers for context {0} current. Error: {1}", gbm_device, Egl.GetError()));
+
+                       bo = Gbm.LockFrontBuffer (gbm_surface);
+                       int fb = GetFramebuffer(bo);
+                       SetScanoutRegion(fb);
+               }
+
+
+               void WaitFlip(bool block)
+               {
+                       PollFD fds = new PollFD();
+                       fds.fd = fd;
+                       fds.events = PollFlags.In;
+
+                       EventContext evctx = new EventContext();
+                       evctx.version = EventContext.Version;
+                       evctx.page_flip_handler = PageFlipPtr;
+
+                       int timeout = block ? -1 : 0;
+
+                       while (is_flip_queued)
+                       {
+                               fds.revents = 0;
+                               if (Libc.poll(ref fds, 1, timeout) < 0)
+                                       break;
+
+                               if ((fds.revents & (PollFlags.Hup | PollFlags.Error)) != 0)
+                                       break;
+
+                               if ((fds.revents & PollFlags.In) != 0)
+                                       Drm.HandleEvent(fd, ref evctx);
+                               else
+                                       break;
+                       }
+
+                       // Page flip has taken place, update buffer objects
+                       if (!is_flip_queued)
+                       {                               
+                               Gbm.ReleaseBuffer(gbm_surface, bo);
+                               bo = next_bo;
+                       }
+               }
+
+               void QueueFlip(int buffer)
+               {
+                       unsafe
+                       {
+                               int ret = Drm.ModePageFlip (fd, pEncoder->crtc_id, buffer, PageFlipFlags.FlipEvent, IntPtr.Zero);
+                               if (ret < 0)
+                                       Debug.Print("[KMS] Failed to enqueue framebuffer flip. Error: {0}", ret);
+
+                               is_flip_queued = true;
+                       }
+               }
+
+               void SetScanoutRegion(int buffer)
+               {                       
+                       unsafe
+                       {
+                               ModeInfo* mode = pConnector->modes;
+                               int connector_id = pConnector->connector_id;
+                               int crtc_id = pEncoder->crtc_id;
+
+                               int x = 0;
+                               int y = 0;
+                               int connector_count = 1;
+                               int ret = Drm.ModeSetCrtc(fd, crtc_id, buffer, x, y, &connector_id, connector_count, mode);
+
+                               if (ret != 0)
+                               {
+                                       Debug.Print("[KMS] Drm.ModeSetCrtc{0}, {1}, {2}, {3}, {4:x}, {5}, {6:x}) failed. Error: {7}",
+                                               fd, crtc_id, buffer, x, y, (IntPtr)connector_id, connector_count, (IntPtr)mode, ret);
+                               }
+                       }
+               }
+                       
+               int GetFramebuffer(BufferObject bo)
+               {
+                       if (bo == BufferObject.Zero)
+                               goto fail;
+
+                       int bo_handle = bo.Handle;
+                       if (bo_handle == 0)
+                       {
+                               Debug.Print("[KMS] Gbm.BOGetHandle({0:x}) failed.", bo);
+                               goto fail;
+                       }
+
+                       int width = bo.Width;
+                       int height = bo.Height;
+                       int bpp = 32;
+                       int depth = 24;
+                       int stride = bo.Stride;
+
+                       if (width == 0 || height == 0 || bpp == 0)
+                       {
+                               Debug.Print("[KMS] Invalid framebuffer format: {0}x{1} {2} {3} {4}",
+                                       width, height, stride, bpp, depth);
+                               goto fail;
+                       }
+
+                       int buffer;
+                       int ret = Drm.ModeAddFB (fd, width, height,(byte)depth, (byte)bpp, stride, bo_handle,out buffer);
+                       if (ret != 0)
+                       {
+                               Debug.Print("[KMS] Drm.ModeAddFB({0}, {1}, {2}, {3}, {4}, {5}, {6}) failed. Error: {7}",
+                                       fd, width, height, depth, bpp, stride, bo_handle, ret);
+                               goto fail;
+                       }
+
+                       bo.SetUserData((IntPtr)buffer, DestroyFB);
+                       return buffer;
+
+                       fail:
+                       Debug.Print("[Error] Failed to create framebuffer.");
+                       return -1;
+               }
+               #endregion
+
+               #region IDisposable implementation
+               public void Dispose ()
+               {
+                       cairoDev.Release ();
+                       cairoSurf.Dispose ();
+                       cairoDev.Dispose ();
+
+                       if (fb != 0)
+                               Drm.ModeRmFB (fd, fb);
+                       if (bo != BufferObject.Zero)
+                               Gbm.ReleaseBuffer (gbm_surface, bo);                    
+                       if (next_fb != 0)
+                               Drm.ModeRmFB (fd, next_fb);
+                       if (next_bo != BufferObject.Zero)
+                               Gbm.ReleaseBuffer (gbm_surface, next_bo);                       
+
+                       if (Egl.GetCurrentContext () == egl_ctx) {
+                               Console.WriteLine ("destroying context");
+                               Egl.DestroyContext (egl_display, egl_ctx);
+                       }else
+                               Console.WriteLine ("not current");
+
+                       cairoDev.Dispose ();
+
+                       Drm.ModeFreeCrtc (Crtc);
+                       Drm.ModeFreeConnector(Connector);
+                       Drm.ModeFreeEncoder(Encoder);
+                       Libc.close(fd);
+               }
+               #endregion
+
+               #region tests
+               unsafe void dumpDrmResources(){
+                       ModeRes* resources = (ModeRes*)Drm.ModeGetResources(fd);
+                       if (resources == null)
+                               throw new NotSupportedException("[KMS] Drm.ModeGetResources failed.");
+                       Console.WriteLine("[KMS] DRM found {0} connectors", resources->count_connectors);
+
+                       Console.WriteLine ("[ENCODERS]");
+                       for (int j = 0; j < resources->count_encoders; j++) {                                                   
+                               ModeEncoder* e = (ModeEncoder*)Drm.ModeGetEncoder(fd, *(resources->encoders + j));
+
+                               if (e == null)
+                                       continue;
+                               Console.WriteLine ("{0}\t{1}\t{2}",e->encoder_id, e->encoder_type, e->crtc_id);
+
+                               Drm.ModeFreeEncoder((IntPtr)e);
+                       }
+
+                       Console.WriteLine ("\n[CONNECTORS]");
+                       ModeConnector* connector = null;
+                       for (int i = 0; i < resources->count_connectors; i++)
+                       {
+                               connector = (ModeConnector*)Drm.ModeGetConnector(fd, *(resources->connectors + i));
+                               if (connector != null)
+                               {
+                                       Console.WriteLine ("{0}\t{1}\t{2}\t{3}",
+                                               connector->connector_id,
+                                               connector->connector_type,
+                                               connector->connection,
+                                               connector->encoder_id);
+
+                                       for (int j = 0; j < connector->count_modes; j++) {
+                                               ModeInfo* mode = connector->modes + j;
+                                               if (mode == null)
+                                                       continue;
+                                               Console.WriteLine ("\t{0,-20}{1,5}{2,5}{3,4} hz",                                                               
+                                                       new string(mode->name),
+                                                       mode->hdisplay,
+                                                       mode->vdisplay,
+                                                       mode->vrefresh);
+                                       }
+                                       Drm.ModeFreeConnector((IntPtr)connector);
+                                       connector = null;
+                               }
+                       }
+               }
+
+               unsafe static void GetModes(LinuxDisplay display, DisplayResolution[] modes, out DisplayResolution current)
+               {
+                       int mode_count = display.pConnector->count_modes;
+                       Console.WriteLine("[KMS] Display supports {0} mode(s)", mode_count);
+                       for (int i = 0; i < mode_count; i++)
+                       {
+                               ModeInfo* mode = display.pConnector->modes + i;
+                               if (mode != null)
+                               {
+                                       Console.WriteLine("Mode {0}: {1}x{2} @{3}", i,
+                                               mode->hdisplay, mode->vdisplay, mode->vrefresh);
+                                       DisplayResolution res = GetDisplayResolution(mode);
+                                       modes[i] = res;
+                               }
+                       }
+
+                       if (display.pCrtc->mode_valid != 0)
+                       {
+                               ModeInfo cmode = display.pCrtc->mode;
+                               current = GetDisplayResolution(&cmode);
+                       }
+                       else
+                       {
+                               current = GetDisplayResolution(display.pConnector->modes);
+                       }
+                       Console.WriteLine("Current mode: {0}", current.ToString());
+               }
+               unsafe static DisplayResolution GetDisplayResolution(ModeInfo* mode)
+               {
+                       return new DisplayResolution(
+                               0, 0,
+                               mode->hdisplay, mode->vdisplay,
+                               32, // This is actually part of the framebuffer, not the DisplayResolution
+                               mode->vrefresh);
+               }
+
+               unsafe static ModeInfo* GetModeInfo(LinuxDisplay display, DisplayResolution resolution)
+               {
+                       for (int i = 0; i < display.pConnector->count_modes; i++)
+                       {
+                               ModeInfo* mode = display.pConnector->modes + i;
+                               if (mode != null &&
+                                       mode->hdisplay == resolution.Width &&
+                                       mode->vdisplay == resolution.Height)
+                               {
+                                       return mode;
+                               }
+                       }
+                       return null;
+               }
+
+               SurfaceFormat GetSurfaceFormat()
+               {
+                       int format;
+                       Egl.GetConfigAttrib(egl_display, egl_config,
+                               Egl.NATIVE_VISUAL_ID, out format);
+                       if (format == 0)
+                               throw new Exception ("[KMS] Failed to retrieve EGL visual from GBM surface. Error: " + Egl.GetError());
+
+                       return (SurfaceFormat)format;
+               }
+               #endregion
+
+               #region INPUT
+               Thread input_thread;
+               long exit;
+
+               static readonly object Sync = new object();
+               static readonly Crow.Key[] KeyMap = Evdev.KeyMap;
+               static long DeviceFDCount;
+
+               IntPtr udev;
+               IntPtr input_context;
+
+               int input_fd = 0;
+
+               InputInterface input_interface = new InputInterface(
+                       OpenRestricted, CloseRestricted);
+               static CloseRestrictedCallback CloseRestricted = CloseRestrictedHandler;
+               static void CloseRestrictedHandler(int fd, IntPtr data)
+               {
+                       Debug.Print("[Input] Closing fd {0}", fd);
+                       int ret = Libc.close(fd);
+
+                       if (ret < 0)
+                       {
+                               Debug.Print("[Input] Failed to close fd {0}. Error: {1}", fd, ret);
+                       }
+                       else
+                       {
+                               Interlocked.Decrement(ref DeviceFDCount);
+                       }
+               }
+
+               static OpenRestrictedCallback OpenRestricted = OpenRestrictedHandler;
+               static int OpenRestrictedHandler(IntPtr path, int flags, IntPtr data) 
+               {
+                       int fd = Libc.open(path, (OpenFlags)flags);
+                       Debug.Print("[Input] Opening '{0}' with flags {1}. fd:{2}",
+                               Marshal.PtrToStringAnsi(path), (OpenFlags)flags, fd);
+
+                       if (fd >= 0)
+                       {
+                               Interlocked.Increment(ref DeviceFDCount);
+                       }
+
+                       return fd;
+               }
+
+               void initInput (){
+                       Semaphore ready = new Semaphore(0, 1);
+                       input_thread = new Thread (InputThreadLoop);
+                       input_thread.IsBackground = true;
+                       input_thread.Start(ready);
+               }
+
+               void InputThreadLoop(object semaphore)
+               {
+                       Debug.Print("[Input] Running on thread {0}", Thread.CurrentThread.ManagedThreadId);
+                       Setup();
+
+                       // Inform the parent thread that initialization has completed successfully
+                       (semaphore as Semaphore).Release();
+                       Debug.Print("[Input] Released main thread.", input_context);
+
+                       // Use a blocking poll for input messages, in order to reduce CPU usage
+                       PollFD poll_fd = new PollFD();
+                       poll_fd.fd = input_fd;
+                       poll_fd.events = PollFlags.In;
+                       Debug.Print("[Input] Created PollFD({0}, {1})", poll_fd.fd, poll_fd.events);
+
+                       Debug.Print("[Input] Entering input loop.", poll_fd.fd, poll_fd.events);
+                       while (Interlocked.Read(ref exit) == 0)
+                       {
+                               int ret = Libc.poll(ref poll_fd, 1, -1);
+                               ErrorNumber error = (ErrorNumber)Marshal.GetLastWin32Error();
+                               bool is_error =
+                                       ret < 0 && !(error == ErrorNumber.Again || error == ErrorNumber.Interrupted) ||
+                                       (poll_fd.revents & (PollFlags.Hup | PollFlags.Error | PollFlags.Invalid)) != 0;
+
+                               if (ret > 0 && (poll_fd.revents & (PollFlags.In | PollFlags.Pri)) != 0)
+                                       ProcessEvents(input_context);
+
+                               if (is_error)
+                               {
+                                       Debug.Print("[Input] Exiting input loop {0} due to poll error [ret:{1} events:{2}]. Error: {3}.",
+                                               input_thread.ManagedThreadId, ret, poll_fd.revents, error);
+                                       Interlocked.Increment(ref exit);
+                               }
+                       }
+                       Debug.Print("[Input] Exited input loop.", poll_fd.fd, poll_fd.events);
+               }
+
+               void Setup()
+               {
+                       // Todo: add static path fallback when udev is not installed.
+                       udev = Udev.New();
+                       if (udev == IntPtr.Zero)
+                       {
+                               Debug.Print("[Input] Udev.New() failed.");
+                               Interlocked.Increment(ref exit);
+                               return;
+                       }
+                       Debug.Print("[Input] Udev.New() = {0:x}", udev);
+
+                       input_context = LibInput.CreateContext(input_interface, IntPtr.Zero, udev);
+                       if (input_context == IntPtr.Zero)
+                       {
+                               Debug.Print("[Input] LibInput.CreateContext({0:x}) failed.", udev);
+                               Interlocked.Increment(ref exit);
+                               return;
+                       }
+                       Debug.Print("[Input] LibInput.CreateContext({0:x}) = {1:x}", udev, input_context);
+
+                       string seat_id = "seat0";
+                       int seat_assignment = LibInput.AssignSeat(input_context, seat_id);
+                       if (seat_assignment == -1)
+                       {
+                               Debug.Print("[Input] LibInput.AssignSeat({0:x}) = {1} failed.", input_context, seat_id);
+                               Interlocked.Increment(ref exit);
+                               return;
+                       }
+                       Debug.Print("[Input] LibInput.AssignSeat({0:x}) = {1}", input_context, seat_id);
+
+                       input_fd = LibInput.GetFD(input_context);
+                       if (input_fd < 0)
+                       {
+                               Debug.Print("[Input] LibInput.GetFD({0:x}) failed.", input_context);
+                               Interlocked.Increment(ref exit);
+                               return;
+                       }
+                       Debug.Print("[Input] LibInput.GetFD({0:x}) = {1}.", input_context, input_fd);
+
+                       ProcessEvents(input_context);
+                       LibInput.Resume(input_context);
+                       Debug.Print("[Input] LibInput.Resume({0:x})", input_context);
+
+                       if (Interlocked.Read(ref DeviceFDCount) <= 0)
+                       {
+                               Debug.Print("[Error] Failed to open any input devices.");
+                               Debug.Print("[Error] Ensure that you have access to '/dev/input/event*'.");
+                               Interlocked.Increment(ref exit);
+                       }
+               }
+
+               void ProcessEvents(IntPtr input_context)
+               {
+                       // Process all events in the event queue
+                       while (true)
+                       {                               
+                               // Data available
+                               int ret = LibInput.Dispatch(input_context);
+                               if (ret != 0)
+                               {
+                                       Debug.Print("[Input] LibInput.Dispatch({0:x}) failed. Error: {1}",
+                                               input_context, ret);
+                                       break;
+                               }
+
+                               IntPtr pevent = LibInput.GetEvent(input_context);
+                               if (pevent == IntPtr.Zero)
+                               {
+                                       break;
+                               }
+
+                               IntPtr device = LibInput.GetDevice(pevent);
+                               InputEventType type = LibInput.GetEventType(pevent);
+
+                               lock (Sync)
+                               {
+                                       switch (type)
+                                       {
+//                                     case InputEventType.DeviceAdded:
+//                                             HandleDeviceAdded(input_context, device);
+//                                             break;
+//
+//                                     case InputEventType.DeviceRemoved:
+//                                             HandleDeviceRemoved(input_context, device);
+//                                             break;
+//
+                                       case InputEventType.KeyboardKey:
+                                               run = false;
+                                               //HandleKeyboard(GetKeyboard(device), LibInput.GetKeyboardEvent(pevent));
+                                               break;
+//
+//                                     case InputEventType.PointerAxis:
+//                                             HandlePointerAxis(GetMouse(device), LibInput.GetPointerEvent(pevent));
+//                                             break;
+//
+//                                     case InputEventType.PointerButton:
+//                                             HandlePointerButton(GetMouse(device), LibInput.GetPointerEvent(pevent));
+//                                             break;
+
+                                       case InputEventType.PointerMotion:
+                                               HandlePointerMotion(LibInput.GetPointerEvent(pevent));
+                                               break;
+
+//                                     case InputEventType.PointerMotionAbsolute:
+//                                             HandlePointerMotionAbsolute(GetMouse(device), LibInput.GetPointerEvent(pevent));
+//                                             break;
+                                       }
+                               }
+
+                               LibInput.DestroyEvent(pevent);
+                       }
+               }
+               int MouseX = 0, MouseY = 0;
+               volatile bool updateMousePos = true;
+
+               void HandlePointerMotion(PointerEvent e)
+               {                       
+                       MouseX += (int)e.DeltaX;
+                       MouseY += (int)e.DeltaY;
+                       updateMousePos = true;
+               }
+
+               #endregion
+       }
+}
+
diff --git a/testDrm/src/Egl.cs b/testDrm/src/Egl.cs
new file mode 100644 (file)
index 0000000..434a54e
--- /dev/null
@@ -0,0 +1,385 @@
+#region License
+//
+// The Open Toolkit Library License
+//
+// Copyright (c) 2006 - 2011 the Open Toolkit library.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights to 
+// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+// the Software, and to permit persons to whom the Software is furnished to do
+// so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+#endregion
+
+using System;
+using System.Runtime.InteropServices;
+using System.Collections.Generic;
+using System.Text;
+
+
+namespace OpenTK.Platform.Egl
+{
+    using EGLNativeDisplayType = IntPtr;
+    using EGLNativeWindowType = IntPtr;
+    using EGLNativePixmapType = IntPtr;
+    using EGLConfig = IntPtr;
+    using EGLContext = IntPtr;
+    using EGLDisplay = IntPtr;
+    using EGLSurface = IntPtr;
+    using EGLClientBuffer = IntPtr;
+
+    enum RenderApi
+    {
+        ES = Egl.OPENGL_ES_API,
+        GL = Egl.OPENGL_API,
+        VG = Egl.OPENVG_API
+    }
+
+    [Flags]
+    enum RenderableFlags
+    {
+        ES = Egl.OPENGL_ES_BIT,
+        ES2 = Egl.OPENGL_ES2_BIT,
+        ES3 = Egl.OPENGL_ES3_BIT,
+        GL = Egl.OPENGL_BIT,
+        VG = Egl.OPENVG_BIT,
+    }
+
+    public enum ErrorCode
+    {
+        SUCCESS = 12288,
+        NOT_INITIALIZED = 12289,
+        BAD_ACCESS = 12290,
+        BAD_ALLOC = 12291,
+        BAD_ATTRIBUTE = 12292,
+        BAD_CONFIG = 12293,
+        BAD_CONTEXT = 12294,
+        BAD_CURRENT_SURFACE = 12295,
+        BAD_DISPLAY = 12296,
+        BAD_MATCH = 12297,
+        BAD_NATIVE_PIXMAP = 12298,
+        BAD_NATIVE_WINDOW = 12299,
+        BAD_PARAMETER = 12300,
+        BAD_SURFACE = 12301,
+        CONTEXT_LOST = 12302,
+    }
+
+    static partial class Egl
+    {
+        public const int VERSION_1_0 = 1;
+        public const int VERSION_1_1 = 1;
+        public const int VERSION_1_2 = 1;
+        public const int VERSION_1_3 = 1;
+        public const int VERSION_1_4 = 1;
+        public const int FALSE = 0;
+        public const int TRUE = 1;
+        public const int DONT_CARE = -1;
+        public const int CONTEXT_LOST = 12302;
+        public const int BUFFER_SIZE = 12320;
+        public const int ALPHA_SIZE = 12321;
+        public const int BLUE_SIZE = 12322;
+        public const int GREEN_SIZE = 12323;
+        public const int RED_SIZE = 12324;
+        public const int DEPTH_SIZE = 12325;
+        public const int STENCIL_SIZE = 12326;
+        public const int CONFIG_CAVEAT = 12327;
+        public const int CONFIG_ID = 12328;
+        public const int LEVEL = 12329;
+        public const int MAX_PBUFFER_HEIGHT = 12330;
+        public const int MAX_PBUFFER_PIXELS = 12331;
+        public const int MAX_PBUFFER_WIDTH = 12332;
+        public const int NATIVE_RENDERABLE = 12333;
+        public const int NATIVE_VISUAL_ID = 12334;
+        public const int NATIVE_VISUAL_TYPE = 12335;
+        public const int PRESERVED_RESOURCES = 12336;
+        public const int SAMPLES = 12337;
+        public const int SAMPLE_BUFFERS = 12338;
+        public const int SURFACE_TYPE = 12339;
+        public const int TRANSPARENT_TYPE = 12340;
+        public const int TRANSPARENT_BLUE_VALUE = 12341;
+        public const int TRANSPARENT_GREEN_VALUE = 12342;
+        public const int TRANSPARENT_RED_VALUE = 12343;
+        public const int NONE = 12344;
+        public const int BIND_TO_TEXTURE_RGB = 12345;
+        public const int BIND_TO_TEXTURE_RGBA = 12346;
+        public const int MIN_SWAP_INTERVAL = 12347;
+        public const int MAX_SWAP_INTERVAL = 12348;
+        public const int LUMINANCE_SIZE = 12349;
+        public const int ALPHA_MASK_SIZE = 12350;
+        public const int COLOR_BUFFER_TYPE = 12351;
+        public const int RENDERABLE_TYPE = 12352;
+        public const int MATCH_NATIVE_PIXMAP = 12353;
+        public const int CONFORMANT = 12354;
+        public const int SLOW_CONFIG = 12368;
+        public const int NON_CONFORMANT_CONFIG = 12369;
+        public const int TRANSPARENT_RGB = 12370;
+        public const int RGB_BUFFER = 12430;
+        public const int LUMINANCE_BUFFER = 12431;
+        public const int NO_TEXTURE = 12380;
+        public const int TEXTURE_RGB = 12381;
+        public const int TEXTURE_RGBA = 12382;
+        public const int TEXTURE_2D = 12383;
+        public const int PBUFFER_BIT = 1;
+        public const int PIXMAP_BIT = 2;
+        public const int WINDOW_BIT = 4;
+        public const int VG_COLORSPACE_LINEAR_BIT = 32;
+        public const int VG_ALPHA_FORMAT_PRE_BIT = 64;
+        public const int MULTISAMPLE_RESOLVE_BOX_BIT = 512;
+        public const int SWAP_BEHAVIOR_PRESERVED_BIT = 1024;
+        public const int OPENGL_ES_BIT = 1;
+        public const int OPENVG_BIT = 2;
+        public const int OPENGL_ES2_BIT = 4;
+        public const int OPENGL_BIT = 8;
+        public const int OPENGL_ES3_BIT = 64;
+        public const int VENDOR = 12371;
+        public const int VERSION = 12372;
+        public const int EXTENSIONS = 12373;
+        public const int CLIENT_APIS = 12429;
+        public const int HEIGHT = 12374;
+        public const int WIDTH = 12375;
+        public const int LARGEST_PBUFFER = 12376;
+        public const int TEXTURE_FORMAT = 12416;
+        public const int TEXTURE_TARGET = 12417;
+        public const int MIPMAP_TEXTURE = 12418;
+        public const int MIPMAP_LEVEL = 12419;
+        public const int RENDER_BUFFER = 12422;
+        public const int VG_COLORSPACE = 12423;
+        public const int VG_ALPHA_FORMAT = 12424;
+        public const int HORIZONTAL_RESOLUTION = 12432;
+        public const int VERTICAL_RESOLUTION = 12433;
+        public const int PIXEL_ASPECT_RATIO = 12434;
+        public const int SWAP_BEHAVIOR = 12435;
+        public const int MULTISAMPLE_RESOLVE = 12441;
+        public const int BACK_BUFFER = 12420;
+        public const int SINGLE_BUFFER = 12421;
+        public const int VG_COLORSPACE_sRGB = 12425;
+        public const int VG_COLORSPACE_LINEAR = 12426;
+        public const int VG_ALPHA_FORMAT_NONPRE = 12427;
+        public const int VG_ALPHA_FORMAT_PRE = 12428;
+        public const int DISPLAY_SCALING = 10000;
+        public const int UNKNOWN = -1;
+        public const int BUFFER_PRESERVED = 12436;
+        public const int BUFFER_DESTROYED = 12437;
+        public const int OPENVG_IMAGE = 12438;
+        public const int CONTEXT_CLIENT_TYPE = 12439;
+        public const int CONTEXT_CLIENT_VERSION = 12440;
+        public const int MULTISAMPLE_RESOLVE_DEFAULT = 12442;
+        public const int MULTISAMPLE_RESOLVE_BOX = 12443;
+        public const int OPENGL_ES_API = 12448;
+        public const int OPENVG_API = 12449;
+        public const int OPENGL_API = 12450;
+        public const int DRAW = 12377;
+        public const int READ = 12378;
+        public const int CORE_NATIVE_ENGINE = 12379;
+        public const int COLORSPACE = VG_COLORSPACE;
+        public const int ALPHA_FORMAT = VG_ALPHA_FORMAT;
+        public const int COLORSPACE_sRGB = VG_COLORSPACE_sRGB;
+        public const int COLORSPACE_LINEAR = VG_COLORSPACE_LINEAR;
+        public const int ALPHA_FORMAT_NONPRE = VG_ALPHA_FORMAT_NONPRE;
+        public const int ALPHA_FORMAT_PRE = VG_ALPHA_FORMAT_PRE;
+
+        // EGL_ANGLE_d3d_share_handle_client_buffer
+        public const int D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE = 0x3200;
+        // EGL_ANGLE_window_fixed_size
+        public const int FIXED_SIZE_ANGLE = 0x3201;
+        // EGL_ANGLE_query_surface_pointer 
+        [DllImport("libEGL.dll", EntryPoint = "eglQuerySurfacePointerANGLE")]
+        public static extern bool QuerySurfacePointerANGLE(EGLDisplay display, EGLSurface surface, int attribute, out IntPtr value);
+        // EGL_ANGLE_software_display
+        public static readonly EGLNativeDisplayType SOFTWARE_DISPLAY_ANGLE = new EGLNativeDisplayType(-1);
+        // EGL_ANGLE_direct3d_display
+        public static readonly EGLNativeDisplayType D3D11_ELSE_D3D9_DISPLAY_ANGLE = new EGLNativeDisplayType(-2);
+        public static readonly EGLNativeDisplayType D3D11_ONLY_DISPLAY_ANGLE = new EGLNativeDisplayType(-3);
+        // EGL_ANGLE_device_d3d
+        public const int D3D9_DEVICE_ANGLE = 0x33A0;
+        public const int D3D11_DEVICE_ANGLE = 0x33A1;
+        // EGL_ANGLE_platform_angle
+        public const int PLATFORM_ANGLE_ANGLE = 0x3202;
+        public const int PLATFORM_ANGLE_TYPE_ANGLE = 0x3203;
+        public const int PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE = 0x3204;
+        public const int PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE = 0x3205;
+        public const int PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE = 0x3206;
+        // EGL_ANGLE_platform_angle_d3d
+        public const int PLATFORM_ANGLE_TYPE_D3D9_ANGLE = 0x3207;
+        public const int PLATFORM_ANGLE_TYPE_D3D11_ANGLE = 0x3208;
+        public const int PLATFORM_ANGLE_DEVICE_TYPE_ANGLE = 0x3209;
+        public const int PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE = 0x320A;
+        public const int PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE = 0x320B;
+        public const int PLATFORM_ANGLE_DEVICE_TYPE_REFERENCE_ANGLE = 0x320C;
+        public const int PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE = 0x320F;
+        // EGL_ANGLE_platform_angle_opengl
+        public const int PLATFORM_ANGLE_TYPE_OPENGL_ANGLE = 0x320D;
+        public const int PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE = 0x320E;
+
+        [DllImportAttribute("libEGL.dll", EntryPoint = "eglGetError")]
+        public static extern ErrorCode GetError();
+
+        [DllImportAttribute("libEGL.dll", EntryPoint = "eglGetDisplay")]
+        public static extern EGLDisplay GetDisplay(EGLNativeDisplayType display_id);
+
+        [DllImportAttribute("libEGL.dll", EntryPoint = "eglInitialize")]
+        //[return: MarshalAsAttribute(UnmanagedType.I1)]
+        public static extern bool Initialize(EGLDisplay dpy, out int major, out int minor);
+
+        [DllImportAttribute("libEGL.dll", EntryPoint = "eglTerminate")]
+        //[return: MarshalAsAttribute(UnmanagedType.I1)]
+        public static extern bool Terminate(EGLDisplay dpy);
+
+        [DllImportAttribute("libEGL.dll", EntryPoint = "eglQueryString")]
+        public static extern IntPtr QueryString(EGLDisplay dpy, int name);
+
+        [DllImportAttribute("libEGL.dll", EntryPoint = "eglGetConfigs")]
+        [return: MarshalAsAttribute(UnmanagedType.I1)]
+        public static extern bool GetConfigs(EGLDisplay dpy, EGLConfig[] configs, int config_size, out int num_config);
+
+        [DllImportAttribute("libEGL.dll", EntryPoint = "eglChooseConfig")]
+        [return: MarshalAsAttribute(UnmanagedType.I1)]
+        public static extern bool ChooseConfig(EGLDisplay dpy, int[] attrib_list, [In, Out] EGLConfig[] configs, int config_size, out int num_config);
+
+        [DllImportAttribute("libEGL.dll", EntryPoint = "eglGetConfigAttrib")]
+        [return: MarshalAsAttribute(UnmanagedType.I1)]
+        public static extern bool GetConfigAttrib(EGLDisplay dpy, EGLConfig config, int attribute, out int value);
+
+        [DllImportAttribute("libEGL.dll", EntryPoint = "eglCreateWindowSurface")]
+        public static extern  EGLSurface CreateWindowSurface(EGLDisplay dpy, EGLConfig config, IntPtr win, IntPtr attrib_list);
+
+        [DllImportAttribute("libEGL.dll", EntryPoint = "eglCreatePbufferSurface")]
+        public static extern EGLSurface CreatePbufferSurface(EGLDisplay dpy, EGLConfig config, int[] attrib_list);
+
+        [DllImportAttribute("libEGL.dll", EntryPoint = "eglCreatePixmapSurface")]
+        public static extern EGLSurface CreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, int[] attrib_list);
+
+        [DllImportAttribute("libEGL.dll", EntryPoint = "eglDestroySurface")]
+        [return: MarshalAsAttribute(UnmanagedType.I1)]
+        public static extern bool DestroySurface(EGLDisplay dpy, EGLSurface surface);
+
+        [DllImportAttribute("libEGL.dll", EntryPoint = "eglQuerySurface")]
+        [return: MarshalAsAttribute(UnmanagedType.I1)]
+        public static extern bool QuerySurface(EGLDisplay dpy, EGLSurface surface, int attribute, out int value);
+
+        [DllImportAttribute("libEGL.dll", EntryPoint = "eglBindAPI")]
+        [return: MarshalAsAttribute(UnmanagedType.I1)]
+        public static extern bool BindAPI(RenderApi api);
+
+        [DllImportAttribute("libEGL.dll", EntryPoint = "eglQueryAPI")]
+        public static extern int QueryAPI();
+
+        [DllImportAttribute("libEGL.dll", EntryPoint = "eglWaitClient")]
+        [return: MarshalAsAttribute(UnmanagedType.I1)]
+        public static extern bool WaitClient();
+
+        [DllImportAttribute("libEGL.dll", EntryPoint = "eglReleaseThread")]
+        [return: MarshalAsAttribute(UnmanagedType.I1)]
+        public static extern bool ReleaseThread();
+
+        [DllImportAttribute("libEGL.dll", EntryPoint = "eglCreatePbufferFromClientBuffer")]
+        public static extern EGLSurface CreatePbufferFromClientBuffer(EGLDisplay dpy, int buftype, EGLClientBuffer buffer, EGLConfig config, int[] attrib_list);
+
+        [DllImportAttribute("libEGL.dll", EntryPoint = "eglSurfaceAttrib")]
+        [return: MarshalAsAttribute(UnmanagedType.I1)]
+        public static extern bool SurfaceAttrib(EGLDisplay dpy, EGLSurface surface, int attribute, int value);
+
+        [DllImportAttribute("libEGL.dll", EntryPoint = "eglBindTexImage")]
+        [return: MarshalAsAttribute(UnmanagedType.I1)]
+        public static extern bool BindTexImage(EGLDisplay dpy, EGLSurface surface, int buffer);
+
+        [DllImportAttribute("libEGL.dll", EntryPoint = "eglReleaseTexImage")]
+        [return: MarshalAsAttribute(UnmanagedType.I1)]
+        public static extern bool ReleaseTexImage(EGLDisplay dpy, EGLSurface surface, int buffer);
+
+        [DllImportAttribute("libEGL.dll", EntryPoint = "eglSwapInterval")]
+        [return: MarshalAsAttribute(UnmanagedType.I1)]
+        public static extern bool SwapInterval(EGLDisplay dpy, int interval);
+
+        [DllImportAttribute("libEGL.dll", EntryPoint = "eglCreateContext")]
+        static extern IntPtr eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, int[] attrib_list);
+
+        public static EGLContext CreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, int[] attrib_list)
+        {
+            IntPtr ptr = eglCreateContext(dpy, config, share_context, attrib_list);
+            if (ptr == IntPtr.Zero)
+                throw new Exception(String.Format("Failed to create EGL context, error: {0}.", Egl.GetError()));
+            return ptr;
+        }
+
+        [DllImportAttribute("libEGL.dll", EntryPoint = "eglDestroyContext")]
+        [return: MarshalAsAttribute(UnmanagedType.I1)]
+        public static extern bool DestroyContext(EGLDisplay dpy, EGLContext ctx);
+
+        [DllImportAttribute("libEGL.dll", EntryPoint = "eglMakeCurrent")]
+        [return: MarshalAsAttribute(UnmanagedType.I1)]
+        public static extern bool MakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx);
+
+        [DllImportAttribute("libEGL.dll", EntryPoint = "eglGetCurrentContext")]
+        public static extern EGLContext GetCurrentContext();
+
+        [DllImportAttribute("libEGL.dll", EntryPoint = "eglGetCurrentSurface")]
+        public static extern EGLSurface GetCurrentSurface(int readdraw);
+
+        [DllImportAttribute("libEGL.dll", EntryPoint = "eglGetCurrentDisplay")]
+        public static extern EGLDisplay GetCurrentDisplay();
+
+        [DllImportAttribute("libEGL.dll", EntryPoint = "eglQueryContext")]
+        [return: MarshalAsAttribute(UnmanagedType.I1)]
+        public static extern bool QueryContext(EGLDisplay dpy, EGLContext ctx, int attribute, out int value);
+
+        [DllImportAttribute("libEGL.dll", EntryPoint = "eglWaitGL")]
+        [return: MarshalAsAttribute(UnmanagedType.I1)]
+        public static extern bool WaitGL();
+
+        [DllImportAttribute("libEGL.dll", EntryPoint = "eglWaitNative")]
+        [return: MarshalAsAttribute(UnmanagedType.I1)]
+        public static extern bool WaitNative(int engine);
+
+        [DllImportAttribute("libEGL.dll", EntryPoint = "eglSwapBuffers")]
+        [return: MarshalAsAttribute(UnmanagedType.I1)]
+        public static extern bool SwapBuffers(EGLDisplay dpy, EGLSurface surface);
+
+        [DllImportAttribute("libEGL.dll", EntryPoint = "eglCopyBuffers")]
+        [return: MarshalAsAttribute(UnmanagedType.I1)]
+        public static extern bool CopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target);
+
+        [DllImportAttribute("libEGL.dll", EntryPoint = "eglGetProcAddress")]
+        public static extern IntPtr GetProcAddress(string funcname);
+
+        [DllImportAttribute("libEGL.dll", EntryPoint = "eglGetProcAddress")]
+        public static extern IntPtr GetProcAddress(IntPtr funcname);
+
+        // EGL_EXT_platform_base
+        [DllImport("libEGL.dll", EntryPoint = "eglGetPlatformDisplayEXT")]
+        public static extern EGLDisplay GetPlatformDisplayEXT(int platform, EGLNativeDisplayType native_display, int[] attrib_list);
+        
+        [DllImport("libEGL.dll", EntryPoint = "eglCreatePlatformWindowSurfaceEXT")]
+        public static extern EGLSurface CreatePlatformWindowSurfaceEXT(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType native_window, int[] attrib_list);
+        
+        [DllImport("libEGL.dll", EntryPoint = "eglCreatePlatformPixmapSurfaceEXT")]
+        public static extern EGLSurface CreatePlatformPixmapSurfaceEXT(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType native_pixmap, int[] attrib_list);
+        
+        // Returns true if Egl drivers exist on the system.
+        public static bool IsSupported
+        {
+            get
+            {
+                try { GetCurrentContext(); }
+                catch (Exception) { return false;  }
+                return true;
+            }
+        }
+
+    }
+#pragma warning restore 0169
+}
\ No newline at end of file
diff --git a/testDrm/src/Linux/Bindings/Drm.cs b/testDrm/src/Linux/Bindings/Drm.cs
new file mode 100644 (file)
index 0000000..449dc0b
--- /dev/null
@@ -0,0 +1,243 @@
+#region License
+//
+// Drm.cs
+//
+// Author:
+//       Stefanos A. <stapostol@gmail.com>
+//
+// 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.Runtime.InteropServices;
+
+#pragma warning disable 0649 // field is never assigned
+
+namespace OpenTK.Platform.Linux
+{
+    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+    delegate void VBlankCallback(int fd,
+        int sequence,
+        int tv_sec,
+        int tv_usec,
+        IntPtr user_data);
+
+    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+    delegate void PageFlipCallback(int fd,
+        int sequence,
+        int tv_sec,
+        int tv_usec,
+        IntPtr user_data);
+
+    class Drm
+    {
+        const string lib = "libdrm";
+
+        [DllImport(lib, EntryPoint = "drmHandleEvent", CallingConvention = CallingConvention.Cdecl)]
+        public static extern int HandleEvent(int fd, ref EventContext evctx);
+
+        [DllImport(lib, EntryPoint = "drmModeAddFB", CallingConvention = CallingConvention.Cdecl)]
+        public static extern int ModeAddFB(int fd, int width, int height, byte depth,
+            byte bpp, int pitch, int bo_handle,
+            out int buf_id);
+
+        [DllImport(lib, EntryPoint = "drmModeRmFB", CallingConvention = CallingConvention.Cdecl)]
+        public static extern int ModeRmFB(int fd, int bufferId);
+
+        [DllImport(lib, EntryPoint = "drmModeFreeCrtc", CallingConvention = CallingConvention.Cdecl)]
+        public static extern void ModeFreeCrtc(IntPtr ptr);
+
+        [DllImport(lib, EntryPoint = "drmModeGetCrtc", CallingConvention = CallingConvention.Cdecl)]
+        public static extern IntPtr ModeGetCrtc(int fd, int 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, int connector_id);
+
+        [DllImport(lib, EntryPoint = "drmModeGetEncoder", CallingConvention = CallingConvention.Cdecl)]
+        public static extern IntPtr ModeGetEncoder(int fd, int encoder_id);
+
+        [DllImport(lib, EntryPoint = "drmModeGetResources", CallingConvention = CallingConvention.Cdecl)]
+        public static extern IntPtr ModeGetResources(int fd);
+
+        [DllImport(lib, EntryPoint = "drmModePageFlip", CallingConvention = CallingConvention.Cdecl)]
+        public static extern int ModePageFlip(int fd, int crtc_id, int fb_id,
+            PageFlipFlags flags, IntPtr user_data);
+
+        [DllImport(lib, EntryPoint = "drmModeSetCrtc", CallingConvention = CallingConvention.Cdecl)]
+        unsafe public static extern int ModeSetCrtc(int fd, int crtcId, int bufferId,
+            int x, int y, int* connectors, int count, ModeInfo* mode);
+
+        [DllImport(lib, EntryPoint = "drmModeSetCursor2", CallingConvention = CallingConvention.Cdecl)]
+        public static extern int SetCursor(int fd, int crtcId, int bo_handle, int width, int height, int hot_x, int hot_y);
+
+        [DllImport(lib, EntryPoint = "drmModeMoveCursor", CallingConvention = CallingConvention.Cdecl)]
+        public static extern int MoveCursor(int fd, int crtcId, int x, int y);
+
+    }
+
+    enum ModeConnection
+    {
+        Connected = 1,
+        Disconnected = 2,
+        Unknown = 3
+    }
+       enum ModeConnectorType
+       {
+               Unknown = 0,
+               VGA=1,
+               DVII=2,
+               DVID=3,
+               DVIA=4,
+               Composite=5,
+               SVIDEO=6,
+               LVDS=7,
+               Component=8,
+               PinDIN9 = 9,
+               DisplayPort=10,
+               HDMIA=11,
+               HDMIB=12,
+               TV=13,
+               eDP=14,
+               VIRTUAL=15,
+               DSI=16,
+               DPI=17
+       }
+       enum ModeEncoderType
+       {
+               NONE=0,
+               DAC=1,
+               TMDS=2,
+               LVDS=3,
+               TVDAC=4,
+               VIRTUAL=5,
+               DSI=6,
+               DPMST=7,
+               DPI=8,
+       }
+    enum ModeSubPixel
+    {
+        Unknown = 1,
+        HorizontalRgb = 2,
+        HorizontalBgr = 3,
+        VerticalRgb = 4,
+        VerticalBgr = 5,
+        None = 6
+    }
+
+    [Flags]
+    enum PageFlipFlags
+    {
+        FlipEvent = 0x01,
+        FlipAsync = 0x02,
+        FlipFlags = FlipEvent | FlipAsync
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    struct EventContext
+    {
+        public int version;
+        public IntPtr vblank_handler;
+        public IntPtr page_flip_handler;
+
+        public static readonly int Version = 2;
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    unsafe struct ModeConnector
+    {
+        public int connector_id;
+        public int encoder_id;
+               public ModeConnectorType connector_type;
+        public int connector_type_id;
+        public ModeConnection connection;
+        public int mmWidth, mmHeight;
+        public ModeSubPixel subpixel;
+
+        public int count_modes;
+        public ModeInfo* modes;
+
+        public int count_props;
+        public int *props;
+        public long *prop_values;
+
+        public int count_encoders;
+        public int *encoders;
+    }
+
+    struct ModeCrtc
+    {
+        public int crtc_id;
+        public int buffer_id;
+
+        public int x, y;
+        public int width, height;
+        public int mode_valid;
+        public ModeInfo mode;
+
+        public int gamma_size;
+    }
+
+    struct ModeEncoder
+    {
+        public int encoder_id;
+        public ModeEncoderType encoder_type;
+        public int crtc_id;
+        public int possible_crtcs;
+        public int 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 int 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 int* fbs;
+        public int count_crtcs;
+        public int* crtcs;
+        public int count_connectors;
+        public int* connectors;
+        public int count_encoders;
+        public int* encoders;
+        public int min_width, max_width;
+        public int min_height, max_height;
+    }
+}
+
diff --git a/testDrm/src/Linux/Bindings/Evdev.cs b/testDrm/src/Linux/Bindings/Evdev.cs
new file mode 100644 (file)
index 0000000..fa4f725
--- /dev/null
@@ -0,0 +1,635 @@
+#region License
+//
+// Evdev.cs
+//
+// Author:
+//       Stefanos A. <stapostol@gmail.com>
+//
+// Copyright (c) 2006-2014 
+//
+// 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.Diagnostics;
+using System.Runtime.InteropServices;
+using Crow;
+
+namespace OpenTK.Platform.Linux
+{
+    // Bindings for linux/input.h
+    class Evdev
+    {
+        public const int KeyCount = 0x300;
+        public const int AxisCount = 0x40;
+        public const int EventCount = (int)EvdevType.CNT;
+
+        #region KeyMap
+
+        public static readonly Key[] KeyMap = new Key[]
+        {
+            // 0-7
+            Key.Unknown,
+            Key.Escape,
+            Key.Number1,
+            Key.Number2,
+            Key.Number3,
+            Key.Number4,
+            Key.Number5,
+            Key.Number6,
+            // 8-15
+            Key.Number7,
+            Key.Number8,
+            Key.Number9,
+            Key.Number0,
+            Key.Minus,
+            Key.Plus,
+            Key.BackSpace,
+            Key.Tab,
+            // 16-23
+            Key.Q,
+            Key.W,
+            Key.E,
+            Key.R,
+            Key.T,
+            Key.Y,
+            Key.U,
+            Key.I,
+            // 24-31
+            Key.O,
+            Key.P,
+            Key.BracketLeft,
+            Key.BracketRight,
+            Key.Enter,
+            Key.ControlLeft,
+            Key.A,
+            Key.S,
+            // 32-39
+            Key.D,
+            Key.F,
+            Key.G,
+            Key.H,
+            Key.J,
+            Key.K,
+            Key.L,
+            Key.Semicolon,
+            // 40-47
+            Key.Quote,
+            Key.Tilde,
+            Key.ShiftLeft,
+            Key.BackSlash, //Key.Execute,
+            Key.Z,
+            Key.X,
+            Key.C,
+            Key.V, //Key.Help,
+            // 48-55
+            Key.B,
+            Key.N,
+            Key.M,
+            Key.Comma,
+            Key.Period,
+            Key.Slash,
+            Key.ShiftRight,
+            Key.KeypadMultiply,
+            // 56-63
+            Key.AltLeft,
+            Key.Space,
+            Key.CapsLock,
+            Key.F1,
+            Key.F2,
+            Key.F3,
+            Key.F4,
+            Key.F5,
+            // 64-71
+            Key.F6,
+            Key.F7,
+            Key.F8,
+            Key.F9,
+            Key.F10,
+            Key.NumLock,
+            Key.ScrollLock,
+            Key.Keypad7,
+            // 72-79
+            Key.Keypad8,
+            Key.Keypad9,
+            Key.KeypadSubtract,
+            Key.Keypad4,
+            Key.Keypad5,
+            Key.Keypad6,
+            Key.KeypadPlus,
+            Key.Keypad1,
+            // 80-87
+            Key.Keypad2,
+            Key.Keypad3,
+            Key.Keypad0,
+            Key.KeypadPeriod,
+            Key.Unknown,
+            Key.Unknown, // zenkakuhankaku
+            Key.Unknown, // 102ND
+            Key.F11,
+            // 88-95
+            Key.F12,
+            Key.Unknown, // ro
+            Key.Unknown, // katakana
+            Key.Unknown, // hiragana
+            Key.Unknown, // henkan
+            Key.Unknown, // katakanahiragana
+            Key.Unknown, // muhenkan
+            Key.Unknown, // kpjpcomma
+            // 96-103
+            Key.KeypadEnter,
+            Key.ControlRight,
+            Key.KeypadDivide,
+            Key.Unknown, // sysrq
+            Key.AltRight,
+            Key.Unknown, // linefeed
+            Key.Home,
+            Key.Up,
+            // 104-111
+            Key.PageUp,
+            Key.Left,
+            Key.Right,
+            Key.End,
+            Key.Down,
+            Key.PageDown,
+            Key.Insert,
+            Key.Delete,
+            // 112-119
+            Key.Unknown, // macro
+            Key.Unknown, // mute
+            Key.Unknown, // volumedown
+            Key.Unknown, // volumeup
+            Key.Unknown, // power
+            Key.Unknown, // kpequal
+            Key.Unknown, // kpplusminus
+            Key.Pause,
+            // 120-127
+            Key.Unknown, // scale
+            Key.Unknown, // kpcomma
+            Key.Unknown, // hangeul / hanguel
+            Key.Unknown, // hanja
+            Key.Unknown, // yen
+            Key.WinLeft,
+            Key.WinRight,
+            Key.Unknown, // compose
+            // 128-135
+            Key.Unknown, // stop
+            Key.Unknown, // again
+            Key.Unknown, // props
+            Key.Unknown, // undo
+            Key.Unknown, // front
+            Key.Unknown, // copy
+            Key.Unknown, // open
+            Key.Unknown, // paste
+            // 136-143
+            Key.Unknown, // find
+            Key.Unknown, // cut
+            Key.Unknown, // help
+            Key.Unknown, // menu
+            Key.Unknown, // calc
+            Key.Unknown, // setup
+            Key.Unknown, // sleep
+            Key.Unknown, // wakeup
+            // 144-151
+            Key.Unknown, // file
+            Key.Unknown, // send file
+            Key.Unknown, // delete file
+            Key.Unknown, // xfer
+            Key.Unknown, // prog1
+            Key.Unknown, // prog2
+            Key.Unknown, // www
+            Key.Unknown, // msdos
+            // 152-159
+            Key.Unknown, // coffee / screenlock
+            Key.Unknown, // direction
+            Key.Unknown, // cycle windows
+            Key.Unknown, // mail
+            Key.Unknown, // bookmarks
+            Key.Unknown, // computer
+            Key.Back,
+            Key.Unknown, // forward
+            // 160-167
+            Key.Unknown, // close cd
+            Key.Unknown, // eject cd
+            Key.Unknown, // eject/close cd
+            Key.Unknown, // next song
+            Key.Unknown, // play/pause
+            Key.Unknown, // previous song
+            Key.Unknown, // stop cd
+            Key.Unknown, // record
+            // 168-175
+            Key.Unknown, // rewind
+            Key.Unknown, // phone
+            Key.Unknown, // iso
+            Key.Unknown, // config
+            Key.Unknown, // homepage
+            Key.Unknown, // refresh
+            Key.Unknown, // exit
+            Key.Unknown, // move,
+            // 176-183
+            Key.Unknown, // edit,
+            Key.Unknown, // scroll up,
+            Key.Unknown, // scroll down,
+            Key.Unknown, // kp left paren,
+            Key.Unknown, // kp right paren,
+            Key.Unknown, // new,
+            Key.Unknown, // redo,
+            Key.F13,
+            // 184-191
+            Key.F14,
+            Key.F15,
+            Key.F16,
+            Key.F17,
+            Key.F18,
+            Key.F19,
+            Key.F20,
+            Key.F21,
+            // 192-199
+            Key.F22,
+            Key.F23,
+            Key.F24,
+            Key.Unknown,
+            Key.Unknown,
+            Key.Unknown,
+            Key.Unknown,
+            Key.Unknown,
+            // 200-207
+            Key.Unknown, // play cd
+            Key.Unknown, // pause cd
+            Key.Unknown, // prog3
+            Key.Unknown, // prog4
+            Key.Unknown, // dashboard
+            Key.Unknown, // suspend
+            Key.Unknown, // close
+            Key.Unknown, // play
+            // 208-215
+            Key.Unknown, // fast forward
+            Key.Unknown, // bass boost
+            Key.Unknown, // print
+            Key.Unknown, // hp
+            Key.Unknown, // camera
+            Key.Unknown, // sound
+            Key.Unknown, // question
+            Key.Unknown, // email
+            // 216-223
+            Key.Unknown, // chat
+            Key.Unknown, // search
+            Key.Unknown, // connect
+            Key.Unknown, // finance
+            Key.Unknown, // sport
+            Key.Unknown, // shop
+            Key.Unknown, // alt erase
+            Key.Unknown, // cancel
+            // 224-231
+            Key.Unknown, // brightness down
+            Key.Unknown, // brightness up
+            Key.Unknown, // media
+            Key.Unknown, // switch video mode
+            Key.Unknown, // dillum toggle
+            Key.Unknown, // dillum down
+            Key.Unknown, // dillum up
+            Key.Unknown, // send
+            // 232-239
+            Key.Unknown, // reply
+            Key.Unknown, // forward email
+            Key.Unknown, // save
+            Key.Unknown, // documents
+            Key.Unknown, // battery
+            Key.Unknown, // bluetooth
+            Key.Unknown, // wlan
+            Key.Unknown, // uwb
+            // 240-247
+            Key.Unknown,
+            Key.Unknown, // video next
+            Key.Unknown, // video prev
+            Key.Unknown, // brightness cycle
+            Key.Unknown, // brightness zero
+            Key.Unknown, // display off
+            Key.Unknown, // wwan / wimax
+            Key.Unknown, // rfkill
+            // 248-255
+            Key.Unknown, // mic mute
+            Key.Unknown,
+            Key.Unknown,
+            Key.Unknown,
+            Key.Unknown,
+            Key.Unknown,
+            Key.Unknown,
+            Key.Unknown, // reserved
+        };
+
+        #endregion
+
+        public static MouseButton GetMouseButton(EvdevButton button)
+        {
+            switch (button)
+            {
+                case EvdevButton.LEFT:
+                    return MouseButton.Left;
+                case EvdevButton.RIGHT:
+                    return MouseButton.Right;
+                case EvdevButton.MIDDLE:
+                    return MouseButton.Middle;
+                case EvdevButton.BTN0:
+                    return MouseButton.Button1;
+                case EvdevButton.BTN1:
+                    return MouseButton.Button2;
+                case EvdevButton.BTN2:
+                    return MouseButton.Button3;
+                case EvdevButton.BTN3:
+                    return MouseButton.Button4;
+                case EvdevButton.BTN4:
+                    return MouseButton.Button5;
+                case EvdevButton.BTN5:
+                    return MouseButton.Button6;
+                case EvdevButton.BTN6:
+                    return MouseButton.Button7;
+                case EvdevButton.BTN7:
+                    return MouseButton.Button8;
+                case EvdevButton.BTN8:
+                    return MouseButton.Button9;
+                default:
+                    Debug.Print("[Input] Unknown EvdevButton {0}", button);
+                    return MouseButton.Left;
+            }
+        }
+
+        static uint IOCreate(DirectionFlags dir, int number, int length)
+        {
+            long v =
+                ((byte)dir << 30) |
+                ((byte)'E' << 8) |
+                (number << 0) |
+                (length << 16);
+            return (uint)v;
+        }
+
+        // Get absolute value / limits
+        public static int GetAbs(int fd, EvdevAxis axis, out InputAbsInfo info)
+        {
+            info = default(InputAbsInfo);
+            unsafe
+            {
+                fixed (InputAbsInfo* pinfo = &info)
+                {
+                    // EVIOCGABS(abs) = _IOR('E', 0x40 + (abs), struct input_absinfo)
+                    uint ioctl = IOCreate(DirectionFlags.Read, (int)axis + 0x40, BlittableValueType<InputAbsInfo>.Stride);
+                    int retval = Libc.ioctl(fd, ioctl, new IntPtr(pinfo));
+                    return retval;
+                }
+            }
+        }
+
+        // Get supported event bits
+        public static int GetBit(int fd, EvdevType ev, int length, IntPtr data)
+        {
+            // EVIOCGBIT = _IOC(_IOC_READ, 'E', 0x20 + (ev), len)
+            uint ioctl = IOCreate(DirectionFlags.Read, (int)ev + 0x20, length);
+            int retval = Libc.ioctl(fd, ioctl, data);
+            return retval;
+        }
+
+        public static int GetName(int fd, out string name)
+        {
+            unsafe
+            {
+                sbyte* pname = stackalloc sbyte[129];
+                int ret = Libc.ioctl(fd, EvdevIoctl.Name128, new IntPtr(pname));
+                name = new string(pname);
+                return ret;
+            }
+        }
+
+        public static int GetId(int fd, out EvdevInputId id)
+        {
+            id = default(EvdevInputId);
+            unsafe
+            {
+                fixed (EvdevInputId* pid = &id)
+                {
+                    return Libc.ioctl(fd, EvdevIoctl.Id, new IntPtr(pid));
+                }
+            }
+        }
+    }
+
+    enum EvdevAxis
+    {
+        X           = 0x00,
+        Y           = 0x01,
+        Z           = 0x02,
+        RX          = 0x03,
+        RY          = 0x04,
+        RZ          = 0x05,
+        THROTTLE    = 0x06,
+        RUDDER      = 0x07,
+        WHEEL       = 0x08,
+        GAS         = 0x09,
+        BRAKE       = 0x0a,
+        HAT0X       = 0x10,
+        HAT0Y       = 0x11,
+        HAT1X       = 0x12,
+        HAT1Y       = 0x13,
+        HAT2X       = 0x14,
+        HAT2Y       = 0x15,
+        HAT3X       = 0x16,
+        HAT3Y       = 0x17,
+        PRESSURE    = 0x18,
+        DISTANCE    = 0x19,
+        TILT_X      = 0x1a,
+        TILT_Y      = 0x1b,
+        TOOL_WIDTH  = 0x1c,
+
+        VOLUME      = 0x20,
+
+        MISC        = 0x28,
+
+        MT_SLOT     = 0x2f,    /* MT slot being modified */
+        MT_TOUCH_MAJOR  = 0x30,    /* Major axis of touching ellipse */
+        MT_TOUCH_MINOR  = 0x31,    /* Minor axis (omit if circular) */
+        MT_WIDTH_MAJOR  = 0x32,    /* Major axis of approaching ellipse */
+        MT_WIDTH_MINOR  = 0x33,    /* Minor axis (omit if circular) */
+        MT_ORIENTATION  = 0x34,    /* Ellipse orientation */
+        MT_POSITION_X   = 0x35,    /* Center X touch position */
+        MT_POSITION_Y   = 0x36,    /* Center Y touch position */
+        MT_TOOL_TYPE    = 0x37,    /* Type of touching device */
+        MT_BLOB_ID      = 0x38,    /* Group a set of packets as a blob */
+        MT_TRACKING_ID  = 0x39,    /* Unique ID of initiated contact */
+        MT_PRESSURE     = 0x3a,    /* Pressure on contact area */
+        MT_DISTANCE     = 0x3b,    /* Contact hover distance */
+        MT_TOOL_X       = 0x3c,    /* Center X tool position */
+        MT_TOOL_Y       = 0x3d,    /* Center Y tool position */
+
+        MAX         = 0x3f,
+        CNT         = (MAX+1),
+    }
+
+    enum EvdevButton
+    {
+        MISC        = 0x100,
+        BTN0        = 0x100,
+        BTN1        = 0x101,
+        BTN2        = 0x102,
+        BTN3        = 0x103,
+        BTN4        = 0x104,
+        BTN5        = 0x105,
+        BTN6        = 0x106,
+        BTN7        = 0x107,
+        BTN8        = 0x108,
+        BTN9        = 0x109,
+
+        MOUSE       = 0x110,
+        LEFT        = 0x110,
+        RIGHT       = 0x111,
+        MIDDLE      = 0x112,
+        SIDE        = 0x113,
+        EXTRA       = 0x114,
+        FORWARD     = 0x115,
+        BACK        = 0x116,
+        TASK        = 0x117,
+
+        JOYSTICK    = 0x120,
+        TRIGGER     = 0x120,
+        THUMB       = 0x121,
+        THUMB2      = 0x122,
+        TOP         = 0x123,
+        TOP2        = 0x124,
+        PINKIE      = 0x125,
+        BASE        = 0x126,
+        BASE2       = 0x127,
+        BASE3       = 0x128,
+        BASE4       = 0x129,
+        BASE5       = 0x12a,
+        BASE6       = 0x12b,
+        DEAD        = 0x12f,
+
+        GAMEPAD     = 0x130,
+        SOUTH       = 0x130,
+        A           = SOUTH,
+        EAST        = 0x131,
+        B           = EAST,
+        C           = 0x132,
+        NORTH       = 0x133,
+        X           = NORTH,
+        WEST        = 0x134,
+        Y           = WEST,
+        Z           = 0x135,
+        TL          = 0x136,
+        TR          = 0x137,
+        TL2         = 0x138,
+        TR2         = 0x139,
+        SELECT      = 0x13a,
+        START       = 0x13b,
+        MODE        = 0x13c,
+        THUMBL      = 0x13d,
+        THUMBR      = 0x13e,
+
+        DIGI        = 0x140,
+        TOOL_PEN        = 0x140,
+        TOOL_RUBBER     = 0x141,
+        TOOL_BRUSH      = 0x142,
+        TOOL_PENCIL     = 0x143,
+        TOOL_AIRBRUSH   = 0x144,
+        TOOL_FINGER     = 0x145,
+        TOOL_MOUSE      = 0x146,
+        TOOL_LENS       = 0x147,
+        TOOL_QUINTTAP   = 0x148, // Five fingers on trackpad
+        TOUCH           = 0x14a,
+        STYLUS          = 0x14b,
+        STYLUS2     = 0x14c,
+        TOOL_DOUBLETAP  = 0x14d,
+        TOOL_TRIPLETAP  = 0x14e,
+        TOOL_QUADTAP    = 0x14f, // Four fingers on trackpad
+
+        WHEEL       = 0x150,
+        GEAR_DOWN   = 0x150,
+        GEAR_UP     = 0x151,
+
+        DPAD_UP     = 0x220,
+        DPAD_DOWN   = 0x221,
+        DPAD_LEFT   = 0x222,
+        DPAD_RIGHT  = 0x223,
+
+        Last = 0x300,
+    }
+
+    enum EvdevType : byte
+    {
+        SYN = 0x00,
+        KEY = 0x01,
+        REL = 0x02,
+        ABS = 0x03,
+        MSC = 0x04,
+        SW =  0x05,
+        LED = 0x11,
+        SND = 0x12,
+        REP = 0x14,
+        FF =  0x15,
+        PWR = 0x16,
+        FF_STATUS = 0x17,
+        MAX = 0x1f,
+        CNT = (MAX+1),
+    }
+
+    enum EvdevIoctl : uint
+    {
+        Id = (2u << 30) | ((byte)'E' << 8) | (0x02u << 0) | (8u << 16), //EVIOCGID = _IOR('E', 0x02, struct input_id)
+        Name128 = (2u << 30) | ((byte)'E' << 8) | (0x06u << 0) | (128u << 16), //EVIOCGNAME(len) = _IOC(_IOC_READ, 'E', 0x06, len)
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    struct InputAbsInfo
+    {
+        public int Value;
+        public int Minimum;
+        public int Maximum;
+        public int Fuzz;
+        public int Flat;
+        public int Resolution;
+    };
+
+    [StructLayout(LayoutKind.Sequential)]
+    struct InputId
+    {
+        public ushort BusType;
+        public ushort Vendor;
+        public ushort Product;
+        public ushort Version;
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    struct InputEvent
+    {
+        public TimeVal Time;
+        ushort type;
+        public ushort Code;
+        public int Value;
+
+        public EvdevType Type { get { return (EvdevType)type; } }
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    struct TimeVal
+    {
+        public IntPtr Seconds;
+        public IntPtr MicroSeconds;
+    }
+}
+
diff --git a/testDrm/src/Linux/Bindings/Gbm.cs b/testDrm/src/Linux/Bindings/Gbm.cs
new file mode 100644 (file)
index 0000000..0392574
--- /dev/null
@@ -0,0 +1,282 @@
+#region License
+//
+// Gbm.cs
+//
+// Author:
+//       Stefanos A. <stapostol@gmail.com>
+//
+// 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.Runtime.InteropServices;
+
+namespace OpenTK.Platform.Linux
+{
+    using Device = IntPtr; // struct gbm_device*
+    using Surface = IntPtr;
+    using BufferObjectHandle = IntPtr;
+
+    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+    delegate void DestroyUserDataCallback(BufferObject bo, IntPtr data);
+
+    class Gbm
+    {
+        const string lib = "gbm";
+
+        [DllImport(lib, EntryPoint = "gbm_bo_create", CallingConvention = CallingConvention.Cdecl)]
+        public static extern BufferObject CreateBuffer(Device gbm, int width, int height, SurfaceFormat format, SurfaceFlags flags);
+
+        [DllImport(lib, EntryPoint = "gbm_bo_destroy", CallingConvention = CallingConvention.Cdecl)]
+        public static extern void DestroyBuffer(BufferObject bo);
+
+        [DllImport(lib, EntryPoint = "gbm_bo_write", CallingConvention = CallingConvention.Cdecl)]
+        public static extern int BOWrite(IntPtr bo, IntPtr buf, IntPtr count);
+
+        [DllImport(lib, EntryPoint = "gbm_bo_get_device", CallingConvention = CallingConvention.Cdecl)]
+        public static extern Device BOGetDevice(IntPtr bo);
+
+        [DllImport(lib, EntryPoint = "gbm_bo_get_handle", CallingConvention = CallingConvention.Cdecl)]
+        public static extern BufferObjectHandle BOGetHandle(IntPtr bo);
+
+        [DllImport(lib, EntryPoint = "gbm_bo_get_height", CallingConvention = CallingConvention.Cdecl)]
+        public static extern int BOGetHeight(IntPtr bo);
+
+        [DllImport(lib, EntryPoint = "gbm_bo_get_width", CallingConvention = CallingConvention.Cdecl)]
+        public static extern int BOGetWidth(IntPtr bo);
+
+        [DllImport(lib, EntryPoint = "gbm_bo_get_stride", CallingConvention = CallingConvention.Cdecl)]
+        public static extern int BOGetStride(IntPtr bo);
+
+        [DllImport(lib, EntryPoint = "gbm_bo_set_user_data", CallingConvention = CallingConvention.Cdecl)]
+        public static extern void BOSetUserData(IntPtr bo, IntPtr data, DestroyUserDataCallback callback);
+
+        [DllImport(lib, EntryPoint = "gbm_create_device", CallingConvention = CallingConvention.Cdecl)]
+        public static extern Device CreateDevice(int fd);
+
+        [DllImport(lib, EntryPoint = "gbm_device_destroy", CallingConvention = CallingConvention.Cdecl)]
+        public static extern void DestroyDevice(Device gbm);
+
+        [DllImport(lib, EntryPoint = "gbm_device_get_fd", CallingConvention = CallingConvention.Cdecl)]
+        public static extern int DeviceGetFD(IntPtr gbm);
+
+        [DllImport(lib, EntryPoint = "gbm_surface_create", CallingConvention = CallingConvention.Cdecl)]
+        public static extern Surface CreateSurface(Device gbm, int width, int height, SurfaceFormat format, SurfaceFlags flags);
+
+        [DllImport(lib, EntryPoint = "gbm_surface_destroy", CallingConvention = CallingConvention.Cdecl)]
+        public static extern void DestroySurface(IntPtr surface);
+
+        [DllImport(lib, EntryPoint = "gbm_device_is_format_supported", CallingConvention = CallingConvention.Cdecl)]
+        [return: MarshalAs(UnmanagedType.Bool)]
+        public static extern bool IsFormatSupported(Device gbm, SurfaceFormat format, SurfaceFlags usage);
+
+        [DllImport(lib, EntryPoint = "gbm_surface_lock_front_buffer", CallingConvention = CallingConvention.Cdecl)]
+        public static extern BufferObject LockFrontBuffer(Surface surface);
+
+        [DllImport(lib, EntryPoint = "gbm_surface_release_buffer", CallingConvention = CallingConvention.Cdecl)]
+        public static extern void ReleaseBuffer(Surface surface, BufferObject buffer);
+
+               [DllImport(lib, EntryPoint = "gbm_surface_has_free_buffers", CallingConvention = CallingConvention.Cdecl)]
+               public static extern int HasFreeBuffers (Surface surface);
+
+    }
+
+    enum SurfaceFormat
+    {
+        BigEndian = 1 << 31,
+        C8 = ((int)('C') | ((int)('8') << 8) | ((int)(' ') << 16) | ((int)(' ') << 24)),
+
+        RGB332 = ((int)('R') | ((int)('G') << 8) | ((int)('B') << 16) | ((int)('8') << 24)),
+        BGR233 = ((int)('B') | ((int)('G') << 8) | ((int)('R') << 16) | ((int)('8') << 24)),
+
+        XRGB4444 = ((int)('X') | ((int)('R') << 8) | ((int)('1') << 16) | ((int)('2') << 24)),
+        XBGR4444 = ((int)('X') | ((int)('B') << 8) | ((int)('1') << 16) | ((int)('2') << 24)),
+        RGBX4444 = ((int)('R') | ((int)('X') << 8) | ((int)('1') << 16) | ((int)('2') << 24)),
+        BGRX4444 = ((int)('B') | ((int)('X') << 8) | ((int)('1') << 16) | ((int)('2') << 24)),
+
+        ARGB4444 = ((int)('A') | ((int)('R') << 8) | ((int)('1') << 16) | ((int)('2') << 24)),
+        ABGR4444 = ((int)('A') | ((int)('B') << 8) | ((int)('1') << 16) | ((int)('2') << 24)),
+        RGBA4444 = ((int)('R') | ((int)('A') << 8) | ((int)('1') << 16) | ((int)('2') << 24)),
+        BGRA4444 = ((int)('B') | ((int)('A') << 8) | ((int)('1') << 16) | ((int)('2') << 24)),
+
+        XRGB1555 = ((int)('X') | ((int)('R') << 8) | ((int)('1') << 16) | ((int)('5') << 24)),
+        XBGR1555 = ((int)('X') | ((int)('B') << 8) | ((int)('1') << 16) | ((int)('5') << 24)),
+        RGBX5551 = ((int)('R') | ((int)('X') << 8) | ((int)('1') << 16) | ((int)('5') << 24)),
+        BGRX5551 = ((int)('B') | ((int)('X') << 8) | ((int)('1') << 16) | ((int)('5') << 24)),
+
+        ARGB1555 = ((int)('A') | ((int)('R') << 8) | ((int)('1') << 16) | ((int)('5') << 24)),
+        ABGR1555 = ((int)('A') | ((int)('B') << 8) | ((int)('1') << 16) | ((int)('5') << 24)),
+        RGBA5551 = ((int)('R') | ((int)('A') << 8) | ((int)('1') << 16) | ((int)('5') << 24)),
+        BGRA5551 = ((int)('B') | ((int)('A') << 8) | ((int)('1') << 16) | ((int)('5') << 24)),
+
+        RGB565 = ((int)('R') | ((int)('G') << 8) | ((int)('1') << 16) | ((int)('6') << 24)),
+        BGR565 = ((int)('B') | ((int)('G') << 8) | ((int)('1') << 16) | ((int)('6') << 24)),
+
+        RGB888 = ((int)('R') | ((int)('G') << 8) | ((int)('2') << 16) | ((int)('4') << 24)),
+        BGR888 = ((int)('B') | ((int)('G') << 8) | ((int)('2') << 16) | ((int)('4') << 24)),
+
+        XRGB8888 = ((int)('X') | ((int)('R') << 8) | ((int)('2') << 16) | ((int)('4') << 24)),
+        XBGR8888 = ((int)('X') | ((int)('B') << 8) | ((int)('2') << 16) | ((int)('4') << 24)),
+        RGBX8888 = ((int)('R') | ((int)('X') << 8) | ((int)('2') << 16) | ((int)('4') << 24)),
+        BGRX8888 = ((int)('B') | ((int)('X') << 8) | ((int)('2') << 16) | ((int)('4') << 24)),
+
+        ARGB8888 = ((int)('A') | ((int)('R') << 8) | ((int)('2') << 16) | ((int)('4') << 24)),
+        ABGR8888 = ((int)('A') | ((int)('B') << 8) | ((int)('2') << 16) | ((int)('4') << 24)),
+        RGBA8888 = ((int)('R') | ((int)('A') << 8) | ((int)('2') << 16) | ((int)('4') << 24)),
+        BGRA8888 = ((int)('B') | ((int)('A') << 8) | ((int)('2') << 16) | ((int)('4') << 24)),
+
+        XRGB2101010 = ((int)('X') | ((int)('R') << 8) | ((int)('3') << 16) | ((int)('0') << 24)),
+        XBGR2101010 = ((int)('X') | ((int)('B') << 8) | ((int)('3') << 16) | ((int)('0') << 24)),
+        RGBX1010102 = ((int)('R') | ((int)('X') << 8) | ((int)('3') << 16) | ((int)('0') << 24)),
+        BGRX1010102 = ((int)('B') | ((int)('X') << 8) | ((int)('3') << 16) | ((int)('0') << 24)),
+
+        ARGB2101010 = ((int)('A') | ((int)('R') << 8) | ((int)('3') << 16) | ((int)('0') << 24)),
+        ABGR2101010 = ((int)('A') | ((int)('B') << 8) | ((int)('3') << 16) | ((int)('0') << 24)),
+        RGBA1010102 = ((int)('R') | ((int)('A') << 8) | ((int)('3') << 16) | ((int)('0') << 24)),
+        BGRA1010102 = ((int)('B') | ((int)('A') << 8) | ((int)('3') << 16) | ((int)('0') << 24)),
+
+        YUYV = ((int)('Y') | ((int)('U') << 8) | ((int)('Y') << 16) | ((int)('V') << 24)),
+        YVYU = ((int)('Y') | ((int)('V') << 8) | ((int)('Y') << 16) | ((int)('U') << 24)),
+        UYVY = ((int)('U') | ((int)('Y') << 8) | ((int)('V') << 16) | ((int)('Y') << 24)),
+        VYUY = ((int)('V') | ((int)('Y') << 8) | ((int)('U') << 16) | ((int)('Y') << 24)),
+
+        AYUV = ((int)('A') | ((int)('Y') << 8) | ((int)('U') << 16) | ((int)('V') << 24)),
+
+        NV12 = ((int)('N') | ((int)('V') << 8) | ((int)('1') << 16) | ((int)('2') << 24)),
+        NV21 = ((int)('N') | ((int)('V') << 8) | ((int)('2') << 16) | ((int)('1') << 24)),
+        NV16 = ((int)('N') | ((int)('V') << 8) | ((int)('1') << 16) | ((int)('6') << 24)),
+        NV61 = ((int)('N') | ((int)('V') << 8) | ((int)('6') << 16) | ((int)('1') << 24)),
+
+        YUV410 = ((int)('Y') | ((int)('U') << 8) | ((int)('V') << 16) | ((int)('9') << 24)),
+        YVU410 = ((int)('Y') | ((int)('V') << 8) | ((int)('U') << 16) | ((int)('9') << 24)),
+        YUV411 = ((int)('Y') | ((int)('U') << 8) | ((int)('1') << 16) | ((int)('1') << 24)),
+        YVU411 = ((int)('Y') | ((int)('V') << 8) | ((int)('1') << 16) | ((int)('1') << 24)),
+        YUV420 = ((int)('Y') | ((int)('U') << 8) | ((int)('1') << 16) | ((int)('2') << 24)),
+        YVU420 = ((int)('Y') | ((int)('V') << 8) | ((int)('1') << 16) | ((int)('2') << 24)),
+        YUV422 = ((int)('Y') | ((int)('U') << 8) | ((int)('1') << 16) | ((int)('6') << 24)),
+        YVU422 = ((int)('Y') | ((int)('V') << 8) | ((int)('1') << 16) | ((int)('6') << 24)),
+        YUV444 = ((int)('Y') | ((int)('U') << 8) | ((int)('2') << 16) | ((int)('4') << 24)),
+        YVU444 = ((int)('Y') | ((int)('V') << 8) | ((int)('2') << 16) | ((int)('4') << 24)),
+    }
+
+    [Flags]
+    enum SurfaceFlags
+    {
+        Scanout = (1 << 0),
+        Cursor64x64 = (1 << 1),
+        Rendering = (1 << 2),
+        Write = (1 << 3),
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    struct BufferObject : IEquatable<BufferObject>
+    {
+        IntPtr buffer;
+
+        public static readonly BufferObject Zero =
+            default(BufferObject);
+
+        public int Write(byte[] data)
+        {
+            unsafe
+            {
+                fixed (byte* pdata = data)
+                {
+                    return Gbm.BOWrite(buffer, (IntPtr)pdata, (IntPtr)data.Length);
+                }
+            }
+        }
+
+        public void SetUserData(IntPtr data, DestroyUserDataCallback destroyFB)
+        {
+            Gbm.BOSetUserData(buffer, data, destroyFB);
+        }
+
+        public Device Device
+        {
+            get { return Gbm.BOGetDevice(buffer); }
+        }
+
+        public int Handle
+        {
+            get { return Gbm.BOGetHandle(buffer).ToInt32(); }
+        }
+
+        public int Width
+        {
+            get { return Gbm.BOGetWidth(buffer); }
+        }
+
+        public int Height
+        {
+            get { return Gbm.BOGetHeight(buffer); }
+        }
+
+        public int Stride
+        {
+            get { return Gbm.BOGetStride(buffer); }
+        }
+
+        public void Dispose()
+        {
+            Gbm.DestroyBuffer(this);
+            buffer = IntPtr.Zero;
+        }
+
+        public static bool operator ==(BufferObject left, BufferObject right)
+        {
+            return left.Equals(right);
+        }
+
+        public static bool operator !=(BufferObject left, BufferObject right)
+        {
+            return !left.Equals(right);
+        }
+
+        public override bool Equals(object obj)
+        {
+            return
+                obj is BufferObject &&
+                this.Equals((BufferObject)obj);
+        }
+
+        public override int GetHashCode()
+        {
+            return buffer.GetHashCode();
+        }
+
+        public override string ToString()
+        {
+            return string.Format("[BufferObject: {0}]", buffer);
+        }
+
+        #region IEquatable implementation
+
+        public bool Equals(BufferObject other)
+        {
+            return buffer == other.buffer;
+        }
+
+        #endregion
+    }
+}
+
diff --git a/testDrm/src/Linux/Bindings/Kms.cs b/testDrm/src/Linux/Bindings/Kms.cs
new file mode 100644 (file)
index 0000000..a5c7f48
--- /dev/null
@@ -0,0 +1,46 @@
+#region License
+//
+// Kms.cs
+//
+// Author:
+//       Stefanos A. <stapostol@gmail.com>
+//
+// Copyright (c) 2006-2014 
+//
+// 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.Runtime.InteropServices;
+
+namespace OpenTK.Platform.Linux
+{
+    class Kms
+    {
+        const string lib = "libkms";
+
+        [DllImport(lib, EntryPoint = "kms_bo_map", CallingConvention = CallingConvention.Cdecl)]
+        public static extern int MapBuffer(IntPtr bo, out IntPtr @out);
+
+        [DllImport(lib, EntryPoint = "kms_bo_unmap", CallingConvention = CallingConvention.Cdecl)]
+        public static extern int UnmapBuffer(IntPtr bo);
+    }
+}
+
diff --git a/testDrm/src/Linux/Bindings/LibInput.cs b/testDrm/src/Linux/Bindings/LibInput.cs
new file mode 100644 (file)
index 0000000..d45f55d
--- /dev/null
@@ -0,0 +1,333 @@
+#region License
+//
+// LibInput.cs
+//
+// Author:
+//       Stefanos A. <stapostol@gmail.com>
+//
+// 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
+
+#pragma warning disable 0169, 0219
+
+using System;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+
+namespace OpenTK.Platform.Linux
+{
+    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+    delegate int OpenRestrictedCallback(IntPtr path, int flags, IntPtr data);
+
+    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+    delegate void CloseRestrictedCallback(int fd, IntPtr data);
+
+    class LibInput
+    {
+        internal const string lib = "libinput";
+
+        [DllImport(lib, EntryPoint = "libinput_udev_create_context", CallingConvention = CallingConvention.Cdecl)]
+        public static extern IntPtr CreateContext(InputInterface @interface,
+            IntPtr user_data, IntPtr udev);
+
+        [DllImport(lib, EntryPoint = "libinput_udev_assign_seat", CallingConvention = CallingConvention.Cdecl)]
+        public static extern int AssignSeat(IntPtr libinput, string seat_id);
+
+        [DllImport(lib, EntryPoint = "libinput_destroy", CallingConvention = CallingConvention.Cdecl)]
+        public static extern void DestroyContext(IntPtr libinput);
+
+        [DllImport(lib, EntryPoint = "libinput_event_destroy", CallingConvention = CallingConvention.Cdecl)]
+        public static extern void DestroyEvent(IntPtr @event);
+
+        [DllImport(lib, EntryPoint = "libinput_device_get_sysname", CallingConvention = CallingConvention.Cdecl)]
+        static extern IntPtr DeviceGetNameInternal(IntPtr device);
+        public static string DeviceGetName(IntPtr device)
+        {
+            unsafe
+            {
+                return new string((sbyte*)DeviceGetNameInternal(device));
+            }
+        }
+
+        [DllImport(lib, EntryPoint = "libinput_device_get_user_data", CallingConvention = CallingConvention.Cdecl)]
+        public static extern IntPtr DeviceGetData(IntPtr device);
+
+        [DllImport(lib, EntryPoint = "libinput_device_set_user_data", CallingConvention = CallingConvention.Cdecl)]
+        public static extern void DeviceSetData(IntPtr device, IntPtr user_data);
+
+        [DllImport(lib, EntryPoint = "libinput_device_get_output_name", CallingConvention = CallingConvention.Cdecl)]
+        static extern IntPtr DeviceGetOutputNameInternal(IntPtr device);
+        public static string DeviceGetOutputName(IntPtr device)
+        {
+            unsafe
+            {
+                sbyte* pname = (sbyte*)DeviceGetOutputNameInternal(device);
+                return pname == null ? String.Empty : new string(pname);
+            }
+        }
+
+        [DllImport(lib, EntryPoint = "libinput_device_get_seat", CallingConvention = CallingConvention.Cdecl)]
+        public static extern IntPtr DeviceGetSeat(IntPtr device);
+
+        [DllImport(lib, EntryPoint = "libinput_device_has_capability", CallingConvention = CallingConvention.Cdecl)]
+        [return: MarshalAs(UnmanagedType.Bool)]
+        public static extern bool DeviceHasCapability(IntPtr device, DeviceCapability capability);
+
+        [DllImport(lib, EntryPoint = "libinput_dispatch", CallingConvention = CallingConvention.Cdecl)]
+        public static extern int Dispatch(IntPtr libinput);
+
+        [DllImport(lib, EntryPoint = "libinput_event_get_device", CallingConvention = CallingConvention.Cdecl)]
+        public static extern IntPtr GetDevice(IntPtr @event);
+
+        [DllImport(lib, EntryPoint = "libinput_get_event", CallingConvention = CallingConvention.Cdecl)]
+        public static extern IntPtr GetEvent(IntPtr libinput);
+
+        [DllImport(lib, EntryPoint = "libinput_event_get_keyboard_event", CallingConvention = CallingConvention.Cdecl)]
+        public static extern KeyboardEvent GetKeyboardEvent(IntPtr @event);
+
+        [DllImport(lib, EntryPoint = "libinput_event_get_pointer_event", CallingConvention = CallingConvention.Cdecl)]
+        public static extern PointerEvent GetPointerEvent(IntPtr @event);
+
+        [DllImport(lib, EntryPoint = "libinput_event_get_type", CallingConvention = CallingConvention.Cdecl)]
+        public static extern InputEventType GetEventType(IntPtr @event);
+
+        [DllImport(lib, EntryPoint = "libinput_get_fd", CallingConvention = CallingConvention.Cdecl)]
+        public static extern int GetFD(IntPtr libinput);
+
+        [DllImport(lib, EntryPoint = "libinput_next_event_type", CallingConvention = CallingConvention.Cdecl)]
+        public static extern InputEventType NextEventType(IntPtr libinput);
+
+        [DllImport(lib, EntryPoint = "libinput_resume", CallingConvention = CallingConvention.Cdecl)]
+        public static extern void Resume(IntPtr libinput);
+
+        [DllImport(lib, EntryPoint = "libinput_suspend", CallingConvention = CallingConvention.Cdecl)]
+        public static extern void Suspend(IntPtr libinput);
+
+        [DllImport(lib, EntryPoint = "libinput_seat_get_logical_name", CallingConvention = CallingConvention.Cdecl)]
+        static extern public IntPtr SeatGetLogicalNameInternal(IntPtr seat);
+        public static string SeatGetLogicalName(IntPtr seat)
+        {
+            unsafe
+            {
+                return new string((sbyte*)SeatGetLogicalNameInternal(seat));
+            }
+        }
+
+        [DllImport(lib, EntryPoint = "libinput_seat_get_physical_name", CallingConvention = CallingConvention.Cdecl)]
+        static extern public IntPtr SeatGetPhysicalNameInternal(IntPtr seat);
+        public static string SeatGetPhysicalName(IntPtr seat)
+        {
+            unsafe
+            {
+                return new string((sbyte*)SeatGetPhysicalNameInternal(seat));
+            }
+        }
+    }
+
+    enum DeviceCapability
+    {
+        Keyboard = 0,
+        Mouse,
+        Touch
+    }
+
+    enum InputEventType
+    {
+        None = 0,
+
+        DeviceAdded,
+        DeviceRemoved,
+
+        KeyboardKey = 300,
+
+        PointerMotion = 400,
+        PointerMotionAbsolute,
+        PointerButton,
+        PointerAxis,
+
+        TouchDown = 500,
+        TouchUP,
+        TouchMotion,
+        TouchCancel,
+
+        /// \internal
+        /// <summary>
+        /// Signals the end of a set of touchpoints at one device sample
+        /// time. This event has no coordinate information attached.
+        /// </summary>
+        TouchFrame
+    }
+
+    enum ButtonState
+    {
+        Released = 0,
+        Pressed = 1
+    }
+
+    enum KeyState
+    {
+        Released = 0,
+        Pressed = 1
+    }
+
+    enum PointerAxis
+    {
+        VerticalScroll = 0,
+        HorizontalScroll = 1
+    }
+
+    struct Fixed24
+    {
+        internal readonly int Value;
+
+        public static implicit operator double(Fixed24 n)
+        {
+            long l = ((1023L + 44L) << 52) + (1L << 51) + n.Value;
+            unsafe
+            {
+                double d = *(double*)&l;
+                return d - (3L << 43);
+            }
+        }
+
+        public static implicit operator float(Fixed24 n)
+        {
+            return (float)(double)n;
+        }
+
+        public static explicit operator int(Fixed24 n)
+        {
+            return n.Value >> 8;
+        }
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    class InputInterface
+    {
+        internal readonly IntPtr open;
+        internal readonly IntPtr close;
+
+        public InputInterface(
+            OpenRestrictedCallback open_restricted,
+            CloseRestrictedCallback close_restricted)
+        {
+            if (open_restricted == null || close_restricted == null)
+                throw new ArgumentNullException();
+
+            open = Marshal.GetFunctionPointerForDelegate(open_restricted);
+            close = Marshal.GetFunctionPointerForDelegate(close_restricted);
+        }
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    struct KeyboardEvent
+    {
+        IntPtr @event;
+
+        public IntPtr BaseEvent { get { return GetBaseEvent(@event); } }
+        public IntPtr Event { get { return @event; } }
+        public uint Time { get { return GetTime(@event); } }
+        public uint Key { get { return GetKey(@event); } }
+        public uint KeyCount { get { return GetSeatKeyCount(@event); } }
+        public KeyState KeyState { get { return GetKeyState(@event); } }
+
+        [DllImport(LibInput.lib, EntryPoint = "libinput_event_keyboard_get_time", CallingConvention = CallingConvention.Cdecl)]
+        static extern uint GetTime(IntPtr @event);
+
+        [DllImport(LibInput.lib, EntryPoint = "libinput_event_keyboard_get_base_event", CallingConvention = CallingConvention.Cdecl)]
+        static extern IntPtr GetBaseEvent(IntPtr @event);
+
+        [DllImport(LibInput.lib, EntryPoint = "libinput_event_keyboard_get_seat_key_count", CallingConvention = CallingConvention.Cdecl)]
+        static extern uint GetSeatKeyCount(IntPtr @event);
+
+        [DllImport(LibInput.lib, EntryPoint = "libinput_event_keyboard_get_key", CallingConvention = CallingConvention.Cdecl)]
+        static extern uint GetKey(IntPtr @event);
+
+        [DllImport(LibInput.lib, EntryPoint = "libinput_event_keyboard_get_key_state", CallingConvention = CallingConvention.Cdecl)]
+        static extern KeyState GetKeyState(IntPtr @event);
+    }
+
+
+    [StructLayout(LayoutKind.Sequential)]
+    struct PointerEvent
+    {
+        IntPtr @event;
+
+        public IntPtr BaseEvent { get { return GetBaseEvent(@event); } }
+        public IntPtr Event { get { return @event; } }
+        public uint Time { get { return GetTime(@event); } }
+        public EvdevButton Button { get { return (EvdevButton)GetButton(@event); } }
+        public uint ButtonCount { get { return GetButtonCount(@event); } }
+        public ButtonState ButtonState { get { return GetButtonState(@event); } }
+        public bool HasAxis(PointerAxis axis) { return HasAxis(@event, axis) != 0; }
+        public double AxisValue(PointerAxis axis) { return GetAxisValue(@event, axis); }
+        public double DeltaX { get { return GetDX(@event); } }
+        public double DeltaY { get { return GetDY(@event); } }
+        public double X { get { return GetAbsX(@event); } }
+        public double Y { get { return GetAbsY(@event); } }
+        public double TransformedX(int width) { return GetAbsXTransformed(@event, width); }
+        public double TransformedY(int height) { return GetAbsYTransformed(@event, height); }
+
+        [DllImport(LibInput.lib, EntryPoint = "libinput_event_pointer_get_time", CallingConvention = CallingConvention.Cdecl)]
+        static extern uint GetTime(IntPtr @event);
+
+        [DllImport(LibInput.lib, EntryPoint = "libinput_event_pointer_get_base_event", CallingConvention = CallingConvention.Cdecl)]
+        static extern IntPtr GetBaseEvent(IntPtr @event);
+
+        [DllImport(LibInput.lib, EntryPoint = "libinput_event_pointer_get_seat_key_count", CallingConvention = CallingConvention.Cdecl)]
+        static extern uint GetSeatKeyCount(IntPtr @event);
+
+        [DllImport(LibInput.lib, EntryPoint = "libinput_event_pointer_get_button", CallingConvention = CallingConvention.Cdecl)]
+        static extern uint GetButton(IntPtr @event);
+
+        [DllImport(LibInput.lib, EntryPoint = "libinput_event_pointer_get_seat_button_count", CallingConvention = CallingConvention.Cdecl)]
+        static extern uint GetButtonCount(IntPtr @event);
+
+        [DllImport(LibInput.lib, EntryPoint = "libinput_event_pointer_get_button_state", CallingConvention = CallingConvention.Cdecl)]
+        static extern ButtonState GetButtonState(IntPtr @event);
+
+        [DllImport(LibInput.lib, EntryPoint = "libinput_event_pointer_has_axis", CallingConvention = CallingConvention.Cdecl)]
+        static extern int HasAxis(IntPtr @event, PointerAxis axis);
+
+        [DllImport(LibInput.lib, EntryPoint = "libinput_event_pointer_get_axis_value", CallingConvention = CallingConvention.Cdecl)]
+        static extern double GetAxisValue(IntPtr @event, PointerAxis axis);
+
+        [DllImport(LibInput.lib, EntryPoint = "libinput_event_pointer_get_dx", CallingConvention = CallingConvention.Cdecl)]
+        static extern double GetDX(IntPtr @event);
+
+        [DllImport(LibInput.lib, EntryPoint = "libinput_event_pointer_get_dy", CallingConvention = CallingConvention.Cdecl)]
+        static extern double GetDY(IntPtr @event);
+
+        [DllImport(LibInput.lib, EntryPoint = "libinput_event_pointer_get_absolute_x", CallingConvention = CallingConvention.Cdecl)]
+        static extern double GetAbsX(IntPtr @event);
+
+        [DllImport(LibInput.lib, EntryPoint = "libinput_event_pointer_get_absolute_y", CallingConvention = CallingConvention.Cdecl)]
+        static extern double GetAbsY(IntPtr @event);
+
+        [DllImport(LibInput.lib, EntryPoint = "libinput_event_pointer_get_absolute_x_transformed", CallingConvention = CallingConvention.Cdecl)]
+        static extern double GetAbsXTransformed(IntPtr @event, int width);
+
+        [DllImport(LibInput.lib, EntryPoint = "libinput_event_pointer_get_absolute_y_transformed", CallingConvention = CallingConvention.Cdecl)]
+        static extern double GetAbsYTransformed(IntPtr @event, int height);
+    }
+}
+
diff --git a/testDrm/src/Linux/Bindings/Libc.cs b/testDrm/src/Linux/Bindings/Libc.cs
new file mode 100644 (file)
index 0000000..1131875
--- /dev/null
@@ -0,0 +1,186 @@
+#region License
+//
+// Linux.cs
+//
+// Author:
+//       Stefanos A. <stapostol@gmail.com>
+//
+// 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.Runtime.InteropServices;
+using System.Text;
+
+#pragma warning disable 0649 // field is never assigned
+
+namespace OpenTK.Platform.Linux
+{
+    partial class Libc
+    {
+        const string lib = "libc";
+
+        [DllImport(lib)]
+        public static extern int dup(int file);
+
+        [DllImport(lib)]
+        public static extern int dup2(int file1, int file2);
+
+        [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, EvdevIoctl request, [Out] IntPtr data);
+
+        [DllImport(lib)]
+        public static extern int ioctl(int d, uint request, [Out] IntPtr data);
+
+        [DllImport(lib)]
+        public static extern int ioctl(int d, KeyboardIoctlCode request, ref IntPtr data);
+
+        [DllImport(lib)]
+        public static extern int ioctl(int d, KeyboardIoctlCode request, int data);
+
+        [DllImport(lib)]
+        public static extern int open([MarshalAs(UnmanagedType.LPStr)]string pathname, OpenFlags flags);
+
+        [DllImport(lib)]
+        public static extern int open(IntPtr 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);
+
+        public static int read(int fd, out byte b)
+        {
+            unsafe
+            {
+                fixed (byte* pb = &b)
+                {
+                    return read(fd, pb, (UIntPtr)1).ToInt32();
+                }
+            }
+        }
+
+        public static int read(int fd, out short s)
+        {
+            unsafe
+            {
+                fixed (short* ps = &s)
+                {
+                    return read(fd, ps, (UIntPtr)2).ToInt32();
+                }
+            }
+        }
+
+        [DllImport(lib)]
+        [return: MarshalAs(UnmanagedType.Bool)]
+        public static extern bool isatty(int fd);
+    }
+
+    enum ErrorNumber
+    {
+        Interrupted = 4,
+        Again = 11,
+        InvalidValue = 22,
+    }
+
+    [Flags]
+    enum DirectionFlags
+    {
+        None = 0,
+        Write = 1,
+        Read = 2
+    }
+
+    [Flags]
+    enum OpenFlags
+    {
+        ReadOnly = 0x0000,
+        WriteOnly = 0x0001,
+        ReadWrite = 0x0002,
+        NonBlock = 0x0800,
+        CloseOnExec = 0x0080000
+    }
+
+    [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)
+    }
+
+    enum KeyboardIoctlCode
+    {
+        GetMode = 0x4b44,
+        SetMode = 0x4b45,
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    struct Stat
+    {
+        public IntPtr dev;     /* ID of device containing file */
+        public IntPtr ino;     /* inode number */
+        public IntPtr mode;    /* protection */
+        public IntPtr nlink;   /* number of hard links */
+        public IntPtr uid;     /* user ID of owner */
+        public IntPtr gid;     /* group ID of owner */
+        public IntPtr rdev;    /* device ID (if special file) */
+        public IntPtr size;    /* total size, in bytes */
+        public IntPtr blksize; /* blocksize for file system I/O */
+        public IntPtr blocks;  /* number of 512B blocks allocated */
+        public IntPtr atime;   /* time of last access */
+        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/testDrm/src/Linux/Bindings/Poll.cs b/testDrm/src/Linux/Bindings/Poll.cs
new file mode 100644 (file)
index 0000000..f78d6d7
--- /dev/null
@@ -0,0 +1,65 @@
+#region License
+//
+// Poll.cs
+//
+// Author:
+//       Stefanos A. <stapostol@gmail.com>
+//
+// 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.Runtime.InteropServices;
+
+namespace OpenTK.Platform.Linux
+{
+    partial class Libc
+    {
+        [DllImport(lib, CallingConvention = CallingConvention.Cdecl, SetLastError = true)]
+        public static extern int poll(ref PollFD fd, IntPtr fd_count, int timeout);
+
+        public static int poll(ref PollFD fd, int fd_count, int timeout)
+        {
+            return poll(ref fd, (IntPtr)fd_count, timeout);
+        }
+    }
+
+    [Flags]
+    enum PollFlags : short
+    {
+        In = 0x01,
+        Pri = 0x02,
+        Out = 0x04,
+        Error = 0x08,
+        Hup = 0x10,
+        Invalid = 0x20,
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    struct PollFD
+    {
+        public int fd;
+        public PollFlags events;
+        public PollFlags revents;
+    }
+}
+
diff --git a/testDrm/src/Linux/Bindings/Terminal.cs b/testDrm/src/Linux/Bindings/Terminal.cs
new file mode 100644 (file)
index 0000000..e72ad74
--- /dev/null
@@ -0,0 +1,170 @@
+#region License
+//
+// Terminal.cs
+//
+// Author:
+//       Stefanos A. <stapostol@gmail.com>
+//
+// 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.Runtime.InteropServices;
+
+namespace OpenTK.Platform.Linux
+{
+    class Terminal
+    {
+        const string lib = "libc";
+
+        [DllImport(lib, EntryPoint = "isatty", CallingConvention = CallingConvention.Cdecl)]
+        [return: MarshalAs(UnmanagedType.I4)]
+        public static extern bool IsTerminal(int fd);
+
+        [DllImport(lib, EntryPoint = "tcgetattr", CallingConvention = CallingConvention.Cdecl)]
+        public static extern int GetAttributes(int fd, out TerminalState state);
+
+        [DllImport(lib, EntryPoint = "tcsetattr", CallingConvention = CallingConvention.Cdecl)]
+        public static extern int SetAttributes(int fd, OptionalActions actions, ref TerminalState state);
+    }
+
+    [Flags]
+    enum InputFlags
+    {
+        IGNBRK = 1 << 0,
+        BRKINT = 1 << 1,
+        IGNPAR = 1 << 2,
+        PARMRK = 1 << 3,
+        INPCK  = 1 << 4,
+        ISTRIP = 1 << 5,
+        INLCR  = 1 << 6,
+        IGNCR  = 1 << 7,
+        ICRNL  = 1 << 8,
+        IUCLC  = 1 << 9,
+        IXON   = 1 << 10,
+        IXANY  = 1 << 11,
+        IXOFF  = 1 << 12,
+        IMAXBEL = 1 << 13,
+        IUTF8  = 1 << 14,
+    }
+
+    [Flags]
+    enum OutputFlags
+    {
+        OPOST  = 1 << 1,
+        OLCUC  = 1 << 2,
+        ONLCR  = 1 << 3,
+        OCRNL  = 1 << 4,
+        ONOCR  = 1 << 5,
+        ONLRET = 1 << 6,
+        OFILL  = 1 << 7,
+        OFDEL  = 1 << 8,
+    }
+
+    [Flags]
+    enum ControlFlags
+    {
+        B0 = 0, // hang up
+        B50,
+        B75,
+        B110,
+        B134,
+        B150,
+        B200,
+        B300,
+        B600,
+        B1200,
+        B1800,
+        B2400,
+        B4800,
+        B9600,
+        B19200,
+        B38400,
+    }
+
+    [Flags]
+    enum LocalFlags
+    {
+        ISIG = 0x01,
+        ICANON = 0x02,
+        ECHO = 0x08,
+    }
+
+    enum OptionalActions
+    {
+        NOW = 0,
+        DRAIN = 1,
+        FLUSH = 2
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    struct TerminalState
+    {
+        public InputFlags InputMode;
+        public OutputFlags OutputMode;
+        public ControlFlags ControlMode;
+        public LocalFlags LocalMode;
+        public byte LineDiscipline;
+        public ControlCharacters ControlCharacters;
+        public int InputSpeed;
+        public int OutputSpeed;
+    }
+
+    [StructLayout(LayoutKind.Sequential)]
+    struct ControlCharacters
+    {
+        public byte VINTR;
+        public byte VQUIT;
+        public byte VERASE;
+        public byte VKILL;
+        public byte VEOF;
+        public byte VTIME;
+        public byte VMIN;
+        public byte VSWTC;
+        public byte VSTART;
+        public byte VSTOP;
+        public byte VSUSP;
+        public byte VEOL;
+        public byte VREPRINT;
+        public byte VDISCARD;
+        public byte VWERASE;
+        public byte VLNEXT;
+        public byte VEOL2;
+        public byte C17;
+        public byte C18;
+        public byte C19;
+        public byte C20;
+        public byte C21;
+        public byte C22;
+        public byte C23;
+        public byte C24;
+        public byte C25;
+        public byte C26;
+        public byte C27;
+        public byte C28;
+        public byte C29;
+        public byte C30;
+        public byte C31;
+
+    }
+}
+
diff --git a/testDrm/src/Linux/Bindings/Udev.cs b/testDrm/src/Linux/Bindings/Udev.cs
new file mode 100644 (file)
index 0000000..4c341b7
--- /dev/null
@@ -0,0 +1,46 @@
+#region License
+//
+// Udev.cs
+//
+// Author:
+//       Stefanos A. <stapostol@gmail.com>
+//
+// 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.Runtime.InteropServices;
+
+namespace OpenTK.Platform.Linux
+{
+    class Udev
+    {
+        const string lib = "libudev";
+
+        [DllImport(lib, EntryPoint = "udev_new", CallingConvention = CallingConvention.Cdecl)]
+        public static extern IntPtr New();
+
+        [DllImport(lib, EntryPoint = "udev_destroy", CallingConvention = CallingConvention.Cdecl)]
+        public static extern void Destroy(IntPtr Udev);
+    }
+}
+
diff --git a/testDrm/src/Linux/DefaultCursor.cs b/testDrm/src/Linux/DefaultCursor.cs
new file mode 100644 (file)
index 0000000..40e58e5
--- /dev/null
@@ -0,0 +1,76 @@
+#region License
+//
+// DefaultCursor.cs
+//
+// Author:
+//       Stefanos A. <stapostol@gmail.com>
+//
+// Copyright (c) 2006-2014 
+//
+// 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;
+
+namespace OpenTK.Platform.Linux
+{
+    static class Cursors
+    {
+        public static readonly MouseCursor Default =
+            new MouseCursor(8, 4, 32, 32, new byte[]
+            {
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x1A, 0x1A, 0x1A, 0x1F, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0xF1, 0xF1, 0xF1, 0xF3, 0x16, 0x16, 0x16, 0x2B, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0B, 0xFF, 0xFF, 0xFF, 0xFF, 0xEC, 0xEC, 0xEC, 0xF4, 0x11, 0x11, 0x11, 0x37, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE9, 0xE9, 0xE9, 0xF3, 0x0C, 0x0C, 0x0C, 0x33, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0E, 0xFF, 0xFF, 0xFF, 0xFF, 0x99, 0x99, 0x99, 0xFF, 0xF7, 0xF7, 0xF7, 0xFF, 0xE4, 0xE4, 0xE4, 0xF0, 0x07, 0x07, 0x07, 0x2D, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0E, 0xFF, 0xFF, 0xFF, 0xFF, 0x61, 0x61, 0x61, 0xFF, 0x52, 0x52, 0x52, 0xFF, 0xF9, 0xF9, 0xF9, 0xFF, 0xE0, 0xE0, 0xE0, 0xEC, 0x03, 0x03, 0x03, 0x29, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0E, 0xFF, 0xFF, 0xFF, 0xFF, 0x5F, 0x5F, 0x5F, 0xFF, 0x13, 0x13, 0x13, 0xFF, 0x5C, 0x5C, 0x5C, 0xFF, 0xFC, 0xFC, 0xFC, 0xFF, 0xD9, 0xD9, 0xD9, 0xE7, 0x01, 0x01, 0x01, 0x26, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0E, 0xFF, 0xFF, 0xFF, 0xFF, 0x5C, 0x5C, 0x5C, 0xFF, 0x10, 0x10, 0x10, 0xFF, 0x19, 0x19, 0x19, 0xFF, 0x66, 0x66, 0x66, 0xFF, 0xFD, 0xFD, 0xFD, 0xFF, 0xD3, 0xD3, 0xD3, 0xE2, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0E, 0xFF, 0xFF, 0xFF, 0xFF, 0x59, 0x59, 0x59, 0xFF, 0x0C, 0x0C, 0x0C, 0xFF, 0x15, 0x15, 0x15, 0xFF, 0x1E, 0x1E, 0x1E, 0xFF, 0x72, 0x72, 0x72, 0xFF, 0xFE, 0xFE, 0xFE, 0xFF, 0xCA, 0xCA, 0xCA, 0xDB, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0E, 0xFF, 0xFF, 0xFF, 0xFF, 0x58, 0x58, 0x58, 0xFF, 0x08, 0x08, 0x08, 0xFF, 0x11, 0x11, 0x11, 0xFF, 0x1A, 0x1A, 0x1A, 0xFF, 0x24, 0x24, 0x24, 0xFF, 0x7C, 0x7C, 0x7C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC1, 0xC1, 0xC1, 0xD4, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0E, 0xFF, 0xFF, 0xFF, 0xFF, 0x58, 0x58, 0x58, 0xFF, 0x04, 0x04, 0x04, 0xFF, 0x0D, 0x0D, 0x0D, 0xFF, 0x16, 0x16, 0x16, 0xFF, 0x20, 0x20, 0x20, 0xFF, 0x29, 0x29, 0x29, 0xFF, 0x88, 0x88, 0x88, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xB7, 0xB7, 0xB7, 0xCD, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0E, 0xFF, 0xFF, 0xFF, 0xFF, 0x58, 0x58, 0x58, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x09, 0x09, 0x09, 0xFF, 0x12, 0x12, 0x12, 0xFF, 0x1C, 0x1C, 0x1C, 0xFF, 0x25, 0x25, 0x25, 0xFF, 0x2F, 0x2F, 0x2F, 0xFF, 0x92, 0x92, 0x92, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAD, 0xAD, 0xAD, 0xC5, 0x00, 0x00, 0x00, 0x1D, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0E, 0xFF, 0xFF, 0xFF, 0xFF, 0x58, 0x58, 0x58, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x05, 0x05, 0x05, 0xFF, 0x0E, 0x0E, 0x0E, 0xFF, 0x18, 0x18, 0x18, 0xFF, 0x21, 0x21, 0x21, 0xFF, 0x2B, 0x2B, 0x2B, 0xFF, 0x34, 0x34, 0x34, 0xFF, 0x9C, 0x9C, 0x9C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xA1, 0xA1, 0xA1, 0xBC, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0E, 0xFF, 0xFF, 0xFF, 0xFF, 0x58, 0x58, 0x58, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x01, 0x01, 0x01, 0xFF, 0x0A, 0x0A, 0x0A, 0xFF, 0x14, 0x14, 0x14, 0xFF, 0x1D, 0x1D, 0x1D, 0xFF, 0x27, 0x27, 0x27, 0xFF, 0x30, 0x30, 0x30, 0xFF, 0x39, 0x39, 0x39, 0xFF, 0xA7, 0xA7, 0xA7, 0xFF, 0xFE, 0xFE, 0xFE, 0xFF, 0x96, 0x96, 0x96, 0xB3, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0E, 0xFF, 0xFF, 0xFF, 0xFF, 0x58, 0x58, 0x58, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x07, 0x07, 0x07, 0xFF, 0x10, 0x10, 0x10, 0xFF, 0x19, 0x19, 0x19, 0xFF, 0x23, 0x23, 0x23, 0xFF, 0x2C, 0x2C, 0x2C, 0xFF, 0x35, 0x35, 0x35, 0xFF, 0x3F, 0x3F, 0x3F, 0xFF, 0xB0, 0xB0, 0xB0, 0xFF, 0xFE, 0xFE, 0xFE, 0xFF, 0x8B, 0x8B, 0x8B, 0xAB, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0E, 0xFF, 0xFF, 0xFF, 0xFF, 0x58, 0x58, 0x58, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x03, 0x03, 0x03, 0xFF, 0x0C, 0x0C, 0x0C, 0xFF, 0x15, 0x15, 0x15, 0xFF, 0x1F, 0x1F, 0x1F, 0xFF, 0x28, 0x28, 0x28, 0xFF, 0x31, 0x31, 0x31, 0xFF, 0x3B, 0x3B, 0x3B, 0xFF, 0x45, 0x45, 0x45, 0xFF, 0xB7, 0xB7, 0xB7, 0xFF, 0xFE, 0xFE, 0xFE, 0xFF, 0x80, 0x80, 0x80, 0xA2, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0E, 0xFF, 0xFF, 0xFF, 0xFF, 0x58, 0x58, 0x58, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x08, 0x08, 0x08, 0xFF, 0x11, 0x11, 0x11, 0xFF, 0x1F, 0x1F, 0x1F, 0xFF, 0x61, 0x61, 0x61, 0xFF, 0x69, 0x69, 0x69, 0xFF, 0x6F, 0x6F, 0x6F, 0xFF, 0x76, 0x76, 0x76, 0xFF, 0x7D, 0x7D, 0x7D, 0xFF, 0xE1, 0xE1, 0xE1, 0xFF, 0xFD, 0xFD, 0xFD, 0xFF, 0x75, 0x75, 0x75, 0x97, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0E, 0xFF, 0xFF, 0xFF, 0xFF, 0x58, 0x58, 0x58, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x04, 0x04, 0x04, 0xFF, 0x0D, 0x0D, 0x0D, 0xFF, 0x17, 0x17, 0x17, 0xFF, 0xCD, 0xCD, 0xCD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x66, 0x66, 0x66, 0x85, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0E, 0xFF, 0xFF, 0xFF, 0xFF, 0x58, 0x58, 0x58, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x5B, 0x5B, 0x5B, 0xFF, 0x10, 0x10, 0x10, 0xFF, 0x13, 0x13, 0x13, 0xFF, 0x61, 0x61, 0x61, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x69, 0x69, 0x69, 0xBA, 0x1E, 0x1E, 0x1E, 0x83, 0x1E, 0x1E, 0x1E, 0x78, 0x1E, 0x1E, 0x1E, 0x77, 0x1E, 0x1E, 0x1E, 0x74, 0x1E, 0x1E, 0x1E, 0x6B, 0x15, 0x15, 0x15, 0x4A, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0E, 0xFF, 0xFF, 0xFF, 0xFF, 0x58, 0x58, 0x58, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x6D, 0x6D, 0x6D, 0xFF, 0xFE, 0xFE, 0xFE, 0xFF, 0x6D, 0x6D, 0x6D, 0xFF, 0x0F, 0x0F, 0x0F, 0xFF, 0x19, 0x19, 0x19, 0xFF, 0xDE, 0xDE, 0xDE, 0xFF, 0xDB, 0xDB, 0xDB, 0xEE, 0x00, 0x00, 0x00, 0x4A, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0E, 0xFF, 0xFF, 0xFF, 0xFF, 0x58, 0x58, 0x58, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x75, 0x75, 0x75, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF7, 0xF7, 0xF7, 0xFC, 0xE6, 0xE6, 0xE6, 0xFF, 0x10, 0x10, 0x10, 0xFF, 0x14, 0x14, 0x14, 0xFF, 0x71, 0x71, 0x71, 0xFF, 0xFE, 0xFE, 0xFE, 0xFF, 0x36, 0x36, 0x36, 0x75, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0E, 0xFF, 0xFF, 0xFF, 0xFF, 0x58, 0x58, 0x58, 0xFF, 0x7E, 0x7E, 0x7E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAF, 0xAF, 0xAF, 0xD9, 0x36, 0x36, 0x36, 0x8F, 0xFD, 0xFD, 0xFD, 0xFF, 0x67, 0x67, 0x67, 0xFF, 0x10, 0x10, 0x10, 0xFF, 0x1E, 0x1E, 0x1E, 0xFF, 0xEA, 0xEA, 0xEA, 0xFF, 0xCD, 0xCD, 0xCD, 0xE2, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0E, 0xFF, 0xFF, 0xFF, 0xFF, 0xCC, 0xCC, 0xCC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xA7, 0xA7, 0xA7, 0xD5, 0x00, 0x00, 0x00, 0x5E, 0x00, 0x00, 0x00, 0x3A, 0xD5, 0xD5, 0xD5, 0xE3, 0xE1, 0xE1, 0xE1, 0xFF, 0x0F, 0x0F, 0x0F, 0xFF, 0x16, 0x16, 0x16, 0xFF, 0x81, 0x81, 0x81, 0xFF, 0xFC, 0xFC, 0xFC, 0xFF, 0x20, 0x20, 0x20, 0x5E, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFE, 0xFE, 0xFF, 0x9F, 0x9F, 0x9F, 0xCF, 0x00, 0x00, 0x00, 0x5B, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x12, 0x3D, 0x3D, 0x3D, 0x59, 0xFD, 0xFD, 0xFD, 0xFF, 0x61, 0x61, 0x61, 0xFF, 0x12, 0x12, 0x12, 0xFF, 0x25, 0x25, 0x25, 0xFF, 0xFA, 0xFA, 0xFA, 0xFF, 0x97, 0x97, 0x97, 0xC0, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0D, 0xFF, 0xFF, 0xFF, 0xFF, 0x97, 0x97, 0x97, 0xC1, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x2B, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0xD9, 0xD9, 0xD9, 0xE5, 0xDC, 0xDC, 0xDC, 0xFF, 0x19, 0x19, 0x19, 0xFF, 0x34, 0x34, 0x34, 0xFF, 0xFB, 0xFB, 0xFB, 0xFF, 0xA2, 0xA2, 0xA2, 0xCB, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0B, 0x8E, 0x8E, 0x8E, 0xA1, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x45, 0x45, 0x45, 0x5F, 0xFA, 0xFA, 0xFA, 0xFF, 0xF2, 0xF2, 0xF2, 0xFF, 0xFB, 0xFB, 0xFB, 0xFF, 0xF2, 0xF2, 0xF2, 0xFC, 0x30, 0x30, 0x30, 0x83, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0E, 0x34, 0x34, 0x34, 0x5D, 0xBB, 0xBB, 0xBB, 0xD5, 0x95, 0x95, 0x95, 0xC4, 0x16, 0x16, 0x16, 0x72, 0x00, 0x00, 0x00, 0x3D, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x2D, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+            });
+
+        public static readonly MouseCursor Empty = MouseCursor.Empty;
+    }
+}
+
diff --git a/testDrm/src/Linux/LinuxDisplayDriver.cs b/testDrm/src/Linux/LinuxDisplayDriver.cs
new file mode 100644 (file)
index 0000000..74aed63
--- /dev/null
@@ -0,0 +1,415 @@
+#region License
+//
+// LinuxDisplayDriver.cs
+//
+// Author:
+//       Stefanos A. <stapostol@gmail.com>
+//
+// 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;
+#if !MINIMAL
+using System.Drawing;
+#endif
+
+namespace OpenTK.Platform.Linux
+{
+    // Stores platform-specific information about a display
+    class LinuxDisplay
+    {
+        public int FD;
+        public IntPtr Connector;
+        public IntPtr Crtc;
+        public IntPtr Encoder;
+
+        unsafe public ModeConnector* pConnector { get { return (ModeConnector*)Connector; } }
+        unsafe public ModeCrtc* pCrtc { get { return (ModeCrtc*)Crtc; } }
+        unsafe public ModeEncoder* pEncoder { get { return (ModeEncoder*)Encoder; } }
+        /*
+        public ModeInfo Mode
+        {
+            get
+            {
+                if (Crtc == IntPtr.Zero)
+                    throw new InvalidOperationException();
+
+                unsafe
+                {
+                    return pCrtc->mode;
+                }
+            }
+        }
+        */
+
+        public ModeInfo OriginalMode;
+
+        public int Id
+        {
+            get
+            {
+                if (Crtc == IntPtr.Zero)
+                    throw new InvalidOperationException();
+
+                unsafe
+                {
+                    return (int)pCrtc->crtc_id;
+                }
+            }
+        }
+
+        public LinuxDisplay(int fd, IntPtr c, IntPtr e, IntPtr r)
+        {
+            FD = fd;
+            Connector = c;
+            Encoder = e;
+            Crtc = r;
+            unsafe
+            {
+                OriginalMode = pCrtc->mode; // in case we change resolution later on
+            }
+        }
+    }
+
+    class LinuxDisplayDriver 
+    {
+        readonly int FD;
+        readonly Dictionary<int, int> DisplayIds =
+            new Dictionary<int, int>();
+
+        public LinuxDisplayDriver(int fd)
+        {
+            Debug.Print("[KMS] Creating LinuxDisplayDriver for fd:{0}", fd);
+            Debug.Indent();
+            try
+            {
+                FD = fd;
+                UpdateDisplays(fd);
+            }
+            finally
+            {
+                Debug.Unindent();
+            }
+        }
+
+        /// \internal
+        /// <summary>
+        /// Queries the specified GPU for connected displays and, optionally,
+        /// returns the list of displays.
+        /// </summary>
+        /// <returns><c>true</c>, if at least one display is connected, <c>false</c> otherwise.</returns>
+        /// <param name="fd">The fd for the GPU to query, obtained through open("/dev/dri/card0").</param>
+        /// <param name="displays">
+        /// If not null, this will contain a list <see cref="LinuxDisplay"/> instances,
+        /// one for each connected display.
+        /// </param>
+        internal static bool QueryDisplays(int fd, List<LinuxDisplay> displays)
+        {
+            unsafe
+            {
+                bool has_displays = false;
+                if (displays != null)
+                {
+                    displays.Clear();
+                }
+
+                ModeRes* resources = (ModeRes*)Drm.ModeGetResources(fd);
+                if (resources == null)
+                {
+                    Debug.Print("[KMS] Drm.ModeGetResources failed.");
+                    return false;
+                }
+                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)
+                    {
+                        bool success = false;
+                        LinuxDisplay display = null;
+                        try
+                        {
+                            if (connector->connection == ModeConnection.Connected &&
+                            connector->count_modes > 0)
+                            {
+                                success = QueryDisplay(fd, connector, out display);
+                                has_displays |= success;
+                            }
+                        }
+                        catch (Exception e)
+                        {
+                            Debug.Print("[KMS] Failed to add display. Error: {0}", e);
+                        }
+
+                        if (success && displays != null)
+                        {
+                            displays.Add(display);
+                        }
+                        else
+                        {
+                            Drm.ModeFreeConnector((IntPtr)connector);
+                            connector = null;
+                        }
+                    }
+                }
+
+                return has_displays;
+            }
+        }
+
+        void UpdateDisplays(int fd)
+        {
+            unsafe
+            {
+                lock (this)
+                {
+                    AvailableDevices.Clear();
+                    DisplayIds.Clear();
+
+                    List<LinuxDisplay> displays = new List<LinuxDisplay>();
+                    if (QueryDisplays(fd, displays))
+                    {
+                        foreach (LinuxDisplay display in displays)
+                        {
+                            AddDisplay(display);
+                        }
+                    }
+
+                    if (AvailableDevices.Count == 0)
+                    {
+                        Debug.Print("[KMS] Failed to find any active displays");
+                    }
+                }
+            }
+        }
+
+        unsafe static ModeEncoder* GetEncoder(int fd, ModeConnector* c)
+        {
+            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 encoder;
+        }
+
+        unsafe static ModeCrtc* GetCrtc(int fd, ModeEncoder* encoder)
+        {
+            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 crtc;
+        }
+
+        unsafe static void GetModes(LinuxDisplay display, DisplayResolution[] modes, out DisplayResolution current)
+        {
+            int mode_count = display.pConnector->count_modes;
+            Debug.Print("[KMS] Display supports {0} mode(s)", mode_count);
+            for (int i = 0; i < mode_count; i++)
+            {
+                ModeInfo* mode = display.pConnector->modes + i;
+                if (mode != null)
+                {
+                    Debug.Print("Mode {0}: {1}x{2} @{3}", i,
+                        mode->hdisplay, mode->vdisplay, mode->vrefresh);
+                    DisplayResolution res = GetDisplayResolution(mode);
+                    modes[i] = res;
+                }
+            }
+
+            if (display.pCrtc->mode_valid != 0)
+            {
+                ModeInfo cmode = display.pCrtc->mode;
+                current = GetDisplayResolution(&cmode);
+            }
+            else
+            {
+                current = GetDisplayResolution(display.pConnector->modes);
+            }
+            Debug.Print("Current mode: {0}", current.ToString());
+        }
+
+        Rectangle GetBounds(DisplayResolution current)
+        {
+            // 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.
+            int x = AvailableDevices.Count == 0 ?
+                0 : AvailableDevices[AvailableDevices.Count - 1].Bounds.Right;
+            int y = 0;
+
+            return new Rectangle(
+                x, y, current.Width, current.Height);
+        }
+
+        void UpdateDisplayIndices(LinuxDisplay display, DisplayDevice device)
+        {
+            if (!DisplayIds.ContainsKey(display.Id))
+            {
+                Debug.Print("[KMS] Adding display {0} as {1}", display.Id, AvailableDevices.Count);
+                DisplayIds.Add(display.Id, AvailableDevices.Count);
+            }
+            int index = DisplayIds[display.Id];
+            if (index >= AvailableDevices.Count)
+            {
+                AvailableDevices.Add(device);
+            }
+            else
+            {
+                AvailableDevices[index] = device;
+            }
+        }
+
+        unsafe static bool QueryDisplay(int fd, ModeConnector* c, out LinuxDisplay display)
+        {
+            display = null;
+
+            // Find corresponding encoder
+            ModeEncoder* encoder = GetEncoder(fd, c);
+            if (encoder == null)
+                return false;
+
+            ModeCrtc* crtc = GetCrtc(fd, encoder);
+            if (crtc == null)
+                return false;
+
+            display = new LinuxDisplay(fd, (IntPtr)c, (IntPtr)encoder, (IntPtr)crtc);
+            return true;
+        }
+
+        unsafe void AddDisplay(LinuxDisplay display)
+        {
+            DisplayResolution[] modes = new DisplayResolution[display.pConnector->count_modes];
+            DisplayResolution current;
+            GetModes(display, modes, out current);
+
+            bool is_primary = AvailableDevices.Count == 0;
+            DisplayDevice device = new DisplayDevice(current, is_primary,
+                modes, GetBounds(current), display);
+
+            if (is_primary)
+            {
+                Primary = device;
+            }
+
+            UpdateDisplayIndices(display, device);
+
+            Debug.Print("[KMS] Added DisplayDevice {0}", device);
+        }
+
+        unsafe static DisplayResolution GetDisplayResolution(ModeInfo* mode)
+        {
+            return new DisplayResolution(
+                0, 0,
+                mode->hdisplay, mode->vdisplay,
+                32, // This is actually part of the framebuffer, not the DisplayResolution
+                mode->vrefresh);
+        }
+
+        unsafe static ModeInfo* GetModeInfo(LinuxDisplay display, DisplayResolution resolution)
+        {
+            for (int i = 0; i < display.pConnector->count_modes; i++)
+            {
+                ModeInfo* mode = display.pConnector->modes + i;
+                if (mode != null &&
+                    mode->hdisplay == resolution.Width &&
+                    mode->vdisplay == resolution.Height)
+                {
+                    return mode;
+                }
+            }
+            return null;
+        }
+
+        #region IDisplayDeviceDriver
+
+        public bool TryChangeResolution(DisplayDevice device, DisplayResolution resolution)
+        {
+            unsafe
+            {
+                LinuxDisplay display = (LinuxDisplay)device.Id;
+                ModeInfo* mode = GetModeInfo(display, resolution);
+                int connector_id = display.pConnector->connector_id;
+                if (mode != null)
+                {
+                    return Drm.ModeSetCrtc(FD, display.Id, 0, 0, 0,
+                        &connector_id, 1, mode) == 0;
+                }
+                return false;
+            }
+        }
+
+        public bool TryRestoreResolution(DisplayDevice device)
+        {
+            unsafe
+            {
+                LinuxDisplay display = (LinuxDisplay)device.Id;
+                ModeInfo mode = display.OriginalMode;
+                int connector_id = display.pConnector->connector_id;
+                return Drm.ModeSetCrtc(FD, display.Id, 0, 0, 0,
+                    &connector_id, 1, &mode) == 0;
+            }
+        }
+
+        #endregion
+    }
+}
+
diff --git a/testDrm/src/Linux/LinuxFactory.cs b/testDrm/src/Linux/LinuxFactory.cs
new file mode 100644 (file)
index 0000000..37d108a
--- /dev/null
@@ -0,0 +1,253 @@
+#region License
+//
+// LinuxFactory.cs
+//
+// Author:
+//       Stefanos A. <stapostol@gmail.com>
+//
+// 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.Diagnostics;
+using System.IO;
+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;
+        IntPtr gbm_device;
+        IntPtr egl_display;
+
+        IJoystickDriver2 JoystickDriver;
+        LinuxInput MouseKeyboardDriver;
+
+        const string gpu_path = "/dev/dri"; // card0, card1, ...
+
+        public LinuxFactory()
+        {
+            Debug.Print("[KMS] Using Linux/KMS backend.");
+        }
+
+        #region Private Members
+
+        int gpu_fd
+        {
+            get
+            {
+                lock (this)
+                {
+                    if (_fd == 0)
+                    {
+                        _fd = CreateDisplay(out gbm_device, out egl_display);
+                    }
+                    return _fd;
+                }
+            }
+        }
+
+        static int CreateDisplay(out IntPtr gbm_device, out IntPtr egl_display)
+        {
+            // Query all GPUs until we find one that has a connected display.
+            // This is necessary in multi-gpu systems, where only one GPU
+            // can output a signal.
+            // Todo: allow OpenTK to drive multiple GPUs
+            // Todo: allow OpenTK to run on an offscreen GPU
+            // Todo: allow the user to pick a GPU
+            int fd = 0;
+            gbm_device = IntPtr.Zero;
+            egl_display = IntPtr.Zero;
+
+            var files = Directory.GetFiles(gpu_path);
+            foreach (var gpu in files)
+            {
+                if (Path.GetFileName(gpu).StartsWith("card"))
+                {
+                    int test_fd = SetupDisplay(gpu, out gbm_device, out egl_display);
+                    if (test_fd >= 0)
+                    {
+                        try
+                        {
+                            if (LinuxDisplayDriver.QueryDisplays(test_fd, null))
+                            {
+                                fd = test_fd;
+                                break;
+                            }
+                        }
+                        catch (Exception e)
+                        {
+                            Debug.WriteLine(e.ToString());
+                        }
+
+                        Debug.Print("[KMS] GPU '{0}' is not connected, skipping.", gpu);
+                        Libc.close(test_fd);
+                    }
+                }
+            }
+
+            if (fd == 0)
+            {
+                Debug.Print("[Error] No valid GPU found, bailing out.");
+                throw new PlatformNotSupportedException();
+            }
+
+            return fd;
+        }
+
+        static int SetupDisplay(string gpu, out IntPtr gbm_device, out IntPtr egl_display)
+        {
+            Debug.Print("[KMS] Attempting to use gpu '{0}'.", gpu);
+
+            gbm_device = IntPtr.Zero;
+            egl_display = IntPtr.Zero;
+            
+            int fd = Libc.open(gpu, OpenFlags.ReadWrite | OpenFlags.CloseOnExec);
+            if (fd < 0)
+            {
+                Debug.Print("[KMS] Failed to open gpu");
+                return fd;
+            }
+            Debug.Print("[KMS] GPU '{0}' opened as fd:{1}", gpu, fd);
+
+            gbm_device = Gbm.CreateDevice(fd);
+            if (gbm_device == IntPtr.Zero)
+            {
+                throw new NotSupportedException("[KMS] Failed to create GBM device");
+            }
+            Debug.Print("[KMS] GBM {0:x} created successfully; ", gbm_device);
+
+            egl_display = Egl.GetDisplay(gbm_device);
+            if (egl_display == IntPtr.Zero)
+            {
+                throw new NotSupportedException("[KMS] Failed to create EGL display");
+            }
+            Debug.Print("[KMS] EGL display {0:x} created successfully", egl_display);
+
+            int major, minor;
+            if (!Egl.Initialize(egl_display, out major, out minor))
+            {
+                ErrorCode error = Egl.GetError();
+                throw new NotSupportedException("[KMS] Failed to initialize EGL display. Error code: " + error);
+            }
+            Debug.Print("[KMS] EGL {0}.{1} initialized successfully on display {2:x}", major, minor, egl_display);
+
+            return fd;
+        }
+
+        #endregion
+
+        #region Protected Members
+
+        protected override void Dispose(bool manual)
+        {
+            if (egl_display != IntPtr.Zero)
+            {
+                Debug.Print("[KMS] Terminating EGL.");
+                Egl.Terminate(egl_display);
+                egl_display = IntPtr.Zero;
+            }
+            if (gbm_device != IntPtr.Zero)
+            {
+                Debug.Print("[KMS] Destroying GBM device.");
+                Gbm.DestroyDevice(gbm_device);
+                gbm_device = IntPtr.Zero;
+            }
+            if (_fd >= 0)
+            {
+                Debug.Print("[KMS] Closing GPU fd.");
+                Libc.close(_fd);
+            }
+
+            base.Dispose(manual);
+        }
+
+        #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(egl_display, gbm_device, gpu_fd, x, y, width, height, title, mode, options, display_device);
+        }
+
+        public override IDisplayDeviceDriver CreateDisplayDeviceDriver()
+        {
+            return new LinuxDisplayDriver(gpu_fd);
+        }
+
+        public override IGraphicsContext CreateGLContext(GraphicsMode mode, IWindowInfo window, IGraphicsContext shareContext, bool directRendering, int major, int minor, GraphicsContextFlags flags)
+        {
+            return new LinuxGraphicsContext(mode, (LinuxWindowInfo)window, shareContext, major, minor, flags);
+        }
+
+        public override GraphicsContext.GetCurrentContextDelegate CreateGetCurrentGraphicsContext()
+        {
+            return (GraphicsContext.GetCurrentContextDelegate)delegate
+            {
+                return new ContextHandle(Egl.GetCurrentContext());
+            };
+        }
+
+        public override IKeyboardDriver2 CreateKeyboardDriver()
+        {
+            lock (this)
+            {
+                MouseKeyboardDriver = MouseKeyboardDriver ?? new LinuxInput();
+                return MouseKeyboardDriver;
+            }
+        }
+
+        public override IMouseDriver2 CreateMouseDriver()
+        {
+            lock (this)
+            {
+                MouseKeyboardDriver = MouseKeyboardDriver ?? new LinuxInput();
+                return MouseKeyboardDriver;
+            }
+        }
+
+        public override IJoystickDriver2 CreateJoystickDriver()
+        {
+            lock (this)
+            {
+                JoystickDriver = JoystickDriver ?? new LinuxJoystick();
+                return JoystickDriver;
+            }
+        }
+
+        public override OpenTK.Input.IGamePadDriver CreateGamePadDriver()
+        {
+            return new MappedGamePadDriver();
+        }
+
+        #endregion
+    }
+}
+
diff --git a/testDrm/src/Linux/LinuxGraphicsContext.cs b/testDrm/src/Linux/LinuxGraphicsContext.cs
new file mode 100644 (file)
index 0000000..779fd36
--- /dev/null
@@ -0,0 +1,302 @@
+#region License
+//
+// LinuxGraphicsContext.cs
+//
+// Author:
+//       thefiddler <stapostol@gmail.com>
+//
+// Copyright (c) 2006-2014 
+//
+// 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.Diagnostics;
+using System.Runtime.InteropServices;
+using OpenTK.Graphics;
+
+namespace OpenTK.Platform.Linux
+{
+    /// \internal
+    /// <summary>
+    /// Defines an IGraphicsContext implementation for the Linux KMS framebuffer.
+    /// For Linux/X11 and other Unix operating systems, use the more generic
+    /// <see cref="OpenTK.Platform.Egl.EglUnixContext"/> instead.
+    /// </summary>
+    /// <remarks>
+    /// Note: to display our results, we need to allocate a GBM framebuffer
+    /// and point the scanout address to that via Drm.ModeSetCrtc.
+    /// </remarks>
+    class LinuxGraphicsContext : Egl.EglUnixContext
+    {
+        BufferObject bo, bo_next;
+        int fd;
+        bool is_flip_queued;
+        int swap_interval;
+
+        public LinuxGraphicsContext(GraphicsMode mode, LinuxWindowInfo window, IGraphicsContext sharedContext,
+            int major, int minor, GraphicsContextFlags flags)
+            : base(mode, window, sharedContext, major, minor, flags)
+        {
+            if (mode.Buffers < 1)
+                throw new ArgumentException();
+            fd = window.FD;
+
+            PageFlip = HandlePageFlip;
+            PageFlipPtr = Marshal.GetFunctionPointerForDelegate(PageFlip);
+        }
+
+        public override void SwapBuffers()
+        {
+            base.SwapBuffers();
+
+            if (is_flip_queued)
+            {
+                // Todo: if we don't wait for the page flip,
+                // we drop all rendering buffers and get a crash
+                // in Egl.SwapBuffers(). We need to fix that
+                // before we can disable vsync.
+                WaitFlip(true); // WaitFlip(SwapInterval > 0)
+                if (is_flip_queued)
+                {
+                    Debug.Print("[KMS] Dropping frame");
+                    return;
+                }
+            }
+
+            bo_next = LockSurface();
+            int fb = GetFramebuffer(bo_next);
+            QueueFlip(fb);
+        }
+
+        public override void Update(IWindowInfo window)
+        {
+            WaitFlip(true);
+
+            base.SwapBuffers();
+
+            bo = LockSurface();
+            int fb = GetFramebuffer(bo);
+            SetScanoutRegion(fb);
+        }
+
+        public override int SwapInterval
+        {
+            get
+            {
+                return swap_interval;
+            }
+            set
+            {
+                // We only support a SwapInterval of 0 (immediate)
+                // or 1 (vsynced).
+                // Todo: add support for SwapInterval of -1 (adaptive).
+                // This requires a small change in WaitFlip().
+                swap_interval = MathHelper.Clamp(value, 0, 1);
+            }
+        }
+
+        void WaitFlip(bool block)
+        {
+            PollFD fds = new PollFD();
+            fds.fd = fd;
+            fds.events = PollFlags.In;
+
+            EventContext evctx = new EventContext();
+            evctx.version = EventContext.Version;
+            evctx.page_flip_handler = PageFlipPtr;
+
+            int timeout = block ? -1 : 0;
+
+            while (is_flip_queued)
+            {
+                fds.revents = 0;
+                if (Libc.poll(ref fds, 1, timeout) < 0)
+                    break;
+
+                if ((fds.revents & (PollFlags.Hup | PollFlags.Error)) != 0)
+                    break;
+
+                if ((fds.revents & PollFlags.In) != 0)
+                    Drm.HandleEvent(fd, ref evctx);
+                else
+                    break;
+            }
+
+            // Page flip has taken place, update buffer objects
+            if (!is_flip_queued)
+            {
+                IntPtr gbm_surface = WindowInfo.Handle;
+                Gbm.ReleaseBuffer(gbm_surface, bo);
+                bo = bo_next;
+            }
+        }
+
+        void QueueFlip(int buffer)
+        {
+            LinuxWindowInfo wnd = WindowInfo as LinuxWindowInfo;
+            if (wnd == null)
+                throw new InvalidOperationException();
+
+            unsafe
+            {
+                int ret = Drm.ModePageFlip(fd, wnd.DisplayDevice.Id, buffer,
+                    PageFlipFlags.FlipEvent, IntPtr.Zero);
+
+                if (ret < 0)
+                {
+                    Debug.Print("[KMS] Failed to enqueue framebuffer flip. Error: {0}", ret);
+                }
+
+                is_flip_queued = true;
+            }
+        }
+
+        void SetScanoutRegion(int buffer)
+        {
+            LinuxWindowInfo wnd = WindowInfo as LinuxWindowInfo;
+            if (wnd == null)
+                throw new InvalidOperationException();
+
+            unsafe
+            {
+                ModeInfo* mode = wnd.DisplayDevice.pConnector->modes;
+                int connector_id = wnd.DisplayDevice.pConnector->connector_id;
+                int crtc_id = wnd.DisplayDevice.Id;
+
+                int x = 0;
+                int y = 0;
+                int connector_count = 1;
+                int ret = Drm.ModeSetCrtc(fd, crtc_id, buffer, x, y,
+                    &connector_id, connector_count, mode);
+
+                if (ret != 0)
+                {
+                    Debug.Print("[KMS] Drm.ModeSetCrtc{0}, {1}, {2}, {3}, {4:x}, {5}, {6:x}) failed. Error: {7}",
+                        fd, crtc_id, buffer, x, y, (IntPtr)connector_id, connector_count, (IntPtr)mode, ret);
+                }
+            }
+        }
+
+        BufferObject LockSurface()
+        {
+            IntPtr gbm_surface = WindowInfo.Handle;
+            return Gbm.LockFrontBuffer(gbm_surface);
+        }
+
+        int GetFramebuffer(BufferObject bo)
+        {
+            if (bo == BufferObject.Zero)
+                goto fail;
+
+            int bo_handle = bo.Handle;
+            if (bo_handle == 0)
+            {
+                Debug.Print("[KMS] Gbm.BOGetHandle({0:x}) failed.", bo);
+                goto fail;
+            }
+
+            int width = bo.Width;
+            int height = bo.Height;
+            int bpp = Mode.ColorFormat.BitsPerPixel;
+            int depth = Mode.Depth;
+            int stride = bo.Stride;
+
+            if (width == 0 || height == 0 || bpp == 0)
+            {
+                Debug.Print("[KMS] Invalid framebuffer format: {0}x{1} {2} {3} {4}",
+                    width, height, stride, bpp, depth);
+                goto fail;
+            }
+
+            int buffer;
+            int ret = Drm.ModeAddFB(
+                fd, width, height,
+                (byte)depth, (byte)bpp, stride, bo_handle,
+                out buffer);
+            if (ret != 0)
+            {
+                Debug.Print("[KMS] Drm.ModeAddFB({0}, {1}, {2}, {3}, {4}, {5}, {6}) failed. Error: {7}",
+                    fd, width, height, depth, bpp, stride, bo_handle, ret);
+                goto fail;
+            }
+
+            bo.SetUserData((IntPtr)buffer, DestroyFB);
+            return buffer;
+
+            fail:
+            Debug.Print("[Error] Failed to create framebuffer.");
+            return -1;
+        }
+
+        readonly IntPtr PageFlipPtr;
+        readonly PageFlipCallback PageFlip;
+        void HandlePageFlip(int fd,
+            int sequence,
+            int tv_sec,
+            int tv_usec,
+            IntPtr user_data)
+        {
+            is_flip_queued = false;
+        }
+
+        static readonly DestroyUserDataCallback DestroyFB = HandleDestroyFB;
+        static void HandleDestroyFB(BufferObject bo, IntPtr data)
+        {
+            IntPtr gbm = bo.Device;
+            int fb = data.ToInt32();
+            Debug.Print("[KMS] Destroying framebuffer {0}", fb);
+
+            if (fb != 0)
+            {
+                Drm.ModeRmFB(Gbm.DeviceGetFD(gbm), fb);
+            }
+        }
+
+        protected override void Dispose(bool manual)
+        {
+            if (manual)
+            {
+                // Reset the scanout region
+                LinuxWindowInfo wnd = WindowInfo as LinuxWindowInfo;
+                if (wnd != null)
+                {
+                    unsafe
+                    {
+                        int connector_id = wnd.DisplayDevice.pConnector->connector_id;
+                        ModeInfo mode = wnd.DisplayDevice.OriginalMode;
+                        Drm.ModeSetCrtc(fd,
+                            wnd.DisplayDevice.pCrtc->crtc_id,
+                            wnd.DisplayDevice.pCrtc->buffer_id,
+                            wnd.DisplayDevice.pCrtc->x,
+                            wnd.DisplayDevice.pCrtc->y,
+                            &connector_id,
+                            1,
+                            &mode);
+                    }
+                }
+            }
+            base.Dispose(manual);
+        }
+    }
+}
+
+
+
diff --git a/testDrm/src/Linux/LinuxInput.cs b/testDrm/src/Linux/LinuxInput.cs
new file mode 100644 (file)
index 0000000..ce5457c
--- /dev/null
@@ -0,0 +1,721 @@
+#region License
+//
+// LinuxKeyboardLibInput.cs
+//
+// Author:
+//       Stefanos A. <stapostol@gmail.com>
+//
+// 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;
+#if !MINIMAL
+using System.Drawing;
+#endif
+using System.Runtime.InteropServices;
+using System.Threading;
+using OpenTK.Input;
+
+namespace OpenTK.Platform.Linux
+{
+    class LinuxInput : IKeyboardDriver2, IMouseDriver2, IDisposable
+    {
+        class DeviceBase
+        {
+            readonly IntPtr Device;
+            string name;
+            string output;
+            string logical_seat;
+            string physical_seat;
+
+            public DeviceBase(IntPtr device, int id)
+            {
+                Device = device;
+                Id = id;
+            }
+
+            public int Id
+            {
+                get
+                {
+                    return GetId(Device);
+                }
+                set
+                {
+                    LibInput.DeviceSetData(Device, (IntPtr)value);
+                }
+            }
+
+            public string Name
+            {
+                get
+                {
+                    name = name ?? LibInput.DeviceGetName(Device);
+                    return name;
+                }
+            }
+
+            public IntPtr Seat
+            {
+                get
+                {
+                    return LibInput.DeviceGetSeat(Device);
+                }
+            }
+
+            public string LogicalSeatName
+            {
+                get
+                {
+                    logical_seat = logical_seat ?? LibInput.SeatGetLogicalName(Seat);
+                    return logical_seat;
+                }
+            }
+
+            public string PhysicalSeatName
+            {
+                get
+                {
+                    physical_seat = physical_seat ?? LibInput.SeatGetPhysicalName(Seat);
+                    return physical_seat;
+                }
+            }
+
+            public string Output
+            {
+                get
+                {
+                    output = output ?? LibInput.DeviceGetOutputName(Device);
+                    return output;
+                }
+            }
+        }
+
+        class KeyboardDevice : DeviceBase
+        {
+            public KeyboardState State;
+
+            public KeyboardDevice(IntPtr device, int id)
+                : base(device, id)
+            {
+            }
+        }
+
+        class MouseDevice : DeviceBase
+        {
+            public MouseState State;
+
+            public MouseDevice(IntPtr device, int id)
+                : base(device, id)
+            {
+            }
+        }
+
+        static readonly object Sync = new object();
+        static readonly Key[] KeyMap = Evdev.KeyMap;
+        static long DeviceFDCount;
+
+        // libinput returns various devices with keyboard/pointer even though
+        // they are not traditional keyboards/mice (for example "Integrated Camera"
+        // can be detected as a keyboard.)
+        // Since there is no API to retrieve actual device capabilities,
+        // we add all detected devices to a "candidate" list and promote them
+        // to an actual keyboard/mouse only when we receive a valid input event.
+        // This is far from optimal, but it appears to be the only viable solution
+        // unless a new API is added to libinput.
+        DeviceCollection<KeyboardDevice> KeyboardCandidates = new DeviceCollection<KeyboardDevice>();
+        DeviceCollection<MouseDevice> MouseCandidates = new DeviceCollection<MouseDevice>();
+        DeviceCollection<KeyboardDevice> Keyboards = new DeviceCollection<KeyboardDevice>();
+        DeviceCollection<MouseDevice> Mice = new DeviceCollection<MouseDevice>();
+
+        // Todo: do we need to maintain the geometry of each display separately?
+        Rectangle bounds;
+
+        // Global mouse cursor state
+        Vector2 CursorPosition = Vector2.Zero;
+        // Global mouse cursor offset (used for emulating SetPosition)
+        Vector2 CursorOffset = Vector2.Zero;
+
+        IntPtr udev;
+        IntPtr input_context;
+        InputInterface input_interface = new InputInterface(
+            OpenRestricted, CloseRestricted);
+        int fd;
+        Thread input_thread;
+        long exit;
+
+        public LinuxInput()
+        {
+            Debug.Print("[Linux] Initializing {0}", GetType().Name);
+            Debug.Indent();
+            try
+            {
+                Semaphore ready = new Semaphore(0, 1);
+                input_thread = new Thread(InputThreadLoop);
+                input_thread.IsBackground = true;
+                input_thread.Start(ready);
+
+                // Wait until the input thread is ready.
+                // Note: it would be nicer if we could avoid this.
+                // however we need to marshal errors back to the caller
+                // as exceptions.
+                // Todo: in a future version, we should add an "Application" object
+                // to handle all communication with the OS (including event processing.)
+                // Once we do that, we can remove all separate input threads.
+                ready.WaitOne();
+                if (exit != 0)
+                {
+                    throw new NotSupportedException();
+                }
+            }
+            finally
+            {
+                Debug.Print("Initialization {0}", exit == 0 ?
+                    "complete" : "failed");
+                Debug.Unindent();
+            }
+        }
+
+        #region Private Members
+
+        static CloseRestrictedCallback CloseRestricted = CloseRestrictedHandler;
+        static void CloseRestrictedHandler(int fd, IntPtr data)
+        {
+            Debug.Print("[Input] Closing fd {0}", fd);
+            int ret = Libc.close(fd);
+
+            if (ret < 0)
+            {
+                Debug.Print("[Input] Failed to close fd {0}. Error: {1}", fd, ret);
+            }
+            else
+            {
+                Interlocked.Decrement(ref DeviceFDCount);
+            }
+        }
+
+        static OpenRestrictedCallback OpenRestricted = OpenRestrictedHandler;
+        static int OpenRestrictedHandler(IntPtr path, int flags, IntPtr data) 
+        {
+            int fd = Libc.open(path, (OpenFlags)flags);
+            Debug.Print("[Input] Opening '{0}' with flags {1}. fd:{2}",
+                Marshal.PtrToStringAnsi(path), (OpenFlags)flags, fd);
+
+            if (fd >= 0)
+            {
+                Interlocked.Increment(ref DeviceFDCount);
+            }
+
+            return fd;
+        }
+
+        void InputThreadLoop(object semaphore)
+        {
+            Debug.Print("[Input] Running on thread {0}", Thread.CurrentThread.ManagedThreadId);
+            Setup();
+
+            // Inform the parent thread that initialization has completed successfully
+            (semaphore as Semaphore).Release();
+            Debug.Print("[Input] Released main thread.", input_context);
+
+            // Use a blocking poll for input messages, in order to reduce CPU usage
+            PollFD poll_fd = new PollFD();
+            poll_fd.fd = fd;
+            poll_fd.events = PollFlags.In;
+            Debug.Print("[Input] Created PollFD({0}, {1})", poll_fd.fd, poll_fd.events);
+
+            Debug.Print("[Input] Entering input loop.", poll_fd.fd, poll_fd.events);
+            while (Interlocked.Read(ref exit) == 0)
+            {
+                int ret = Libc.poll(ref poll_fd, 1, -1);
+                ErrorNumber error = (ErrorNumber)Marshal.GetLastWin32Error();
+                bool is_error =
+                    ret < 0 && !(error == ErrorNumber.Again || error == ErrorNumber.Interrupted) ||
+                    (poll_fd.revents & (PollFlags.Hup | PollFlags.Error | PollFlags.Invalid)) != 0;
+
+                // We need to query the desktop bounds in order to position the mouse cursor correctly.
+                // This value will be used for the current bunch of input events. If a monitor changes
+                // resolution in the meantime, we might be slightly off in our calculations - this error
+                // will be corrected when the next bunch of input events arrives.
+                UpdateDisplayBounds();
+
+                if (ret > 0 && (poll_fd.revents & (PollFlags.In | PollFlags.Pri)) != 0)
+                {
+                    ProcessEvents(input_context);
+                }
+
+                if (is_error)
+                {
+                    Debug.Print("[Input] Exiting input loop {0} due to poll error [ret:{1} events:{2}]. Error: {3}.",
+                        input_thread.ManagedThreadId, ret, poll_fd.revents, error);
+                    Interlocked.Increment(ref exit);
+                }
+            }
+            Debug.Print("[Input] Exited input loop.", poll_fd.fd, poll_fd.events);
+        }
+
+        void UpdateDisplayBounds()
+        {
+            bounds = Rectangle.Empty;
+            for (DisplayIndex i = DisplayIndex.First; i < DisplayIndex.Sixth; i++)
+            {
+                DisplayDevice display = DisplayDevice.GetDisplay(i);
+                if (display != null)
+                {
+                    bounds = Rectangle.Union(bounds, display.Bounds);
+                }
+            }
+        }
+
+        void UpdateCursor()
+        {
+            Point p = new Point(
+                (int)Math.Round(CursorPosition.X + CursorOffset.X),
+                (int)Math.Round(CursorPosition.Y + CursorOffset.Y));
+
+            DisplayDevice display = DisplayDevice.FromPoint(p.X, p.Y) ?? DisplayDevice.Default;
+            if (display != null)
+            {
+                LinuxDisplay d = (LinuxDisplay)display.Id;
+                Drm.MoveCursor(d.FD, d.Id, p.X, p.Y);
+            }
+        }
+
+        void Setup()
+        {
+            // Todo: add static path fallback when udev is not installed.
+            udev = Udev.New();
+            if (udev == IntPtr.Zero)
+            {
+                Debug.Print("[Input] Udev.New() failed.");
+                Interlocked.Increment(ref exit);
+                return;
+            }
+            Debug.Print("[Input] Udev.New() = {0:x}", udev);
+
+            input_context = LibInput.CreateContext(input_interface, IntPtr.Zero, udev);
+            if (input_context == IntPtr.Zero)
+            {
+                Debug.Print("[Input] LibInput.CreateContext({0:x}) failed.", udev);
+                Interlocked.Increment(ref exit);
+                return;
+            }
+            Debug.Print("[Input] LibInput.CreateContext({0:x}) = {1:x}", udev, input_context);
+
+            string seat_id = "seat0";
+            int seat_assignment = LibInput.AssignSeat(input_context, seat_id);
+            if (seat_assignment == -1)
+            {
+                Debug.Print("[Input] LibInput.AssignSeat({0:x}) = {1} failed.", input_context, seat_id);
+                Interlocked.Increment(ref exit);
+                return;
+            }
+            Debug.Print("[Input] LibInput.AssignSeat({0:x}) = {1}", input_context, seat_id);
+
+            fd = LibInput.GetFD(input_context);
+            if (fd < 0)
+            {
+                Debug.Print("[Input] LibInput.GetFD({0:x}) failed.", input_context);
+                Interlocked.Increment(ref exit);
+                return;
+            }
+            Debug.Print("[Input] LibInput.GetFD({0:x}) = {1}.", input_context, fd);
+
+            ProcessEvents(input_context);
+            LibInput.Resume(input_context);
+            Debug.Print("[Input] LibInput.Resume({0:x})", input_context);
+
+            if (Interlocked.Read(ref DeviceFDCount) <= 0)
+            {
+                Debug.Print("[Error] Failed to open any input devices.");
+                Debug.Print("[Error] Ensure that you have access to '/dev/input/event*'.");
+                Interlocked.Increment(ref exit);
+            }
+        }
+
+        void ProcessEvents(IntPtr input_context)
+        {
+            // Process all events in the event queue
+            while (true)
+            {
+                // Data available
+                int ret = LibInput.Dispatch(input_context);
+                if (ret != 0)
+                {
+                    Debug.Print("[Input] LibInput.Dispatch({0:x}) failed. Error: {1}",
+                        input_context, ret);
+                    break;
+                }
+
+                IntPtr pevent = LibInput.GetEvent(input_context);
+                if (pevent == IntPtr.Zero)
+                {
+                    break;
+                }
+
+                IntPtr device = LibInput.GetDevice(pevent);
+                InputEventType type = LibInput.GetEventType(pevent);
+
+                lock (Sync)
+                {
+                    switch (type)
+                    {
+                        case InputEventType.DeviceAdded:
+                            HandleDeviceAdded(input_context, device);
+                            break;
+
+                        case InputEventType.DeviceRemoved:
+                            HandleDeviceRemoved(input_context, device);
+                            break;
+
+                        case InputEventType.KeyboardKey:
+                            HandleKeyboard(GetKeyboard(device), LibInput.GetKeyboardEvent(pevent));
+                            break;
+
+                        case InputEventType.PointerAxis:
+                            HandlePointerAxis(GetMouse(device), LibInput.GetPointerEvent(pevent));
+                            break;
+
+                        case InputEventType.PointerButton:
+                            HandlePointerButton(GetMouse(device), LibInput.GetPointerEvent(pevent));
+                            break;
+
+                        case InputEventType.PointerMotion:
+                            HandlePointerMotion(GetMouse(device), LibInput.GetPointerEvent(pevent));
+                            break;
+
+                        case InputEventType.PointerMotionAbsolute:
+                            HandlePointerMotionAbsolute(GetMouse(device), LibInput.GetPointerEvent(pevent));
+                            break;
+                    }
+                }
+
+                LibInput.DestroyEvent(pevent);
+            }
+        }
+
+        void HandleDeviceAdded(IntPtr context, IntPtr device)
+        {
+            if (LibInput.DeviceHasCapability(device, DeviceCapability.Keyboard))
+            {
+                KeyboardDevice keyboard = new KeyboardDevice(device, Keyboards.Count);
+                KeyboardCandidates.Add(keyboard.Id, keyboard);
+                Debug.Print("[Input] Added keyboard device {0} '{1}' on '{2}' ('{3}')",
+                    keyboard.Id, keyboard.Name, keyboard.LogicalSeatName, keyboard.PhysicalSeatName);
+            }
+
+            if (LibInput.DeviceHasCapability(device, DeviceCapability.Mouse))
+            {
+                MouseDevice mouse = new MouseDevice(device, Mice.Count);
+                MouseCandidates.Add(mouse.Id, mouse);
+                Debug.Print("[Input] Added mouse device {0} '{1}' on '{2}' ('{3}')",
+                    mouse.Id, mouse.Name, mouse.LogicalSeatName, mouse.PhysicalSeatName);
+            }
+
+            if (LibInput.DeviceHasCapability(device, DeviceCapability.Touch))
+            {
+                Debug.Print("[Input] Todo: touch device.");
+            }
+        }
+
+        void HandleDeviceRemoved(IntPtr context, IntPtr device)
+        {
+            if (LibInput.DeviceHasCapability(device, DeviceCapability.Keyboard))
+            {
+                int id = GetId(device);
+                Keyboards.TryRemove(id);
+                KeyboardCandidates.TryRemove(id);
+            }
+
+            if (LibInput.DeviceHasCapability(device, DeviceCapability.Mouse))
+            {
+                int id = GetId(device);
+                Mice.TryRemove(id);
+                MouseCandidates.TryRemove(id);
+            }
+        }
+
+        void HandleKeyboard(KeyboardDevice device, KeyboardEvent e)
+        {
+            if (device != null)
+            {
+                device.State.SetIsConnected(true);
+                Debug.Print("[Input] Added keyboard {0}", device.Id);
+
+                Key key = Key.Unknown;
+                uint raw = e.Key;
+                if (raw >= 0 && raw < KeyMap.Length)
+                {
+                    key = KeyMap[raw];
+                }
+
+                if (key == Key.Unknown)
+                {
+                    Debug.Print("[Linux] Unknown key with code '{0}'", raw);
+                }
+
+                device.State.SetKeyState(key, e.KeyState == KeyState.Pressed);
+            }
+        }
+
+        void HandlePointerAxis(MouseDevice mouse, PointerEvent e)
+        {
+            if (mouse != null)
+            {
+                mouse.State.SetIsConnected(true);
+
+                if (e.HasAxis(PointerAxis.HorizontalScroll))
+                {
+                    mouse.State.SetScrollRelative((float)e.AxisValue(PointerAxis.HorizontalScroll), 0);
+                }
+                if (e.HasAxis(PointerAxis.VerticalScroll))
+                {
+                    mouse.State.SetScrollRelative(0, (float)e.AxisValue(PointerAxis.VerticalScroll));
+                }
+            }
+        }
+
+        void HandlePointerButton(MouseDevice mouse, PointerEvent e)
+        {
+            if (mouse != null)
+            {
+                mouse.State.SetIsConnected(true);
+
+                MouseButton button = Evdev.GetMouseButton(e.Button);
+                ButtonState state = e.ButtonState;
+                mouse.State[(MouseButton)button] = state == ButtonState.Pressed;
+            }
+        }
+
+        void HandlePointerMotion(MouseDevice mouse, PointerEvent e)
+        {
+            Vector2 delta = new Vector2((float)e.DeltaX, (float)e.DeltaY);
+            if (mouse != null)
+            {
+                mouse.State.SetIsConnected(true);
+                mouse.State.Position += delta;
+            }
+
+            CursorPosition = new Vector2(
+                MathHelper.Clamp(CursorPosition.X + delta.X, bounds.Left, bounds.Right - 1),
+                MathHelper.Clamp(CursorPosition.Y + delta.Y, bounds.Top, bounds.Bottom - 1));
+            UpdateCursor();
+        }
+
+        void HandlePointerMotionAbsolute(MouseDevice mouse, PointerEvent e)
+        {
+            if (mouse != null)
+            {
+                mouse.State.SetIsConnected(true);
+                mouse.State.Position = new Vector2((float)e.X, (float)e.Y);
+            }
+
+            CursorPosition = new Vector2(
+                (float)e.TransformedX(bounds.Width),
+                (float)e.TransformedY(bounds.Height));
+            UpdateCursor();
+        }
+
+        static int GetId(IntPtr device)
+        {
+            return LibInput.DeviceGetData(device).ToInt32();
+        }
+
+        KeyboardDevice GetKeyboard(IntPtr device)
+        {
+            int id = GetId(device);
+            KeyboardDevice keyboard = KeyboardCandidates.FromHardwareId(id);
+            if (keyboard != null)
+            {
+                Keyboards.Add(id, keyboard);
+            }
+            else
+            {
+                Debug.Print("[Input] Keyboard {0} does not exist in device list.", id);
+            }
+            return keyboard;
+        }
+
+        MouseDevice GetMouse(IntPtr device)
+        {
+            int id = GetId(device);
+            MouseDevice mouse = MouseCandidates.FromHardwareId(id);
+            if (mouse != null)
+            {
+                Mice.Add(id, mouse);
+            }
+            else
+            {
+                Debug.Print("[Input] Mouse {0} does not exist in device list.", id);
+            }
+            return mouse;
+        }
+
+        #endregion
+
+        #region IKeyboardDriver2 implementation
+
+        KeyboardState IKeyboardDriver2.GetState()
+        {
+            lock (Sync)
+            {
+                KeyboardState state = new KeyboardState();
+                foreach (KeyboardDevice keyboard in Keyboards)
+                {
+                    state.MergeBits(keyboard.State);
+                }
+                return state;
+            }
+        }
+
+        KeyboardState IKeyboardDriver2.GetState(int index)
+        {
+            lock (Sync)
+            {
+                KeyboardDevice device = Keyboards.FromIndex(index);
+                if (device != null)
+                {
+                    return device.State;
+                }
+                else
+                {
+                    return new KeyboardState();
+                }
+            }
+        }
+
+        string IKeyboardDriver2.GetDeviceName(int index)
+        {
+            lock (Sync)
+            {
+                KeyboardDevice device = Keyboards.FromIndex(index);
+                if (device != null)
+                {
+                    return device.Name;
+                }
+                else
+                {
+                    return String.Empty;
+                }
+            }
+        }
+
+        #endregion
+
+        #region IMouseDriver2 implementation
+
+        MouseState IMouseDriver2.GetState()
+        {
+            lock (Sync)
+            {
+                MouseState state = new MouseState();
+                foreach (MouseDevice mouse in Mice)
+                {
+                    state.MergeBits(mouse.State);
+                }
+                return state;
+            }
+        }
+
+        MouseState IMouseDriver2.GetState(int index)
+        {
+            lock (Sync)
+            {
+                MouseDevice device = Mice.FromIndex(index);
+                if (device != null)
+                {
+                    return device.State;
+                }
+                else
+                {
+                    return new MouseState();
+                }
+            }
+        }
+
+        void IMouseDriver2.SetPosition(double x, double y)
+        {
+            // Todo: this does not appear to be supported in libinput.
+            // We will have to emulate this in the KMS mouse rendering code.
+            CursorOffset = new Vector2(
+                (float)x - CursorPosition.X,
+                (float)y - CursorPosition.Y);
+            UpdateCursor();
+        }
+
+        MouseState IMouseDriver2.GetCursorState()
+        {
+            MouseState state = (this as IMouseDriver2).GetState();
+            state.Position = CursorPosition + CursorOffset;
+            return state;
+        }
+
+        #endregion
+
+        #region IDisposable implementation
+
+        public void Dispose()
+        {
+            Dispose(true);
+            GC.SuppressFinalize(this);
+        }
+
+        void Dispose(bool disposing)
+        {
+            if (disposing)
+            {
+                if (input_context != IntPtr.Zero)
+                {
+                    Debug.Print("[Input] Destroying libinput context");
+                    LibInput.Suspend(input_context);
+                    Interlocked.Increment(ref exit);
+
+                    LibInput.DestroyContext(input_context);
+                    input_context = IntPtr.Zero;
+                }
+
+                if (udev != IntPtr.Zero)
+                {
+                    Debug.Print("[Input] Destroying udev context");
+                    Udev.Destroy(udev);
+                    udev = IntPtr.Zero;
+                }
+
+                input_interface = null;
+            }
+            else
+            {
+                Debug.Print("[Input] {0} leaked. Did you forget to call Dispose()?", GetType().FullName);
+            }
+        }
+
+        ~LinuxInput()
+        {
+            Dispose(false);
+        }
+
+        #endregion
+    }
+}
+
diff --git a/testDrm/src/Linux/LinuxJoystick.cs b/testDrm/src/Linux/LinuxJoystick.cs
new file mode 100644 (file)
index 0000000..fa47bdf
--- /dev/null
@@ -0,0 +1,533 @@
+#region License
+//
+// The Open Toolkit Library License
+//
+// Copyright (c) 2006 - 2008 the Open Toolkit library, except where noted.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights to 
+// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+// the Software, and to permit persons to whom the Software is furnished to do
+// so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Text;
+using OpenTK.Input;
+
+namespace OpenTK.Platform.Linux
+{
+    struct AxisInfo
+    {
+        public JoystickAxis Axis;
+        public InputAbsInfo Info;
+    }
+
+    class LinuxJoystickDetails
+    {
+        public Guid Guid;
+        public string Name;
+        public int FileDescriptor;
+        public int PathIndex; // e.g. "0" for "/dev/input/event0". Used as a hardware id
+        public JoystickState State;
+        public JoystickCapabilities Caps;
+
+        public readonly Dictionary<EvdevAxis, AxisInfo> AxisMap =
+            new Dictionary<EvdevAxis, AxisInfo>();
+        public readonly Dictionary<EvdevButton, int> ButtonMap =
+            new Dictionary<EvdevButton, int>();
+    }
+
+    sealed class LinuxJoystick : IJoystickDriver2
+    {
+        #region Fields
+
+        static readonly HatPosition[,] HatPositions = new HatPosition[,]
+        {
+            { HatPosition.UpLeft, HatPosition.Up, HatPosition.UpRight },
+            { HatPosition.Left, HatPosition.Centered, HatPosition.Right },
+            { HatPosition.DownLeft, HatPosition.Down, HatPosition.DownRight }
+        };
+
+        readonly object sync = new object();
+
+        readonly FileSystemWatcher watcher = new FileSystemWatcher();
+
+        readonly DeviceCollection<LinuxJoystickDetails> Sticks =
+            new DeviceCollection<LinuxJoystickDetails>();
+
+        bool disposed;
+
+        #endregion
+
+        #region Constructors
+
+        public LinuxJoystick()
+        {
+            string path =
+                Directory.Exists(JoystickPath) ? JoystickPath :
+                Directory.Exists(JoystickPathLegacy) ? JoystickPathLegacy :
+                String.Empty;
+
+            if (!String.IsNullOrEmpty(path))
+            {
+                watcher.Path = path;
+
+                watcher.Created += JoystickAdded;
+                watcher.Deleted += JoystickRemoved;
+                watcher.EnableRaisingEvents = true;
+
+                OpenJoysticks(path);
+            }
+        }
+
+        #endregion
+
+        #region Private Members
+
+        void OpenJoysticks(string path)
+        {
+            lock (sync)
+            {
+                foreach (string file in Directory.GetFiles(path))
+                {
+                    LinuxJoystickDetails stick = OpenJoystick(file);
+                    if (stick != null)
+                    {
+                        Sticks.Add(stick.PathIndex, stick);
+                    }
+                }
+            }
+        }
+
+        int GetJoystickNumber(string path)
+        {
+            const string evdev = "event";
+            if (path.StartsWith(evdev))
+            {
+                int num;
+                if (Int32.TryParse(path.Substring(evdev.Length), out num))
+                {
+                    return num;
+                }
+            }
+            return -1;
+        }
+
+        void JoystickAdded(object sender, FileSystemEventArgs e)
+        {
+            lock (sync)
+            {
+                OpenJoystick(e.FullPath);
+            }
+        }
+
+        void JoystickRemoved(object sender, FileSystemEventArgs e)
+        {
+            lock (sync)
+            {
+                string file = Path.GetFileName(e.FullPath);
+                int number = GetJoystickNumber(file);
+                if (number != -1)
+                {
+                    var stick = Sticks.FromHardwareId(number);
+                    if (stick != null)
+                    {
+                        CloseJoystick(stick);
+                    }
+                }
+            }
+        }
+
+        #endregion
+
+        #region Private Members
+
+        Guid CreateGuid(EvdevInputId id, string name)
+        {
+            // Note: the first 8bytes of the Guid are byteswapped
+            // in three parts when using `new Guid(byte[])`:
+            // (int, short, short).
+            // We need to take that into account to match the expected
+            // Guid in the database. Ugh.
+
+            byte[] bytes = new byte[16];
+
+            int i = 0;
+            byte[] bus = BitConverter.GetBytes((int)id.BusType);
+            bytes[i++] = bus[3];
+            bytes[i++] = bus[2];
+            bytes[i++] = bus[1];
+            bytes[i++] = bus[0];
+
+            if (id.Vendor != 0 && id.Product != 0 && id.Version != 0)
+            {
+                byte[] vendor = BitConverter.GetBytes(id.Vendor);
+                byte[] product = BitConverter.GetBytes(id.Product);
+                byte[] version = BitConverter.GetBytes(id.Version);
+                bytes[i++] = vendor[1];
+                bytes[i++] = vendor[0];
+                bytes[i++] = 0;
+                bytes[i++] = 0;
+                bytes[i++] = product[0]; // no byteswapping
+                bytes[i++] = product[1];
+                bytes[i++] = 0;
+                bytes[i++] = 0;
+                bytes[i++] = version[0]; // no byteswapping
+                bytes[i++] = version[1];
+                bytes[i++] = 0;
+                bytes[i++] = 0;
+            }
+            else
+            {
+                for (int j = 0; j < bytes.Length - i; j++)
+                {
+                    bytes[i + j] = (byte)name[j];
+                }
+            }
+
+            return new Guid(bytes);
+        }
+
+        unsafe static bool TestBit(byte* ptr, int bit)
+        {
+            int byte_offset = bit / 8;
+            int bit_offset = bit % 8;
+            return (*(ptr + byte_offset) & (1 << bit_offset)) != 0;
+        }
+
+        unsafe static void QueryCapabilities(LinuxJoystickDetails stick,
+            byte* axisbit, int axisbytes,
+            byte* keybit, int keybytes,
+            out int axes, out int buttons, out int hats)
+        {
+            // Note: since we are trying to be compatible with the SDL2 gamepad database,
+            // we have to match SDL2 behavior bug-for-bug. This means:
+            // HAT0-HAT3 are all reported as hats (even if the docs say that HAT1 and HAT2 can be analogue triggers)
+            // DPAD buttons are reported as buttons, not as hats (unlike Windows and Mac OS X)
+
+            axes = buttons = hats = 0;
+            for (EvdevAxis axis = 0; axis < EvdevAxis.CNT && (int)axis < axisbytes * 8; axis++)
+            {
+                InputAbsInfo info;
+                bool is_valid = true;
+                is_valid &= TestBit(axisbit, (int)axis);
+                is_valid &= Evdev.GetAbs(stick.FileDescriptor, axis, out info) >= 0;
+                if (is_valid)
+                {
+                    if (axis >= EvdevAxis.HAT0X && axis <= EvdevAxis.HAT3Y)
+                    {
+                        // Analogue hat
+                        stick.AxisMap.Add(axis, new AxisInfo
+                        {
+                            Axis = (JoystickAxis)(JoystickHat)hats++,
+                            Info = info
+                        });
+                    }
+                    else
+                    {
+                        // Regular axis
+                        stick.AxisMap.Add(axis, new AxisInfo
+                        {
+                            Axis = (JoystickAxis)axes++,
+                            Info = info
+                        });
+                    }
+                }
+            }
+
+            for (EvdevButton button = 0; button < EvdevButton.Last && (int)button < keybytes * 8; button++)
+            {
+                if (TestBit(keybit, (int)button))
+                {
+                    stick.ButtonMap.Add(button, buttons++);
+                }
+            }
+        }
+
+        LinuxJoystickDetails OpenJoystick(string path)
+        {
+            LinuxJoystickDetails stick = null;
+
+            int number = GetJoystickNumber(Path.GetFileName(path));
+            if (number >= 0)
+            {
+                int fd = -1;
+                try
+                {
+                    fd = Libc.open(path, OpenFlags.NonBlock);
+                    if (fd == -1)
+                        return null;
+
+                    unsafe
+                    {
+                        const int evsize = Evdev.EventCount / 8;
+                        const int axissize = Evdev.AxisCount / 8;
+                        const int keysize = Evdev.KeyCount / 8;
+                        byte* evbit = stackalloc byte[evsize];
+                        byte* axisbit = stackalloc byte[axissize];
+                        byte* keybit = stackalloc byte[keysize];
+
+                        string name;
+                        EvdevInputId id;
+
+                        // Ensure this is a joystick device
+                        bool is_valid = true;
+
+                        is_valid &= Evdev.GetBit(fd, 0, evsize, new IntPtr(evbit)) >= 0;
+                        is_valid &= Evdev.GetBit(fd, EvdevType.ABS, axissize, new IntPtr(axisbit)) >= 0;
+                        is_valid &= Evdev.GetBit(fd, EvdevType.KEY, keysize, new IntPtr(keybit)) >= 0;
+
+                        is_valid &= TestBit(evbit, (int)EvdevType.KEY);
+                        is_valid &= TestBit(evbit, (int)EvdevType.ABS);
+                        is_valid &= TestBit(axisbit, (int)EvdevAxis.X);
+                        is_valid &= TestBit(axisbit, (int)EvdevAxis.Y);
+
+                        is_valid &= Evdev.GetName(fd, out name) >= 0;
+                        is_valid &= Evdev.GetId(fd, out id) >= 0;
+
+                        if (is_valid)
+                        {
+                            stick = new LinuxJoystickDetails
+                            {
+                                FileDescriptor = fd,
+                                PathIndex = number,
+                                State = new JoystickState(),
+                                Name = name,
+                                Guid = CreateGuid(id, name),
+                            };
+
+                            int axes, buttons, hats;
+                            QueryCapabilities(stick, axisbit, axissize, keybit, keysize,
+                                out axes, out buttons, out hats);
+
+                            stick.Caps = new JoystickCapabilities(axes, buttons, hats, false);
+
+                            // Poll the joystick once, to initialize its state
+                            PollJoystick(stick);
+                        }
+                    }
+
+                    Debug.Print("Found joystick on path {0}", path);
+                }
+                catch (Exception e)
+                {
+                    Debug.Print("Error opening joystick: {0}", e.ToString());
+                }
+                finally
+                {
+                    if (stick == null && fd != -1)
+                    {
+                        // Not a joystick
+                        Libc.close(fd);
+                    }
+                }
+            }
+
+            return stick;
+        }
+
+        void CloseJoystick(LinuxJoystickDetails js)
+        {
+            Sticks.Remove(js.FileDescriptor);
+
+            Libc.close(js.FileDescriptor);
+            js.FileDescriptor = -1;
+            js.State = new JoystickState(); // clear joystick state
+            js.Caps = new JoystickCapabilities();
+        }
+
+        JoystickHatState TranslateHat(int x, int y)
+        {
+            return new JoystickHatState(HatPositions[x, y]);
+        }
+
+        void PollJoystick(LinuxJoystickDetails js)
+        {
+            unsafe
+            {
+                const int EventCount = 32;
+                InputEvent* events = stackalloc InputEvent[EventCount];
+
+                long length = 0;
+                while (true)
+                {
+                    length = (long)Libc.read(js.FileDescriptor, (void*)events, (UIntPtr)(sizeof(InputEvent) * EventCount));
+                    if (length <= 0)
+                        break;
+
+                    // Only mark the joystick as connected when we actually start receiving events.
+                    // Otherwise, the Xbox wireless receiver will register 4 joysticks even if no
+                    // actual joystick is connected to the receiver.
+                    js.Caps.SetIsConnected(true);
+                    js.State.SetIsConnected(true);
+
+                    length /= sizeof(InputEvent);
+                    for (int i = 0; i < length; i++)
+                    {
+                        InputEvent *e = events + i;
+                        switch (e->Type)
+                        {
+                            case EvdevType.ABS:
+                                {
+                                    AxisInfo axis;
+                                    if (js.AxisMap.TryGetValue((EvdevAxis)e->Code, out axis))
+                                    {
+                                        if (axis.Info.Maximum > axis.Info.Minimum)
+                                        {
+                                            if (e->Code >= (int)EvdevAxis.HAT0X && e->Code <= (int)EvdevAxis.HAT3Y)
+                                            {
+                                                // We currently treat analogue hats as digital hats
+                                                // to maintain compatibility with SDL2. We can do
+                                                // better than this, however.
+                                                JoystickHat hat = JoystickHat.Hat0 + (e->Code - (int)EvdevAxis.HAT0X) / 2;
+                                                JoystickHatState pos = js.State.GetHat(hat);
+                                                int xy_axis = (int)axis.Axis & 0x1;
+                                                switch (xy_axis)
+                                                {
+                                                    case 0:
+                                                        // X-axis
+                                                        pos = TranslateHat(
+                                                            e->Value.CompareTo(0) + 1,
+                                                            pos.IsUp ? 0 : pos.IsDown ? 2 : 1);
+                                                        break;
+
+                                                    case 1:
+                                                        // Y-axis
+                                                        pos = TranslateHat(
+                                                            pos.IsLeft ? 0 : pos.IsRight ? 2 : 1,
+                                                            e->Value.CompareTo(0) + 1);
+                                                        break;
+                                                }
+
+                                                js.State.SetHat(hat, pos);
+                                            }
+                                            else
+                                            {
+                                                // This axis represents a regular axis or trigger
+                                                js.State.SetAxis(
+                                                    axis.Axis,
+                                                    (short)Common.HidHelper.ScaleValue(e->Value,
+                                                        axis.Info.Minimum, axis.Info.Maximum,
+                                                        short.MinValue, short.MaxValue));
+                                            }
+                                        }
+                                    }
+                                    break;
+                                }
+
+                            case EvdevType.KEY:
+                                {
+                                    int button;
+                                    if (js.ButtonMap.TryGetValue((EvdevButton)e->Code, out button))
+                                    {
+                                        js.State.SetButton(button, e->Value != 0);
+                                    }
+                                    break;
+                                }
+                        }
+
+                        // Create a serial number (total seconds in 24.8 fixed point format)
+                        int sec = (int)((long)e->Time.Seconds & 0xffffffff);
+                        int msec = (int)e->Time.MicroSeconds / 1000;
+                        int packet =
+                            ((sec & 0x00ffffff) << 24) |
+                            Common.HidHelper.ScaleValue(msec, 0, 1000, 0, 255);
+                        js.State.SetPacketNumber(packet);
+                    }
+                }
+            }
+        }
+
+        static readonly string JoystickPath = "/dev/input";
+        static readonly string JoystickPathLegacy = "/dev";
+
+        #endregion
+
+        #region IDisposable Members
+
+        public void Dispose()
+        {
+            Dispose(true);
+            GC.SuppressFinalize(this);
+        }
+
+        void Dispose(bool manual)
+        {
+            if (!disposed)
+            {
+                if (manual)
+                {
+                }
+
+                watcher.Dispose();
+                foreach (LinuxJoystickDetails js in Sticks)
+                {
+                    CloseJoystick(js);
+                }
+
+                disposed = true;
+            }
+        }
+
+        ~LinuxJoystick()
+        {
+            Dispose(false);
+        }
+
+        #endregion
+
+        #region IJoystickDriver2 Members
+
+        JoystickState IJoystickDriver2.GetState(int index)
+        {
+            LinuxJoystickDetails js = Sticks.FromIndex(index);
+            if (js != null)
+            {
+                PollJoystick(js);
+                return js.State;
+            }
+            return new JoystickState();
+        }
+
+        JoystickCapabilities IJoystickDriver2.GetCapabilities(int index)
+        {
+            LinuxJoystickDetails js = Sticks.FromIndex(index);
+            if (js != null)
+            {
+                return js.Caps;
+            }
+            return new JoystickCapabilities();
+        }
+
+        Guid IJoystickDriver2.GetGuid(int index)
+        {
+            LinuxJoystickDetails js = Sticks.FromIndex(index);
+            if (js != null)
+            {
+                return js.Guid;
+            }
+            return Guid.Empty;
+        }
+
+        #endregion
+    }
+}
diff --git a/testDrm/src/Linux/LinuxKeyboardTTY.cs b/testDrm/src/Linux/LinuxKeyboardTTY.cs
new file mode 100644 (file)
index 0000000..afe66bc
--- /dev/null
@@ -0,0 +1,268 @@
+#region License
+//
+// LinuxKeyboardTTY.cs
+//
+// Author:
+//       thefiddler <stapostol@gmail.com>
+//
+// Copyright (c) 2006-2014 
+//
+// 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.Diagnostics;
+using System.IO;
+using System.Threading;
+using OpenTK.Input;
+
+namespace OpenTK.Platform.Linux
+{
+    // Todo: this has terrible side-effects on process exit
+    // (the keyboard remains tied up.) We need to find a
+    // proper way to clean up after ourselves, even in case
+    // of a crash.
+    #if EXPERIMENTAL
+    class LinuxKeyboardTTY : IKeyboardDriver2, IDisposable
+    {
+        const int stdin = 0; // STDIN_FILENO
+        readonly object sync = new object();
+        Thread input_thread;
+        long exit;
+        KeyboardState state;
+
+        TerminalState original_state;
+        TerminalState current_state;
+
+        IntPtr original_mode = new IntPtr(-1);
+        int original_stdin;
+
+        public LinuxKeyboardTTY()
+        {
+            Debug.Print("[Linux] Using TTY keyboard input.");
+
+            if (!SetupTTY(stdin))
+            {
+                throw new NotSupportedException();
+            }
+
+            input_thread = new Thread(ProcessEvents);
+            input_thread.IsBackground = true;
+            input_thread.Start();
+        }
+
+        #region Private Members
+
+        bool SetupTTY(int stdin)
+        {
+            // Ensure that we are using a real terminal,
+            // rather than some short of file redirection.thing.
+            if (!Terminal.IsTerminal(stdin))
+            {
+                Debug.Print("[Linux] Terminal.IsTerminal({0}) returned false.", stdin);
+                return false;
+            }
+
+            //original_stdin = Libc.dup(stdin);
+
+            int ret = Terminal.GetAttributes(stdin, out original_state);
+            if (ret < 0)
+            {
+                Debug.Print("[Linux] Terminal.GetAttributes({0}) failed. Error: {1}",
+                    stdin, ret);
+                return false;
+            }
+
+            // Retrieve current keyboard mode
+            ret = Libc.ioctl(stdin, KeyboardIoctlCode.GetMode, ref original_mode);
+            if (ret != 0)
+            {
+                Debug.Print("[Linux] Libc.ioctl({0}, KeyboardIoctlCode.GetMode) failed. Error: {1}",
+                    stdin, ret);
+                return false;
+            }
+
+            // Update terminal state
+            current_state = original_state;
+            current_state.LocalMode &= ~(/*LocalFlags.ECHO |*/ LocalFlags.ICANON | LocalFlags.ISIG);
+            current_state.InputMode &= ~(
+                InputFlags.ISTRIP | InputFlags.IGNCR | InputFlags.ICRNL |
+                InputFlags.INLCR | InputFlags.IXOFF | InputFlags.IXON);
+            current_state.ControlCharacters.VMIN = 0;
+            current_state.ControlCharacters.VTIME = 0;
+            Terminal.SetAttributes(stdin, OptionalActions.FLUSH, ref current_state);
+
+            // Request keycodes
+            int mode = 0x02; // K_MEDIUMRAW
+            ret = Libc.ioctl(stdin, KeyboardIoctlCode.SetMode, mode);
+            if (ret != 0)
+            {
+                Debug.Print("[Linux] Libc.ioctl({0}, KeyboardIoctlCode.SetMode, {1}) failed. Error: {2}",
+                    stdin, mode, ret);
+                ExitTTY(this, EventArgs.Empty);
+                return false;
+            }
+
+            // Ensure we reset the original keyboard/terminal state on exit,
+            // even if we crash.
+            HookEvents();
+
+            return true;
+        }
+
+        void ExitTTY(object sender, EventArgs e)
+        {
+            if (original_mode != new IntPtr(-1))
+            {
+                Debug.Print("[Linux] Exiting TTY keyboard input.");
+
+                Libc.ioctl(stdin, KeyboardIoctlCode.SetMode, ref original_mode);
+                Terminal.SetAttributes(stdin, OptionalActions.FLUSH, ref original_state);
+                original_mode = new IntPtr(-1);
+
+                UnhookEvents();
+            }
+        }
+
+        void HookEvents()
+        {
+            Process.GetCurrentProcess().Exited += ExitTTY;
+            Console.CancelKeyPress += ExitTTY;
+        }
+
+        void UnhookEvents()
+        {
+            Process.GetCurrentProcess().Exited -= ExitTTY;
+            Console.CancelKeyPress -= ExitTTY;
+        }
+
+        void ProcessEvents()
+        {
+            state.SetIsConnected(true);
+
+            while (Interlocked.Read(ref exit) == 0)
+            {
+                byte scancode;
+                short extended;
+
+                while (Libc.read(stdin, out scancode) > 0)
+                {
+                    bool pressed = (scancode & 0x80) == 0;
+                    int key = scancode & ~0x80;
+                    KeyModifiers mods;
+                    Debug.Print("{0}:{1} is {2}", key, (int)TranslateKey(key, out mods), pressed);
+
+                    if (key == 0)
+                    {
+                        // This is an extended scancode, ignore
+                        Libc.read(stdin, out extended);
+                    }
+                    else
+                    {
+                        lock (sync)
+                        {
+                            state[(Key)key] = pressed;
+                        }
+                    }
+
+                }
+            }
+
+            input_thread = null;
+        }
+
+        Key TranslateKey(int key, out KeyModifiers mods)
+        {
+            int k = MathHelper.Clamp((int)key, 0, KeyMap.Length);
+            Key result = KeyMap[k];
+            mods = 0;
+            mods |= (result == Key.AltLeft || result == Key.AltRight) ? KeyModifiers.Alt : 0;
+            mods |= (result == Key.ControlLeft || result == Key.ControlRight) ? KeyModifiers.Control : 0;
+            mods |= (result == Key.ShiftLeft || result == Key.ShiftRight) ? KeyModifiers.Shift : 0;
+            return KeyMap[k];
+        }
+
+        static readonly Key[] KeyMap = Evdev.KeyMap;
+
+        #endregion
+
+        #region IKeyboardDriver2 implementation
+
+        public KeyboardState GetState()
+        {
+            lock (this)
+            {
+                return state;
+            }
+        }
+
+        public KeyboardState GetState(int index)
+        {
+            lock (this)
+            {
+                if (index == 0)
+                    return state;
+                else
+                    return new KeyboardState();
+            }
+        }
+
+        public string GetDeviceName(int index)
+        {
+            if (index == 0)
+                return "Standard Input";
+            else
+                return String.Empty;
+        }
+
+        #endregion
+
+        #region IDisposable Implementation
+
+        public void Dispose()
+        {
+            Dispose(true);
+            GC.SuppressFinalize(this);
+        }
+
+        void Dispose(bool disposing)
+        {
+            Interlocked.Increment(ref exit);
+
+            if (disposing)
+            {
+                ExitTTY(this, EventArgs.Empty);
+            }
+            else
+            {
+                Debug.Print("{0} leaked, did you forget to call Dispose()?", typeof(LinuxKeyboardTTY).FullName);
+            }
+        }
+
+        ~LinuxKeyboardTTY()
+        {
+            Dispose(false);
+        }
+
+        #endregion
+    }
+    #endif
+}
+
diff --git a/testDrm/src/Linux/LinuxNativeWindow.cs b/testDrm/src/Linux/LinuxNativeWindow.cs
new file mode 100644 (file)
index 0000000..46ff13b
--- /dev/null
@@ -0,0 +1,537 @@
+#region License
+//
+// LinuxNativeWindow.cs
+//
+// Author:
+//       Stefanos A. <stapostol@gmail.com>
+//
+// 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.Diagnostics;
+#if !MINIMAL
+using System.Drawing;
+#endif
+using System.Runtime.InteropServices;
+using OpenTK.Graphics;
+using OpenTK.Input;
+using OpenTK.Platform.Egl;
+
+namespace OpenTK.Platform.Linux
+{
+    using Egl = OpenTK.Platform.Egl.Egl;
+
+    class LinuxNativeWindow : NativeWindowBase
+    {
+        LinuxWindowInfo window;
+        string title;
+        Icon icon;
+        Rectangle bounds;
+        Size client_size;
+        bool exists;
+        bool is_focused;
+        bool is_cursor_visible = true;
+
+        KeyboardState previous_keyboard;
+        MouseState previous_mouse;
+
+        MouseCursor cursor_current;
+        BufferObject cursor_custom;
+        BufferObject cursor_default;
+        BufferObject cursor_empty;
+
+        public LinuxNativeWindow(IntPtr display, IntPtr gbm, int fd,
+            int x, int y, int width, int height, string title,
+            GraphicsMode mode, GameWindowFlags options,
+            DisplayDevice display_device)
+        {
+            Debug.Print("[KMS] Creating window on display {0:x}", display);
+
+            Title = title;
+
+            display_device = display_device ?? DisplayDevice.Default;
+            if (display_device == null)
+            {
+                throw new NotSupportedException("[KMS] Driver does not currently support headless systems");
+            }
+
+            window = new LinuxWindowInfo(display, fd, gbm, display_device.Id as LinuxDisplay);
+
+            // Note: we only support fullscreen windows on KMS.
+            // We implicitly override the requested width and height
+            // by the width and height of the DisplayDevice, if any.
+            width = display_device.Width;
+            height = display_device.Height;
+            bounds = new Rectangle(0, 0, width, height);
+            client_size = bounds.Size;
+
+            if (!mode.Index.HasValue)
+            {
+                mode = new EglGraphicsMode().SelectGraphicsMode(window, mode, 0);
+            }
+            Debug.Print("[KMS] Selected EGL mode {0}", mode);
+
+            SurfaceFormat format = GetSurfaceFormat(display, mode);
+            SurfaceFlags usage = SurfaceFlags.Rendering | SurfaceFlags.Scanout;
+            if (!Gbm.IsFormatSupported(gbm, format, usage))
+            {
+                Debug.Print("[KMS] Failed to find suitable surface format, using XRGB8888");
+                format = SurfaceFormat.XRGB8888;
+            }
+
+            Debug.Print("[KMS] Creating GBM surface on {0:x} with {1}x{2} {3} [{4}]",
+                gbm, width, height, format, usage);
+            IntPtr gbm_surface =  Gbm.CreateSurface(gbm,
+                    width, height, format, usage);
+            if (gbm_surface == IntPtr.Zero)
+            {
+                throw new NotSupportedException("[KMS] Failed to create GBM surface for rendering");
+            }
+
+            window.Handle = gbm_surface;
+                Debug.Print("[KMS] Created GBM surface {0:x}", window.Handle);
+
+            window.CreateWindowSurface(mode.Index.Value);
+            Debug.Print("[KMS] Created EGL surface {0:x}", window.Surface);
+
+            cursor_default = CreateCursor(gbm, Cursors.Default);
+            cursor_empty = CreateCursor(gbm, Cursors.Empty);
+            Cursor = MouseCursor.Default;
+            exists = true;
+        }
+
+        #region Private Members
+
+        static BufferObject CreateCursor(IntPtr gbm, MouseCursor cursor)
+        {
+            if (cursor.Width > 64 || cursor.Height > 64)
+            {
+                Debug.Print("[KMS] Cursor size {0}x{1} unsupported. Maximum is 64x64.",
+                    cursor.Width, cursor.Height);
+                return default(BufferObject);
+            }
+
+            int width = 64;
+            int height = 64;
+            SurfaceFormat format = SurfaceFormat.ARGB8888;
+            SurfaceFlags usage = SurfaceFlags.Cursor64x64 | SurfaceFlags.Write;
+
+            Debug.Print("[KMS] Gbm.CreateBuffer({0:X}, {1}, {2}, {3}, {4}).",
+                gbm, width, height, format, usage);
+
+            BufferObject bo = Gbm.CreateBuffer(
+                gbm, width, height, format, usage);
+
+            if (bo == BufferObject.Zero)
+            {
+                Debug.Print("[KMS] Failed to create buffer.");
+                return bo;
+            }
+
+            // Copy cursor.Data into a new buffer of the correct size
+            byte[] cursor_data = new byte[width * height * 4];
+            for (int y = 0; y < cursor.Height; y++)
+            {
+                int dst_offset = y * width * 4;
+                int src_offset = y * cursor.Width * 4;
+                int src_length = cursor.Width * 4;
+                Array.Copy(
+                    cursor.Data, src_offset,
+                    cursor_data, dst_offset,
+                    src_length);
+            }
+            bo.Write(cursor_data);
+
+            return bo;
+        }
+
+        void SetCursor(MouseCursor cursor)
+        {
+            BufferObject bo = default(BufferObject);
+            if (cursor == MouseCursor.Default)
+            {
+                bo = cursor_default;
+            }
+            else if (cursor == MouseCursor.Empty)
+            {
+                bo = cursor_empty;
+            }
+            else
+            {
+                if (cursor_custom != BufferObject.Zero)
+                    cursor_custom.Dispose();
+                cursor_custom = CreateCursor(window.BufferManager, cursor);
+                bo = cursor_custom;
+            }
+
+            // If we failed to create a proper cursor, try falling back
+            // to the empty cursor. We do not want to crash here!
+            if (bo == BufferObject.Zero)
+            {
+                bo = cursor_empty;
+            }
+
+            if (bo != BufferObject.Zero)
+            {
+                Drm.SetCursor(window.FD, window.DisplayDevice.Id,
+                    bo.Handle, bo.Width, bo.Height, cursor.X, cursor.Y);
+            }
+        }
+
+        static SurfaceFormat GetSurfaceFormat(IntPtr display, GraphicsMode mode)
+        {
+            // Use EGL 1.4 EGL_NATIVE_VISUAL_ID to retrieve
+            // the corresponding surface format. If that fails
+            // fall back to a manual algorithm.
+            int format;
+            Egl.GetConfigAttrib(display, mode.Index.Value,
+                Egl.NATIVE_VISUAL_ID, out format);
+            if ((SurfaceFormat)format != 0)
+                return (SurfaceFormat)format;
+
+            Debug.Print("[KMS] Failed to retrieve EGL visual from GBM surface. Error: {0}",
+                Egl.GetError());
+            Debug.Print("[KMS] Falling back to hardcoded formats.");
+
+            int r = mode.ColorFormat.Red;
+            int g = mode.ColorFormat.Green;
+            int b = mode.ColorFormat.Blue;
+            int a = mode.ColorFormat.Alpha;
+
+            if (mode.ColorFormat.IsIndexed)
+                return SurfaceFormat.C8;
+            if (r == 3 && g == 3 && b == 2 && a == 0)
+                return SurfaceFormat.RGB332;
+            if (r == 5 && g == 6 && b == 5 && a == 0)
+                return SurfaceFormat.RGB565;
+            if (r == 5 && g == 6 && b == 5 && a == 0)
+                return SurfaceFormat.RGB565;
+            if (r == 8 && g == 8 && b == 8 && a == 0)
+                return SurfaceFormat.RGB888;
+            if (r == 5 && g == 5 && b == 5 && a == 1)
+                return SurfaceFormat.RGBA5551;
+            if (r == 10 && g == 10 && b == 10 && a == 2)
+                return SurfaceFormat.RGBA1010102;
+            if (r == 4 && g == 4 && b == 4 && a == 4)
+                return SurfaceFormat.RGBA4444;
+            if (r == 8 && g == 8 && b == 8 && a == 8)
+                return SurfaceFormat.RGBA8888;
+
+            return SurfaceFormat.RGBA8888;
+        }
+
+        KeyboardState ProcessKeyboard(KeyboardState keyboard)
+        {
+            for (Key i = 0; i < Key.LastKey; i++)
+            {
+                if (keyboard[i])
+                {
+                    OnKeyDown(i, previous_keyboard[i]);
+                    // Todo: implement libxkb-common binding for text input
+                }
+
+                if (!keyboard[i] && previous_keyboard[i])
+                {
+                    OnKeyUp(i);
+                }
+            }
+            return keyboard;
+        }
+
+        MouseState ProcessMouse(MouseState mouse)
+        {
+            // Handle mouse buttons
+            for (MouseButton i = 0; i < MouseButton.LastButton; i++)
+            {
+                if (mouse[i] && !previous_mouse[i])
+                {
+                    OnMouseDown(i);
+                }
+
+                if (!mouse[i] && previous_mouse[i])
+                {
+                    OnMouseUp(i);
+                }
+            }
+
+            // Handle mouse movement
+            {
+                int x = mouse.X;
+                int y = mouse.Y;
+
+                // Make sure the mouse cannot leave the GameWindow when captured
+                if (!CursorVisible)
+                {
+                    x = MathHelper.Clamp(mouse.X, Bounds.Left, Bounds.Right - 1);
+                    y = MathHelper.Clamp(mouse.Y, Bounds.Top, Bounds.Bottom - 1);
+                    if (x != mouse.X || y != mouse.Y)
+                    {
+                        Mouse.SetPosition(x, y);
+                    }
+                }
+
+                if (x != previous_mouse.X || y != previous_mouse.Y)
+                {
+                    OnMouseMove(x, y);
+                }
+            }
+
+            // Handle mouse scroll
+            if (mouse.Scroll != previous_mouse.Scroll)
+            {
+                float dx = mouse.Scroll.X - previous_mouse.Scroll.X;
+                float dy = mouse.Scroll.Y - previous_mouse.Scroll.Y;
+                OnMouseWheel(dx, dy);
+            }
+
+            // Handle mouse focus
+            // Note: focus follows mouse. Literally.
+            bool cursor_in = Bounds.Contains(new Point(mouse.X, mouse.Y));
+            if (!cursor_in && Focused)
+            {
+                OnMouseLeave(EventArgs.Empty);
+                SetFocus(false);
+            }
+            else if (cursor_in && !Focused)
+            {
+                OnMouseEnter(EventArgs.Empty);
+                SetFocus(true);
+            }
+
+            return mouse;
+        }
+
+        void SetFocus(bool focus)
+        {
+            if (is_focused != focus)
+            {
+                is_focused = focus;
+                OnFocusedChanged(EventArgs.Empty);
+            }
+        }
+
+        #endregion
+
+        #region INativeWindow Members
+
+        public override void ProcessEvents()
+        {
+            // Note: there is no event-based keyboard/mouse input available.
+            // We will fake that by polling OpenTK.Input.
+            previous_keyboard = ProcessKeyboard(Keyboard.GetState());
+            previous_mouse = ProcessMouse(Mouse.GetCursorState());
+
+            base.ProcessEvents();
+        }
+
+        public override void Close()
+        {
+            exists = false;
+        }
+
+        public override Point PointToClient(Point point)
+        {
+            var client = Location;
+            return new Point(point.X - client.X, point.Y - client.Y);
+        }
+
+        public override Point PointToScreen(Point point)
+        {
+            var client = Location;
+            return new Point(point.X + client.X, point.Y + client.Y);
+        }
+
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing)
+            {
+                Debug.Print("[KMS] Destroying window {0}.", window.Handle);
+                Drm.SetCursor(window.FD, window.DisplayDevice.Id, 0, 0, 0, 0, 0);
+                window.Dispose();
+                Gbm.DestroySurface(window.Handle);
+            }
+            else
+            {
+                Debug.Print("[KMS] {0} leaked. Did you forget to call Dispose()?", GetType().FullName);
+            }
+        }
+
+        public override Icon Icon
+        {
+            get
+            {
+                return icon;
+            }
+            set
+            {
+                if (icon != value)
+                {
+                    icon = value;
+                    OnIconChanged(EventArgs.Empty);
+                }
+            }
+        }
+
+        public override string Title
+        {
+            get
+            {
+                return title;
+            }
+            set
+            {
+                if (title != value)
+                {
+                    title = value;
+                    OnTitleChanged(EventArgs.Empty);
+                }
+            }
+        }
+
+        public override bool Focused
+        {
+            get
+            {
+                return is_focused;
+            }
+        }
+
+        public override bool Visible
+        {
+            get
+            {
+                return true;
+            }
+            set
+            {
+            }
+        }
+
+        public override bool Exists
+        {
+            get
+            {
+                return exists;
+            }
+        }
+
+        public override IWindowInfo WindowInfo
+        {
+            get
+            {
+                return window;
+            }
+        }
+
+        public override WindowState WindowState
+        {
+            get
+            {
+                return WindowState.Fullscreen;
+            }
+            set
+            {
+            }
+        }
+
+        public override WindowBorder WindowBorder
+        {
+            get
+            {
+                return WindowBorder.Hidden;
+            }
+            set
+            {
+            }
+        }
+
+        public override Rectangle Bounds
+        {
+            get
+            {
+                return bounds;
+            }
+            set
+            {
+            }
+        }
+
+        public override Size ClientSize
+        {
+            get
+            {
+                return client_size;
+            }
+            set
+            {
+            }
+        }
+
+        public override bool CursorVisible
+        {
+            get
+            {
+                return is_cursor_visible;
+            }
+            set
+            {
+                if (value && !is_cursor_visible)
+                {
+                    SetCursor(cursor_current);
+                }
+                else if (!value && is_cursor_visible)
+                {
+                    SetCursor(MouseCursor.Empty);
+                }
+                is_cursor_visible = value;
+            }
+        }
+
+        public override MouseCursor Cursor
+        {
+            get
+            {
+                return cursor_current;
+            }
+            set
+            {
+                if (cursor_current != value)
+                {
+                    if (cursor_custom != BufferObject.Zero)
+                    {
+                        cursor_custom.Dispose();
+                    }
+
+                    if (CursorVisible)
+                    {
+                        SetCursor(value);
+                    }
+                    cursor_current = value;
+                }
+            }
+        }
+
+        #endregion
+    }
+}
+
diff --git a/testDrm/src/Linux/LinuxWindowInfo.cs b/testDrm/src/Linux/LinuxWindowInfo.cs
new file mode 100644 (file)
index 0000000..e1d91e9
--- /dev/null
@@ -0,0 +1,56 @@
+#region License
+//
+// LinuxWindowInfo.cs
+//
+// Author:
+//       Stefanos A. <stapostol@gmail.com>
+//
+// 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.Diagnostics;
+using OpenTK.Platform.Egl;
+
+namespace OpenTK.Platform.Linux
+{
+    class LinuxWindowInfo : EglWindowInfo
+    {
+        public int FD { get; private set; }
+        public LinuxDisplay DisplayDevice { get; private set; }
+        public IntPtr BufferManager { get; private set; }
+
+        public LinuxWindowInfo(IntPtr display, int fd, IntPtr gbm, LinuxDisplay display_device)
+            : base(IntPtr.Zero, display, IntPtr.Zero)
+        {
+            if (display_device == null)
+                throw new ArgumentNullException();
+
+            FD = fd;
+            BufferManager = gbm;
+            DisplayDevice = display_device;
+            // The window handle and surface handle must
+            // be filled in manually once they are known.
+        }
+    }
+}
+
diff --git a/testDrm/src/MouseCursor.cs b/testDrm/src/MouseCursor.cs
new file mode 100644 (file)
index 0000000..df8cd0c
--- /dev/null
@@ -0,0 +1,135 @@
+#region License
+//
+// Cursor.cs
+//
+// Author:
+//       Stefanos A. <stapostol@gmail.com>
+//
+// 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;
+
+namespace OpenTK
+{
+    /// <summary>
+    /// Represents a predefined or custom mouse cursor.
+    /// </summary>
+    public sealed class MouseCursor : WindowIcon
+    {
+        static readonly MouseCursor default_cursor = new MouseCursor();
+        static readonly MouseCursor empty_cursor = new MouseCursor(
+            0, 0, 16, 16, new byte[16 * 16 * 4]);
+
+        int x;
+        int y;
+
+        MouseCursor()
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new <see cref="MouseCursor"/> instance from a
+        /// contiguous array of BGRA pixels.
+        /// Each pixel is composed of 4 bytes, representing B, G, R and A values,
+        /// respectively. For correct antialiasing of translucent cursors,
+        /// the B, G and R components should be premultiplied with the A component:
+        /// <code>
+        /// B = (byte)((B * A) / 255)
+        /// G = (byte)((G * A) / 255)
+        /// R = (byte)((R * A) / 255)
+        /// </code>
+        /// </summary>
+        /// <param name="hotx">The x-coordinate of the cursor hotspot, in the range [0, width]</param>
+        /// <param name="hoty">The y-coordinate of the cursor hotspot, in the range [0, height]</param>
+        /// <param name="width">The width of the cursor data, in pixels.</param>
+        /// <param name="height">The height of the cursor data, in pixels.</param>
+        /// <param name="data">
+        /// A byte array representing the cursor image,
+        /// laid out as a contiguous array of BGRA pixels.
+        /// </param>
+        public MouseCursor(int hotx, int hoty, int width, int height, byte[] data)
+            : base(width, height, data)
+        {
+            if (hotx < 0 || hotx >= Width || hoty < 0 || hoty >= Height)
+                throw new ArgumentOutOfRangeException();
+
+            x = hotx;
+            y = hoty;
+        }
+
+        /// <summary>
+        /// Initializes a new <see cref="MouseCursor"/> instance from a
+        /// contiguous array of BGRA pixels.
+        /// Each pixel is composed of 4 bytes, representing B, G, R and A values,
+        /// respectively. For correct antialiasing of translucent cursors,
+        /// the B, G and R components should be premultiplied with the A component:
+        /// <code>
+        /// B = (byte)((B * A) / 255)
+        /// G = (byte)((G * A) / 255)
+        /// R = (byte)((R * A) / 255)
+        /// </code>
+        /// </summary>
+        /// <param name="hotx">The x-coordinate of the cursor hotspot, in the range [0, width]</param>
+        /// <param name="hoty">The y-coordinate of the cursor hotspot, in the range [0, height]</param>
+        /// <param name="width">The width of the cursor data, in pixels.</param>
+        /// <param name="height">The height of the cursor data, in pixels.</param>
+        /// <param name="data">
+        /// A pointer to the cursor image, laid out as a contiguous array of BGRA pixels.
+        /// </param>
+        public MouseCursor(int hotx, int hoty, int width, int height, IntPtr data)
+            : base(width, height, data)
+        {
+            if (hotx < 0 || hotx >= Width || hoty < 0 || hoty >= Height)
+                throw new ArgumentOutOfRangeException();
+
+            x = hotx;
+            y = hoty;
+        }
+
+        internal int X { get { return x; } }
+        internal int Y { get { return y; } }
+
+        /// <summary>
+        /// Gets the default mouse cursor for this platform.
+        /// </summary>
+        public static MouseCursor Default
+        {
+            get
+            {
+                return default_cursor;
+            }
+        }
+
+        /// <summary>
+        /// Gets an empty (invisible) mouse cursor.
+        /// </summary>
+        public static MouseCursor Empty
+        {
+            get
+            {
+                return empty_cursor;
+            }
+        }
+    }
+}
+
diff --git a/testDrm/src/WindowIcon.cs b/testDrm/src/WindowIcon.cs
new file mode 100644 (file)
index 0000000..53d2d1f
--- /dev/null
@@ -0,0 +1,91 @@
+#region License
+//
+// WindowIcon.cs
+//
+// Author:
+//       Stefanos A. <stapostol@gmail.com>
+//
+// 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.Runtime.InteropServices;
+
+namespace OpenTK
+{
+    /// <summary>
+    /// Stores a window icon. A window icon is defined
+    /// as a 2-dimensional buffer of RGBA values.
+    /// </summary>
+    public class WindowIcon
+    {
+        byte[] data;
+        int width;
+        int height;
+
+        /// \internal
+        /// <summary>
+        /// Initializes a new instance of the <see cref="OpenTK.WindowIcon"/> class.
+        /// </summary>
+        internal protected WindowIcon()
+        {
+        }
+
+        WindowIcon(int width, int height)
+        {
+            if (width < 0 || width > 256 || height < 0 || height > 256)
+                throw new ArgumentOutOfRangeException();
+
+            this.width = width;
+            this.height = height;
+        }
+
+        internal WindowIcon(int width, int height, byte[] data)
+            : this(width, height)
+        {
+            if (data == null)
+                throw new ArgumentNullException();
+            if (data.Length < Width * Height * 4)
+                throw new ArgumentOutOfRangeException();
+
+            this.data = data;
+        }
+
+        internal WindowIcon(int width, int height, IntPtr data)
+            : this(width, height)
+        {
+            if (data == IntPtr.Zero)
+                throw new ArgumentNullException();
+
+            // We assume that width and height are correctly set.
+            // If they are not, we will read garbage and probably
+            // crash.
+            this.data = new byte[width * height * 4];
+            Marshal.Copy(data, this.data, 0, this.data.Length);
+        }
+
+        internal byte[] Data { get { return data; } }
+        internal int Width { get { return width; } }
+        internal int Height { get { return height; } }
+    }
+}
+
diff --git a/testDrm/testDrm.csproj b/testDrm/testDrm.csproj
new file mode 100644 (file)
index 0000000..21b5bf3
--- /dev/null
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>8.0.30703</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{4B57740A-75FB-4978-A8E8-8B1793B7474F}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <RootNamespace>testDrm</RootNamespace>
+    <AssemblyName>testDrm</AssemblyName>
+    <ReleaseVersion>0.5</ReleaseVersion>
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+    <OutputPath>$(SolutionDir)build/$(Configuration)</OutputPath>
+    <IntermediateOutputPath>$(SolutionDir)build/obj/$(Configuration)</IntermediateOutputPath>
+    <CustomCommands>
+      <CustomCommands>
+        <Command type="Execute" command="${TargetName}" workingdir="${SolutionDir}/build/${ProjectConfigName}" />
+      </CustomCommands>
+    </CustomCommands>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <DefineConstants>DEBUG;</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <ConsolePause>false</ConsolePause>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+    <IntermediateOutputPath>$(SolutionDir)build\obj\$(Configuration)</IntermediateOutputPath>
+    <OutputPath>$(SolutionDir)build\$(Configuration)</OutputPath>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>full</DebugType>
+    <Optimize>true</Optimize>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <ConsolePause>false</ConsolePause>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+    <IntermediateOutputPath>$(SolutionDir)build\obj\$(Configuration)</IntermediateOutputPath>
+    <OutputPath>$(SolutionDir)build\$(Configuration)</OutputPath>
+  </PropertyGroup>
+  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+  <ItemGroup>
+    <Compile Include="Main.cs" />
+    <Compile Include="src\Linux\Bindings\Drm.cs" />
+    <Compile Include="src\Linux\Bindings\Evdev.cs" />
+    <Compile Include="src\Linux\Bindings\Gbm.cs" />
+    <Compile Include="src\Linux\Bindings\Kms.cs" />
+    <Compile Include="src\Linux\Bindings\Libc.cs" />
+    <Compile Include="src\Linux\Bindings\LibInput.cs" />
+    <Compile Include="src\Linux\Bindings\Poll.cs" />
+    <Compile Include="src\Linux\Bindings\Terminal.cs" />
+    <Compile Include="src\Linux\Bindings\Udev.cs" />
+    <Compile Include="src\BlittableValueType.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\DisplayResolution.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\Egl.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\DrmDevice.cs" />
+    <Compile Include="src\Linux\DefaultCursor.cs" />
+    <Compile Include="src\MouseCursor.cs" />
+    <Compile Include="src\WindowIcon.cs" />
+    <Compile Include="Mono.Cairo\Antialias.cs" />
+    <Compile Include="Mono.Cairo\Cairo.cs" />
+    <Compile Include="Mono.Cairo\CairoDebug.cs" />
+    <Compile Include="Mono.Cairo\Color.cs" />
+    <Compile Include="Mono.Cairo\Content.cs" />
+    <Compile Include="Mono.Cairo\Context.cs" />
+    <Compile Include="Mono.Cairo\DirectFBSurface.cs" />
+    <Compile Include="Mono.Cairo\Distance.cs" />
+    <Compile Include="Mono.Cairo\Extend.cs" />
+    <Compile Include="Mono.Cairo\FillRule.cs" />
+    <Compile Include="Mono.Cairo\Filter.cs" />
+    <Compile Include="Mono.Cairo\FontExtents.cs" />
+    <Compile Include="Mono.Cairo\FontFace.cs" />
+    <Compile Include="Mono.Cairo\FontOptions.cs" />
+    <Compile Include="Mono.Cairo\FontSlant.cs" />
+    <Compile Include="Mono.Cairo\FontType.cs" />
+    <Compile Include="Mono.Cairo\FontWeight.cs" />
+    <Compile Include="Mono.Cairo\Format.cs" />
+    <Compile Include="Mono.Cairo\GlitzSurface.cs" />
+    <Compile Include="Mono.Cairo\Glyph.cs" />
+    <Compile Include="Mono.Cairo\Gradient.cs" />
+    <Compile Include="Mono.Cairo\HintMetrics.cs" />
+    <Compile Include="Mono.Cairo\HintStyle.cs" />
+    <Compile Include="Mono.Cairo\ImageSurface.cs" />
+    <Compile Include="Mono.Cairo\LineCap.cs" />
+    <Compile Include="Mono.Cairo\LineJoin.cs" />
+    <Compile Include="Mono.Cairo\LinearGradient.cs" />
+    <Compile Include="Mono.Cairo\Matrix.cs" />
+    <Compile Include="Mono.Cairo\NativeMethods.cs" />
+    <Compile Include="Mono.Cairo\Operator.cs" />
+    <Compile Include="Mono.Cairo\PSSurface.cs" />
+    <Compile Include="Mono.Cairo\Path.cs" />
+    <Compile Include="Mono.Cairo\Pattern.cs" />
+    <Compile Include="Mono.Cairo\PatternType.cs" />
+    <Compile Include="Mono.Cairo\PdfSurface.cs" />
+    <Compile Include="Mono.Cairo\Point.cs" />
+    <Compile Include="Mono.Cairo\PointD.cs" />
+    <Compile Include="Mono.Cairo\RadialGradient.cs" />
+    <Compile Include="Mono.Cairo\Rectangle.cs" />
+    <Compile Include="Mono.Cairo\Region.cs" />
+    <Compile Include="Mono.Cairo\ScaledFont.cs" />
+    <Compile Include="Mono.Cairo\SolidPattern.cs" />
+    <Compile Include="Mono.Cairo\Status.cs" />
+    <Compile Include="Mono.Cairo\SubpixelOrder.cs" />
+    <Compile Include="Mono.Cairo\Surface.cs" />
+    <Compile Include="Mono.Cairo\SurfacePattern.cs" />
+    <Compile Include="Mono.Cairo\SurfaceType.cs" />
+    <Compile Include="Mono.Cairo\SvgSurface.cs" />
+    <Compile Include="Mono.Cairo\SvgVersion.cs" />
+    <Compile Include="Mono.Cairo\TextExtents.cs" />
+    <Compile Include="Mono.Cairo\Win32Surface.cs" />
+    <Compile Include="Mono.Cairo\XcbSurface.cs" />
+    <Compile Include="Mono.Cairo\XlibSurface.cs" />
+    <Compile Include="Mono.Cairo\Device.cs" />
+    <Compile Include="Mono.Cairo\GLSurface.cs" />
+    <Compile Include="Mono.Cairo\GLXDevice.cs" />
+    <Compile Include="Mono.Cairo\WGLDevice.cs" />
+    <Compile Include="Mono.Cairo\EGLDevice.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Drawing" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Folder Include="src\" />
+    <Folder Include="Mono.Cairo\" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="src\Linux\LinuxFactory.cs" />
+    <None Include="src\Linux\LinuxGraphicsContext.cs" />
+    <None Include="src\Linux\LinuxInput.cs" />
+    <None Include="src\Linux\LinuxJoystick.cs">
+      <SubType>Code</SubType>
+    </None>
+    <None Include="src\Linux\LinuxKeyboardTTY.cs" />
+    <None Include="src\Linux\LinuxNativeWindow.cs" />
+    <None Include="src\Linux\LinuxWindowInfo.cs" />
+    <None Include="src\Linux\LinuxDisplayDriver.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\Crow.csproj">
+      <Project>{C2980F9B-4798-4C05-99E2-E174810F7C7B}</Project>
+      <Name>Crow</Name>
+    </ProjectReference>
+  </ItemGroup>
+</Project>
\ No newline at end of file