<Compile Include="src\Mono.Cairo\Device.cs" />
<Compile Include="src\Mono.Cairo\DirectFBSurface.cs" />
<Compile Include="src\Mono.Cairo\Distance.cs" />
- <Compile Include="src\Mono.Cairo\EGLDevice.cs" />
<Compile Include="src\Mono.Cairo\Extend.cs" />
<Compile Include="src\Mono.Cairo\FillRule.cs" />
<Compile Include="src\Mono.Cairo\Filter.cs" />
<Compile Include="src\Mono.Cairo\Win32Surface.cs" />
<Compile Include="src\Mono.Cairo\XcbSurface.cs" />
<Compile Include="src\Mono.Cairo\XlibSurface.cs" />
+ <Compile Include="src\Mono.Cairo\EGLDevice.cs" />
+ <Compile Include="src\Mono.Cairo\DRMDevice.cs" />
+ <Compile Include="src\Mono.Cairo\DRMSurface.cs" />
</ItemGroup>
<ItemGroup>
<Reference Include="System" />
namespace Crow
{
- public class Container : PrivateContainer, IXmlSerializable
+ public class Container : PrivateContainer
{
#region CTOR
public Container()
{
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
}
}
namespace Crow
{
- public class GraphicObject : IXmlSerializable, ILayoutable, IValueChange, ICloneable
+ public class GraphicObject : ILayoutable, IValueChange
{
internal static ulong currentUid = 0;
internal ulong uid = 0;
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<XmlIgnoreAttribute> () != null)
- continue;
- if (pi.Name == "DataSource")
- continue;
-
- pi.SetValue(result, pi.GetValue(this));
- }
- return result;
- }
- #endregion
- /// <summary>
- /// full GraphicTree clone with binding definition
- /// </summary>
public override string ToString ()
{
namespace Crow
{
- public class Group : GraphicObject, IXmlSerializable
+ public class Group : GraphicObject
{
#region CTOR
public Group()
}
}
}
-
#region Mouse handling
public override void checkHoverWidget (MouseMoveEventArgs e)
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
-
}
}
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
}
}
namespace Crow
{
- public abstract class TemplatedControl : PrivateContainer, IXmlSerializable
+ public abstract class TemplatedControl : PrivateContainer
{
#region CTOR
public TemplatedControl () : base()
}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<string, ItemTemplate> ();
-//
-// 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
}
}
// }
#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<string, ItemTemplate> ();
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 ();
}
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];
--- /dev/null
+//
+// 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);}
+ }
+}
+
--- /dev/null
+//
+// 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)
+ {}
+ }
+}
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);
// 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()
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
}
using OpenTK.Platform.Linux;
using System.IO.Compression;
-namespace Crow.Linux
+namespace Linux
{
internal class DRMContext : IDisposable
unsafe void initEgl () {
int major, minor;
IntPtr[] configs = new IntPtr[1];
+
int[] contextAttrib = new int[] {
Egl.CONTEXT_CLIENT_VERSION, 2,
Egl.NONE
// 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);
Drm.HandleEvent (fd_gpu, ref evctx);
else
break;
+ Thread.Sleep (1);
}
if (is_flip_queued != 0)
Console.WriteLine ("flip canceled");
--- /dev/null
+//
+// Context.cs
+//
+// Author:
+// Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
+//
+// Copyright (c) 2013-2017 Jean-Philippe Bruyère
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using System.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";
+ }
+ }
+ }
+}
+
--- /dev/null
+//
+// EGL.cs
+//
+// Author:
+// Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
+//
+// Copyright (c) 2013-2017 Jean-Philippe Bruyère
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+
+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,
+ }
+}
+
--- /dev/null
+//
+// Surface.cs
+//
+// Author:
+// Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
+//
+// Copyright (c) 2013-2017 Jean-Philippe Bruyère
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using System.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
+
+ }
+}
+
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,
{
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;
}
// THE SOFTWARE.
//
using OpenTK;
+using Linux;
+using Crow;
#endregion
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
-using Crow;
-namespace Crow.Linux
+namespace Linux
{
// Bindings for linux/input.h
class Evdev
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);
[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);
[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);
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)),
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<BufferObject>
- {
- IntPtr buffer;
-
- public static readonly BufferObject Zero =
- default(BufferObject);
-
- public int Write(byte[] data)
- {
- unsafe
- {
- fixed (byte* pdata = data)
- {
- return Gbm.BOWrite(buffer, (IntPtr)pdata, (IntPtr)data.Length);
- }
- }
- }
-
+ Linear = (1 << 4),
+ }
+ [Flags]public enum TransferFlags : uint {
+ /// <summary> Buffer contents read back (or accessed directly) at transfer create time.</summary>
+ Read = 1 << 0,
+ /// <summary> Buffer contents will be written back at unmap time (or modified as a result of being accessed directly).</summary>
+ Write = 1 << 1,
+ /// <summary>Read/modify/write</summary>
+ 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<BufferObject>
+// {
+// IntPtr buffer;
+//
+// public static readonly BufferObject Zero =
+// default(BufferObject);
+//
+// public int Write(byte[] data)
+// {
+// unsafe
+// {
+// fixed (byte* pdata = data)
+// {
+// return Gbm.BOWrite(buffer, (IntPtr)pdata, (IntPtr)data.Length);
+// }
+// }
+// }
+//
+// public void SetUserData(IntPtr data, 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
+// }
}
using System.Diagnostics;
using System.Runtime.InteropServices;
-namespace Crow.Linux
+namespace Linux
{
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
delegate int OpenRestrictedCallback(IntPtr path, int flags, IntPtr data);
#pragma warning disable 0649 // field is never assigned
-namespace Crow.Linux
+namespace Linux
{
partial class Libc
{
using System;
using System.Runtime.InteropServices;
-namespace Crow.Linux
+namespace Linux
{
partial class Libc
{
--- /dev/null
+//
+// DRM.cs
+//
+// Author:
+// Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
+//
+// Copyright (c) 2013-2017 Jean-Philippe Bruyère
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using System.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
+ }
+ /// <summary>Video mode flags, bit compatible with the xorg definitions. </summary>
+ [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
--- /dev/null
+//
+// Connector.cs
+//
+// Author:
+// Stefanos Apostolopoulos <stapostol@gmail.com>
+// Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
+//
+// 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);
+ }
+ }
+}
+
--- /dev/null
+//
+// Crtc.cs
+//
+// Author:
+// Stefanos Apostolopoulos <stapostol@gmail.com>
+// Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
+//
+// 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);
+ }
+ }
+}
+
--- /dev/null
+//
+// Encoder.cs
+//
+// Author:
+// Stefanos Apostolopoulos <stapostol@gmail.com>
+// Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
+//
+// 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);
+ }
+ }
+}
+
--- /dev/null
+//
+// Plane.cs
+//
+// Author:
+// Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
+//
+// Copyright (c) 2013-2017 Jean-Philippe Bruyère
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using System.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
+ }
+}
+
--- /dev/null
+//
+// Resources.cs
+//
+// Author:
+// Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
+//
+// Copyright (c) 2013-2017 Jean-Philippe Bruyère
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using System.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
+
+ }
+}
+
+++ /dev/null
-//
-// DRM.cs
-//
-// Author:
-// Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
-//
-// Copyright (c) 2013-2017 Jean-Philippe Bruyère
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-using System;
-using System.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
--- /dev/null
+//
+// Device.cs
+//
+// Author:
+// Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
+//
+// Copyright (c) 2013-2017 Jean-Philippe Bruyère
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using System.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
+ }
+}
+
--- /dev/null
+//
+// Device.cs
+//
+// Author:
+// Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
+//
+// Copyright (c) 2013-2017 Jean-Philippe Bruyère
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+using System;
+using System.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
+ }
+}
+
--- /dev/null
+//
+// Surface.cs
+//
+// Author:
+// Stefanos Apostolopoulos <stapostol@gmail.com>
+// Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
+//
+// 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 {
+ /// <summary> Buffer contents read back (or accessed directly) at transfer create time.</summary>
+ Read = 1 << 0,
+ /// <summary> Buffer contents will be written back at unmap time (or modified as a result of being accessed directly).</summary>
+ Write = 1 << 1,
+ /// <summary>Read/modify/write</summary>
+ 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
+ }
+}
+
using System;
using System.Runtime.InteropServices;
-namespace Crow.Linux.VT {
+namespace Linux.VT {
public enum KDMode : byte {
TEXT = 0x00,
GRAPHICS= 0x01,
</PropertyGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>
- <Compile Include="Main.cs" />
<Compile Include="src\Linux\Bindings\Drm.cs" />
<Compile Include="src\Linux\Bindings\Evdev.cs" />
<Compile Include="src\Linux\Bindings\Gbm.cs" />
</Compile>
<Compile Include="src\MouseCursor.cs" />
<Compile Include="src\WindowIcon.cs" />
- <Compile Include="src\Application.cs" />
- <Compile Include="src\DRMContext.cs" />
<Compile Include="src\Linux\Bindings\Egl.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="src\Linux\TTY.cs" />
<Compile Include="src\Linux\Signal.cs" />
<Compile Include="src\Linux\VT.cs" />
- <Compile Include="src\Linux\DRM.cs" />
+ <Compile Include="src\Linux\DRI.cs" />
+ <Compile Include="src\Linux\DRI\Connector.cs" />
+ <Compile Include="src\Linux\DRI\Encoder.cs" />
+ <Compile Include="src\Linux\DRI\Resources.cs" />
+ <Compile Include="src\Linux\DRI\Crtc.cs" />
+ <Compile Include="src\Linux\DRI\Plane.cs" />
+ <Compile Include="src\Egl\EGL.cs" />
+ <Compile Include="src\Egl\Surface.cs" />
+ <Compile Include="src\Egl\Context.cs" />
+ <Compile Include="src\Linux\GBM\Surface.cs" />
+ <Compile Include="src\Linux\GBM\BufferObject.cs" />
+ <Compile Include="src\Linux\GBM\Device.cs" />
+ <Compile Include="src\Application.cs" />
</ItemGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Drawing" />
<Reference Include="System.Xml" />
+ <Reference Include="System.Xml.Linq" />
</ItemGroup>
<ItemGroup>
<Folder Include="src\" />
<Folder Include="ui\" />
+ <Folder Include="src\Linux\DRI\" />
+ <Folder Include="src\Egl\" />
+ <Folder Include="src\Linux\GBM\" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Crow.csproj">
<ItemGroup>
<EmbeddedResource Include="ui\menu.crow" />
</ItemGroup>
+ <ItemGroup>
+ <None Include="src\DRMContext.cs" />
+ <None Include="Main.cs" />
+ </ItemGroup>
</Project>
\ No newline at end of file
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<int,string> dic = new Dictionary<int, string> ();
+
+ //parseEglConsts ("/home/jp/tmp/EGL/eglplatform.h", ref dic);
+ parseEglConsts ("/home/jp/tmp/EGL/egl.h", ref dic);
+
+ IOrderedEnumerable<KeyValuePair<int,string>> result = dic.OrderBy (p => p.Key);
+
+ foreach (KeyValuePair<int,string> kv in result) {
+ Console.WriteLine ("case {0}:\n\treturn \"{1}\";", kv.Key, kv.Value);
+ }
+ }
+ static void parseEglConsts (string path, ref Dictionary<int,string> 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");
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);
+// // }
+// }
+// }
}
}
<MenuItem Caption="New" />
<MenuItem Caption="Open"/>
<MenuItem Caption="Save"/>
- <MenuItem Caption="Quit"/>
+ <MenuItem Caption="Quit" MouseClick="onQuitClick"/>
</MenuItem>
<MenuItem Caption="Edit" Name="edit" Width="Fit">
<MenuItem Caption="Cut"/>