From df9a7fe88ce844de7dbbc0386a2d584eea90885d Mon Sep 17 00:00:00 2001 From: jpbruyere Date: Thu, 25 May 2017 22:11:42 +0200 Subject: [PATCH] evdev Device class, test with keymapping --- Crow.sln | 8 + CrowIDE/CrowIDE.csproj | 26 +- CrowIDE/OpenGL/Shader.cs | 335 -------- CrowIDE/OpenGL/Texture.cs | 94 --- CrowIDE/OpenGL/vaoMesh.cs | 221 ------ CrowIDE/OpenTKGameWindow.cs | 334 -------- CrowIDE/src/Application.cs | 614 +++++++++++++++ .../Linux => CrowIDE/src}/Bindings/Evdev.cs | 5 +- CrowIDE/src/Bindings/LibInput.cs | 338 ++++++++ CrowIDE/src/Bindings/Poll.cs | 65 ++ CrowIDE/src/Bindings/Udev.cs | 46 ++ CrowIDE/src/BlittableValueType.cs | 291 +++++++ CrowIDE/src/CrowIDEdrm.cs | 125 +++ CrowIDE/src/DRIControler.cs | 487 ++++++++++++ CrowIDE/src/ImlVisualEditor.cs | 4 +- CrowIDE/src/Signal.cs | 77 ++ Tests/BasicTests.cs | 26 +- Tests/CrowWindow.cs | 4 - src/CompilerServices/CompilerServices.cs | 4 + src/Interface.cs | 39 +- src/PerformanceMeasure.cs | 21 +- testDrm/Main.cs | 135 ++-- testDrm/defineToEnum.cs | 100 +++ testDrm/src/Application.cs | 200 ++++- testDrm/src/BlittableValueType.cs | 2 +- testDrm/src/DRMContext.cs | 2 +- testDrm/src/EVDEV/Device.cs | 245 ++++++ testDrm/src/EVDEV/Enums.cs | 734 ++++++++++++++++++ testDrm/src/Egl/Context.cs | 109 ++- testDrm/src/Egl/Surface.cs | 26 + testDrm/src/Linux/Bindings/EvdevClass.cs | 640 +++++++++++++++ testDrm/src/Linux/Bindings/LibInput.cs | 7 +- testDrm/src/Linux/Bindings/Libc.cs | 21 +- testDrm/src/Linux/DRI/DRIControler.cs | 144 +--- testDrm/src/Linux/VT.cs | 117 ++- testDrm/test.style | 25 +- testDrm/testDrm.csproj | 21 +- testDrm/testLibInput.cs | 312 ++++++++ testDrm/tests.cs | 239 +++--- testDrm/ui/menu.crow | 4 +- testDrm/ui/perfMeasures.crow | 5 +- testDrm/ui/perfMsr.crow | 5 +- 42 files changed, 4843 insertions(+), 1414 deletions(-) delete mode 100644 CrowIDE/OpenGL/Shader.cs delete mode 100644 CrowIDE/OpenGL/Texture.cs delete mode 100644 CrowIDE/OpenGL/vaoMesh.cs delete mode 100644 CrowIDE/OpenTKGameWindow.cs create mode 100644 CrowIDE/src/Application.cs rename {testDrm/src/Linux => CrowIDE/src}/Bindings/Evdev.cs (99%) create mode 100644 CrowIDE/src/Bindings/LibInput.cs create mode 100644 CrowIDE/src/Bindings/Poll.cs create mode 100644 CrowIDE/src/Bindings/Udev.cs create mode 100644 CrowIDE/src/BlittableValueType.cs create mode 100644 CrowIDE/src/CrowIDEdrm.cs create mode 100644 CrowIDE/src/DRIControler.cs create mode 100644 CrowIDE/src/Signal.cs create mode 100644 testDrm/defineToEnum.cs create mode 100644 testDrm/src/EVDEV/Device.cs create mode 100644 testDrm/src/EVDEV/Enums.cs create mode 100644 testDrm/src/Linux/Bindings/EvdevClass.cs create mode 100644 testDrm/testLibInput.cs diff --git a/Crow.sln b/Crow.sln index 97e14933..aad0db27 100644 --- a/Crow.sln +++ b/Crow.sln @@ -11,22 +11,30 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenTK", "..\..\src\opentk- EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "testDrm", "testDrm\testDrm.csproj", "{4B57740A-75FB-4978-A8E8-8B1793B7474F}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DRI.net", "..\DRI.net\DRI.net.csproj", "{0189EAEF-DCD4-42F8-A83A-2DEA82926671}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution + {0189EAEF-DCD4-42F8-A83A-2DEA82926671}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0189EAEF-DCD4-42F8-A83A-2DEA82926671}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0189EAEF-DCD4-42F8-A83A-2DEA82926671}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0189EAEF-DCD4-42F8-A83A-2DEA82926671}.Release|Any CPU.Build.0 = Release|Any CPU {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 {B6D911CD-1D09-42FC-B300-9187190F2AE1}.Release|Any CPU.Build.0 = Release|Any CPU {C2980F9B-4798-4C05-99E2-E174810F7C7B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU diff --git a/CrowIDE/CrowIDE.csproj b/CrowIDE/CrowIDE.csproj index 90cd9290..bafc2933 100644 --- a/CrowIDE/CrowIDE.csproj +++ b/CrowIDE/CrowIDE.csproj @@ -19,6 +19,7 @@ 0.5 CrowIDE.CrowIDE + true true @@ -27,7 +28,6 @@ DEBUG; prompt 4 - false $(SolutionDir)build\obj\$(Configuration) $(SolutionDir)build\$(Configuration) @@ -45,10 +45,6 @@ - - $(SolutionDir)packages\OpenTK.2.0.0\lib\net20\OpenTK.dll - opentk - @@ -56,17 +52,26 @@ {C2980F9B-4798-4C05-99E2-E174810F7C7B} Crow + + {0189EAEF-DCD4-42F8-A83A-2DEA82926671} + DRI.net + - - - - - + + + + + + + + + Code + @@ -93,5 +98,6 @@ PreserveNewest + diff --git a/CrowIDE/OpenGL/Shader.cs b/CrowIDE/OpenGL/Shader.cs deleted file mode 100644 index 0f355fcd..00000000 --- a/CrowIDE/OpenGL/Shader.cs +++ /dev/null @@ -1,335 +0,0 @@ -// -// Shader.cs -// -// Author: -// Jean-Philippe Bruyère -// -// Copyright (c) 2016 jp -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -using System; -using System.Diagnostics; -using System.IO; -using OpenTK; -using OpenTK.Graphics.OpenGL; - -namespace Crow -{ - public class Shader : IDisposable - { - #region CTOR - public Shader () - { - Init (); - } - public Shader (string vertResPath, string fragResPath = null, string geomResPath = null) - { - VertSourcePath = vertResPath; - FragSourcePath = fragResPath; - GeomSourcePath = geomResPath; - - loadSourcesFiles (); - - Init (); - } - #endregion - - public string VertSourcePath, - FragSourcePath, - GeomSourcePath; - #region Sources - protected string _vertSource = @" - #version 330 - precision lowp float; - - uniform mat4 mvp; - - layout(location = 0) in vec3 in_position; - layout(location = 1) in vec2 in_tex; - - out vec2 texCoord; - - void main(void) - { - texCoord = in_tex; - gl_Position = mvp * vec4(in_position, 1.0); - }"; - - protected string _fragSource = @" - #version 330 - precision lowp float; - - uniform sampler2D tex; - - in vec2 texCoord; - out vec4 out_frag_color; - - void main(void) - { - out_frag_color = texture( tex, texCoord);//vec4(1,0,0,1); - }"; - string _geomSource = @""; -// #version 330 -// layout(triangles) in; -// layout(triangle_strip, max_vertices=3) out; -// void main() -// { -// for(int i=0; i<3; i++) -// { -// gl_Position = gl_in[i].gl_Position; -// EmitVertex(); -// } -// EndPrimitive(); -// }"; - #endregion - - #region Private and protected fields - public int vsId, fsId, gsId, pgmId, mvpLocation; - - Matrix4 mvp = Matrix4.Identity; - #endregion - - - #region Public properties - public virtual string vertSource - { - get { return _vertSource;} - set { _vertSource = value; } - } - public virtual string fragSource - { - get { return _fragSource;} - set { _fragSource = value; } - } - public virtual string geomSource - { - get { return _geomSource; } - set { _geomSource = value; } - } - - public virtual Matrix4 MVP{ - set { mvp = value; } - get { return mvp; } - } - #endregion - - #region Public functions - /// - /// configure sources and compile - /// - public virtual void Init() - { - Compile (); - } - public void Reload(){ - loadSourcesFiles (); - Compile (); - } - public void SetSource(ShaderType shaderType, string _source){ - switch (shaderType) { - case ShaderType.FragmentShader: - fragSource = _source; - return; - case ShaderType.VertexShader: - vertSource = _source; - return; - case ShaderType.GeometryShader: - geomSource = _source; - return; - } - } - public string GetSource(ShaderType shaderType){ - switch (shaderType) { - case ShaderType.FragmentShader: - return fragSource; - case ShaderType.VertexShader: - return vertSource; - case ShaderType.GeometryShader: - return geomSource; - } - return ""; - } - public string GetSourcePath(ShaderType shaderType){ - switch (shaderType) { - case ShaderType.FragmentShader: - return FragSourcePath; - case ShaderType.VertexShader: - return VertSourcePath; - case ShaderType.GeometryShader: - return GeomSourcePath; - } - return ""; - } - public virtual void Compile() - { - Dispose (); - - pgmId = GL.CreateProgram(); - - if (!string.IsNullOrEmpty(vertSource)) - { - vsId = GL.CreateShader(ShaderType.VertexShader); - compileShader(vsId, vertSource); - } - if (!string.IsNullOrEmpty(fragSource)) - { - fsId = GL.CreateShader(ShaderType.FragmentShader); - compileShader(fsId, fragSource); - - } - if (!string.IsNullOrEmpty(geomSource)) - { - gsId = GL.CreateShader(ShaderType.GeometryShader); - compileShader(gsId,geomSource); - } - - if (vsId != 0) - GL.AttachShader(pgmId, vsId); - if (fsId != 0) - GL.AttachShader(pgmId, fsId); - if (gsId != 0) - GL.AttachShader(pgmId, gsId); - - BindVertexAttributes (); - - string info; - GL.LinkProgram(pgmId); - GL.GetProgramInfoLog(pgmId, out info); - - if (!string.IsNullOrEmpty (info)) { - Debug.WriteLine ("Linkage:"); - Debug.WriteLine (info); - } - - info = null; - - GL.ValidateProgram(pgmId); - GL.GetProgramInfoLog(pgmId, out info); - if (!string.IsNullOrEmpty (info)) { - Debug.WriteLine ("Validation:"); - Debug.WriteLine (info); - } - - GL.UseProgram (pgmId); - - GetUniformLocations (); - BindSamplesSlots (); - - Disable (); - } - - protected virtual void BindVertexAttributes() - { - GL.BindAttribLocation(pgmId, 0, "in_position"); - GL.BindAttribLocation(pgmId, 1, "in_tex"); - } - protected virtual void GetUniformLocations() - { - mvpLocation = GL.GetUniformLocation(pgmId, "mvp"); - } - protected virtual void BindSamplesSlots(){ - GL.Uniform1(GL.GetUniformLocation (pgmId, "tex"), 0); - } - public void SetMVP(Matrix4 _mvp){ - GL.UniformMatrix4(mvpLocation, false, ref _mvp); - } - public virtual void Enable(){ - GL.UseProgram (pgmId); - } - public virtual void Disable(){ - GL.UseProgram (0); - } - public static void Enable(Shader s) - { - if (s == null) - return; - s.Enable (); - } - public static void Disable(Shader s) - { - if (s == null) - return; - s.Disable (); - } - #endregion - - void loadSourcesFiles(){ - Stream s; - - if (!string.IsNullOrEmpty (VertSourcePath)) { - s = Crow.Interface.GetStreamFromPath (VertSourcePath); - if (s != null) { - using (StreamReader sr = new StreamReader (s)) { - vertSource = sr.ReadToEnd (); - } - } - } - - if (!string.IsNullOrEmpty (FragSourcePath)) { - s = Crow.Interface.GetStreamFromPath (FragSourcePath); - if (s != null) { - using (StreamReader sr = new StreamReader (s)) { - fragSource = sr.ReadToEnd (); - } - } - } - - if (!string.IsNullOrEmpty (GeomSourcePath)) { - s = Crow.Interface.GetStreamFromPath (GeomSourcePath); - if (s != null) { - using (StreamReader sr = new StreamReader (s)) { - geomSource = sr.ReadToEnd (); - } - } - } - } - void compileShader(int shader, string source) - { - GL.ShaderSource(shader, source); - GL.CompileShader(shader); - - string info; - GL.GetShaderInfoLog(shader, out info); - Debug.WriteLine(info); - - int compileResult; - GL.GetShader(shader, ShaderParameter.CompileStatus, out compileResult); - if (compileResult != 1) - { - Debug.WriteLine("Compile Error!"); - Debug.WriteLine(source); - } - } - public override string ToString () - { - return string.Format ("{0} {1} {2}", VertSourcePath, FragSourcePath, GeomSourcePath); - } - - #region IDisposable implementation - public virtual void Dispose () - { - if (GL.IsProgram (pgmId)) - GL.DeleteProgram (pgmId); - - if (GL.IsShader (vsId)) - GL.DeleteShader (vsId); - if (GL.IsShader (fsId)) - GL.DeleteShader (fsId); - if (GL.IsShader (gsId)) - GL.DeleteShader (gsId); - } - #endregion - } -} diff --git a/CrowIDE/OpenGL/Texture.cs b/CrowIDE/OpenGL/Texture.cs deleted file mode 100644 index e6bec071..00000000 --- a/CrowIDE/OpenGL/Texture.cs +++ /dev/null @@ -1,94 +0,0 @@ -// -// Texture.cs -// -// Author: -// Jean-Philippe Bruyère -// -// Copyright (c) 2016 jp -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -using System; -using System.Drawing; -using OpenTK.Graphics.OpenGL; -using System.Drawing.Imaging; -using System.IO; -using System.Diagnostics; - -namespace Crow -{ - public class Texture - { - public string Map; - public int texRef; - public int Width; - public int Height; - - public Texture(string _mapPath, bool flipY = true) - { - using (Stream s = Interface.GetStreamFromPath (_mapPath)) { - - try { - Map = _mapPath; - - Bitmap bitmap = new Bitmap (s); - - if (flipY) - bitmap.RotateFlip (RotateFlipType.RotateNoneFlipY); - - BitmapData data = bitmap.LockBits (new System.Drawing.Rectangle (0, 0, bitmap.Width, bitmap.Height), - ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb); - - createTexture (data.Scan0, data.Width, data.Height); - - bitmap.UnlockBits (data); - - GL.TexParameter (TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.LinearMipmapLinear); - GL.TexParameter (TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear); - - GL.GenerateMipmap (GenerateMipmapTarget.Texture2D); - - } catch (Exception ex) { - Debug.WriteLine ("Error loading texture: " + Map + ":" + ex.Message); - } - } - } - - public Texture(int width, int height) - { - createTexture (IntPtr.Zero, width, height); - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear); - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear); - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.Clamp); - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.Clamp); - } - - void createTexture(IntPtr data, int width, int height) - { - Width = width; - Height = height; - - GL.GenTextures(1, out texRef); - GL.BindTexture(TextureTarget.Texture2D, texRef); - GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, width, height, 0, - OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, data); - } - - public static implicit operator int(Texture t) - { - return t == null ? 0: t.texRef; - } - } - -} diff --git a/CrowIDE/OpenGL/vaoMesh.cs b/CrowIDE/OpenGL/vaoMesh.cs deleted file mode 100644 index c0b24528..00000000 --- a/CrowIDE/OpenGL/vaoMesh.cs +++ /dev/null @@ -1,221 +0,0 @@ -// -// vaoMesh.cs -// -// Author: -// Jean-Philippe Bruyère -// -// Copyright (c) 2016 jp -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -using System; -using OpenTK; -using OpenTK.Graphics.OpenGL; - -namespace Crow -{ - public class vaoMesh : IDisposable - { - public int vaoHandle, - positionVboHandle, - texVboHandle, - eboHandle; - - public Vector3[] positions; - public Vector2[] texCoords; - public int[] indices; - - public vaoMesh() - { - } - - public vaoMesh (Vector3[] _positions, Vector2[] _texCoord, int[] _indices) - { - positions = _positions; - texCoords = _texCoord; - indices = _indices; - - CreateBuffers (); - } - - public vaoMesh (float x, float y, float z, float width, float height, float TileX = 1f, float TileY = 1f) - { - positions = - new Vector3[] { - new Vector3 (x - width / 2, y + height / 2, z), - new Vector3 (x - width / 2, y - height / 2, z), - new Vector3 (x + width / 2, y + height / 2, z), - new Vector3 (x + width / 2, y - height / 2, z) - }; - texCoords = new Vector2[] { - new Vector2 (0, TileY), - new Vector2 (0, 0), - new Vector2 (TileX, TileY), - new Vector2 (TileX, 0) - }; - indices = new int[] { 0, 1, 2, 3 }; - - CreateBuffers (); - } - public static vaoMesh CreateCube(){ - vaoMesh tmp = new vaoMesh (); - tmp.positions = new Vector3[] - { - new Vector3(-1.0f, -1.0f, -1.0f), - new Vector3( -1.0f, -1.0f, 1.0f), - new Vector3( 1.0f, -1.0f, -1.0f), - new Vector3(1.0f, -1.0f, 1.0f), - new Vector3(1.0f, 1.0f, -1.0f), - new Vector3( 1.0f, 1.0f, 1.0f), - new Vector3( -1.0f, 1.0f, -1.0f), - new Vector3(-1.0f, 1.0f, 1.0f) - }; - tmp.indices = new int[] - { - // front face - 0, 2, 1, 1, 2, 3, - // top face - 2, 4, 3, 3, 4, 5, - // back face - 4, 6, 5, 5, 6, 7, - // left face - 6, 0, 7, 7, 0, 1, - // bottom face - 1, 3, 7, 7, 3, 5, - // right face -// 1, 5, 6, 6, 2, 1, - }; - tmp.texCoords = new Vector2[] - { - new Vector2(0, 0), - new Vector2(0, 1), - new Vector2(1, 0), - new Vector2(1, 1), - new Vector2(0, 0), - new Vector2(0, 1), - new Vector2(1, 0), - new Vector2(1, 1), - }; - tmp.CreateBuffers (); - return tmp; -// Normals = new Vector3[] -// { -// new Vector3(-1.0f, -1.0f, 1.0f), -// new Vector3( 1.0f, -1.0f, 1.0f), -// new Vector3( 1.0f, 1.0f, 1.0f), -// new Vector3(-1.0f, 1.0f, 1.0f), -// new Vector3(-1.0f, -1.0f, -1.0f), -// new Vector3( 1.0f, -1.0f, -1.0f), -// new Vector3( 1.0f, 1.0f, -1.0f), -// new Vector3(-1.0f, 1.0f, -1.0f), -// }; -// -// Colors = new int[] -// { -// Utilities.ColorToRgba32(Color.DarkRed), -// Utilities.ColorToRgba32(Color.DarkRed), -// Utilities.ColorToRgba32(Color.Gold), -// Utilities.ColorToRgba32(Color.Gold), -// Utilities.ColorToRgba32(Color.DarkRed), -// Utilities.ColorToRgba32(Color.DarkRed), -// Utilities.ColorToRgba32(Color.Gold), -// Utilities.ColorToRgba32(Color.Gold), -// }; - } - public void CreateBuffers(){ - CreateVBOs (); - CreateVAOs (); - } - protected void CreateVBOs() - { - positionVboHandle = GL.GenBuffer(); - GL.BindBuffer(BufferTarget.ArrayBuffer, positionVboHandle); - GL.BufferData(BufferTarget.ArrayBuffer, - new IntPtr(positions.Length * Vector3.SizeInBytes), - positions, BufferUsageHint.StaticDraw); - - if (texCoords != null) { - texVboHandle = GL.GenBuffer (); - GL.BindBuffer (BufferTarget.ArrayBuffer, texVboHandle); - GL.BufferData (BufferTarget.ArrayBuffer, - new IntPtr (texCoords.Length * Vector2.SizeInBytes), - texCoords, BufferUsageHint.StaticDraw); - } - - GL.BindBuffer(BufferTarget.ArrayBuffer, 0); - - if (indices != null) { - eboHandle = GL.GenBuffer (); - GL.BindBuffer (BufferTarget.ElementArrayBuffer, eboHandle); - GL.BufferData (BufferTarget.ElementArrayBuffer, - new IntPtr (sizeof(uint) * indices.Length), - indices, BufferUsageHint.StaticDraw); - GL.BindBuffer(BufferTarget.ElementArrayBuffer, 0); - } - } - protected void CreateVAOs() - { - vaoHandle = GL.GenVertexArray(); - GL.BindVertexArray(vaoHandle); - - GL.EnableVertexAttribArray(0); - GL.BindBuffer(BufferTarget.ArrayBuffer, positionVboHandle); - GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, true, Vector3.SizeInBytes, 0); - - if (texCoords != null) { - GL.EnableVertexAttribArray (1); - GL.BindBuffer (BufferTarget.ArrayBuffer, texVboHandle); - GL.VertexAttribPointer (1, 2, VertexAttribPointerType.Float, true, Vector2.SizeInBytes, 0); - } - if (indices != null) - GL.BindBuffer(BufferTarget.ElementArrayBuffer, eboHandle); - - GL.BindVertexArray(0); - } - - public void Render(BeginMode _primitiveType){ - GL.BindVertexArray(vaoHandle); - if (indices == null) - GL.DrawArrays (_primitiveType, 0, positions.Length); - else - GL.DrawElements(_primitiveType, indices.Length, - DrawElementsType.UnsignedInt, IntPtr.Zero); - GL.BindVertexArray (0); - } - public void Render(BeginMode _primitiveType, int[] _customIndices){ - GL.BindVertexArray(vaoHandle); - GL.DrawElements(_primitiveType, _customIndices.Length, - DrawElementsType.UnsignedInt, _customIndices); - GL.BindVertexArray (0); - } - public void Render(BeginMode _primitiveType, int instances){ - - GL.BindVertexArray(vaoHandle); - GL.DrawElementsInstanced(_primitiveType, indices.Length, - DrawElementsType.UnsignedInt, IntPtr.Zero, instances); - GL.BindVertexArray (0); - } - - #region IDisposable implementation - public void Dispose () - { - GL.DeleteBuffer (positionVboHandle); - GL.DeleteBuffer (texVboHandle); - GL.DeleteBuffer (eboHandle); - GL.DeleteVertexArray (vaoHandle); - } - #endregion - - } -} \ No newline at end of file diff --git a/CrowIDE/OpenTKGameWindow.cs b/CrowIDE/OpenTKGameWindow.cs deleted file mode 100644 index b3851904..00000000 --- a/CrowIDE/OpenTKGameWindow.cs +++ /dev/null @@ -1,334 +0,0 @@ -// -// OpenTKGameWindow.cs -// -// Author: -// Jean-Philippe Bruyère -// -// Copyright (c) 2016 jp -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -using System; -using System.Threading; -using OpenTK; -using OpenTK.Graphics.OpenGL; - -namespace Crow -{ - public class OpenTKGameWindow : GameWindow, IValueChange - { - #region IValueChange implementation - public event EventHandler ValueChanged; - public virtual void NotifyValueChanged(string MemberName, object _value) - { - if (ValueChanged != null) - ValueChanged.Invoke(this, new ValueChangeEventArgs(MemberName, _value)); - } - #endregion - - public Interface CrowInterface; - - #region FPS - int frameCpt = 0; - int _fps = 0; - - public int fps { - get { return _fps; } - set { - if (_fps == value) - return; - - _fps = value; - - if (_fps > fpsMax) { - fpsMax = _fps; - ValueChanged.Raise(this, new ValueChangeEventArgs ("fpsMax", fpsMax)); - } else if (_fps < fpsMin) { - fpsMin = _fps; - ValueChanged.Raise(this, new ValueChangeEventArgs ("fpsMin", fpsMin)); - } - - ValueChanged.Raise(this, new ValueChangeEventArgs ("fps", _fps)); - #if MEASURE_TIME - ValueChanged.Raise (this, new ValueChangeEventArgs ("update", - this.CrowInterface.updateTime.ElapsedTicks.ToString () + " ticks")); - ValueChanged.Raise (this, new ValueChangeEventArgs ("layouting", - this.CrowInterface.layoutTime.ElapsedTicks.ToString () + " ticks")); - ValueChanged.Raise (this, new ValueChangeEventArgs ("drawing", - this.CrowInterface.drawingTime.ElapsedTicks.ToString () + " ticks")); - ValueChanged.Raise (this, new ValueChangeEventArgs ("clipping", - this.CrowInterface.clippingTime.ElapsedTicks.ToString () + " ticks")); - #endif - } - } - - public int fpsMin = int.MaxValue; - public int fpsMax = 0; - - void resetFps () - { - fpsMin = int.MaxValue; - fpsMax = 0; - _fps = 0; - } - public string update = ""; - public string drawing = ""; - public string layouting = ""; - public string clipping = ""; - #endregion - - #region ctor - public OpenTKGameWindow(int _width = 800, int _height = 600, 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), - _title,GameWindowFlags.Default,DisplayDevice.Default, - major,minor,OpenTK.Graphics.GraphicsContextFlags.Default) - { - } - public OpenTKGameWindow (int width, int height, OpenTK.Graphics.GraphicsMode mode, string title, GameWindowFlags options, DisplayDevice device, int major, int minor, OpenTK.Graphics.GraphicsContextFlags flags) - : base(width,height,mode,title,options,device,major,minor,flags) - { - CrowInterface = new Interface (); - - Thread t = new Thread (interfaceThread); - t.IsBackground = true; - t.Start (); - } - - #endregion - - void interfaceThread() - { - CrowInterface.Quit += Quit; - CrowInterface.MouseCursorChanged += CrowInterface_MouseCursorChanged; - while (CrowInterface.ClientRectangle.Size.Width == 0) - Thread.Sleep (5); - - while (true) { - CrowInterface.Update (); - Thread.Sleep (1); - } - } - - public void Quit (object sender, EventArgs e) - { - this.Exit (); - } - void CrowInterface_MouseCursorChanged (object sender, MouseCursorChangedEventArgs e) - { - this.Cursor = new MouseCursor( - (int)e.NewCursor.Xhot, - (int)e.NewCursor.Yhot, - (int)e.NewCursor.Width, - (int)e.NewCursor.Height, - e.NewCursor.data); - } - - #region Events - //those events are raised only if mouse isn't in a graphic object - public event EventHandler MouseWheelChanged; - public event EventHandler MouseButtonUp; - public event EventHandler MouseButtonDown; - public event EventHandler MouseClick; - public event EventHandler MouseMove; - public event EventHandler KeyboardKeyDown; - public event EventHandler KeyboardKeyUp; - - #endregion - - #region graphic context - public int texID; - public Shader shader; - public vaoMesh quad; - public Matrix4 projection; - - void createContext() - { - #region Create texture - if (GL.IsTexture(texID)) - GL.DeleteTexture (texID); - GL.GenTextures(1, out texID); - GL.ActiveTexture (TextureUnit.Texture0); - GL.BindTexture(TextureTarget.Texture2D, texID); - - GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, - ClientRectangle.Width, ClientRectangle.Height, 0, - OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, CrowInterface.bmp); - - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear); - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear); - - GL.BindTexture(TextureTarget.Texture2D, 0); - #endregion - } - void OpenGLDraw() - { - bool blend, depthTest; - GL.GetBoolean (GetPName.Blend, out blend); - GL.GetBoolean (GetPName.DepthTest, out depthTest); - GL.Enable (EnableCap.Blend); - GL.Disable (EnableCap.DepthTest); - - shader.Enable (); - shader.SetMVP (projection); - GL.ActiveTexture (TextureUnit.Texture0); - GL.BindTexture (TextureTarget.Texture2D, texID); - lock (CrowInterface.RenderMutex) { - if (CrowInterface.IsDirty) { - GL.TexSubImage2D (TextureTarget.Texture2D, 0, - CrowInterface.DirtyRect.Left, CrowInterface.DirtyRect.Top, - CrowInterface.DirtyRect.Width, CrowInterface.DirtyRect.Height, - OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, CrowInterface.dirtyBmp); - CrowInterface.IsDirty = false; - } - } - quad.Render (BeginMode.TriangleStrip); - GL.BindTexture(TextureTarget.Texture2D, 0); - - if (!blend) - GL.Disable (EnableCap.Blend); - if (depthTest) - GL.Enable (EnableCap.DepthTest); - } - #endregion - - /// - /// Override this method for your OpenGL rendering calls - /// - public virtual void OnRender(FrameEventArgs e) - { - } - /// - /// Override this method to customize clear method between frames - /// - public virtual void GLClear() - { - GL.Clear (ClearBufferMask.ColorBufferBit|ClearBufferMask.DepthBufferBit); - } - - #region Game win overrides - protected override void OnLoad(EventArgs e) - { - base.OnLoad(e); - - this.KeyPress += new EventHandler(OpenTKGameWindow_KeyPress); - Keyboard.KeyDown += new EventHandler(Keyboard_KeyDown); - Keyboard.KeyUp += new EventHandler(Keyboard_KeyUp); - Mouse.WheelChanged += new EventHandler(Mouse_WheelChanged); - Mouse.ButtonDown += new EventHandler(Mouse_ButtonDown); - Mouse.ButtonUp += new EventHandler(Mouse_ButtonUp); - Mouse.Move += new EventHandler(Mouse_Move); - - GL.ClearColor(0.0f, 0.0f, 0.0f, 0.0f); - - Console.WriteLine("\n\n*************************************"); - Console.WriteLine("GL version: " + GL.GetString (StringName.Version)); - Console.WriteLine("GL vendor: " + GL.GetString (StringName.Vendor)); - Console.WriteLine("GLSL version: " + GL.GetString (StringName.ShadingLanguageVersion)); - Console.WriteLine("*************************************\n"); - - projection = OpenTK.Matrix4.CreateOrthographicOffCenter (-0.5f, 0.5f, -0.5f, 0.5f, 1, -1); - - shader = new Shader (); - quad = new Crow.vaoMesh (0, 0, 0, 1, 1, 1, -1); - } - - protected override void OnUpdateFrame(FrameEventArgs e) - { - base.OnUpdateFrame(e); - fps = (int)RenderFrequency; - - - if (frameCpt > 50) { - resetFps (); - frameCpt = 0; - GC.Collect(); - GC.WaitForPendingFinalizers(); - NotifyValueChanged("memory", GC.GetTotalMemory (false).ToString()); - } - frameCpt++; - } - protected override void OnRenderFrame(FrameEventArgs e) - { - GLClear (); - - base.OnRenderFrame(e); - - OnRender (e); - OpenGLDraw (); - - SwapBuffers (); - } - - protected override void OnResize(EventArgs e) - { - base.OnResize (e); - CrowInterface.ProcessResize( - new Rectangle( - 0, - 0, - this.ClientRectangle.Width, - this.ClientRectangle.Height)); - createContext (); - GL.Viewport (0, 0, ClientRectangle.Width, ClientRectangle.Height); - } - #endregion - - #region Mouse Handling - void update_mouseButtonStates(ref MouseState e, OpenTK.Input.MouseState otk_e){ - for (int i = 0; i < MouseState.MaxButtons; i++) { - if (otk_e.IsButtonDown ((OpenTK.Input.MouseButton)i)) - e.EnableBit (i); - } - } - void Mouse_Move(object sender, OpenTK.Input.MouseMoveEventArgs otk_e) - { - if (!CrowInterface.ProcessMouseMove (otk_e.X, otk_e.Y)) - MouseMove.Raise (sender, otk_e); - } - void Mouse_ButtonUp(object sender, OpenTK.Input.MouseButtonEventArgs otk_e) - { - if (!CrowInterface.ProcessMouseButtonUp ((int)otk_e.Button)) - MouseButtonUp.Raise (sender, otk_e); - } - void Mouse_ButtonDown(object sender, OpenTK.Input.MouseButtonEventArgs otk_e) - { - if (!CrowInterface.ProcessMouseButtonDown ((int)otk_e.Button)) - MouseButtonDown.Raise (sender, otk_e); - } - void Mouse_WheelChanged(object sender, OpenTK.Input.MouseWheelEventArgs otk_e) - { - if (!CrowInterface.ProcessMouseWheelChanged (otk_e.DeltaPrecise)) - MouseWheelChanged.Raise (sender, otk_e); - } - #endregion - - #region keyboard Handling - void Keyboard_KeyDown(object sender, OpenTK.Input.KeyboardKeyEventArgs otk_e) - { - if (!CrowInterface.ProcessKeyDown((int)otk_e.Key)) - KeyboardKeyDown.Raise (this, otk_e); - } - void Keyboard_KeyUp(object sender, OpenTK.Input.KeyboardKeyEventArgs otk_e) - { - if (!CrowInterface.ProcessKeyUp((int)otk_e.Key)) - KeyboardKeyUp.Raise (this, otk_e); - } - void OpenTKGameWindow_KeyPress (object sender, OpenTK.KeyPressEventArgs e) - { - CrowInterface.ProcessKeyPress (e.KeyChar); - } - #endregion - } -} diff --git a/CrowIDE/src/Application.cs b/CrowIDE/src/Application.cs new file mode 100644 index 00000000..b6bf5bc1 --- /dev/null +++ b/CrowIDE/src/Application.cs @@ -0,0 +1,614 @@ +// +// DrmKms.cs +// +// Author: +// Jean-Philippe Bruyère +// +// 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.IO; +using System.Collections.Generic; +using System.Diagnostics; +using System.Runtime.InteropServices; +using System.Threading; + +using Linux; +using Linux.VT; +using System.Text; + +namespace Crow +{ + public class Application : IDisposable + { + public enum RunState { + ActivateRequest, + DesactivateRequest, + Paused, + Running, + } + #if MEASURE_TIME + public List PerfMeasures; + protected PerformanceMeasure glDrawMeasure = new PerformanceMeasure("OpenGL Draw", 10); + #endif + + public bool Running = true; + public volatile RunState CurrentState = RunState.Running; + + protected Interface CrowInterface; + protected DRI.DRIControler gpu; + protected Cairo.GLSurface cairoSurf { get { return gpu?.CairoSurf; }} + + protected bool mouseIsInInterface = false; + + protected volatile int ifaceSleep = 1, updateSleep = 0; + + void interfaceThread() + { + while (CrowInterface.ClientRectangle.Size.Width == 0) + Thread.Sleep (5); + + while (true) { + if (CurrentState == RunState.Running) { + CrowInterface.Update (); + Thread.Sleep (ifaceSleep); + } else + Thread.Sleep (1000); + } + } + + int previousVT = -1, appVT = -1; + + public Application(){ + if (Kernel.signal (Signal.SIGUSR1, switch_request_handle) < 0) + throw new Exception ("signal handler registation failed"); +// if (Kernel.signal (Signal.SIGUSR2, switch_request_handle) < 0) +// throw new Exception ("signal handler registation failed"); + if (Kernel.signal (Signal.SIGINT, sigint_handler) < 0) + throw new Exception ("SIGINT handler registation failed"); + + using (VTControler master = new VTControler ()) { + previousVT = master.CurrentVT; + appVT = master.FirstAvailableVT; + + master.SwitchTo (appVT); + + try { + master.KDMode = KDMode.GRAPHICS; +// VT.vt_mode vtm = master.VTMode; +// vtm.mode = VT.SwitchMode.PROCESS; +// master.VTMode = vtm; + } catch (Exception ex) { + Console.WriteLine (ex.ToString ()); + } + } + + initDri (); + + initCrow (); + + initInput (); + + MouseX = gpu.Width / 2; + MouseY = gpu.Height / 2; + + initCursor (); + } + + #region CROW + public GraphicObject Load (string path){ + return CrowInterface.LoadInterface (path); + } + + void initCrow () { + CrowInterface = new Interface (); + + Thread t = new Thread (interfaceThread); + t.Name = "Interface"; + t.IsBackground = true; + t.Start (); + + CrowInterface.ProcessResize (new Size (gpu.Width, gpu.Height)); + CrowInterface.MouseCursorChanged += CrowInterface_MouseCursorChanged; + + #if MEASURE_TIME + PerfMeasures = new List ( + new PerformanceMeasure[] { + this.CrowInterface.updateMeasure, + this.CrowInterface.layoutingMeasure, + this.CrowInterface.clippingMeasure, + this.CrowInterface.drawingMeasure, + this.glDrawMeasure + } + ); + #endif + } + void CrowInterface_MouseCursorChanged (object sender, MouseCursorChangedEventArgs e) + { + gpu.updateCursor (e.NewCursor); + } + #endregion + + void initDri(){ + gpu = new DRI.DRIControler(); + //cairoSurf = gpu.CairoSurf; + } + void initCursor(){ + gpu.updateCursor (XCursor.Default); + gpu.moveCursor ((uint)MouseX - 8, (uint)MouseY - 4); + } + + void switch_request_handle (Signal s){ + Console.WriteLine ("****** switch request catched: " + s.ToString()); + using (VTControler master = new VTControler ()) { + Libc.write (master.fd, Encoding.ASCII.GetBytes ("this is a test string")); + master.AcknoledgeSwitchRequest (); + } + } + void sigint_handler (Signal s){ + Console.WriteLine ("{0}: SIGINT catched"); + Running = false; + } + + public virtual void Run () + { + int cpt = 0; + while(Running){ + switch (CurrentState) { + case RunState.ActivateRequest: + activate (); + continue; + case RunState.DesactivateRequest: + desactivate (); + continue; + case RunState.Paused: + Thread.Sleep (1000); + continue; + } + + uiDraw (); + + #if MEASURE_TIME + if (cpt%10==0){ + foreach (PerformanceMeasure m in PerfMeasures) + m.NotifyChanges(); + } + #endif + + cpt++; + Thread.Sleep (updateSleep); + } + } + protected virtual void uiDraw (){ +// #if MEASURE_TIME +// glDrawMeasure.StartCycle(); +// #endif + + bool update = false; + + if (updateMousePos) { + lock (Sync) { + updateMousePos = false; + gpu.moveCursor ((uint)MouseX - 8, (uint)MouseY - 4); + } + } + + if (Monitor.TryEnter (CrowInterface.RenderMutex)) { + if (CrowInterface.IsDirty) { + CrowInterface.IsDirty = false; + update = true; + Rectangle r = CrowInterface.DirtyRect; + using (Cairo.Context ctx = new Cairo.Context (cairoSurf)) { + using (Cairo.Surface d = new Cairo.ImageSurface (CrowInterface.dirtyBmp, Cairo.Format.ARGB32, + r.Width, r.Height, r.Width * 4)) { + ctx.SetSourceSurface (d, 0, 0); + ctx.Operator = Cairo.Operator.Source; + ctx.Paint (); + } + } + } + Monitor.Exit (CrowInterface.RenderMutex); + } + +// if (!update) +// return; +// update = false; + + + + + cairoSurf.Flush (); + cairoSurf.SwapBuffers (); + + //gpu.UpdateWithPageFlip (); + gpu.Update(); + +// #if MEASURE_TIME +// glDrawMeasure.StopCycle (); +// #endif + } + + #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.Name = "input_thread"; + 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) + { + if (CurrentState != RunState.Running) { + Thread.Sleep (1000); + continue; + } + //drmTimeOut.Restart (); + + 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(LibInput.GetKeyboardEvent(pevent)); + break; + // + case InputEventType.PointerAxis: + handlePointerAxis(LibInput.GetPointerEvent(pevent)); + break; + + case InputEventType.PointerButton: + handlePointerButton (LibInput.GetPointerEvent(pevent)); + break; + + case InputEventType.PointerMotion: + handlePointerMotion (LibInput.GetPointerEvent(pevent)); + break; + +// case InputEventType.PointerMotionAbsolute: +// handlePointerMotionAbsolute(LibInput.GetPointerEvent(pevent)); +// break; + } + } + + LibInput.DestroyEvent(pevent); + } + } + int MouseX = 0, MouseY = 0; + volatile bool updateMousePos = true; + + int roundDelta (double d){ + return d > 0 ? (int)Math.Ceiling(d) : (int)Math.Floor (d); + } + void handlePointerAxis(PointerEvent e){ +// if (e.HasAxis(PointerAxis.HorizontalScroll)) +// { +// CrowInterface.ProcessMouseWheelChanged ((float)e.AxisValue (PointerAxis.HorizontalScroll)); +// } + if (e.HasAxis(PointerAxis.VerticalScroll)) + { + CrowInterface.ProcessMouseWheelChanged ((float)-e.AxisValue (PointerAxis.VerticalScroll)); + } + } + void handlePointerMotion(PointerEvent e) + { + MouseX += roundDelta (e.DeltaX); + MouseY += roundDelta (e.DeltaY); + + Rectangle bounds = CrowInterface.ClientRectangle; + if (MouseX < bounds.Left) + MouseX = bounds.Left; + else if (MouseX > bounds.Right) + MouseX = bounds.Right; + + if (MouseY < bounds.Top) + MouseY = bounds.Top; + else if (MouseY > bounds.Bottom) + MouseY = bounds.Bottom; + + CrowInterface.ProcessMouseMove (MouseX, MouseY); + + updateMousePos = true; + } + void handlePointerButton (PointerEvent e) + { + int but = 0; + switch (e.Button) { + case EvdevButton.LEFT: + but = 0; + break; + case EvdevButton.MIDDLE: + but = 1; + break; + case EvdevButton.RIGHT: + but = 2; + break; + } + if (e.ButtonState == global::Linux.ButtonState.Pressed) + CrowInterface.ProcessMouseButtonDown (but); + else + CrowInterface.ProcessMouseButtonUp (but); + } + + KeyModifiers curModifiers = KeyModifiers.None; + + void handleKeyboard(KeyboardEvent e) + { + int key = (int)Evdev.KeyMap [e.Key]; + Key k = (Key)key; + if (e.KeyState == KeyState.Pressed) { + CrowInterface.ProcessKeyDown (key); + switch (k) { + case Key.ShiftLeft: + case Key.ShiftRight: + curModifiers |= KeyModifiers.Shift; + break; + case Key.ControlLeft: + case Key.ControlRight: + curModifiers |= KeyModifiers.Control; + break; + case Key.AltLeft: + curModifiers |= KeyModifiers.Alt; + break; + case Key.AltRight: + curModifiers |= KeyModifiers.AltGr; + break; + } + }else { + CrowInterface.ProcessKeyUp (key); + switch (k) { + case Key.ShiftLeft: + case Key.ShiftRight: + curModifiers &= ~KeyModifiers.Shift; + break; + case Key.ControlLeft: + case Key.ControlRight: + curModifiers &= ~KeyModifiers.Control; + break; + case Key.AltLeft: + curModifiers &= ~KeyModifiers.Alt; + break; + case Key.AltRight: + curModifiers &= ~KeyModifiers.AltGr; + break; + } +// if (!keymap.ContainsKey (curModifiers)) { +// Console.WriteLine ("keymap not found for: " + curModifiers + " " + (int)curModifiers); +// return; +// } + // string tmp = keymap [curModifiers] [e.Key]; + // if (string.IsNullOrEmpty (tmp)) + // return; + // if (char.IsControl (tmp[0])) + // return; + // CrowInterface.ProcessKeyPress (tmp [0]); + } + } + + #endregion + + + + void desactivate () { + CurrentState = RunState.Paused; + + //cairoSurf = null; + gpu.Dispose (); + gpu = null; + } + void activate (){ + initDri(); + initCursor (); + + CurrentState = RunState.Running; + } + + #region IDisposable implementation + ~Application(){ + Dispose (false); + } + public void Dispose () + { + Dispose (true); + GC.SuppressFinalize (this); + } + protected virtual void Dispose (bool disposing){ + if (gpu != null) + gpu.Dispose (); + gpu = null; + + using (VTControler master = new VTControler ()) { + // try { + // master.KDMode = VT.KDMode.TEXT; + // } catch (Exception ex) { + // Console.WriteLine (ex.ToString ()); + // } + master.SwitchTo (previousVT); + } + + } + #endregion + } +} + diff --git a/testDrm/src/Linux/Bindings/Evdev.cs b/CrowIDE/src/Bindings/Evdev.cs similarity index 99% rename from testDrm/src/Linux/Bindings/Evdev.cs rename to CrowIDE/src/Bindings/Evdev.cs index 96bbd18c..3aaca78e 100644 --- a/testDrm/src/Linux/Bindings/Evdev.cs +++ b/CrowIDE/src/Bindings/Evdev.cs @@ -25,7 +25,6 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // -using OpenTK; using Linux; using Crow; @@ -415,7 +414,7 @@ namespace Linux unsafe { sbyte* pname = stackalloc sbyte[129]; - int ret = Libc.ioctl(fd, EvdevIoctl.Name128, new IntPtr(pname)); + int ret = Libc.ioctl(fd, (uint)EvdevIoctl.Name128, new IntPtr(pname)); name = new string(pname); return ret; } @@ -428,7 +427,7 @@ namespace Linux { fixed (EvdevInputId* pid = &id) { - return Libc.ioctl(fd, EvdevIoctl.Id, new IntPtr(pid)); + return Libc.ioctl(fd, (uint)EvdevIoctl.Id, new IntPtr(pid)); } } } diff --git a/CrowIDE/src/Bindings/LibInput.cs b/CrowIDE/src/Bindings/LibInput.cs new file mode 100644 index 00000000..6db92722 --- /dev/null +++ b/CrowIDE/src/Bindings/LibInput.cs @@ -0,0 +1,338 @@ +#region License +// +// LibInput.cs +// +// Author: +// Stefanos A. +// +// Copyright (c) 2006-2014 Stefanos Apostolopoulos +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +#endregion + +#pragma warning disable 0169, 0219 + +using System; +using System.Diagnostics; +using System.Runtime.InteropServices; + +namespace 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 + /// + /// Signals the end of a set of touchpoints at one device sample + /// time. This event has no coordinate information attached. + /// + 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); + + public override string ToString () + { + return string.Format ("[PointerEvent: BaseEvent={0}, Event={1}, Time={2}, Button={3}, ButtonCount={4}, ButtonState={5}, DeltaX={6}, DeltaY={7}, X={8}, Y={9}]", BaseEvent, Event, Time, Button, ButtonCount, ButtonState, DeltaX, DeltaY, X, Y); + } + } +} + diff --git a/CrowIDE/src/Bindings/Poll.cs b/CrowIDE/src/Bindings/Poll.cs new file mode 100644 index 00000000..d3a663b5 --- /dev/null +++ b/CrowIDE/src/Bindings/Poll.cs @@ -0,0 +1,65 @@ +#region License +// +// Poll.cs +// +// Author: +// Stefanos A. +// +// Copyright (c) 2006-2014 Stefanos Apostolopoulos +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +#endregion + +using System; +using System.Runtime.InteropServices; + +namespace 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/CrowIDE/src/Bindings/Udev.cs b/CrowIDE/src/Bindings/Udev.cs new file mode 100644 index 00000000..25496f9c --- /dev/null +++ b/CrowIDE/src/Bindings/Udev.cs @@ -0,0 +1,46 @@ +#region License +// +// Udev.cs +// +// Author: +// Stefanos A. +// +// Copyright (c) 2006-2014 Stefanos Apostolopoulos +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +#endregion + +using System; +using System.Runtime.InteropServices; + +namespace 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/CrowIDE/src/BlittableValueType.cs b/CrowIDE/src/BlittableValueType.cs new file mode 100644 index 00000000..81ce16ae --- /dev/null +++ b/CrowIDE/src/BlittableValueType.cs @@ -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 Linux +{ + #region BlittableValueType + + /// + /// Checks whether the specified type parameter is a blittable value type. + /// + /// + /// A blittable value type is a struct that only references other value types recursively, + /// which allows it to be passed to unmanaged code directly. + /// + public static class BlittableValueType + { + #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 + + /// + /// Gets the size of the type in bytes or 0 for non-blittable types. + /// + /// + /// This property returns 0 for non-blittable types. + /// + public static int Stride { get { return stride; } } + + #region Check + + /// + /// Checks whether the current typename T is blittable. + /// + /// True if T is blittable; false otherwise. + public static bool Check() + { + return Check(Type); + } + + /// + /// Checks whether type is a blittable value type. + /// + /// A System.Type to check. + /// True if T is blittable; false otherwise. + 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 + + /// + /// Checks whether the specified type parameter is a blittable value type. + /// + /// + /// A blittable value type is a struct that only references other value types recursively, + /// which allows it to be passed to unmanaged code directly. + /// + public static class BlittableValueType + { + #region Check + + /// + /// Checks whether type is a blittable value type. + /// + /// An instance of the type to check. + /// True if T is blittable; false otherwise. + public static bool Check(T type) + { + return BlittableValueType.Check(); + } + + /// + /// Checks whether type is a blittable value type. + /// + /// An instance of the type to check. + /// True if T is blittable; false otherwise. + [CLSCompliant(false)] + public static bool Check(T[] type) + { + return BlittableValueType.Check(); + } + + /// + /// Checks whether type is a blittable value type. + /// + /// An instance of the type to check. + /// True if T is blittable; false otherwise. + [CLSCompliant(false)] + public static bool Check(T[,] type) + { + return BlittableValueType.Check(); + } + + /// + /// Checks whether type is a blittable value type. + /// + /// An instance of the type to check. + /// True if T is blittable; false otherwise. + [CLSCompliant(false)] + public static bool Check(T[, ,] type) + { + return BlittableValueType.Check(); + } + + /// + /// Checks whether type is a blittable value type. + /// + /// An instance of the type to check. + /// True if T is blittable; false otherwise. + [CLSCompliant(false)] + public static bool Check(T[][] type) + { + return BlittableValueType.Check(); + } + + #endregion + + #region StrideOf + + /// + /// Returns the size of the specified value type in bytes or 0 if the type is not blittable. + /// + /// The value type. Must be blittable. + /// An instance of the value type. + /// An integer, specifying the size of the type in bytes. + /// Occurs when type is not blittable. + public static int StrideOf(T type) + { + if (!Check(type)) + throw new ArgumentException("type"); + + return BlittableValueType.Stride; + } + + /// + /// Returns the size of a single array element in bytes or 0 if the element is not blittable. + /// + /// The value type. + /// An instance of the value type. + /// An integer, specifying the size of the type in bytes. + /// Occurs when type is not blittable. + [CLSCompliant(false)] + public static int StrideOf(T[] type) + { + if (!Check(type)) + throw new ArgumentException("type"); + + return BlittableValueType.Stride; + } + + /// + /// Returns the size of a single array element in bytes or 0 if the element is not blittable. + /// + /// The value type. + /// An instance of the value type. + /// An integer, specifying the size of the type in bytes. + /// Occurs when type is not blittable. + [CLSCompliant(false)] + public static int StrideOf(T[,] type) + { + if (!Check(type)) + throw new ArgumentException("type"); + + return BlittableValueType.Stride; + } + + /// + /// Returns the size of a single array element in bytes or 0 if the element is not blittable. + /// + /// The value type. + /// An instance of the value type. + /// An integer, specifying the size of the type in bytes. + /// Occurs when type is not blittable. + [CLSCompliant(false)] + public static int StrideOf(T[, ,] type) + { + if (!Check(type)) + throw new ArgumentException("type"); + + return BlittableValueType.Stride; + } + + #endregion + } + + #endregion +} diff --git a/CrowIDE/src/CrowIDEdrm.cs b/CrowIDE/src/CrowIDEdrm.cs new file mode 100644 index 00000000..8e20d736 --- /dev/null +++ b/CrowIDE/src/CrowIDEdrm.cs @@ -0,0 +1,125 @@ +// +// HelloCube.cs +// +// Author: +// Jean-Philippe Bruyère +// +// Copyright (c) 2016 jp +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +using System; +using Crow; +using System.Reflection; +using System.Collections.Generic; +using System.Collections; +using System.Xml.Serialization; +using System.IO; +//using Cairo; +namespace CrowIDE +{ + class CrowIDE : Application + { +// public Command CMDLoad = new Command(new Action(() => System.Diagnostics.Debug.WriteLine("Open"))) { Caption = "Open", Icon = new SvgPicture("#Crow.Icons.open-file.svg")}; +// public Command CMDSave = new Command(new Action(() => System.Diagnostics.Debug.WriteLine("Save"))) { Caption = "Save", Icon = new SvgPicture("#Crow.Icons.open-file.svg")}; + public Command CMDQuit; +//// public Command CMDSave = new Command(actionOpenFile) { Caption = "Open...", Icon = new SvgPicture("#Crow.Icons.open-file.svg")}; +// public Command CMDQuit = new Command(actionOpenFile) { Caption = "Open...", Icon = new SvgPicture("#Crow.Icons.open-file.svg")}; +// public Command CMDCut = new Command(new Action(() => System.Diagnostics.Debug.WriteLine("Cut"))) { Caption = "Cut", Icon = new SvgPicture("#Crow.Icons.scissors.svg")}; +// public Command CMDCopy = new Command(new Action(() => System.Diagnostics.Debug.WriteLine("Copy"))) { Caption = "Copy", Icon = new SvgPicture("#Crow.Icons.copy-file.svg")}; +// public Command CMDPaste = new Command(new Action(() => System.Diagnostics.Debug.WriteLine("Paste"))) { Caption = "Paste", Icon = new SvgPicture("#Crow.Icons.paste-on-document.svg")}; +// public Command CMDHelp = new Command(new Action(() => System.Diagnostics.Debug.WriteLine("Help"))) { Caption = "Help", Icon = new SvgPicture("#Crow.Icons.question.svg")}; + public Command CMDViewGTExp; + public Command CMDViewProps; + public Command CMDViewProj; +// + ImlVisualEditor imlVE; +// + #region MAIN + [STAThread] + static void Main () + { + try { + using (CrowIDE crowApp = new CrowIDE ()) + crowApp.Run (); + } catch (Exception ex) { + Console.WriteLine (ex.ToString ()); + } + } + #endregion + + #region CTOR + public CrowIDE () + : base() + { + System.Threading.Thread.Sleep (1000); + CMDQuit = new Command(new Action(() => Running = false)) { Caption = "Quit", Icon = new SvgPicture("#Crow.Icons.exit-symbol.svg")}; + CMDViewGTExp = new Command(new Action(() => loadWindow ("#CrowIDE.ui.GTreeExplorer.crow"))) { Caption = "Graphic Tree Explorer"}; + CMDViewProps = new Command(new Action(() => loadWindow ("#CrowIDE.ui.MemberView.crow"))) { Caption = "Properties View"}; +// CMDViewProj = new Command(new Action(() => loadWindow ("#CrowIDE.ui.CSProjExplorer.crow"))) { Caption = "Project Explorer"}; +// +// //this.KeyDown += CrowIDE_KeyDown; +// + //this.CrowInterface.LoadInterface ("#CrowIDE.ui.imlEditor.crow").DataSource = this; +// //GraphicObject go = this.CrowInterface.LoadInterface (@"ui/test.crow"); + GraphicObject go = this.CrowInterface.LoadInterface (@"#CrowIDE.ui.imlEditor.crow"); + imlVE = go.FindByName ("crowContainer") as ImlVisualEditor; + go.DataSource = this; + } + #endregion + + + +// void CrowIDE_KeyDown (object sender, OpenTK.Input.KeyboardKeyEventArgs e) +// { +// if (e.Key == OpenTK.Input.Key.Escape) { +// Quit (null, null); +// return; +// } else if (e.Key == OpenTK.Input.Key.F4) { +// loadWindow ("#CrowIDE.ui.MemberView.crow"); +// } else if (e.Key == OpenTK.Input.Key.F5) { +// loadWindow ("#CrowIDE.ui.GTreeExplorer.crow"); +// } else if (e.Key == OpenTK.Input.Key.F6) { +// loadWindow ("#CrowIDE.ui.LQIsExplorer.crow"); +// } else if (e.Key == OpenTK.Input.Key.F7) { +// loadWindow ("#CrowIDE.ui.CSProjExplorer.crow"); +// } +// } + void loadWindow(string path){ + try { + GraphicObject g = CrowInterface.FindByName (path); + if (g != null) + return; + g = CrowInterface.LoadInterface (path); + g.Name = path; + g.DataSource = imlVE; + } catch (Exception ex) { + System.Diagnostics.Debug.WriteLine (ex.ToString ()); + } + } + void closeWindow (string path){ + GraphicObject g = CrowInterface.FindByName (path); + if (g != null) + CrowInterface.DeleteWidget (g); + } + + protected void onCommandSave(object sender, MouseButtonEventArgs e){ + System.Diagnostics.Debug.WriteLine("save"); + } + + void actionOpenFile(){ + System.Diagnostics.Debug.WriteLine ("OpenFile action"); + } + } +} \ No newline at end of file diff --git a/CrowIDE/src/DRIControler.cs b/CrowIDE/src/DRIControler.cs new file mode 100644 index 00000000..d903a337 --- /dev/null +++ b/CrowIDE/src/DRIControler.cs @@ -0,0 +1,487 @@ +// +// DRM.cs +// +// Author: +// Jean-Philippe Bruyère +// +// 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.Runtime.InteropServices; +using System.Collections.Generic; +using System.Diagnostics; +using System.Threading; +using DRI.DRM; +using Linux; + + +namespace DRI { + #region DRM callback signatures + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void VBlankCallback(int fd, int sequence, int tv_sec, int tv_usec, IntPtr user_data); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void PageFlipCallback(int fd, int sequence, int tv_sec, int tv_usec, ref int user_data); + #endregion + + #region DRM enums + public enum EncoderType : uint + { + NONE=0, + DAC=1, + TMDS=2, + LVDS=3, + TVDAC=4, + VIRTUAL=5, + DSI=6, + DPMST=7, + DPI=8, + } + [Flags]public enum PageFlipFlags : uint + { + FlipEvent = 0x01, + FlipAsync = 0x02, + FlipFlags = FlipEvent | FlipAsync + } + /// Video mode flags, bit compatible with the xorg definitions. + [Flags]public enum VideoMode + { + PHSYNC = 0x01, + NHSYNC = 0x02, + PVSYNC = 0x04, + NVSYNC = 0x08, + INTERLACE = 0x10, + DBLSCAN = 0x20, + CSYNC = 0x40, + PCSYNC = 0x80, + NCSYNC = 0x10, + HSKEW = 0x0200, + BCAST = 0x0400, + PIXMUX = 0x0800, + DBLCLK = 0x1000, + CLKDIV2 = 0x2000, + // FLAG_3D_MASK (0x1f<<14) + // FLAG_3D_NONE = 0x0; + // FLAG_3D_FRAME_PACKING = 0x4000, + // FLAG_3D_FIELD_ALTERNATIVE = 0x8000, + // FLAG_3D_LINE_ALTERNATIVE (3<<14) + // FLAG_3D_SIDE_BY_SIDE_FULL (4<<14) + // FLAG_3D_L_DEPTH (5<<14) + // FLAG_3D_L_DEPTH_GFX_GFX_DEPTH (6<<14) + // FLAG_3D_TOP_AND_BOTTOM (7<<14) + // FLAG_3D_SIDE_BY_SIDE_HALF (8<<14) + } + #endregion + + #region DRM structs + [StructLayout(LayoutKind.Sequential)] + public struct EventContext + { + public int version; + public IntPtr vblank_handler; + public IntPtr page_flip_handler; + public static readonly int Version = 2; + } + [StructLayout(LayoutKind.Sequential)] + unsafe public struct drmFrameBuffer { + public uint fb_id; + public uint width, height; + public uint pitch; + public uint bpp; + public uint depth; + /* driver specific handle */ + public uint handle; + } + [StructLayout(LayoutKind.Sequential)] + struct drmClip { + public ushort x1; + public ushort y1; + public ushort x2; + public ushort y2; + } + #endregion + + public class DRIControler : IDisposable { + #region PINVOKE + const string lib = "libdrm"; + [DllImport(lib, CallingConvention = CallingConvention.Cdecl)] + internal static extern int drmHandleEvent(int fd, ref EventContext evctx); + [DllImport(lib, CallingConvention = CallingConvention.Cdecl)] + internal static extern int drmModeAddFB(int fd, uint width, uint height, byte depth, byte bpp, + uint stride, uint bo_handle, out uint buf_id); + [DllImport(lib, CallingConvention = CallingConvention.Cdecl)] + internal static extern int drmModeRmFB(int fd, uint bufferId); + [DllImport(lib, CallingConvention = CallingConvention.Cdecl)] + internal static extern int drmModeDirtyFB(int fd, uint bufferId, IntPtr clips, uint num_clips); + [DllImport(lib,CallingConvention = CallingConvention.Cdecl)] + unsafe internal static extern drmFrameBuffer* drmModeGetFB(int fd, uint fb_id); + [DllImport(lib, CallingConvention = CallingConvention.Cdecl)] + unsafe internal static extern void drmModeFreeFB(drmFrameBuffer* ptr); + [DllImport(lib, CallingConvention = CallingConvention.Cdecl)] + static extern int drmModePageFlip(int fd, uint crtc_id, uint fb_id, PageFlipFlags flags, ref int user_data); + [DllImport(lib, CallingConvention = CallingConvention.Cdecl)] + unsafe static extern int drmModeSetCrtc(int fd, uint crtcId, uint bufferId, uint x, uint y, uint* connectors, int count, ref ModeInfo mode); + [DllImport(lib, CallingConvention = CallingConvention.Cdecl)] + internal static extern int drmModeSetCursor2(int fd, uint crtcId, uint bo_handle, uint width, uint height, int hot_x, int hot_y); + [DllImport(lib, CallingConvention = CallingConvention.Cdecl)] + internal static extern int drmModeMoveCursor(int fd, uint crtcId, uint x, uint y); + #endregion + + int fd_gpu = -1; + GBM.Device gbmDev; + GBM.Surface gbmSurf; + public EGL.Context eglctx; + EGL.Surface eglSurf; + + Cairo.EGLDevice cairoDev; + public Cairo.GLSurface CairoSurf; + + Resources resources = null; + Connector connector = null; + Crtc currentCrtc = null; + ModeInfo currentMode, originalMode; + uint originalFB; + + byte bpp = 32; + byte depth = 24; + + public volatile int FlipPollingSleep = 1; + + #region CTOR + public DRIControler(string gpu_path = "/dev/dri/card0"){ + fd_gpu = Libc.open(gpu_path, OpenFlags.ReadWrite | OpenFlags.CloseOnExec); + if (fd_gpu < 0) + throw new NotSupportedException("[DRI] Failed to open gpu"); + + resources = new Resources (fd_gpu); + gbmDev = new GBM.Device (fd_gpu); + eglctx = new EGL.Context (gbmDev); + + try { + if (defaultConfiguration ()) + Console.WriteLine ("default config ok"); + } catch (Exception ex) { + Console.WriteLine (ex.ToString()); + } + } + #endregion + + public int Width { get { return (int)currentMode.hdisplay; }} + public int Height { get { return (int)currentMode.vdisplay; }} + + bool defaultConfiguration (){ + //select the first connected connector + foreach (Connector c in resources.Connectors) { + if (c.State == ConnectionStatus.Connected) { + connector = c; + break; + } + } + if (connector == null) + return false; + + currentCrtc = connector.CurrentEncoder.CurrentCrtc; + originalMode = currentCrtc.CurrentMode; + originalFB = currentCrtc.CurrentFbId; + //currentMode = originalMode; + currentMode = getNewMode(); + + //configure a rendering stack + gbmSurf = new GBM.Surface (gbmDev, Width, Height, + GBM.SurfaceFlags.Rendering | GBM.SurfaceFlags.Scanout); + + eglSurf = new EGL.Surface (eglctx, gbmSurf); + eglSurf.MakeCurrent (); + + Console.WriteLine ("dpy:{0} ctx{1}", eglctx.dpy, eglctx.ctx); + + cairoDev = new Cairo.EGLDevice (eglctx.dpy, eglctx.ctx); + CairoSurf = new Cairo.GLSurface (cairoDev, eglSurf.handle, Width, Height); + //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."); + +// using (Cairo.Context ctx = new Cairo.Context (CairoSurf)) { +// ctx.Rectangle (0, 0, Width, Height); +// ctx.SetSourceRGB (0, 0, 1); +// ctx.Fill (); +// } + //CairoSurf.Flush (); + //CairoSurf.SwapBuffers (); + //Update (); + //setScanOutRegion(); + //Thread.Sleep (100); + + initPageFlipUpdate (); + return true; + } + + void handleDestroyFB(ref GBM.gbm_bo bo, ref uint data) + { + uint fb = data; + + if (fb != 0) { + if (drmModeRmFB (fd_gpu, fb) != 0) + Console.WriteLine ("DestroyFB failed"); + + data = 0; + } + } + + unsafe GBM.gbm_bo* bo; + uint fb; + + unsafe public void Update(){ + int ret = 0; + if (!gbmSurf.HasFreeBuffers) + throw new NotSupportedException("[GBM] Out of free buffer"); + bo = gbmSurf.Lock (); + + if (fb == 0) { + ret = drmModeAddFB (fd_gpu, currentMode.hdisplay, currentMode.vdisplay, (byte)depth, (byte)bpp, bo->Stride, (uint)bo->Handle32, out fb); + if (ret != 0) + Console.WriteLine ("addFb failed: {0}", ret); + } + uint connId = connector.Id; + ret = drmModeSetCrtc (fd_gpu, currentCrtc.Id, fb, 0, 0, &connId, 1, ref currentMode); + if (ret != 0) + Console.WriteLine ("setCrtc failed: {0}", ret); + gbmSurf.Release (bo); + } + + static void HandlePageFlip(int fd, int sequence, int tv_sec, int tv_usec, ref int user_data) + { + user_data = 0; + } + + PollFD fds; + EventContext evctx; + static IntPtr PageFlipPtr = Marshal.GetFunctionPointerForDelegate((PageFlipCallback)HandlePageFlip); + public void initPageFlipUpdate (){ + fds = new PollFD(); + fds.fd = fd_gpu; + fds.events = PollFlags.In; + + evctx = new EventContext(); + evctx.version = EventContext.Version; + evctx.page_flip_handler = Marshal.GetFunctionPointerForDelegate((PageFlipCallback)HandlePageFlip); + } + unsafe public void UpdateWithPageFlip(){ + GBM.gbm_bo* next_bo; + uint fb; + + int timeout = -1;//block ? -1 : 0; + + if (!gbmSurf.HasFreeBuffers) + throw new NotSupportedException("[GBM] Out of free buffer"); + + next_bo = gbmSurf.Lock (); + + int ret = drmModeAddFB (fd_gpu, currentMode.hdisplay, currentMode.vdisplay, (byte)depth, (byte)bpp, next_bo->Stride, (uint)next_bo->Handle32, out fb); + if (ret != 0) + Console.WriteLine ("addFb failed: {0}", ret); + next_bo->SetUserData (ref fb, handleDestroyFB); + + if (bo == null) { + uint connId = connector.Id; + ret = drmModeSetCrtc (fd_gpu, currentCrtc.Id, fb, 0, 0, &connId, 1, ref currentMode); + if (ret != 0) + Console.WriteLine ("setCrtc failed: {0}", ret); + bo = next_bo; + } else { + + int is_flip_queued = 1; + + while (drmModePageFlip (fd_gpu, currentCrtc.Id, fb, PageFlipFlags.FlipEvent, ref is_flip_queued) < 0) { + //Console.WriteLine ("[DRM] Failed to enqueue framebuffer flip."); + Thread.Sleep (1); + } + + while (is_flip_queued != 0) { + 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) + drmHandleEvent (fd_gpu, ref evctx); + else + break; + Thread.Sleep (FlipPollingSleep); + } + if (is_flip_queued != 0) + Console.WriteLine ("flip canceled"); + + gbmSurf.Release (bo); + bo = next_bo; + } + } + + #region cursor + GBM.BufferObject boMouseCursor; + + internal void updateCursor (Crow.XCursor cursor) { + uint width = 64, height = 64; + if (cursor.Width > width || cursor.Height > height){ + Debug.Print("[DRM] Cursor size {0}x{1} unsupported. Maximum is 64x64.", + cursor.Width, cursor.Height); + return; + } + boMouseCursor = new GBM.BufferObject (gbmDev, width, height, GBM.SurfaceFormat.ARGB8888, + GBM.SurfaceFlags.Cursor64x64 | GBM.SurfaceFlags.Write); + + // Copy cursor.Data into a new buffer of the correct size + byte[] cursor_data = new byte[width * height * 4]; + for (uint y = 0; y < cursor.Height; y++) + { + uint dst_offset = y * width * 4; + uint src_offset = y * cursor.Width * 4; + uint src_length = cursor.Width * 4; + Array.Copy( + cursor.data, src_offset, + cursor_data, dst_offset, + src_length); + } + + boMouseCursor.Data = cursor_data; + uint crtcid = currentCrtc.Id; + + unsafe { + drmModeSetCursor2 (fd_gpu, crtcid, + (uint)boMouseCursor.handle->Handle32, width, height, (int)cursor.Xhot, (int)cursor.Yhot); + //drmModeMoveCursor (fd_gpu, crtcid, 0, 0); + } + } + internal void moveCursor (uint x, uint y){ + drmModeMoveCursor (fd_gpu, currentCrtc.Id, x, y); + } + #endregion + + ModeInfo getNewMode(){ + ModeInfo mode = currentCrtc.CurrentMode; + mode.clock = 118250; + mode.hdisplay = 1600; + mode.hsync_start = 1696; + mode.hsync_end = 1856; + mode.htotal = 2112; + mode.vdisplay = 900; + mode.vsync_start = 903; + mode.vsync_end = 908; + mode.vtotal = 934; + mode.flags |= (uint)VideoMode.NHSYNC; + mode.flags |= (uint)VideoMode.PVSYNC; + return mode; + } + + +// unsafe public drmPlane GetPlane (uint id) { +// drmPlane p = new drmPlane(); +// drmPlane* pPlane = ModeGetPlane (fd_gpu, id); +// if (pPlane != null) { +// p = *pPlane; +// ModeFreePlane (pPlane); +// } +// return p; +// } +// public void SetPlane (drmPlane p, uint flags, uint crtc_w, uint crtc_h, uint src_w, uint src_h) { +// ModeSetPlane (fd_gpu, p.plane_id, p.crtc_id, p.fb_id, flags, +// (int)p.crtc_x, (int)p.crtc_y, +// crtc_w, crtc_h, +// p.x, p.y, +// src_w, src_h); +// +// +// } + + #region IDisposable implementation + ~DRIControler(){ + Dispose (false); + } + public void Dispose () + { + Dispose (true); + GC.SuppressFinalize (this); + } + bool disposed = false; + protected virtual void Dispose (bool disposing){ + if (disposed) + return; + unsafe{ + if (bo != null) + gbmSurf.Release (bo); + } + if (fb != 0) + if (drmModeRmFB (fd_gpu, fb) != 0) + Console.WriteLine ("DestroyFB failed"); + if (eglctx != null) + eglctx.ResetMakeCurrent (); + if (cairoDev != null) { + cairoDev.Release (); + CairoSurf.Dispose (); + cairoDev.Dispose (); + cairoDev = null; + CairoSurf = null; + } + + if (boMouseCursor != null) { + drmModeSetCursor2 (fd_gpu, currentCrtc.Id, 0u, 0, 0, 0, 0); + boMouseCursor.Dispose (); + } + boMouseCursor = null; + if (connector != null) { + uint connId = connector.Id; + unsafe { + int ret = drmModeSetCrtc (fd_gpu, currentCrtc.Id, originalFB, 0, 0, &connId, 1, ref originalMode); + if (ret != 0) + Console.WriteLine ("restore Crtc failed: {0}", ret); + } + } + if (eglctx != null) { + eglctx.ResetMakeCurrent (); + if (eglSurf != null) + eglSurf.Dispose (); + eglSurf = null; + if (eglctx != null) + eglctx.Dispose (); + eglctx = null; + } + + if (gbmSurf != null) + gbmSurf.Dispose (); + if (gbmDev != null) + gbmDev.Dispose (); + if (currentCrtc != null) + currentCrtc.Dispose (); + if (connector != null) + connector.Dispose (); + if (resources != null) + resources.Dispose (); + resources = null; + if (fd_gpu > 0) + Libc.close (fd_gpu); + fd_gpu = -1; + disposed = true; + Console.WriteLine ("GPU controler disposed"); + } + #endregion + } +} \ No newline at end of file diff --git a/CrowIDE/src/ImlVisualEditor.cs b/CrowIDE/src/ImlVisualEditor.cs index 61a1e8c8..a0e3c1d4 100644 --- a/CrowIDE/src/ImlVisualEditor.cs +++ b/CrowIDE/src/ImlVisualEditor.cs @@ -269,7 +269,7 @@ namespace CrowIDE // gr.DrawCote (new Cairo.PointD (hr.Center.X, hr.Y), new Cairo.PointD (hr.Center.X, hr.Bottom)); //hr.Inflate (2); gr.SetSourceColor (Color.LightGray); - gr.SetDash (new double[]{ 3.0, 3.0 }, 0.0); + //gr.SetDash (new double[]{ 3.0, 2.0 }, 1.0); gr.Rectangle (hr, 1.0); } @@ -278,7 +278,7 @@ namespace CrowIDE hr = SelectedItem.ScreenCoordinates(SelectedItem.getSlot ()); hr.Inflate (1); gr.SetSourceColor (Color.Yellow); - gr.SetDash (new double[]{ 5.0, 3.0 },0.0); + //gr.SetDash (new double[]{ 5.0, 3.0 },0.0); gr.Rectangle (hr, 1.0); } #endregion diff --git a/CrowIDE/src/Signal.cs b/CrowIDE/src/Signal.cs new file mode 100644 index 00000000..16eca34a --- /dev/null +++ b/CrowIDE/src/Signal.cs @@ -0,0 +1,77 @@ +// +// Signals.cs +// +// Author: +// Jean-Philippe Bruyère +// +// 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.Runtime.InteropServices; + +namespace Linux +{ + public enum Signal : int { + SIGHUP = 1, + SIGINT = 2, + SIGQUIT = 3, + SIGILL = 4, + SIGTRAP = 5, + SIGABRT = 6, + SIGIOT = 6, + SIGBUS = 7, + SIGFPE = 8, + SIGKILL = 9, + SIGUSR1 = 10, + SIGSEGV = 11, + SIGUSR2 = 12, + SIGPIPE = 13, + SIGALRM = 14, + SIGTERM = 15, + SIGSTKFLT = 16, + SIGCHLD = 17, + SIGCONT = 18, + SIGSTOP = 19, + SIGTSTP = 20, + SIGTTIN = 21, + SIGTTOU = 22, + SIGURG = 23, + SIGXCPU = 24, + SIGXFSZ = 25, + SIGVTALRM = 26, + SIGPROF = 27, + SIGWINCH = 28, + /// same as SIGPOLL + SIGIO = 29, + SIGPWR = 30, + SIGSYS = 31, + SIGUNUSED = 31 + } + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void SignalHandler(Signal signal); + + public static class Kernel + { + [DllImport("libc")] + public static extern int signal(Signal s, SignalHandler handler); + } +} + diff --git a/Tests/BasicTests.cs b/Tests/BasicTests.cs index 44c33fd3..d48364e8 100644 --- a/Tests/BasicTests.cs +++ b/Tests/BasicTests.cs @@ -41,6 +41,7 @@ namespace Tests public BasicTests () : base(1600, 900,"test: press to toogle test files") { + } int idx = 0; @@ -129,6 +130,12 @@ namespace Tests #endregion + #if MEASURE_TIME + public List PerfMeasures; + public PerformanceMeasure glDrawMeasure = new PerformanceMeasure("OpenGL Draw", 10); + public Command CMDViewPerf; + #endif + void OnClear (object sender, MouseButtonEventArgs e) => TestList = null; void OnLoadList (object sender, MouseButtonEventArgs e) => TestList = Color.ColorDic.ToList(); @@ -142,6 +149,7 @@ namespace Tests //testFiles = new string [] { @"Interfaces/Unsorted/testFileDialog.crow" }; //testFiles = new string [] { @"Interfaces/Divers/colorPicker.crow" }; testFiles = new string [] { @"Interfaces/Divers/welcome.crow" }; + //testFiles = new string [] { @"#Tests.Interfaces.perfMsr.crow" }; testFiles = testFiles.Concat (Directory.GetFiles (@"Interfaces/GraphicObject", "*.crow")).ToArray (); testFiles = testFiles.Concat (Directory.GetFiles (@"Interfaces/Container", "*.crow")).ToArray (); testFiles = testFiles.Concat (Directory.GetFiles (@"Interfaces/Group", "*.crow")).ToArray (); @@ -155,7 +163,19 @@ namespace Tests testFiles = testFiles.Concat (Directory.GetFiles (@"Interfaces/Unsorted", "*.crow")).ToArray (); object tc = Color.AirForceBlueRaf; - Load(testFiles[idx]).DataSource = this; + Load (testFiles [idx]).DataSource = this; + + #if MEASURE_TIME + PerfMeasures = new List ( + new PerformanceMeasure[] { + this.ifaceControl[0].CrowInterface.updateMeasure, + this.ifaceControl[0].CrowInterface.layoutingMeasure, + this.ifaceControl[0].CrowInterface.clippingMeasure, + this.ifaceControl[0].CrowInterface.drawingMeasure, + this.ifaceControl[0].glDrawMeasure + } + ); + #endif } void KeyboardKeyDown1 (object sender, OpenTK.Input.KeyboardKeyEventArgs e) { @@ -259,6 +279,10 @@ namespace Tests if (IntValue == 1000) IntValue = 0; NotifyValueChanged ("PropertyLessBinding", test); + #if MEASURE_TIME + foreach (PerformanceMeasure m in PerfMeasures) + m.NotifyChanges(); + #endif } void onNew(object sender, EventArgs e){ Debug.WriteLine ("menu new clicked"); diff --git a/Tests/CrowWindow.cs b/Tests/CrowWindow.cs index c5a544ac..a578fa64 100644 --- a/Tests/CrowWindow.cs +++ b/Tests/CrowWindow.cs @@ -65,10 +65,6 @@ namespace Crow #endif if (frameCpt % 3 == 0) ValueChanged.Raise(this, new ValueChangeEventArgs ("fps", _fps)); - #if MEASURE_TIME -// foreach (PerformanceMeasure m in PerfMeasures) -// m.NotifyChanges(); - #endif } } diff --git a/src/CompilerServices/CompilerServices.cs b/src/CompilerServices/CompilerServices.cs index 05dc3652..9961c52d 100644 --- a/src/CompilerServices/CompilerServices.cs +++ b/src/CompilerServices/CompilerServices.cs @@ -629,6 +629,10 @@ namespace Crow /// Removes delegate from event handler by name /// static void removeEventHandlerByName(object instance, string eventName, string delegateName){ + if (instance == null){ + Debug.WriteLine ("RemoveHandlerByName: instance is NULL for Event '" + eventName); + return; + } Type t = instance.GetType (); FieldInfo fiEvt = getEventHandlerField (t, eventName); if (fiEvt == null) { diff --git a/src/Interface.cs b/src/Interface.cs index df6a5c67..7faace46 100644 --- a/src/Interface.cs +++ b/src/Interface.cs @@ -110,6 +110,14 @@ namespace Crow #region Events public event EventHandler MouseCursorChanged; public event EventHandler Quit; + + public event EventHandler MouseWheelChanged; + public event EventHandler MouseButtonUp; + public event EventHandler MouseButtonDown; + public event EventHandler MouseClick; + public event EventHandler MouseMove; + public event EventHandler KeyboardKeyDown; + public event EventHandler KeyboardKeyUp; #endregion #region Public Fields @@ -387,15 +395,19 @@ namespace Crow if (mouseRepeatCount > 0) { int mc = mouseRepeatCount; mouseRepeatCount -= mc; - for (int i = 0; i < mc; i++) { - FocusedWidget.onMouseClick (this, new MouseButtonEventArgs (Mouse.X, Mouse.Y, MouseButton.Left, true)); + if (_focusedWidget != null) { + for (int i = 0; i < mc; i++) { + _focusedWidget.onMouseClick (this, new MouseButtonEventArgs (Mouse.X, Mouse.Y, MouseButton.Left, true)); + } } } if (keyboardRepeatCount > 0) { int mc = keyboardRepeatCount; keyboardRepeatCount -= mc; - for (int i = 0; i < mc; i++) { - _focusedWidget.onKeyDown (this, lastKeyDownEvt); + if (_focusedWidget != null) { + for (int i = 0; i < mc; i++) { + _focusedWidget.onKeyDown (this, lastKeyDownEvt); + } } } CrowThread[] tmpThreads; @@ -796,31 +808,36 @@ namespace Crow } public bool ProcessKeyDown(int Key){ Keyboard.SetKeyState((Crow.Key)Key,true); - if (_focusedWidget == null) - return false; + KeyboardKeyEventArgs e = lastKeyDownEvt = new KeyboardKeyEventArgs((Crow.Key)Key, false, Keyboard); lastKeyDownEvt.IsRepeat = true; - _focusedWidget.onKeyDown (this, e); + + KeyboardKeyDown.Raise (this, e); keyboardRepeatThread = new Thread (keyboardRepeatThreadFunc); keyboardRepeatThread.IsBackground = true; keyboardRepeatThread.Start (); + if (_focusedWidget == null) + return false; + _focusedWidget.onKeyDown (this, e); + return true; } public bool ProcessKeyUp(int Key){ - Keyboard.SetKeyState((Crow.Key)Key,false); - if (_focusedWidget == null) - return false; + Keyboard.SetKeyState ((Crow.Key)Key, false); KeyboardKeyEventArgs e = new KeyboardKeyEventArgs((Crow.Key)Key, false, Keyboard); - _focusedWidget.onKeyUp (this, e); + KeyboardKeyUp (this, e); if (keyboardRepeatThread != null) { keyboardRepeatOn = false; keyboardRepeatThread.Abort(); keyboardRepeatThread.Join (); } + if (_focusedWidget == null) + return false; + _focusedWidget.onKeyUp (this, e); return true; } public bool ProcessKeyPress(char Key){ diff --git a/src/PerformanceMeasure.cs b/src/PerformanceMeasure.cs index f5c39e35..172f926d 100644 --- a/src/PerformanceMeasure.cs +++ b/src/PerformanceMeasure.cs @@ -58,14 +58,16 @@ namespace Crow computeStats (); } public void NotifyChanges(){ - if (cptMeasures == 0) - return; - NotifyValueChanged("minimum", minimum); - NotifyValueChanged("maximum", maximum); - NotifyValueChanged("current", current); - // NotifyValueChanged("total", total); - // NotifyValueChanged("cptMeasures", cptMeasures); - NotifyValueChanged("mean", total / cptMeasures); + lock(this){ + if (cptMeasures == 0) + return; + NotifyValueChanged("minimum", minimum); + NotifyValueChanged("maximum", maximum); + NotifyValueChanged("current", current); + // NotifyValueChanged("total", total); + // NotifyValueChanged("cptMeasures", cptMeasures); + NotifyValueChanged("mean", total / cptMeasures); + } } void computeStats(){ @@ -85,7 +87,8 @@ namespace Crow minimum = long.MaxValue; } void onResetClick(object sender, MouseButtonEventArgs e){ - ResetStats(); + lock(this) + ResetStats(); } } } diff --git a/testDrm/Main.cs b/testDrm/Main.cs index d13108bf..8102abd7 100644 --- a/testDrm/Main.cs +++ b/testDrm/Main.cs @@ -32,6 +32,7 @@ using Crow.Linux; using Crow; using System.Reflection; using System.Linq; +using System.Threading; namespace testDrm { @@ -41,11 +42,22 @@ namespace testDrm [STAThread] static void Main () { +// int pid = Mono.Unix.Native.Syscall.getpid (); +// uint gid = Mono.Unix.Native.Syscall.getgid (); +// int sid = Mono.Unix.Native.Syscall.getsid (0); +// int newsid = Mono.Unix.Native.Syscall.setsid (); +// +// Console.WriteLine ("pid:{0} gid:{1} sid:{2}", pid, gid, sid); +// Console.WriteLine ("pid:{0} gid:{1} sid:{2}", +// Mono.Unix.Native.Syscall.getpid (), +// Mono.Unix.Native.Syscall.getgid (), +// Mono.Unix.Native.Syscall.getsid (0)); + System.Threading.Thread.CurrentThread.Name = "Main"; + try { - using (TestApp crowApp = new TestApp ()) { + using (TestApp crowApp = new TestApp ()) crowApp.Run (); - } } catch (Exception ex) { Console.WriteLine (ex.ToString ()); } @@ -62,27 +74,33 @@ namespace testDrm #endregion - #if MEASURE_TIME - public List PerfMeasures; - public PerformanceMeasure glDrawMeasure = new PerformanceMeasure("OpenGL Draw", 10); - public Command CMDViewPerf, CMDViewCfg, CMDViewTest0; - #endif + public Command CMDViewPerf, CMDViewCfg, CMDViewTest0, CMDOpen; public TestApp () : base () { - #if MEASURE_TIME - PerfMeasures = new List ( - new PerformanceMeasure[] { - this.CrowInterface.updateMeasure, - this.CrowInterface.layoutingMeasure, - this.CrowInterface.clippingMeasure, - this.CrowInterface.drawingMeasure, - this.glDrawMeasure - } - ); + CrowInterface.KeyboardKeyDown += CrowInterface_KeyboardKeyDown; + CMDViewPerf = new Command(new Action(() => Load ("#testDrm.ui.perfMeasures.crow").DataSource = this)) { Caption = "Performances"}; CMDViewCfg = new Command(new Action(() => Load ("#testDrm.ui.2.crow").DataSource = this)) { Caption = "Configuration"}; CMDViewTest0 = new Command(new Action(() => Load ("#testDrm.ui.0.crow").DataSource = this)) { Caption = "Test view 0"}; - #endif + CMDOpen = new Command(new Action(() => { + lock (CrowInterface.UpdateMutex) CrowInterface.AddWidget(new FileDialog());})) { Caption = "Open"}; + + Load ("#testDrm.ui.menu.crow").DataSource = this; + + initTests (); + } + + void CrowInterface_KeyboardKeyDown (object sender, KeyboardKeyEventArgs e) + { + if (e.Alt){ + if (e.Key >= Key.F1 && e.Key <= Key.F8){ + int ttyNum = 0; + + if (int.TryParse (e.Key.ToString ().Substring (1), out ttyNum)) + Console.WriteLine ("tty switch {0}", ttyNum); + this.CurrentState = RunState.DesactivateRequest; + } + } } public int frameTime = 0; @@ -187,39 +205,66 @@ namespace testDrm } } + EGL.Surface pbuff; + void initTests(){ - public override void Run () - { - Stopwatch frame = new Stopwatch (); - Load ("#testDrm.ui.menu.crow").DataSource = this; - int i = 0; - while(Running){ - try { - frame.Restart(); - i++; - base.Run (); - - frame.Stop(); - frameTime = (int)frame.ElapsedTicks; - NotifyValueChanged("frameTime", frameTime); - if (frameTime > frameMax){ - frameMax = frameTime; - NotifyValueChanged("frameMax", frameMax); - } - if (frameTime < frameMin){ - frameMin = frameTime; - NotifyValueChanged("frameMin", frameMin); + +// pbuff = EGL.Surface.CreatePBuffer(gpu.eglctx,800,600); +// Console.WriteLine ("pbuff created successfully"); +// Thread.Sleep (100); +// pbuff.Dispose (); + } + void testegldraw() + { + int width = 19; + int height = 19; + using (Cairo.ImageSurface img = new Cairo.ImageSurface (Cairo.Format.Argb32, gpu.Width, gpu.Height)) { + glDrawMeasure.StartCycle (); + using (Cairo.Context ctx = new Cairo.Context (img)) { + for (int x = 100; x < 800; x += 20) { + for (int y = 100; y < 800; y += 20) { + ctx.Rectangle (x, y, width, height); + ctx.SetSourceRGBA (x / 800.0, y / 800.0, 0.5, 0.5); + ctx.Fill (); + } } - #if MEASURE_TIME - foreach (PerformanceMeasure m in PerfMeasures) - m.NotifyChanges(); - #endif - } catch (Exception ex) { - Console.WriteLine (ex.ToString()); } + glDrawMeasure.StopCycle (); + using (Cairo.Context ctx = new Cairo.Context (cairoSurf)) { + ctx.SetSourceSurface (img, 0, 0); + ctx.Paint (); + } + } + } + + protected override void uiDraw () + { + Stopwatch frame = Stopwatch.StartNew (); + + testegldraw (); + + base.uiDraw (); + + frame.Stop(); + frameTime = (int)frame.ElapsedTicks; + NotifyValueChanged("frameTime", frameTime); + if (frameTime > frameMax){ + frameMax = frameTime; + NotifyValueChanged("frameMax", frameMax); + } + if (frameTime < frameMin){ + frameMin = frameTime; + NotifyValueChanged("frameMin", frameMin); + } + #if MEASURE_TIME + foreach (PerformanceMeasure m in PerfMeasures) + m.NotifyChanges(); + #endif + } + void onQuitClick(object send, Crow.MouseButtonEventArgs e) { Running = false; diff --git a/testDrm/defineToEnum.cs b/testDrm/defineToEnum.cs new file mode 100644 index 00000000..10ec5bfd --- /dev/null +++ b/testDrm/defineToEnum.cs @@ -0,0 +1,100 @@ +// +// defineToEnum.cs +// +// Author: +// Jean-Philippe Bruyère +// +// 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.IO; +using System.Collections.Generic; + +namespace testDrm +{ + public class defineToEnum + { + static void Main (){ + parseDefines("/usr/include/linux/input-event-codes.h"); + } + public struct enumdef { + public string name; + public int value; + } + static void parseDefines (string path){ + Dictionary> defines = new Dictionary>(); + + + using (Stream s = new FileStream (path, FileMode.Open,FileAccess.Read)) { + using (StreamReader sr = new StreamReader (s)) { + while (!sr.EndOfStream) { + string l = sr.ReadLine ().Trim(); + if (!l.StartsWith ("#define")) + continue; + l = l.Substring (8); + string[] ll = l.Split (new char[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries); + string[] cn = ll [0].Split ('_'); + try { + string constName = ""; + string enumName = cn [0].ToLowerInvariant ().Substring (1); + enumName = char.ToUpperInvariant (cn [0][0]) + enumName; + for (int i = 1; i < cn.Length; i++) { + cn [i] = cn [i].ToLowerInvariant (); + constName += char.ToUpperInvariant (cn [i] [0]) + cn [i].Substring (1); + } + if (char.IsDigit (constName[0])) + constName = "_" + constName; + + int value = 0; + if (ll [1].StartsWith ("0x")) { + if (!int.TryParse (ll [1].Substring (2), System.Globalization.NumberStyles.AllowHexSpecifier, System.Globalization.CultureInfo.CurrentCulture, out value)){ + Console.WriteLine ("parsing error: " + l); + continue; + } + } else { + if (!int.TryParse (ll[1], out value)){ + Console.WriteLine ("parsing error: " + l); + continue; + } + } + if (!defines.ContainsKey(enumName)) + defines[enumName] = new List(); + defines[enumName].Add (new enumdef() {name=constName,value=value}); + } catch (Exception ex) { + Console.WriteLine ("failed: " + l); + } + } + } + } + using (Stream f = new FileStream ("output.txt", FileMode.Create)) { + using (StreamWriter sw = new StreamWriter (f)){ + foreach (string k in defines.Keys) { + sw.WriteLine ("public enum {0}Type {{", k); + foreach (enumdef ed in defines[k]) { + sw.WriteLine ("\t{0,-20}= 0x{1:X4},", ed.name, ed.value); + } + sw.WriteLine ("}"); + } + } + } + } + } +} + diff --git a/testDrm/src/Application.cs b/testDrm/src/Application.cs index 7d5c1d5f..c63ae124 100644 --- a/testDrm/src/Application.cs +++ b/testDrm/src/Application.cs @@ -36,16 +36,29 @@ using DRI = Linux.DRI; using Linux; using System.Text; using OpenTK.Platform.Linux; +using Linux.oldEvDev; namespace Crow { public class Application : IDisposable { + public enum RunState { + ActivateRequest, + DesactivateRequest, + Paused, + Running, + } + #if MEASURE_TIME + public List PerfMeasures; + protected PerformanceMeasure glDrawMeasure = new PerformanceMeasure("OpenGL Draw", 10); + #endif + public bool Running = true; - protected DRI.DRIControler gpu; - Cairo.GLSurface cairoSurf; + public volatile RunState CurrentState = RunState.Running; protected Interface CrowInterface; + protected DRI.DRIControler gpu; + protected Cairo.GLSurface cairoSurf { get { return gpu?.CairoSurf; }} protected bool mouseIsInInterface = false; @@ -57,34 +70,58 @@ namespace Crow Thread.Sleep (5); while (true) { - CrowInterface.Update (); - Thread.Sleep (ifaceSleep); + if (CurrentState == RunState.Running) { + CrowInterface.Update (); + Thread.Sleep (ifaceSleep); + } else + Thread.Sleep (1000); } } -// - Crow.XCursor cursor; + int previousVT = -1, appVT = -1; public Application(){ if (Kernel.signal (Signal.SIGUSR1, switch_request_handle) < 0) throw new Exception ("signal handler registation failed"); +// if (Kernel.signal (Signal.SIGUSR2, switch_request_handle) < 0) +// throw new Exception ("signal handler registation failed"); if (Kernel.signal (Signal.SIGINT, sigint_handler) < 0) throw new Exception ("SIGINT handler registation failed"); using (VT.VTControler master = new VT.VTControler ()) { previousVT = master.CurrentVT; appVT = master.FirstAvailableVT; + master.SwitchTo (appVT); + try { master.KDMode = VT.KDMode.GRAPHICS; +// VT.vt_mode vtm = master.VTMode; +// vtm.mode = VT.SwitchMode.PROCESS; +// master.VTMode = vtm; } catch (Exception ex) { Console.WriteLine (ex.ToString ()); } } - gpu = new DRI.DRIControler(); - cairoSurf = gpu.CairoSurf; + initDri (); + + initCrow (); + + initInput (); + + MouseX = gpu.Width / 2; + MouseY = gpu.Height / 2; + + initCursor (); + } + + #region CROW + public GraphicObject Load (string path){ + return CrowInterface.LoadInterface (path); + } + void initCrow () { CrowInterface = new Interface (); Thread t = new Thread (interfaceThread); @@ -92,36 +129,82 @@ namespace Crow t.IsBackground = true; t.Start (); - initInput (); - CrowInterface.ProcessResize (new Size (gpu.Width, gpu.Height)); + CrowInterface.MouseCursorChanged += CrowInterface_MouseCursorChanged; + #if MEASURE_TIME + PerfMeasures = new List ( + new PerformanceMeasure[] { + this.CrowInterface.updateMeasure, + this.CrowInterface.layoutingMeasure, + this.CrowInterface.clippingMeasure, + this.CrowInterface.drawingMeasure, + this.glDrawMeasure + } + ); + #endif + } + void CrowInterface_MouseCursorChanged (object sender, MouseCursorChangedEventArgs e) + { + gpu.updateCursor (e.NewCursor); + } + #endregion + + void initDri(){ + gpu = new DRI.DRIControler(); + //cairoSurf = gpu.CairoSurf; + } + void initCursor(){ gpu.updateCursor (XCursor.Default); - MouseX = gpu.Width / 2; - MouseY = gpu.Height / 2; gpu.moveCursor ((uint)MouseX - 8, (uint)MouseY - 4); - CrowInterface.MouseCursorChanged += CrowInterface_MouseCursorChanged; } + void switch_request_handle (Signal s){ -// Console.WriteLine ("switch request catched: " + s.ToString()); -// using (VT.VTControler master = new VT.VTControler ()) { -// Libc.write (master.fd, Encoding.ASCII.GetBytes ("this is a test string")); -// master.AcknoledgeSwitchRequest (); -// } + Console.WriteLine ("****** switch request catched: " + s.ToString()); + using (VT.VTControler master = new VT.VTControler ()) { + Libc.write (master.fd, Encoding.ASCII.GetBytes ("this is a test string")); + master.AcknoledgeSwitchRequest (); + } } void sigint_handler (Signal s){ Console.WriteLine ("{0}: SIGINT catched"); Running = false; } - void CrowInterface_MouseCursorChanged (object sender, MouseCursorChangedEventArgs e) + + public virtual void Run () { - gpu.updateCursor (e.NewCursor); - } + int cpt = 0; + while(Running){ + switch (CurrentState) { + case RunState.ActivateRequest: + activate (); + continue; + case RunState.DesactivateRequest: + desactivate (); + continue; + case RunState.Paused: + Thread.Sleep (1000); + continue; + } - public GraphicObject Load (string path){ - return CrowInterface.LoadInterface (path); + uiDraw (); + + #if MEASURE_TIME + if (cpt%10==0){ + foreach (PerformanceMeasure m in PerfMeasures) + m.NotifyChanges(); + } + #endif + + cpt++; + Thread.Sleep (updateSleep); + } } - public virtual void Run (){ + protected virtual void uiDraw (){ +// #if MEASURE_TIME +// glDrawMeasure.StartCycle(); +// #endif + bool update = false; if (updateMousePos) { @@ -148,15 +231,22 @@ namespace Crow Monitor.Exit (CrowInterface.RenderMutex); } - if (!update) - return; - update = false; +// if (!update) +// return; +// update = false; + + + cairoSurf.Flush (); cairoSurf.SwapBuffers (); - gpu.UpdateWithPageFlip (); - Thread.Sleep (updateSleep); + //gpu.UpdateWithPageFlip (); + gpu.Update(); + +// #if MEASURE_TIME +// glDrawMeasure.StopCycle (); +// #endif } #region INPUT @@ -164,7 +254,7 @@ namespace Crow long exit; static readonly object Sync = new object(); - static readonly Crow.Key[] KeyMap = Evdev.KeyMap; + static readonly Crow.Key[] KeyMap = EvdevClass.KeyMap; static long DeviceFDCount; IntPtr udev; @@ -231,6 +321,10 @@ namespace Crow Debug.Print("[Input] Entering input loop.", poll_fd.fd, poll_fd.events); while (Interlocked.Read(ref exit) == 0) { + if (CurrentState != RunState.Running) { + Thread.Sleep (1000); + continue; + } //drmTimeOut.Restart (); int ret = Libc.poll(ref poll_fd, 1, -1); @@ -344,10 +438,10 @@ namespace Crow handleKeyboard(LibInput.GetKeyboardEvent(pevent)); break; // - // case InputEventType.PointerAxis: - // HandlePointerAxis(GetMouse(device), LibInput.GetPointerEvent(pevent)); - // break; - // + case InputEventType.PointerAxis: + handlePointerAxis(LibInput.GetPointerEvent(pevent)); + break; + case InputEventType.PointerButton: handlePointerButton (LibInput.GetPointerEvent(pevent)); break; @@ -356,9 +450,9 @@ namespace Crow handlePointerMotion (LibInput.GetPointerEvent(pevent)); break; - // case InputEventType.PointerMotionAbsolute: - // HandlePointerMotionAbsolute(GetMouse(device), LibInput.GetPointerEvent(pevent)); - // break; +// case InputEventType.PointerMotionAbsolute: +// handlePointerMotionAbsolute(LibInput.GetPointerEvent(pevent)); +// break; } } @@ -371,7 +465,16 @@ namespace Crow int roundDelta (double d){ return d > 0 ? (int)Math.Ceiling(d) : (int)Math.Floor (d); } - + void handlePointerAxis(PointerEvent e){ +// if (e.HasAxis(PointerAxis.HorizontalScroll)) +// { +// CrowInterface.ProcessMouseWheelChanged ((float)e.AxisValue (PointerAxis.HorizontalScroll)); +// } + if (e.HasAxis(PointerAxis.VerticalScroll)) + { + CrowInterface.ProcessMouseWheelChanged ((float)-e.AxisValue (PointerAxis.VerticalScroll)); + } + } void handlePointerMotion(PointerEvent e) { MouseX += roundDelta (e.DeltaX); @@ -415,9 +518,8 @@ namespace Crow KeyModifiers curModifiers = KeyModifiers.None; void handleKeyboard(KeyboardEvent e) - { - return; - int key = (int)Evdev.KeyMap [e.Key]; + { + int key = (int)EvdevClass.KeyMap [e.Key]; Key k = (Key)key; if (e.KeyState == KeyState.Pressed) { CrowInterface.ProcessKeyDown (key); @@ -470,6 +572,22 @@ namespace Crow #endregion + + + void desactivate () { + CurrentState = RunState.Paused; + + //cairoSurf = null; + gpu.Dispose (); + gpu = null; + } + void activate (){ + initDri(); + initCursor (); + + CurrentState = RunState.Running; + } + #region IDisposable implementation ~Application(){ Dispose (false); diff --git a/testDrm/src/BlittableValueType.cs b/testDrm/src/BlittableValueType.cs index 00595179..81ce16ae 100644 --- a/testDrm/src/BlittableValueType.cs +++ b/testDrm/src/BlittableValueType.cs @@ -32,7 +32,7 @@ using System.Runtime.InteropServices; using System.Diagnostics; using System.Reflection; -namespace Crow +namespace Linux { #region BlittableValueType diff --git a/testDrm/src/DRMContext.cs b/testDrm/src/DRMContext.cs index 07e3bbff..b9451952 100644 --- a/testDrm/src/DRMContext.cs +++ b/testDrm/src/DRMContext.cs @@ -817,7 +817,7 @@ namespace Linux Console.WriteLine ("keymap not found for: " + curModifiers + " " + (int)curModifiers); return; } -// string tmp = keymap [curModifiers] [e.Key]; + string tmp = keymap [curModifiers] [e.Key]; // if (string.IsNullOrEmpty (tmp)) // return; // if (char.IsControl (tmp[0])) diff --git a/testDrm/src/EVDEV/Device.cs b/testDrm/src/EVDEV/Device.cs new file mode 100644 index 00000000..3a1d3f1b --- /dev/null +++ b/testDrm/src/EVDEV/Device.cs @@ -0,0 +1,245 @@ +// +// Device.cs +// +// Author: +// Jean-Philippe Bruyère +// +// 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.Runtime.InteropServices; + +namespace Linux.Evdev +{ + public enum GrabMode { + Grab = 3, + Ungrab = 4 + } + [StructLayout(LayoutKind.Sequential)] + public struct InputAbsInfo + { + public int Value; + public int Minimum; + public int Maximum; + public int Fuzz; + public int Flat; + public int Resolution; + }; + + [StructLayout(LayoutKind.Sequential)] + public struct InputId + { + public ushort BusType; + public ushort Vendor; + public ushort Product; + public ushort Version; + } + + [StructLayout(LayoutKind.Sequential)] + unsafe public struct KeyMapEntry + { + public byte Flags; + public byte Length; + public ushort Index; + public uint Keycode; + fixed sbyte scancode[32]; + + public string ScanCode { + get { + fixed(sbyte* bytes = scancode) { + string test = new string (bytes); + return test; + } + + } + } + public override string ToString () + { + return string.Format ("Flags={0} Length={1} Index={2} KeyCode={3} Scancode={4}", + Flags, Length, Index, Keycode, ScanCode); + } + + } + + [StructLayout(LayoutKind.Sequential)] + public struct InputEvent + { + public TimeVal Time; + ushort type; + public ushort Code; + public int Value; + + public EvType Type { get { return (EvType)type; } } + public string CodeName { get { return Marshal.PtrToStringAuto(Device.libevdev_event_code_get_name ((uint)type,(uint)Code)); } } + public override string ToString () + { + return string.Format ("[Event: {0}:{1} Type={2} Code={3} Value={4} CodeName={5}]", + Time.Seconds, Time.MicroSeconds, Type, Code, Value, CodeName); + } + } + + [StructLayout(LayoutKind.Sequential)] + public struct TimeVal + { + public IntPtr Seconds; + public IntPtr MicroSeconds; + } + + public class Device : IDisposable + { + public const int SUCCESS = 0; + public const int SYNC = 1; + + const string libevdev = "libevdev"; + + #region pinvoke + [DllImport(libevdev, CallingConvention = CallingConvention.Cdecl)] + internal static extern int libevdev_new_from_fd (int fd, out IntPtr handle); + [DllImport(libevdev, CallingConvention = CallingConvention.Cdecl)] + internal static extern void libevdev_free (IntPtr dev); + [DllImport(libevdev, CallingConvention = CallingConvention.Cdecl)] + internal static extern IntPtr libevdev_get_name (IntPtr dev); + [DllImport(libevdev, CallingConvention = CallingConvention.Cdecl)] + internal static extern int libevdev_get_id_bustype (IntPtr dev); + [DllImport(libevdev, CallingConvention = CallingConvention.Cdecl)] + internal static extern int libevdev_get_id_product (IntPtr dev); + [DllImport(libevdev, CallingConvention = CallingConvention.Cdecl)] + internal static extern int libevdev_get_id_vendor (IntPtr dev); + [DllImport(libevdev, CallingConvention = CallingConvention.Cdecl)] + internal static extern int libevdev_get_id_version (IntPtr dev); + [DllImport(libevdev, CallingConvention = CallingConvention.Cdecl)] + internal static extern IntPtr libevdev_get_phys (IntPtr dev); + [DllImport(libevdev, CallingConvention = CallingConvention.Cdecl)] + internal static extern IntPtr libevdev_get_uniq (IntPtr dev); + + [DllImport(libevdev, CallingConvention = CallingConvention.Cdecl)] + internal static extern IntPtr libevdev_event_type_get_name (uint type); + [DllImport(libevdev, CallingConvention = CallingConvention.Cdecl)] + internal static extern IntPtr libevdev_event_code_get_name (uint type, uint code); + + [DllImport(libevdev, CallingConvention = CallingConvention.Cdecl)] + internal static extern int libevdev_get_repeat (IntPtr dev, out int delay, out int period); + + [DllImport(libevdev, CallingConvention = CallingConvention.Cdecl)] + internal static extern int libevdev_has_event_type (IntPtr dev, EvType type); + [DllImport(libevdev, CallingConvention = CallingConvention.Cdecl)] + internal static extern int libevdev_has_event_code (IntPtr dev, EvType type, uint code); + [DllImport(libevdev, CallingConvention = CallingConvention.Cdecl)] + internal static extern int libevdev_has_property (IntPtr dev, PropertyType prop); + + [DllImport(libevdev, CallingConvention = CallingConvention.Cdecl)] + internal static extern int libevdev_grab (IntPtr dev, GrabMode mode); + [DllImport(libevdev, CallingConvention = CallingConvention.Cdecl)] + internal static extern int libevdev_next_event (IntPtr dev, ReadFlag flags, out InputEvent evt); + #endregion + + int fd = -1; + IntPtr handle = IntPtr.Zero; + + public Device (string devPath) + { + fd = Libc.open(devPath, OpenFlags.ReadOnly | OpenFlags.NonBlock); + if (fd < 0) + throw new Exception (string.Format ("EVDEV: faile to open {0}", devPath)); + int ret = libevdev_new_from_fd (fd, out handle); + if (ret < 0) + throw new Exception (string.Format ("EVDEV: ibevdev_new_from_fd failed on {0}: {1}", devPath, ret)); + } + public Device (int num) : this ("/dev/input/event" + num) + { + } + + public string Name { get { return Marshal.PtrToStringAuto(libevdev_get_name (handle)); }} + public string PhysLocation { get { return Marshal.PtrToStringAuto(libevdev_get_phys (handle)); }} + public string UniqueId { get { return Marshal.PtrToStringAuto (libevdev_get_uniq (handle)); }} + public int BusTypeId { get { return libevdev_get_id_bustype (handle); }} + public int ProductId { get { return libevdev_get_id_product (handle); }} + public int VendorId { get { return libevdev_get_id_vendor (handle); }} + public int VersionId { get { return libevdev_get_id_version (handle); }} + + public bool HasEventOfType (EvType evType) => libevdev_has_event_type (handle, evType) > 0; + public bool HasEventCodeOfType (EvType evType, uint evCode) => libevdev_has_event_code (handle, evType, evCode) > 0; + public bool HasEventOfType (PropertyType propType) => libevdev_has_property (handle, propType) > 0; + + public bool GetNextEvent (out InputEvent evt){ + return libevdev_next_event (handle, ReadFlag.Normal, out evt) == 0; + } + + public bool TryGrab (){ + return libevdev_grab (handle, GrabMode.Grab) == 0; + } + public bool TryRelease (){ + return libevdev_grab (handle, GrabMode.Ungrab) == 0; + } + const uint EVIOCGKEYCODE = 0x80084504; + const uint EVIOCGKEYCODE_V2 = 0x80284504; + + public void test(){ + int[] codes = new int[2]; + + for (int i=0; i<130; i++) { + + codes[0] = i; + int ret = Libc.ioctl (fd, EVIOCGKEYCODE, codes); + if(ret!=0) { + Console.WriteLine ("evdev ioctl error: " + ret); + }else + Console.WriteLine ("[0]= {0}, [1] = {1}\n", codes[0], codes[1]); + } + } + public void test2(){ + KeyMapEntry kme = default(KeyMapEntry); + + for (int i=0; i<130; i++) { + kme.Flags = 1; + kme.Index = (ushort)i; + kme.Length = sizeof(uint); + int ret = Libc.ioctl (fd, EVIOCGKEYCODE_V2, ref kme); + if(ret!=0) { + Console.WriteLine ("evdev ioctl error: " + ret); + }else + Console.WriteLine (kme.ToString()); + } + } +// public KeyMapEntry GetKeyMapEntry (KeyType k){ +// KeyMapEntry kme; +// return kme; +// } + #region IDisposable implementation + ~Device(){ + Dispose (false); + } + public void Dispose () + { + Dispose (true); + GC.SuppressFinalize (this); + } + protected virtual void Dispose (bool disposing){ + if (handle != IntPtr.Zero) + libevdev_free (handle); + handle = IntPtr.Zero; + if (fd > 0) + Libc.close(fd); + fd = -1; + } + #endregion + } +} + diff --git a/testDrm/src/EVDEV/Enums.cs b/testDrm/src/EVDEV/Enums.cs new file mode 100644 index 00000000..69edcdc0 --- /dev/null +++ b/testDrm/src/EVDEV/Enums.cs @@ -0,0 +1,734 @@ +// +// Enums.cs +// +// Author: +// Jean-Philippe Bruyère +// +// 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; + +namespace Linux.Evdev +{ + [Flags]public enum ReadFlag { + Sync = 0x01, /**< Process data in sync mode */ + Normal = 0x02, /**< Process data in normal mode */ + ForceSync = 0x04, /**< Pretend the next event is a SYN_DROPPED and require the caller to sync */ + Blocking = 0x08 /**< The fd is not in O_NONBLOCK and a read may block */ + } + + public enum PropertyType : uint { + Pointer = 0x0000, + Direct = 0x0001, + Buttonpad = 0x0002, + SemiMt = 0x0003, + Topbuttonpad = 0x0004, + PointingStick = 0x0005, + Accelerometer = 0x0006, + Max = 0x001F, + } + public enum EvType : uint { + Syn = 0x0000, + Key = 0x0001, + Rel = 0x0002, + Abs = 0x0003, + Msc = 0x0004, + Sw = 0x0005, + Led = 0x0011, + Snd = 0x0012, + Rep = 0x0014, + Ff = 0x0015, + Pwr = 0x0016, + FfStatus = 0x0017, + Max = 0x001F, + Cnt = (Max+1), + } + public enum SynType : uint { + Report = 0x0000, + Config = 0x0001, + MtReport = 0x0002, + Dropped = 0x0003, + Max = 0x000F, + } + public enum KeyType : uint { + Reserved = 0x0000, + Esc = 0x0001, + _1 = 0x0002, + _2 = 0x0003, + _3 = 0x0004, + _4 = 0x0005, + _5 = 0x0006, + _6 = 0x0007, + _7 = 0x0008, + _8 = 0x0009, + _9 = 0x000A, + _0 = 0x000B, + Minus = 0x000C, + Equal = 0x000D, + Backspace = 0x000E, + Tab = 0x000F, + Q = 0x0010, + W = 0x0011, + E = 0x0012, + R = 0x0013, + T = 0x0014, + Y = 0x0015, + U = 0x0016, + I = 0x0017, + O = 0x0018, + P = 0x0019, + Leftbrace = 0x001A, + Rightbrace = 0x001B, + Enter = 0x001C, + Leftctrl = 0x001D, + A = 0x001E, + S = 0x001F, + D = 0x0020, + F = 0x0021, + G = 0x0022, + H = 0x0023, + J = 0x0024, + K = 0x0025, + L = 0x0026, + Semicolon = 0x0027, + Apostrophe = 0x0028, + Grave = 0x0029, + Leftshift = 0x002A, + Backslash = 0x002B, + Z = 0x002C, + X = 0x002D, + C = 0x002E, + V = 0x002F, + B = 0x0030, + N = 0x0031, + M = 0x0032, + Comma = 0x0033, + Dot = 0x0034, + Slash = 0x0035, + Rightshift = 0x0036, + Kpasterisk = 0x0037, + Leftalt = 0x0038, + Space = 0x0039, + Capslock = 0x003A, + F1 = 0x003B, + F2 = 0x003C, + F3 = 0x003D, + F4 = 0x003E, + F5 = 0x003F, + F6 = 0x0040, + F7 = 0x0041, + F8 = 0x0042, + F9 = 0x0043, + F10 = 0x0044, + Numlock = 0x0045, + Scrolllock = 0x0046, + Kp7 = 0x0047, + Kp8 = 0x0048, + Kp9 = 0x0049, + Kpminus = 0x004A, + Kp4 = 0x004B, + Kp5 = 0x004C, + Kp6 = 0x004D, + Kpplus = 0x004E, + Kp1 = 0x004F, + Kp2 = 0x0050, + Kp3 = 0x0051, + Kp0 = 0x0052, + Kpdot = 0x0053, + Zenkakuhankaku = 0x0055, + _102nd = 0x0056, + F11 = 0x0057, + F12 = 0x0058, + Ro = 0x0059, + Katakana = 0x005A, + Hiragana = 0x005B, + Henkan = 0x005C, + Katakanahiragana = 0x005D, + Muhenkan = 0x005E, + Kpjpcomma = 0x005F, + Kpenter = 0x0060, + Rightctrl = 0x0061, + Kpslash = 0x0062, + Sysrq = 0x0063, + Rightalt = 0x0064, + Linefeed = 0x0065, + Home = 0x0066, + Up = 0x0067, + Pageup = 0x0068, + Left = 0x0069, + Right = 0x006A, + End = 0x006B, + Down = 0x006C, + Pagedown = 0x006D, + Insert = 0x006E, + Delete = 0x006F, + Macro = 0x0070, + Mute = 0x0071, + Volumedown = 0x0072, + Volumeup = 0x0073, + Power = 0x0074, + Kpequal = 0x0075, + Kpplusminus = 0x0076, + Pause = 0x0077, + Scale = 0x0078, + Kpcomma = 0x0079, + Hangeul = 0x007A, + Hanja = 0x007B, + Yen = 0x007C, + Leftmeta = 0x007D, + Rightmeta = 0x007E, + Compose = 0x007F, + Stop = 0x0080, + Again = 0x0081, + Props = 0x0082, + Undo = 0x0083, + Front = 0x0084, + Copy = 0x0085, + Open = 0x0086, + Paste = 0x0087, + Find = 0x0088, + Cut = 0x0089, + Help = 0x008A, + Menu = 0x008B, + Calc = 0x008C, + Setup = 0x008D, + Sleep = 0x008E, + Wakeup = 0x008F, + File = 0x0090, + Sendfile = 0x0091, + Deletefile = 0x0092, + Xfer = 0x0093, + Prog1 = 0x0094, + Prog2 = 0x0095, + Www = 0x0096, + Msdos = 0x0097, + Coffee = 0x0098, + RotateDisplay = 0x0099, + Cyclewindows = 0x009A, + Mail = 0x009B, + Bookmarks = 0x009C, + Computer = 0x009D, + Back = 0x009E, + Forward = 0x009F, + Closecd = 0x00A0, + Ejectcd = 0x00A1, + Ejectclosecd = 0x00A2, + Nextsong = 0x00A3, + Playpause = 0x00A4, + Previoussong = 0x00A5, + Stopcd = 0x00A6, + Record = 0x00A7, + Rewind = 0x00A8, + Phone = 0x00A9, + Iso = 0x00AA, + Config = 0x00AB, + Homepage = 0x00AC, + Refresh = 0x00AD, + Exit = 0x00AE, + Move = 0x00AF, + Edit = 0x00B0, + Scrollup = 0x00B1, + Scrolldown = 0x00B2, + Kpleftparen = 0x00B3, + Kprightparen = 0x00B4, + New = 0x00B5, + Redo = 0x00B6, + F13 = 0x00B7, + F14 = 0x00B8, + F15 = 0x00B9, + F16 = 0x00BA, + F17 = 0x00BB, + F18 = 0x00BC, + F19 = 0x00BD, + F20 = 0x00BE, + F21 = 0x00BF, + F22 = 0x00C0, + F23 = 0x00C1, + F24 = 0x00C2, + Playcd = 0x00C8, + Pausecd = 0x00C9, + Prog3 = 0x00CA, + Prog4 = 0x00CB, + Dashboard = 0x00CC, + Suspend = 0x00CD, + Close = 0x00CE, + Play = 0x00CF, + Fastforward = 0x00D0, + Bassboost = 0x00D1, + Print = 0x00D2, + Hp = 0x00D3, + Camera = 0x00D4, + Sound = 0x00D5, + Question = 0x00D6, + Email = 0x00D7, + Chat = 0x00D8, + Search = 0x00D9, + Connect = 0x00DA, + Finance = 0x00DB, + Sport = 0x00DC, + Shop = 0x00DD, + Alterase = 0x00DE, + Cancel = 0x00DF, + Brightnessdown = 0x00E0, + Brightnessup = 0x00E1, + Media = 0x00E2, + Switchvideomode = 0x00E3, + Kbdillumtoggle = 0x00E4, + Kbdillumdown = 0x00E5, + Kbdillumup = 0x00E6, + Send = 0x00E7, + Reply = 0x00E8, + Forwardmail = 0x00E9, + Save = 0x00EA, + Documents = 0x00EB, + Battery = 0x00EC, + Bluetooth = 0x00ED, + Wlan = 0x00EE, + Uwb = 0x00EF, + Unknown = 0x00F0, + VideoNext = 0x00F1, + VideoPrev = 0x00F2, + BrightnessCycle = 0x00F3, + BrightnessAuto = 0x00F4, + DisplayOff = 0x00F5, + Wwan = 0x00F6, + Rfkill = 0x00F7, + Micmute = 0x00F8, + Ok = 0x0160, + Select = 0x0161, + Goto = 0x0162, + Clear = 0x0163, + Power2 = 0x0164, + Option = 0x0165, + Info = 0x0166, + Time = 0x0167, + Vendor = 0x0168, + Archive = 0x0169, + Program = 0x016A, + Channel = 0x016B, + Favorites = 0x016C, + Epg = 0x016D, + Pvr = 0x016E, + Mhp = 0x016F, + Language = 0x0170, + Title = 0x0171, + Subtitle = 0x0172, + Angle = 0x0173, + Zoom = 0x0174, + Mode = 0x0175, + Keyboard = 0x0176, + Screen = 0x0177, + Pc = 0x0178, + Tv = 0x0179, + Tv2 = 0x017A, + Vcr = 0x017B, + Vcr2 = 0x017C, + Sat = 0x017D, + Sat2 = 0x017E, + Cd = 0x017F, + Tape = 0x0180, + Radio = 0x0181, + Tuner = 0x0182, + Player = 0x0183, + Text = 0x0184, + Dvd = 0x0185, + Aux = 0x0186, + Mp3 = 0x0187, + Audio = 0x0188, + Video = 0x0189, + Directory = 0x018A, + List = 0x018B, + Memo = 0x018C, + Calendar = 0x018D, + Red = 0x018E, + Green = 0x018F, + Yellow = 0x0190, + Blue = 0x0191, + Channelup = 0x0192, + Channeldown = 0x0193, + First = 0x0194, + Last = 0x0195, + Ab = 0x0196, + Next = 0x0197, + Restart = 0x0198, + Slow = 0x0199, + Shuffle = 0x019A, + Break = 0x019B, + Previous = 0x019C, + Digits = 0x019D, + Teen = 0x019E, + Twen = 0x019F, + Videophone = 0x01A0, + Games = 0x01A1, + Zoomin = 0x01A2, + Zoomout = 0x01A3, + Zoomreset = 0x01A4, + Wordprocessor = 0x01A5, + Editor = 0x01A6, + Spreadsheet = 0x01A7, + Graphicseditor = 0x01A8, + Presentation = 0x01A9, + Database = 0x01AA, + News = 0x01AB, + Voicemail = 0x01AC, + Addressbook = 0x01AD, + Messenger = 0x01AE, + Displaytoggle = 0x01AF, + Spellcheck = 0x01B0, + Logoff = 0x01B1, + Dollar = 0x01B2, + Euro = 0x01B3, + Frameback = 0x01B4, + Frameforward = 0x01B5, + ContextMenu = 0x01B6, + MediaRepeat = 0x01B7, + _10channelsup = 0x01B8, + _10channelsdown = 0x01B9, + Images = 0x01BA, + DelEol = 0x01C0, + DelEos = 0x01C1, + InsLine = 0x01C2, + DelLine = 0x01C3, + Fn = 0x01D0, + FnEsc = 0x01D1, + FnF1 = 0x01D2, + FnF2 = 0x01D3, + FnF3 = 0x01D4, + FnF4 = 0x01D5, + FnF5 = 0x01D6, + FnF6 = 0x01D7, + FnF7 = 0x01D8, + FnF8 = 0x01D9, + FnF9 = 0x01DA, + FnF10 = 0x01DB, + FnF11 = 0x01DC, + FnF12 = 0x01DD, + Fn1 = 0x01DE, + Fn2 = 0x01DF, + FnD = 0x01E0, + FnE = 0x01E1, + FnF = 0x01E2, + FnS = 0x01E3, + FnB = 0x01E4, + BrlDot1 = 0x01F1, + BrlDot2 = 0x01F2, + BrlDot3 = 0x01F3, + BrlDot4 = 0x01F4, + BrlDot5 = 0x01F5, + BrlDot6 = 0x01F6, + BrlDot7 = 0x01F7, + BrlDot8 = 0x01F8, + BrlDot9 = 0x01F9, + BrlDot10 = 0x01FA, + Numeric0 = 0x0200, + Numeric1 = 0x0201, + Numeric2 = 0x0202, + Numeric3 = 0x0203, + Numeric4 = 0x0204, + Numeric5 = 0x0205, + Numeric6 = 0x0206, + Numeric7 = 0x0207, + Numeric8 = 0x0208, + Numeric9 = 0x0209, + NumericStar = 0x020A, + NumericPound = 0x020B, + NumericA = 0x020C, + NumericB = 0x020D, + NumericC = 0x020E, + NumericD = 0x020F, + CameraFocus = 0x0210, + WpsButton = 0x0211, + TouchpadToggle = 0x0212, + TouchpadOn = 0x0213, + TouchpadOff = 0x0214, + CameraZoomin = 0x0215, + CameraZoomout = 0x0216, + CameraUp = 0x0217, + CameraDown = 0x0218, + CameraLeft = 0x0219, + CameraRight = 0x021A, + AttendantOn = 0x021B, + AttendantOff = 0x021C, + AttendantToggle = 0x021D, + LightsToggle = 0x021E, + AlsToggle = 0x0230, + Buttonconfig = 0x0240, + Taskmanager = 0x0241, + Journal = 0x0242, + Controlpanel = 0x0243, + Appselect = 0x0244, + Screensaver = 0x0245, + Voicecommand = 0x0246, + BrightnessMin = 0x0250, + BrightnessMax = 0x0251, + KbdinputassistPrev = 0x0260, + KbdinputassistNext = 0x0261, + KbdinputassistPrevgroup= 0x0262, + KbdinputassistNextgroup= 0x0263, + KbdinputassistAccept= 0x0264, + KbdinputassistCancel= 0x0265, + RightUp = 0x0266, + RightDown = 0x0267, + LeftUp = 0x0268, + LeftDown = 0x0269, + RootMenu = 0x026A, + MediaTopMenu = 0x026B, + Numeric11 = 0x026C, + Numeric12 = 0x026D, + AudioDesc = 0x026E, + _3dMode = 0x026F, + NextFavorite = 0x0270, + StopRecord = 0x0271, + PauseRecord = 0x0272, + Vod = 0x0273, + Unmute = 0x0274, + Fastreverse = 0x0275, + Slowreverse = 0x0276, + Data = 0x0277, + Max = 0x02FF, + } + public enum BtnType : uint { + Misc = 0x0100, + _0 = 0x0100, + _1 = 0x0101, + _2 = 0x0102, + _3 = 0x0103, + _4 = 0x0104, + _5 = 0x0105, + _6 = 0x0106, + _7 = 0x0107, + _8 = 0x0108, + _9 = 0x0109, + Mouse = 0x0110, + Left = 0x0110, + Right = 0x0111, + Middle = 0x0112, + Side = 0x0113, + Extra = 0x0114, + Forward = 0x0115, + Back = 0x0116, + Task = 0x0117, + Joystick = 0x0120, + Trigger = 0x0120, + Thumb = 0x0121, + Thumb2 = 0x0122, + Top = 0x0123, + Top2 = 0x0124, + Pinkie = 0x0125, + Base = 0x0126, + Base2 = 0x0127, + Base3 = 0x0128, + Base4 = 0x0129, + Base5 = 0x012A, + Base6 = 0x012B, + Dead = 0x012F, + Gamepad = 0x0130, + South = 0x0130, + East = 0x0131, + C = 0x0132, + North = 0x0133, + West = 0x0134, + Z = 0x0135, + Tl = 0x0136, + Tr = 0x0137, + Tl2 = 0x0138, + Tr2 = 0x0139, + Select = 0x013A, + Start = 0x013B, + Mode = 0x013C, + Thumbl = 0x013D, + Thumbr = 0x013E, + Digi = 0x0140, + ToolPen = 0x0140, + ToolRubber = 0x0141, + ToolBrush = 0x0142, + ToolPencil = 0x0143, + ToolAirbrush = 0x0144, + ToolFinger = 0x0145, + ToolMouse = 0x0146, + ToolLens = 0x0147, + ToolQuinttap = 0x0148, + Touch = 0x014A, + Stylus = 0x014B, + Stylus2 = 0x014C, + ToolDoubletap = 0x014D, + ToolTripletap = 0x014E, + ToolQuadtap = 0x014F, + Wheel = 0x0150, + GearDown = 0x0150, + GearUp = 0x0151, + DpadUp = 0x0220, + DpadDown = 0x0221, + DpadLeft = 0x0222, + DpadRight = 0x0223, + TriggerHappy = 0x02C0, + TriggerHappy1 = 0x02C0, + TriggerHappy2 = 0x02C1, + TriggerHappy3 = 0x02C2, + TriggerHappy4 = 0x02C3, + TriggerHappy5 = 0x02C4, + TriggerHappy6 = 0x02C5, + TriggerHappy7 = 0x02C6, + TriggerHappy8 = 0x02C7, + TriggerHappy9 = 0x02C8, + TriggerHappy10 = 0x02C9, + TriggerHappy11 = 0x02CA, + TriggerHappy12 = 0x02CB, + TriggerHappy13 = 0x02CC, + TriggerHappy14 = 0x02CD, + TriggerHappy15 = 0x02CE, + TriggerHappy16 = 0x02CF, + TriggerHappy17 = 0x02D0, + TriggerHappy18 = 0x02D1, + TriggerHappy19 = 0x02D2, + TriggerHappy20 = 0x02D3, + TriggerHappy21 = 0x02D4, + TriggerHappy22 = 0x02D5, + TriggerHappy23 = 0x02D6, + TriggerHappy24 = 0x02D7, + TriggerHappy25 = 0x02D8, + TriggerHappy26 = 0x02D9, + TriggerHappy27 = 0x02DA, + TriggerHappy28 = 0x02DB, + TriggerHappy29 = 0x02DC, + TriggerHappy30 = 0x02DD, + TriggerHappy31 = 0x02DE, + TriggerHappy32 = 0x02DF, + TriggerHappy33 = 0x02E0, + TriggerHappy34 = 0x02E1, + TriggerHappy35 = 0x02E2, + TriggerHappy36 = 0x02E3, + TriggerHappy37 = 0x02E4, + TriggerHappy38 = 0x02E5, + TriggerHappy39 = 0x02E6, + TriggerHappy40 = 0x02E7, + } + public enum RelType : uint { + X = 0x0000, + Y = 0x0001, + Z = 0x0002, + Rx = 0x0003, + Ry = 0x0004, + Rz = 0x0005, + Hwheel = 0x0006, + Dial = 0x0007, + Wheel = 0x0008, + Misc = 0x0009, + Max = 0x000F, + } + public enum AbsType : uint { + X = 0x0000, + Y = 0x0001, + Z = 0x0002, + Rx = 0x0003, + Ry = 0x0004, + Rz = 0x0005, + Throttle = 0x0006, + Rudder = 0x0007, + Wheel = 0x0008, + Gas = 0x0009, + Brake = 0x000A, + Hat0x = 0x0010, + Hat0y = 0x0011, + Hat1x = 0x0012, + Hat1y = 0x0013, + Hat2x = 0x0014, + Hat2y = 0x0015, + Hat3x = 0x0016, + Hat3y = 0x0017, + Pressure = 0x0018, + Distance = 0x0019, + TiltX = 0x001A, + TiltY = 0x001B, + ToolWidth = 0x001C, + Volume = 0x0020, + Misc = 0x0028, + MtSlot = 0x002F, + MtTouchMajor = 0x0030, + MtTouchMinor = 0x0031, + MtWidthMajor = 0x0032, + MtWidthMinor = 0x0033, + MtOrientation = 0x0034, + MtPositionX = 0x0035, + MtPositionY = 0x0036, + MtToolType = 0x0037, + MtBlobId = 0x0038, + MtTrackingId = 0x0039, + MtPressure = 0x003A, + MtDistance = 0x003B, + MtToolX = 0x003C, + MtToolY = 0x003D, + Max = 0x003F, + } + public enum SwType : uint { + Lid = 0x0000, + TabletMode = 0x0001, + HeadphoneInsert = 0x0002, + RfkillAll = 0x0003, + MicrophoneInsert = 0x0004, + Dock = 0x0005, + LineoutInsert = 0x0006, + JackPhysicalInsert = 0x0007, + VideooutInsert = 0x0008, + CameraLensCover = 0x0009, + KeypadSlide = 0x000A, + FrontProximity = 0x000B, + RotateLock = 0x000C, + LineinInsert = 0x000D, + MuteDevice = 0x000E, + PenInserted = 0x000F, + Max = 0x000F, + } + public enum MscType : uint { + Serial = 0x0000, + Pulseled = 0x0001, + Gesture = 0x0002, + Raw = 0x0003, + Scan = 0x0004, + Timestamp = 0x0005, + Max = 0x0007, + } + public enum LedType : uint { + Numl = 0x0000, + Capsl = 0x0001, + Scrolll = 0x0002, + Compose = 0x0003, + Kana = 0x0004, + Sleep = 0x0005, + Suspend = 0x0006, + Mute = 0x0007, + Misc = 0x0008, + Mail = 0x0009, + Charging = 0x000A, + Max = 0x000F, + } + public enum RepType : uint { + Delay = 0x0000, + Period = 0x0001, + Max = 0x0001, + } + public enum SndType : uint { + Click = 0x0000, + Bell = 0x0001, + Tone = 0x0002, + Max = 0x0007, + } +} + diff --git a/testDrm/src/Egl/Context.cs b/testDrm/src/Egl/Context.cs index 92a97437..c7b0eb69 100644 --- a/testDrm/src/Egl/Context.cs +++ b/testDrm/src/Egl/Context.cs @@ -370,39 +370,65 @@ namespace EGL ctx = CreateContext(dpy, currentCfg, IntPtr.Zero, contextAttrib); if (ctx == IntPtr.Zero) throw new NotSupportedException(String.Format("[EGL] Failed to create egl context, error {0}.", GetError())); - -// int[] attribs = new int[] { -// (int)Attribute.BufferSize, -// Egl.RED_SIZE, -// Egl.GREEN_SIZE, -// Egl.BLUE_SIZE, -// Egl.ALPHA_SIZE, -// (int)Attribute.DepthSize, -// //(int)Attribute.Height, -// Egl.WIDTH, -// (int)Attribute.Width, -// (int)Attribute.Samples, -// (int)Attribute.SampleBuffers, -// (int)Attribute.RenderableType, -// (int)Attribute.SurfaceType, -// (int)Attribute.Level, -// (int)Attribute.ConfigCaveat, -// }; -// -// for (int i = 0; i < configs.Length; i++) { -// IntPtr conf = configs[i]; -// Console.Write ("{0,-3}:", i); -// for (int j = 0; j < attribs.Length; j++) { -// int value; -// GetConfigAttrib (dpy, conf, attribs[j], out value); -// Console.Write ("\t{0} = {1}, ", EglConstToString ((int)attribs[j]), value); -// } -// Console.Write ("\n"); -// } - } #endregion + public IntPtr GetConfig (int[] desiredCfg){ + int num_configs; + IntPtr[] configs = new IntPtr[1]; + if (!ChooseConfig(dpy, desiredCfg, configs, 1, out num_configs)||num_configs<1) + throw new NotSupportedException(String.Format("[EGL] Failed to retrieve GraphicsMode, error {0}", GetError())); + return configs [0]; + } + public IntPtr[] GetAllConfigs (){ + int num_configs; + int[] desiredConfig = new int[] + { + Egl.SURFACE_TYPE, Egl.PBUFFER_BIT, + Egl.RENDERABLE_TYPE, Egl.OPENGL_BIT, + Egl.NONE + }; + + if (!ChooseConfig(dpy, desiredConfig, null, 0, out num_configs)||num_configs==0) + throw new NotSupportedException(String.Format("[EGL] Failed to retrieve GraphicsMode, error {0}", GetError())); + + IntPtr[] configs = new IntPtr[num_configs]; + if (!ChooseConfig(dpy, null, configs, num_configs, out num_configs)) + throw new NotSupportedException(String.Format("[EGL] Failed to retrieve GraphicsMode, error {0}", GetError())); + return configs; + } + public void DumpAllConf(){ + Console.Write ("EGL Configs"); + IntPtr[] configs = GetAllConfigs(); + int[] attribs = new int[] { + (int)Attribute.BufferSize, + Egl.RED_SIZE, + Egl.GREEN_SIZE, + Egl.BLUE_SIZE, + Egl.ALPHA_SIZE, + (int)Attribute.DepthSize, + //(int)Attribute.Height, + Egl.WIDTH, + (int)Attribute.Width, + (int)Attribute.Samples, + (int)Attribute.SampleBuffers, + (int)Attribute.RenderableType, + (int)Attribute.SurfaceType, + (int)Attribute.Level, + (int)Attribute.ConfigCaveat, + }; + + for (int i = 0; i < configs.Length; i++) { + IntPtr conf = configs[i]; + Console.Write ("{0,-3}:", i); + for (int j = 0; j < attribs.Length; j++) { + int value; + GetConfigAttrib (dpy, conf, attribs[j], out value); + Console.Write ("\t{0} = {1}, ", EglConstToString ((int)attribs[j]), value); + } + Console.Write ("\n"); + } + } enum ConfigAttribute { RedSize , GreenSize, @@ -413,16 +439,6 @@ namespace EGL if (!Context.MakeCurrent (dpy, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero)) Console.WriteLine ("egl clear current ctx failed"); } - public void DestroyContext (){ - try { - if (ctx != IntPtr.Zero) - DestroyContext (dpy, ctx); - } catch (Exception ex) { - Console.WriteLine ("error disposing egl context: {0}", ex.ToString ()); - }finally { - ctx = IntPtr.Zero; - } - } #region IDisposable implementation ~Context(){ @@ -434,8 +450,17 @@ namespace EGL GC.SuppressFinalize (this); } protected virtual void Dispose (bool disposing){ - if (dpy != IntPtr.Zero) - Terminate (dpy); + try { + if (ctx != IntPtr.Zero) + DestroyContext (dpy, ctx); + if (dpy != IntPtr.Zero) + Terminate (dpy); + } catch (Exception ex) { + Console.WriteLine ("error disposing egl context: {0}", ex.ToString ()); + }finally { + ctx = IntPtr.Zero; + dpy = IntPtr.Zero; + } } #endregion diff --git a/testDrm/src/Egl/Surface.cs b/testDrm/src/Egl/Surface.cs index 5a441a56..2faa76b7 100644 --- a/testDrm/src/Egl/Surface.cs +++ b/testDrm/src/Egl/Surface.cs @@ -66,6 +66,12 @@ namespace EGL Context ctx; internal EGLSurface handle; + Surface (Context _ctx, IntPtr config, int[] attrib_list){ + ctx = _ctx; + handle = eglCreatePbufferSurface (ctx.dpy, config, attrib_list); + if (handle == IntPtr.Zero) + throw new NotSupportedException(String.Format("[EGL] Failed to create surface, error {0}.", EGL.Context.GetError())); + } public Surface (Context _ctx, Linux.GBM.Surface gbmSurf) { ctx = _ctx; @@ -73,6 +79,26 @@ namespace EGL if (handle == IntPtr.Zero) throw new NotSupportedException(String.Format("[EGL] Failed to create surface, error {0}.", EGL.Context.GetError())); } + public static Surface CreatePBuffer (Context _ctx, int _width, int _height){ + int[] config = new int[] + { + Egl.SURFACE_TYPE, Egl.PBUFFER_BIT, +// Egl.RENDERABLE_TYPE, Egl.OPENGL_BIT, +// Egl.RED_SIZE, 8, +// Egl.GREEN_SIZE, 8, +// Egl.BLUE_SIZE, 8, + Egl.NONE + }; + int[] attribs = new int[] + { + Egl.WIDTH, _width, + Egl.HEIGHT, _height, + Egl.NONE + }; + IntPtr cfg = _ctx.GetConfig (config); + Console.WriteLine ("pbuff cfg: {0}", cfg.ToString ()); + return new Surface (_ctx, cfg, attribs); + } public void MakeCurrent (){ if (!Context.MakeCurrent(ctx.dpy, handle, handle, ctx.ctx)) diff --git a/testDrm/src/Linux/Bindings/EvdevClass.cs b/testDrm/src/Linux/Bindings/EvdevClass.cs new file mode 100644 index 00000000..d024bf07 --- /dev/null +++ b/testDrm/src/Linux/Bindings/EvdevClass.cs @@ -0,0 +1,640 @@ +#region License +// +// Evdev.cs +// +// Author: +// Stefanos A. +// +// 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. +// +using OpenTK; +using Linux; +using Crow; + + +#endregion + +using System; +using System.Diagnostics; +using System.Runtime.InteropServices; + +namespace Linux.oldEvDev +{ + // Bindings for linux/input.h + class EvdevClass + { + + 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.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/LibInput.cs b/testDrm/src/Linux/Bindings/LibInput.cs index c1a56ad5..aa72c8e1 100644 --- a/testDrm/src/Linux/Bindings/LibInput.cs +++ b/testDrm/src/Linux/Bindings/LibInput.cs @@ -275,7 +275,7 @@ namespace Linux 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 Linux.oldEvDev.EvdevButton Button { get { return (Linux.oldEvDev.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; } @@ -328,6 +328,11 @@ namespace Linux [DllImport(LibInput.lib, EntryPoint = "libinput_event_pointer_get_absolute_y_transformed", CallingConvention = CallingConvention.Cdecl)] static extern double GetAbsYTransformed(IntPtr @event, int height); + + public override string ToString () + { + return string.Format ("[PointerEvent: BaseEvent={0}, Event={1}, Time={2}, Button={3}, ButtonCount={4}, ButtonState={5}, DeltaX={6}, DeltaY={7}, X={8}, Y={9}]", BaseEvent, Event, Time, Button, ButtonCount, ButtonState, DeltaX, DeltaY, X, Y); + } } } diff --git a/testDrm/src/Linux/Bindings/Libc.cs b/testDrm/src/Linux/Bindings/Libc.cs index c3a07094..35098bd4 100644 --- a/testDrm/src/Linux/Bindings/Libc.cs +++ b/testDrm/src/Linux/Bindings/Libc.cs @@ -52,10 +52,16 @@ namespace Linux 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); + public static extern int ioctl(int d, Linux.oldEvDev.EvdevIoctl request, [Out] IntPtr data); [DllImport(lib)] - public static extern int ioctl(int d, uint request, [Out] IntPtr data); + public static extern int ioctl(int d, uint request, [Out] IntPtr data); + + [DllImport(lib)] + public static extern int ioctl(int d, uint request, ref Evdev.KeyMapEntry kme); + + [DllImport(lib)] + public static extern int ioctl(int d, uint request, [In, Out] int[] data); [DllImport(lib)] public static extern int ioctl(int d, KeyboardIoctlCode request, ref IntPtr data); @@ -113,6 +119,17 @@ namespace Linux [DllImport(lib)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool isatty(int fd); + + [DllImport(lib)] + public static extern int getgid (); + [DllImport(lib)] + public static extern int setpgid (int pid, int pgid); + [DllImport(lib)] + public static extern int getpgid (int pid); + + //public static extern int setpgrp (int pgid); + [DllImport(lib)] + public static extern int getpgrp (); } enum ErrorNumber diff --git a/testDrm/src/Linux/DRI/DRIControler.cs b/testDrm/src/Linux/DRI/DRIControler.cs index a336309d..3c0c5e3d 100644 --- a/testDrm/src/Linux/DRI/DRIControler.cs +++ b/testDrm/src/Linux/DRI/DRIControler.cs @@ -82,7 +82,7 @@ namespace Linux.DRI { // FLAG_3D_L_DEPTH (5<<14) // FLAG_3D_L_DEPTH_GFX_GFX_DEPTH (6<<14) // FLAG_3D_TOP_AND_BOTTOM (7<<14) - // FLAG_3D_SIDE_BY_SIDE_HALF (8<<14) + // FLAG_3D_SIDE_BY_SIDE_HALF (8<<14) } #endregion @@ -143,7 +143,7 @@ namespace Linux.DRI { int fd_gpu = -1; GBM.Device gbmDev; GBM.Surface gbmSurf; - EGL.Context eglctx; + public EGL.Context eglctx; EGL.Surface eglSurf; Cairo.EGLDevice cairoDev; @@ -165,14 +165,14 @@ namespace Linux.DRI { fd_gpu = Libc.open(gpu_path, OpenFlags.ReadWrite | OpenFlags.CloseOnExec); if (fd_gpu < 0) throw new NotSupportedException("[DRI] Failed to open gpu"); - + resources = new Resources (fd_gpu); gbmDev = new GBM.Device (fd_gpu); eglctx = new EGL.Context (gbmDev); try { if (defaultConfiguration ()) - Console.WriteLine ("default config ok"); + Console.WriteLine ("default config ok"); } catch (Exception ex) { Console.WriteLine (ex.ToString()); } @@ -188,19 +188,17 @@ namespace Linux.DRI { if (c.State == ConnectionStatus.Connected) { connector = c; break; - } + } } if (connector == null) return false; - + currentCrtc = connector.CurrentEncoder.CurrentCrtc; originalMode = currentCrtc.CurrentMode; originalFB = currentCrtc.CurrentFbId; //currentMode = originalMode; currentMode = getNewMode(); - //setScanOutRegion(); - //configure a rendering stack gbmSurf = new GBM.Surface (gbmDev, Width, Height, GBM.SurfaceFlags.Rendering | GBM.SurfaceFlags.Scanout); @@ -213,7 +211,7 @@ namespace Linux.DRI { CairoSurf = new Cairo.GLSurface (cairoDev, eglSurf.handle, Width, Height); //cairoSurf = new Cairo.EGLSurface (cairoDev, egl_surface, 1600, 900); - cairoDev.SetThreadAware (false); + cairoDev.SetThreadAware (true); if (cairoDev.Acquire () != Cairo.Status.Success) Console.WriteLine ("[Cairo]: Failed to acquire egl device."); @@ -245,28 +243,24 @@ namespace Linux.DRI { } } + unsafe GBM.gbm_bo* bo; + uint fb; - - unsafe public void Update(){ - GBM.gbm_bo* bo; - uint fb; - + int ret = 0; if (!gbmSurf.HasFreeBuffers) throw new NotSupportedException("[GBM] Out of free buffer"); - bo = gbmSurf.Lock (); - int ret = drmModeAddFB (fd_gpu, currentMode.hdisplay, currentMode.vdisplay, (byte)depth, (byte)bpp, bo->Stride, (uint)bo->Handle32, out fb); - if (ret != 0) - Console.WriteLine ("addFb failed: {0}", ret); - bo->SetUserData (ref fb, handleDestroyFB); - + if (fb == 0) { + ret = drmModeAddFB (fd_gpu, currentMode.hdisplay, currentMode.vdisplay, (byte)depth, (byte)bpp, bo->Stride, (uint)bo->Handle32, out fb); + if (ret != 0) + Console.WriteLine ("addFb failed: {0}", ret); + } uint connId = connector.Id; ret = drmModeSetCrtc (fd_gpu, currentCrtc.Id, fb, 0, 0, &connId, 1, ref currentMode); if (ret != 0) Console.WriteLine ("setCrtc failed: {0}", ret); - gbmSurf.Release (bo); } @@ -287,17 +281,9 @@ namespace Linux.DRI { evctx.version = EventContext.Version; evctx.page_flip_handler = Marshal.GetFunctionPointerForDelegate((PageFlipCallback)HandlePageFlip); } - unsafe GBM.gbm_bo* bo; unsafe public void UpdateWithPageFlip(){ - GBM.gbm_bo* next_bo; + GBM.gbm_bo* next_bo; uint fb; -// fds = new PollFD(); -// fds.fd = fd_gpu; -// fds.events = PollFlags.In; - -// evctx = new EventContext(); -// evctx.version = EventContext.Version; -// evctx.page_flip_handler = PageFlipPtr; int timeout = -1;//block ? -1 : 0; @@ -311,7 +297,7 @@ namespace Linux.DRI { Console.WriteLine ("addFb failed: {0}", ret); next_bo->SetUserData (ref fb, handleDestroyFB); - if (bo == null) { + if (bo == null) { uint connId = connector.Id; ret = drmModeSetCrtc (fd_gpu, currentCrtc.Id, fb, 0, 0, &connId, 1, ref currentMode); if (ret != 0) @@ -329,7 +315,7 @@ namespace Linux.DRI { while (is_flip_queued != 0) { fds.revents = 0; if (Libc.poll (ref fds, 1, timeout) < 0) - break; + break; if ((fds.revents & (PollFlags.Hup | PollFlags.Error)) != 0) break; if ((fds.revents & PollFlags.In) != 0) @@ -358,7 +344,7 @@ namespace Linux.DRI { } boMouseCursor = new GBM.BufferObject (gbmDev, width, height, GBM.SurfaceFormat.ARGB8888, GBM.SurfaceFlags.Cursor64x64 | GBM.SurfaceFlags.Write); - + // Copy cursor.Data into a new buffer of the correct size byte[] cursor_data = new byte[width * height * 4]; for (uint y = 0; y < cursor.Height; y++) @@ -401,27 +387,7 @@ namespace Linux.DRI { mode.flags |= (uint)VideoMode.PVSYNC; return mode; } - unsafe void setScanOutRegion(){ - - //currentCrtc.handle->mode = currentMode; - // ModeInfo* mode = (ModeInfo*)Marshal.AllocHGlobal (sizeof(ModeInfo));// pConnector->modes; - // *mode = currentMode; - - uint fb; - GBM.gbm_bo* bo = GBM.BufferObject.gbm_bo_create (gbmDev.handle, (uint)Width, (uint)Height, GBM.SurfaceFormat.ARGB8888, GBM.SurfaceFlags.Rendering); - int ret = drmModeAddFB (fd_gpu, (uint)Width, (uint)Height, (byte)depth, (byte)bpp, bo->Stride, (uint)bo->Handle32, out fb); - if (ret != 0) - Console.WriteLine ("addFb failed: {0}", ret); - bo->SetUserData (ref fb, handleDestroyFB); - - uint connId = connector.Id; - ret = drmModeSetCrtc (fd_gpu, currentCrtc.Id, currentCrtc.CurrentFbId, 0, 0, &connId, 1, ref currentMode); - if (ret != 0) - Console.WriteLine ("set new mode setCrtc failed: {0}", ret); - //GBM.BufferObject.gbm_bo_destroy (bo); - Console.WriteLine ("new mode set to {0} x {1} fbid:{2}", Width, Height, currentCrtc.CurrentFbId); - } // unsafe public drmPlane GetPlane (uint id) { // drmPlane p = new drmPlane(); @@ -439,7 +405,7 @@ namespace Linux.DRI { // p.x, p.y, // src_w, src_h); // -// +// // } #region IDisposable implementation @@ -451,12 +417,19 @@ namespace Linux.DRI { Dispose (true); GC.SuppressFinalize (this); } + bool disposed = false; protected virtual void Dispose (bool disposing){ + if (disposed) + return; unsafe{ if (bo != null) - gbmSurf.Release (bo); + gbmSurf.Release (bo); } - Thread.Sleep (10); + if (fb != 0) + if (drmModeRmFB (fd_gpu, fb) != 0) + Console.WriteLine ("DestroyFB failed"); + if (eglctx != null) + eglctx.ResetMakeCurrent (); if (cairoDev != null) { cairoDev.Release (); CairoSurf.Dispose (); @@ -480,76 +453,31 @@ namespace Linux.DRI { } if (eglctx != null) { eglctx.ResetMakeCurrent (); - eglctx.DestroyContext (); - if (eglSurf != null) - eglSurf.Dispose (); + eglSurf.Dispose (); eglSurf = null; + if (eglctx != null) + eglctx.Dispose (); + eglctx = null; } if (gbmSurf != null) gbmSurf.Dispose (); - if (eglctx != null) - eglctx.Dispose (); - eglctx = null; if (gbmDev != null) gbmDev.Dispose (); - if (currentCrtc != null) - currentCrtc.Dispose (); + currentCrtc.Dispose (); if (connector != null) - connector.Dispose (); + connector.Dispose (); if (resources != null) resources.Dispose (); resources = null; if (fd_gpu > 0) Libc.close (fd_gpu); fd_gpu = -1; + disposed = true; Console.WriteLine ("GPU controler disposed"); } #endregion - - - unsafe public void MarkFBDirty(){ - IntPtr pClip = Marshal.AllocHGlobal (sizeof(drmClip)); - drmClip dc = new drmClip () { x1 = 0, y1 = 0, x2 = 500, y2 = 500 }; - Marshal.StructureToPtr (dc, pClip,false); - int ret = drmModeDirtyFB (fd_gpu, currentCrtc.CurrentFbId, IntPtr.Zero, 0); - if (ret < 0) - Console.WriteLine ("set FB dirty failed: {0}", ret); - } - - -// unsafe static bool paint(gbm_bo * bo) -// { -// uint w = (uint)bo->Width; -// uint h = (uint)bo->Height; -// uint stride = (uint)bo->Stride; -// -// Console.WriteLine ("trying to map bo: {0}x{1} stride:{2}", w, h, stride); -// bool success = false; -// try { -// unsafe { -// IntPtr map_data = IntPtr.Zero; -// IntPtr addr = Gbm.Map (bo, 0, 0, w, h, TransferFlags.Write, ref stride, out map_data); -// if (addr == IntPtr.Zero || map_data == IntPtr.Zero) { -// Console.WriteLine ("failed to mmap gbm bo"); -// return false; -// } -// Console.WriteLine ("addr = {0}", addr.ToString()); -// byte* b = (byte*)addr; -// for (int y = 0; y < h; y++) { -// for (int x = 0; x < w; x++) { -// *(b + x + y * stride) = 0xff; -// } -// } -// Gbm.Unmap (bo, map_data); -// success = true; -// } -// } catch (Exception ex) { -// Console.WriteLine (ex.ToString ()); -// } -// return success; -// } } } \ No newline at end of file diff --git a/testDrm/src/Linux/VT.cs b/testDrm/src/Linux/VT.cs index c555fe2a..00e52335 100644 --- a/testDrm/src/Linux/VT.cs +++ b/testDrm/src/Linux/VT.cs @@ -25,6 +25,7 @@ // THE SOFTWARE. using System; using System.Runtime.InteropServices; +using System.Collections.Generic; namespace Linux.VT { public enum KDMode : byte { @@ -33,7 +34,7 @@ namespace Linux.VT { TEXT0 = 0x02, /* obsolete */ TEXT1 = 0x03 /* obsolete */ } - public enum SwitchMode : sbyte { + public enum SwitchMode : byte { AUTO = 0x00, /* auto vt switching */ PROCESS = 0x01, /* process controls switching */ ACKACQ = 0x02 /* acknowledge switch */ @@ -45,12 +46,17 @@ namespace Linux.VT { UNICODE = 0x03, OFF = 0x04, } + [StructLayout(LayoutKind.Sequential)] public struct vt_mode { public SwitchMode mode; /* vt mode */ - public sbyte waitv; /* if set, hang on writes if not active */ + public byte waitv; /* if set, hang on writes if not active */ public short relsig; /* signal to raise on release req */ public short acqsig; /* signal to raise on acquisition */ public short frsig; /* unused (set to 0) */ + public override string ToString () + { + return string.Format ("[vt_mode]:waitv:{0} relsig:{1} acqsig:{2} switchmode:{3}", waitv, relsig, acqsig, mode); + } } public struct State { public ushort v_active; /* active vt */ @@ -62,13 +68,70 @@ namespace Linux.VT { public ushort v_cols; /* number of columns */ public ushort v_scrollsize; /* number of lines of scrollback */ } + [StructLayout(LayoutKind.Sequential)] + unsafe public struct KbsEntry { + public byte kb_func; + fixed byte kb_string[512]; + + public string KbString { + get { + fixed(byte* bytes = kb_string) { + int i = 0; + List lb = new List (); + while (i<512){ + byte b = (byte)*(bytes + i); + if ((int)b == 0) + break; + lb.Add (b); + i++; + } + string test = System.Text.Encoding.ASCII.GetString (lb.ToArray ()); + + return test; + } + + } + } + } + [StructLayout(LayoutKind.Sequential)] public struct KbEntry { - public byte kb_table; + public KbTable kb_table; public byte kb_index; public ushort kb_value; + + public byte ActionCode { get { return (byte)(kb_value & 0xff);}} + public KtType KeyType { get { return (KtType)(kb_value>>8); }} + + public override string ToString () + { + return string.Format ("KbEntry: {0} {1} {2}", kb_table, kb_index, kb_value); + } + } + [Flags]public enum KtType : byte { + Latin = 0x00, /* we depend on this being zero */ + Fn = 0x01, + Spec = 0x02, + Pad = 0x03, + Dead = 0x04, + Cons = 0x05, + Cur = 0x06, + Shift = 0x07, + Meta = 0x08, + Ascii = 0x09, + Lock = 0x0a, + Letter = 0x0b, /* symbol that can be acted upon by CapsLock */ + Slock = 0x0c, + Dead2 = 0x0d, + Brl = 0x0e } + [Flags]public enum KbTable : byte { + Normal = 0x00, + Shift = 0x01, + Alt = 0x02, + AltShift= 0x03 + } public class VTControler : IDisposable { public int fd = -1; @@ -81,7 +144,7 @@ namespace Linux.VT { #endregion /// set Graphic or Text mode for VT. - unsafe public KDMode KDMode { + public KDMode KDMode { get { KDMode m = 0; if (ioctl (fd, KDGETMODE, ref m) < 0) @@ -94,7 +157,7 @@ namespace Linux.VT { } } /// set AUTO or PROCESS mode for VT. - unsafe public vt_mode VTMode { + public vt_mode VTMode { get { vt_mode m = new vt_mode(); if (ioctl (fd, VT_GETMODE, ref m) < 0) @@ -106,7 +169,19 @@ namespace Linux.VT { throw new Exception ("VTControler: failed to set VTMode for current VT"); } } - + /// get/set keyboard mode. + public KbdMode KbdMode { + get { + KbdMode m = 0; + if (ioctl (fd, KDGKBMODE, ref m) < 0) + throw new Exception ("VTControler: failed to get current keyboard mode"); + return m; + } + set { + if (ioctl (fd, KDSKBMODE, (int)value) < 0) + throw new Exception ("VTControler: failed to set current keyboard mode"); + } + } /// /// Switchs to V. /// @@ -147,6 +222,30 @@ namespace Linux.VT { if (ioctl (fd, VT_RELDISP, ACKACQ)<0) throw new Exception ("VTControler: failed to acknowledge switch with VT_RELDISP"); } + public void AtachProcessTOTTY (int ttyNum){ + int ret =ioctl (fd, TIOCSCTTY, ttyNum); + if (ret<0) + throw new Exception (string.Format ("VTControler: failed to attach process to TTY {0}: {1}",ttyNum,ret)); + } + public void DetachProcess () { + if (ioctl (fd, TIOCNOTTY, 0)<0) + throw new Exception ("VTControler: failed to dettach process from TTY"); + } + + public KbEntry GetKDBEntry (KbTable table, byte index){ + KbEntry ke = new KbEntry() { kb_table = table, kb_index = index}; + int ret = ioctl (fd, KDGKBENT, ref ke); + if (ret < 0) + throw new Exception ("VTControler: failed to get KDEntry: " + ret ); + return ke; + } + public string GetKbString (byte action_code){ + KbsEntry ke = new KbsEntry() { kb_func = action_code}; + int ret = ioctl (fd, KDGKBSENT, ref ke); + if (ret < 0) + throw new Exception ("VTControler: failed to get KDSEntry: " + ret ); + return ke.KbString; + } #region IDisposable implementation ~VTControler(){ @@ -172,6 +271,8 @@ namespace Linux.VT { const uint KDSKBMODE = 0x4B45; /* sets current keyboard mode */ const uint KDGKBENT = 0x4B46; /* gets one entry in translation table */ const uint KDSKBENT = 0x4B47; /* sets one entry in translation table */ + const uint KDGKBSENT = 0x4B48; /* gets one function key string entry */ + const uint KDSKBSENT = 0x4B49; /* sets one function key string entry */ const uint VT_OPENQRY = 0x5600; /* find available vt */ const uint VT_GETMODE = 0x5601; /* get mode of active vt */ @@ -187,12 +288,16 @@ namespace Linux.VT { const uint VT_DISALLOCATE= 0x5608; /* free memory associated to vt */ const uint VT_RESIZE = 0x5609; /* set kernel's idea of screensize */ + const uint TIOCNOTTY = 0x5422; /* dettach process from tty */ + const uint TIOCSCTTY = 0x540E; /* attach process to tty */ #endregion #region ioctl overrides [DllImport("libc")] static extern int ioctl(int d, uint request, ref KbEntry entry); [DllImport("libc")] + static extern int ioctl(int d, uint request, ref KbsEntry entry); + [DllImport("libc")] static extern int ioctl(int d, uint request, ref KbdMode value); [DllImport("libc")] static extern int ioctl(int d, uint request, ref long value); diff --git a/testDrm/test.style b/testDrm/test.style index fc327ab1..0db7f47d 100644 --- a/testDrm/test.style +++ b/testDrm/test.style @@ -1,34 +1,17 @@ FpsLabel { Width = 50%; - Font = droid, 10; + Font = droid, 8; Margin = 0; TextAlignment = Center; Background = Onyx; } FpsDisp { - Font = droid bold, 10; + Font = droid , 8; Width = 50%; Margin = 0; TextAlignment = Center; Background = Teal; } -CheckBox2 { - Template= #Tests.Interfaces.CheckBox2.imlt; - Background = Onyx; - Checked={Background=Mantis;Font=droid bold, 10}; - Unchecked = {Background=Onyx;Font=droid,10}; -} -RadioButton2 { - Template=#Tests.Interfaces.CheckBox2.imlt; - Background = Onyx; - Checked = {Background=Mantis;Font=droid bold, 10}; - Unchecked = {Background=Onyx;Font=droid,10}; -} -labPerf { - Font = droid, 8; - Width = 50%; -} -labPerfVal{ - Font = droid, 8; - Width = 50%; +Window { + Template = #Crow.ToolWindow.template; } diff --git a/testDrm/testDrm.csproj b/testDrm/testDrm.csproj index 290ebc2b..0d06b0c7 100644 --- a/testDrm/testDrm.csproj +++ b/testDrm/testDrm.csproj @@ -15,10 +15,11 @@ $(SolutionDir)build/obj/$(Configuration) + - testDrm.TestApp + testDrm.Tests true @@ -30,7 +31,13 @@ true $(SolutionDir)build\obj\$(Configuration) $(SolutionDir)build\Debug - true + + + + + + + false full @@ -45,7 +52,6 @@ - @@ -82,6 +88,12 @@ + + + + + + @@ -89,6 +101,7 @@ + @@ -96,6 +109,7 @@ + @@ -119,6 +133,5 @@ - \ No newline at end of file diff --git a/testDrm/testLibInput.cs b/testDrm/testLibInput.cs new file mode 100644 index 00000000..4cc2df64 --- /dev/null +++ b/testDrm/testLibInput.cs @@ -0,0 +1,312 @@ +// +// testLibInput.cs +// +// Author: +// Jean-Philippe Bruyère +// +// 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 Linux; +using System.Runtime.InteropServices; +using System.Threading; +using Crow; +using OpenTK.Platform.Linux; +using System.IO; + +namespace testDrm +{ + public class testLibInput + { + static void Main(){ + + testLibInput tli = new testLibInput(); + tli.run (); + } + public testLibInput () + { + Console.WriteLine ("starting"); + initInput (); + } + void run(){ + while (true) + Console.ReadKey (true); + } + #region INPUT + Thread input_thread; + long exit; + + static readonly object Sync = new object(); + static readonly Crow.Key[] KeyMap = Linux.oldEvDev.EvdevClass.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.Name = "input_thread"; + 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) + { + + //drmTimeOut.Restart (); + + 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(LibInput.GetKeyboardEvent(pevent)); + break; + // + + + // case InputEventType.PointerMotionAbsolute: + // handlePointerMotionAbsolute(LibInput.GetPointerEvent(pevent)); + // break; + } + } + + LibInput.DestroyEvent(pevent); + } + } + + + + KeyModifiers curModifiers = KeyModifiers.None; + + void handleKeyboard(KeyboardEvent e) + { + int key = (int)Linux.oldEvDev.EvdevClass.KeyMap [e.Key]; + Key k = (Key)key; + if (e.KeyState == KeyState.Pressed) { + Console.WriteLine ("KeyDown: raw:{0} evdev:{1} key:{2}",e.Key, key,k); + switch (k) { + case Key.ShiftLeft: + case Key.ShiftRight: + curModifiers |= KeyModifiers.Shift; + break; + case Key.ControlLeft: + case Key.ControlRight: + curModifiers |= KeyModifiers.Control; + break; + case Key.AltLeft: + curModifiers |= KeyModifiers.Alt; + break; + case Key.AltRight: + curModifiers |= KeyModifiers.AltGr; + break; + } + }else { + Console.WriteLine ("KeyUp: raw:{0} evdev:{1} key:{2}",e.Key, key,k); + switch (k) { + case Key.ShiftLeft: + case Key.ShiftRight: + curModifiers &= ~KeyModifiers.Shift; + break; + case Key.ControlLeft: + case Key.ControlRight: + curModifiers &= ~KeyModifiers.Control; + break; + case Key.AltLeft: + curModifiers &= ~KeyModifiers.Alt; + break; + case Key.AltRight: + curModifiers &= ~KeyModifiers.AltGr; + break; + } + // if (!keymap.ContainsKey (curModifiers)) { + // Console.WriteLine ("keymap not found for: " + curModifiers + " " + (int)curModifiers); + // return; + // } + // string tmp = keymap [curModifiers] [e.Key]; + // if (string.IsNullOrEmpty (tmp)) + // return; + // if (char.IsControl (tmp[0])) + // return; + // CrowInterface.ProcessKeyPress (tmp [0]); + } + } + + #endregion + + } +} + diff --git a/testDrm/tests.cs b/testDrm/tests.cs index 576b4481..5d7bb78b 100644 --- a/testDrm/tests.cs +++ b/testDrm/tests.cs @@ -39,67 +39,140 @@ using System.Linq; using Crow; using System.Diagnostics; - +using Linux.Evdev; +using Linux.VT; namespace testDrm { - public class TestApp : Application, IValueChange + static class Tests { - #region IValueChange implementation - public event EventHandler ValueChanged; - public virtual void NotifyValueChanged(string MemberName, object _value) + static void Main () { - //Debug.WriteLine ("Value changed: {0}->{1} = {2}", this, MemberName, _value); - ValueChanged.Raise(this, new ValueChangeEventArgs(MemberName, _value)); - } - #endregion - - public bool Running = true; - - public TestApp () : base () { - +// using (VTControler vt = new VTControler()){ +// Console.WriteLine (vt.CurrentVT); +// +// for (byte i = 0; i < 0x7F; i++) { +// Console.Write ("{0:X2}: ", i); +// printke (vt.GetKDBEntry (KbTable.Normal, i)); +// printke (vt.GetKDBEntry (KbTable.Shift, i)); +// printke (vt.GetKDBEntry (KbTable.Alt, i)); +// Console.Write ("\n"); +// } +// } +// //return; + testEVDEV (); } - int frTime = 0; - int frMin = int.MaxValue; - int frMax = 0; - - public override void Run () - { - Stopwatch frame = new Stopwatch (); - Load ("#testDrm.ui.menu.crow").DataSource = this; - Load ("#testDrm.ui.0.crow").DataSource = this; - - while(Running){ - try { - frame.Restart(); - base.Run (); - frame.Stop(); - frTime = (int)frame.ElapsedTicks; - NotifyValueChanged("frameTime", frTime); - if (frTime > frMax){ - frMax = frTime; - NotifyValueChanged("frameMax", frMax); - } - if (frTime < frMin){ - frMin = frTime; - NotifyValueChanged("frameMin", frMin); +// static void printke(KbEntry ke){ +// string output = ""; +// if (ke.KeyType.HasFlag (KtType.Latin)) +// output = new string(new char[] {ke.ActionCode}); +// if (ke.KeyType.HasFlag (KtType.Fn)) +// break; +// if (ke.KeyType.HasFlag (KtType.Spec)) +// break; +// if (ke.KeyType.HasFlag (KtType.Pad)) +// break; +// if (ke.KeyType.HasFlag (KtType.Dead)) +// break; +// if (ke.KeyType.HasFlag (KtType.Cons)) +// break; +// if (ke.KeyType.HasFlag (KtType.Cur)) +// break; +// if (ke.KeyType.HasFlag (KtType.Shift)) +// break; +// if (ke.KeyType.HasFlag (KtType.Meta)) +// break; +// if (ke.KeyType.HasFlag (KtType.Ascii)) +// output = new string(new char[] {ke.ActionCode}); +// if (ke.KeyType.HasFlag (KtType.Lock)) +// break; +// if (ke.KeyType.HasFlag (KtType.Letter)) +// output = new string(new char[] {ke.ActionCode}); +// if (ke.KeyType.HasFlag (KtType.Slock)) +// break; +// if (ke.KeyType.HasFlag (KtType.Dead2)) +// break; +// if (ke.KeyType.HasFlag (KtType.Brl)) +// break; +// +//// if (!ke.KeyType.HasFlag(KtType.)|ke.KeyType.HasFlag(KtType.Letter)) +//// Console.Write ("{0:X4} '{1}' ", ke.kb_value, (char)ke.ActionCode); +// } + static void evThread (){ + using (VTControler vt = new VTControler ()) { + using (Device dev = new Device (0)) { + Console.WriteLine (dev.Name); + Console.WriteLine ("Physical location: {0}", dev.PhysLocation); + Console.WriteLine ("\tbus:{0}\n\tvendor:{1}\n\tproduct:{2}\n\tversion:{3}", + dev.BusTypeId, dev.VendorId, dev.ProductId, dev.VersionId); + + while (true) { + InputEvent evt; + if (!dev.GetNextEvent (out evt)) + continue; + } - - } catch (Exception ex) { - Console.WriteLine (ex.ToString()); } } } - void onQuitClick(object send, Crow.MouseButtonEventArgs e) - { - Running = false; + static void dumpDevices (){ + string[] devices = Directory.GetFiles("/dev/input", "event*"); + foreach (string path in devices) { + using (Device dev = new Device (path)) { + Console.Write (dev.Name + " => "); + Console.WriteLine ("\tbus:{0} vendor:{1} product:{2} version:{3} path:{4}", + dev.BusTypeId, dev.VendorId, dev.ProductId, dev.VersionId, path); + if (dev.HasEventCodeOfType (EvType.Key, (uint)Linux.Evdev.KeyType.A)) + Console.WriteLine ("\t\thas a key"); + } + } } - } - static class Tests - { + + static void testEVDEV (){ + + using (Device dev = new Device (0)) { + Console.WriteLine (dev.Name); + Console.WriteLine ("Physical location: {0}", dev.PhysLocation); + Console.WriteLine ("\tbus:{0}\n\tvendor:{1}\n\tproduct:{2}\n\tversion:{3}", + dev.BusTypeId, dev.VendorId, dev.ProductId, dev.VersionId); + dev.test2 (); +// +// if (!dev.TryGrab ()) { +// Console.WriteLine ("failed to grab device"); +// return; +// } +// using (VTControler vt = new VTControler ()) { +// while (true) { +// InputEvent evt; +// if (!dev.GetNextEvent (out evt)) +// continue; +// if (evt.Code == (ushort)Linux.Evdev.KeyType.Esc && evt.Value == 1) +// break; +// if (evt.Type != EvType.Key) +// continue; +// KbEntry ke = vt.GetKDBEntry (KbTable.Normal, (byte)evt.Code); +// Console.WriteLine (evt.ToString ()); +// Console.WriteLine ("raw={0} {1} {2}", evt.Code, ke.KeyType, (char)ke.ActionCode); +// } +// } +// dev.TryRelease (); + } + +// +// Thread t = new Thread(evThread); +// t.IsBackground = true; +// t.Start (); +// +// while (true) +// Console.ReadKey (true); + } + static void signal_handler (Signal s){ Console.WriteLine ("signal catched: " + s.ToString()); } + static void switch_request_handle (Signal s){ + Console.WriteLine ("switch signal catched: " + s.ToString()); + } static void genEglConstCase (){ Dictionary dic = new Dictionary (); @@ -150,16 +223,6 @@ namespace testDrm } } } - static void Main () - { - try { - using (TestApp crowApp = new TestApp ()) { - crowApp.Run (); - } - } catch (Exception ex) { - Console.WriteLine (ex.ToString ()); - } - } static void testApp () { int previousVT = -1, appVT = -1; @@ -196,57 +259,13 @@ namespace testDrm } } - static void testKMS(){ - int previousVT = -1, appVT = -1; - - if (Kernel.signal (Signal.SIGUSR1, switch_request_handle) < 0) - throw new Exception ("signal handler registation failed"); - if (Kernel.signal (Signal.SIGINT, sigint_handler) < 0) - throw new Exception ("SIGINT handler registation failed"); - - using (VT.VTControler master = new VT.VTControler ()) { - previousVT = master.CurrentVT; - appVT = master.FirstAvailableVT; - master.SwitchTo (appVT); - try { - master.KDMode = VT.KDMode.GRAPHICS; - } catch (Exception ex) { - Console.WriteLine (ex.ToString ()); - } - } - try { - using (DRI.GPUControler gpu = new DRI.GPUControler ()) { - -// int i = 0; -// while(running && i < 1000){ -// try { -// gpu.Update (); -// i++; -// } catch (Exception ex) { -// Console.WriteLine (ex.ToString()); -// } -// -// } - - - } - } catch (Exception ex) { - Console.WriteLine (ex.ToString ()); - } - using (VT.VTControler master = new VT.VTControler ()) { - // try { - // master.KDMode = VT.KDMode.TEXT; - // } catch (Exception ex) { - // Console.WriteLine (ex.ToString ()); - // } - master.SwitchTo (previousVT); - } - } static void signalTest (){ if (Kernel.signal (Signal.SIGINT, signal_handler) < 0) throw new Exception ("signal handler registation failed"); + if (Kernel.signal (Signal.SIGUSR1, switch_request_handle) < 0) + throw new Exception ("signal handler registation failed"); Console.WriteLine ("Handler registered for {0}", Signal.SIGINT); while (true) Thread.Sleep (1); @@ -335,13 +354,13 @@ namespace testDrm //vtc.CurrentMode = VT.Mode.GRAPHICS; } static bool running = true; - static void switch_request_handle (Signal s){ - Console.WriteLine ("switch request catched: " + s.ToString()); - using (VT.VTControler master = new VT.VTControler ()) { - Libc.write (master.fd, Encoding.ASCII.GetBytes ("this is a test string")); - master.AcknoledgeSwitchRequest (); - } - } +// static void switch_request_handle (Signal s){ +// Console.WriteLine ("switch request catched: " + s.ToString()); +// using (VT.VTControler master = new VT.VTControler ()) { +// Libc.write (master.fd, Encoding.ASCII.GetBytes ("this is a test string")); +// master.AcknoledgeSwitchRequest (); +// } +// } static void sigint_handler (Signal s){ Console.WriteLine ("SIGINT catched"); running = false; diff --git a/testDrm/ui/menu.crow b/testDrm/ui/menu.crow index e65adfb9..abe22fbc 100755 --- a/testDrm/ui/menu.crow +++ b/testDrm/ui/menu.crow @@ -1,8 +1,8 @@  - - + + diff --git a/testDrm/ui/perfMeasures.crow b/testDrm/ui/perfMeasures.crow index e49e7f15..57c97202 100755 --- a/testDrm/ui/perfMeasures.crow +++ b/testDrm/ui/perfMeasures.crow @@ -1,5 +1,4 @@ - - + + diff --git a/testDrm/ui/perfMsr.crow b/testDrm/ui/perfMsr.crow index d823ea42..072d20ee 100755 --- a/testDrm/ui/perfMsr.crow +++ b/testDrm/ui/perfMsr.crow @@ -1,9 +1,8 @@ - -