<Reference Include="System.Data" />
<Reference Include="System.Xml" />
<Reference Include="System.Drawing" />
- <Reference Include="cairo-sharp">
- <Package>gtk-sharp-3.0</Package>
- </Reference>
<Reference Include="OpenTK">
<HintPath>$(SolutionDir)packages\OpenTK.2.0.0\lib\net20\OpenTK.dll</HintPath>
<Package>opentk</Package>
void computeStats(){
current = timer.ElapsedTicks;
- if (current < cancelLimit)
- return;
+// if (current < cancelLimit)
+// return;
cptMeasures++;
total += timer.ElapsedTicks;
if (timer.ElapsedTicks < minimum)
#endregion
+ #if MEASURE_TIME
+ public List<PerformanceMeasure> PerfMeasures;
+ public PerformanceMeasure glDrawMeasure = new PerformanceMeasure("OpenGL Draw", 10);
+ public Command CMDViewPerf, CMDViewCfg, CMDViewTest0;
+ #endif
public TestApp () : base () {
-
+ #if MEASURE_TIME
+ PerfMeasures = new List<PerformanceMeasure> (
+ new PerformanceMeasure[] {
+ this.CrowInterface.updateMeasure,
+ this.CrowInterface.layoutingMeasure,
+ this.CrowInterface.clippingMeasure,
+ this.CrowInterface.drawingMeasure,
+ this.glDrawMeasure
+ }
+ );
+ CMDViewPerf = new Command(new Action(() => Load ("#testDrm.ui.perfMeasures.crow").DataSource = this)) { Caption = "Performances"};
+ CMDViewCfg = new Command(new Action(() => Load ("#testDrm.ui.2.crow").DataSource = this)) { Caption = "Configuration"};
+ CMDViewTest0 = new Command(new Action(() => Load ("#testDrm.ui.0.crow").DataSource = this)) { Caption = "Test view 0"};
+ #endif
}
public int frameTime = 0;
#endregion
+ public int InterfaceSleep {
+ get { return ifaceSleep; }
+ set {
+ if (ifaceSleep == value)
+ return;
+ ifaceSleep = value;
+ NotifyValueChanged ("InterfaceSleep", ifaceSleep);
+ }
+ }
+ public int FlipPollSleep {
+ get { return gpu.FlipPollingSleep; }
+ set {
+ if (gpu.FlipPollingSleep == value)
+ return;
+ gpu.FlipPollingSleep = value;
+ NotifyValueChanged ("FlipPollSleep", gpu.FlipPollingSleep);
+ }
+ }
+ public int UpdateSleep {
+ get { return updateSleep; }
+ set {
+ if (updateSleep == value)
+ return;
+ updateSleep = value;
+ NotifyValueChanged ("UpdateSleep", updateSleep);
+ }
+ }
+
+
public override void Run ()
{
Stopwatch frame = new Stopwatch ();
-// Load ("#testDrm.ui.menu.crow").DataSource = this;
-// Load ("#testDrm.ui.0.crow").DataSource = this;
-// Load ("#testDrm.ui.0.crow").DataSource = this;
-// Load ("#testDrm.ui.0.crow").DataSource = this;
-
- System.Threading.Thread.Sleep (50);
Load ("#testDrm.ui.menu.crow").DataSource = this;
int i = 0;
while(Running){
i++;
base.Run ();
-
+
frame.Stop();
frameTime = (int)frame.ElapsedTicks;
NotifyValueChanged("frameTime", frameTime);
frameMin = frameTime;
NotifyValueChanged("frameMin", frameMin);
}
-
+ #if MEASURE_TIME
+ foreach (PerformanceMeasure m in PerfMeasures)
+ m.NotifyChanges();
+ #endif
} catch (Exception ex) {
Console.WriteLine (ex.ToString());
}
{
Running = false;
}
- void onLoadClick(object send, Crow.MouseButtonEventArgs e)
- {
- Console.WriteLine ("********** LOADING ui item ******************");
- GraphicObject go = Load ("#testDrm.ui.2.crow");
- Console.WriteLine ("********** SETTING DATASOURCE ON ITEM ******************");
- go.DataSource = this;
- Console.WriteLine ("********** LOADING FINISHED ******************");
- }
}
}
public class Application : IDisposable
{
public bool Running = true;
- DRI.GPUControler gpu;
+ protected DRI.DRIControler gpu;
Cairo.GLSurface cairoSurf;
- public Interface CrowInterface;
+ protected Interface CrowInterface;
- public bool mouseIsInInterface = false;
+ protected bool mouseIsInInterface = false;
+
+ protected volatile int ifaceSleep = 1, updateSleep = 0;
void interfaceThread()
{
while (true) {
CrowInterface.Update ();
- Thread.Sleep (1);
+ Thread.Sleep (ifaceSleep);
}
}
//
}
}
- gpu = new DRI.GPUControler();
+ gpu = new DRI.DRIControler();
cairoSurf = gpu.CairoSurf;
CrowInterface = new Interface ();
initInput ();
CrowInterface.ProcessResize (new Size (gpu.Width, gpu.Height));
- cursor = Crow.XCursorFile.Load("#Crow.Images.Icons.Cursors.arrow").Cursors[0];
- gpu.updateCursor (cursor);
- //CrowInterface.MouseCursorChanged += CrowInterface_MouseCursorChanged;
+
+ gpu.updateCursor (XCursor.Default);
+ MouseX = gpu.Width / 2;
+ MouseY = gpu.Height / 2;
+ gpu.moveCursor ((uint)MouseX - 8, (uint)MouseY - 4);
+ CrowInterface.MouseCursorChanged += CrowInterface_MouseCursorChanged;
}
void switch_request_handle (Signal s){
- Console.WriteLine ("switch request catched: " + s.ToString());
- using (VT.VTControler master = new VT.VTControler ()) {
- Libc.write (master.fd, Encoding.ASCII.GetBytes ("this is a test string"));
- master.AcknoledgeSwitchRequest ();
- }
+// Console.WriteLine ("switch request catched: " + s.ToString());
+// using (VT.VTControler master = new VT.VTControler ()) {
+// Libc.write (master.fd, Encoding.ASCII.GetBytes ("this is a test string"));
+// master.AcknoledgeSwitchRequest ();
+// }
}
void sigint_handler (Signal s){
Console.WriteLine ("{0}: SIGINT catched");
Running = false;
}
-// void CrowInterface_MouseCursorChanged (object sender, MouseCursorChangedEventArgs e)
-// {
-// gpu.updateCursor (e.NewCursor);
-// }
+ 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) {
}
}
-// using (Cairo.Context ctx = new Cairo.Context (cairoSurf)) {
-// ctx.Rectangle (0, 0, gpu.Width, gpu.Height);
-// ctx.SetSourceRGB (0, 0, 1);
-// ctx.Fill ();
-// ctx.Rectangle (5, 5, 50, 50);
-// ctx.SetSourceRGB (1, 0, 0);
-// ctx.Fill ();
-// ctx.Rectangle (1550, 850, 50, 50);
-// ctx.SetSourceRGB (0, 1, 0);
-// ctx.Fill ();
-// }
if (Monitor.TryEnter (CrowInterface.RenderMutex)) {
if (CrowInterface.IsDirty) {
CrowInterface.IsDirty = false;
}
Monitor.Exit (CrowInterface.RenderMutex);
}
-//
-// if (!update)
-// return;
-// update = false;
+
+ if (!update)
+ return;
+ update = false;
cairoSurf.Flush ();
cairoSurf.SwapBuffers ();
- gpu.Update ();
- //Thread.Sleep (1);
- //gpu.MarkFBDirty ();
+ gpu.UpdateWithPageFlip ();
+ Thread.Sleep (updateSleep);
}
-
-
+
#region INPUT
Thread input_thread;
long exit;
BlueSize,
AlphaSize
}
+ public void ResetMakeCurrent (){
+ if (!Context.MakeCurrent (dpy, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero))
+ Console.WriteLine ("egl clear current ctx failed");
+ }
+ public void DestroyContext (){
+ try {
+ if (ctx != IntPtr.Zero)
+ DestroyContext (dpy, ctx);
+ } catch (Exception ex) {
+ Console.WriteLine ("error disposing egl context: {0}", ex.ToString ());
+ }finally {
+ ctx = IntPtr.Zero;
+ }
+ }
#region IDisposable implementation
~Context(){
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
+++ /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;
-using System.Threading;
-
-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, originalMode;
- uint originalFB;
-
- 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; }}
-
- ModeInfo getNewMode(){
- ModeInfo mode = currentCrtc.CurrentMode;
- mode.clock = 118250;
- mode.hdisplay = 1600;
- mode.hsync_start = 1696;
- mode.hsync_end = 1856;
- mode.htotal = 2112;
- mode.vdisplay = 900;
- mode.vsync_start = 903;
- mode.vsync_end = 908;
- mode.vtotal = 934;
- mode.flags |= (uint)VideoMode.NHSYNC;
- mode.flags |= (uint)VideoMode.PVSYNC;
- return mode;
- }
- unsafe void setNewMode(){
-
- //currentCrtc.handle->mode = currentMode;
-// ModeInfo* mode = (ModeInfo*)Marshal.AllocHGlobal (sizeof(ModeInfo));// pConnector->modes;
-// *mode = currentMode;
-
- uint fb;
- GBM.gbm_bo* bo = GBM.BufferObject.gbm_bo_create (gbmDev.handle, (uint)Width, (uint)Height, GBM.SurfaceFormat.ARGB8888, GBM.SurfaceFlags.Scanout);
- int ret = drmModeAddFB (fd_gpu, (uint)Width, (uint)Height, (byte)depth, (byte)bpp, bo->Stride, (uint)bo->Handle32, out fb);
- if (ret != 0)
- Console.WriteLine ("addFb failed: {0}", ret);
- bo->SetUserData ((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 ("set new mode setCrtc failed: {0}", ret);
- //GBM.BufferObject.gbm_bo_destroy (bo);
-
- //Console.WriteLine ("new mode set to {0} x {1}", Width, Height);
- }
- bool defaultConfiguration (){
- //select the first connected connector
- foreach (Connector c in resources.Connectors) {
- if (c.State == ConnectionStatus.Connected) {
- connector = c;
- break;
- }
- }
- if (connector == null)
- return false;
-
- currentCrtc = connector.CurrentEncoder.CurrentCrtc;
- originalMode = currentCrtc.CurrentMode;
- originalFB = currentCrtc.CurrentFbId;
- currentMode = getNewMode();
-
-
- //configure a rendering stack
- gbmSurf = new GBM.Surface (gbmDev, Width, Height,
- GBM.SurfaceFlags.Rendering | GBM.SurfaceFlags.Scanout);
-
- //setNewMode ();
-
- 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.");
-
-// using (Cairo.Context ctx = new Cairo.Context (CairoSurf)) {
-// ctx.Rectangle (0, 0, Width, Height);
-// ctx.SetSourceRGB (0, 0, 1);
-// ctx.Fill ();
-// }
-// CairoSurf.Flush ();
-// CairoSurf.SwapBuffers ();
-// Update ();
-
- //Thread.Sleep (1);
- return true;
- }
- void handleDestroyFB(ref GBM.gbm_bo bo, IntPtr data)
- {
- int fb = data.ToInt32();
-
- if (fb != 0) {
- try {
- if (drmModeRmFB (fd_gpu, fb) != 0)
- Console.WriteLine ("DestroyFB failed");
- else
- Console.WriteLine ("DestroyFB ok fd={0}", fd_gpu);
- } catch (Exception ex) {
- Console.WriteLine ("DestroyFB error:" + ex.ToString());
- }
- }
- }
-
-
-
- unsafe public void Update(){
- GBM.gbm_bo* bo;
- uint fb;
-
- if (!gbmSurf.HasFreeBuffers)
- throw new NotSupportedException("[GBM] Out of free buffer");
-
- bo = gbmSurf.Lock ();
-
- int ret = drmModeAddFB (fd_gpu, currentMode.hdisplay, currentMode.vdisplay, (byte)depth, (byte)bpp, bo->Stride, (uint)bo->Handle32, out fb);
- if (ret != 0)
- Console.WriteLine ("addFb failed: {0}", ret);
- bo->SetUserData ((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);
- }
- [StructLayout(LayoutKind.Sequential)]
- struct drmClip {
- public ushort x1;
- public ushort y1;
- public ushort x2;
- public ushort y2;
- }
- unsafe public void MarkFBDirty(){
- IntPtr pClip = Marshal.AllocHGlobal (sizeof(drmClip));
- drmClip dc = new drmClip () { x1 = 0, y1 = 0, x2 = 500, y2 = 500 };
- Marshal.StructureToPtr (dc, pClip,false);
- int ret = drmModeDirtyFB (fd_gpu, currentCrtc.CurrentFbId, IntPtr.Zero, 0);
- if (ret < 0)
- Console.WriteLine ("set FB dirty failed: {0}", ret);
- }
- #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
-
-// 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;
- }
-
- uint connId = connector.Id;
- unsafe{
- int ret = drmModeSetCrtc (fd_gpu, currentCrtc.Id, originalFB, 0, 0, &connId, 1, ref originalMode);
- if (ret != 0)
- Console.WriteLine ("restore Crtc failed: {0}", ret);
- }
-
- if (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, CallingConvention = CallingConvention.Cdecl)]
- public static extern int drmModeDirtyFB(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, EntryPoint = "drmModeSetCrtc", CallingConvention = CallingConvention.Cdecl)]
- unsafe static extern int ModeSetCrtc(int fd, uint crtcId, uint bufferId, uint x, uint y, uint* connectors, int count, 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
+//
+// 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;
+using System.Threading;
+
+namespace Linux.DRI {
+ #region DRM callback signatures
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ public delegate void VBlankCallback(int fd, int sequence, int tv_sec, int tv_usec, IntPtr user_data);
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ public delegate void PageFlipCallback(int fd, int sequence, int tv_sec, int tv_usec, ref int user_data);
+ #endregion
+
+ #region DRM enums
+ public enum EncoderType : uint
+ {
+ NONE=0,
+ DAC=1,
+ TMDS=2,
+ LVDS=3,
+ TVDAC=4,
+ VIRTUAL=5,
+ DSI=6,
+ DPMST=7,
+ DPI=8,
+ }
+ [Flags]public enum PageFlipFlags : uint
+ {
+ FlipEvent = 0x01,
+ FlipAsync = 0x02,
+ FlipFlags = FlipEvent | FlipAsync
+ }
+ /// <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)
+ }
+ #endregion
+
+ #region DRM structs
+ [StructLayout(LayoutKind.Sequential)]
+ public struct EventContext
+ {
+ public int version;
+ public IntPtr vblank_handler;
+ public IntPtr page_flip_handler;
+ public static readonly int Version = 2;
+ }
+ [StructLayout(LayoutKind.Sequential)]
+ unsafe public struct drmFrameBuffer {
+ public uint fb_id;
+ public uint width, height;
+ public uint pitch;
+ public uint bpp;
+ public uint depth;
+ /* driver specific handle */
+ public uint handle;
+ }
+ [StructLayout(LayoutKind.Sequential)]
+ struct drmClip {
+ public ushort x1;
+ public ushort y1;
+ public ushort x2;
+ public ushort y2;
+ }
+ #endregion
+
+ public class DRIControler : IDisposable {
+ #region PINVOKE
+ const string lib = "libdrm";
+ [DllImport(lib, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern int drmHandleEvent(int fd, ref EventContext evctx);
+ [DllImport(lib, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern int drmModeAddFB(int fd, uint width, uint height, byte depth, byte bpp,
+ uint stride, uint bo_handle, out uint buf_id);
+ [DllImport(lib, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern int drmModeRmFB(int fd, uint bufferId);
+ [DllImport(lib, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern int drmModeDirtyFB(int fd, uint bufferId, IntPtr clips, uint num_clips);
+ [DllImport(lib,CallingConvention = CallingConvention.Cdecl)]
+ unsafe internal static extern drmFrameBuffer* drmModeGetFB(int fd, uint fb_id);
+ [DllImport(lib, CallingConvention = CallingConvention.Cdecl)]
+ unsafe internal static extern void drmModeFreeFB(drmFrameBuffer* ptr);
+ [DllImport(lib, CallingConvention = CallingConvention.Cdecl)]
+ static extern int drmModePageFlip(int fd, uint crtc_id, uint fb_id, PageFlipFlags flags, ref int user_data);
+ [DllImport(lib, CallingConvention = CallingConvention.Cdecl)]
+ unsafe static extern int drmModeSetCrtc(int fd, uint crtcId, uint bufferId, uint x, uint y, uint* connectors, int count, ref ModeInfo mode);
+ [DllImport(lib, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern int drmModeSetCursor2(int fd, uint crtcId, uint bo_handle, uint width, uint height, int hot_x, int hot_y);
+ [DllImport(lib, CallingConvention = CallingConvention.Cdecl)]
+ internal static extern int drmModeMoveCursor(int fd, uint crtcId, uint x, uint y);
+ #endregion
+
+ int fd_gpu = -1;
+ GBM.Device gbmDev;
+ GBM.Surface gbmSurf;
+ EGL.Context eglctx;
+ EGL.Surface eglSurf;
+
+ Cairo.EGLDevice cairoDev;
+ public Cairo.GLSurface CairoSurf;
+
+ Resources resources = null;
+ Connector connector = null;
+ Crtc currentCrtc = null;
+ ModeInfo currentMode, originalMode;
+ uint originalFB;
+
+ byte bpp = 32;
+ byte depth = 24;
+
+ public volatile int FlipPollingSleep = 1;
+
+ #region CTOR
+ public DRIControler(string gpu_path = "/dev/dri/card0"){
+ fd_gpu = Libc.open(gpu_path, OpenFlags.ReadWrite | OpenFlags.CloseOnExec);
+ if (fd_gpu < 0)
+ throw new NotSupportedException("[DRI] Failed to open gpu");
+
+ resources = new Resources (fd_gpu);
+ gbmDev = new GBM.Device (fd_gpu);
+ eglctx = new EGL.Context (gbmDev);
+
+ try {
+ if (defaultConfiguration ())
+ Console.WriteLine ("default config ok");
+ } catch (Exception ex) {
+ Console.WriteLine (ex.ToString());
+ }
+ }
+ #endregion
+
+ public int Width { get { return (int)currentMode.hdisplay; }}
+ public int Height { get { return (int)currentMode.vdisplay; }}
+
+ bool defaultConfiguration (){
+ //select the first connected connector
+ foreach (Connector c in resources.Connectors) {
+ if (c.State == ConnectionStatus.Connected) {
+ connector = c;
+ break;
+ }
+ }
+ if (connector == null)
+ return false;
+
+ currentCrtc = connector.CurrentEncoder.CurrentCrtc;
+ originalMode = currentCrtc.CurrentMode;
+ originalFB = currentCrtc.CurrentFbId;
+ //currentMode = originalMode;
+ currentMode = getNewMode();
+
+ //setScanOutRegion();
+
+ //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.");
+
+// using (Cairo.Context ctx = new Cairo.Context (CairoSurf)) {
+// ctx.Rectangle (0, 0, Width, Height);
+// ctx.SetSourceRGB (0, 0, 1);
+// ctx.Fill ();
+// }
+ //CairoSurf.Flush ();
+ //CairoSurf.SwapBuffers ();
+ //Update ();
+ //setScanOutRegion();
+ //Thread.Sleep (100);
+
+ initPageFlipUpdate ();
+ return true;
+ }
+
+ void handleDestroyFB(ref GBM.gbm_bo bo, ref uint data)
+ {
+ uint fb = data;
+
+ if (fb != 0) {
+ if (drmModeRmFB (fd_gpu, fb) != 0)
+ Console.WriteLine ("DestroyFB failed");
+
+ data = 0;
+ }
+ }
+
+
+
+
+ unsafe public void Update(){
+ GBM.gbm_bo* bo;
+ uint fb;
+
+ if (!gbmSurf.HasFreeBuffers)
+ throw new NotSupportedException("[GBM] Out of free buffer");
+
+ bo = gbmSurf.Lock ();
+
+ int ret = drmModeAddFB (fd_gpu, currentMode.hdisplay, currentMode.vdisplay, (byte)depth, (byte)bpp, bo->Stride, (uint)bo->Handle32, out fb);
+ if (ret != 0)
+ Console.WriteLine ("addFb failed: {0}", ret);
+ bo->SetUserData (ref fb, handleDestroyFB);
+
+ uint connId = connector.Id;
+ ret = drmModeSetCrtc (fd_gpu, currentCrtc.Id, fb, 0, 0, &connId, 1, ref currentMode);
+ if (ret != 0)
+ Console.WriteLine ("setCrtc failed: {0}", ret);
+
+ gbmSurf.Release (bo);
+ }
+
+ static void HandlePageFlip(int fd, int sequence, int tv_sec, int tv_usec, ref int user_data)
+ {
+ user_data = 0;
+ }
+
+ PollFD fds;
+ EventContext evctx;
+ static IntPtr PageFlipPtr = Marshal.GetFunctionPointerForDelegate((PageFlipCallback)HandlePageFlip);
+ public void initPageFlipUpdate (){
+ fds = new PollFD();
+ fds.fd = fd_gpu;
+ fds.events = PollFlags.In;
+
+ evctx = new EventContext();
+ evctx.version = EventContext.Version;
+ evctx.page_flip_handler = Marshal.GetFunctionPointerForDelegate((PageFlipCallback)HandlePageFlip);
+ }
+ unsafe GBM.gbm_bo* bo;
+ unsafe public void UpdateWithPageFlip(){
+ GBM.gbm_bo* next_bo;
+ uint fb;
+// fds = new PollFD();
+// fds.fd = fd_gpu;
+// fds.events = PollFlags.In;
+
+// evctx = new EventContext();
+// evctx.version = EventContext.Version;
+// evctx.page_flip_handler = PageFlipPtr;
+
+ int timeout = -1;//block ? -1 : 0;
+
+ if (!gbmSurf.HasFreeBuffers)
+ throw new NotSupportedException("[GBM] Out of free buffer");
+
+ next_bo = gbmSurf.Lock ();
+
+ int ret = drmModeAddFB (fd_gpu, currentMode.hdisplay, currentMode.vdisplay, (byte)depth, (byte)bpp, next_bo->Stride, (uint)next_bo->Handle32, out fb);
+ if (ret != 0)
+ Console.WriteLine ("addFb failed: {0}", ret);
+ next_bo->SetUserData (ref fb, handleDestroyFB);
+
+ if (bo == null) {
+ uint connId = connector.Id;
+ ret = drmModeSetCrtc (fd_gpu, currentCrtc.Id, fb, 0, 0, &connId, 1, ref currentMode);
+ if (ret != 0)
+ Console.WriteLine ("setCrtc failed: {0}", ret);
+ bo = next_bo;
+ } else {
+
+ int is_flip_queued = 1;
+
+ while (drmModePageFlip (fd_gpu, currentCrtc.Id, fb, PageFlipFlags.FlipEvent, ref is_flip_queued) < 0) {
+ //Console.WriteLine ("[DRM] Failed to enqueue framebuffer flip.");
+ Thread.Sleep (1);
+ }
+
+ while (is_flip_queued != 0) {
+ fds.revents = 0;
+ if (Libc.poll (ref fds, 1, timeout) < 0)
+ break;
+ if ((fds.revents & (PollFlags.Hup | PollFlags.Error)) != 0)
+ break;
+ if ((fds.revents & PollFlags.In) != 0)
+ drmHandleEvent (fd_gpu, ref evctx);
+ else
+ break;
+ Thread.Sleep (FlipPollingSleep);
+ }
+ if (is_flip_queued != 0)
+ Console.WriteLine ("flip canceled");
+
+ gbmSurf.Release (bo);
+ bo = next_bo;
+ }
+ }
+
+ #region cursor
+ GBM.BufferObject boMouseCursor;
+
+ internal void updateCursor (Crow.XCursor cursor) {
+ uint width = 64, height = 64;
+ if (cursor.Width > width || cursor.Height > height){
+ Debug.Print("[DRM] Cursor size {0}x{1} unsupported. Maximum is 64x64.",
+ cursor.Width, cursor.Height);
+ return;
+ }
+ boMouseCursor = new GBM.BufferObject (gbmDev, width, height, GBM.SurfaceFormat.ARGB8888,
+ GBM.SurfaceFlags.Cursor64x64 | GBM.SurfaceFlags.Write);
+
+ // Copy cursor.Data into a new buffer of the correct size
+ byte[] cursor_data = new byte[width * height * 4];
+ for (uint y = 0; y < cursor.Height; y++)
+ {
+ uint dst_offset = y * width * 4;
+ uint src_offset = y * cursor.Width * 4;
+ uint src_length = cursor.Width * 4;
+ Array.Copy(
+ cursor.data, src_offset,
+ cursor_data, dst_offset,
+ src_length);
+ }
+
+ boMouseCursor.Data = cursor_data;
+ uint crtcid = currentCrtc.Id;
+
+ unsafe {
+ drmModeSetCursor2 (fd_gpu, crtcid,
+ (uint)boMouseCursor.handle->Handle32, width, height, (int)cursor.Xhot, (int)cursor.Yhot);
+ //drmModeMoveCursor (fd_gpu, crtcid, 0, 0);
+ }
+ }
+ internal void moveCursor (uint x, uint y){
+ drmModeMoveCursor (fd_gpu, currentCrtc.Id, x, y);
+ }
+ #endregion
+
+ ModeInfo getNewMode(){
+ ModeInfo mode = currentCrtc.CurrentMode;
+ mode.clock = 118250;
+ mode.hdisplay = 1600;
+ mode.hsync_start = 1696;
+ mode.hsync_end = 1856;
+ mode.htotal = 2112;
+ mode.vdisplay = 900;
+ mode.vsync_start = 903;
+ mode.vsync_end = 908;
+ mode.vtotal = 934;
+ mode.flags |= (uint)VideoMode.NHSYNC;
+ mode.flags |= (uint)VideoMode.PVSYNC;
+ return mode;
+ }
+ unsafe void setScanOutRegion(){
+
+ //currentCrtc.handle->mode = currentMode;
+ // ModeInfo* mode = (ModeInfo*)Marshal.AllocHGlobal (sizeof(ModeInfo));// pConnector->modes;
+ // *mode = currentMode;
+
+ uint fb;
+ GBM.gbm_bo* bo = GBM.BufferObject.gbm_bo_create (gbmDev.handle, (uint)Width, (uint)Height, GBM.SurfaceFormat.ARGB8888, GBM.SurfaceFlags.Rendering);
+ int ret = drmModeAddFB (fd_gpu, (uint)Width, (uint)Height, (byte)depth, (byte)bpp, bo->Stride, (uint)bo->Handle32, out fb);
+ if (ret != 0)
+ Console.WriteLine ("addFb failed: {0}", ret);
+ bo->SetUserData (ref fb, handleDestroyFB);
+
+ uint connId = connector.Id;
+ ret = drmModeSetCrtc (fd_gpu, currentCrtc.Id, currentCrtc.CurrentFbId, 0, 0, &connId, 1, ref currentMode);
+ if (ret != 0)
+ Console.WriteLine ("set new mode setCrtc failed: {0}", ret);
+ //GBM.BufferObject.gbm_bo_destroy (bo);
+
+ Console.WriteLine ("new mode set to {0} x {1} fbid:{2}", Width, Height, currentCrtc.CurrentFbId);
+ }
+
+// unsafe public drmPlane GetPlane (uint id) {
+// drmPlane p = new drmPlane();
+// drmPlane* pPlane = ModeGetPlane (fd_gpu, id);
+// if (pPlane != null) {
+// p = *pPlane;
+// ModeFreePlane (pPlane);
+// }
+// return p;
+// }
+// public void SetPlane (drmPlane p, uint flags, uint crtc_w, uint crtc_h, uint src_w, uint src_h) {
+// ModeSetPlane (fd_gpu, p.plane_id, p.crtc_id, p.fb_id, flags,
+// (int)p.crtc_x, (int)p.crtc_y,
+// crtc_w, crtc_h,
+// p.x, p.y,
+// src_w, src_h);
+//
+//
+// }
+
+ #region IDisposable implementation
+ ~DRIControler(){
+ Dispose (false);
+ }
+ public void Dispose ()
+ {
+ Dispose (true);
+ GC.SuppressFinalize (this);
+ }
+ protected virtual void Dispose (bool disposing){
+ unsafe{
+ if (bo != null)
+ gbmSurf.Release (bo);
+ }
+ Thread.Sleep (10);
+ if (cairoDev != null) {
+ cairoDev.Release ();
+ CairoSurf.Dispose ();
+ cairoDev.Dispose ();
+ cairoDev = null;
+ CairoSurf = null;
+ }
+
+ if (boMouseCursor != null) {
+ drmModeSetCursor2 (fd_gpu, currentCrtc.Id, 0u, 0, 0, 0, 0);
+ boMouseCursor.Dispose ();
+ }
+ boMouseCursor = null;
+ if (connector != null) {
+ uint connId = connector.Id;
+ unsafe {
+ int ret = drmModeSetCrtc (fd_gpu, currentCrtc.Id, originalFB, 0, 0, &connId, 1, ref originalMode);
+ if (ret != 0)
+ Console.WriteLine ("restore Crtc failed: {0}", ret);
+ }
+ }
+ if (eglctx != null) {
+ eglctx.ResetMakeCurrent ();
+ eglctx.DestroyContext ();
+
+ if (eglSurf != null)
+ eglSurf.Dispose ();
+ eglSurf = null;
+ }
+
+ if (gbmSurf != null)
+ gbmSurf.Dispose ();
+ if (eglctx != null)
+ eglctx.Dispose ();
+ eglctx = null;
+ 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 ("GPU controler disposed");
+ }
+ #endregion
+
+
+ unsafe public void MarkFBDirty(){
+ IntPtr pClip = Marshal.AllocHGlobal (sizeof(drmClip));
+ drmClip dc = new drmClip () { x1 = 0, y1 = 0, x2 = 500, y2 = 500 };
+ Marshal.StructureToPtr (dc, pClip,false);
+ int ret = drmModeDirtyFB (fd_gpu, currentCrtc.CurrentFbId, IntPtr.Zero, 0);
+ if (ret < 0)
+ Console.WriteLine ("set FB dirty failed: {0}", ret);
+ }
+
+
+// unsafe static bool paint(gbm_bo * bo)
+// {
+// uint w = (uint)bo->Width;
+// uint h = (uint)bo->Height;
+// uint stride = (uint)bo->Stride;
+//
+// Console.WriteLine ("trying to map bo: {0}x{1} stride:{2}", w, h, stride);
+// bool success = false;
+// try {
+// unsafe {
+// IntPtr map_data = IntPtr.Zero;
+// IntPtr addr = Gbm.Map (bo, 0, 0, w, h, TransferFlags.Write, ref stride, out map_data);
+// if (addr == IntPtr.Zero || map_data == IntPtr.Zero) {
+// Console.WriteLine ("failed to mmap gbm bo");
+// return false;
+// }
+// Console.WriteLine ("addr = {0}", addr.ToString());
+// byte* b = (byte*)addr;
+// for (int y = 0; y < h; y++) {
+// for (int x = 0; x < w; x++) {
+// *(b + x + y * stride) = 0xff;
+// }
+// }
+// Gbm.Unmap (bo, map_data);
+// success = true;
+// }
+// } catch (Exception ex) {
+// Console.WriteLine (ex.ToString ());
+// }
+// return success;
+// }
+ }
+}
\ No newline at end of file
namespace Linux.DRI
{
+ public enum PlaneType {
+ Overlay = 0,
+ Primary = 1,
+ Cursor = 2
+ }
[StructLayout(LayoutKind.Sequential)]
unsafe public struct drmPlane {
public uint count_formats;
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);
+ [DllImport("libdrm", CallingConvention = CallingConvention.Cdecl)]
+ unsafe internal static extern drmPlane* drmModeGetPlane(int fd, uint id);
+ [DllImport("libdrm", CallingConvention = CallingConvention.Cdecl)]
+ unsafe internal static extern void drmModeFreePlane(drmPlane* ptr);
+ [DllImport("libdrm", CallingConvention = CallingConvention.Cdecl)]
+ unsafe static extern int drmModeSetPlane(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);
+
#endregion
drmPlane* handle;
protected virtual void Dispose (bool disposing){
unsafe {
if (handle != null)
- ModeFreePlane (handle);
+ drmModeFreePlane (handle);
handle = null;
}
}
--- /dev/null
+//
+// PlaneResources.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 drmPlaneRes {
+ public uint count_planes;
+ public uint *planes;
+ }
+
+ unsafe public class PlaneResources : IDisposable
+ {
+ #region pinvoke
+ [DllImport("libdrm", CallingConvention = CallingConvention.Cdecl)]
+ unsafe internal static extern drmPlaneRes* drmModeGetPlaneResources(int fd);
+ [DllImport("libdrm", CallingConvention = CallingConvention.Cdecl)]
+ unsafe internal static extern void drmModeFreePlaneResources(drmPlaneRes* ptr);
+ #endregion
+
+ int gpu_fd;
+ drmPlaneRes* handle;
+
+ internal PlaneResources (int fd_gpu)
+ {
+ gpu_fd = fd_gpu;
+ handle = drmModeGetPlaneResources (fd_gpu);
+
+ if (handle == null)
+ throw new NotSupportedException("[DRI] drmModeGetPlaneResources failed.");
+ }
+
+ #region IDisposable implementation
+ ~PlaneResources(){
+ Dispose (false);
+ }
+ public void Dispose ()
+ {
+ Dispose (true);
+ GC.SuppressFinalize (this);
+ }
+ protected virtual void Dispose (bool disposing){
+ unsafe {
+ if (handle != null)
+ drmModeFreePlaneResources (handle);
+ handle = null;
+ }
+ }
+ #endregion
+ }
+}
+
namespace Linux.GBM
{
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
- public delegate void DestroyUserDataCallback(ref GBM.gbm_bo bo, IntPtr data);
+ public delegate void DestroyUserDataCallback(ref GBM.gbm_bo bo, ref uint data);
[StructLayout(LayoutKind.Sequential)]
public struct gbm_bo {
{
get { return BufferObject.gbm_bo_get_stride(ref this); }
}
- public void SetUserData(IntPtr data, DestroyUserDataCallback destroyFB)
+ public void SetUserData(ref uint data, DestroyUserDataCallback destroyFB)
{
- BufferObject.gbm_bo_set_user_data(ref this, data, destroyFB);
+ BufferObject.gbm_bo_set_user_data(ref this, ref data, destroyFB);
}
}
unsafe public class BufferObject : IDisposable
internal 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", EntryPoint = "gbm_bo_destroy", CallingConvention = CallingConvention.Cdecl)]
+ internal static extern void destryBO (ref 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)]
[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);
+ internal static extern void gbm_bo_set_user_data(ref gbm_bo bo, ref uint 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);
+ 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
[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);
+ internal 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)]
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
- <DefineConstants>DEBUG;</DefineConstants>
+ <DefineConstants>DEBUG;MEASURE_TIME;</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Compile Include="src\Linux\TTY.cs" />
<Compile Include="src\Linux\Signal.cs" />
<Compile Include="src\Linux\VT.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\GBM\Device.cs" />
<Compile Include="src\Application.cs" />
<Compile Include="Main.cs" />
+ <Compile Include="src\Linux\DRI\PlaneResources.cs" />
+ <Compile Include="src\Linux\DRI\DRIControler.cs" />
</ItemGroup>
<ItemGroup>
<Reference Include="System" />
<EmbeddedResource Include="ui\2.crow" />
<EmbeddedResource Include="ui\colorItem.crow" />
<EmbeddedResource Include="test.style" />
+ <EmbeddedResource Include="ui\perfMsr.crow">
+ <LogicalName>ui.perfMsr.crow</LogicalName>
+ </EmbeddedResource>
+ <EmbeddedResource Include="ui\perfMeasures.crow">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </EmbeddedResource>
</ItemGroup>
<ItemGroup>
<None Include="src\DRMContext.cs" />
MouseDown="{Background=Mantis}"
MouseUp="{Background=Onyx}"/>
</HorizontalStack>
- <GroupBox Caption="Templated controls" Height="Fit" Margin="5">
- <HorizontalStack Height="Fit">
- <VerticalStack Width="50%">
- <CheckBox IsChecked="true" Style="CheckBox2"/>
- <CheckBox Style="CheckBox2"/>
- <CheckBox Style="CheckBox2"/>
- <CheckBox Style="CheckBox2"/>
- </VerticalStack>
- <Splitter/>
- <VerticalStack Width="50%">
- <RadioButton Style="RadioButton2"/>
- <RadioButton Style="RadioButton2"/>
- <RadioButton Style="RadioButton2"/>
- <RadioButton Style="RadioButton2"/>
- </VerticalStack>
- </HorizontalStack>
- </GroupBox>
+
<HorizontalStack Height="Fit">
<Label Text="Spinner"/>
<Spinner Fit="true"/>
<DirectoryView Name="dv" CurrentDirectory="/" Margin="1"/>
</Border>
<Splitter/>-->
-<!-- <ListBox Name="colorList" Data="{TestList}" Margin="5"/>-->
-<!-- ItemTemplate="#testDrm.ui.colorItem.crow"
- Template="#Crow.Templates.ScrollingListBox.goml"-->
+ <ListBox Name="colorList" Data="{TestList}" Margin="5"
+ ItemTemplate="#testDrm.ui.colorItem.crow"
+ Template="#Crow.Templates.ScrollingListBox.goml"/>
</VerticalStack>
</HorizontalStack>
</Window>
\ No newline at end of file
<?xml version="1.0"?>
-<Window Caption="Performances" Height="160" Width="200">
+<Window Caption="Performances" Height="160" Width="200" CornerRadius="5">
<VerticalStack Width="90%" Height="Fit" Spacing="1" Margin="10">
<HorizontalStack>
<Label Text="Frame:" Style="FpsLabel"/>
<Label Text="Drawing:" Style="FpsLabel"/>
<Label Text="{drawing}" Style="FpsDisp"/>
</HorizontalStack>
-
+ <HorizontalStack>
+ <Label Text="IfaceSleep:" Style="FpsLabel"/>
+ <Spinner Maximum="100" Fit="true" Value="{²InterfaceSleep}" />
+ </HorizontalStack>
+ <HorizontalStack>
+ <Label Text="FlipPollSleep:" Style="FpsLabel"/>
+ <Spinner Maximum="100" Fit="true" Value="{²FlipPollSleep}" />
+ </HorizontalStack>
+ <HorizontalStack>
+ <Label Text="UpdateSleep:" Style="FpsLabel"/>
+ <Spinner Maximum="100" Fit="true" Value="{²UpdateSleep}" />
+ </HorizontalStack>
</VerticalStack>
</Window>
\ No newline at end of file
<MenuItem Caption="Save"/>
<MenuItem Caption="Quit" MouseClick="onQuitClick"/>
</MenuItem>
+ <MenuItem Caption="View" Width="Fit">
+ <MenuItem Command="{CMDViewPerf}"/>
+ <MenuItem Command="{CMDViewCfg}"/>
+ <MenuItem Command="{CMDViewTest0}"/>
+ </MenuItem>
<MenuItem Caption="Edit" Name="edit" Width="Fit">
<MenuItem Caption="Cut"/>
<MenuItem Caption="Copy"/>
--- /dev/null
+<?xml version="1.0"?>
+<Window Focusable="true" Caption="Measures" Width="30%" Height="Fit" MinimumSize="100,100">
+ <ListBox Data="{PerfMeasures}" Fit="true"
+ ItemTemplate="#ui.perfMsr.crow"/>
+</Window>
--- /dev/null
+<?xml version="1.0"?>
+
+ <VerticalStack Spacing="0" Fit="true" Width="160">
+ <HorizontalStack Background="Black">
+ <Label Text="{Name}" Width="Stretched" Font="doid bold, 10" Margin="2"/>
+ <Button Caption="Reset" MouseClick="onResetClick" Height="Fit"/>
+ </HorizontalStack>
+ <HorizontalStack>
+ <Label Text="Current:" Style="FpsLabel"/>
+ <Label Text="{current}" Style="FpsDisp"/>
+ </HorizontalStack>
+ <HorizontalStack>
+ <Label Text="Minimum:" Style="FpsLabel"/>
+ <Label Text="{minimum}" Style="FpsDisp"/>
+ </HorizontalStack>
+ <HorizontalStack>
+ <Label Text="Mean:" Style="FpsLabel"/>
+ <Label Text="{mean}" Style="FpsDisp"/>
+ </HorizontalStack>
+ <HorizontalStack>
+ <Label Text="Maximum:" Style="FpsLabel"/>
+ <Label Text="{maximum}" Style="FpsDisp"/>
+ </HorizontalStack>
+<!-- <HorizontalStack>
+ <Label Text="Total:" Style="FpsLabel"/>
+ <Label Text="{total}" Style="FpsDisp"/>
+ </HorizontalStack>
+ <HorizontalStack>
+ <Label Text="Cpt:" Style="FpsLabel"/>
+ <Label Text="{cptMeasures}" Style="FpsDisp"/>
+ </HorizontalStack>-->
+ </VerticalStack>
+