From 60d85ba884344aa4ad638a724f11d48af758e367 Mon Sep 17 00:00:00 2001 From: jpbruyere Date: Wed, 17 May 2017 16:59:57 +0200 Subject: [PATCH] restructured classes for Linux platform --- Crow.csproj | 4 +- src/GraphicObjects/Container.cs | 55 +- src/GraphicObjects/GraphicObject.cs | 191 +----- src/GraphicObjects/Group.cs | 58 +- src/GraphicObjects/TemplatedContainer.cs | 66 -- src/GraphicObjects/TemplatedControl.cs | 96 +-- src/GraphicObjects/TemplatedGroup.cs | 59 -- src/Interface.cs | 47 +- src/Mono.Cairo/DRMDevice.cs | 53 ++ src/Mono.Cairo/DRMSurface.cs | 53 ++ src/Mono.Cairo/NativeMethods.cs | 53 ++ testDrm/src/Application.cs | 448 +++++++++++++- testDrm/src/DRMContext.cs | 5 +- testDrm/src/Egl/Context.cs | 738 +++++++++++++++++++++++ testDrm/src/Egl/EGL.cs | 257 ++++++++ testDrm/src/Egl/Surface.cs | 97 +++ testDrm/src/Linux/Bindings/Egl.cs | 22 +- testDrm/src/Linux/Bindings/Evdev.cs | 5 +- testDrm/src/Linux/Bindings/Gbm.cs | 252 ++++---- testDrm/src/Linux/Bindings/LibInput.cs | 2 +- testDrm/src/Linux/Bindings/Libc.cs | 2 +- testDrm/src/Linux/Bindings/Poll.cs | 2 +- testDrm/src/Linux/DRI.cs | 524 ++++++++++++++++ testDrm/src/Linux/DRI/Connector.cs | 190 ++++++ testDrm/src/Linux/DRI/Crtc.cs | 104 ++++ testDrm/src/Linux/DRI/Encoder.cs | 101 ++++ testDrm/src/Linux/DRI/Plane.cs | 84 +++ testDrm/src/Linux/DRI/Resources.cs | 117 ++++ testDrm/src/Linux/DRM.cs | 291 --------- testDrm/src/Linux/GBM/BufferObject.cs | 123 ++++ testDrm/src/Linux/GBM/Device.cs | 76 +++ testDrm/src/Linux/GBM/Surface.cs | 183 ++++++ testDrm/src/Linux/VT.cs | 2 +- testDrm/testDrm.csproj | 25 +- testDrm/tests.cs | 220 ++++++- testDrm/ui/menu.crow | 2 +- 36 files changed, 3621 insertions(+), 986 deletions(-) create mode 100644 src/Mono.Cairo/DRMDevice.cs create mode 100644 src/Mono.Cairo/DRMSurface.cs create mode 100644 testDrm/src/Egl/Context.cs create mode 100644 testDrm/src/Egl/EGL.cs create mode 100644 testDrm/src/Egl/Surface.cs create mode 100644 testDrm/src/Linux/DRI.cs create mode 100644 testDrm/src/Linux/DRI/Connector.cs create mode 100644 testDrm/src/Linux/DRI/Crtc.cs create mode 100644 testDrm/src/Linux/DRI/Encoder.cs create mode 100644 testDrm/src/Linux/DRI/Plane.cs create mode 100644 testDrm/src/Linux/DRI/Resources.cs delete mode 100644 testDrm/src/Linux/DRM.cs create mode 100644 testDrm/src/Linux/GBM/BufferObject.cs create mode 100644 testDrm/src/Linux/GBM/Device.cs create mode 100644 testDrm/src/Linux/GBM/Surface.cs diff --git a/Crow.csproj b/Crow.csproj index a434dc87..3e8bcd55 100644 --- a/Crow.csproj +++ b/Crow.csproj @@ -163,7 +163,6 @@ - @@ -212,6 +211,9 @@ + + + diff --git a/src/GraphicObjects/Container.cs b/src/GraphicObjects/Container.cs index aac35946..df14b8e2 100644 --- a/src/GraphicObjects/Container.cs +++ b/src/GraphicObjects/Container.cs @@ -33,7 +33,7 @@ using System.Threading; namespace Crow { - public class Container : PrivateContainer, IXmlSerializable + public class Container : PrivateContainer { #region CTOR public Container() @@ -51,59 +51,6 @@ namespace Crow { base.SetChild (_child); } - - #region IXmlSerializable - - public override System.Xml.Schema.XmlSchema GetSchema() - { - return null; - } - public override void ReadXml(System.Xml.XmlReader reader) - { - //only read attributes in GraphicObject IXmlReader implementation - base.ReadXml(reader); - - - using (System.Xml.XmlReader subTree = reader.ReadSubtree()) - { - subTree.Read(); //skip current node - subTree.Read(); //read first child - - if (!subTree.IsStartElement()) - return; - - Type t = Type.GetType("Crow." + subTree.Name); - if (t == null) { - Assembly a = Assembly.GetEntryAssembly (); - foreach (Type expT in a.GetExportedTypes ()) { - if (expT.Name == subTree.Name) { - t = expT; - break; - } - } - } - GraphicObject go = (GraphicObject)Activator.CreateInstance(t); - - (go as IXmlSerializable).ReadXml(subTree); - - SetChild(go); - - subTree.Read();//closing tag - } - } - public override void WriteXml(System.Xml.XmlWriter writer) - { - base.WriteXml(writer); - - if (Child == null) - return; - - writer.WriteStartElement(Child.GetType().Name); - (Child as IXmlSerializable).WriteXml(writer); - writer.WriteEndElement(); - } - - #endregion } } diff --git a/src/GraphicObjects/GraphicObject.cs b/src/GraphicObjects/GraphicObject.cs index bfed68b4..5de94f60 100644 --- a/src/GraphicObjects/GraphicObject.cs +++ b/src/GraphicObjects/GraphicObject.cs @@ -38,7 +38,7 @@ using System.IO; namespace Crow { - public class GraphicObject : IXmlSerializable, ILayoutable, IValueChange, ICloneable + public class GraphicObject : ILayoutable, IValueChange { internal static ulong currentUid = 0; internal ulong uid = 0; @@ -1339,195 +1339,6 @@ namespace Crow protected virtual void onLogicalParentChanged(object sender, DataSourceChangeEventArgs e) { LogicalParentChanged.Raise (this, e); } - #region IXmlSerializable - public virtual System.Xml.Schema.XmlSchema GetSchema () - { - return null; - } -// void affectMember(string name, string value){ -// Type thisType = this.GetType (); -// -// if (string.IsNullOrEmpty (value)) -// return; -// -// MemberInfo mi = thisType.GetMember (name).FirstOrDefault(); -// if (mi == null) { -// Debug.WriteLine ("XML: Unknown attribute in " + thisType.ToString() + " : " + name); -// return; -// } -// if (mi.MemberType == MemberTypes.Event) { -// this.Bindings.Add (new Binding (new MemberReference(this, mi), value)); -// return; -// } -// if (mi.MemberType == MemberTypes.Property) { -// PropertyInfo pi = mi as PropertyInfo; -// -// if (pi.GetSetMethod () == null) { -// Debug.WriteLine ("XML: Read only property in " + thisType.ToString() + " : " + name); -// return; -// } -// -// XmlAttributeAttribute xaa = (XmlAttributeAttribute)pi.GetCustomAttribute (typeof(XmlAttributeAttribute)); -// if (xaa != null) { -// if (!string.IsNullOrEmpty (xaa.AttributeName)) -// name = xaa.AttributeName; -// } -// if (value.StartsWith("{",StringComparison.Ordinal)) { -// //binding -// if (!value.EndsWith("}", StringComparison.Ordinal)) -// throw new Exception (string.Format("XML:Malformed binding: {0}", value)); -// -// this.Bindings.Add (new Binding (new MemberReference(this, pi), value.Substring (1, value.Length - 2))); -// return; -// } -// if (pi.GetCustomAttribute (typeof(XmlIgnoreAttribute)) != null) -// return; -// if (xaa == null)//not define as xmlAttribute -// return; -// -// if (pi.PropertyType == typeof(string)) { -// pi.SetValue (this, value, null); -// return; -// } -// -// if (pi.PropertyType.IsEnum) { -// pi.SetValue (this, Enum.Parse (pi.PropertyType, value), null); -// } else { -// MethodInfo me = pi.PropertyType.GetMethod ("Parse", new Type[] { typeof(string) }); -// pi.SetValue (this, me.Invoke (null, new string[] { value }), null); -// } -// } -// } - public virtual void ReadXml (System.Xml.XmlReader reader) - { - if (reader.HasAttributes) { - - style = reader.GetAttribute ("Style"); - - loadDefaultValues (); - - while (reader.MoveToNextAttribute ()) { - if (reader.Name == "Style") - continue; - - //affectMember (reader.Name, reader.Value); - } - reader.MoveToElement (); - }else - loadDefaultValues (); - } - public virtual void WriteXml (System.Xml.XmlWriter writer) - { - foreach (PropertyInfo pi in this.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance)) { - if (pi.GetSetMethod () == null) - continue; - - bool isAttribute = false; - bool hasDefaultValue = false; - bool ignore = false; - string name = ""; - object value = null; - Type valueType = null; - - - MemberInfo mi = pi.GetGetMethod (); - - if (mi == null) - continue; - - value = pi.GetValue (this, null); - valueType = pi.PropertyType; - name = pi.Name; - - - - object[] att = pi.GetCustomAttributes (false); - - foreach (object o in att) { - XmlAttributeAttribute xaa = o as XmlAttributeAttribute; - if (xaa != null) { - isAttribute = true; - if (string.IsNullOrEmpty (xaa.AttributeName)) - name = pi.Name; - else - name = xaa.AttributeName; - continue; - } - - XmlIgnoreAttribute xia = o as XmlIgnoreAttribute; - if (xia != null) { - ignore = true; - continue; - } - - DefaultValueAttribute dv = o as DefaultValueAttribute; - if (dv != null) { - if (dv.Value.Equals (value)) - hasDefaultValue = true; - if (dv.Value.ToString () == value.ToString ()) - hasDefaultValue = true; - - continue; - } - - - } - - if (hasDefaultValue || ignore || value==null) - continue; - - if (isAttribute) - writer.WriteAttributeString (name, value.ToString ()); - else { - if (valueType.GetInterface ("IXmlSerializable") == null) - continue; - - (pi.GetValue (this, null) as IXmlSerializable).WriteXml (writer); - } - } - foreach (EventInfo ei in this.GetType().GetEvents()) { - FieldInfo fi = this.GetType().GetField(ei.Name, - BindingFlags.NonPublic | - BindingFlags.Instance | - BindingFlags.GetField); - - Delegate dg = (System.Delegate)fi.GetValue (this); - - if (dg == null) - continue; - - foreach (Delegate d in dg.GetInvocationList()) { - if (!d.Method.Name.StartsWith ("<"))//Skipping empty handler, not clear it's trikky - writer.WriteAttributeString (ei.Name, d.Method.Name); - } - } - } - #endregion - - #region ICloneable implementation - public object Clone () - { - Type type = this.GetType (); - GraphicObject result = (GraphicObject)Activator.CreateInstance (type); - result.CurrentInterface = CurrentInterface; - - foreach (PropertyInfo pi in type.GetProperties(BindingFlags.Public | BindingFlags.Instance)) { - if (pi.GetSetMethod () == null) - continue; - - if (pi.GetCustomAttribute () != null) - continue; - if (pi.Name == "DataSource") - continue; - - pi.SetValue(result, pi.GetValue(this)); - } - return result; - } - #endregion - /// - /// full GraphicTree clone with binding definition - /// public override string ToString () { diff --git a/src/GraphicObjects/Group.cs b/src/GraphicObjects/Group.cs index a71c53a0..0739d480 100644 --- a/src/GraphicObjects/Group.cs +++ b/src/GraphicObjects/Group.cs @@ -35,7 +35,7 @@ using System.Reflection; namespace Crow { - public class Group : GraphicObject, IXmlSerializable + public class Group : GraphicObject { #region CTOR public Group() @@ -336,7 +336,6 @@ namespace Crow } } } - #region Mouse handling public override void checkHoverWidget (MouseMoveEventArgs e) @@ -355,60 +354,5 @@ namespace Crow base.checkHoverWidget (e); } #endregion - - - #region IXmlSerializable - - public override System.Xml.Schema.XmlSchema GetSchema() - { - return null; - } - public override void ReadXml(System.Xml.XmlReader reader) - { - base.ReadXml(reader); - - using (System.Xml.XmlReader subTree = reader.ReadSubtree()) - { - subTree.Read(); - - while (!subTree.EOF) - { - subTree.Read(); - - if (!subTree.IsStartElement()) - break; - - Type t = Type.GetType("Crow." + subTree.Name); - if (t == null) { - Assembly a = Assembly.GetEntryAssembly (); - foreach (Type expT in a.GetExportedTypes ()) { - if (expT.Name == subTree.Name) { - t = expT; - break; - } - } - } - if (t == null) - throw new Exception (subTree.Name + " type not found"); - GraphicObject go = (GraphicObject)Activator.CreateInstance(t); - (go as IXmlSerializable).ReadXml(subTree); - AddChild(go); - } - } - } - public override void WriteXml(System.Xml.XmlWriter writer) - { - base.WriteXml(writer); - - foreach (GraphicObject go in Children) - { - writer.WriteStartElement(go.GetType().Name); - (go as IXmlSerializable).WriteXml(writer); - writer.WriteEndElement(); - } - } - - #endregion - } } diff --git a/src/GraphicObjects/TemplatedContainer.cs b/src/GraphicObjects/TemplatedContainer.cs index 1ab8cf7d..b8a32167 100644 --- a/src/GraphicObjects/TemplatedContainer.cs +++ b/src/GraphicObjects/TemplatedContainer.cs @@ -57,72 +57,6 @@ namespace Crow return Content.Contains (goToFind); } #endregion - - #region IXmlSerialisation Overrides - public override void ReadXml(System.Xml.XmlReader reader) - { - using (System.Xml.XmlReader subTree = reader.ReadSubtree ()) { - subTree.Read (); - string tmp = subTree.ReadOuterXml (); - - //seek for template tag - using (XmlReader xr = new XmlTextReader (tmp, XmlNodeType.Element, null)) { - xr.Read (); - base.ReadXml (xr); - } - //process content - using (XmlReader xr = new XmlTextReader (tmp, XmlNodeType.Element, null)) { - xr.Read (); //skip current node - - while (!xr.EOF) { - xr.Read (); //read first child - - if (!xr.IsStartElement ()) - continue; - - if (xr.Name == "Template"){ - xr.Skip (); - if (!xr.IsStartElement ()) - continue; - } - - Type t = Type.GetType ("Crow." + xr.Name); - if (t == null) { - Assembly a = Assembly.GetEntryAssembly (); - foreach (Type expT in a.GetExportedTypes ()) { - if (expT.Name == xr.Name) { - t = expT; - break; - } - } - } - if (t == null) - throw new Exception (xr.Name + " type not found"); - - GraphicObject go = (GraphicObject)Activator.CreateInstance (t); - - (go as IXmlSerializable).ReadXml (xr); - - Content = go; - - xr.Read (); //closing tag - } - - } - } - } - public override void WriteXml(System.Xml.XmlWriter writer) - { - base.WriteXml(writer); - - if (Content == null) - return; - //TODO: if template is not the default one, we have to save it - writer.WriteStartElement(Content.GetType().Name); - (Content as IXmlSerializable).WriteXml(writer); - writer.WriteEndElement(); - } - #endregion } } diff --git a/src/GraphicObjects/TemplatedControl.cs b/src/GraphicObjects/TemplatedControl.cs index 082d0426..0461a8ee 100644 --- a/src/GraphicObjects/TemplatedControl.cs +++ b/src/GraphicObjects/TemplatedControl.cs @@ -37,7 +37,7 @@ using System.Reflection; namespace Crow { - public abstract class TemplatedControl : PrivateContainer, IXmlSerializable + public abstract class TemplatedControl : PrivateContainer { #region CTOR public TemplatedControl () : base() @@ -111,100 +111,6 @@ namespace Crow }else this.SetChild (template); } - - //TODO:IXmlSerializable is not used anymore - #region IXmlSerializable - public override System.Xml.Schema.XmlSchema GetSchema(){ return null; } - public override void ReadXml(System.Xml.XmlReader reader) - { - //Template could be either an attribute containing path or expressed inlined - //as a Template Element - using (System.Xml.XmlReader subTree = reader.ReadSubtree()) - { - subTree.Read (); - - string template = reader.GetAttribute ("Template"); - string tmp = subTree.ReadOuterXml (); - - //Load template from path set as attribute in templated control - if (string.IsNullOrEmpty (template)) { - //seek for template tag first - using (XmlReader xr = new XmlTextReader (tmp, XmlNodeType.Element, null)) { - //load template first if inlined - - xr.Read (); //read first child - xr.Read (); //skip root node - - while (!xr.EOF) { - if (!xr.IsStartElement ()) { - xr.Read (); - continue; - } - if (xr.Name == "ItemTemplate") { - string dataType = "default", datas = "", itemTmp; - while (xr.MoveToNextAttribute ()) { - if (xr.Name == "DataType") - dataType = xr.Value; - else if (xr.Name == "Data") - datas = xr.Value; - } - xr.MoveToElement (); - itemTmp = xr.ReadInnerXml (); - -// if (ItemTemplates == null) -// ItemTemplates = new Dictionary (); -// -// using (IMLReader iTmp = new IMLReader (null, itemTmp)) { -// ItemTemplates [dataType] = -// new ItemTemplate (iTmp.RootType, iTmp.GetLoader (), dataType, datas); -// } -// if (!string.IsNullOrEmpty (datas)) -// ItemTemplates [dataType].CreateExpandDelegate(this); - - continue; - } - if (xr.Name == "Template") { - xr.Read (); - - Type t = Type.GetType ("Crow." + xr.Name); - if (t == null) { - Assembly a = Assembly.GetEntryAssembly (); - foreach (Type expT in a.GetExportedTypes ()) { - if (expT.Name == xr.Name) { - t = expT; - break; - } - } - } - GraphicObject go = (GraphicObject)Activator.CreateInstance (t); - (go as IXmlSerializable).ReadXml (xr); - - loadTemplate (go); - continue; - } - xr.ReadInnerXml (); - } - } - } else - loadTemplate (CurrentInterface.Load (template)); - - //if no template found, load default one - if (this.child == null) - loadTemplate (); - - //normal xml read - using (XmlReader xr = new XmlTextReader (tmp, XmlNodeType.Element, null)) { - xr.Read (); - base.ReadXml(xr); - } - } - } - public override void WriteXml(System.Xml.XmlWriter writer) - { - //TODO: - throw new NotImplementedException(); - } - #endregion } } diff --git a/src/GraphicObjects/TemplatedGroup.cs b/src/GraphicObjects/TemplatedGroup.cs index e4447168..eea3a184 100644 --- a/src/GraphicObjects/TemplatedGroup.cs +++ b/src/GraphicObjects/TemplatedGroup.cs @@ -267,65 +267,6 @@ namespace Crow // } #endregion - #region IXmlSerialisation Overrides - public override void ReadXml(System.Xml.XmlReader reader) - { - using (System.Xml.XmlReader subTree = reader.ReadSubtree ()) { - subTree.Read (); - string tmp = subTree.ReadOuterXml (); - - //seek for template tag - using (XmlReader xr = new XmlTextReader (tmp, XmlNodeType.Element, null)) { - xr.Read (); - base.ReadXml (xr); - } - //process content - using (XmlReader xr = new XmlTextReader (tmp, XmlNodeType.Element, null)) { - xr.Read (); //skip current node - - while (!xr.EOF) { - xr.Read (); //read first child - - if (!xr.IsStartElement ()) - continue; - - if (xr.Name == "Template" || Name == "ItemTemplate"){ - xr.Skip (); - if (!xr.IsStartElement ()) - continue; - } - - Type t = Type.GetType ("Crow." + xr.Name); - if (t == null) { - Assembly a = Assembly.GetEntryAssembly (); - foreach (Type expT in a.GetExportedTypes ()) { - if (expT.Name == xr.Name) { - t = expT; - break; - } - } - } - if (t == null) - throw new Exception (xr.Name + " type not found"); - - GraphicObject go = (GraphicObject)Activator.CreateInstance (t); - - (go as IXmlSerializable).ReadXml (xr); - - AddItem (go); - - xr.Read (); //closing tag - } - - } - } - } - public override void WriteXml(System.Xml.XmlWriter writer) - { - throw new NotImplementedException (); - } - #endregion - void loading(){ if (ItemTemplates == null) ItemTemplates = new Dictionary (); diff --git a/src/Interface.cs b/src/Interface.cs index 6c7d99c4..df6a5c67 100644 --- a/src/Interface.cs +++ b/src/Interface.cs @@ -511,30 +511,30 @@ namespace Crow clipping.stroke (ctx, Color.Red.AdjustAlpha(0.5)); #endif lock (RenderMutex) { - Array.Copy (bmp, dirtyBmp, bmp.Length); +// Array.Copy (bmp, dirtyBmp, bmp.Length); IsDirty = true; -// if (IsDirty) -// DirtyRect += clipping.Bounds; -// else -// DirtyRect = clipping.Bounds; -// -// 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); -// } -// -// } else -// IsDirty = false; + if (IsDirty) + DirtyRect += clipping.Bounds; + else + DirtyRect = clipping.Bounds; + + 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); + } + + } else + IsDirty = false; } clipping.Reset (); } @@ -644,7 +644,6 @@ namespace Crow 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]; diff --git a/src/Mono.Cairo/DRMDevice.cs b/src/Mono.Cairo/DRMDevice.cs new file mode 100644 index 00000000..a03195fb --- /dev/null +++ b/src/Mono.Cairo/DRMDevice.cs @@ -0,0 +1,53 @@ +// +// Mono.Cairo.Device.cs +// +// Authors: +// JP Bruyère (jp_bruyere@hotmail.com) +// +// This is an OO wrapper API for the Cairo API +// +// Copyright (C) 2016 JP Bruyère +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +using System; + +namespace Cairo +{ + public class DRMDevice : Device + { + public DRMDevice () : base (NativeMethods.cairo_drm_device_default (), true) + { + } + public DRMDevice (int fd) : base (NativeMethods.cairo_drm_device_get_for_fd (fd), true) + { + } + public DRMDevice (IntPtr udev_device) : base (NativeMethods.cairo_drm_device_get (udev_device), true) + { + } + + public int FileDescriptor { + get { return NativeMethods.cairo_drm_device_get_fd (Handle); } + } + + public void DeviceThrottle () { NativeMethods.cairo_drm_device_throttle (Handle);} + } +} + diff --git a/src/Mono.Cairo/DRMSurface.cs b/src/Mono.Cairo/DRMSurface.cs new file mode 100644 index 00000000..248541c7 --- /dev/null +++ b/src/Mono.Cairo/DRMSurface.cs @@ -0,0 +1,53 @@ +// +// Mono.Cairo.GLSurface.cs +// +// Authors: +// JP Bruyère (jp_bruyere@hotmail.com) +// +// This is an OO wrapper API for the Cairo API +// +// Copyright (C) 2016 JP Bruyère +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// + +using System; + +namespace Cairo { + + public class DRMSurface : Surface + { + + public DRMSurface (IntPtr ptr, bool own) : base (ptr, own) + {} + + public DRMSurface (DRMDevice device, Format format, int width, int height) + : base (NativeMethods.cairo_drm_surface_create (device.Handle, format, width, height), true) + {} + + public DRMSurface (DRMDevice device, uint name, Format format, int width, int height, int stride) + : base (NativeMethods.cairo_drm_surface_create_for_name (device.Handle, name, format, width, height, stride), true) + {} + + public DRMSurface (DRMDevice device, IntPtr imageSurface) + : base (NativeMethods.cairo_drm_surface_create_from_cacheable_image (device.Handle, imageSurface), true) + {} + } +} diff --git a/src/Mono.Cairo/NativeMethods.cs b/src/Mono.Cairo/NativeMethods.cs index 9726cb8c..ab36a40c 100644 --- a/src/Mono.Cairo/NativeMethods.cs +++ b/src/Mono.Cairo/NativeMethods.cs @@ -925,6 +925,59 @@ namespace Cairo internal static extern IntPtr cairo_gl_surface_create_for_egl (IntPtr device, IntPtr eglSurface, int width, int height); #endregion + #region DRM Functions + [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)] + internal static extern IntPtr cairo_drm_device_get (IntPtr udev_device); + + [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)] + internal static extern IntPtr cairo_drm_device_get_for_fd (int fd); + + [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)] + internal static extern IntPtr cairo_drm_device_default (); + + [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)] + internal static extern int cairo_drm_device_get_fd (IntPtr cairo_device); + + [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)] + internal static extern void cairo_drm_device_throttle (IntPtr cairo_device); + + [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)] + internal static extern IntPtr cairo_drm_surface_create (IntPtr cairo_device, Format format, int width, int height); + + [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)] + internal static extern IntPtr cairo_drm_surface_create_for_name (IntPtr cairo_device, uint name, Format format, int width, int height, int stride); + + [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)] + internal static extern IntPtr cairo_drm_surface_create_from_cacheable_image (IntPtr cairo_device, IntPtr imageSurface); + + [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)] + internal static extern Status cairo_drm_surface_enable_scan_out (IntPtr drmSurface); + + [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)] + internal static extern IntPtr cairo_drm_surface_get_handle (IntPtr drmSurface); + + [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)] + internal static extern IntPtr cairo_drm_surface_get_name (IntPtr drmSurface); + + [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)] + internal static extern Format cairo_drm_surface_get_format (IntPtr drmSurface); + + [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)] + internal static extern int cairo_drm_surface_get_width (IntPtr drmSurface); + + [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)] + internal static extern int cairo_drm_surface_get_height (IntPtr drmSurface); + + [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)] + internal static extern int cairo_drm_surface_get_stride (IntPtr drmSurface); + + [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)] + internal static extern IntPtr cairo_drm_surface_map_to_image (IntPtr drmSurface); + + [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)] + internal static extern void cairo_drm_surface_unmap (IntPtr drmSurface, IntPtr imageSurface); + #endregion + #region Device [DllImport (cairo, CallingConvention=CallingConvention.Cdecl)] internal static extern IntPtr cairo_device_reference (IntPtr device); diff --git a/testDrm/src/Application.cs b/testDrm/src/Application.cs index 63edaae8..43330e03 100644 --- a/testDrm/src/Application.cs +++ b/testDrm/src/Application.cs @@ -24,20 +24,28 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. using System; -using OpenTK.Platform.Linux; -using OpenTK; using System.IO; using System.Collections.Generic; using System.Diagnostics; using System.Runtime.InteropServices; using System.Threading; -namespace Crow.Linux +using VT = Linux.VT; +using DRI = Linux.DRI; + +using Linux; +using System.Text; +using OpenTK.Platform.Linux; + +namespace Crow { public class Application : IDisposable - { - DRMContext drm; + { + DRI.GPUControler gpu; + Cairo.GLSurface cairoSurf; + public Interface CrowInterface; + public bool mouseIsInInterface = false; void interfaceThread() @@ -50,36 +58,444 @@ namespace Crow.Linux Thread.Sleep (1); } } +// + Crow.XCursor cursor; + int previousVT = -1, appVT = -1; +// + public Application(){ + + if (Kernel.signal (Signal.SIGUSR1, switch_request_handle) < 0) + throw new Exception ("signal handler registation failed"); + if (Kernel.signal (Signal.SIGINT, sigint_handler) < 0) + throw new Exception ("SIGINT handler registation failed"); + + using (VT.VTControler master = new VT.VTControler ()) { + previousVT = master.CurrentVT; + appVT = master.FirstAvailableVT; + master.SwitchTo (appVT); + try { + master.KDMode = VT.KDMode.GRAPHICS; + } catch (Exception ex) { + Console.WriteLine (ex.ToString ()); + } + } + + gpu = new DRI.GPUControler(); + cairoSurf = gpu.CairoSurf; + cursor = Crow.XCursorFile.Load("#Crow.Images.Icons.Cursors.arrow").Cursors[0]; - public Application(){ - drm = new DRMContext(); CrowInterface = new Interface (); - drm.CrowInterface = CrowInterface; Thread t = new Thread (interfaceThread); t.IsBackground = true; t.Start (); - CrowInterface.ProcessResize (new Size (drm.width, drm.height)); - drm.updateCursor (XCursor.Default); + initInput (); + + CrowInterface.ProcessResize (new Size (gpu.Width, gpu.Height)); + gpu.updateCursor (cursor); + //CrowInterface.MouseCursorChanged += CrowInterface_MouseCursorChanged; + } + void switch_request_handle (Signal s){ + Console.WriteLine ("switch request catched: " + s.ToString()); + using (VT.VTControler master = new VT.VTControler ()) { + Libc.write (master.fd, Encoding.ASCII.GetBytes ("this is a test string")); + master.AcknoledgeSwitchRequest (); + } + } + void sigint_handler (Signal s){ + Console.WriteLine ("SIGINT catched"); + //Running = false; + } +// void CrowInterface_MouseCursorChanged (object sender, MouseCursorChangedEventArgs e) +// { +// gpu.updateCursor (e.NewCursor); +// } + + public GraphicObject Load (string path){ + return CrowInterface.LoadInterface (path); + } + public virtual void Run (){ + updateCrow (); + } + + public void updateCrow (){ + bool update = false; + + if (updateMousePos) { + lock (Sync) { + updateMousePos = false; + gpu.moveCursor ((uint)MouseX - 8, (uint)MouseY - 4); + } + } + +// using (Cairo.Context ctx = new Cairo.Context (cairoSurf)) { +// ctx.Rectangle (0, 0, gpu.Width, gpu.Height); +// ctx.SetSourceRGB (0, 0, 0.1); +// ctx.Fill (); +// } + if (Monitor.TryEnter (CrowInterface.RenderMutex)) { + if (CrowInterface.IsDirty) { + CrowInterface.IsDirty = false; + update = true; + Rectangle r = CrowInterface.DirtyRect; + using (Cairo.Context ctx = new Cairo.Context (cairoSurf)) { + using (Cairo.Surface d = new Cairo.ImageSurface (CrowInterface.dirtyBmp, Cairo.Format.ARGB32, + r.Width, r.Height, r.Width * 4)) { + ctx.SetSourceSurface (d, 0, 0); + ctx.Operator = Cairo.Operator.Source; + ctx.Paint (); + } + } + } + Monitor.Exit (CrowInterface.RenderMutex); + } + +// if (!update) +// return; +// update = false; + + cairoSurf.Flush (); + cairoSurf.SwapBuffers (); + + gpu.Update (); + } + + + #region INPUT + Thread input_thread; + long exit; - CrowInterface.MouseCursorChanged += CrowInterface_MouseCursorChanged; + static readonly object Sync = new object(); + static readonly Crow.Key[] KeyMap = Evdev.KeyMap; + static long DeviceFDCount; + + IntPtr udev; + IntPtr input_context; + + int input_fd = 0; + + InputInterface input_interface = new InputInterface( + OpenRestricted, CloseRestricted); + static CloseRestrictedCallback CloseRestricted = CloseRestrictedHandler; + static void CloseRestrictedHandler(int fd, IntPtr data) + { + Debug.Print("[Input] Closing fd {0}", fd); + int ret = Libc.close(fd); + + if (ret < 0) + { + Debug.Print("[Input] Failed to close fd {0}. Error: {1}", fd, ret); + } + else + { + Interlocked.Decrement(ref DeviceFDCount); + } } - void CrowInterface_MouseCursorChanged (object sender, MouseCursorChangedEventArgs e) + static OpenRestrictedCallback OpenRestricted = OpenRestrictedHandler; + static int OpenRestrictedHandler(IntPtr path, int flags, IntPtr data) { - drm.updateCursor (e.NewCursor); + int fd = Libc.open(path, (OpenFlags)flags); + Debug.Print("[Input] Opening '{0}' with flags {1}. fd:{2}", + Marshal.PtrToStringAnsi(path), (OpenFlags)flags, fd); + + if (fd >= 0) + { + Interlocked.Increment(ref DeviceFDCount); + } + + return fd; } - public void Run (){ - drm.Run (); + void initInput (){ + Semaphore ready = new Semaphore(0, 1); + input_thread = new Thread (InputThreadLoop); + input_thread.IsBackground = true; + input_thread.Start(ready); } + void InputThreadLoop(object semaphore) + { + Debug.Print("[Input] Running on thread {0}", Thread.CurrentThread.ManagedThreadId); + Setup(); + + // Inform the parent thread that initialization has completed successfully + (semaphore as Semaphore).Release(); + Debug.Print("[Input] Released main thread.", input_context); + + // Use a blocking poll for input messages, in order to reduce CPU usage + PollFD poll_fd = new PollFD(); + poll_fd.fd = input_fd; + poll_fd.events = PollFlags.In; + Debug.Print("[Input] Created PollFD({0}, {1})", poll_fd.fd, poll_fd.events); + + Debug.Print("[Input] Entering input loop.", poll_fd.fd, poll_fd.events); + while (Interlocked.Read(ref exit) == 0) + { + //drmTimeOut.Restart (); + + int ret = Libc.poll(ref poll_fd, 1, -1); + ErrorNumber error = (ErrorNumber)Marshal.GetLastWin32Error(); + bool is_error = + ret < 0 && !(error == ErrorNumber.Again || error == ErrorNumber.Interrupted) || + (poll_fd.revents & (PollFlags.Hup | PollFlags.Error | PollFlags.Invalid)) != 0; + + if (ret > 0 && (poll_fd.revents & (PollFlags.In | PollFlags.Pri)) != 0) + ProcessEvents(input_context); + + if (is_error) + { + Debug.Print("[Input] Exiting input loop {0} due to poll error [ret:{1} events:{2}]. Error: {3}.", + input_thread.ManagedThreadId, ret, poll_fd.revents, error); + Interlocked.Increment(ref exit); + } + } + Debug.Print("[Input] Exited input loop.", poll_fd.fd, poll_fd.events); + } + + void Setup() + { + // Todo: add static path fallback when udev is not installed. + udev = Udev.New(); + if (udev == IntPtr.Zero) + { + Debug.Print("[Input] Udev.New() failed."); + Interlocked.Increment(ref exit); + return; + } + Debug.Print("[Input] Udev.New() = {0:x}", udev); + + input_context = LibInput.CreateContext(input_interface, IntPtr.Zero, udev); + if (input_context == IntPtr.Zero) + { + Debug.Print("[Input] LibInput.CreateContext({0:x}) failed.", udev); + Interlocked.Increment(ref exit); + return; + } + Debug.Print("[Input] LibInput.CreateContext({0:x}) = {1:x}", udev, input_context); + + string seat_id = "seat0"; + int seat_assignment = LibInput.AssignSeat(input_context, seat_id); + if (seat_assignment == -1) + { + Debug.Print("[Input] LibInput.AssignSeat({0:x}) = {1} failed.", input_context, seat_id); + Interlocked.Increment(ref exit); + return; + } + Debug.Print("[Input] LibInput.AssignSeat({0:x}) = {1}", input_context, seat_id); + + input_fd = LibInput.GetFD(input_context); + if (input_fd < 0) + { + Debug.Print("[Input] LibInput.GetFD({0:x}) failed.", input_context); + Interlocked.Increment(ref exit); + return; + } + Debug.Print("[Input] LibInput.GetFD({0:x}) = {1}.", input_context, input_fd); + + ProcessEvents(input_context); + LibInput.Resume(input_context); + Debug.Print("[Input] LibInput.Resume({0:x})", input_context); + + if (Interlocked.Read(ref DeviceFDCount) <= 0) + { + Debug.Print("[Error] Failed to open any input devices."); + Debug.Print("[Error] Ensure that you have access to '/dev/input/event*'."); + Interlocked.Increment(ref exit); + } + } + + void ProcessEvents(IntPtr input_context) + { + // Process all events in the event queue + while (true) + { + // Data available + int ret = LibInput.Dispatch(input_context); + if (ret != 0) + { + Debug.Print("[Input] LibInput.Dispatch({0:x}) failed. Error: {1}", + input_context, ret); + break; + } + + IntPtr pevent = LibInput.GetEvent(input_context); + if (pevent == IntPtr.Zero) + { + break; + } + + IntPtr device = LibInput.GetDevice(pevent); + InputEventType type = LibInput.GetEventType(pevent); + + lock (Sync) + { + switch (type) + { + // case InputEventType.DeviceAdded: + // HandleDeviceAdded(input_context, device); + // break; + // + // case InputEventType.DeviceRemoved: + // HandleDeviceRemoved(input_context, device); + // break; + // + case InputEventType.KeyboardKey: + //run = false; + handleKeyboard(LibInput.GetKeyboardEvent(pevent)); + break; + // + // case InputEventType.PointerAxis: + // HandlePointerAxis(GetMouse(device), LibInput.GetPointerEvent(pevent)); + // break; + // + case InputEventType.PointerButton: + handlePointerButton (LibInput.GetPointerEvent(pevent)); + break; + + case InputEventType.PointerMotion: + handlePointerMotion (LibInput.GetPointerEvent(pevent)); + break; + + // case InputEventType.PointerMotionAbsolute: + // HandlePointerMotionAbsolute(GetMouse(device), LibInput.GetPointerEvent(pevent)); + // break; + } + } + + LibInput.DestroyEvent(pevent); + } + } + int MouseX = 0, MouseY = 0; + volatile bool updateMousePos = true; + + int roundDelta (double d){ + return d > 0 ? (int)Math.Ceiling(d) : (int)Math.Floor (d); + } + + void handlePointerMotion(PointerEvent e) + { + MouseX += roundDelta (e.DeltaX); + MouseY += roundDelta (e.DeltaY); + + Rectangle bounds = CrowInterface.ClientRectangle; + if (MouseX < bounds.Left) + MouseX = bounds.Left; + else if (MouseX > bounds.Right) + MouseX = bounds.Right; + + if (MouseY < bounds.Top) + MouseY = bounds.Top; + else if (MouseY > bounds.Bottom) + MouseY = bounds.Bottom; + + CrowInterface.ProcessMouseMove (MouseX, MouseY); + + updateMousePos = true; + } + void handlePointerButton (PointerEvent e) + { + int but = 0; + switch (e.Button) { + case EvdevButton.LEFT: + but = 0; + break; + case EvdevButton.MIDDLE: + but = 1; + break; + case EvdevButton.RIGHT: + but = 2; + break; + } + if (e.ButtonState == global::Linux.ButtonState.Pressed) + CrowInterface.ProcessMouseButtonDown (but); + else + CrowInterface.ProcessMouseButtonUp (but); + } + + KeyModifiers curModifiers = KeyModifiers.None; + + void handleKeyboard(KeyboardEvent e) + { + return; + int key = (int)Evdev.KeyMap [e.Key]; + Key k = (Key)key; + if (e.KeyState == KeyState.Pressed) { + CrowInterface.ProcessKeyDown (key); + switch (k) { + case Key.ShiftLeft: + case Key.ShiftRight: + curModifiers |= KeyModifiers.Shift; + break; + case Key.ControlLeft: + case Key.ControlRight: + curModifiers |= KeyModifiers.Control; + break; + case Key.AltLeft: + curModifiers |= KeyModifiers.Alt; + break; + case Key.AltRight: + curModifiers |= KeyModifiers.AltGr; + break; + } + }else { + CrowInterface.ProcessKeyUp (key); + switch (k) { + case Key.ShiftLeft: + case Key.ShiftRight: + curModifiers &= ~KeyModifiers.Shift; + break; + case Key.ControlLeft: + case Key.ControlRight: + curModifiers &= ~KeyModifiers.Control; + break; + case Key.AltLeft: + curModifiers &= ~KeyModifiers.Alt; + break; + case Key.AltRight: + curModifiers &= ~KeyModifiers.AltGr; + break; + } +// if (!keymap.ContainsKey (curModifiers)) { +// Console.WriteLine ("keymap not found for: " + curModifiers + " " + (int)curModifiers); +// return; +// } + // string tmp = keymap [curModifiers] [e.Key]; + // if (string.IsNullOrEmpty (tmp)) + // return; + // if (char.IsControl (tmp[0])) + // return; + // CrowInterface.ProcessKeyPress (tmp [0]); + } + } + + #endregion + #region IDisposable implementation + ~Application(){ + Dispose (false); + } public void Dispose () { - drm.Dispose (); + Dispose (true); + GC.SuppressFinalize (this); + } + protected virtual void Dispose (bool disposing){ + if (gpu != null) + gpu.Dispose (); + gpu = null; + + using (VT.VTControler master = new VT.VTControler ()) { + // try { + // master.KDMode = VT.KDMode.TEXT; + // } catch (Exception ex) { + // Console.WriteLine (ex.ToString ()); + // } + master.SwitchTo (previousVT); + } + } #endregion } diff --git a/testDrm/src/DRMContext.cs b/testDrm/src/DRMContext.cs index 720d4ed9..07e3bbff 100644 --- a/testDrm/src/DRMContext.cs +++ b/testDrm/src/DRMContext.cs @@ -33,7 +33,7 @@ using OpenTK; using OpenTK.Platform.Linux; using System.IO.Compression; -namespace Crow.Linux +namespace Linux { internal class DRMContext : IDisposable @@ -173,6 +173,7 @@ namespace Crow.Linux unsafe void initEgl () { int major, minor; IntPtr[] configs = new IntPtr[1]; + int[] contextAttrib = new int[] { Egl.CONTEXT_CLIENT_VERSION, 2, Egl.NONE @@ -223,6 +224,7 @@ namespace Crow.Linux // See what we really got int r, g, b, a, d, s, sample_buffers, samples; IntPtr active_config = configs[0]; + Egl.GetConfigAttrib(egl_display, active_config, Egl.RED_SIZE, out r); Egl.GetConfigAttrib(egl_display, active_config, Egl.GREEN_SIZE, out g); Egl.GetConfigAttrib(egl_display, active_config, Egl.BLUE_SIZE, out b); @@ -407,6 +409,7 @@ namespace Crow.Linux Drm.HandleEvent (fd_gpu, ref evctx); else break; + Thread.Sleep (1); } if (is_flip_queued != 0) Console.WriteLine ("flip canceled"); diff --git a/testDrm/src/Egl/Context.cs b/testDrm/src/Egl/Context.cs new file mode 100644 index 00000000..122f2e72 --- /dev/null +++ b/testDrm/src/Egl/Context.cs @@ -0,0 +1,738 @@ +// +// Context.cs +// +// Author: +// Jean-Philippe Bruyère +// +// Copyright (c) 2013-2017 Jean-Philippe Bruyère +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using System.Runtime.InteropServices; +using Linux; +using GBM = Linux.GBM; + +namespace EGL +{ + using EGLNativeDisplayType = IntPtr; + using EGLNativeWindowType = IntPtr; + using EGLNativePixmapType = IntPtr; + using EGLConfig = IntPtr; + using EGLContext = IntPtr; + using EGLDisplay = IntPtr; + using EGLSurface = IntPtr; + using EGLClientBuffer = IntPtr; + + public enum RenderApi + { + ES = Egl.OPENGL_ES_API, + GL = Egl.OPENGL_API, + VG = Egl.OPENVG_API + } + [Flags]public enum RenderableFlags + { + ES = Egl.OPENGL_ES_BIT, + ES2 = Egl.OPENGL_ES2_BIT, + ES3 = Egl.OPENGL_ES3_BIT, + GL = Egl.OPENGL_BIT, + VG = Egl.OPENVG_BIT, + } + public enum ErrorCode + { + SUCCESS = 12288, + NOT_INITIALIZED = 12289, + BAD_ACCESS = 12290, + BAD_ALLOC = 12291, + BAD_ATTRIBUTE = 12292, + BAD_CONFIG = 12293, + BAD_CONTEXT = 12294, + BAD_CURRENT_SURFACE = 12295, + BAD_DISPLAY = 12296, + BAD_MATCH = 12297, + BAD_NATIVE_PIXMAP = 12298, + BAD_NATIVE_WINDOW = 12299, + BAD_PARAMETER = 12300, + BAD_SURFACE = 12301, + CONTEXT_LOST = 12302, + } + + #region consts + public static class Egl { + public const int VERSION_1_0 = 1; + public const int VERSION_1_1 = 1; + public const int VERSION_1_2 = 1; + public const int VERSION_1_3 = 1; + public const int VERSION_1_4 = 1; + public const int FALSE = 0; + public const int TRUE = 1; + public const int DONT_CARE = -1; + public const int CONTEXT_LOST = 12302; + public const int BUFFER_SIZE = 12320; + public const int ALPHA_SIZE = 12321; + public const int BLUE_SIZE = 12322; + public const int GREEN_SIZE = 12323; + public const int RED_SIZE = 12324; + public const int DEPTH_SIZE = 12325; + public const int STENCIL_SIZE = 12326; + public const int CONFIG_CAVEAT = 12327; + public const int CONFIG_ID = 12328; + public const int LEVEL = 12329; + public const int MAX_PBUFFER_HEIGHT = 12330; + public const int MAX_PBUFFER_PIXELS = 12331; + public const int MAX_PBUFFER_WIDTH = 12332; + public const int NATIVE_RENDERABLE = 12333; + public const int NATIVE_VISUAL_ID = 12334; + public const int NATIVE_VISUAL_TYPE = 12335; + public const int PRESERVED_RESOURCES = 12336; + public const int SAMPLES = 12337; + public const int SAMPLE_BUFFERS = 12338; + public const int SURFACE_TYPE = 12339; + public const int TRANSPARENT_TYPE = 12340; + public const int TRANSPARENT_BLUE_VALUE = 12341; + public const int TRANSPARENT_GREEN_VALUE = 12342; + public const int TRANSPARENT_RED_VALUE = 12343; + public const int NONE = 12344; + public const int BIND_TO_TEXTURE_RGB = 12345; + public const int BIND_TO_TEXTURE_RGBA = 12346; + public const int MIN_SWAP_INTERVAL = 12347; + public const int MAX_SWAP_INTERVAL = 12348; + public const int LUMINANCE_SIZE = 12349; + public const int ALPHA_MASK_SIZE = 12350; + public const int COLOR_BUFFER_TYPE = 12351; + public const int RENDERABLE_TYPE = 12352; + public const int MATCH_NATIVE_PIXMAP = 12353; + public const int CONFORMANT = 12354; + public const int SLOW_CONFIG = 12368; + public const int NON_CONFORMANT_CONFIG = 12369; + public const int TRANSPARENT_RGB = 12370; + public const int RGB_BUFFER = 12430; + public const int LUMINANCE_BUFFER = 12431; + public const int NO_TEXTURE = 12380; + public const int TEXTURE_RGB = 12381; + public const int TEXTURE_RGBA = 12382; + public const int TEXTURE_2D = 12383; + public const int PBUFFER_BIT = 1; + public const int PIXMAP_BIT = 2; + public const int WINDOW_BIT = 4; + public const int VG_COLORSPACE_LINEAR_BIT = 32; + public const int VG_ALPHA_FORMAT_PRE_BIT = 64; + public const int MULTISAMPLE_RESOLVE_BOX_BIT = 512; + public const int SWAP_BEHAVIOR_PRESERVED_BIT = 1024; + public const int OPENGL_ES_BIT = 1; + public const int OPENVG_BIT = 2; + public const int OPENGL_ES2_BIT = 4; + public const int OPENGL_BIT = 8; + public const int OPENGL_ES3_BIT = 64; + public const int VENDOR = 12371; + public const int VERSION = 12372; + public const int EXTENSIONS = 12373; + public const int CLIENT_APIS = 12429; + public const int HEIGHT = 12374; + public const int WIDTH = 12375; + public const int LARGEST_PBUFFER = 12376; + public const int TEXTURE_FORMAT = 12416; + public const int TEXTURE_TARGET = 12417; + public const int MIPMAP_TEXTURE = 12418; + public const int MIPMAP_LEVEL = 12419; + public const int RENDER_BUFFER = 12422; + public const int VG_COLORSPACE = 12423; + public const int VG_ALPHA_FORMAT = 12424; + public const int HORIZONTAL_RESOLUTION = 12432; + public const int VERTICAL_RESOLUTION = 12433; + public const int PIXEL_ASPECT_RATIO = 12434; + public const int SWAP_BEHAVIOR = 12435; + public const int MULTISAMPLE_RESOLVE = 12441; + public const int BACK_BUFFER = 12420; + public const int SINGLE_BUFFER = 12421; + public const int VG_COLORSPACE_sRGB = 12425; + public const int VG_COLORSPACE_LINEAR = 12426; + public const int VG_ALPHA_FORMAT_NONPRE = 12427; + public const int VG_ALPHA_FORMAT_PRE = 12428; + public const int DISPLAY_SCALING = 10000; + public const int UNKNOWN = -1; + public const int BUFFER_PRESERVED = 12436; + public const int BUFFER_DESTROYED = 12437; + public const int OPENVG_IMAGE = 12438; + public const int CONTEXT_CLIENT_TYPE = 12439; + public const int CONTEXT_CLIENT_VERSION = 12440; + public const int MULTISAMPLE_RESOLVE_DEFAULT = 12442; + public const int MULTISAMPLE_RESOLVE_BOX = 12443; + public const int OPENGL_ES_API = 12448; + public const int OPENVG_API = 12449; + public const int OPENGL_API = 12450; + public const int DRAW = 12377; + public const int READ = 12378; + public const int CORE_NATIVE_ENGINE = 12379; + public const int COLORSPACE = VG_COLORSPACE; + public const int ALPHA_FORMAT = VG_ALPHA_FORMAT; + public const int COLORSPACE_sRGB = VG_COLORSPACE_sRGB; + public const int COLORSPACE_LINEAR = VG_COLORSPACE_LINEAR; + public const int ALPHA_FORMAT_NONPRE = VG_ALPHA_FORMAT_NONPRE; + public const int ALPHA_FORMAT_PRE = VG_ALPHA_FORMAT_PRE; + + // EGL_ANGLE_d3d_share_handle_client_buffer + public const int D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE = 0x3200; + // EGL_ANGLE_window_fixed_size + public const int FIXED_SIZE_ANGLE = 0x3201; + // EGL_ANGLE_query_surface_pointer + [DllImport("libEGL.dll", EntryPoint = "eglQuerySurfacePointerANGLE")] + public static extern bool QuerySurfacePointerANGLE(EGLDisplay display, EGLSurface surface, int attribute, out IntPtr value); + // EGL_ANGLE_software_display + public static readonly EGLNativeDisplayType SOFTWARE_DISPLAY_ANGLE = new EGLNativeDisplayType(-1); + // EGL_ANGLE_direct3d_display + public static readonly EGLNativeDisplayType D3D11_ELSE_D3D9_DISPLAY_ANGLE = new EGLNativeDisplayType(-2); + public static readonly EGLNativeDisplayType D3D11_ONLY_DISPLAY_ANGLE = new EGLNativeDisplayType(-3); + // EGL_ANGLE_device_d3d + public const int D3D9_DEVICE_ANGLE = 0x33A0; + public const int D3D11_DEVICE_ANGLE = 0x33A1; + // EGL_ANGLE_platform_angle + public const int PLATFORM_ANGLE_ANGLE = 0x3202; + public const int PLATFORM_ANGLE_TYPE_ANGLE = 0x3203; + public const int PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE = 0x3204; + public const int PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE = 0x3205; + public const int PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE = 0x3206; + // EGL_ANGLE_platform_angle_d3d + public const int PLATFORM_ANGLE_TYPE_D3D9_ANGLE = 0x3207; + public const int PLATFORM_ANGLE_TYPE_D3D11_ANGLE = 0x3208; + public const int PLATFORM_ANGLE_DEVICE_TYPE_ANGLE = 0x3209; + public const int PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE = 0x320A; + public const int PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE = 0x320B; + public const int PLATFORM_ANGLE_DEVICE_TYPE_REFERENCE_ANGLE = 0x320C; + public const int PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE = 0x320F; + // EGL_ANGLE_platform_angle_opengl + public const int PLATFORM_ANGLE_TYPE_OPENGL_ANGLE = 0x320D; + public const int PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE = 0x320E; + } + #endregion + + unsafe public class Context : IDisposable + { + #region pinvoke + [DllImportAttribute("libEGL.dll", EntryPoint = "eglGetError")] + public static extern ErrorCode GetError(); + [DllImportAttribute("libEGL.dll", EntryPoint = "eglGetDisplay")] + public static extern EGLDisplay GetDisplay(EGLNativeDisplayType display_id); + [DllImportAttribute("libEGL.dll", EntryPoint = "eglInitialize")] + public static extern bool Initialize(EGLDisplay dpy, out int major, out int minor); + [DllImportAttribute("libEGL.dll", EntryPoint = "eglTerminate")] + public static extern bool Terminate(EGLDisplay dpy); + [DllImportAttribute("libEGL.dll", EntryPoint = "eglQueryString")] + public static extern IntPtr QueryString(EGLDisplay dpy, int name); + [DllImportAttribute("libEGL.dll", EntryPoint = "eglGetConfigs")] + [return: MarshalAsAttribute(UnmanagedType.I1)] + public static extern bool GetConfigs(EGLDisplay dpy, EGLConfig[] configs, int config_size, out int num_config); + [DllImportAttribute("libEGL.dll", EntryPoint = "eglChooseConfig")] + [return: MarshalAsAttribute(UnmanagedType.I1)] + public static extern bool ChooseConfig(EGLDisplay dpy, int[] attrib_list, [In, Out] EGLConfig[] configs, int config_size, out int num_config); + [DllImportAttribute("libEGL.dll", EntryPoint = "eglGetConfigAttrib")] + [return: MarshalAsAttribute(UnmanagedType.I1)] + public static extern bool GetConfigAttrib(EGLDisplay dpy, EGLConfig config, int attribute, out int value); + + [DllImportAttribute("libEGL.dll", EntryPoint = "eglBindAPI")] + [return: MarshalAsAttribute(UnmanagedType.I1)] + public static extern bool BindAPI(RenderApi api); + [DllImportAttribute("libEGL.dll", EntryPoint = "eglQueryAPI")] + public static extern int QueryAPI(); + [DllImportAttribute("libEGL.dll", EntryPoint = "eglWaitClient")] + [return: MarshalAsAttribute(UnmanagedType.I1)] + public static extern bool WaitClient(); + [DllImportAttribute("libEGL.dll", EntryPoint = "eglReleaseThread")] + [return: MarshalAsAttribute(UnmanagedType.I1)] + public static extern bool ReleaseThread(); + + [DllImportAttribute("libEGL.dll", EntryPoint = "eglSwapInterval")] + [return: MarshalAsAttribute(UnmanagedType.I1)] + public static extern bool SwapInterval(EGLDisplay dpy, int interval); + [DllImportAttribute("libEGL.dll", EntryPoint = "eglCreateContext")] + static extern IntPtr eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, int[] attrib_list); + public static EGLContext CreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, int[] attrib_list) + { + IntPtr ptr = eglCreateContext(dpy, config, share_context, attrib_list); + if (ptr == IntPtr.Zero) + throw new Exception(String.Format("Failed to create EGL context, error: {0}.", GetError())); + return ptr; + } + [DllImportAttribute("libEGL.dll", EntryPoint = "eglDestroyContext")] + [return: MarshalAsAttribute(UnmanagedType.I1)] + public static extern bool DestroyContext(EGLDisplay dpy, EGLContext ctx); + [DllImportAttribute("libEGL.dll", EntryPoint = "eglMakeCurrent")] + [return: MarshalAsAttribute(UnmanagedType.I1)] + public static extern bool MakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx); + + [DllImportAttribute("libEGL.dll", EntryPoint = "eglGetCurrentContext")] + public static extern EGLContext GetCurrentContext(); + [DllImportAttribute("libEGL.dll", EntryPoint = "eglGetCurrentSurface")] + public static extern EGLSurface GetCurrentSurface(int readdraw); + [DllImportAttribute("libEGL.dll", EntryPoint = "eglGetCurrentDisplay")] + public static extern EGLDisplay GetCurrentDisplay(); + [DllImportAttribute("libEGL.dll", EntryPoint = "eglQueryContext")] + [return: MarshalAsAttribute(UnmanagedType.I1)] + public static extern bool QueryContext(EGLDisplay dpy, EGLContext ctx, int attribute, out int value); + [DllImportAttribute("libEGL.dll", EntryPoint = "eglWaitGL")] + [return: MarshalAsAttribute(UnmanagedType.I1)] + public static extern bool WaitGL(); + [DllImportAttribute("libEGL.dll", EntryPoint = "eglWaitNative")] + [return: MarshalAsAttribute(UnmanagedType.I1)] + public static extern bool WaitNative(int engine); + [DllImportAttribute("libEGL.dll", EntryPoint = "eglSwapBuffers")] + [return: MarshalAsAttribute(UnmanagedType.I1)] + public static extern bool SwapBuffers(EGLDisplay dpy, EGLSurface surface); + [DllImportAttribute("libEGL.dll", EntryPoint = "eglCopyBuffers")] + [return: MarshalAsAttribute(UnmanagedType.I1)] + public static extern bool CopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target); + [DllImportAttribute("libEGL.dll", EntryPoint = "eglGetProcAddress")] + public static extern IntPtr GetProcAddress(string funcname); + [DllImportAttribute("libEGL.dll", EntryPoint = "eglGetProcAddress")] + public static extern IntPtr GetProcAddress(IntPtr funcname); + // EGL_EXT_platform_base + [DllImport("libEGL.dll", EntryPoint = "eglGetPlatformDisplayEXT")] + public static extern EGLDisplay GetPlatformDisplayEXT(int platform, EGLNativeDisplayType native_display, int[] attrib_list); + [DllImport("libEGL.dll", EntryPoint = "eglCreatePlatformWindowSurfaceEXT")] + public static extern EGLSurface CreatePlatformWindowSurfaceEXT(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType native_window, int[] attrib_list); + [DllImport("libEGL.dll", EntryPoint = "eglCreatePlatformPixmapSurfaceEXT")] + public static extern EGLSurface CreatePlatformPixmapSurfaceEXT(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType native_pixmap, int[] attrib_list); + // Returns true if Egl drivers exist on the system. + public static bool IsSupported + { + get + { + try { GetCurrentContext(); } + catch (Exception) { return false; } + return true; + } + } + #endregion + + int fd_gpu; + internal EGLDisplay dpy; + internal EGLContext ctx; + internal EGLConfig currentCfg; + + int major, minor; + + public string Version { get { return Marshal.PtrToStringAuto (QueryString (dpy, Egl.VERSION)); }} + public string Vendor { get { return Marshal.PtrToStringAuto (QueryString (dpy, Egl.VENDOR)); }} + public string Extensions { get { return Marshal.PtrToStringAuto (QueryString (dpy, Egl.EXTENSIONS)); }} + public string OffScreenExtensions { get { return Marshal.PtrToStringAuto (QueryString (IntPtr.Zero, Egl.EXTENSIONS)); }} + + #region ctor + public Context (GBM.Device gbmDev) + { + dpy = GetDisplay(gbmDev.handle); + + if (dpy == IntPtr.Zero) + throw new NotSupportedException("[EGL] GetDisplay failed.: " + GetError()); + + if (!Initialize(dpy, out major, out minor)) + throw new NotSupportedException("[EGL] Failed to initialize EGL display. Error code: " + GetError()); + + if (!BindAPI (RenderApi.GL)) + throw new NotSupportedException("[EGL] Failed to bind EGL Api: " + GetError()); + + int[] contextAttrib = new int[] { + Egl.CONTEXT_CLIENT_VERSION, 2, + Egl.NONE + }; + int[] desiredConfig = new int[] + { + Egl.SURFACE_TYPE, Egl.WINDOW_BIT, + Egl.RENDERABLE_TYPE, Egl.OPENGL_BIT, + Egl.RED_SIZE, 1, + Egl.GREEN_SIZE, 1, + Egl.BLUE_SIZE, 1, + Egl.ALPHA_SIZE, 0, + //Egl.DEPTH_SIZE, 24, + //Egl.STENCIL_SIZE, 0, + //Egl.SAMPLE_BUFFERS, 2, + //Egl.SAMPLES, 0, + Egl.NONE + }; + int num_configs; + IntPtr[] configs = new IntPtr[1]; + if (!ChooseConfig(dpy, desiredConfig, configs, 1, out num_configs)) + throw new NotSupportedException(String.Format("[EGL] Failed to retrieve GraphicsMode, error {0}", GetError())); + + currentCfg = configs [0]; + + ctx = CreateContext(dpy, currentCfg, IntPtr.Zero, contextAttrib); + if (ctx == IntPtr.Zero) + throw new NotSupportedException(String.Format("[EGL] Failed to create egl context, error {0}.", GetError())); + +// int[] attribs = new int[] { +// (int)Attribute.BufferSize, +// Egl.RED_SIZE, +// Egl.GREEN_SIZE, +// Egl.BLUE_SIZE, +// Egl.ALPHA_SIZE, +// (int)Attribute.DepthSize, +// //(int)Attribute.Height, +// Egl.WIDTH, +// (int)Attribute.Width, +// (int)Attribute.Samples, +// (int)Attribute.SampleBuffers, +// (int)Attribute.RenderableType, +// (int)Attribute.SurfaceType, +// (int)Attribute.Level, +// (int)Attribute.ConfigCaveat, +// }; +// +// for (int i = 0; i < configs.Length; i++) { +// IntPtr conf = configs[i]; +// Console.Write ("{0,-3}:", i); +// for (int j = 0; j < attribs.Length; j++) { +// int value; +// GetConfigAttrib (dpy, conf, attribs[j], out value); +// Console.Write ("\t{0} = {1}, ", EglConstToString ((int)attribs[j]), value); +// } +// Console.Write ("\n"); +// } + + } + #endregion + + enum ConfigAttribute { + RedSize , + GreenSize, + BlueSize, + AlphaSize + } + + #region IDisposable implementation + ~Context(){ + Dispose (false); + } + public void Dispose () + { + Dispose (true); + GC.SuppressFinalize (this); + } + protected virtual void Dispose (bool disposing){ + if (GetCurrentContext () == ctx) { + Console.WriteLine ("destroying context"); + DestroyContext (dpy, ctx); + }else + Console.WriteLine ("not current"); + + if (dpy != IntPtr.Zero) + Terminate (dpy); + dpy = IntPtr.Zero; + } + #endregion + + + static string EglConstToString (int cst){ + switch (cst) { +/* not hex value: EGL_DONT_CARE ((EGLint)-1) + not hex value: EGL_FALSE 0 + not hex value: EGL_NO_CONTEXT ((EGLContext)0) + not hex value: EGL_NO_DISPLAY ((EGLDisplay)0) + not hex value: EGL_NO_SURFACE ((EGLSurface)0) + not hex value: EGL_TRUE 1 + not hex value: EGL_VERSION_1_1 1 + not hex value: EGL_VERSION_1_2 1 + not hex value: EGL_DISPLAY_SCALING 10000 + not hex value: EGL_UNKNOWN ((EGLint)-1) + not hex value: EGL_VERSION_1_3 1 + not hex value: EGL_VERSION_1_4 1 + not hex value: EGL_DEFAULT_DISPLAY ((EGLNativeDisplayType)0) + not hex value: EGL_VERSION_1_5 1 + parsing error: EGL_FOREVER 0xFFFFFFFFFFFFFFFFull + not hex value: EGL_NO_SYNC ((EGLSync)0) + not hex value: EGL_NO_IMAGE ((EGLImage)0)*/ + case 1: + return "PBUFFER_BIT|OPENGL_ES_BIT|CONTEXT_OPENGL_CORE_PROFILE_BIT|SYNC_FLUSH_COMMANDS_BIT"; + case 2: + return "PIXMAP_BIT|OPENVG_BIT|CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT"; + case 4: + return "WINDOW_BIT|OPENGL_ES2_BIT"; + case 8: + return "OPENGL_BIT"; + case 32: + return "VG_COLORSPACE_LINEAR_BIT"; + case 64: + return "VG_ALPHA_FORMAT_PRE_BIT|OPENGL_ES3_BIT"; + case 512: + return "MULTISAMPLE_RESOLVE_BOX_BIT"; + case 1024: + return "SWAP_BEHAVIOR_PRESERVED_BIT"; + case 12288: + return "SUCCESS"; + case 12289: + return "NOT_INITIALIZED"; + case 12290: + return "BAD_ACCESS"; + case 12291: + return "BAD_ALLOC"; + case 12292: + return "BAD_ATTRIBUTE"; + case 12293: + return "BAD_CONFIG"; + case 12294: + return "BAD_CONTEXT"; + case 12295: + return "BAD_CURRENT_SURFACE"; + case 12296: + return "BAD_DISPLAY"; + case 12297: + return "BAD_MATCH"; + case 12298: + return "BAD_NATIVE_PIXMAP"; + case 12299: + return "BAD_NATIVE_WINDOW"; + case 12300: + return "BAD_PARAMETER"; + case 12301: + return "BAD_SURFACE"; + case 12302: + return "CONTEXT_LOST"; + case 12320: + return "BUFFER_SIZE"; + case 12321: + return "ALPHA_SIZE"; + case 12322: + return "BLUE_SIZE"; + case 12323: + return "GREEN_SIZE"; + case 12324: + return "RED_SIZE"; + case 12325: + return "DEPTH_SIZE"; + case 12326: + return "STENCIL_SIZE"; + case 12327: + return "CONFIG_CAVEAT"; + case 12328: + return "CONFIG_ID"; + case 12329: + return "LEVEL"; + case 12330: + return "MAX_PBUFFER_HEIGHT"; + case 12331: + return "MAX_PBUFFER_PIXELS"; + case 12332: + return "MAX_PBUFFER_WIDTH"; + case 12333: + return "NATIVE_RENDERABLE"; + case 12334: + return "NATIVE_VISUAL_ID"; + case 12335: + return "NATIVE_VISUAL_TYPE"; + case 12337: + return "SAMPLES"; + case 12338: + return "SAMPLE_BUFFERS"; + case 12339: + return "SURFACE_TYPE"; + case 12340: + return "TRANSPARENT_TYPE"; + case 12341: + return "TRANSPARENT_BLUE_VALUE"; + case 12342: + return "TRANSPARENT_GREEN_VALUE"; + case 12343: + return "TRANSPARENT_RED_VALUE"; + case 12344: + return "NONE"; + case 12345: + return "BIND_TO_TEXTURE_RGB"; + case 12346: + return "BIND_TO_TEXTURE_RGBA"; + case 12347: + return "MIN_SWAP_INTERVAL"; + case 12348: + return "MAX_SWAP_INTERVAL"; + case 12349: + return "LUMINANCE_SIZE"; + case 12350: + return "ALPHA_MASK_SIZE"; + case 12351: + return "COLOR_BUFFER_TYPE"; + case 12352: + return "RENDERABLE_TYPE"; + case 12353: + return "MATCH_NATIVE_PIXMAP"; + case 12354: + return "CONFORMANT"; + case 12368: + return "SLOW_CONFIG"; + case 12369: + return "NON_CONFORMANT_CONFIG"; + case 12370: + return "TRANSPARENT_RGB"; + case 12371: + return "VENDOR"; + case 12372: + return "VERSION"; + case 12373: + return "EXTENSIONS"; + case 12374: + return "HEIGHT"; + case 12375: + return "WIDTH"; + case 12376: + return "LARGEST_PBUFFER"; + case 12377: + return "DRAW"; + case 12378: + return "READ"; + case 12379: + return "CORE_NATIVE_ENGINE"; + case 12380: + return "NO_TEXTURE"; + case 12381: + return "TEXTURE_RGB"; + case 12382: + return "TEXTURE_RGBA"; + case 12383: + return "TEXTURE_2D"; + case 12416: + return "TEXTURE_FORMAT"; + case 12417: + return "TEXTURE_TARGET"; + case 12418: + return "MIPMAP_TEXTURE"; + case 12419: + return "MIPMAP_LEVEL"; + case 12420: + return "BACK_BUFFER"; + case 12421: + return "SINGLE_BUFFER"; + case 12422: + return "RENDER_BUFFER"; + case 12423: + return "COLORSPACE|VG_COLORSPACE"; + case 12424: + return "ALPHA_FORMAT|VG_ALPHA_FORMAT"; + case 12425: + return "COLORSPACE_sRGB|VG_COLORSPACE_sRGB|GL_COLORSPACE_SRGB"; + case 12426: + return "COLORSPACE_LINEAR|VG_COLORSPACE_LINEAR|GL_COLORSPACE_LINEAR"; + case 12427: + return "ALPHA_FORMAT_NONPRE|VG_ALPHA_FORMAT_NONPRE"; + case 12428: + return "ALPHA_FORMAT_PRE|VG_ALPHA_FORMAT_PRE"; + case 12429: + return "CLIENT_APIS"; + case 12430: + return "RGB_BUFFER"; + case 12431: + return "LUMINANCE_BUFFER"; + case 12432: + return "HORIZONTAL_RESOLUTION"; + case 12433: + return "VERTICAL_RESOLUTION"; + case 12434: + return "PIXEL_ASPECT_RATIO"; + case 12435: + return "SWAP_BEHAVIOR"; + case 12436: + return "BUFFER_PRESERVED"; + case 12437: + return "BUFFER_DESTROYED"; + case 12438: + return "OPENVG_IMAGE"; + case 12439: + return "CONTEXT_CLIENT_TYPE"; + case 12440: + return "CONTEXT_CLIENT_VERSION|CONTEXT_MAJOR_VERSION"; + case 12441: + return "MULTISAMPLE_RESOLVE"; + case 12442: + return "MULTISAMPLE_RESOLVE_DEFAULT"; + case 12443: + return "MULTISAMPLE_RESOLVE_BOX"; + case 12444: + return "CL_EVENT_HANDLE"; + case 12445: + return "GL_COLORSPACE"; + case 12448: + return "OPENGL_ES_API"; + case 12449: + return "OPENVG_API"; + case 12450: + return "OPENGL_API"; + case 12465: + return "GL_TEXTURE_2D"; + case 12466: + return "GL_TEXTURE_3D"; + case 12467: + return "GL_TEXTURE_CUBE_MAP_POSITIVE_X"; + case 12468: + return "GL_TEXTURE_CUBE_MAP_NEGATIVE_X"; + case 12469: + return "GL_TEXTURE_CUBE_MAP_POSITIVE_Y"; + case 12470: + return "GL_TEXTURE_CUBE_MAP_NEGATIVE_Y"; + case 12471: + return "GL_TEXTURE_CUBE_MAP_POSITIVE_Z"; + case 12472: + return "GL_TEXTURE_CUBE_MAP_NEGATIVE_Z"; + case 12473: + return "GL_RENDERBUFFER"; + case 12476: + return "GL_TEXTURE_LEVEL"; + case 12477: + return "GL_TEXTURE_ZOFFSET"; + case 12498: + return "IMAGE_PRESERVED"; + case 12528: + return "SYNC_PRIOR_COMMANDS_COMPLETE"; + case 12529: + return "SYNC_STATUS"; + case 12530: + return "SIGNALED"; + case 12531: + return "UNSIGNALED"; + case 12533: + return "TIMEOUT_EXPIRED"; + case 12534: + return "CONDITION_SATISFIED"; + case 12535: + return "SYNC_TYPE"; + case 12536: + return "SYNC_CONDITION"; + case 12537: + return "SYNC_FENCE"; + case 12539: + return "CONTEXT_MINOR_VERSION"; + case 12541: + return "CONTEXT_OPENGL_PROFILE_MASK"; + case 12542: + return "SYNC_CL_EVENT"; + case 12543: + return "SYNC_CL_EVENT_COMPLETE"; + case 12720: + return "CONTEXT_OPENGL_DEBUG"; + case 12721: + return "CONTEXT_OPENGL_FORWARD_COMPATIBLE"; + case 12722: + return "CONTEXT_OPENGL_ROBUST_ACCESS"; + case 12733: + return "CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY"; + case 12734: + return "NO_RESET_NOTIFICATION"; + case 12735: + return "LOSE_CONTEXT_ON_RESET"; + default: + return "unknown"; + } + } + } +} + diff --git a/testDrm/src/Egl/EGL.cs b/testDrm/src/Egl/EGL.cs new file mode 100644 index 00000000..c8608a9f --- /dev/null +++ b/testDrm/src/Egl/EGL.cs @@ -0,0 +1,257 @@ +// +// EGL.cs +// +// Author: +// Jean-Philippe Bruyère +// +// Copyright (c) 2013-2017 Jean-Philippe Bruyère +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; + +namespace EGL +{ + public enum Error { + NoContext = 0, + NoDisplay = 0, + NoSurface = 0, + + NotInitialized = 0x3001, + BadAccess = 0x3002, + BadAlloc = 0x3003, + BadAttribute = 0x3004, + BadConfig = 0x3005, + BadContext = 0x3006, + BadCurrentSurface= 0x3007, + BadDisplay = 0x3008, + BadMatch = 0x3009, + BadNativePixmap = 0x300A, + BadNativeWindow = 0x300B, + BadParameter = 0x300C, + BadSurface = 0x300D, + + ContextLost = 0x300E, + + } + public enum Attribute { + BufferSize = 0x3020, + AlphaSize = 0x3021, + BlueSize = 0x3022, + GreenSize = 0x3023, + RedSize = 0x3024, + DepthSize = 0x3025, + StencilSize = 0x3026, + ConfigCaveat= 0x3027, + ConfigId = 0x3028, + Level = 0x3029, + Samples = 0x3031, + SampleBuffers = 0x3032, + Height = 0x3056, + Width = 0x3057, + LargestPbuffer = 0x3058, + MaxPbufferHeight = 0x302A, + MaxPbufferPixels = 0x302B, + MaxPbufferWidth = 0x302C, + SurfaceType = 0x3033, + TransparentType = 0x3034, + TransparentBlueValue = 0x3035, + TransparentGreenValue = 0x3036, + TransparentRedValue = 0x3037, + BindToTextureRgb = 0x3039, + RenderableType = 0x3040, + BindToTextureRgba = 0x303A, + MinSwapInterval = 0x303B, + MaxSwapInterval = 0x303C, + AlphaMaskSize = 0x303E, + ColorBufferType = 0x303F, + MatchNativePixmap = 0x3041, + TransparentRgb = 0x3052, + } + + [Flags]public enum SurfaceType { + DontCare = -1, + None = 0x3038, + + Pbuffer = 0x0001, + Pixmap = 0x0002, + Window = 0x0004, + VgColorspaceLinear = 0x0020, + VgAlphaFormatPre = 0x0040, + MultisampleResolveBox = 0x0200, + SwapBehaviorPreserved = 0x0400, + } + [Flags]public enum RenderableType { + DontCare = -1, + None = 0x3038, + + OpenglEs = 0x0001, + Openvg = 0x0002, + OpenglEs2 = 0x0004, + Opengl = 0x0008, + OpenglEs3 = 0x00000040, + } + [Flags]enum ConformantType { + DontCare = -1, + None = 0x3038, + + SlowConfig = 0x3050, + NonConformantConfig = 0x3051, + } + [Flags]enum ColorBufferType { + RgbBuffer = 0x308E, + LuminanceBuffer = 0x308F, + } + + [Flags]public enum EglConsts { + Version10 = 1, + + CoreNativeEngine = 0x305B, + + + Draw = 0x3059, + Extensions = 0x3055, + False = 0, + NativeRenderable = 0x302D, + NativeVisualId = 0x302E, + NativeVisualType = 0x302F, + + + Read = 0x305A, + + + Success = 0x3000, + + + True = 1, + + Vendor = 0x3053, + Version = 0x3054, + + + Version11 = 1, + + BackBuffer = 0x3084, + + + MipmapTexture = 0x3082, + MipmapLevel = 0x3083, + NoTexture = 0x305C, + Texture2d = 0x305F, + TextureFormat = 0x3080, + TextureRgb = 0x305D, + TextureRgba = 0x305E, + TextureTarget = 0x3081, + Version12 = 1, + AlphaFormat = 0x3088, + AlphaFormatNonpre = 0x308B, + AlphaFormatPre = 0x308C, + + BufferPreserved = 0x3094, + BufferDestroyed = 0x3095, + ClientApis = 0x308D, + Colorspace = 0x3087, + ColorspaceSrgb = 0x3089, + ColorspaceLinear = 0x308A, + + ContextClientType = 0x3097, + DisplayScaling = 10000, + HorizontalResolution = 0x3090, + LuminanceSize = 0x303D, + + OpenglEsApi = 0x30A0, + OpenvgApi = 0x30A1, + OpenvgImage = 0x3096, + PixelAspectRatio = 0x3092, + + RenderBuffer = 0x3086, + + + + SingleBuffer = 0x3085, + SwapBehavior = 0x3093, + Unknown = -1, + VerticalResolution = 0x3091, + Version13 = 1, + Conformant = 0x3042, + ContextClientVersion = 0x3098, + + VgAlphaFormat = 0x3088, + VgAlphaFormatNonpre = 0x308B, + VgAlphaFormatPre = 0x308C, + + VgColorspace = 0x3087, + VgColorspaceSrgb = 0x3089, + VgColorspaceLinear = 0x308A, + + Version14 = 1, + + DefaultDisplay = 0, + + MultisampleResolve = 0x3099, + MultisampleResolveDefault = 0x309A, + MultisampleResolveBox = 0x309B, + OpenglApi = 0x30A2, + Version15 = 1, + ContextMajorVersion = 0x3098, + ContextMinorVersion = 0x30FB, + ContextOpenglProfileMask = 0x30FD, + ContextOpenglResetNotificationStrategy = 0x31BD, + NoResetNotification = 0x31BE, + LoseContextOnReset = 0x31BF, + ContextOpenglCoreProfileBit = 0x00000001, + ContextOpenglCompatibilityProfileBit = 0x00000002, + ContextOpenglDebug = 0x31B0, + ContextOpenglForwardCompatible = 0x31B1, + ContextOpenglRobustAccess = 0x31B2, + + ClEventHandle = 0x309C, + SyncClEvent = 0x30FE, + SyncClEventComplete = 0x30FF, + SyncPriorCommandsComplete = 0x30F0, + SyncType = 0x30F7, + SyncStatus = 0x30F1, + SyncCondition = 0x30F8, + Signaled = 0x30F2, + Unsignaled = 0x30F3, + SyncFlushCommandsBit = 0x0001, + Forever = int.MinValue, + TimeoutExpired = 0x30F5, + ConditionSatisfied = 0x30F6, + NoSync = 0, + SyncFence = 0x30F9, + + GlColorspace = 0x309D, + GlColorspaceSrgb = 0x3089, + GlColorspaceLinear = 0x308A, + GlRenderbuffer = 0x30B9, + GlTexture2d = 0x30B1, + GlTextureLevel = 0x30BC, + GlTexture3d = 0x30B2, + GlTextureZoffset = 0x30BD, + GlTextureCubeMapPositiveX = 0x30B3, + GlTextureCubeMapNegativeX = 0x30B4, + GlTextureCubeMapPositiveY = 0x30B5, + GlTextureCubeMapNegativeY = 0x30B6, + GlTextureCubeMapPositiveZ = 0x30B7, + GlTextureCubeMapNegativeZ = 0x30B8, + ImagePreserved = 0x30D2, + NoImage = 0, + } +} + diff --git a/testDrm/src/Egl/Surface.cs b/testDrm/src/Egl/Surface.cs new file mode 100644 index 00000000..ccfcaa9c --- /dev/null +++ b/testDrm/src/Egl/Surface.cs @@ -0,0 +1,97 @@ +// +// Surface.cs +// +// Author: +// Jean-Philippe Bruyère +// +// Copyright (c) 2013-2017 Jean-Philippe Bruyère +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using System.Runtime.InteropServices; + +namespace EGL +{ + using EGLNativeDisplayType = IntPtr; + using EGLNativeWindowType = IntPtr; + using EGLNativePixmapType = IntPtr; + using EGLConfig = IntPtr; + using EGLContext = IntPtr; + using EGLDisplay = IntPtr; + using EGLSurface = IntPtr; + using EGLClientBuffer = IntPtr; + + public class Surface : IDisposable + { + #region pinvoke + [DllImportAttribute("libEGL.dll")] + public static extern EGLSurface eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, IntPtr win, IntPtr attrib_list); + [DllImportAttribute("libEGL.dll")] + public static extern EGLSurface eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, int[] attrib_list); + [DllImportAttribute("libEGL.dll")] + public static extern EGLSurface eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, int[] attrib_list); + [DllImportAttribute("libEGL.dll")][return: MarshalAsAttribute(UnmanagedType.I1)] + public static extern bool eglDestroySurface(EGLDisplay dpy, EGLSurface surface); + [DllImportAttribute("libEGL.dll")][return: MarshalAsAttribute(UnmanagedType.I1)] + public static extern bool eglQuerySurface(EGLDisplay dpy, EGLSurface surface, int attribute, out int value); + [DllImportAttribute("libEGL.dll")] + public static extern EGLSurface eglCreatePbufferFromClientBuffer(EGLDisplay dpy, int buftype, EGLClientBuffer buffer, EGLConfig config, int[] attrib_list); + [DllImportAttribute("libEGL.dll")][return: MarshalAsAttribute(UnmanagedType.I1)] + public static extern bool eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, int attribute, int value); + [DllImportAttribute("libEGL.dll")][return: MarshalAsAttribute(UnmanagedType.I1)] + public static extern bool eglBindTexImage(EGLDisplay dpy, EGLSurface surface, int buffer); + [DllImportAttribute("libEGL.dll")][return: MarshalAsAttribute(UnmanagedType.I1)] + public static extern bool eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, int buffer); + #endregion + + Context ctx; + internal EGLSurface handle; + + public Surface (Context _ctx, Linux.GBM.Surface gbmSurf) + { + ctx = _ctx; + handle = eglCreateWindowSurface(ctx.dpy, ctx.currentCfg, gbmSurf.handle, IntPtr.Zero); + if (handle == IntPtr.Zero) + throw new NotSupportedException(String.Format("[EGL] Failed to create surface, error {0}.", EGL.Context.GetError())); + } + + public void MakeCurrent (){ + if (!Context.MakeCurrent(ctx.dpy, handle, handle, ctx.ctx)) + throw new NotSupportedException(string.Format("eglMakeCurrent on surface Failed: {0}",Context.GetError())); + } + + #region IDisposable implementation + ~Surface(){ + Dispose (false); + } + public void Dispose () + { + Dispose (true); + GC.SuppressFinalize (this); + } + protected virtual void Dispose (bool disposing){ + if (handle != IntPtr.Zero) + eglDestroySurface (ctx.dpy, handle); + handle = IntPtr.Zero; + } + #endregion + + } +} + diff --git a/testDrm/src/Linux/Bindings/Egl.cs b/testDrm/src/Linux/Bindings/Egl.cs index f9919265..754a12d5 100644 --- a/testDrm/src/Linux/Bindings/Egl.cs +++ b/testDrm/src/Linux/Bindings/Egl.cs @@ -44,21 +44,19 @@ namespace Crow.Linux enum RenderApi { - ES = Egl.OPENGL_ES_API, - GL = Egl.OPENGL_API, - VG = Egl.OPENVG_API + ES = Egl.OPENGL_ES_API, + GL = Egl.OPENGL_API, + VG = Egl.OPENVG_API } - [Flags] - enum RenderableFlags + [Flags]enum RenderableFlags { - ES = Egl.OPENGL_ES_BIT, - ES2 = Egl.OPENGL_ES2_BIT, - ES3 = Egl.OPENGL_ES3_BIT, - GL = Egl.OPENGL_BIT, - VG = Egl.OPENVG_BIT, + ES = Egl.OPENGL_ES_BIT, + ES2 = Egl.OPENGL_ES2_BIT, + ES3 = Egl.OPENGL_ES3_BIT, + GL = Egl.OPENGL_BIT, + VG = Egl.OPENVG_BIT, } - public enum ErrorCode { SUCCESS = 12288, @@ -312,7 +310,7 @@ namespace Crow.Linux { IntPtr ptr = eglCreateContext(dpy, config, share_context, attrib_list); if (ptr == IntPtr.Zero) - throw new Exception(String.Format("Failed to create EGL context, error: {0}.", Egl.GetError())); + throw new Exception(String.Format("Failed to create EGL context, error: {0}.", GetError())); return ptr; } diff --git a/testDrm/src/Linux/Bindings/Evdev.cs b/testDrm/src/Linux/Bindings/Evdev.cs index d162c071..96bbd18c 100644 --- a/testDrm/src/Linux/Bindings/Evdev.cs +++ b/testDrm/src/Linux/Bindings/Evdev.cs @@ -26,6 +26,8 @@ // THE SOFTWARE. // using OpenTK; +using Linux; +using Crow; #endregion @@ -33,9 +35,8 @@ using OpenTK; using System; using System.Diagnostics; using System.Runtime.InteropServices; -using Crow; -namespace Crow.Linux +namespace Linux { // Bindings for linux/input.h class Evdev diff --git a/testDrm/src/Linux/Bindings/Gbm.cs b/testDrm/src/Linux/Bindings/Gbm.cs index a0659461..22fb26a9 100644 --- a/testDrm/src/Linux/Bindings/Gbm.cs +++ b/testDrm/src/Linux/Bindings/Gbm.cs @@ -30,24 +30,24 @@ using System; using System.Runtime.InteropServices; -namespace Crow.Linux +namespace Linux.gbm { using Device = IntPtr; // struct gbm_device* using Surface = IntPtr; using BufferObjectHandle = IntPtr; - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - delegate void DestroyUserDataCallback(BufferObject bo, IntPtr data); +// [UnmanagedFunctionPointer(CallingConvention.Cdecl)] +// delegate void DestroyUserDataCallback(BufferObject bo, IntPtr data); class Gbm { const string lib = "gbm"; - [DllImport(lib, EntryPoint = "gbm_bo_create", CallingConvention = CallingConvention.Cdecl)] - public static extern BufferObject CreateBuffer(Device gbm, int width, int height, SurfaceFormat format, SurfaceFlags flags); + [DllImport(lib, EntryPoint = "gbm_bo_create", CallingConvention = CallingConvention.Cdecl)] + unsafe public static extern gbm_bo* CreateBO (Device gbm, int width, int height, SurfaceFormat format, SurfaceFlags flags); [DllImport(lib, EntryPoint = "gbm_bo_destroy", CallingConvention = CallingConvention.Cdecl)] - public static extern void DestroyBuffer(BufferObject bo); + unsafe public static extern void DestroyBuffer (gbm_bo* bo); [DllImport(lib, EntryPoint = "gbm_bo_write", CallingConvention = CallingConvention.Cdecl)] public static extern int BOWrite(IntPtr bo, IntPtr buf, IntPtr count); @@ -58,6 +58,9 @@ namespace Crow.Linux [DllImport(lib, EntryPoint = "gbm_bo_get_handle", CallingConvention = CallingConvention.Cdecl)] public static extern BufferObjectHandle BOGetHandle(IntPtr bo); + [DllImport(lib, EntryPoint = "gbm_bo_get_handle", CallingConvention = CallingConvention.Cdecl)] + public static extern ulong BOGetHandle(ref gbm_bo bo); + [DllImport(lib, EntryPoint = "gbm_bo_get_height", CallingConvention = CallingConvention.Cdecl)] public static extern int BOGetHeight(IntPtr bo); @@ -67,8 +70,11 @@ namespace Crow.Linux [DllImport(lib, EntryPoint = "gbm_bo_get_stride", CallingConvention = CallingConvention.Cdecl)] public static extern int BOGetStride(IntPtr bo); + [DllImport(lib, EntryPoint = "gbm_bo_get_stride", CallingConvention = CallingConvention.Cdecl)] + public static extern uint BOGetStride (ref gbm_bo bo); + [DllImport(lib, EntryPoint = "gbm_bo_set_user_data", CallingConvention = CallingConvention.Cdecl)] - public static extern void BOSetUserData(IntPtr bo, IntPtr data, IntPtr callback); + public static extern void BOSetUserData(ref gbm_bo bo, IntPtr data, IntPtr callback); // [DllImport(lib, EntryPoint = "gbm_bo_get_user_data", CallingConvention = CallingConvention.Cdecl)] // public static extern IntPtr BOGetUserData (IntPtr bo); @@ -93,19 +99,25 @@ namespace Crow.Linux public static extern bool IsFormatSupported(Device gbm, SurfaceFormat format, SurfaceFlags usage); [DllImport(lib, EntryPoint = "gbm_surface_lock_front_buffer", CallingConvention = CallingConvention.Cdecl)] - public static extern BufferObject LockFrontBuffer(Surface surface); + unsafe public static extern gbm_bo* LockFrontBuffer(Surface surface); [DllImport(lib, EntryPoint = "gbm_surface_release_buffer", CallingConvention = CallingConvention.Cdecl)] - public static extern void ReleaseBuffer(Surface surface, BufferObject buffer); + unsafe public static extern void ReleaseBuffer(Surface surface, gbm_bo* buffer); [DllImport(lib, EntryPoint = "gbm_surface_has_free_buffers", CallingConvention = CallingConvention.Cdecl)] public static extern int HasFreeBuffers (Surface surface); + [DllImport(lib, EntryPoint = "gbm_bo_map", CallingConvention = CallingConvention.Cdecl)] + unsafe public static extern IntPtr Map (gbm_bo* bo, uint x, uint y, uint width, uint height, TransferFlags flags, ref uint stride, out IntPtr data); + + [DllImport(lib, EntryPoint = "gbm_bo_unmap", CallingConvention = CallingConvention.Cdecl)] + unsafe public static extern void Unmap (gbm_bo* bo, IntPtr data); + } - enum SurfaceFormat + public enum SurfaceFormat : uint { - BigEndian = 1 << 31, + BigEndian = 1u << 31, C8 = ((int)('C') | ((int)('8') << 8) | ((int)(' ') << 16) | ((int)(' ') << 24)), RGB332 = ((int)('R') | ((int)('G') << 8) | ((int)('B') << 16) | ((int)('8') << 24)), @@ -180,106 +192,134 @@ namespace Crow.Linux YUV444 = ((int)('Y') | ((int)('U') << 8) | ((int)('2') << 16) | ((int)('4') << 24)), YVU444 = ((int)('Y') | ((int)('V') << 8) | ((int)('2') << 16) | ((int)('4') << 24)), } - - [Flags] - enum SurfaceFlags + + [Flags]public enum SurfaceFlags : uint { Scanout = (1 << 0), Cursor64x64 = (1 << 1), Rendering = (1 << 2), Write = (1 << 3), - } - - [StructLayout(LayoutKind.Sequential)] - struct BufferObject : IEquatable - { - IntPtr buffer; - - public static readonly BufferObject Zero = - default(BufferObject); - - public int Write(byte[] data) - { - unsafe - { - fixed (byte* pdata = data) - { - return Gbm.BOWrite(buffer, (IntPtr)pdata, (IntPtr)data.Length); - } - } - } - + Linear = (1 << 4), + } + [Flags]public enum TransferFlags : uint { + /// Buffer contents read back (or accessed directly) at transfer create time. + Read = 1 << 0, + /// Buffer contents will be written back at unmap time (or modified as a result of being accessed directly). + Write = 1 << 1, + /// Read/modify/write + ReadWrite = Read | Write, + } + + [StructLayout(LayoutKind.Sequential)] + public struct gbm_bo { + IntPtr device; + public uint Width, Height; + public SurfaceFormat Format; + public SurfaceFlags Flags; + + public uint Handle32 + { + get { return (uint)Gbm.BOGetHandle(ref this); } + } + public uint Stride + { + get { return Gbm.BOGetStride(ref this); } + } public void SetUserData(IntPtr data, IntPtr destroyFB) - { - Gbm.BOSetUserData(buffer, data, destroyFB); - } - - public Device Device - { - get { return Gbm.BOGetDevice(buffer); } - } - - public int Handle - { - get { return Gbm.BOGetHandle(buffer).ToInt32(); } - } - - public int Width - { - get { return Gbm.BOGetWidth(buffer); } - } - - public int Height - { - get { return Gbm.BOGetHeight(buffer); } - } - - public int Stride - { - get { return Gbm.BOGetStride(buffer); } - } - - public void Dispose() - { - Gbm.DestroyBuffer(this); - buffer = IntPtr.Zero; - } - - public static bool operator ==(BufferObject left, BufferObject right) - { - return left.Equals(right); - } - - public static bool operator !=(BufferObject left, BufferObject right) - { - return !left.Equals(right); - } - - public override bool Equals(object obj) - { - return - obj is BufferObject && - this.Equals((BufferObject)obj); - } - - public override int GetHashCode() - { - return buffer.GetHashCode(); - } - - public override string ToString() - { - return string.Format("[BufferObject: {0}]", buffer); - } - - #region IEquatable implementation - - public bool Equals(BufferObject other) - { - return buffer == other.buffer; - } - - #endregion - } + { + Gbm.BOSetUserData(ref this, data, destroyFB); + } + } +// [StructLayout(LayoutKind.Sequential)] +// public struct BufferObject : IEquatable +// { +// IntPtr buffer; +// +// public static readonly BufferObject Zero = +// default(BufferObject); +// +// public int Write(byte[] data) +// { +// unsafe +// { +// fixed (byte* pdata = data) +// { +// return Gbm.BOWrite(buffer, (IntPtr)pdata, (IntPtr)data.Length); +// } +// } +// } +// +// public void SetUserData(IntPtr data, IntPtr destroyFB) +// { +// Gbm.BOSetUserData(buffer, data, destroyFB); +// } +// +// public Device Device +// { +// get { return Gbm.BOGetDevice(buffer); } +// } +// +// public int Handle +// { +// get { return Gbm.BOGetHandle(buffer).ToInt32(); } +// } +// +// public int Width +// { +// get { return Gbm.BOGetWidth(buffer); } +// } +// +// public int Height +// { +// get { return Gbm.BOGetHeight(buffer); } +// } +// +// public int Stride +// { +// get { return Gbm.BOGetStride(buffer); } +// } +// +// public void Dispose() +// { +// Gbm.DestroyBuffer(this); +// buffer = IntPtr.Zero; +// } +// +// public static bool operator ==(BufferObject left, BufferObject right) +// { +// return left.Equals(right); +// } +// +// public static bool operator !=(BufferObject left, BufferObject right) +// { +// return !left.Equals(right); +// } +// +// public override bool Equals(object obj) +// { +// return +// obj is BufferObject && +// this.Equals((BufferObject)obj); +// } +// +// public override int GetHashCode() +// { +// return buffer.GetHashCode(); +// } +// +// public override string ToString() +// { +// return string.Format("[BufferObject: {0}]", buffer); +// } +// +// #region IEquatable implementation +// +// public bool Equals(BufferObject other) +// { +// return buffer == other.buffer; +// } +// +// #endregion +// } } diff --git a/testDrm/src/Linux/Bindings/LibInput.cs b/testDrm/src/Linux/Bindings/LibInput.cs index b7c05f6e..c1a56ad5 100644 --- a/testDrm/src/Linux/Bindings/LibInput.cs +++ b/testDrm/src/Linux/Bindings/LibInput.cs @@ -33,7 +33,7 @@ using System; using System.Diagnostics; using System.Runtime.InteropServices; -namespace Crow.Linux +namespace Linux { [UnmanagedFunctionPointer(CallingConvention.Cdecl)] delegate int OpenRestrictedCallback(IntPtr path, int flags, IntPtr data); diff --git a/testDrm/src/Linux/Bindings/Libc.cs b/testDrm/src/Linux/Bindings/Libc.cs index c39330c2..c3a07094 100644 --- a/testDrm/src/Linux/Bindings/Libc.cs +++ b/testDrm/src/Linux/Bindings/Libc.cs @@ -33,7 +33,7 @@ using System.Text; #pragma warning disable 0649 // field is never assigned -namespace Crow.Linux +namespace Linux { partial class Libc { diff --git a/testDrm/src/Linux/Bindings/Poll.cs b/testDrm/src/Linux/Bindings/Poll.cs index cdd9c412..d3a663b5 100644 --- a/testDrm/src/Linux/Bindings/Poll.cs +++ b/testDrm/src/Linux/Bindings/Poll.cs @@ -30,7 +30,7 @@ using System; using System.Runtime.InteropServices; -namespace Crow.Linux +namespace Linux { partial class Libc { diff --git a/testDrm/src/Linux/DRI.cs b/testDrm/src/Linux/DRI.cs new file mode 100644 index 00000000..c1f60a41 --- /dev/null +++ b/testDrm/src/Linux/DRI.cs @@ -0,0 +1,524 @@ +// +// DRM.cs +// +// Author: +// Jean-Philippe Bruyère +// +// Copyright (c) 2013-2017 Jean-Philippe Bruyère +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using System.Runtime.InteropServices; +using System.Collections.Generic; +using System.Diagnostics; + +namespace Linux.DRI { + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void VBlankCallback(int fd, int sequence, int tv_sec, int tv_usec, IntPtr user_data); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void PageFlipCallback(int fd, int sequence, int tv_sec, int tv_usec, ref int user_data); + + public enum EncoderType : uint + { + NONE=0, + DAC=1, + TMDS=2, + LVDS=3, + TVDAC=4, + VIRTUAL=5, + DSI=6, + DPMST=7, + DPI=8, + } + public enum PlaneType { + Overlay = 0, + Primary = 1, + Cursor = 2 + } + + [Flags]public enum PageFlipFlags + { + FlipEvent = 0x01, + FlipAsync = 0x02, + FlipFlags = FlipEvent | FlipAsync + } + /// Video mode flags, bit compatible with the xorg definitions. + [Flags]public enum VideoMode + { + PHSYNC = 0x01, + NHSYNC = 0x02, + PVSYNC = 0x04, + NVSYNC = 0x08, + INTERLACE = 0x10, + DBLSCAN = 0x20, + CSYNC = 0x40, + PCSYNC = 0x80, + NCSYNC = 0x10, + HSKEW = 0x0200, + BCAST = 0x0400, + PIXMUX = 0x0800, + DBLCLK = 0x1000, + CLKDIV2 = 0x2000, + // FLAG_3D_MASK (0x1f<<14) + // FLAG_3D_NONE = 0x0; + // FLAG_3D_FRAME_PACKING = 0x4000, + // FLAG_3D_FIELD_ALTERNATIVE = 0x8000, + // FLAG_3D_LINE_ALTERNATIVE (3<<14) + // FLAG_3D_SIDE_BY_SIDE_FULL (4<<14) + // FLAG_3D_L_DEPTH (5<<14) + // FLAG_3D_L_DEPTH_GFX_GFX_DEPTH (6<<14) + // FLAG_3D_TOP_AND_BOTTOM (7<<14) + // FLAG_3D_SIDE_BY_SIDE_HALF (8<<14) + } + + [StructLayout(LayoutKind.Sequential)] + public struct EventContext + { + public int version; + public IntPtr vblank_handler; + public IntPtr page_flip_handler; + public static readonly int Version = 2; + } + [StructLayout(LayoutKind.Sequential)] + unsafe public struct drmFrameBuffer { + public uint fb_id; + public uint width, height; + public uint pitch; + public uint bpp; + public uint depth; + /* driver specific handle */ + public uint handle; + } + [StructLayout(LayoutKind.Sequential)] + unsafe internal struct drmPlaneRes { + public uint count_planes; + public uint *planes; + } + + public class GPUControler : IDisposable { + int fd_gpu = -1; + GBM.Device gbmDev; + GBM.Surface gbmSurf; + EGL.Context eglctx; + EGL.Surface eglSurf; + + Cairo.EGLDevice cairoDev; + public Cairo.GLSurface CairoSurf; + + Resources resources = null; + Connector connector = null; + Crtc currentCrtc = null; + ModeInfo currentMode; + + public GPUControler(string gpu_path = "/dev/dri/card0"){ + fd_gpu = Libc.open(gpu_path, OpenFlags.ReadWrite | OpenFlags.CloseOnExec); + if (fd_gpu < 0) + throw new NotSupportedException("[DRI] Failed to open gpu"); + + resources = new Resources (fd_gpu); + gbmDev = new GBM.Device (fd_gpu); + eglctx = new EGL.Context (gbmDev); + + try { + if (defaultConfiguration ()) + Console.WriteLine ("default config ok"); + } catch (Exception ex) { + Console.WriteLine (ex.ToString()); + } + } + + byte bpp = 32; + byte depth = 24; + + public int Width { get { return (int)currentMode.hdisplay; }} + public int Height { get { return (int)currentMode.vdisplay; }} + + bool defaultConfiguration (){ + //select the first connected connector + foreach (Connector c in resources.Connectors) { + if (c.State == ConnectionStatus.Connected) { + connector = c; + break; + } + } + if (connector == null) + return false; + + currentCrtc = connector.CurrentEncoder.CurrentCrtc; + currentMode = currentCrtc.CurrentMode; + + //configure a rendering stack + gbmSurf = new GBM.Surface (gbmDev, Width, Height, + GBM.SurfaceFlags.Rendering | GBM.SurfaceFlags.Scanout); + + eglSurf = new EGL.Surface (eglctx, gbmSurf); + eglSurf.MakeCurrent (); + + cairoDev = new Cairo.EGLDevice (eglctx.dpy, eglctx.ctx); + + CairoSurf = new Cairo.GLSurface (cairoDev, eglSurf.handle, Width, Height); + //cairoSurf = new Cairo.EGLSurface (cairoDev, egl_surface, 1600, 900); + + cairoDev.SetThreadAware (false); + + if (cairoDev.Acquire () != Cairo.Status.Success) + Console.WriteLine ("[Cairo]: Failed to acquire egl device."); + + return true; + } + void handleDestroyFB(ref GBM.gbm_bo bo, IntPtr data) + { + int fb = data.ToInt32(); + + if (fb != 0) { + if (drmModeRmFB (fd_gpu, fb) != 0) + Console.WriteLine ("DestroyFB failed"); + else + Console.WriteLine ("DestroyFB ok fd={0}", fd_gpu); + } + } + + + + unsafe public void Update(){ + GBM.gbm_bo* bo; + uint fb; + +// PollFD fds = new PollFD(); +// fds.fd = fd_gpu; +// fds.events = PollFlags.In; +// +// EventContext evctx = new EventContext(); +// evctx.version = EventContext.Version; +// evctx.page_flip_handler = PageFlipPtr; + +// int timeout = -1;//block ? -1 : 0; +// + + if (!gbmSurf.HasFreeBuffers) + throw new NotSupportedException("[GBM] Out of free buffer"); + + bo = gbmSurf.Lock (); + //fb = getFbFromBo (bo); + //unsafe { + //Console.WriteLine ("current fb: {0}", currentCrtc.CurrentFbId); + //if (currentCrtc.CurrentFbId == 0) + + int ret = drmModeAddFB (fd_gpu, currentMode.hdisplay, currentMode.vdisplay, (byte)depth, (byte)bpp, bo->Stride, (uint)bo->Handle32, out fb); + if (ret != 0) + Console.WriteLine ("addFb failed: {0}", ret); + //else + // fb = currentCrtc.CurrentFbId; + bo->SetUserData ((IntPtr)fb, handleDestroyFB); + + uint connId = connector.Id; + ret = drmModeSetCrtc (fd_gpu, currentCrtc.Id, fb, 0, 0, &connId, 1, ref currentMode); + if (ret != 0) + Console.WriteLine ("setCrtc failed: {0}", ret); + //} + gbmSurf.Release (bo); + + //bo.Dispose (); +// +// SetScanoutRegion (fb); +// drmTimeOut.Restart(); +// +// while (run && drmTimeOut.ElapsedMilliseconds < 10000){ +// BufferObject next_bo; +// bool update = false; +// +// if (updateMousePos) { +// lock (Sync) { +// updateMousePos = false; +// unsafe { +// Drm.MoveCursor (fd_gpu, pEncoder->crtc_id, MouseX-8, MouseY-4); +// } +// } +// } +// +// if (Monitor.TryEnter (CrowInterface.RenderMutex)) { +// if (CrowInterface.IsDirty) { +// CrowInterface.IsDirty = false; +// update = true; +// using (Cairo.Context ctx = new Cairo.Context (cairoSurf)) { +// using (Cairo.Surface d = new Cairo.ImageSurface (CrowInterface.dirtyBmp, Cairo.Format.Argb32, +// width, height, width * 4)) { +// ctx.SetSourceSurface (d, 0, 0); +// ctx.Operator = Cairo.Operator.Source; +// ctx.Paint (); +// } +// } +// } +// Monitor.Exit (CrowInterface.RenderMutex); +// } +// +// if (!update) +// continue; +// update = false; +// +// cairoSurf.Flush (); +// cairoSurf.SwapBuffers (); +// +// if (Gbm.HasFreeBuffers (gbm_surface) == 0) +// throw new Exception ("[GBM]: Out of free buffers."); +// +// next_bo = Gbm.LockFrontBuffer (gbm_surface); +// if (next_bo == BufferObject.Zero) +// throw new Exception ("[GBM]: Failed to lock front buffer."); +// +// fb = getFbFromBo (next_bo); +// +// unsafe{ +// int is_flip_queued = 1; +// +// while (Drm.ModePageFlip (fd_gpu, pEncoder->crtc_id, fb, PageFlipFlags.FlipEvent, ref is_flip_queued) < 0) { +// //Console.WriteLine ("[DRM] Failed to enqueue framebuffer flip."); +// continue; +// } +// +// while (is_flip_queued != 0) +// { +// fds.revents = 0; +// if (Libc.poll (ref fds, 1, timeout) < 0) +// break; +// +// if ((fds.revents & (PollFlags.Hup | PollFlags.Error)) != 0) +// break; +// +// if ((fds.revents & PollFlags.In) != 0) +// Drm.HandleEvent (fd_gpu, ref evctx); +// else +// break; +// Thread.Sleep (1); +// } +// if (is_flip_queued != 0) +// Console.WriteLine ("flip canceled"); +// +// Gbm.ReleaseBuffer (gbm_surface, bo); +// //Drm.ModeRmFB(fd_gpu, fb); +// +// bo = next_bo; +// next_bo = BufferObject.Zero; +// +// } +// } + } + + #region cursor + GBM.BufferObject boMouseCursor; + + internal void updateCursor (Crow.XCursor cursor) { + uint width = 64, height = 64; + if (cursor.Width > width || cursor.Height > height){ + Debug.Print("[DRM] Cursor size {0}x{1} unsupported. Maximum is 64x64.", + cursor.Width, cursor.Height); + return; + } + boMouseCursor = new GBM.BufferObject (gbmDev, width, height, GBM.SurfaceFormat.ARGB8888, + GBM.SurfaceFlags.Cursor64x64 | GBM.SurfaceFlags.Write); + + // Copy cursor.Data into a new buffer of the correct size + byte[] cursor_data = new byte[width * height * 4]; + for (uint y = 0; y < cursor.Height; y++) + { + uint dst_offset = y * width * 4; + uint src_offset = y * cursor.Width * 4; + uint src_length = cursor.Width * 4; + Array.Copy( + cursor.data, src_offset, + cursor_data, dst_offset, + src_length); + } + + boMouseCursor.Data = cursor_data; + uint crtcid = currentCrtc.Id; + + unsafe { + drmModeSetCursor2 (fd_gpu, crtcid, + (uint)boMouseCursor.handle->Handle32, width, height, (int)cursor.Xhot, (int)cursor.Yhot); + drmModeMoveCursor (fd_gpu, crtcid, 0, 0); + } + } + internal void moveCursor (uint x, uint y){ + drmModeMoveCursor (fd_gpu, currentCrtc.Id, x, y); + } + #endregion +// void initGbm (){ +// gbm_surface = Gbm.CreateSurface(gbm_device, mode.hdisplay, mode.vdisplay, SurfaceFormat.ARGB8888, SurfaceFlags.Rendering | SurfaceFlags.Scanout); +// if (gbm_surface == IntPtr.Zero) +// throw new NotSupportedException("[GBM] Failed to create GBM surface for rendering"); +// +// unsafe { +// gbm_bo* bo = Gbm.CreateBO (gbm_device, mode.hdisplay, mode.vdisplay, SurfaceFormat.ARGB8888, SurfaceFlags.Scanout); +// if (bo == null) +// Console.WriteLine ("failed to create a BufferObject for screen 0"); +// else { +// uint fb_id = screens [0].BindBuffer (bo); +// // if (paint (bo)) +// // Console.WriteLine ("[DRI] bo paint succeed"); +// // ModeDirtyFB (fd_gpu, fb_id, IntPtr.Zero, 0); +// } +// // //Gbm.DestroyBuffer (bo); +// ModeAddFB (fd_gpu, bo->Width, bo->Height,(byte)depth, (byte)bpp, bo->Stride, bo->Handle32, out fb_id); +// bo->SetUserData ((IntPtr)fb_id, IntPtr.Zero); +// +// int ret = ModeSetCrtc(fd_gpu, crtc_id, fb_id, x, y, &connector_id, 1, ref mode); +// } +// } +// unsafe public drmPlane GetPlane (uint id) { +// drmPlane p = new drmPlane(); +// drmPlane* pPlane = ModeGetPlane (fd_gpu, id); +// if (pPlane != null) { +// p = *pPlane; +// ModeFreePlane (pPlane); +// } +// return p; +// } +// public void SetPlane (drmPlane p, uint flags, uint crtc_w, uint crtc_h, uint src_w, uint src_h) { +// ModeSetPlane (fd_gpu, p.plane_id, p.crtc_id, p.fb_id, flags, +// (int)p.crtc_x, (int)p.crtc_y, +// crtc_w, crtc_h, +// p.x, p.y, +// src_w, src_h); +// +// +// } + + #region IDisposable implementation + ~GPUControler(){ + Dispose (false); + } + public void Dispose () + { + Dispose (true); + GC.SuppressFinalize (this); + } + protected virtual void Dispose (bool disposing){ + if (cairoDev != null) { + cairoDev.Release (); + CairoSurf.Dispose (); + cairoDev.Dispose (); + cairoDev = null; + CairoSurf = null; + } + + if (boMouseCursor != null) + boMouseCursor.Dispose (); + boMouseCursor = null; + if (eglctx != null) + eglctx.Dispose (); + eglctx = null; + + if (gbmSurf != null) + gbmSurf.Dispose (); + if (gbmDev != null) + gbmDev.Dispose (); + if (currentCrtc != null) + currentCrtc.Dispose (); + if (connector != null) + connector.Dispose (); + if (resources != null) + resources.Dispose (); + resources = null; + if (fd_gpu > 0) + Libc.close (fd_gpu); + fd_gpu = -1; + Console.WriteLine ("disposing ok"); + } + #endregion + + #region dllimports + const string lib = "libdrm"; + [DllImport(lib, EntryPoint = "drmHandleEvent", CallingConvention = CallingConvention.Cdecl)] + public static extern int HandleEvent(int fd, ref EventContext evctx); + [DllImport(lib, CallingConvention = CallingConvention.Cdecl)] + public static extern int drmModeAddFB(int fd, uint width, uint height, byte depth, + byte bpp, uint stride, uint bo_handle, out uint buf_id); + [DllImport(lib, CallingConvention = CallingConvention.Cdecl)] + public static extern int drmModeRmFB(int fd, int bufferId); + [DllImport(lib, EntryPoint = "drmModeDirtyFB", CallingConvention = CallingConvention.Cdecl)] + public static extern int ModeDirtyFB(int fd, uint bufferId, IntPtr clips, uint num_clips); + + + [DllImport(lib, EntryPoint = "drmModeGetFB", CallingConvention = CallingConvention.Cdecl)] + unsafe internal static extern drmFrameBuffer* ModeGetFB(int fd, uint fb_id); + [DllImport(lib, EntryPoint = "drmModeGetPlaneResources", CallingConvention = CallingConvention.Cdecl)] + unsafe internal static extern drmPlaneRes* ModeGetPlaneResources(int fd); + + [DllImport(lib, EntryPoint = "drmModeFreeFB", CallingConvention = CallingConvention.Cdecl)] + unsafe internal static extern void ModeFreeFB(drmFrameBuffer* ptr); + [DllImport(lib, EntryPoint = "drmModeFreePlaneResources", CallingConvention = CallingConvention.Cdecl)] + unsafe internal static extern void ModeFreePlaneResources(drmPlaneRes* ptr); + + [DllImport(lib, EntryPoint = "drmModeSetPlane", CallingConvention = CallingConvention.Cdecl)] + unsafe static extern int ModeSetPlane(int fd, uint plane_id, uint crtc_id, + uint fb_id, uint flags, + int crtc_x, int crtc_y, + uint crtc_w, uint crtc_h, + uint src_x, uint src_y, + uint src_w, uint src_h); + + [DllImport(lib, EntryPoint = "drmModePageFlip", CallingConvention = CallingConvention.Cdecl)] + static extern int ModePageFlip(int fd, int crtc_id, int fb_id, + PageFlipFlags flags, ref int user_data); + + [DllImport(lib, CallingConvention = CallingConvention.Cdecl)] + unsafe static extern int drmModeSetCrtc(int fd, uint crtcId, uint bufferId, uint x, uint y, uint* connectors, int count, ref ModeInfo mode); + + [DllImport(lib, CallingConvention = CallingConvention.Cdecl)] + internal static extern int drmModeSetCursor2(int fd, uint crtcId, uint bo_handle, uint width, uint height, int hot_x, int hot_y); + + [DllImport(lib, CallingConvention = CallingConvention.Cdecl)] + internal static extern int drmModeMoveCursor(int fd, uint crtcId, uint x, uint y); + #endregion + + +// unsafe static bool paint(gbm_bo * bo) +// { +// uint w = (uint)bo->Width; +// uint h = (uint)bo->Height; +// uint stride = (uint)bo->Stride; +// +// Console.WriteLine ("trying to map bo: {0}x{1} stride:{2}", w, h, stride); +// bool success = false; +// try { +// unsafe { +// IntPtr map_data = IntPtr.Zero; +// IntPtr addr = Gbm.Map (bo, 0, 0, w, h, TransferFlags.Write, ref stride, out map_data); +// if (addr == IntPtr.Zero || map_data == IntPtr.Zero) { +// Console.WriteLine ("failed to mmap gbm bo"); +// return false; +// } +// Console.WriteLine ("addr = {0}", addr.ToString()); +// byte* b = (byte*)addr; +// for (int y = 0; y < h; y++) { +// for (int x = 0; x < w; x++) { +// *(b + x + y * stride) = 0xff; +// } +// } +// Gbm.Unmap (bo, map_data); +// success = true; +// } +// } catch (Exception ex) { +// Console.WriteLine (ex.ToString ()); +// } +// return success; +// } + } +} \ No newline at end of file diff --git a/testDrm/src/Linux/DRI/Connector.cs b/testDrm/src/Linux/DRI/Connector.cs new file mode 100644 index 00000000..97acf4b8 --- /dev/null +++ b/testDrm/src/Linux/DRI/Connector.cs @@ -0,0 +1,190 @@ +// +// Connector.cs +// +// Author: +// Stefanos Apostolopoulos +// Jean-Philippe Bruyère +// +// Copyright (c) 2006-2014 Stefanos Apostolopoulos +// Copyright (c) 2013-2017 Jean-Philippe Bruyère +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using System.Runtime.InteropServices; + +namespace Linux.DRI +{ + #region Enums + public enum ConnectionStatus + { + Connected = 1, + Disconnected = 2, + Unknown = 3 + } + public enum ConnectorType + { + Unknown = 0, + VGA=1, + DVII=2, + DVID=3, + DVIA=4, + Composite=5, + SVIDEO=6, + LVDS=7, + Component=8, + PinDIN9 = 9, + DisplayPort=10, + HDMIA=11, + HDMIB=12, + TV=13, + eDP=14, + VIRTUAL=15, + DSI=16, + DPI=17 + } + public enum SubPixel + { + Unknown = 1, + HorizontalRgb = 2, + HorizontalBgr = 3, + VerticalRgb = 4, + VerticalBgr = 5, + None = 6 + } + #endregion + + [StructLayout(LayoutKind.Sequential)] + unsafe internal struct drmConnector + { + public uint connector_id; + public uint encoder_id; + public ConnectorType connector_type; + public uint connector_type_id; + public ConnectionStatus connection; + public uint mmWidth, mmHeight; + public SubPixel subpixel; + + public int count_modes; + public ModeInfo* modes; + + public int count_props; + public uint *props; + public ulong *prop_values; + + public int count_encoders; + public uint *encoders; + } + [StructLayout(LayoutKind.Sequential)] + unsafe public struct ModeInfo + { + public uint clock; + public ushort hdisplay, hsync_start, hsync_end, htotal, hskew; + public ushort vdisplay, vsync_start, vsync_end, vtotal, vscan; + + public int vrefresh; // refresh rate * 1000 + + public uint flags; + public uint type; + public fixed sbyte name[32]; + + public string Name { + get { + fixed( sbyte* bytes = name) + return new string (bytes); + } + } + + public override string ToString () + { + return string.Format ("{0} {1} {2} {3} {4} {5} {6} {7} {8} {9} {10}", + Name, clock, hdisplay, hsync_start, hsync_end, htotal, hskew, + vdisplay, vsync_start, vsync_end, vtotal, vscan, vrefresh); + } + } + + unsafe public class Connector : IDisposable + { + #region pinvoke + [DllImport("libdrm", EntryPoint = "drmModeGetConnector", CallingConvention = CallingConvention.Cdecl)] + internal static extern drmConnector* ModeGetConnector(int fd, uint connector_id); + [DllImport("libdrm", EntryPoint = "drmModeFreeConnector", CallingConvention = CallingConvention.Cdecl)] + internal static extern void ModeFreeConnector(drmConnector* ptr); + #endregion + + int fd_gpu; + drmConnector* handle; + + #region ctor + public Connector (int _fd_gpu, uint _id) + { + fd_gpu = _fd_gpu; + handle = ModeGetConnector (fd_gpu, _id); + + if (handle == null) + throw new NotSupportedException("[DRI] drmModeGetConnector failed."); + } + #endregion + + public uint Id { get { return handle->connector_id; }} + public ConnectionStatus State { get { return handle->connection; }} + public ConnectorType Type { get { return handle->connector_type; }} + public SubPixel SubPixel { get { return handle->subpixel; }} + + public Encoder CurrentEncoder { + get { + return handle->encoder_id == 0 ? null : new Encoder (fd_gpu, handle->encoder_id); + } + } + + public ModeInfo[] Modes { + get { + ModeInfo[] tmp = new ModeInfo[handle->count_modes]; + for (int i = 0; i < handle->count_modes; i++) { + ModeInfo m = *(handle->modes + i); + tmp [i] = m; + } + return tmp; + } + } + + #region IDisposable implementation + ~Connector(){ + Dispose (false); + } + public void Dispose () + { + Dispose (true); + GC.SuppressFinalize (this); + } + protected virtual void Dispose (bool disposing){ + unsafe { + if (handle != null) + ModeFreeConnector (handle); + handle = null; + } + } + #endregion + + public override string ToString () + { + return string.Format ("Connector: Id={0}, State={1}, Type={2}, SubPixel={3}", Id, State, Type, SubPixel); + } + } +} + diff --git a/testDrm/src/Linux/DRI/Crtc.cs b/testDrm/src/Linux/DRI/Crtc.cs new file mode 100644 index 00000000..0ec316ef --- /dev/null +++ b/testDrm/src/Linux/DRI/Crtc.cs @@ -0,0 +1,104 @@ +// +// Crtc.cs +// +// Author: +// Stefanos Apostolopoulos +// Jean-Philippe Bruyère +// +// Copyright (c) 2006-2014 Stefanos Apostolopoulos +// Copyright (c) 2013-2017 Jean-Philippe Bruyère +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using System.Runtime.InteropServices; + +namespace Linux.DRI +{ + [StructLayout(LayoutKind.Sequential)] + internal struct drmCrtc + { + public uint crtc_id; + public uint buffer_id; + + public uint x, y; + public uint width, height; + public int mode_valid; + public ModeInfo mode; + + public int gamma_size; + } + + unsafe public class Crtc : IDisposable + { + #region pinvoke + [DllImport("libdrm", EntryPoint = "drmModeGetCrtc", CallingConvention = CallingConvention.Cdecl)] + internal static extern drmCrtc* ModeGetCrtc(int fd, uint crtcId); + [DllImport("libdrm", EntryPoint = "drmModeFreeCrtc", CallingConvention = CallingConvention.Cdecl)] + internal static extern void ModeFreeCrtc(drmCrtc* ptr); + #endregion + + int fd_gpu; + internal drmCrtc* handle; + + #region ctor + internal Crtc (int _fd_gpu, uint _id) + { + fd_gpu = _fd_gpu; + handle = ModeGetCrtc (fd_gpu, _id); + + if (handle == null) + throw new NotSupportedException("[DRI] drmModeGetCrtc failed."); + } + #endregion + + public uint Id { get { return handle->crtc_id; }} + public ModeInfo CurrentMode { get { return handle->mode; }} + public uint CurrentFbId { get { return handle->buffer_id; }} + public bool ModeIsValid { get { return handle->mode_valid == 0 ? false : true; }} + public uint X { get { return handle->x; }} + public uint Y { get { return handle->x; }} + public uint Height { get { return handle->height; }} + public uint Width { get { return handle->width; }} + public int GammaSize { get { return handle->gamma_size; }} + + #region IDisposable implementation + ~Crtc(){ + Dispose (false); + } + public void Dispose () + { + Dispose (true); + GC.SuppressFinalize (this); + } + protected virtual void Dispose (bool disposing){ + unsafe { + if (handle != null) + ModeFreeCrtc (handle); + handle = null; + } + } + #endregion + + public override string ToString () + { + return string.Format ("[Crtc: Id={0}, CurrentMode={1}, CurrentFbId={2}, ModeIsValid={3}, X={4}, Y={5}, Height={6}, Width={7}, GammaSize={8}]", Id, CurrentMode, CurrentFbId, ModeIsValid, X, Y, Height, Width, GammaSize); + } + } +} + diff --git a/testDrm/src/Linux/DRI/Encoder.cs b/testDrm/src/Linux/DRI/Encoder.cs new file mode 100644 index 00000000..a3b3b705 --- /dev/null +++ b/testDrm/src/Linux/DRI/Encoder.cs @@ -0,0 +1,101 @@ +// +// Encoder.cs +// +// Author: +// Stefanos Apostolopoulos +// Jean-Philippe Bruyère +// +// Copyright (c) 2006-2014 Stefanos Apostolopoulos +// Copyright (c) 2013-2017 Jean-Philippe Bruyère +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using System.Runtime.InteropServices; + +namespace Linux.DRI +{ + [StructLayout(LayoutKind.Sequential)] + public struct drmEncoder + { + public uint encoder_id; + public EncoderType encoder_type; + public uint crtc_id; + public uint possible_crtcs; + public uint possible_clones; + } + + unsafe public class Encoder : IDisposable + { + #region pinvoke + [DllImport("libdrm", EntryPoint = "drmModeGetEncoder", CallingConvention = CallingConvention.Cdecl)] + internal static extern drmEncoder* ModeGetEncoder(int fd, uint encoder_id); + [DllImport("libdrm", EntryPoint = "drmModeFreeEncoder", CallingConvention = CallingConvention.Cdecl)] + internal static extern void ModeFreeEncoder(drmEncoder* ptr); + #endregion + + int fd_gpu; + drmEncoder* handle; + + #region ctor + unsafe internal Encoder (int _fd_gpu, uint _id) + { + fd_gpu = _fd_gpu; + handle = ModeGetEncoder (fd_gpu, _id); + + if (handle == null) + throw new NotSupportedException("[DRI] drmModeGetEncoder failed."); + } + #endregion + + public uint Id { get { return handle->encoder_id; }} + public EncoderType Type { get { return handle->encoder_type; }} + public uint PossibleCrtcs { get { return handle->possible_crtcs; }} + public uint PossibleClones { get { return handle->possible_clones; }} + + public Crtc CurrentCrtc { + get { + return handle->crtc_id == 0 ? null : new Crtc (fd_gpu, handle->crtc_id); + } + } + + #region IDisposable implementation + ~Encoder(){ + Dispose (false); + } + public void Dispose () + { + Dispose (true); + GC.SuppressFinalize (this); + } + protected virtual void Dispose (bool disposing){ + unsafe { + if (handle != null) + ModeFreeEncoder (handle); + handle = null; + } + } + #endregion + + public override string ToString () + { + return string.Format ("[Encoder: Id={0}, Type={1}, PossibleCrtcs={2}, PossibleClones={3}]", Id, Type, PossibleCrtcs, PossibleClones); + } + } +} + diff --git a/testDrm/src/Linux/DRI/Plane.cs b/testDrm/src/Linux/DRI/Plane.cs new file mode 100644 index 00000000..80b49455 --- /dev/null +++ b/testDrm/src/Linux/DRI/Plane.cs @@ -0,0 +1,84 @@ +// +// Plane.cs +// +// Author: +// Jean-Philippe Bruyère +// +// Copyright (c) 2013-2017 Jean-Philippe Bruyère +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using System.Runtime.InteropServices; + +namespace Linux.DRI +{ + [StructLayout(LayoutKind.Sequential)] + unsafe public struct drmPlane { + public uint count_formats; + public uint *formats; + public uint plane_id; + + public uint crtc_id; + public uint fb_id; + + public uint crtc_x, crtc_y; + public uint x, y; + + public uint possible_crtcs; + public uint gamma_size; + } + + unsafe public class Plane : IDisposable + { + #region pinvoke + [DllImport("libdrm", EntryPoint = "drmModeGetPlane", CallingConvention = CallingConvention.Cdecl)] + unsafe internal static extern drmPlane* ModeGetPlane(int fd, uint id); + [DllImport("libdrm", EntryPoint = "drmModeFreePlane", CallingConvention = CallingConvention.Cdecl)] + unsafe internal static extern void ModeFreePlane(drmPlane* ptr); + #endregion + + drmPlane* handle; + + internal Plane (drmPlane* _handle) + { + handle = _handle; + } + + public uint Id { get { return handle->plane_id; }} + + #region IDisposable implementation + ~Plane(){ + Dispose (false); + } + public void Dispose () + { + Dispose (true); + GC.SuppressFinalize (this); + } + protected virtual void Dispose (bool disposing){ + unsafe { + if (handle != null) + ModeFreePlane (handle); + handle = null; + } + } + #endregion + } +} + diff --git a/testDrm/src/Linux/DRI/Resources.cs b/testDrm/src/Linux/DRI/Resources.cs new file mode 100644 index 00000000..d4b136d8 --- /dev/null +++ b/testDrm/src/Linux/DRI/Resources.cs @@ -0,0 +1,117 @@ +// +// Resources.cs +// +// Author: +// Jean-Philippe Bruyère +// +// Copyright (c) 2013-2017 Jean-Philippe Bruyère +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using System.Runtime.InteropServices; + +namespace Linux.DRI +{ + [StructLayout(LayoutKind.Sequential)] + unsafe internal struct drmResources + { + public int count_fbs; + public uint* fbs; + public int count_crtcs; + public uint* crtcs; + public int count_connectors; + public uint* connectors; + public int count_encoders; + public uint* encoders; + public uint min_width, max_width; + public uint min_height, max_height; + } + + unsafe public class Resources: IDisposable + { + #region pinvoke + [DllImport("libdrm", EntryPoint = "drmModeGetResources", CallingConvention = CallingConvention.Cdecl)] + internal static extern drmResources* ModeGetResources(int fd); + [DllImport("libdrm", EntryPoint = "drmModeFreeResources", CallingConvention = CallingConvention.Cdecl)] + internal static extern void ModeFreeResources(drmResources* ptr); + #endregion + + int gpu_fd; + drmResources* handle; + + #region ctor + public Resources (int fd_gpu) + { + gpu_fd = fd_gpu; + handle = ModeGetResources (fd_gpu); + + if (handle == null) + throw new NotSupportedException("[DRI] drmModeGetResources failed."); + } + #endregion + + public uint min_width { get { return handle->min_width; }} + public uint max_width { get { return handle->max_width; }} + public uint min_height { get { return handle->min_height; }} + public uint max_height { get { return handle->max_height; }} + + public Connector[] Connectors { + get { + Connector[] tmp = new Connector[handle->count_connectors]; + for (int i = 0; i < handle->count_connectors; i++) + tmp [i] = new Connector (gpu_fd, *(handle->connectors + i)); + return tmp; + } + } + public Encoder[] Encoders { + get { + Encoder[] tmp = new Encoder[handle->count_encoders]; + for (int i = 0; i < handle->count_encoders; i++) + tmp [i] = new Encoder (gpu_fd, *(handle->encoders + i)); + return tmp; + } + } + public Crtc[] Crtcs { + get { + Crtc[] tmp = new Crtc[handle->count_encoders]; + for (int i = 0; i < handle->count_crtcs; i++) + tmp [i] = new Crtc (gpu_fd, *(handle->crtcs + i)); + return tmp; + } + } + + #region IDisposable implementation + ~Resources(){ + Dispose (false); + } + public void Dispose () + { + Dispose (true); + GC.SuppressFinalize (this); + } + protected virtual void Dispose (bool disposing){ + if (handle != null) + ModeFreeResources (handle); + handle = null; + } + #endregion + + } +} + diff --git a/testDrm/src/Linux/DRM.cs b/testDrm/src/Linux/DRM.cs deleted file mode 100644 index 3bdd9504..00000000 --- a/testDrm/src/Linux/DRM.cs +++ /dev/null @@ -1,291 +0,0 @@ -// -// DRM.cs -// -// Author: -// Jean-Philippe Bruyère -// -// Copyright (c) 2013-2017 Jean-Philippe Bruyère -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -using System; -using System.Runtime.InteropServices; - -namespace Crow.Linux.DRI { - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void VBlankCallback(int fd, int sequence, int tv_sec, int tv_usec, IntPtr user_data); - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void PageFlipCallback(int fd, int sequence, int tv_sec, int tv_usec, ref int user_data); - - enum ModeConnection - { - Connected = 1, - Disconnected = 2, - Unknown = 3 - } - enum ModeConnectorType - { - Unknown = 0, - VGA=1, - DVII=2, - DVID=3, - DVIA=4, - Composite=5, - SVIDEO=6, - LVDS=7, - Component=8, - PinDIN9 = 9, - DisplayPort=10, - HDMIA=11, - HDMIB=12, - TV=13, - eDP=14, - VIRTUAL=15, - DSI=16, - DPI=17 - } - enum ModeEncoderType - { - NONE=0, - DAC=1, - TMDS=2, - LVDS=3, - TVDAC=4, - VIRTUAL=5, - DSI=6, - DPMST=7, - DPI=8, - } - enum ModeSubPixel - { - Unknown = 1, - HorizontalRgb = 2, - HorizontalBgr = 3, - VerticalRgb = 4, - VerticalBgr = 5, - None = 6 - } - - [Flags] - enum PageFlipFlags - { - FlipEvent = 0x01, - FlipAsync = 0x02, - FlipFlags = FlipEvent | FlipAsync - } - - [Flags] - enum ModeFlags - { - /* Video mode flags */ - /* bit compatible with the xorg definitions. */ - PHSYNC = 0x01, - NHSYNC = 0x02, - PVSYNC = 0x04, - NVSYNC = 0x08, - INTERLACE = 0x10, - DBLSCAN = 0x20, - CSYNC = 0x40, - PCSYNC = 0x80, - NCSYNC = 0x10, - HSKEW = 0x0200, - BCAST = 0x0400, - PIXMUX = 0x0800, - DBLCLK = 0x1000, - CLKDIV2 = 0x2000, - // FLAG_3D_MASK (0x1f<<14) - // FLAG_3D_NONE = 0x0; - // FLAG_3D_FRAME_PACKING = 0x4000, - // FLAG_3D_FIELD_ALTERNATIVE = 0x8000, - // FLAG_3D_LINE_ALTERNATIVE (3<<14) - // FLAG_3D_SIDE_BY_SIDE_FULL (4<<14) - // FLAG_3D_L_DEPTH (5<<14) - // FLAG_3D_L_DEPTH_GFX_GFX_DEPTH (6<<14) - // FLAG_3D_TOP_AND_BOTTOM (7<<14) - // FLAG_3D_SIDE_BY_SIDE_HALF (8<<14) - } - - [StructLayout(LayoutKind.Sequential)] - public struct EventContext - { - public int version; - public IntPtr vblank_handler; - public IntPtr page_flip_handler; - public static readonly int Version = 2; - } - - [StructLayout(LayoutKind.Sequential)] - unsafe struct ModeConnector - { - public int connector_id; - public int encoder_id; - public ModeConnectorType connector_type; - public int connector_type_id; - public ModeConnection connection; - public int mmWidth, mmHeight; - public ModeSubPixel subpixel; - - public int count_modes; - public ModeInfo* modes; - - public int count_props; - public int *props; - public long *prop_values; - - public int count_encoders; - public int *encoders; - } - - [StructLayout(LayoutKind.Sequential)] - struct ModeCrtc - { - public int crtc_id; - public int buffer_id; - - public int x, y; - public int width, height; - public int mode_valid; - public ModeInfo mode; - - public int gamma_size; - } - - [StructLayout(LayoutKind.Sequential)] - struct ModeEncoder - { - public int encoder_id; - public ModeEncoderType encoder_type; - public int crtc_id; - public int possible_crtcs; - public int possible_clones; - } - - [StructLayout(LayoutKind.Sequential)] - unsafe struct ModeInfo - { - public uint clock; - public ushort hdisplay, hsync_start, hsync_end, htotal, hskew; - public ushort vdisplay, vsync_start, vsync_end, vtotal, vscan; - - public int vrefresh; // refresh rate * 1000 - - public uint flags; - public uint type; - public fixed sbyte name[32]; - } - - [StructLayout(LayoutKind.Sequential)] - unsafe struct ModeRes - { - public int count_fbs; - public uint* fbs; - public int count_crtcs; - public uint* crtcs; - public int count_connectors; - public uint* connectors; - public int count_encoders; - public uint* encoders; - public uint min_width, max_width; - public uint min_height, max_height; - } - - - - public class GPUControler : IDisposable { - int fd_gpu = -1; - ModeRes resources = new ModeRes (); - - public GPUControler(string gpu_path = "/dev/dri/card0"){ - fd_gpu = Libc.open(gpu_path, OpenFlags.ReadWrite | OpenFlags.CloseOnExec); - if (fd_gpu < 0) - throw new NotSupportedException("[KMS] Failed to open gpu"); - - unsafe { - ModeRes* ptrRes = ModeGetResources (fd_gpu); - resources = *ptrRes; - ModeFreeResources (ptrRes); - } - -// if (resources == null) -// throw new NotSupportedException("[KMS] Drm.ModeGetResources failed."); - } - - #region IDisposable implementation - ~GPUControler(){ - Dispose (false); - } - public void Dispose () - { - Dispose (true); - GC.SuppressFinalize (this); - } - protected virtual void Dispose (bool disposing){ - if (fd_gpu > 0) - Libc.close (fd_gpu); - fd_gpu = -1; - } - #endregion - - #region ioctl overrides - const string lib = "libdrm"; - [DllImport(lib, EntryPoint = "drmHandleEvent", CallingConvention = CallingConvention.Cdecl)] - public static extern int HandleEvent(int fd, ref EventContext evctx); - - [DllImport(lib, EntryPoint = "drmModeAddFB", CallingConvention = CallingConvention.Cdecl)] - public static extern int ModeAddFB(int fd, int width, int height, byte depth, - byte bpp, int pitch, int bo_handle, - out int buf_id); - - [DllImport(lib, EntryPoint = "drmModeRmFB", CallingConvention = CallingConvention.Cdecl)] - public static extern int ModeRmFB(int fd, int bufferId); - - - [DllImport(lib, EntryPoint = "drmModeGetResources", CallingConvention = CallingConvention.Cdecl)] - unsafe static extern ModeRes* ModeGetResources(int fd); - [DllImport(lib, EntryPoint = "drmModeGetCrtc", CallingConvention = CallingConvention.Cdecl)] - public static extern IntPtr ModeGetCrtc(int fd, int crtcId); - [DllImport(lib, EntryPoint = "drmModeGetConnector", CallingConvention = CallingConvention.Cdecl)] - public static extern IntPtr ModeGetConnector(int fd, int connector_id); - [DllImport(lib, EntryPoint = "drmModeGetEncoder", CallingConvention = CallingConvention.Cdecl)] - public static extern IntPtr ModeGetEncoder(int fd, int encoder_id); - - [DllImport(lib, EntryPoint = "drmModeFreeResources", CallingConvention = CallingConvention.Cdecl)] - unsafe static extern void ModeFreeResources(ModeRes* ptr); - [DllImport(lib, EntryPoint = "drmModeFreeCrtc", CallingConvention = CallingConvention.Cdecl)] - public static extern void ModeFreeCrtc(IntPtr ptr); - [DllImport(lib, EntryPoint = "drmModeFreeConnector", CallingConvention = CallingConvention.Cdecl)] - public static extern void ModeFreeConnector(IntPtr ptr); - [DllImport(lib, EntryPoint = "drmModeFreeEncoder", CallingConvention = CallingConvention.Cdecl)] - public static extern void ModeFreeEncoder(IntPtr ptr); - - [DllImport(lib, EntryPoint = "drmModePageFlip", CallingConvention = CallingConvention.Cdecl)] - static extern int ModePageFlip(int fd, int crtc_id, int fb_id, - PageFlipFlags flags, ref int user_data); - - [DllImport(lib, EntryPoint = "drmModeSetCrtc", CallingConvention = CallingConvention.Cdecl)] - unsafe static extern int ModeSetCrtc(int fd, int crtcId, int bufferId, - int x, int y, int* connectors, int count, ModeInfo* mode); - - [DllImport(lib, EntryPoint = "drmModeSetCursor2", CallingConvention = CallingConvention.Cdecl)] - public static extern int SetCursor(int fd, int crtcId, int bo_handle, int width, int height, int hot_x, int hot_y); - - [DllImport(lib, EntryPoint = "drmModeMoveCursor", CallingConvention = CallingConvention.Cdecl)] - public static extern int MoveCursor(int fd, int crtcId, int x, int y); - #endregion - } -} \ No newline at end of file diff --git a/testDrm/src/Linux/GBM/BufferObject.cs b/testDrm/src/Linux/GBM/BufferObject.cs new file mode 100644 index 00000000..fd6adcb8 --- /dev/null +++ b/testDrm/src/Linux/GBM/BufferObject.cs @@ -0,0 +1,123 @@ +// +// Device.cs +// +// Author: +// Jean-Philippe Bruyère +// +// Copyright (c) 2013-2017 Jean-Philippe Bruyère +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using System.Runtime.InteropServices; + +namespace Linux.GBM +{ + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void DestroyUserDataCallback(ref GBM.gbm_bo bo, IntPtr data); + + [StructLayout(LayoutKind.Sequential)] + public struct gbm_bo { + IntPtr device; + public uint Width, Height; + public SurfaceFormat Format; + public SurfaceFlags Flags; + + public uint Handle32 + { + get { return (uint)BufferObject.gbm_bo_get_handle(ref this); } + } + public uint Stride + { + get { return BufferObject.gbm_bo_get_stride(ref this); } + } + public void SetUserData(IntPtr data, DestroyUserDataCallback destroyFB) + { + BufferObject.gbm_bo_set_user_data(ref this, data, destroyFB); + } + } + unsafe public class BufferObject : IDisposable + { + #region pinvoke + [DllImport("gbm", CallingConvention = CallingConvention.Cdecl)] + static extern gbm_bo* gbm_bo_create (IntPtr gbm, uint width, uint height, SurfaceFormat format, SurfaceFlags flags); + [DllImport("gbm", CallingConvention = CallingConvention.Cdecl)] + internal static extern void gbm_bo_destroy (gbm_bo* bo); + [DllImport("gbm", CallingConvention = CallingConvention.Cdecl)] + internal static extern int gbm_bo_write(gbm_bo* bo, IntPtr buf, IntPtr count); + [DllImport("gbm", CallingConvention = CallingConvention.Cdecl)] + internal static extern Device gbm_bo_get_device(ref gbm_bo bo); + [DllImport("gbm", CallingConvention = CallingConvention.Cdecl)] + internal static extern ulong gbm_bo_get_handle(ref gbm_bo bo); + [DllImport("gbm", CallingConvention = CallingConvention.Cdecl)] + internal static extern int gbm_bo_get_height(ref gbm_bo bo); + [DllImport("gbm", CallingConvention = CallingConvention.Cdecl)] + internal static extern int gbm_bo_get_width(ref gbm_bo bo); + [DllImport("gbm", CallingConvention = CallingConvention.Cdecl)] + internal static extern uint gbm_bo_get_stride (ref gbm_bo bo); + [DllImport("gbm", CallingConvention = CallingConvention.Cdecl)] + internal static extern void gbm_bo_set_user_data(ref gbm_bo bo, IntPtr data, DestroyUserDataCallback callback); + [DllImport("gbm", CallingConvention = CallingConvention.Cdecl)] + internal static extern IntPtr gbm_bo_get_user_data (IntPtr bo); + [DllImport("gbm", CallingConvention = CallingConvention.Cdecl)] + internal static extern IntPtr gbm_bo_map (ref gbm_bo bo, uint x, uint y, uint width, uint height, TransferFlags flags, ref uint stride, out IntPtr data); + [DllImport("gbm", CallingConvention = CallingConvention.Cdecl)] + internal static extern void gbm_bo_unmap (ref gbm_bo bo, IntPtr data); + #endregion + + internal gbm_bo* handle; + + #region ctor + public BufferObject (gbm_bo* _handle){ + handle = _handle; + } + public BufferObject (Device dev, uint _width, uint _height, SurfaceFormat format, SurfaceFlags flags) + { + handle = gbm_bo_create (dev.handle, _width, _height, format, flags); + if (handle == null) + throw new NotSupportedException("[GBM] BO creation failed."); + } + #endregion + + public uint Stride { get { return handle->Stride; }} + public byte[] Data { + set { + fixed (byte* pdata = value) { + gbm_bo_write (handle, (IntPtr)pdata, (IntPtr)value.Length); + } + } + } + + #region IDisposable implementation + ~BufferObject(){ + Dispose (false); + } + public void Dispose () + { + Dispose (true); + GC.SuppressFinalize (this); + } + protected virtual void Dispose (bool disposing){ + if (handle != null) + gbm_bo_destroy (handle); + handle = null; + } + #endregion + } +} + diff --git a/testDrm/src/Linux/GBM/Device.cs b/testDrm/src/Linux/GBM/Device.cs new file mode 100644 index 00000000..a52b06c2 --- /dev/null +++ b/testDrm/src/Linux/GBM/Device.cs @@ -0,0 +1,76 @@ +// +// Device.cs +// +// Author: +// Jean-Philippe Bruyère +// +// Copyright (c) 2013-2017 Jean-Philippe Bruyère +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using System.Runtime.InteropServices; + +namespace Linux.GBM +{ + unsafe public class Device : IDisposable + { + #region pinvoke + [DllImport("gbm", EntryPoint = "gbm_create_device", CallingConvention = CallingConvention.Cdecl)] + static extern IntPtr CreateDevice(int fd); + [DllImport("gbm", EntryPoint = "gbm_device_destroy", CallingConvention = CallingConvention.Cdecl)] + static extern void DestroyDevice(IntPtr gbm); + [DllImport("gbm", EntryPoint = "gbm_device_get_fd", CallingConvention = CallingConvention.Cdecl)] + static extern int DeviceGetFD(IntPtr gbm); + [DllImport("gbm", EntryPoint = "gbm_device_is_format_supported", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.Bool)] + static extern bool IsFormatSupported(IntPtr gbm, SurfaceFormat format, SurfaceFlags usage); + #endregion + + int fd_gpu; + internal IntPtr handle; + + #region ctor + public Device (int _fd_gpu) + { + fd_gpu = _fd_gpu; + handle = CreateDevice(fd_gpu); + + if (handle == IntPtr.Zero) + throw new NotSupportedException("[GBM] device creation failed."); + } + #endregion + + #region IDisposable implementation + ~Device(){ + Dispose (false); + } + public void Dispose () + { + Dispose (true); + GC.SuppressFinalize (this); + } + protected virtual void Dispose (bool disposing){ + if (handle != IntPtr.Zero) + DestroyDevice (handle); + handle = IntPtr.Zero; + } + #endregion + } +} + diff --git a/testDrm/src/Linux/GBM/Surface.cs b/testDrm/src/Linux/GBM/Surface.cs new file mode 100644 index 00000000..9257e14e --- /dev/null +++ b/testDrm/src/Linux/GBM/Surface.cs @@ -0,0 +1,183 @@ +// +// Surface.cs +// +// Author: +// Stefanos Apostolopoulos +// Jean-Philippe Bruyère +// +// Copyright (c) 2006-2014 Stefanos Apostolopoulos +// Copyright (c) 2013-2017 Jean-Philippe Bruyère +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using System.Runtime.InteropServices; + +namespace Linux.GBM +{ + public enum SurfaceFormat : uint + { + BigEndian = 1u << 31, + C8 = ((int)('C') | ((int)('8') << 8) | ((int)(' ') << 16) | ((int)(' ') << 24)), + + RGB332 = ((int)('R') | ((int)('G') << 8) | ((int)('B') << 16) | ((int)('8') << 24)), + BGR233 = ((int)('B') | ((int)('G') << 8) | ((int)('R') << 16) | ((int)('8') << 24)), + + XRGB4444 = ((int)('X') | ((int)('R') << 8) | ((int)('1') << 16) | ((int)('2') << 24)), + XBGR4444 = ((int)('X') | ((int)('B') << 8) | ((int)('1') << 16) | ((int)('2') << 24)), + RGBX4444 = ((int)('R') | ((int)('X') << 8) | ((int)('1') << 16) | ((int)('2') << 24)), + BGRX4444 = ((int)('B') | ((int)('X') << 8) | ((int)('1') << 16) | ((int)('2') << 24)), + + ARGB4444 = ((int)('A') | ((int)('R') << 8) | ((int)('1') << 16) | ((int)('2') << 24)), + ABGR4444 = ((int)('A') | ((int)('B') << 8) | ((int)('1') << 16) | ((int)('2') << 24)), + RGBA4444 = ((int)('R') | ((int)('A') << 8) | ((int)('1') << 16) | ((int)('2') << 24)), + BGRA4444 = ((int)('B') | ((int)('A') << 8) | ((int)('1') << 16) | ((int)('2') << 24)), + + XRGB1555 = ((int)('X') | ((int)('R') << 8) | ((int)('1') << 16) | ((int)('5') << 24)), + XBGR1555 = ((int)('X') | ((int)('B') << 8) | ((int)('1') << 16) | ((int)('5') << 24)), + RGBX5551 = ((int)('R') | ((int)('X') << 8) | ((int)('1') << 16) | ((int)('5') << 24)), + BGRX5551 = ((int)('B') | ((int)('X') << 8) | ((int)('1') << 16) | ((int)('5') << 24)), + + ARGB1555 = ((int)('A') | ((int)('R') << 8) | ((int)('1') << 16) | ((int)('5') << 24)), + ABGR1555 = ((int)('A') | ((int)('B') << 8) | ((int)('1') << 16) | ((int)('5') << 24)), + RGBA5551 = ((int)('R') | ((int)('A') << 8) | ((int)('1') << 16) | ((int)('5') << 24)), + BGRA5551 = ((int)('B') | ((int)('A') << 8) | ((int)('1') << 16) | ((int)('5') << 24)), + + RGB565 = ((int)('R') | ((int)('G') << 8) | ((int)('1') << 16) | ((int)('6') << 24)), + BGR565 = ((int)('B') | ((int)('G') << 8) | ((int)('1') << 16) | ((int)('6') << 24)), + + RGB888 = ((int)('R') | ((int)('G') << 8) | ((int)('2') << 16) | ((int)('4') << 24)), + BGR888 = ((int)('B') | ((int)('G') << 8) | ((int)('2') << 16) | ((int)('4') << 24)), + + XRGB8888 = ((int)('X') | ((int)('R') << 8) | ((int)('2') << 16) | ((int)('4') << 24)), + XBGR8888 = ((int)('X') | ((int)('B') << 8) | ((int)('2') << 16) | ((int)('4') << 24)), + RGBX8888 = ((int)('R') | ((int)('X') << 8) | ((int)('2') << 16) | ((int)('4') << 24)), + BGRX8888 = ((int)('B') | ((int)('X') << 8) | ((int)('2') << 16) | ((int)('4') << 24)), + + ARGB8888 = ((int)('A') | ((int)('R') << 8) | ((int)('2') << 16) | ((int)('4') << 24)), + ABGR8888 = ((int)('A') | ((int)('B') << 8) | ((int)('2') << 16) | ((int)('4') << 24)), + RGBA8888 = ((int)('R') | ((int)('A') << 8) | ((int)('2') << 16) | ((int)('4') << 24)), + BGRA8888 = ((int)('B') | ((int)('A') << 8) | ((int)('2') << 16) | ((int)('4') << 24)), + + XRGB2101010 = ((int)('X') | ((int)('R') << 8) | ((int)('3') << 16) | ((int)('0') << 24)), + XBGR2101010 = ((int)('X') | ((int)('B') << 8) | ((int)('3') << 16) | ((int)('0') << 24)), + RGBX1010102 = ((int)('R') | ((int)('X') << 8) | ((int)('3') << 16) | ((int)('0') << 24)), + BGRX1010102 = ((int)('B') | ((int)('X') << 8) | ((int)('3') << 16) | ((int)('0') << 24)), + + ARGB2101010 = ((int)('A') | ((int)('R') << 8) | ((int)('3') << 16) | ((int)('0') << 24)), + ABGR2101010 = ((int)('A') | ((int)('B') << 8) | ((int)('3') << 16) | ((int)('0') << 24)), + RGBA1010102 = ((int)('R') | ((int)('A') << 8) | ((int)('3') << 16) | ((int)('0') << 24)), + BGRA1010102 = ((int)('B') | ((int)('A') << 8) | ((int)('3') << 16) | ((int)('0') << 24)), + + YUYV = ((int)('Y') | ((int)('U') << 8) | ((int)('Y') << 16) | ((int)('V') << 24)), + YVYU = ((int)('Y') | ((int)('V') << 8) | ((int)('Y') << 16) | ((int)('U') << 24)), + UYVY = ((int)('U') | ((int)('Y') << 8) | ((int)('V') << 16) | ((int)('Y') << 24)), + VYUY = ((int)('V') | ((int)('Y') << 8) | ((int)('U') << 16) | ((int)('Y') << 24)), + + AYUV = ((int)('A') | ((int)('Y') << 8) | ((int)('U') << 16) | ((int)('V') << 24)), + + NV12 = ((int)('N') | ((int)('V') << 8) | ((int)('1') << 16) | ((int)('2') << 24)), + NV21 = ((int)('N') | ((int)('V') << 8) | ((int)('2') << 16) | ((int)('1') << 24)), + NV16 = ((int)('N') | ((int)('V') << 8) | ((int)('1') << 16) | ((int)('6') << 24)), + NV61 = ((int)('N') | ((int)('V') << 8) | ((int)('6') << 16) | ((int)('1') << 24)), + + YUV410 = ((int)('Y') | ((int)('U') << 8) | ((int)('V') << 16) | ((int)('9') << 24)), + YVU410 = ((int)('Y') | ((int)('V') << 8) | ((int)('U') << 16) | ((int)('9') << 24)), + YUV411 = ((int)('Y') | ((int)('U') << 8) | ((int)('1') << 16) | ((int)('1') << 24)), + YVU411 = ((int)('Y') | ((int)('V') << 8) | ((int)('1') << 16) | ((int)('1') << 24)), + YUV420 = ((int)('Y') | ((int)('U') << 8) | ((int)('1') << 16) | ((int)('2') << 24)), + YVU420 = ((int)('Y') | ((int)('V') << 8) | ((int)('1') << 16) | ((int)('2') << 24)), + YUV422 = ((int)('Y') | ((int)('U') << 8) | ((int)('1') << 16) | ((int)('6') << 24)), + YVU422 = ((int)('Y') | ((int)('V') << 8) | ((int)('1') << 16) | ((int)('6') << 24)), + YUV444 = ((int)('Y') | ((int)('U') << 8) | ((int)('2') << 16) | ((int)('4') << 24)), + YVU444 = ((int)('Y') | ((int)('V') << 8) | ((int)('2') << 16) | ((int)('4') << 24)), + } + [Flags]public enum SurfaceFlags : uint + { + Scanout = (1 << 0), + Cursor64x64 = (1 << 1), + Rendering = (1 << 2), + Write = (1 << 3), + Linear = (1 << 4), + } + [Flags]public enum TransferFlags : uint { + /// Buffer contents read back (or accessed directly) at transfer create time. + Read = 1 << 0, + /// Buffer contents will be written back at unmap time (or modified as a result of being accessed directly). + Write = 1 << 1, + /// Read/modify/write + ReadWrite = Read | Write, + } + + unsafe public class Surface : IDisposable + { + #region pinvoke + [DllImport("gbm", CallingConvention = CallingConvention.Cdecl)] + static extern IntPtr gbm_surface_create (IntPtr gbm, int width, int height, SurfaceFormat format, SurfaceFlags flags); + [DllImport("gbm", CallingConvention = CallingConvention.Cdecl)] + static extern void gbm_surface_destroy (IntPtr surface); + [DllImport("gbm", CallingConvention = CallingConvention.Cdecl)] + static extern gbm_bo* gbm_surface_lock_front_buffer (IntPtr surface); + [DllImport("gbm", CallingConvention = CallingConvention.Cdecl)] + static extern void gbm_surface_release_buffer (IntPtr surface, gbm_bo* buffer); + [DllImport("gbm", CallingConvention = CallingConvention.Cdecl)] + static extern int gbm_surface_has_free_buffers (IntPtr surface); + #endregion + + internal IntPtr handle; + + #region ctor + public Surface (Device gbmDev, int width, int height, SurfaceFlags flags, SurfaceFormat format = SurfaceFormat.ARGB8888) + { + handle = gbm_surface_create(gbmDev.handle, width, height, format, flags); + + if (handle == IntPtr.Zero) + throw new NotSupportedException("[GBM] Failed to create GBM surface"); + } + #endregion + + public bool HasFreeBuffers { get { return gbm_surface_has_free_buffers (handle) > 0; }} + + public gbm_bo* Lock (){ + gbm_bo* bo = gbm_surface_lock_front_buffer (handle); + if (bo == null) + throw new Exception ("[GBM]: Failed to lock front buffer."); + return bo; + } + public void Release (gbm_bo* bo) { + gbm_surface_release_buffer (handle, bo); + } + + #region IDisposable implementation + ~Surface(){ + Dispose (false); + } + public void Dispose () + { + Dispose (true); + GC.SuppressFinalize (this); + } + protected virtual void Dispose (bool disposing){ + if (handle != IntPtr.Zero) + gbm_surface_destroy (handle); + handle = IntPtr.Zero; + } + #endregion + } +} + diff --git a/testDrm/src/Linux/VT.cs b/testDrm/src/Linux/VT.cs index a9402c85..c555fe2a 100644 --- a/testDrm/src/Linux/VT.cs +++ b/testDrm/src/Linux/VT.cs @@ -26,7 +26,7 @@ using System; using System.Runtime.InteropServices; -namespace Crow.Linux.VT { +namespace Linux.VT { public enum KDMode : byte { TEXT = 0x00, GRAPHICS= 0x01, diff --git a/testDrm/testDrm.csproj b/testDrm/testDrm.csproj index b033b0bc..5b4f7f84 100644 --- a/testDrm/testDrm.csproj +++ b/testDrm/testDrm.csproj @@ -44,7 +44,6 @@ - @@ -62,8 +61,6 @@ - - Code @@ -71,17 +68,33 @@ - + + + + + + + + + + + + + + + + + @@ -92,4 +105,8 @@ + + + + \ No newline at end of file diff --git a/testDrm/tests.cs b/testDrm/tests.cs index 026ce199..1098c10c 100644 --- a/testDrm/tests.cs +++ b/testDrm/tests.cs @@ -31,21 +31,191 @@ using System.Runtime.InteropServices; using System.Text; //using static Crow.Linux.VT.VTControler; -using VT = Crow.Linux.VT; -using Crow.Linux.DRI; +using VT = Linux.VT; +using DRI = Linux.DRI; +using System.IO; +using System.Collections.Generic; +using System.Linq; +using Crow; + + namespace testDrm { + public class TestApp : Application { + + public bool Running = true; + + public TestApp () : base () { + + } + public override void Run () + { + Load ("#testDrm.ui.menu.crow").DataSource = this; + Load (@"/mnt/data2/devel/crow/Tests/Interfaces/Divers/0.crow"); + + while(Running){ + try { + base.Run (); + } catch (Exception ex) { + Console.WriteLine (ex.ToString()); + } + } + } + void onQuitClick(object send, Crow.MouseButtonEventArgs e) + { + Running = false; + } + } static class Tests { static void signal_handler (Signal s){ Console.WriteLine ("signal catched: " + s.ToString()); } + static void genEglConstCase (){ + Dictionary dic = new Dictionary (); + + //parseEglConsts ("/home/jp/tmp/EGL/eglplatform.h", ref dic); + parseEglConsts ("/home/jp/tmp/EGL/egl.h", ref dic); + + IOrderedEnumerable> result = dic.OrderBy (p => p.Key); + + foreach (KeyValuePair kv in result) { + Console.WriteLine ("case {0}:\n\treturn \"{1}\";", kv.Key, kv.Value); + } + } + static void parseEglConsts (string path, ref Dictionary dic){ + using (Stream s = new FileStream (path, FileMode.Open)) { + using (StreamReader sr = new StreamReader (s)) { + while (!sr.EndOfStream) { + string l = sr.ReadLine (); + if (!l.StartsWith ("#define")) + continue; + l = l.Substring (8); + string[] ll = l.Split (new char[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries); + string[] cn = ll [0].Split ('_'); + try { + string constName = ""; + + for (int i = 1; i < cn.Length; i++) { + cn [i] = cn [i].ToLowerInvariant (); + constName += char.ToUpperInvariant (cn [i] [0]) + cn [i].Substring (1); + } + + int value = 0; + if (ll [1].StartsWith ("0x")) { + if (int.TryParse (ll [1].Substring (2), System.Globalization.NumberStyles.AllowHexSpecifier, System.Globalization.CultureInfo.CurrentCulture, out value)) { + if (dic.ContainsKey (value)) + dic [value] += "|" + ll [0].Substring (4); + else + dic [value] = ll [0].Substring (4); + continue; + } else + Console.WriteLine ("parsing error: " + l); + } else + Console.WriteLine ("not hex value: " + l); + //Console.WriteLine ("{0}\t= {1},", constName, ll [1]); + } catch (Exception ex) { + Console.WriteLine ("failed: " + l); + } + } + } + } + } static void Main () { - using (GPUControler gpu = new GPUControler ()) { + try { + using (TestApp crowApp = new TestApp ()) { + crowApp.Run (); + } + } catch (Exception ex) { + Console.WriteLine (ex.ToString ()); + } + } + static void testApp () { + int previousVT = -1, appVT = -1; + + if (Kernel.signal (Signal.SIGUSR1, switch_request_handle) < 0) + throw new Exception ("signal handler registation failed"); + if (Kernel.signal (Signal.SIGINT, sigint_handler) < 0) + throw new Exception ("SIGINT handler registation failed"); + + using (VT.VTControler master = new VT.VTControler ()) { + previousVT = master.CurrentVT; + appVT = master.FirstAvailableVT; + master.SwitchTo (appVT); + try { + master.KDMode = VT.KDMode.GRAPHICS; + } catch (Exception ex) { + Console.WriteLine (ex.ToString ()); + } + } + try { + using (TestApp crowApp = new TestApp ()) { + crowApp.Run (); + } + } catch (Exception ex) { + Console.WriteLine (ex.ToString ()); + } + + using (VT.VTControler master = new VT.VTControler ()) { + // try { + // master.KDMode = VT.KDMode.TEXT; + // } catch (Exception ex) { + // Console.WriteLine (ex.ToString ()); + // } + master.SwitchTo (previousVT); } } + + static void testKMS(){ + int previousVT = -1, appVT = -1; + + if (Kernel.signal (Signal.SIGUSR1, switch_request_handle) < 0) + throw new Exception ("signal handler registation failed"); + if (Kernel.signal (Signal.SIGINT, sigint_handler) < 0) + throw new Exception ("SIGINT handler registation failed"); + + using (VT.VTControler master = new VT.VTControler ()) { + previousVT = master.CurrentVT; + appVT = master.FirstAvailableVT; + master.SwitchTo (appVT); + try { + master.KDMode = VT.KDMode.GRAPHICS; + } catch (Exception ex) { + Console.WriteLine (ex.ToString ()); + } + } + try { + using (DRI.GPUControler gpu = new DRI.GPUControler ()) { + +// int i = 0; +// while(running && i < 1000){ +// try { +// gpu.Update (); +// i++; +// } catch (Exception ex) { +// Console.WriteLine (ex.ToString()); +// } +// +// } + + + } + } catch (Exception ex) { + Console.WriteLine (ex.ToString ()); + } + + using (VT.VTControler master = new VT.VTControler ()) { + // try { + // master.KDMode = VT.KDMode.TEXT; + // } catch (Exception ex) { + // Console.WriteLine (ex.ToString ()); + // } + master.SwitchTo (previousVT); + } + } + static void signalTest (){ if (Kernel.signal (Signal.SIGINT, signal_handler) < 0) throw new Exception ("signal handler registation failed"); @@ -148,7 +318,51 @@ namespace testDrm Console.WriteLine ("SIGINT catched"); running = false; } + static void dumpDrmResources(){ + string gpu_path = "/dev/dri/card0"; + int fd_gpu = Libc.open(gpu_path, OpenFlags.ReadWrite | OpenFlags.CloseOnExec); + if (fd_gpu < 0) + throw new NotSupportedException("[DRI] Failed to open gpu"); + using (DRI.Resources resources = new DRI.Resources (fd_gpu)) { + foreach (DRI.Connector e in resources.Connectors) { + Console.WriteLine (e.ToString ()); + } + foreach (DRI.Encoder e in resources.Encoders) + Console.WriteLine (e.ToString ()); + foreach (DRI.Crtc e in resources.Crtcs) + Console.WriteLine (e.ToString ()); + } + + Libc.close (fd_gpu); + } +// static void dumpDrm(){ +// using (DRI.GPUControler gpu = new DRI.GPUControler ()) { +// +// +// if (gpu.PlanesIds.Length > 0){ +// DRI.drmPlane plane = gpu.GetPlane (gpu.PlanesIds [0]); +// } +// +// Console.WriteLine ("DRI Resources:"); +// Console.WriteLine ("\t- Connectors\t({0})", gpu.ConnectorIds.Length); +// for (int i = 0; i < gpu.ConnectorIds.Length; i++) { +// DRI.Connector mc = gpu.GetConnector (gpu.ConnectorIds [i]); +// Console.WriteLine ("\t\t{0}. {1,-11} ({2})",i, mc.Type, mc.State); +// //DRI.Encoder e = mc.CurrentEncoder; +// //DRI.Crtc c = gpu.GetCrtc (e.crtc_id); +// //DRI.FrameBuffer fb = gpu.GetFB (c.buffer_id); +// +// } +// Console.WriteLine ("\t- Encoderds\t({0})", gpu.EncoderIds.Length); +// Console.WriteLine ("\t- Crtcs\t\t({0})", gpu.CrtcIds.Length); +// Console.WriteLine ("\t- FrameBuffers\t({0})", gpu.FbIds.Length); +// Console.WriteLine ("\t- Planes\t({0})", gpu.PlanesIds.Length); +// // foreach (Crow.Linux.DRI.ModeConnector c in gpu.Connectors) { +// // Console.WriteLine ("connector id: {0}\tType: {1}", c.connector_id, c.connector_type); +// // } +// } +// } } } diff --git a/testDrm/ui/menu.crow b/testDrm/ui/menu.crow index 92cd224b..67e5d604 100755 --- a/testDrm/ui/menu.crow +++ b/testDrm/ui/menu.crow @@ -4,7 +4,7 @@ - + -- 2.47.3