From 0d0496908cf21c770acce2a49c2b53e1d882d235 Mon Sep 17 00:00:00 2001 From: jpbruyere Date: Sun, 21 May 2017 18:24:35 +0200 Subject: [PATCH] drm double buffered, but disposing not ok --- CrowIDE/CrowIDE.csproj | 3 - src/PerformanceMeasure.cs | 4 +- testDrm/Main.cs | 70 +++- testDrm/src/Application.cs | 70 ++-- testDrm/src/Egl/Context.cs | 21 +- .../src/Linux/{DRI.cs => DRI/DRIControler.cs} | 356 +++++++++++------- testDrm/src/Linux/DRI/Plane.cs | 23 +- testDrm/src/Linux/DRI/PlaneResources.cs | 77 ++++ testDrm/src/Linux/GBM/BufferObject.cs | 12 +- testDrm/src/Linux/GBM/Surface.cs | 2 +- testDrm/testDrm.csproj | 11 +- testDrm/ui/0.crow | 24 +- testDrm/ui/2.crow | 15 +- testDrm/ui/menu.crow | 5 + testDrm/ui/perfMeasures.crow | 5 + testDrm/ui/perfMsr.crow | 33 ++ 16 files changed, 485 insertions(+), 246 deletions(-) rename testDrm/src/Linux/{DRI.cs => DRI/DRIControler.cs} (69%) create mode 100644 testDrm/src/Linux/DRI/PlaneResources.cs create mode 100755 testDrm/ui/perfMeasures.crow create mode 100755 testDrm/ui/perfMsr.crow diff --git a/CrowIDE/CrowIDE.csproj b/CrowIDE/CrowIDE.csproj index 1773f750..90cd9290 100644 --- a/CrowIDE/CrowIDE.csproj +++ b/CrowIDE/CrowIDE.csproj @@ -45,9 +45,6 @@ - - gtk-sharp-3.0 - $(SolutionDir)packages\OpenTK.2.0.0\lib\net20\OpenTK.dll opentk diff --git a/src/PerformanceMeasure.cs b/src/PerformanceMeasure.cs index 1db29e30..f5c39e35 100644 --- a/src/PerformanceMeasure.cs +++ b/src/PerformanceMeasure.cs @@ -70,8 +70,8 @@ namespace Crow void computeStats(){ current = timer.ElapsedTicks; - if (current < cancelLimit) - return; +// if (current < cancelLimit) +// return; cptMeasures++; total += timer.ElapsedTicks; if (timer.ElapsedTicks < minimum) diff --git a/testDrm/Main.cs b/testDrm/Main.cs index 528a8e95..d13108bf 100644 --- a/testDrm/Main.cs +++ b/testDrm/Main.cs @@ -62,9 +62,27 @@ namespace testDrm #endregion + #if MEASURE_TIME + public List PerfMeasures; + public PerformanceMeasure glDrawMeasure = new PerformanceMeasure("OpenGL Draw", 10); + public Command CMDViewPerf, CMDViewCfg, CMDViewTest0; + #endif public TestApp () : base () { - + #if MEASURE_TIME + PerfMeasures = new List ( + new PerformanceMeasure[] { + this.CrowInterface.updateMeasure, + this.CrowInterface.layoutingMeasure, + this.CrowInterface.clippingMeasure, + this.CrowInterface.drawingMeasure, + this.glDrawMeasure + } + ); + 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; @@ -141,15 +159,38 @@ namespace testDrm #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){ @@ -158,7 +199,7 @@ namespace testDrm i++; base.Run (); - + frame.Stop(); frameTime = (int)frame.ElapsedTicks; NotifyValueChanged("frameTime", frameTime); @@ -170,7 +211,10 @@ namespace testDrm frameMin = frameTime; NotifyValueChanged("frameMin", frameMin); } - + #if MEASURE_TIME + foreach (PerformanceMeasure m in PerfMeasures) + m.NotifyChanges(); + #endif } catch (Exception ex) { Console.WriteLine (ex.ToString()); } @@ -180,14 +224,6 @@ namespace testDrm { 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 ******************"); - } } } diff --git a/testDrm/src/Application.cs b/testDrm/src/Application.cs index a1fc45f1..7d5c1d5f 100644 --- a/testDrm/src/Application.cs +++ b/testDrm/src/Application.cs @@ -42,12 +42,14 @@ namespace Crow 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() { @@ -56,7 +58,7 @@ namespace Crow while (true) { CrowInterface.Update (); - Thread.Sleep (1); + Thread.Sleep (ifaceSleep); } } // @@ -80,7 +82,7 @@ namespace Crow } } - gpu = new DRI.GPUControler(); + gpu = new DRI.DRIControler(); cairoSurf = gpu.CairoSurf; CrowInterface = new Interface (); @@ -93,34 +95,33 @@ namespace Crow 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) { @@ -130,17 +131,6 @@ namespace Crow } } -// 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; @@ -157,20 +147,18 @@ namespace Crow } 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; diff --git a/testDrm/src/Egl/Context.cs b/testDrm/src/Egl/Context.cs index b8efecc8..92a97437 100644 --- a/testDrm/src/Egl/Context.cs +++ b/testDrm/src/Egl/Context.cs @@ -409,6 +409,20 @@ namespace EGL 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(){ @@ -420,15 +434,8 @@ namespace EGL 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 diff --git a/testDrm/src/Linux/DRI.cs b/testDrm/src/Linux/DRI/DRIControler.cs similarity index 69% rename from testDrm/src/Linux/DRI.cs rename to testDrm/src/Linux/DRI/DRIControler.cs index b39044f7..a336309d 100644 --- a/testDrm/src/Linux/DRI.cs +++ b/testDrm/src/Linux/DRI/DRIControler.cs @@ -30,11 +30,14 @@ 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, @@ -47,13 +50,7 @@ namespace Linux.DRI { DPMST=7, DPI=8, } - public enum PlaneType { - Overlay = 0, - Primary = 1, - Cursor = 2 - } - - [Flags]public enum PageFlipFlags + [Flags]public enum PageFlipFlags : uint { FlipEvent = 0x01, FlipAsync = 0x02, @@ -87,7 +84,9 @@ namespace Linux.DRI { // 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 { @@ -107,12 +106,40 @@ namespace Linux.DRI { public uint handle; } [StructLayout(LayoutKind.Sequential)] - unsafe internal struct drmPlaneRes { - public uint count_planes; - public uint *planes; + 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 - public class GPUControler : IDisposable { int fd_gpu = -1; GBM.Device gbmDev; GBM.Surface gbmSurf; @@ -128,7 +155,13 @@ namespace Linux.DRI { ModeInfo currentMode, originalMode; uint originalFB; - public GPUControler(string gpu_path = "/dev/dri/card0"){ + 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"); @@ -144,49 +177,11 @@ namespace Linux.DRI { Console.WriteLine (ex.ToString()); } } - - byte bpp = 32; - byte depth = 24; + #endregion 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) { @@ -201,15 +196,15 @@ namespace Linux.DRI { 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); - //setNewMode (); - eglSurf = new EGL.Surface (eglctx, gbmSurf); eglSurf.MakeCurrent (); @@ -228,31 +223,31 @@ namespace Linux.DRI { // ctx.SetSourceRGB (0, 0, 1); // ctx.Fill (); // } -// CairoSurf.Flush (); -// CairoSurf.SwapBuffers (); -// Update (); + //CairoSurf.Flush (); + //CairoSurf.SwapBuffers (); + //Update (); + //setScanOutRegion(); + //Thread.Sleep (100); - //Thread.Sleep (1); + initPageFlipUpdate (); return true; } - void handleDestroyFB(ref GBM.gbm_bo bo, IntPtr data) + + void handleDestroyFB(ref GBM.gbm_bo bo, ref uint data) { - int fb = data.ToInt32(); + uint fb = data; 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()); - } + if (drmModeRmFB (fd_gpu, fb) != 0) + Console.WriteLine ("DestroyFB failed"); + + data = 0; } } + unsafe public void Update(){ GBM.gbm_bo* bo; uint fb; @@ -265,7 +260,7 @@ namespace Linux.DRI { 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); + bo->SetUserData (ref fb, handleDestroyFB); uint connId = connector.Id; ret = drmModeSetCrtc (fd_gpu, currentCrtc.Id, fb, 0, 0, &connId, 1, ref currentMode); @@ -274,21 +269,83 @@ namespace Linux.DRI { gbmSurf.Release (bo); } - [StructLayout(LayoutKind.Sequential)] - struct drmClip { - public ushort x1; - public ushort y1; - public ushort x2; - public ushort y2; + + static void HandlePageFlip(int fd, int sequence, int tv_sec, int tv_usec, ref int user_data) + { + user_data = 0; } - 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); + + 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; @@ -321,7 +378,7 @@ namespace Linux.DRI { unsafe { drmModeSetCursor2 (fd_gpu, crtcid, (uint)boMouseCursor.handle->Handle32, width, height, (int)cursor.Xhot, (int)cursor.Yhot); - drmModeMoveCursor (fd_gpu, crtcid, 0, 0); + //drmModeMoveCursor (fd_gpu, crtcid, 0, 0); } } internal void moveCursor (uint x, uint y){ @@ -329,6 +386,43 @@ namespace Linux.DRI { } #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); @@ -349,7 +443,7 @@ namespace Linux.DRI { // } #region IDisposable implementation - ~GPUControler(){ + ~DRIControler(){ Dispose (false); } public void Dispose () @@ -358,6 +452,11 @@ namespace Linux.DRI { 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 (); @@ -366,24 +465,36 @@ namespace Linux.DRI { 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) + if (boMouseCursor != null) { + drmModeSetCursor2 (fd_gpu, currentCrtc.Id, 0u, 0, 0, 0, 0); boMouseCursor.Dispose (); + } boMouseCursor = null; - if (eglctx != null) - eglctx.Dispose (); - eglctx = 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 (); + gbmDev.Dispose (); + if (currentCrtc != null) currentCrtc.Dispose (); if (connector != null) @@ -394,56 +505,19 @@ namespace Linux.DRI { if (fd_gpu > 0) Libc.close (fd_gpu); fd_gpu = -1; - Console.WriteLine ("disposing ok"); + Console.WriteLine ("GPU controler disposed"); } #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 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) diff --git a/testDrm/src/Linux/DRI/Plane.cs b/testDrm/src/Linux/DRI/Plane.cs index 80b49455..c632e595 100644 --- a/testDrm/src/Linux/DRI/Plane.cs +++ b/testDrm/src/Linux/DRI/Plane.cs @@ -28,6 +28,11 @@ using System.Runtime.InteropServices; namespace Linux.DRI { + public enum PlaneType { + Overlay = 0, + Primary = 1, + Cursor = 2 + } [StructLayout(LayoutKind.Sequential)] unsafe public struct drmPlane { public uint count_formats; @@ -47,10 +52,18 @@ namespace Linux.DRI 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; @@ -74,7 +87,7 @@ namespace Linux.DRI protected virtual void Dispose (bool disposing){ unsafe { if (handle != null) - ModeFreePlane (handle); + drmModeFreePlane (handle); handle = null; } } diff --git a/testDrm/src/Linux/DRI/PlaneResources.cs b/testDrm/src/Linux/DRI/PlaneResources.cs new file mode 100644 index 00000000..cb7990e4 --- /dev/null +++ b/testDrm/src/Linux/DRI/PlaneResources.cs @@ -0,0 +1,77 @@ +// +// PlaneResources.cs +// +// Author: +// Jean-Philippe Bruyère +// +// Copyright (c) 2013-2017 Jean-Philippe Bruyère +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using System.Runtime.InteropServices; + +namespace Linux.DRI +{ + [StructLayout(LayoutKind.Sequential)] + unsafe internal struct 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 + } +} + diff --git a/testDrm/src/Linux/GBM/BufferObject.cs b/testDrm/src/Linux/GBM/BufferObject.cs index 7f6012b3..accf9103 100644 --- a/testDrm/src/Linux/GBM/BufferObject.cs +++ b/testDrm/src/Linux/GBM/BufferObject.cs @@ -29,7 +29,7 @@ using System.Runtime.InteropServices; 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 { @@ -46,9 +46,9 @@ namespace Linux.GBM { 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 @@ -58,6 +58,8 @@ namespace Linux.GBM 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)] @@ -71,11 +73,11 @@ namespace Linux.GBM [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 diff --git a/testDrm/src/Linux/GBM/Surface.cs b/testDrm/src/Linux/GBM/Surface.cs index 9257e14e..073fab61 100644 --- a/testDrm/src/Linux/GBM/Surface.cs +++ b/testDrm/src/Linux/GBM/Surface.cs @@ -130,7 +130,7 @@ namespace Linux.GBM [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)] diff --git a/testDrm/testDrm.csproj b/testDrm/testDrm.csproj index 66df986a..290ebc2b 100644 --- a/testDrm/testDrm.csproj +++ b/testDrm/testDrm.csproj @@ -24,7 +24,7 @@ true full false - DEBUG; + DEBUG;MEASURE_TIME; prompt 4 true @@ -67,7 +67,6 @@ - @@ -81,6 +80,8 @@ + + @@ -109,6 +110,12 @@ + + ui.perfMsr.crow + + + PreserveNewest + diff --git a/testDrm/ui/0.crow b/testDrm/ui/0.crow index bcb80e7c..ab786226 100755 --- a/testDrm/ui/0.crow +++ b/testDrm/ui/0.crow @@ -68,23 +68,7 @@ MouseDown="{Background=Mantis}" MouseUp="{Background=Onyx}"/> - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/testDrm/ui/2.crow b/testDrm/ui/2.crow index 1843e2dd..a56d079d 100755 --- a/testDrm/ui/2.crow +++ b/testDrm/ui/2.crow @@ -1,5 +1,5 @@  - + - + + + + + + \ No newline at end of file diff --git a/testDrm/ui/menu.crow b/testDrm/ui/menu.crow index b3863d5d..e65adfb9 100755 --- a/testDrm/ui/menu.crow +++ b/testDrm/ui/menu.crow @@ -6,6 +6,11 @@ + + + + + diff --git a/testDrm/ui/perfMeasures.crow b/testDrm/ui/perfMeasures.crow new file mode 100755 index 00000000..e49e7f15 --- /dev/null +++ b/testDrm/ui/perfMeasures.crow @@ -0,0 +1,5 @@ + + + + diff --git a/testDrm/ui/perfMsr.crow b/testDrm/ui/perfMsr.crow new file mode 100755 index 00000000..d823ea42 --- /dev/null +++ b/testDrm/ui/perfMsr.crow @@ -0,0 +1,33 @@ + + + + +