From: Jean-Philippe Bruyère Date: Sat, 26 Aug 2017 02:57:51 +0000 (+0200) Subject: test texture surface backend with sdl and xcb X-Git-Url: https://git.osiis.dedyn.io/?a=commitdiff_plain;h=refs%2Fheads%2FTestXCBandSDL;p=jp%2Fcrow.git test texture surface backend with sdl and xcb --- diff --git a/Crow.csproj b/Crow.csproj index 29bcd8e0..949dbd84 100644 --- a/Crow.csproj +++ b/Crow.csproj @@ -25,6 +25,7 @@ crow.key 8.0.30703 2.0 + 0.5 true diff --git a/Crow.dll.config b/Crow.dll.config index ef7562ac..43b2ed22 100644 --- a/Crow.dll.config +++ b/Crow.dll.config @@ -1,13 +1,7 @@ - - - - - - - + diff --git a/Tests/BasicTests.cs b/Tests/BasicTests.cs index 9340fe88..a7b03cc6 100644 --- a/Tests/BasicTests.cs +++ b/Tests/BasicTests.cs @@ -30,16 +30,27 @@ using System.Collections.Generic; using System.Linq; using System.IO; using System.Reflection; +using System.Runtime.InteropServices; using System.Text; using System.Diagnostics; +using Crow.SDL2; + +using Native; + +using XCBConnection = System.IntPtr; +using XCBSetup = System.IntPtr; +using XCBScreen = System.IntPtr; +using XCBWindow = System.UInt32; +using XCBColorMap = System.UInt32; +using XCBVisualId = System.UInt32; namespace Tests { - class BasicTests : CrowWindow + class BasicTests : CrowWindow3 { public BasicTests () - : base(800, 600,"test: press to toogle test files") + //: base(800, 600,"test: press to toogle test files") { } @@ -140,8 +151,8 @@ namespace Tests this.KeyDown += KeyboardKeyDown1; //testFiles = new string [] { @"Interfaces/Unsorted/testFileDialog.crow" }; - //testFiles = new string [] { @"Interfaces/Divers/colorPicker.crow" }; - testFiles = new string [] { @"Interfaces/Divers/welcome.crow" }; + testFiles = new string [] { @"Interfaces/Divers/colorPicker.crow" }; + //testFiles = new string [] { @"Interfaces/Divers/welcome.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 (); @@ -180,7 +191,7 @@ namespace Tests return; }else if (e.Key == OpenTK.Input.Key.F7) { GraphicObject w = Load ("Interfaces/Divers/perfMeasures.crow"); - w.DataSource = this.ifaceControl[0]; + w.DataSource = this; return; } else if (e.Key == OpenTK.Input.Key.F2) idx--; @@ -190,7 +201,7 @@ namespace Tests return; try { - ClearInterface (); + CrowInterface.ClearInterface (); if (idx == testFiles.Length) idx = 0; diff --git a/Tests/CrowWindow.cs b/Tests/CrowWindow.cs index 2934af23..82ba6a06 100644 --- a/Tests/CrowWindow.cs +++ b/Tests/CrowWindow.cs @@ -74,6 +74,9 @@ namespace Crow } #if MEASURE_TIME + public List PerfMeasures { + get { return ifaceControl[0]?.PerfMeasures; } + } public PerformanceMeasure glDrawMeasure = new PerformanceMeasure("OpenGL Draw", 10); public int fpsMin = int.MaxValue; diff --git a/Tests/CrowWindow2.cs b/Tests/CrowWindow2.cs new file mode 100644 index 00000000..b28224b7 --- /dev/null +++ b/Tests/CrowWindow2.cs @@ -0,0 +1,435 @@ +// +// CrowWindow.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.Threading; +using OpenTK; +using OpenTK.Graphics.OpenGL; +using System.Collections.Generic; +using OpenTK.Platform; +using Crow.SDL2; + +namespace Crow +{ + public class CrowWindow2 : 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 + + #region FPS + int frameCpt = 0; + int _fps = 0; + public int fps { + get { return _fps; } + set { + if (_fps == value) + return; + + _fps = value; + #if MEASURE_TIME + 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)); + } + #endif + if (frameCpt % 3 == 0) { + ValueChanged.Raise (this, new ValueChangeEventArgs ("fps", _fps)); + #if MEASURE_TIME + foreach (PerformanceMeasure m in PerfMeasures) + m.NotifyChanges (); + #endif + } + } + } + + #if MEASURE_TIME + public List PerfMeasures; + public PerformanceMeasure glDrawMeasure = new PerformanceMeasure("OpenGL Draw", 10); + + public int fpsMin = int.MaxValue; + public int fpsMax = 0; + + void resetFps () + { + fpsMin = int.MaxValue; + fpsMax = 0; + _fps = 0; + } + #endif + #endregion + + #region ctor + public CrowWindow2(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 CrowWindow2 (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) + { + } + #endregion + + IntPtr hCairoGLCtx; + Cairo.GLXDevice dev; + Cairo.GLSurface surf; + + public Interface CrowInterface; + + protected Matrix4 projection; + protected Shader shader; + public int texID; + public vaoMesh quad; + public bool mouseIsInInterface = false; + + void initCrow() { + CrowInterface = new Interface (); + CrowInterface.MouseCursorChanged += CrowInterface_MouseCursorChanged; + + #if MEASURE_TIME + PerfMeasures = new List ( + new PerformanceMeasure[] { + CrowInterface.updateMeasure, + CrowInterface.layoutingMeasure, + CrowInterface.clippingMeasure, + CrowInterface.drawingMeasure, + glDrawMeasure + } + ); + #endif + +// Thread t = new Thread (interfaceThread); +// t.IsBackground = true; +// t.Start (); + } + + void initCairo(){ + SysWMInfo sdlInfo; + IntPtr hWnd = this.WindowInfo.Handle; + SDL.GL.SetAttribute (ContextAttribute.SHARE_WITH_CURRENT_CONTEXT, 1); + SDL.GL.SetAttribute (ContextAttribute.CONTEXT_MAJOR_VERSION, 3); + SDL.GL.SetAttribute (ContextAttribute.CONTEXT_MAJOR_VERSION, 0); + int test; + SDL.GL.GetAttribute (ContextAttribute.SHARE_WITH_CURRENT_CONTEXT, out test); + SDL.GetWindowWMInfo (hWnd, out sdlInfo); + + hCairoGLCtx = SDL.GL.CreateContext (hWnd); + + + dev = new Cairo.GLXDevice (sdlInfo.Info.X11.Display, hCairoGLCtx); + } + +// void interfaceThread() +// { +// while (CrowInterface.ClientRectangle.Size.Width == 0) +// Thread.Sleep (5); +// +// while (true) { +// CrowInterface.Update (); +// Thread.Sleep (1); +// } +// } + + #region graphic context + public virtual void initGL(){ + #if DEBUG + 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"); + #endif + + shader = new Shader (); + shader.Enable (); + + GL.ClearColor(0.0f, 0.0f, 0.0f, 0.0f); + projection = OpenTK.Matrix4.CreateOrthographicOffCenter (-0.5f, 0.5f, -0.5f, 0.5f, 1, -1); + quad = new Crow.vaoMesh (0, 0, 0, 1, 1, 1, -1); + + createContext (); + } + /// Create the texture for the interface redering + public virtual void createContext() + { + 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, + CrowInterface.ClientRectangle.Width, CrowInterface.ClientRectangle.Height, 0, + OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, IntPtr.Zero); + GL.TexParameter (TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Nearest); + GL.TexParameter (TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Nearest); + + surf = new Cairo.GLSurface (dev, Cairo.Content.ColorAlpha, (uint)texID, + CrowInterface.ClientRectangle.Width, CrowInterface.ClientRectangle.Height); + + SDL.GL.MakeCurrent(this.WindowInfo.Handle, hCairoGLCtx); + using (Cairo.Context gr = new Cairo.Context (surf)) { + gr.Rectangle (150, 100, 200, 100); + gr.SetSourceRGBA (1.0, 0.0, 0.0,0.5); + gr.Fill (); + gr.Rectangle (200, 150, 200, 100); + gr.SetSourceRGBA (0.0, 1.0, 0.0,0.5); + gr.Fill (); + } + surf.Flush (); + surf.SwapBuffers (); + surf.WriteToPng ("/mnt/data/test.png"); + this.MakeCurrent (); + CrowInterface.bmp = surf; + //GL.BindTexture (TextureTarget.Texture2D, 0); + } + + void openGLDraw(){ + //save GL states + bool blend, depthTest, cullFace; + GL.GetBoolean (GetPName.Blend, out blend); + GL.GetBoolean (GetPName.DepthTest, out depthTest); + GL.GetBoolean (GetPName.CullFace, out cullFace); + GL.Enable (EnableCap.Blend); + GL.Disable (EnableCap.DepthTest); + GL.Disable (EnableCap.CullFace); + GL.Viewport (0, 0, CrowInterface.ClientRectangle.Width, CrowInterface.ClientRectangle.Height); + + #if MEASURE_TIME + glDrawMeasure.StartCycle(); + #endif + + shader.Enable (); + shader.SetMVP (projection); + + GL.ActiveTexture (TextureUnit.Texture0); + GL.BindTexture (TextureTarget.Texture2D, texID); +// if (Monitor.TryEnter(CrowInterface.RenderMutex)) { +// if (CrowInterface.IsDirty) { +// byte[] data = null; +// if (CrowInterface.dirtyBmp != null) +// data = (CrowInterface.dirtyBmp as Cairo.ImageSurface).Data; +// GL.TexSubImage2D (TextureTarget.Texture2D, 0, +// CrowInterface.DirtyRect.Left, CrowInterface.DirtyRect.Top, +// CrowInterface.DirtyRect.Width, CrowInterface.DirtyRect.Height, +// OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, data); +// CrowInterface.IsDirty = false; +// } +// Monitor.Exit (CrowInterface.RenderMutex); +// } +// + quad.Render (BeginMode.TriangleStrip); + GL.BindTexture(TextureTarget.Texture2D, 0); + + #if MEASURE_TIME + glDrawMeasure.StopCycle(); + #endif + //restore GL states + if (!blend) + GL.Disable (EnableCap.Blend); + if (depthTest) + GL.Enable (EnableCap.DepthTest); + if (cullFace) + GL.Enable (EnableCap.CullFace); + } + #endregion + + public void Quit (object sender, EventArgs e) + { + dev.Dispose (); + SDL.GL.MakeCurrent (this.WindowInfo.Handle, IntPtr.Zero); + SDL.GL.DeleteContext (hCairoGLCtx); + this.MakeCurrent (); + + 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 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 + + + public GraphicObject AddWidget (GraphicObject g){ + CrowInterface.AddWidget (g); + return g; + } + public void DeleteWidget (GraphicObject g){ + CrowInterface.DeleteWidget (g); + } + public GraphicObject Load (string path){ + return CrowInterface.LoadInterface (path); + } + public GraphicObject FindByName (string nameToFind){ + return CrowInterface.FindByName (nameToFind); + } + + /// 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(GL_Mouse_WheelChanged); + Mouse.ButtonDown += new EventHandler(GL_Mouse_ButtonDown); + Mouse.ButtonUp += new EventHandler(GL_Mouse_ButtonUp); + Mouse.Move += new EventHandler(GL_Mouse_Move); + + initCairo (); + initCrow (); + initGL (); + } + protected override void OnUpdateFrame(FrameEventArgs e) + { + base.OnUpdateFrame(e); + fps = (int)RenderFrequency; + + #if MEASURE_TIME + if (frameCpt > 500) { + resetFps (); + frameCpt = 0; +// #if DEBUG +// GC.Collect(); +// GC.WaitForPendingFinalizers(); +// NotifyValueChanged("memory", GC.GetTotalMemory (false).ToString()); +// #endif + } + #endif + + frameCpt++; + + SDL.GL.MakeCurrent (this.WindowInfo.Handle, hCairoGLCtx); + CrowInterface.Update (); + surf.Flush (); + surf.SwapBuffers (); + surf.WriteToPng ("/mnt/data/test1.png"); + this.MakeCurrent (); + } + protected override void OnRenderFrame(FrameEventArgs e) + { + GLClear (); + + base.OnRenderFrame(e); + + OnRender (e); + openGLDraw (); + + SwapBuffers (); + } + protected override void OnResize(EventArgs e) + { + base.OnResize (e); + + lock (CrowInterface.UpdateMutex) { + CrowInterface.ClientRectangle = this.ClientRectangle; + createContext (); + CrowInterface.ProcessResize (); + } + } + #endregion + + #region Mouse and Keyboard 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); + } + } + protected virtual void GL_Mouse_Move(object sender, OpenTK.Input.MouseMoveEventArgs otk_e) + { + if (!CrowInterface.ProcessMouseMove (otk_e.X, otk_e.Y)) + MouseMove.Raise (sender, otk_e); + } + protected virtual void GL_Mouse_ButtonUp(object sender, OpenTK.Input.MouseButtonEventArgs otk_e) + { + if (!CrowInterface.ProcessMouseButtonUp ((int)otk_e.Button)) + MouseButtonUp.Raise (sender, otk_e); + } + protected virtual void GL_Mouse_ButtonDown(object sender, OpenTK.Input.MouseButtonEventArgs otk_e) + { + if (!CrowInterface.ProcessMouseButtonDown ((int)otk_e.Button)) + MouseButtonDown.Raise (sender, otk_e); + } + protected virtual void GL_Mouse_WheelChanged(object sender, OpenTK.Input.MouseWheelEventArgs otk_e) + { + if (!CrowInterface.ProcessMouseWheelChanged (otk_e.DeltaPrecise)) + MouseWheelChanged.Raise (sender, otk_e); + } + protected virtual void Keyboard_KeyDown(object sender, OpenTK.Input.KeyboardKeyEventArgs otk_e) + { + if (!CrowInterface.ProcessKeyDown((int)otk_e.Key)) + KeyboardKeyDown.Raise (this, otk_e); + } + protected virtual void Keyboard_KeyUp(object sender, OpenTK.Input.KeyboardKeyEventArgs otk_e) + { + if (!CrowInterface.ProcessKeyUp((int)otk_e.Key)) + KeyboardKeyUp.Raise (this, otk_e); + } + protected virtual void OpenTKGameWindow_KeyPress (object sender, OpenTK.KeyPressEventArgs e) + { + CrowInterface.ProcessKeyPress (e.KeyChar); + //TODO:create keyboardkeypress evt + } + #endregion + } +} diff --git a/Tests/CrowWindow3.cs b/Tests/CrowWindow3.cs new file mode 100644 index 00000000..fce2840e --- /dev/null +++ b/Tests/CrowWindow3.cs @@ -0,0 +1,428 @@ +// +// CrowWindow.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.Threading; +using OpenTK; +using OpenTK.Graphics.OpenGL; +using System.Collections.Generic; +using OpenTK.Platform; +using Crow.SDL2; + +namespace Crow +{ + public class CrowWindow3 : 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 + + #region FPS + int frameCpt = 0; + int _fps = 0; + public int fps { + get { return _fps; } + set { + if (_fps == value) + return; + + _fps = value; + #if MEASURE_TIME + 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)); + } + #endif + if (frameCpt % 3 == 0) { + ValueChanged.Raise (this, new ValueChangeEventArgs ("fps", _fps)); + #if MEASURE_TIME + foreach (PerformanceMeasure m in PerfMeasures) + m.NotifyChanges (); + #endif + } + } + } + + #if MEASURE_TIME + public List PerfMeasures; + public PerformanceMeasure glDrawMeasure = new PerformanceMeasure("OpenGL Draw", 10); + + public int fpsMin = int.MaxValue; + public int fpsMax = 0; + + void resetFps () + { + fpsMin = int.MaxValue; + fpsMax = 0; + _fps = 0; + } + #endif + #endregion + + #region ctor + public CrowWindow3(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=0) + : this(_width, _height, new OpenTK.Graphics.GraphicsMode(colors, depth, stencil, samples), + _title,GameWindowFlags.Default,DisplayDevice.Default, major, minor,OpenTK.Graphics.GraphicsContextFlags.Default) + { + } + public CrowWindow3 (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) + { + } + #endregion + + IntPtr hCairoGLCtx; + Cairo.GLXDevice dev; + Cairo.GLSurface surf; + + public Interface CrowInterface; + + protected Matrix4 projection; + public int texID; + public bool mouseIsInInterface = false; + + void initCrow() { + CrowInterface = new Interface (); + CrowInterface.MouseCursorChanged += CrowInterface_MouseCursorChanged; + + #if MEASURE_TIME + PerfMeasures = new List ( + new PerformanceMeasure[] { + CrowInterface.updateMeasure, + CrowInterface.layoutingMeasure, + CrowInterface.clippingMeasure, + CrowInterface.drawingMeasure, + glDrawMeasure + } + ); + #endif + +// Thread t = new Thread (interfaceThread); +// t.IsBackground = true; +// t.Start (); + } + + void initCairo(){ + SysWMInfo sdlInfo; + IntPtr hWnd = this.WindowInfo.Handle; + SDL.GL.SetAttribute (ContextAttribute.SHARE_WITH_CURRENT_CONTEXT, 1); + int test; + SDL.GL.GetAttribute (ContextAttribute.SHARE_WITH_CURRENT_CONTEXT, out test); + SDL.GetWindowWMInfo (hWnd, out sdlInfo); + + hCairoGLCtx = SDL.GL.CreateContext (hWnd); + + + dev = new Cairo.GLXDevice (sdlInfo.Info.X11.Display, hCairoGLCtx); + } + +// void interfaceThread() +// { +// while (CrowInterface.ClientRectangle.Size.Width == 0) +// Thread.Sleep (5); +// +// while (true) { +// CrowInterface.Update (); +// Thread.Sleep (1); +// } +// } + + #region graphic context + public virtual void initGL(){ + #if DEBUG + 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"); + #endif + + GL.ClearColor(0.0f, 0.0f, 0.0f, 0.0f); + projection = OpenTK.Matrix4.CreateOrthographicOffCenter (-0.5f, 0.5f, -0.5f, 0.5f, 1, -1); + + createContext (); + } + /// Create the texture for the interface redering + public virtual void createContext() + { + 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, + CrowInterface.ClientRectangle.Width, CrowInterface.ClientRectangle.Height, 0, + OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, IntPtr.Zero); + GL.TexParameter (TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Nearest); + GL.TexParameter (TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Nearest); + + surf = new Cairo.GLSurface (dev, Cairo.Content.ColorAlpha, (uint)texID, + CrowInterface.ClientRectangle.Width, CrowInterface.ClientRectangle.Height); + + CrowInterface.bmp = surf; + GL.BindTexture (TextureTarget.Texture2D, 0); + } + + void openGLDraw(){ + //save GL states + bool blend, depthTest, cullFace; + GL.GetBoolean (GetPName.Blend, out blend); + GL.GetBoolean (GetPName.DepthTest, out depthTest); + GL.GetBoolean (GetPName.CullFace, out cullFace); + GL.Enable (EnableCap.Texture2D); + GL.Enable (EnableCap.Blend); + GL.BlendFunc (BlendingFactorSrc.One, BlendingFactorDest.OneMinusSrcAlpha); + GL.Disable (EnableCap.DepthTest); + GL.Disable (EnableCap.CullFace); + GL.Viewport (0, 0, CrowInterface.ClientRectangle.Width, CrowInterface.ClientRectangle.Height); + + #if MEASURE_TIME + glDrawMeasure.StartCycle(); + #endif + + + GL.ActiveTexture (TextureUnit.Texture0); + GL.BindTexture (TextureTarget.Texture2D, texID); +// if (Monitor.TryEnter(CrowInterface.RenderMutex)) { +// if (CrowInterface.IsDirty) { +// byte[] data = null; +// if (CrowInterface.dirtyBmp != null) +// data = (CrowInterface.dirtyBmp as Cairo.ImageSurface).Data; +// GL.TexSubImage2D (TextureTarget.Texture2D, 0, +// CrowInterface.DirtyRect.Left, CrowInterface.DirtyRect.Top, +// CrowInterface.DirtyRect.Width, CrowInterface.DirtyRect.Height, +// OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, data); +// CrowInterface.IsDirty = false; +// } +// Monitor.Exit (CrowInterface.RenderMutex); +// } +// + + Matrix4 proj = Matrix4.CreateOrthographicOffCenter (-1f, 1f, -1f, 1f, 1.0f, -1.0f); + GL.MatrixMode(MatrixMode.Projection); + GL.LoadMatrix (ref proj); + GL.MatrixMode(MatrixMode.Modelview); + GL.LoadIdentity(); + + GL.BindTexture (TextureTarget.Texture2D, texID); + + GL.Begin(PrimitiveType.Quads); + GL.TexCoord2(0, 1); GL.Vertex2(-1, -1); + GL.TexCoord2(0, 0); GL.Vertex2(-1, 1); + GL.TexCoord2(1, 0); GL.Vertex2(1, 1); + GL.TexCoord2(1, 1); GL.Vertex2(1, -1); + GL.End(); + + GL.BindTexture(TextureTarget.Texture2D, 0); + + #if MEASURE_TIME + glDrawMeasure.StopCycle(); + #endif + //restore GL states + if (!blend) + GL.Disable (EnableCap.Blend); + if (depthTest) + GL.Enable (EnableCap.DepthTest); + if (cullFace) + GL.Enable (EnableCap.CullFace); + } + #endregion + + public void Quit (object sender, EventArgs e) + { + dev.Dispose (); + SDL.GL.MakeCurrent (this.WindowInfo.Handle, IntPtr.Zero); + SDL.GL.DeleteContext (hCairoGLCtx); + this.MakeCurrent (); + + 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 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 + + + public GraphicObject AddWidget (GraphicObject g){ + CrowInterface.AddWidget (g); + return g; + } + public void DeleteWidget (GraphicObject g){ + CrowInterface.DeleteWidget (g); + } + public GraphicObject Load (string path){ + return CrowInterface.LoadInterface (path); + } + public GraphicObject FindByName (string nameToFind){ + return CrowInterface.FindByName (nameToFind); + } + + /// 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(GL_Mouse_WheelChanged); + Mouse.ButtonDown += new EventHandler(GL_Mouse_ButtonDown); + Mouse.ButtonUp += new EventHandler(GL_Mouse_ButtonUp); + Mouse.Move += new EventHandler(GL_Mouse_Move); + + initCairo (); + initCrow (); + initGL (); + } + protected override void OnUpdateFrame(FrameEventArgs e) + { + base.OnUpdateFrame(e); + fps = (int)RenderFrequency; + + #if MEASURE_TIME + if (frameCpt > 500) { + resetFps (); + frameCpt = 0; +// #if DEBUG +// GC.Collect(); +// GC.WaitForPendingFinalizers(); +// NotifyValueChanged("memory", GC.GetTotalMemory (false).ToString()); +// #endif + } + #endif + + frameCpt++; + + SDL.GL.MakeCurrent (this.WindowInfo.Handle, hCairoGLCtx); + CrowInterface.Update (); + surf.Flush (); + surf.SwapBuffers (); + this.MakeCurrent (); + } + protected override void OnRenderFrame(FrameEventArgs e) + { + GLClear (); + + base.OnRenderFrame(e); + + OnRender (e); + openGLDraw (); + + SwapBuffers (); + } + protected override void OnResize(EventArgs e) + { + base.OnResize (e); + + lock (CrowInterface.UpdateMutex) { + CrowInterface.ClientRectangle = this.ClientRectangle; + createContext (); + CrowInterface.ProcessResize (); + } + } + #endregion + + #region Mouse and Keyboard 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); + } + } + protected virtual void GL_Mouse_Move(object sender, OpenTK.Input.MouseMoveEventArgs otk_e) + { + if (!CrowInterface.ProcessMouseMove (otk_e.X, otk_e.Y)) + MouseMove.Raise (sender, otk_e); + } + protected virtual void GL_Mouse_ButtonUp(object sender, OpenTK.Input.MouseButtonEventArgs otk_e) + { + if (!CrowInterface.ProcessMouseButtonUp ((int)otk_e.Button)) + MouseButtonUp.Raise (sender, otk_e); + } + protected virtual void GL_Mouse_ButtonDown(object sender, OpenTK.Input.MouseButtonEventArgs otk_e) + { + if (!CrowInterface.ProcessMouseButtonDown ((int)otk_e.Button)) + MouseButtonDown.Raise (sender, otk_e); + } + protected virtual void GL_Mouse_WheelChanged(object sender, OpenTK.Input.MouseWheelEventArgs otk_e) + { + if (!CrowInterface.ProcessMouseWheelChanged (otk_e.DeltaPrecise)) + MouseWheelChanged.Raise (sender, otk_e); + } + protected virtual void Keyboard_KeyDown(object sender, OpenTK.Input.KeyboardKeyEventArgs otk_e) + { + if (!CrowInterface.ProcessKeyDown((int)otk_e.Key)) + KeyboardKeyDown.Raise (this, otk_e); + } + protected virtual void Keyboard_KeyUp(object sender, OpenTK.Input.KeyboardKeyEventArgs otk_e) + { + if (!CrowInterface.ProcessKeyUp((int)otk_e.Key)) + KeyboardKeyUp.Raise (this, otk_e); + } + protected virtual void OpenTKGameWindow_KeyPress (object sender, OpenTK.KeyPressEventArgs e) + { + CrowInterface.ProcessKeyPress (e.KeyChar); + //TODO:create keyboardkeypress evt + } + #endregion + } +} diff --git a/Tests/InterfaceControler.cs b/Tests/InterfaceControler.cs index 4d988c10..af0fe3d9 100644 --- a/Tests/InterfaceControler.cs +++ b/Tests/InterfaceControler.cs @@ -52,7 +52,8 @@ namespace Crow public override void initGL(){ quad = new Crow.vaoMesh (0, 0, 0, 1, 1, 1, -1); //ifaceModelMat = Matrix4.CreateRotationX(MathHelper.PiOver2) * Matrix4.CreateTranslation(Vector3.UnitY); - CrowInterface.ProcessResize(iRect); + //Cairo.Device dev = new Cairo.Device(); + CrowInterface.ProcessResize(); createContext (); //CrowInterface.ProcessResize (iRect); } @@ -162,14 +163,14 @@ namespace Crow while (true) { CrowInterface.Update (); - //Thread.Sleep (1); + Thread.Sleep (1); } } #region Mouse And Keyboard handling public virtual void ProcessResize(Rectangle newSize){ iRect = newSize; - CrowInterface.ProcessResize(newSize); + CrowInterface.ProcessResize(); createContext (); GL.Viewport (0, 0, newSize.Width, newSize.Height);//TODO:find a better place for this } @@ -214,12 +215,16 @@ namespace Crow GL.ActiveTexture (TextureUnit.Texture0); GL.BindTexture(TextureTarget.Texture2D, texID); + byte[] data = null; + if (CrowInterface.bmp != null) + data = (CrowInterface.bmp as Cairo.ImageSurface).Data; + GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, iRect.Width, iRect.Height, 0, - OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, CrowInterface.bmp); + OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, data); - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear); - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear); + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Nearest); + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Nearest); GL.BindTexture(TextureTarget.Texture2D, 0); } @@ -234,10 +239,13 @@ namespace Crow GL.BindTexture (TextureTarget.Texture2D, texID); if (Monitor.TryEnter(CrowInterface.RenderMutex)) { if (CrowInterface.IsDirty) { + byte[] data = null; + if (CrowInterface.dirtyBmp != null) + data = (CrowInterface.dirtyBmp as Cairo.ImageSurface).Data; 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); + OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, data); CrowInterface.IsDirty = false; } Monitor.Exit (CrowInterface.RenderMutex); diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj index 2adcdb16..16d63764 100644 --- a/Tests/Tests.csproj +++ b/Tests/Tests.csproj @@ -8,7 +8,7 @@ Exe Tests Tests - Tests.Showcase + Tests.BasicTests v4.5 AnyCPU 0.5 @@ -26,10 +26,11 @@ false prompt 4 - false DEBUG;TRACE;MEASURE_TIME $(SolutionDir)build\obj\$(Configuration) - $(SolutionDir)build\$(Configuration) + $(SolutionDir)build\Debug + true + true none @@ -37,7 +38,8 @@ 0 false $(SolutionDir)build\obj\$(Configuration) - $(SolutionDir)build\$(Configuration) + $(SolutionDir)build\Release + true @@ -62,6 +64,13 @@ + + + + + + + diff --git a/Tests/sdl2.cs b/Tests/sdl2.cs new file mode 100644 index 00000000..9237be9b --- /dev/null +++ b/Tests/sdl2.cs @@ -0,0 +1,1752 @@ +// +// The Open Toolkit Library License +// +// Copyright (c) 2006 - 2013 Stefanos Apostolopoulos for 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. +// + +using System; +using System.Diagnostics; +using System.Security; +using System.Runtime.InteropServices; + +#pragma warning disable 0169 + +namespace Crow.SDL2 +{ + using Surface = IntPtr; + using Cursor = IntPtr; + + internal partial class SDL + { + #if ANDROID + const string lib = "libSDL2.so"; + #elif IPHONE + const string lib = "__Internal"; + #else + private const string lib = "SDL2.dll"; + #endif + + public readonly static object Sync = new object(); + private static Nullable version; + public static Version Version + { + get + { + try + { + if (!version.HasValue) + { + version = GetVersion(); + } + return version.Value; + } + catch + { + // nom nom + Debug.Print("[SDL2] Failed to retrieve version"); + return new Version(); + } + } + } + + private static string IntPtrToString(IntPtr ptr) + { + return Marshal.PtrToStringAnsi(ptr); + //int strlen = 0; + //while (Marshal.ReadByte(ptr) != 0) + // strlen++; + } + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_CreateColorCursor", ExactSpelling = true)] + public static extern Cursor CreateColorCursor(Surface surface, int hot_x, int hot_y); + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_FreeCursor", ExactSpelling = true)] + public static extern void FreeCursor(Cursor cursor); + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GetDefaultCursor", ExactSpelling = true)] + public static extern IntPtr GetDefaultCursor(); + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_SetCursor", ExactSpelling = true)] + public static extern void SetCursor(Cursor cursor); + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_AddEventWatch", ExactSpelling = true)] + public static extern void AddEventWatch(EventFilter filter, IntPtr userdata); + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_AddEventWatch", ExactSpelling = true)] + public static extern void AddEventWatch(IntPtr filter, IntPtr userdata); + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_CreateRGBSurfaceFrom", ExactSpelling = true)] + public static extern IntPtr CreateRGBSurfaceFrom(IntPtr pixels, + int width, int height, int depth, int pitch, + uint Rmask, uint Gmask, uint Bmask, uint Amask); + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_CreateWindow", ExactSpelling = true)] + public static extern IntPtr CreateWindow(string title, int x, int y, int w, int h, WindowFlags flags); + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_CreateWindowFrom", ExactSpelling = true)] + public static extern IntPtr CreateWindowFrom(IntPtr data); + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_DelEventWatch", ExactSpelling = true)] + public static extern void DelEventWatch(EventFilter filter, IntPtr userdata); + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_DelEventWatch", ExactSpelling = true)] + public static extern void DelEventWatch(IntPtr filter, IntPtr userdata); + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_DestroyWindow", ExactSpelling = true)] + public static extern void DestroyWindow(IntPtr window); + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_FreeSurface", ExactSpelling = true)] + public static extern void FreeSurface(IntPtr surface); + + [SuppressUnmanagedCodeSecurity] + [DllImport (lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_free", ExactSpelling = true)] + public static extern void Free(IntPtr memblock); + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GameControllerEventState", ExactSpelling = true)] + public static extern EventState GameControllerEventState(EventState state); + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GameControllerGetAxis", ExactSpelling = true)] + public static extern short GameControllerGetAxis(IntPtr gamecontroller, GameControllerAxis axis); + + /// + /// Gets the SDL joystick layer binding for the specified game controller axis + /// + /// Pointer to a game controller instance returned by GameControllerOpen. + /// A value from the GameControllerAxis enumeration + /// A GameControllerButtonBind instance describing the specified binding + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GameControllerGetBindForAxis", ExactSpelling = true)] + public static extern GameControllerButtonBind GameControllerGetBindForAxis(IntPtr gamecontroller, GameControllerAxis axis); + + /// + /// Gets the SDL joystick layer binding for the specified game controller button + /// + /// Pointer to a game controller instance returned by GameControllerOpen. + /// A value from the GameControllerButton enumeration + /// A GameControllerButtonBind instance describing the specified binding + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GameControllerGetBindForButton", ExactSpelling = true)] + public static extern GameControllerButtonBind GameControllerGetBindForButton( + IntPtr gamecontroller, GameControllerButton button); + + /// + /// Gets the current state of a button on a game controller. + /// + /// A game controller handle previously opened with GameControllerOpen. + /// A zero-based GameControllerButton value. + /// true if the specified button is pressed; false otherwise. + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GameControllerGetButton", ExactSpelling = true)] + public static extern bool GameControllerGetButton(IntPtr gamecontroller, GameControllerButton button); + + /// + /// Retrieve the joystick handle that corresponds to the specified game controller. + /// + /// A game controller handle previously opened with GameControllerOpen. + /// A handle to a joystick, or IntPtr.Zero in case of error. The pointer is owned by the callee. Use SDL.GetError to retrieve error information + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GameControllerGetJoystick", ExactSpelling = true)] + public static extern IntPtr GameControllerGetJoystick(IntPtr gamecontroller); + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GetCurrentDisplayMode", ExactSpelling = true)] + public static extern int GetCurrentDisplayMode(int displayIndex, out DisplayMode mode); + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GameControllerName", ExactSpelling = true)] + private static extern IntPtr GameControllerNameInternal(IntPtr gamecontroller); + + /// + /// Return the name for an openend game controller instance. + /// + /// The name of the game controller name. + /// Pointer to a game controller instance returned by GameControllerOpen. + public static string GameControllerName(IntPtr gamecontroller) + { + unsafe + { + return new string((sbyte*)GameControllerNameInternal(gamecontroller)); + } + } + + /// + /// Opens a game controller for use. + /// + /// + /// A zero-based index for the game controller. + /// This index is the value which will identify this controller in future controller events. + /// + /// A handle to the game controller instance, or IntPtr.Zero in case of error. + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GameControllerOpen", ExactSpelling = true)] + public static extern IntPtr GameControllerOpen(int joystick_index); + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GetDisplayBounds", ExactSpelling = true)] + public static extern int GetDisplayBounds(int displayIndex, out Rect rect); + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GetDisplayMode", ExactSpelling = true)] + public static extern int GetDisplayMode(int displayIndex, int modeIndex, out DisplayMode mode); + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GetError", ExactSpelling = true)] + private static extern IntPtr GetErrorInternal(); + public static string GetError() + { + return IntPtrToString(GetErrorInternal()); + } + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GetModState", ExactSpelling = true)] + public static extern Keymod GetModState(); + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GetMouseState", ExactSpelling = true)] + public static extern ButtonFlags GetMouseState(out int hx, out int hy); + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GetGlobalMouseState", ExactSpelling = true)] + public static extern ButtonFlags GetGlobalMouseState(out int hx, out int hy); + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GetNumDisplayModes", ExactSpelling = true)] + public static extern int GetNumDisplayModes(int displayIndex); + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GetNumVideoDisplays", ExactSpelling = true)] + public static extern int GetNumVideoDisplays(); + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GetScancodeFromKey", ExactSpelling = true)] + public static extern Scancode GetScancodeFromKey(Keycode key); + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GetVersion", ExactSpelling = true)] + public static extern void GetVersion(out Version version); + public static Version GetVersion() + { + Version v; + GetVersion(out v); + return v; + } + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GetWindowID", ExactSpelling = true)] + public static extern uint GetWindowID(IntPtr window); + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GetWindowPosition", ExactSpelling = true)] + public static extern void GetWindowPosition(IntPtr window, out int x, out int y); + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GetWindowSize", ExactSpelling = true)] + public static extern void GetWindowSize(IntPtr window, out int w, out int h); + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GetWindowTitle", ExactSpelling = true)] + private static extern IntPtr GetWindowTitlePrivate(IntPtr window); + public static string GetWindowTitle(IntPtr window) + { + return Marshal.PtrToStringAnsi(GetWindowTitlePrivate(window)); + } + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_HideWindow", ExactSpelling = true)] + public static extern void HideWindow(IntPtr window); + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_DisableScreenSaver", ExactSpelling = true)] + public static extern void DisableScreenSaver(); + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_Init", ExactSpelling = true)] + public static extern int Init(SystemFlags flags); + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_InitSubSystem", ExactSpelling = true)] + public static extern int InitSubSystem(SystemFlags flags); + + /// + /// Determines if the specified joystick is supported by the GameController API. + /// + /// true if joystick_index is supported by the GameController API; false otherwise. + /// The index of the joystick to check. + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_IsGameController", ExactSpelling = true)] + public static extern bool IsGameController(int joystick_index); + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_JoystickClose", ExactSpelling = true)] + public static extern void JoystickClose(IntPtr joystick); + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_JoystickEventState", ExactSpelling = true)] + public static extern EventState JoystickEventState(EventState enabled); + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_JoystickGetAxis", ExactSpelling = true)] + public static extern short JoystickGetAxis(IntPtr joystick, int axis); + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_JoystickGetButton", ExactSpelling = true)] + public static extern byte JoystickGetButton(IntPtr joystick, int button); + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_JoystickGetGUID", ExactSpelling = true)] + public static extern JoystickGuid JoystickGetGUID(IntPtr joystick); + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_JoystickInstanceID", ExactSpelling = true)] + public static extern int JoystickInstanceID(IntPtr joystick); + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_JoystickName", ExactSpelling = true)] + private static extern IntPtr JoystickNameInternal(IntPtr joystick); + public static string JoystickName(IntPtr joystick) + { + unsafe + { + return new string((sbyte*)JoystickNameInternal(joystick)); + } + } + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_JoystickNumAxes", ExactSpelling = true)] + public static extern int JoystickNumAxes(IntPtr joystick); + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_JoystickNumBalls", ExactSpelling = true)] + public static extern int JoystickNumBalls(IntPtr joystick); + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_JoystickNumButtons", ExactSpelling = true)] + public static extern int JoystickNumButtons(IntPtr joystick); + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_JoystickNumHats", ExactSpelling = true)] + public static extern int JoystickNumHats(IntPtr joystick); + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_JoystickOpen", ExactSpelling = true)] + public static extern IntPtr JoystickOpen(int device_index); + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_JoystickUpdate", ExactSpelling = true)] + public static extern void JoystickUpdate(); + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_MaximizeWindow", ExactSpelling = true)] + public static extern void MaximizeWindow(IntPtr window); + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_MinimizeWindow", ExactSpelling = true)] + public static extern void MinimizeWindow(IntPtr window); + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_NumJoysticks", ExactSpelling = true)] + public static extern int NumJoysticks(); + + public static int PeepEvents(ref Event e, EventAction action, EventType min, EventType max) + { + unsafe + { + fixed (Event* pe = &e) + { + return PeepEvents(pe, 1, action, min, max); + } + } + } + + public static int PeepEvents(Event[] e, int count, EventAction action, EventType min, EventType max) + { + if (e == null) + { + throw new ArgumentNullException(); + } + if (count <= 0 || count > e.Length) + { + throw new ArgumentOutOfRangeException(); + } + + unsafe + { + fixed (Event *pe = e) + { + return PeepEvents(pe, count, action, min, max); + } + } + } + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_PeepEvents", ExactSpelling = true)] + private unsafe static extern int PeepEvents(Event* e, int count, EventAction action, EventType min, EventType max); + + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_PixelFormatEnumToMasks", ExactSpelling = true)] + public static extern bool PixelFormatEnumToMasks(uint format, out int bpp, + out uint rmask, out uint gmask, out uint bmask, out uint amask); + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_PollEvent", ExactSpelling = true)] + public static extern int PollEvent(out Event e); + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_PumpEvents", ExactSpelling = true)] + public static extern void PumpEvents(); + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_PushEvent", ExactSpelling = true)] + public static extern int PushEvent(ref Event @event); + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_RaiseWindow", ExactSpelling = true)] + public static extern void RaiseWindow(IntPtr window); + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_RestoreWindow", ExactSpelling = true)] + public static extern void RestoreWindow(IntPtr window); + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_SetRelativeMouseMode", ExactSpelling = true)] + public static extern int SetRelativeMouseMode(bool enabled); + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_SetWindowBordered", ExactSpelling = true)] + public static extern void SetWindowBordered(IntPtr window, bool bordered); + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_SetWindowFullscreen", ExactSpelling = true)] + public static extern int SetWindowFullscreen(IntPtr window, uint flags); + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_SetWindowGrab", ExactSpelling = true)] + public static extern void SetWindowGrab(IntPtr window, bool grabbed); + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_SetWindowIcon", ExactSpelling = true)] + public static extern void SetWindowIcon(IntPtr window, IntPtr icon); + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_SetWindowPosition", ExactSpelling = true)] + public static extern void SetWindowPosition(IntPtr window, int x, int y); + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_SetWindowSize", ExactSpelling = true)] + public static extern void SetWindowSize(IntPtr window, int x, int y); + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_SetWindowTitle", ExactSpelling = true)] + public static extern void SetWindowTitle(IntPtr window, string title); + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_ShowCursor", ExactSpelling = true)] + public static extern int ShowCursor(bool toggle); + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_ShowWindow", ExactSpelling = true)] + public static extern void ShowWindow(IntPtr window); + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_WasInit", ExactSpelling = true)] + public static extern bool WasInit(SystemFlags flags); + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_WarpMouseInWindow", ExactSpelling = true)] + public static extern void WarpMouseInWindow(IntPtr window, int x, int y); + + [SuppressUnmanagedCodeSecurity] + [DllImport (lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_WarpMouseGlobal", ExactSpelling = true)] + public static extern void WarpMouseGlobal(int x, int y); + + /// + /// Retrieves driver-dependent window information. + /// + /// + /// The window about which information is being requested. + /// + /// + /// Returns driver-dependent information about the specified window. + /// + /// + /// True, if the function is implemented and the version number of the info struct is valid; + /// false, otherwise. + /// + public static bool GetWindowWMInfo(IntPtr window, out SysWMInfo info) + { + info = new SysWMInfo(); + info.Version = GetVersion(); + return GetWindowWMInfoInternal(window, ref info); + } + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GetWindowWMInfo", ExactSpelling = true)] + private static extern bool GetWindowWMInfoInternal(IntPtr window, ref SysWMInfo info); + + public partial class GL + { + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GL_CreateContext", ExactSpelling = true)] + public static extern IntPtr CreateContext(IntPtr window); + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GL_DeleteContext", ExactSpelling = true)] + public static extern void DeleteContext(IntPtr context); + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GL_GetAttribute", ExactSpelling = true)] + public static extern int GetAttribute(ContextAttribute attr, out int value); + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GL_GetCurrentContext", ExactSpelling = true)] + public static extern IntPtr GetCurrentContext(); + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GL_GetDrawableSize", ExactSpelling = true)] + public static extern void GetDrawableSize(IntPtr window, out int w, out int h); + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GL_GetProcAddress", ExactSpelling = true)] + public static extern IntPtr GetProcAddress(IntPtr proc); + public static IntPtr GetProcAddress(string proc) + { + IntPtr p = Marshal.StringToHGlobalAnsi(proc); + try + { + return GetProcAddress(p); + } + finally + { + Marshal.FreeHGlobal(p); + } + } + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GL_GetSwapInterval", ExactSpelling = true)] + public static extern int GetSwapInterval(); + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GL_MakeCurrent", ExactSpelling = true)] + public static extern int MakeCurrent(IntPtr window, IntPtr context); + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GL_SetAttribute", ExactSpelling = true)] + public static extern int SetAttribute(ContextAttribute attr, int value); + public static int SetAttribute(ContextAttribute attr, ContextFlags value) + { + return SetAttribute(attr, (int)value); + } + public static int SetAttribute(ContextAttribute attr, ContextProfileFlags value) + { + return SetAttribute(attr, (int)value); + } + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GL_SetSwapInterval", ExactSpelling = true)] + public static extern int SetSwapInterval(int interval); + + [SuppressUnmanagedCodeSecurity] + [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GL_SwapWindow", ExactSpelling = true)] + public static extern void SwapWindow(IntPtr window); + } + } + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate int EventFilter(IntPtr userdata, IntPtr @event); + + internal enum Button : byte + { + Left = 1, + Middle, + Right, + X1, + X2 + } + + [Flags] + internal enum ButtonFlags + { + Left = 1 << (Button.Left - 1), + Middle = 1 << (Button.Middle - 1), + Right = 1 << (Button.Right - 1), + X1 = 1 << (Button.X1 - 1), + X2 = 1 << (Button.X2 - 1), + } + + internal enum ContextAttribute + { + RED_SIZE, + GREEN_SIZE, + BLUE_SIZE, + ALPHA_SIZE, + BUFFER_SIZE, + DOUBLEBUFFER, + DEPTH_SIZE, + STENCIL_SIZE, + ACCUM_RED_SIZE, + ACCUM_GREEN_SIZE, + ACCUM_BLUE_SIZE, + ACCUM_ALPHA_SIZE, + STEREO, + MULTISAMPLEBUFFERS, + MULTISAMPLESAMPLES, + ACCELERATED_VISUAL, + RETAINED_BACKING, + CONTEXT_MAJOR_VERSION, + CONTEXT_MINOR_VERSION, + CONTEXT_EGL, + CONTEXT_FLAGS, + CONTEXT_PROFILE_MASK, + SHARE_WITH_CURRENT_CONTEXT + } + + [Flags] + internal enum ContextFlags + { + DEBUG = 0x0001, + FORWARD_COMPATIBLE = 0x0002, + ROBUST_ACCESS = 0x0004, + RESET_ISOLATION = 0x0008 + } + + [Flags] + internal enum ContextProfileFlags + { + CORE = 0x0001, + COMPATIBILITY = 0x0002, + ES = 0x0004 + } + + internal enum EventAction + { + Add, + Peek, + Get + } + + internal enum EventState + { + Query = -1, + Ignore = 0, + Enable = 1 + } + + internal enum EventType + { + FIRSTEVENT = 0, + QUIT = 0x100, + WINDOWEVENT = 0x200, + SYSWMEVENT, + KEYDOWN = 0x300, + KEYUP, + TEXTEDITING, + TEXTINPUT, + MOUSEMOTION = 0x400, + MOUSEBUTTONDOWN, + MOUSEBUTTONUP, + MOUSEWHEEL, + JOYAXISMOTION = 0x600, + JOYBALLMOTION, + JOYHATMOTION, + JOYBUTTONDOWN, + JOYBUTTONUP, + JOYDEVICEADDED, + JOYDEVICEREMOVED, + CONTROLLERAXISMOTION = 0x650, + CONTROLLERBUTTONDOWN, + CONTROLLERBUTTONUP, + CONTROLLERDEVICEADDED, + CONTROLLERDEVICEREMOVED, + CONTROLLERDEVICEREMAPPED, + FINGERDOWN = 0x700, + FINGERUP, + FINGERMOTION, + DOLLARGESTURE = 0x800, + DOLLARRECORD, + MULTIGESTURE, + CLIPBOARDUPDATE = 0x900, + DROPFILE = 0x1000, + USEREVENT = 0x8000, + LASTEVENT = 0xFFFF + } + + internal enum GameControllerAxis : byte + { + Invalid = 0xff, + LeftX = 0, + LeftY, + RightX, + RightY, + TriggerLeft, + TriggerRight, + Max + } + + internal enum GameControllerButton : byte + { + INVALID = 0xff, + A = 0, + B, + X, + Y, + BACK, + GUIDE, + START, + LEFTSTICK, + RIGHTSTICK, + LEFTSHOULDER, + RIGHTSHOULDER, + DPAD_UP, + DPAD_DOWN, + DPAD_LEFT, + DPAD_RIGHT, + Max + } + + internal enum GameControllerBindType : byte + { + None = 0, + Button, + Axis, + Hat + } + + [Flags] + internal enum HatPosition : byte + { + Centered = 0x00, + Up = 0x01, + Right = 0x02, + Down = 0x04, + Left = 0x08, + RightUp = Right | Up, + RightDown = Right | Down, + LeftUp = Left | Up, + LeftDown = Left | Down + } + + internal enum Keycode + { + UNKNOWN = 0, + RETURN = '\r', + ESCAPE = 27, // '\033' octal + BACKSPACE = '\b', + TAB = '\t', + SPACE = ' ', + EXCLAIM = '!', + QUOTEDBL = '"', + HASH = '#', + PERCENT = '%', + DOLLAR = '$', + AMPERSAND = '&', + QUOTE = '\'', + LEFTPAREN = '(', + RIGHTPAREN = ')', + ASTERISK = '*', + PLUS = '+', + COMMA = ',', + MINUS = '-', + PERIOD = '.', + SLASH = '/', + Num0 = '0', + Num1 = '1', + Num2 = '2', + Num3 = '3', + Num4 = '4', + Num5 = '5', + Num6 = '6', + Num7 = '7', + Num8 = '8', + Num9 = '9', + COLON = ':', + SEMICOLON = ';', + LESS = '<', + EQUALS = '=', + GREATER = '>', + QUESTION = '?', + AT = '@', + LEFTBRACKET = '[', + BACKSLASH = '\\', + RIGHTBRACKET = ']', + CARET = '^', + UNDERSCORE = '_', + BACKQUOTE = '`', + a = 'a', + b = 'b', + c = 'c', + d = 'd', + e = 'e', + f = 'f', + g = 'g', + h = 'h', + i = 'i', + j = 'j', + k = 'k', + l = 'l', + m = 'm', + n = 'n', + o = 'o', + p = 'p', + q = 'q', + r = 'r', + s = 's', + t = 't', + u = 'u', + v = 'v', + w = 'w', + x = 'x', + y = 'y', + z = 'z', + CAPSLOCK = (1 << 30) | (int)Scancode.CAPSLOCK, + F1 = (1 << 30) | (int)Scancode.F1, + F2 = (1 << 30) | (int)Scancode.F2, + F3 = (1 << 30) | (int)Scancode.F3, + F4 = (1 << 30) | (int)Scancode.F4, + F5 = (1 << 30) | (int)Scancode.F5, + F6 = (1 << 30) | (int)Scancode.F6, + F7 = (1 << 30) | (int)Scancode.F7, + F8 = (1 << 30) | (int)Scancode.F8, + F9 = (1 << 30) | (int)Scancode.F9, + F10 = (1 << 30) | (int)Scancode.F10, + F11 = (1 << 30) | (int)Scancode.F11, + F12 = (1 << 30) | (int)Scancode.F12, + PRINTSCREEN = (1 << 30) | (int)Scancode.PRINTSCREEN, + SCROLLLOCK = (1 << 30) | (int)Scancode.SCROLLLOCK, + PAUSE = (1 << 30) | (int)Scancode.PAUSE, + INSERT = (1 << 30) | (int)Scancode.INSERT, + HOME = (1 << 30) | (int)Scancode.HOME, + PAGEUP = (1 << 30) | (int)Scancode.PAGEUP, + DELETE = 127, // '\177' octal + END = (1 << 30) | (int)Scancode.END, + PAGEDOWN = (1 << 30) | (int)Scancode.PAGEDOWN, + RIGHT = (1 << 30) | (int)Scancode.RIGHT, + LEFT = (1 << 30) | (int)Scancode.LEFT, + DOWN = (1 << 30) | (int)Scancode.DOWN, + UP = (1 << 30) | (int)Scancode.UP, + NUMLOCKCLEAR = (1 << 30) | (int)Scancode.NUMLOCKCLEAR, + KP_DIVIDE = (1 << 30) | (int)Scancode.KP_DIVIDE, + KP_MULTIPLY = (1 << 30) | (int)Scancode.KP_MULTIPLY, + KP_MINUS = (1 << 30) | (int)Scancode.KP_MINUS, + KP_PLUS = (1 << 30) | (int)Scancode.KP_PLUS, + KP_ENTER = (1 << 30) | (int)Scancode.KP_ENTER, + KP_1 = (1 << 30) | (int)Scancode.KP_1, + KP_2 = (1 << 30) | (int)Scancode.KP_2, + KP_3 = (1 << 30) | (int)Scancode.KP_3, + KP_4 = (1 << 30) | (int)Scancode.KP_4, + KP_5 = (1 << 30) | (int)Scancode.KP_5, + KP_6 = (1 << 30) | (int)Scancode.KP_6, + KP_7 = (1 << 30) | (int)Scancode.KP_7, + KP_8 = (1 << 30) | (int)Scancode.KP_8, + KP_9 = (1 << 30) | (int)Scancode.KP_9, + KP_0 = (1 << 30) | (int)Scancode.KP_0, + KP_PERIOD = (1 << 30) | (int)Scancode.KP_PERIOD, + APPLICATION = (1 << 30) | (int)Scancode.APPLICATION, + POWER = (1 << 30) | (int)Scancode.POWER, + KP_EQUALS = (1 << 30) | (int)Scancode.KP_EQUALS, + F13 = (1 << 30) | (int)Scancode.F13, + F14 = (1 << 30) | (int)Scancode.F14, + F15 = (1 << 30) | (int)Scancode.F15, + F16 = (1 << 30) | (int)Scancode.F16, + F17 = (1 << 30) | (int)Scancode.F17, + F18 = (1 << 30) | (int)Scancode.F18, + F19 = (1 << 30) | (int)Scancode.F19, + F20 = (1 << 30) | (int)Scancode.F20, + F21 = (1 << 30) | (int)Scancode.F21, + F22 = (1 << 30) | (int)Scancode.F22, + F23 = (1 << 30) | (int)Scancode.F23, + F24 = (1 << 30) | (int)Scancode.F24, + EXECUTE = (1 << 30) | (int)Scancode.EXECUTE, + HELP = (1 << 30) | (int)Scancode.HELP, + MENU = (1 << 30) | (int)Scancode.MENU, + SELECT = (1 << 30) | (int)Scancode.SELECT, + STOP = (1 << 30) | (int)Scancode.STOP, + AGAIN = (1 << 30) | (int)Scancode.AGAIN, + UNDO = (1 << 30) | (int)Scancode.UNDO, + CUT = (1 << 30) | (int)Scancode.CUT, + COPY = (1 << 30) | (int)Scancode.COPY, + PASTE = (1 << 30) | (int)Scancode.PASTE, + FIND = (1 << 30) | (int)Scancode.FIND, + MUTE = (1 << 30) | (int)Scancode.MUTE, + VOLUMEUP = (1 << 30) | (int)Scancode.VOLUMEUP, + VOLUMEDOWN = (1 << 30) | (int)Scancode.VOLUMEDOWN, + KP_COMMA = (1 << 30) | (int)Scancode.KP_COMMA, + KP_EQUALSAS400 = (1 << 30) | (int)Scancode.KP_EQUALSAS400, + ALTERASE = (1 << 30) | (int)Scancode.ALTERASE, + SYSREQ = (1 << 30) | (int)Scancode.SYSREQ, + CANCEL = (1 << 30) | (int)Scancode.CANCEL, + CLEAR = (1 << 30) | (int)Scancode.CLEAR, + PRIOR = (1 << 30) | (int)Scancode.PRIOR, + RETURN2 = (1 << 30) | (int)Scancode.RETURN2, + SEPARATOR = (1 << 30) | (int)Scancode.SEPARATOR, + OUT = (1 << 30) | (int)Scancode.OUT, + OPER = (1 << 30) | (int)Scancode.OPER, + CLEARAGAIN = (1 << 30) | (int)Scancode.CLEARAGAIN, + CRSEL = (1 << 30) | (int)Scancode.CRSEL, + EXSEL = (1 << 30) | (int)Scancode.EXSEL, + KP_00 = (1 << 30) | (int)Scancode.KP_00, + KP_000 = (1 << 30) | (int)Scancode.KP_000, + THOUSANDSSEPARATOR = (1 << 30) | (int)Scancode.THOUSANDSSEPARATOR, + DECIMALSEPARATOR = (1 << 30) | (int)Scancode.DECIMALSEPARATOR, + CURRENCYUNIT = (1 << 30) | (int)Scancode.CURRENCYUNIT, + CURRENCYSUBUNIT = (1 << 30) | (int)Scancode.CURRENCYSUBUNIT, + KP_LEFTPAREN = (1 << 30) | (int)Scancode.KP_LEFTPAREN, + KP_RIGHTPAREN = (1 << 30) | (int)Scancode.KP_RIGHTPAREN, + KP_LEFTBRACE = (1 << 30) | (int)Scancode.KP_LEFTBRACE, + KP_RIGHTBRACE = (1 << 30) | (int)Scancode.KP_RIGHTBRACE, + KP_TAB = (1 << 30) | (int)Scancode.KP_TAB, + KP_BACKSPACE = (1 << 30) | (int)Scancode.KP_BACKSPACE, + KP_A = (1 << 30) | (int)Scancode.KP_A, + KP_B = (1 << 30) | (int)Scancode.KP_B, + KP_C = (1 << 30) | (int)Scancode.KP_C, + KP_D = (1 << 30) | (int)Scancode.KP_D, + KP_E = (1 << 30) | (int)Scancode.KP_E, + KP_F = (1 << 30) | (int)Scancode.KP_F, + KP_XOR = (1 << 30) | (int)Scancode.KP_XOR, + KP_POWER = (1 << 30) | (int)Scancode.KP_POWER, + KP_PERCENT = (1 << 30) | (int)Scancode.KP_PERCENT, + KP_LESS = (1 << 30) | (int)Scancode.KP_LESS, + KP_GREATER = (1 << 30) | (int)Scancode.KP_GREATER, + KP_AMPERSAND = (1 << 30) | (int)Scancode.KP_AMPERSAND, + KP_DBLAMPERSAND = (1 << 30) | (int)Scancode.KP_DBLAMPERSAND, + KP_VERTICALBAR = (1 << 30) | (int)Scancode.KP_VERTICALBAR, + KP_DBLVERTICALBAR = (1 << 30) | (int)Scancode.KP_DBLVERTICALBAR, + KP_COLON = (1 << 30) | (int)Scancode.KP_COLON, + KP_HASH = (1 << 30) | (int)Scancode.KP_HASH, + KP_SPACE = (1 << 30) | (int)Scancode.KP_SPACE, + KP_AT = (1 << 30) | (int)Scancode.KP_AT, + KP_EXCLAM = (1 << 30) | (int)Scancode.KP_EXCLAM, + KP_MEMSTORE = (1 << 30) | (int)Scancode.KP_MEMSTORE, + KP_MEMRECALL = (1 << 30) | (int)Scancode.KP_MEMRECALL, + KP_MEMCLEAR = (1 << 30) | (int)Scancode.KP_MEMCLEAR, + KP_MEMADD = (1 << 30) | (int)Scancode.KP_MEMADD, + KP_MEMSUBTRACT = (1 << 30) | (int)Scancode.KP_MEMSUBTRACT, + KP_MEMMULTIPLY = (1 << 30) | (int)Scancode.KP_MEMMULTIPLY, + KP_MEMDIVIDE = (1 << 30) | (int)Scancode.KP_MEMDIVIDE, + KP_PLUSMINUS = (1 << 30) | (int)Scancode.KP_PLUSMINUS, + KP_CLEAR = (1 << 30) | (int)Scancode.KP_CLEAR, + KP_CLEARENTRY = (1 << 30) | (int)Scancode.KP_CLEARENTRY, + KP_BINARY = (1 << 30) | (int)Scancode.KP_BINARY, + KP_OCTAL = (1 << 30) | (int)Scancode.KP_OCTAL, + KP_DECIMAL = (1 << 30) | (int)Scancode.KP_DECIMAL, + KP_HEXADECIMAL = (1 << 30) | (int)Scancode.KP_HEXADECIMAL, + LCTRL = (1 << 30) | (int)Scancode.LCTRL, + LSHIFT = (1 << 30) | (int)Scancode.LSHIFT, + LALT = (1 << 30) | (int)Scancode.LALT, + LGUI = (1 << 30) | (int)Scancode.LGUI, + RCTRL = (1 << 30) | (int)Scancode.RCTRL, + RSHIFT = (1 << 30) | (int)Scancode.RSHIFT, + RALT = (1 << 30) | (int)Scancode.RALT, + RGUI = (1 << 30) | (int)Scancode.RGUI, + MODE = (1 << 30) | (int)Scancode.MODE, + AUDIONEXT = (1 << 30) | (int)Scancode.AUDIONEXT, + AUDIOPREV = (1 << 30) | (int)Scancode.AUDIOPREV, + AUDIOSTOP = (1 << 30) | (int)Scancode.AUDIOSTOP, + AUDIOPLAY = (1 << 30) | (int)Scancode.AUDIOPLAY, + AUDIOMUTE = (1 << 30) | (int)Scancode.AUDIOMUTE, + MEDIASELECT = (1 << 30) | (int)Scancode.MEDIASELECT, + WWW = (1 << 30) | (int)Scancode.WWW, + MAIL = (1 << 30) | (int)Scancode.MAIL, + CALCULATOR = (1 << 30) | (int)Scancode.CALCULATOR, + COMPUTER = (1 << 30) | (int)Scancode.COMPUTER, + AC_SEARCH = (1 << 30) | (int)Scancode.AC_SEARCH, + AC_HOME = (1 << 30) | (int)Scancode.AC_HOME, + AC_BACK = (1 << 30) | (int)Scancode.AC_BACK, + AC_FORWARD = (1 << 30) | (int)Scancode.AC_FORWARD, + AC_STOP = (1 << 30) | (int)Scancode.AC_STOP, + AC_REFRESH = (1 << 30) | (int)Scancode.AC_REFRESH, + AC_BOOKMARKS = (1 << 30) | (int)Scancode.AC_BOOKMARKS, + BRIGHTNESSDOWN = (1 << 30) | (int)Scancode.BRIGHTNESSDOWN, + BRIGHTNESSUP = (1 << 30) | (int)Scancode.BRIGHTNESSUP, + DISPLAYSWITCH = (1 << 30) | (int)Scancode.DISPLAYSWITCH, + KBDILLUMTOGGLE = (1 << 30) | (int)Scancode.KBDILLUMTOGGLE, + KBDILLUMDOWN = (1 << 30) | (int)Scancode.KBDILLUMDOWN, + KBDILLUMUP = (1 << 30) | (int)Scancode.KBDILLUMUP, + EJECT = (1 << 30) | (int)Scancode.EJECT, + SLEEP = (1 << 30) | (int)Scancode.SLEEP + } + + [Flags] + internal enum Keymod : ushort + { + NONE = 0x0000, + LSHIFT = 0x0001, + RSHIFT = 0x0002, + LCTRL = 0x0040, + RCTRL = 0x0080, + LALT = 0x0100, + RALT = 0x0200, + LGUI = 0x0400, + RGUI = 0x0800, + NUM = 0x1000, + CAPS = 0x2000, + MODE = 0x4000, + RESERVED = 0x8000, + CTRL = (LCTRL | RCTRL), + SHIFT = (LSHIFT | RSHIFT), + ALT = (LALT | RALT), + GUI = (LGUI | RGUI) + } + + internal enum Scancode + { + UNKNOWN = 0, + A = 4, + B = 5, + C = 6, + D = 7, + E = 8, + F = 9, + G = 10, + H = 11, + I = 12, + J = 13, + K = 14, + L = 15, + M = 16, + N = 17, + O = 18, + P = 19, + Q = 20, + R = 21, + S = 22, + T = 23, + U = 24, + V = 25, + W = 26, + X = 27, + Y = 28, + Z = 29, + Num1 = 30, + Num2 = 31, + Num3 = 32, + Num4 = 33, + Num5 = 34, + Num6 = 35, + Num7 = 36, + Num8 = 37, + Num9 = 38, + Num0 = 39, + RETURN = 40, + ESCAPE = 41, + BACKSPACE = 42, + TAB = 43, + SPACE = 44, + MINUS = 45, + EQUALS = 46, + LEFTBRACKET = 47, + RIGHTBRACKET = 48, + BACKSLASH = 49, + NONUSHASH = 50, + SEMICOLON = 51, + APOSTROPHE = 52, + GRAVE = 53, + COMMA = 54, + PERIOD = 55, + SLASH = 56, + CAPSLOCK = 57, + F1 = 58, + F2 = 59, + F3 = 60, + F4 = 61, + F5 = 62, + F6 = 63, + F7 = 64, + F8 = 65, + F9 = 66, + F10 = 67, + F11 = 68, + F12 = 69, + PRINTSCREEN = 70, + SCROLLLOCK = 71, + PAUSE = 72, + INSERT = 73, + HOME = 74, + PAGEUP = 75, + DELETE = 76, + END = 77, + PAGEDOWN = 78, + RIGHT = 79, + LEFT = 80, + DOWN = 81, + UP = 82, + NUMLOCKCLEAR = 83, + KP_DIVIDE = 84, + KP_MULTIPLY = 85, + KP_MINUS = 86, + KP_PLUS = 87, + KP_ENTER = 88, + KP_1 = 89, + KP_2 = 90, + KP_3 = 91, + KP_4 = 92, + KP_5 = 93, + KP_6 = 94, + KP_7 = 95, + KP_8 = 96, + KP_9 = 97, + KP_0 = 98, + KP_PERIOD = 99, + NONUSBACKSLASH = 100, + APPLICATION = 101, + POWER = 102, + KP_EQUALS = 103, + F13 = 104, + F14 = 105, + F15 = 106, + F16 = 107, + F17 = 108, + F18 = 109, + F19 = 110, + F20 = 111, + F21 = 112, + F22 = 113, + F23 = 114, + F24 = 115, + EXECUTE = 116, + HELP = 117, + MENU = 118, + SELECT = 119, + STOP = 120, + AGAIN = 121, + UNDO = 122, + CUT = 123, + COPY = 124, + PASTE = 125, + FIND = 126, + MUTE = 127, + VOLUMEUP = 128, + VOLUMEDOWN = 129, + // not sure whether there's a reason to enable these + // LOCKINGCAPSLOCK = 130, + // LOCKINGNUMLOCK = 131, + // LOCKINGSCROLLLOCK = 132, + KP_COMMA = 133, + KP_EQUALSAS400 = 134, + INTERNATIONAL1 = 135, + INTERNATIONAL2 = 136, + INTERNATIONAL3 = 137, + INTERNATIONAL4 = 138, + INTERNATIONAL5 = 139, + INTERNATIONAL6 = 140, + INTERNATIONAL7 = 141, + INTERNATIONAL8 = 142, + INTERNATIONAL9 = 143, + LANG1 = 144, + LANG2 = 145, + LANG3 = 146, + LANG4 = 147, + LANG5 = 148, + LANG6 = 149, + LANG7 = 150, + LANG8 = 151, + LANG9 = 152, + ALTERASE = 153, + SYSREQ = 154, + CANCEL = 155, + CLEAR = 156, + PRIOR = 157, + RETURN2 = 158, + SEPARATOR = 159, + OUT = 160, + OPER = 161, + CLEARAGAIN = 162, + CRSEL = 163, + EXSEL = 164, + KP_00 = 176, + KP_000 = 177, + THOUSANDSSEPARATOR = 178, + DECIMALSEPARATOR = 179, + CURRENCYUNIT = 180, + CURRENCYSUBUNIT = 181, + KP_LEFTPAREN = 182, + KP_RIGHTPAREN = 183, + KP_LEFTBRACE = 184, + KP_RIGHTBRACE = 185, + KP_TAB = 186, + KP_BACKSPACE = 187, + KP_A = 188, + KP_B = 189, + KP_C = 190, + KP_D = 191, + KP_E = 192, + KP_F = 193, + KP_XOR = 194, + KP_POWER = 195, + KP_PERCENT = 196, + KP_LESS = 197, + KP_GREATER = 198, + KP_AMPERSAND = 199, + KP_DBLAMPERSAND = 200, + KP_VERTICALBAR = 201, + KP_DBLVERTICALBAR = 202, + KP_COLON = 203, + KP_HASH = 204, + KP_SPACE = 205, + KP_AT = 206, + KP_EXCLAM = 207, + KP_MEMSTORE = 208, + KP_MEMRECALL = 209, + KP_MEMCLEAR = 210, + KP_MEMADD = 211, + KP_MEMSUBTRACT = 212, + KP_MEMMULTIPLY = 213, + KP_MEMDIVIDE = 214, + KP_PLUSMINUS = 215, + KP_CLEAR = 216, + KP_CLEARENTRY = 217, + KP_BINARY = 218, + KP_OCTAL = 219, + KP_DECIMAL = 220, + KP_HEXADECIMAL = 221, + LCTRL = 224, + LSHIFT = 225, + LALT = 226, + LGUI = 227, + RCTRL = 228, + RSHIFT = 229, + RALT = 230, + RGUI = 231, + MODE = 257, + // These come from the USB consumer page (0x0C) + AUDIONEXT = 258, + AUDIOPREV = 259, + AUDIOSTOP = 260, + AUDIOPLAY = 261, + AUDIOMUTE = 262, + MEDIASELECT = 263, + WWW = 264, + MAIL = 265, + CALCULATOR = 266, + COMPUTER = 267, + AC_SEARCH = 268, + AC_HOME = 269, + AC_BACK = 270, + AC_FORWARD = 271, + AC_STOP = 272, + AC_REFRESH = 273, + AC_BOOKMARKS = 274, + // These come from other sources, and are mostly mac related + BRIGHTNESSDOWN = 275, + BRIGHTNESSUP = 276, + DISPLAYSWITCH = 277, + KBDILLUMTOGGLE = 278, + KBDILLUMDOWN = 279, + KBDILLUMUP = 280, + EJECT = 281, + SLEEP = 282, + APP1 = 283, + APP2 = 284, + // This is not a key, simply marks the number of scancodes + // so that you know how big to make your arrays. + SDL_NUM_SCANCODES = 512 + } + + internal enum State : byte + { + Released = 0, + Pressed = 1 + } + + [Flags] + internal enum SystemFlags : uint + { + Default = 0, + TIMER = 0x00000001, + AUDIO = 0x00000010, + VIDEO = 0x00000020, + JOYSTICK = 0x00000200, + HAPTIC = 0x00001000, + GAMECONTROLLER = 0x00002000, + NOPARACHUTE = 0x00100000, + EVERYTHING = TIMER | AUDIO | VIDEO | + JOYSTICK | HAPTIC | GAMECONTROLLER + } + + internal enum SysWMType + { + Unknown = 0, + Windows, + X11, + Wayland, + DirectFB, + Cocoa, + UIKit, + } + + internal enum WindowEventID : byte + { + NONE, + SHOWN, + HIDDEN, + EXPOSED, + MOVED, + RESIZED, + SIZE_CHANGED, + MINIMIZED, + MAXIMIZED, + RESTORED, + ENTER, + LEAVE, + FOCUS_GAINED, + FOCUS_LOST, + CLOSE, + } + + internal enum WindowFlags + { + Default = 0, + FULLSCREEN = 0x00000001, + OPENGL = 0x00000002, + SHOWN = 0x00000004, + HIDDEN = 0x00000008, + BORDERLESS = 0x00000010, + RESIZABLE = 0x00000020, + MINIMIZED = 0x00000040, + MAXIMIZED = 0x00000080, + INPUT_GRABBED = 0x00000100, + INPUT_FOCUS = 0x00000200, + MOUSE_FOCUS = 0x00000400, + FULLSCREEN_DESKTOP = (FULLSCREEN | 0x00001000), + FOREIGN = 0x00000800, + ALLOW_HIGHDPI = 0x00002000, + } + + internal struct ControllerAxisEvent + { + public EventType Type; + public uint Timestamp; + public int Which; + public GameControllerAxis Axis; + private byte padding1; + private byte padding2; + private byte padding3; + public short Value; + private ushort padding4; + } + + internal struct ControllerButtonEvent + { + public EventType Type; + public uint Timestamp; + public int Which; + public GameControllerButton Button; + public State State; + private byte padding1; + private byte padding2; + } + + internal struct ControllerDeviceEvent + { + public EventType Type; + public uint Timestamp; + + /// + /// The joystick device index for the ADDED event, instance id for the REMOVED or REMAPPED event + /// + public int Which; + } + + internal struct DisplayMode + { + public uint Format; + public int Width; + public int Height; + public int RefreshRate; + public IntPtr DriverData; + } + + [StructLayout(LayoutKind.Explicit)] + internal struct Event + { + [FieldOffset(0)] + public EventType Type; + [FieldOffset(0)] + public WindowEvent Window; + [FieldOffset(0)] + public KeyboardEvent Key; + [FieldOffset(0)] + public TextEditingEvent Edit; + [FieldOffset(0)] + public TextInputEvent Text; + [FieldOffset(0)] + public MouseMotionEvent Motion; + [FieldOffset(0)] + public MouseButtonEvent Button; + [FieldOffset(0)] + public MouseWheelEvent Wheel; + [FieldOffset(0)] + public JoyAxisEvent JoyAxis; + [FieldOffset(0)] + public JoyBallEvent JoyBall; + [FieldOffset(0)] + public JoyHatEvent JoyHat; + [FieldOffset(0)] + public JoyButtonEvent JoyButton; + [FieldOffset(0)] + public JoyDeviceEvent JoyDevice; + [FieldOffset(0)] + public ControllerAxisEvent ControllerAxis; + [FieldOffset(0)] + public ControllerButtonEvent ControllerButton; + [FieldOffset(0)] + public ControllerDeviceEvent ControllerDevice; + [FieldOffset(0)] + public DropEvent Drop; + #if false + [FieldOffset(0)] + public QuitEvent quit; + [FieldOffset(0)] + public UserEvent user; + [FieldOffset(0)] + public SysWMEvent syswm; + [FieldOffset(0)] + public TouchFingerEvent tfinger; + [FieldOffset(0)] + public MultiGestureEvent mgesture; + [FieldOffset(0)] + public DollarGestureEvent dgesture; + #endif + + // Ensure the structure is big enough + // This hack is necessary to ensure compatibility + // with different SDL versions, which might have + // different sizeof(SDL_Event). + [FieldOffset(0)] + private unsafe fixed byte reserved[128]; + } + + [StructLayout(LayoutKind.Explicit)] + internal struct GameControllerButtonBind + { + [FieldOffset(0)] + public GameControllerBindType BindType; + [FieldOffset(4)] + public Button Button; + [FieldOffset(4)] + public GameControllerAxis Axis; + [FieldOffset(4)] + public int Hat; + [FieldOffset(8)] + public int HatMask; + } + + internal struct JoyAxisEvent + { + public EventType Type; + public UInt32 Timestamp; + public Int32 Which; // SDL_JoystickID + public byte Axis; + private byte padding1; + private byte padding2; + private byte padding3; + public Int16 Value; + private UInt16 padding4; + } + + internal struct JoyBallEvent + { + public EventType Type; + public uint Timestamp; + public int Which; + public byte Ball; + private byte padding1; + private byte padding2; + private byte padding3; + public short Xrel; + public short Yrel; + } + + internal struct JoyButtonEvent + { + public EventType Type; + public uint Timestamp; + public int Which; + public byte Button; + public State State; + private byte padding1; + private byte padding2; + } + + internal struct JoyDeviceEvent + { + public EventType Type; + public uint Timestamp; + public int Which; + } + + internal struct JoyHatEvent + { + public EventType Type; + public uint Timestamp; + public int Which; + public byte Hat; + public HatPosition Value; + private byte padding1; + private byte padding2; + } + + internal struct JoystickGuid + { + private long data0; + private long data1; + + public Guid ToGuid() + { + byte[] data = new byte[16]; + + unsafe + { + fixed (JoystickGuid* pdata = &this) + { + Marshal.Copy(new IntPtr(pdata), data, 0, data.Length); + } + } + + // The Guid(byte[]) constructor swaps the first 4+2+2 bytes. + // Compensate for that, otherwise we will not be able to match + // the Guids in the configuration database. + if (BitConverter.IsLittleEndian) + { + Array.Reverse(data, 0, 4); + Array.Reverse(data, 4, 2); + Array.Reverse(data, 6, 2); + } + + return new Guid(data); + } + } + + internal struct KeyboardEvent + { + public EventType Type; + public uint Timestamp; + public uint WindowID; + public State State; + public byte Repeat; + private byte padding2; + private byte padding3; + public Keysym Keysym; + } + + internal struct Keysym + { + public Scancode Scancode; + public Keycode Sym; + public Keymod Mod; + [Obsolete] + public uint Unicode; + } + + internal struct MouseButtonEvent + { + public EventType Type; + public UInt32 Timestamp; + public UInt32 WindowID; + public UInt32 Which; + public Button Button; + public State State; + public byte Clicks; + private byte padding1; + public Int32 X; + public Int32 Y; + } + + internal struct MouseMotionEvent + { + public EventType Type; + public uint Timestamp; + public uint WindowID; + public uint Which; + public ButtonFlags State; + public Int32 X; + public Int32 Y; + public Int32 Xrel; + public Int32 Yrel; + } + + internal struct MouseWheelEvent + { + public EventType Type; + public uint Timestamp; + public uint WindowID; + public uint Which; + public int X; + public int Y; + + public enum EventType : uint + { + /* Touch events */ + FingerDown = 0x700, + FingerUp, + FingerMotion, + + /* Gesture events */ + DollarGesture = 0x800, + DollarRecord, + MultiGesture, + } + + public const uint TouchMouseID = 0xffffffff; + } + + internal struct Rect + { + public int X; + public int Y; + public int Width; + public int Height; + } + + internal struct SysWMInfo + { + public Version Version; + public SysWMType Subsystem; + public SysInfo Info; + + [StructLayout(LayoutKind.Explicit)] + public struct SysInfo + { + [FieldOffset(0)] + public WindowsInfo Windows; + [FieldOffset(0)] + public X11Info X11; + [FieldOffset(0)] + public WaylandInfo Wayland; + [FieldOffset(0)] + public DirectFBInfo DirectFB; + [FieldOffset(0)] + public CocoaInfo Cocoa; + [FieldOffset(0)] + public UIKitInfo UIKit; + + public struct WindowsInfo + { + public IntPtr Window; + } + + public struct X11Info + { + public IntPtr Display; + public IntPtr Window; + } + + public struct WaylandInfo + { + public IntPtr Display; + public IntPtr Surface; + public IntPtr ShellSurface; + } + + public struct DirectFBInfo + { + public IntPtr Dfb; + public IntPtr Window; + public IntPtr Surface; + } + + public struct CocoaInfo + { + public IntPtr Window; + } + + public struct UIKitInfo + { + public IntPtr Window; + } + } + } + + internal struct TextEditingEvent + { + public const int TextSize = 32; + + public EventType Type; + public UInt32 Timestamp; + public UInt32 WindowID; + public unsafe fixed byte Text[TextSize]; + public Int32 Start; + public Int32 Length; + } + + internal struct TextInputEvent + { + public const int TextSize = 32; + + public EventType Type; + public UInt32 Timestamp; + public UInt32 WindowID; + public unsafe fixed byte Text[TextSize]; + } + + internal struct Version + { + public byte Major; + public byte Minor; + public byte Patch; + + public int Number + { + get { return 1000 * Major + 100 * Minor + Patch; } + } + } + + internal struct WindowEvent + { + public EventType Type; + public UInt32 Timestamp; + public UInt32 WindowID; + public WindowEventID Event; + private byte padding1; + private byte padding2; + private byte padding3; + public Int32 Data1; + public Int32 Data2; + } + + /// + /// Drop event for SDL2 interop. For detailed info look: https://wiki.libsdl.org/SDL_DropEvent + /// + internal struct DropEvent + { + public UInt32 Type; + public UInt32 Timestamp; + public IntPtr File; + public UInt32 WindowID; + } +} + diff --git a/Tests/test-sdl2 (copier).cs b/Tests/test-sdl2 (copier).cs new file mode 100644 index 00000000..6bc2c64e --- /dev/null +++ b/Tests/test-sdl2 (copier).cs @@ -0,0 +1,162 @@ +// +// test-sdl2.cs +// +// Author: +// jp <> +// +// Copyright (c) 2013-2017 Jean-Philippe Bruyère +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using OpenTK; +using OpenTK.Graphics.OpenGL; +using OpenTK.Platform; +using Crow.SDL2; + +namespace Crow +{ + public class test_sdl2_2 + { + public test_sdl2_2 () + { + } + + static int colors = 32, depth=24, stencil=0,samples=1; + static int width=500,height=500; + + static void Main(){ + SysWMInfo sdlInfo; + + SDL.Init (SystemFlags.EVERYTHING); + + + + + IntPtr hWin = SDL.CreateWindow ("test sdl2", 0, 0, width, height, WindowFlags.OPENGL | WindowFlags.SHOWN); + +// SDL.GL.SetAttribute (ContextAttribute.CONTEXT_MAJOR_VERSION, 4); +// SDL.GL.SetAttribute (ContextAttribute.CONTEXT_MAJOR_VERSION, 5); + SDL.GL.SetAttribute (ContextAttribute.SHARE_WITH_CURRENT_CONTEXT, 1); + + IntPtr hCtx = SDL.GL.CreateContext (hWin); + IntPtr hCairoCtx = SDL.GL.CreateContext (hWin); + + SDL.GetWindowWMInfo (hWin, out sdlInfo); + SDL.GL.MakeCurrent(hWin,hCtx); + + int major, minor; + SDL.GL.GetAttribute (ContextAttribute.CONTEXT_MAJOR_VERSION, out major); + SDL.GL.GetAttribute (ContextAttribute.CONTEXT_MINOR_VERSION, out minor); + Console.WriteLine ("gl context = {0}.{1}\n", major, minor); + + Toolkit.Init(); + IWindowInfo wi = Utilities.CreateSdl2WindowInfo (hWin); + ContextHandle otkCtx = new ContextHandle (hCtx); +// //OpenTK.Graphics.GraphicsMode gm = new OpenTK.Graphics.GraphicsMode (colors, depth, stencil, samples); + OpenTK.Graphics.GraphicsContext ctx = new OpenTK.Graphics.GraphicsContext (otkCtx, wi); +// ctx.MakeCurrent(wi); + + + ctx.LoadAll(); + + Cairo.GLXDevice dev = new Cairo.GLXDevice (sdlInfo.Info.X11.Display, hCairoCtx); + + int tex = GL.GenTexture (); + GL.BindTexture (TextureTarget.Texture2D, tex); + GL.TexImage2D (TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, width, height, 0, + PixelFormat.Bgra, PixelType.UnsignedByte, IntPtr.Zero); + + //dev.Acquire (); + Cairo.GLSurface surf = new Cairo.GLSurface (dev,Cairo.Content.ColorAlpha,(uint)tex, width,height); + + SDL.GL.MakeCurrent(hWin,hCairoCtx); + using (Cairo.Context gr = new Cairo.Context (surf)) { + gr.Rectangle (150, 100, 200, 100); + gr.SetSourceRGBA (1.0, 0.0, 0.0,0.5); + gr.Fill (); + gr.Rectangle (200, 150, 200, 100); + gr.SetSourceRGBA (0.0, 1.0, 0.0,0.5); + gr.Fill (); + } + surf.Flush (); + surf.SwapBuffers (); + //surf.WriteToPng ("/mnt/data/test.png"); + + SDL.GL.MakeCurrent(hWin,hCtx); + + + Matrix4 proj = Matrix4.CreateOrthographicOffCenter (-1f, 1f, -1f, 1f, 1.0f, -1.0f); + GL.MatrixMode(MatrixMode.Projection); + GL.LoadMatrix (ref proj); + GL.MatrixMode(MatrixMode.Modelview); + GL.LoadIdentity(); + + GL.ClearColor(0.0f, 0.0f, 0.5f, 1.0f); + GL.Clear (ClearBufferMask.ColorBufferBit|ClearBufferMask.DepthBufferBit); + + GL.Viewport (0, 0, width, height); + + GL.Enable(EnableCap.DepthTest); + GL.Enable(EnableCap.Texture2D); + GL.Enable (EnableCap.Blend); + GL.BlendFunc (BlendingFactorSrc.One, BlendingFactorDest.OneMinusSrcAlpha); + + GL.BindTexture (TextureTarget.Texture2D, tex); + GL.Begin(PrimitiveType.Quads); + + // Bottom-Left + GL.TexCoord2(0, 1); + GL.Vertex2(-1, -1); + + // Upper-Left + GL.TexCoord2(0, 0); + GL.Vertex2(-1, 1); + + // Upper-Right + GL.TexCoord2(1, 0); + GL.Vertex2(1, 1); + + // Bottom-Right + GL.TexCoord2(1, 1); + GL.Vertex2(1, -1); + + GL.End(); + + //ctx.SwapBuffers (); + SDL.GL.SwapWindow (hWin); + + System.Threading.Thread.Sleep (1000); + + surf.Dispose(); + GL.DeleteTexture (tex); + dev.Dispose (); + + + SDL.GL.MakeCurrent (hWin, IntPtr.Zero); + SDL.GL.DeleteContext (hCairoCtx); + SDL.GL.DeleteContext (hCtx); + SDL.DestroyWindow (hWin); + + + + + } + } +} + diff --git a/Tests/test-sdl2.cs b/Tests/test-sdl2.cs new file mode 100644 index 00000000..d405696a --- /dev/null +++ b/Tests/test-sdl2.cs @@ -0,0 +1,159 @@ +// +// test-sdl2.cs +// +// Author: +// jp <> +// +// Copyright (c) 2013-2017 Jean-Philippe Bruyère +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using OpenTK; +using OpenTK.Graphics.OpenGL; +using OpenTK.Platform; +using Crow.SDL2; + +namespace Crow +{ + public class test_sdl2 + { + public test_sdl2 () + { + } + + static int colors = 32, depth=24, stencil=0,samples=1; + static int width=500,height=500; + + static void Main(){ + SysWMInfo sdlInfo; + + SDL.Init (SystemFlags.EVERYTHING); + + + IntPtr hWin = SDL.CreateWindow ("test sdl2", 0, 0, width, height, WindowFlags.OPENGL | WindowFlags.SHOWN); + + SDL.GL.SetAttribute (ContextAttribute.CONTEXT_MAJOR_VERSION, 3); + SDL.GL.SetAttribute (ContextAttribute.CONTEXT_MAJOR_VERSION, 3); + SDL.GL.SetAttribute (ContextAttribute.SHARE_WITH_CURRENT_CONTEXT, 1); + + IntPtr hCtx = SDL.GL.CreateContext (hWin); + IntPtr hCairoCtx = SDL.GL.CreateContext (hWin); + + SDL.GetWindowWMInfo (hWin, out sdlInfo); + SDL.GL.MakeCurrent(hWin,hCtx); + + int major, minor; + SDL.GL.GetAttribute (ContextAttribute.CONTEXT_MAJOR_VERSION, out major); + SDL.GL.GetAttribute (ContextAttribute.CONTEXT_MINOR_VERSION, out minor); + Console.WriteLine ("gl context = {0}.{1}\n", major, minor); + + Toolkit.Init(); + IWindowInfo wi = Utilities.CreateSdl2WindowInfo (hWin); + ContextHandle otkCtx = new ContextHandle (hCtx); + + OpenTK.Graphics.GraphicsContext ctx = new OpenTK.Graphics.GraphicsContext (otkCtx, wi); + + + + ctx.LoadAll(); + + Cairo.GLXDevice dev = new Cairo.GLXDevice (sdlInfo.Info.X11.Display, hCairoCtx); + + int tex = GL.GenTexture (); + GL.BindTexture (TextureTarget.Texture2D, tex); + GL.TexImage2D (TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, width, height, 0, + PixelFormat.Bgra, PixelType.UnsignedByte, IntPtr.Zero); + + //dev.Acquire (); + Cairo.GLSurface surf = new Cairo.GLSurface (dev,Cairo.Content.ColorAlpha,(uint)tex, width,height); + + SDL.GL.MakeCurrent(hWin,hCairoCtx); + using (Cairo.Context gr = new Cairo.Context (surf)) { + gr.Rectangle (150, 100, 200, 100); + gr.SetSourceRGBA (1.0, 0.0, 0.0,0.5); + gr.Fill (); + gr.Rectangle (200, 150, 200, 100); + gr.SetSourceRGBA (0.0, 1.0, 0.0,0.5); + gr.Fill (); + } + surf.Flush (); + surf.SwapBuffers (); + + SDL.GL.MakeCurrent(hWin,hCtx); + + + Matrix4 proj = Matrix4.CreateOrthographicOffCenter (-1f, 1f, -1f, 1f, 1.0f, -1.0f); + GL.MatrixMode(MatrixMode.Projection); + GL.LoadMatrix (ref proj); + GL.MatrixMode(MatrixMode.Modelview); + GL.LoadIdentity(); + + GL.ClearColor(0.0f, 0.0f, 0.5f, 1.0f); + GL.Clear (ClearBufferMask.ColorBufferBit|ClearBufferMask.DepthBufferBit); + + GL.Viewport (0, 0, width, height); + + GL.Enable(EnableCap.DepthTest); + GL.Enable(EnableCap.Texture2D); + GL.Enable (EnableCap.Blend); + GL.BlendFunc (BlendingFactorSrc.One, BlendingFactorDest.OneMinusSrcAlpha); + + GL.BindTexture (TextureTarget.Texture2D, tex); + GL.Begin(PrimitiveType.Quads); + + // Bottom-Left + GL.TexCoord2(0, 1); + GL.Vertex2(-1, -1); + + // Upper-Left + GL.TexCoord2(0, 0); + GL.Vertex2(-1, 1); + + // Upper-Right + GL.TexCoord2(1, 0); + GL.Vertex2(1, 1); + + // Bottom-Right + GL.TexCoord2(1, 1); + GL.Vertex2(1, -1); + + GL.End(); + + //ctx.SwapBuffers (); + SDL.GL.SwapWindow (hWin); + + System.Threading.Thread.Sleep (1000); + + surf.Dispose(); + GL.DeleteTexture (tex); + dev.Dispose (); + + + SDL.GL.MakeCurrent (hWin, IntPtr.Zero); + SDL.GL.DeleteContext (hCairoCtx); + SDL.GL.DeleteContext (hCtx); + SDL.DestroyWindow (hWin); + + + + + } + } +} + diff --git a/Tests/test_xcb.cs b/Tests/test_xcb.cs new file mode 100644 index 00000000..62e0a4d8 --- /dev/null +++ b/Tests/test_xcb.cs @@ -0,0 +1,145 @@ +// +// BasicTests.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 Crow; +using System.Collections.Generic; +using System.Linq; +using System.IO; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Text; +using System.Diagnostics; +using Crow.SDL2; + +using Native; + +using XCBConnection = System.IntPtr; +using XCBSetup = System.IntPtr; +using XCBScreen = System.IntPtr; +using XCBWindow = System.UInt32; +using XCBColorMap = System.UInt32; +using XCBVisualId = System.UInt32; + + +namespace Tests +{ + class test_xcb + { +// static IntPtr findVisual(XCBConnection conn, XCBVisualId visualId){ +// Xcb.GenericIterator iter = Xcb.SetupRootsIterator (Xcb.GetSetup (conn)); +// for (; iter.rem > 0; Xcb.ScreenNext(ref iter)) { +// +// Xcb.Screen screen = Marshal.PtrToStructure (iter.data); +// Xcb.GenericIterator depthIter = Xcb.ScreenAllowedDepthsIterator (ref screen); +// for (; depthIter.rem > 0; Xcb.DepthNext (ref depthIter)) { +// Xcb.Depth depth = Marshal.PtrToStructure (depthIter.data); +// Console.WriteLine ("Depth = {0}\n\tVisuals: ", depth.depth); +// Xcb.GenericIterator visualIter = Xcb.DepthVisualsIterator (ref depth); +// for (; visualIter.rem > 0; Xcb.VisualtypeNext (ref visualIter)) { +// Xcb.VisualType visual = Marshal.PtrToStructure (visualIter.data); +// Console.WriteLine ("{0}, ", visual.visual_id); +// if (visualId == visual.visual_id) +// return visualIter.data; +// } +// } +// } +// return IntPtr.Zero; +// } + + [STAThread] + static void Main () + { + XCBConnection conn = Xcb.Connect (); + + Xcb.Result res = Xcb.ConnectionHasError (conn); + + if (res != Xcb.Result.SUCCESS) + Console.WriteLine ("error"); + + IntPtr screenPtr = Xcb.SetupRootsIterator (Xcb.GetSetup (conn)).data; + XCBWindow win = Xcb.GenerateId (conn); + + Xcb.Screen scr = Marshal.PtrToStructure (screenPtr); + + int[] mask = {1,(int)(Xcb.EventMask.EXPOSURE|Xcb.EventMask.KEY_PRESS|Xcb.EventMask.BUTTON_PRESS)}; + + int maskSize =sizeof(int)*mask.Length; + + //IntPtr pMask = Marshal.AllocHGlobal(mask.Length * sizeof(uint)); + IntPtr pMask = Marshal.AllocHGlobal(sizeof(int)*mask.Length); + Marshal.Copy(mask, 0, pMask, mask.Length); + + uint result = Xcb.CreateWindow (conn, 0, win, scr.root, 10, 10, 200, 200, 1, (ushort)Xcb.WindowClass.INPUT_OUTPUT, scr.root_visual, + Xcb.Cw.OVERRIDE_REDIRECT | Xcb.Cw.EVENT_MASK, pMask); + + Marshal.FreeHGlobal(pMask); + + result = Xcb.MapWindow (conn, win); + + IntPtr visual = Xcb.FindVisual (conn, scr.root_visual); + + Console.WriteLine ("visual={0:X}", visual); + if (visual == IntPtr.Zero) + throw new Exception ("visual not found"); + + Cairo.XcbSurface surf = new Cairo.XcbSurface (conn, win, visual, 200, 200); + if (surf.Status != Cairo.Status.Success) + Console.WriteLine ("surf.status: " + surf.Status); + + bool quit = false; + + Xcb.Flush (conn); + + while (!quit) { + IntPtr pEvt = Xcb.WaitForEvent (conn); + Xcb.GenericEvent e = Marshal.PtrToStructure (pEvt); + + switch (e.response_type) { + case Xcb.EventType.EXPOSE: + using (Cairo.Context ctx = new Cairo.Context (surf)) { + ctx.SetSourceRGBA (0.0, 0.0, 1.0, 1.0); + ctx.Rectangle (10, 10, 100, 100); + ctx.Fill (); + } + surf.Flush (); + break; + case Xcb.EventType.BUTTON_PRESS: + quit = true; + break; + default: + break; + } + Xcb.Flush (conn); + } + + surf.Finish (); + surf.Dispose (); + + Xcb.Disconnect (conn); + } + } +} diff --git a/Tests/xcb.cs b/Tests/xcb.cs new file mode 100644 index 00000000..40250f48 --- /dev/null +++ b/Tests/xcb.cs @@ -0,0 +1,244 @@ +// +// xcb.cs +// +// Author: +// jp <> +// +// 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 XCBConnection = System.IntPtr; +using XCBSetup = System.IntPtr; +using XCBScreen = System.IntPtr; +using XCBWindow = System.UInt32; +using XCBColorMap = System.UInt32; +using XCBVisualId = System.UInt32; + +using System.Runtime.InteropServices; + +namespace Native +{ + + + public static class Xcb + { + + const string lib = "libxcb.so.1"; + + public enum Result { + SUCCESS = 0, + ERROR = 1, /** xcb connection errors because of socket, pipe and other stream errors. */ + EXT_NOTSUPPORTED = 2, /** xcb connection shutdown because of extension not supported */ + MEM_INSUFFICIENT = 3, /** malloc(), calloc() and realloc() error upon failure, for eg ENOMEM */ + REQ_LEN_EXCEED = 4, /** Connection closed, exceeding request length that server accepts. */ + PARSE_ERR = 5, /** Connection closed, error during parsing display string. */ + INVALID_SCREEN = 6, /** Connection closed because the server does not have a screen matching the display. */ + FDPASSING_FAILED = 7, /** Connection closed because some FD passing operation failed */ + } + public enum EventMask : uint { + NO_EVENT = 0, + KEY_PRESS = 1, + KEY_RELEASE = 2, + BUTTON_PRESS = 4, + BUTTON_RELEASE = 8, + ENTER_WINDOW = 16, + LEAVE_WINDOW = 32, + POINTER_MOTION = 64, + POINTER_MOTION_HINT = 128, + BUTTON_1_MOTION = 256, + BUTTON_2_MOTION = 512, + BUTTON_3_MOTION = 1024, + BUTTON_4_MOTION = 2048, + BUTTON_5_MOTION = 4096, + BUTTON_MOTION = 8192, + KEYMAP_STATE = 16384, + EXPOSURE = 32768, + VISIBILITY_CHANGE = 65536, + STRUCTURE_NOTIFY = 131072, + RESIZE_REDIRECT = 262144, + SUBSTRUCTURE_NOTIFY = 524288, + SUBSTRUCTURE_REDIRECT = 1048576, + FOCUS_CHANGE = 2097152, + PROPERTY_CHANGE = 4194304, + COLOR_MAP_CHANGE = 8388608, + OWNER_GRAB_BUTTON = 16777216 + } + public enum WindowClass : ushort { + COPY_FROM_PARENT = 0, + INPUT_OUTPUT = 1, + INPUT_ONLY = 2 + } + public enum Cw : uint { + BACK_PIXMAP = 1, + BACK_PIXEL = 2, + BORDER_PIXMAP = 4, + BORDER_PIXEL = 8, + BIT_GRAVITY = 16, + WIN_GRAVITY = 32, + BACKING_STORE = 64, + BACKING_PLANES = 128, + BACKING_PIXEL = 256, + OVERRIDE_REDIRECT = 512, + SAVE_UNDER = 1024, + EVENT_MASK = 2048, + DONT_PROPAGATE = 4096, + COLORMAP = 8192, + CURSOR = 16384 + } + + public enum EventType : byte { + KEY_PRESS = 2, + KEY_RELEASE = 3, + BUTTON_PRESS = 4, + BUTTON_RELEASE = 5, + MOTION_NOTIFY = 6, + ENTER_NOTIFY = 7, + LEAVE_NOTIFY = 8, + FOCUS_IN = 9, + FOCUS_OUT = 10, + KEYMAP_NOTIFY = 11, + EXPOSE = 12 + } + + [StructLayout(LayoutKind.Sequential)] + public struct GenericIterator { + public IntPtr data; /**< Data of the current iterator */ + public int rem; /**< remaining elements */ + public int index; /**< index of the current iterator */ + } + [StructLayout(LayoutKind.Sequential)] + public struct Screen { + public XCBWindow root; + public XCBColorMap default_colormap; + public uint white_pixel; + public uint black_pixel; + public uint current_input_masks; + public ushort width_in_pixels; + public ushort height_in_pixels; + public ushort width_in_millimeters; + public ushort height_in_millimeters; + public ushort min_installed_maps; + public ushort max_installed_maps; + public XCBVisualId root_visual; + public byte backing_stores; + public byte save_unders; + public byte root_depth; + public byte allowed_depths_len; + } + [StructLayout(LayoutKind.Explicit,Size=8)] +// [StructLayout(LayoutKind.Sequential)] + public struct Depth { + [FieldOffset(0)] public byte depth; + [FieldOffset(2)] public ushort visuals_len; +// public byte depth; +// public byte pad0; +// public ushort visuals_len; +// public byte pad1; +// public byte pad2; +// public byte pad3; +// public byte pad4; + } + + [StructLayout(LayoutKind.Explicit, Size=24)] + public struct VisualType { + [FieldOffset(0)]public XCBVisualId visual_id; + [FieldOffset(4)]public byte _class; + [FieldOffset(5)]public byte bits_per_rgb_value; + [FieldOffset(6)]public ushort colormap_entries; + [FieldOffset(8)]public uint red_mask; + [FieldOffset(12)]public uint green_mask; + [FieldOffset(16)]public uint blue_mask; + } + [StructLayout(LayoutKind.Explicit, Size = 36)] + public struct GenericEvent { + [FieldOffset(0)] public EventType response_type; // Type of the response + [FieldOffset(2)] public ushort sequence; // Sequence number + [FieldOffset(32)] public uint full_sequence; // full sequence + }; + +// struct GenericReply { +// byte response_type; +// byte pad0; +// UInt16 sequence; +// UInt32 length; +// } + + [DllImport(lib, EntryPoint = "xcb_connect", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + public extern static XCBConnection Connect([MarshalAs(UnmanagedType.LPStr)] string displayname = null, IntPtr screen = default(IntPtr)); + [DllImport(lib, EntryPoint = "xcb_disconnect", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + public extern static void Disconnect(XCBConnection connection); + + [DllImport(lib, EntryPoint = "xcb_connection_has_error", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + public extern static Result ConnectionHasError(XCBConnection connection); + [DllImport(lib, EntryPoint = "xcb_get_setup", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + public extern static XCBSetup GetSetup(XCBConnection connection); + [DllImport(lib, EntryPoint = "xcb_setup_roots_iterator", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + public extern static GenericIterator SetupRootsIterator (XCBSetup setup); + [DllImport(lib, EntryPoint = "xcb_generate_id", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + public extern static XCBWindow GenerateId(XCBConnection connection); + + /*xcb_void_cookie_t + xcb_create_window (xcb_connection_t *c, + uint8_t depth, + xcb_window_t wid, + xcb_window_t parent, + int16_t x, + int16_t y, + uint16_t width, + uint16_t height, + uint16_t border_width, + uint16_t _class, + xcb_visualid_t visual, + uint32_t value_mask, + const void *value_list);*/ + + [DllImport(lib, EntryPoint = "xcb_create_window", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + public extern static uint CreateWindow ( + XCBConnection conn, byte depth, XCBWindow wid, XCBWindow parent, + short x, short y, ushort width, ushort height, ushort border_width, ushort _class, + XCBVisualId visual, Cw value_mask, IntPtr value_list); + + [DllImport(lib, EntryPoint = "xcb_map_window", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + public extern static uint MapWindow (XCBConnection conn, XCBWindow window); + + [DllImport(lib, EntryPoint = "xcb_screen_next", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + public extern static void ScreenNext (ref GenericIterator iter); +// [DllImport(lib, EntryPoint = "xcb_screen_allowed_depths_length", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] +// public extern static IntPtr ScreenAllowedDepthsLength (ref Xcb.Screen screen); + [DllImport(lib, EntryPoint = "xcb_screen_allowed_depths_iterator", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + public extern static GenericIterator ScreenAllowedDepthsIterator (ref Xcb.Screen screen); + [DllImport(lib, EntryPoint = "xcb_depth_next", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + public extern static void DepthNext (ref GenericIterator iter); + [DllImport(lib, EntryPoint = "xcb_depth_visuals_iterator", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + public extern static GenericIterator DepthVisualsIterator (ref Xcb.Depth depth); + [DllImport(lib, EntryPoint = "xcb_visualtype_next", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + public extern static void VisualtypeNext (ref GenericIterator iter); + + [DllImport(lib, EntryPoint = "xcb_flush", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + public extern static int Flush(XCBConnection conn); + [DllImport(lib, EntryPoint = "xcb_wait_for_event", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + public extern static IntPtr WaitForEvent(XCBConnection conn); + + [DllImport("/mnt/devel/gts/tests/libxcb-helper.so", EntryPoint = "find_visual", CallingConvention = CallingConvention.Cdecl, ExactSpelling = true)] + public extern static IntPtr FindVisual(XCBConnection conn, XCBVisualId visualId); + } +} + diff --git a/src/GraphicObjects/GraphicObject.cs b/src/GraphicObjects/GraphicObject.cs index 41738802..f593b099 100644 --- a/src/GraphicObjects/GraphicObject.cs +++ b/src/GraphicObjects/GraphicObject.cs @@ -1120,7 +1120,7 @@ namespace Crow IsDirty = false; if (bmp != null) bmp.Dispose (); - bmp = new ImageSurface (Format.Argb32, Slot.Width, Slot.Height); + bmp = CurrentInterface.bmp.CreateSimilar(Content.ColorAlpha, Slot.Width, Slot.Height); using (Context gr = new Context (bmp)) { gr.Antialias = Interface.Antialias; onDraw (gr); diff --git a/src/Interface.cs b/src/Interface.cs index adcb2830..f79d7a2e 100644 --- a/src/Interface.cs +++ b/src/Interface.cs @@ -124,9 +124,9 @@ namespace Crow /// Graphic Tree of this interface public List GraphicTree = new List(); /// Interface's resulting bitmap - public byte[] bmp; + public Surface bmp; /// resulting bitmap limited to last redrawn part - public byte[] dirtyBmp; + public Surface dirtyBmp; /// True when host has to repaint Interface public bool IsDirty = false; /// Coordinate of the dirty bmp on the original bmp @@ -500,64 +500,62 @@ namespace Crow #if MEASURE_TIME drawingMeasure.StartCycle(); #endif - using (surf = new ImageSurface (bmp, Format.Argb32, ClientRectangle.Width, ClientRectangle.Height, ClientRectangle.Width * 4)) { - using (ctx = new Context (surf)){ - if (!clipping.IsEmpty) { - - for (int i = 0; i < clipping.NumRectangles; i++) - ctx.Rectangle(clipping.GetRectangle(i)); - ctx.ClipPreserve(); - ctx.Operator = Operator.Clear; - ctx.Fill(); - ctx.Operator = Operator.Over; - - for (int i = GraphicTree.Count -1; i >= 0 ; i--){ - GraphicObject p = GraphicTree[i]; - if (!p.Visible) - continue; - if (clipping.Contains (p.Slot) == RegionOverlap.Out) - continue; - - ctx.Save (); - p.Paint (ref ctx); - ctx.Restore (); - } - #if DEBUG_CLIP_RECTANGLE - clipping.stroke (ctx, Color.Red.AdjustAlpha(0.5)); - #endif - lock (RenderMutex) { -// Array.Copy (bmp, dirtyBmp, bmp.Length); + using (ctx = new Context (bmp)){ + if (!clipping.IsEmpty) { + + for (int i = 0; i < clipping.NumRectangles; i++) + ctx.Rectangle(clipping.GetRectangle(i)); + ctx.ClipPreserve(); + ctx.Operator = Operator.Clear; + ctx.Fill(); + ctx.Operator = Operator.Over; + + for (int i = GraphicTree.Count -1; i >= 0 ; i--){ + GraphicObject p = GraphicTree[i]; + if (!p.Visible) + continue; + if (clipping.Contains (p.Slot) == RegionOverlap.Out) + continue; + + ctx.Save (); + p.Paint (ref ctx); + ctx.Restore (); + } - IsDirty = true; - if (IsDirty) - DirtyRect += clipping.Extents; - else - DirtyRect = clipping.Extents; - - DirtyRect.Left = Math.Max (0, DirtyRect.Left); - DirtyRect.Top = Math.Max (0, DirtyRect.Top); - DirtyRect.Width = Math.Min (ClientRectangle.Width - DirtyRect.Left, DirtyRect.Width); - DirtyRect.Height = Math.Min (ClientRectangle.Height - DirtyRect.Top, DirtyRect.Height); - DirtyRect.Width = Math.Max (0, DirtyRect.Width); - DirtyRect.Height = Math.Max (0, DirtyRect.Height); - - if (DirtyRect.Width > 0 && DirtyRect.Height >0) { - dirtyBmp = new byte[4 * DirtyRect.Width * DirtyRect.Height]; - for (int y = 0; y < DirtyRect.Height; y++) { - Array.Copy (bmp, - ((DirtyRect.Top + y) * ClientRectangle.Width * 4) + DirtyRect.Left * 4, - dirtyBmp, y * DirtyRect.Width * 4, DirtyRect.Width * 4); - } + #if DEBUG_CLIP_RECTANGLE + clipping.stroke (ctx, Color.Red.AdjustAlpha(0.5)); + #endif + lock (RenderMutex) { +// Array.Copy (bmp, dirtyBmp, bmp.Length); - } else - IsDirty = false; - } - clipping.Dispose (); - clipping = new Region (); + IsDirty = true; + if (IsDirty) + DirtyRect += clipping.Extents; + else + DirtyRect = clipping.Extents; + + DirtyRect.Left = Math.Max (0, DirtyRect.Left); + DirtyRect.Top = Math.Max (0, DirtyRect.Top); + DirtyRect.Width = Math.Min (ClientRectangle.Width - DirtyRect.Left, DirtyRect.Width); + DirtyRect.Height = Math.Min (ClientRectangle.Height - DirtyRect.Top, DirtyRect.Height); + DirtyRect.Width = Math.Max (0, DirtyRect.Width); + DirtyRect.Height = Math.Max (0, DirtyRect.Height); + + if (DirtyRect.Width > 0 && DirtyRect.Height >0) { + dirtyBmp?.Dispose (); + dirtyBmp = bmp.CreateSimilar (Content.ColorAlpha, DirtyRect.Width, DirtyRect.Height); + using (Context dctx = new Context (dirtyBmp)) { + dctx.SetSourceSurface (bmp, DirtyRect.Left, DirtyRect.Top); + dctx.Paint (); + } + } else + IsDirty = false; } - //surf.WriteToPng (@"/mnt/data/test.png"); + clipping.Dispose (); + clipping = new Region (); } + //bmp.WriteToPng (@"/mnt/data/test.png"); } #if MEASURE_TIME drawingMeasure.StopCycle(); @@ -659,19 +657,10 @@ namespace Crow } #endregion - public void ProcessResize(Rectangle bounds){ - lock (UpdateMutex) { - clientRectangle = bounds; - int stride = 4 * ClientRectangle.Width; - int bmpSize = Math.Abs (stride) * ClientRectangle.Height; - bmp = new byte[bmpSize]; - dirtyBmp = new byte[bmpSize]; - - foreach (GraphicObject g in GraphicTree) - g.RegisterForLayouting (LayoutingType.All); - - RegisterClip (clientRectangle); - } + public void ProcessResize(){ + foreach (GraphicObject g in GraphicTree) + g.RegisterForLayouting (LayoutingType.All); + RegisterClip (clientRectangle); } #region Mouse and Keyboard Handling @@ -906,6 +895,7 @@ namespace Crow public Rectangle ClientRectangle { get { return clientRectangle; } + set { clientRectangle = value; } } public Interface HostContainer { get { return this; } diff --git a/src/Mono.Cairo/ImageSurface.cs b/src/Mono.Cairo/ImageSurface.cs index 98143fe8..f109718b 100644 --- a/src/Mono.Cairo/ImageSurface.cs +++ b/src/Mono.Cairo/ImageSurface.cs @@ -100,5 +100,13 @@ namespace Cairo { public int Stride { get { return NativeMethods.cairo_image_surface_get_stride (Handle); } } + + public override Surface CreateSimilar (Content content, int width, int height) + { + IntPtr p = NativeMethods.cairo_surface_create_similar ( + this.Handle, content, width, height); + + return new Cairo.ImageSurface (p, true); + } } } diff --git a/src/Mono.Cairo/Surface.cs b/src/Mono.Cairo/Surface.cs index d38b7555..cdf26d10 100644 --- a/src/Mono.Cairo/Surface.cs +++ b/src/Mono.Cairo/Surface.cs @@ -114,7 +114,7 @@ namespace Cairo { } - public Cairo.Surface CreateSimilar ( + public virtual Cairo.Surface CreateSimilar ( Cairo.Content content, int width, int height) { IntPtr p = NativeMethods.cairo_surface_create_similar (