From: jpbruyere Date: Sun, 21 May 2017 16:24:35 +0000 (+0200) Subject: drm double buffered, but disposing not ok X-Git-Url: https://git.osiis.dedyn.io/?a=commitdiff_plain;h=0d0496908cf21c770acce2a49c2b53e1d882d235;p=jp%2Fcrow.git drm double buffered, but disposing not ok --- 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.cs deleted file mode 100644 index b39044f7..00000000 --- a/testDrm/src/Linux/DRI.cs +++ /dev/null @@ -1,481 +0,0 @@ -// -// DRM.cs -// -// Author: -// Jean-Philippe Bruyère -// -// Copyright (c) 2013-2017 Jean-Philippe Bruyère -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -using System; -using System.Runtime.InteropServices; -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 - } - /// Video mode flags, bit compatible with the xorg definitions. - [Flags]public enum VideoMode - { - PHSYNC = 0x01, - NHSYNC = 0x02, - PVSYNC = 0x04, - NVSYNC = 0x08, - INTERLACE = 0x10, - DBLSCAN = 0x20, - CSYNC = 0x40, - PCSYNC = 0x80, - NCSYNC = 0x10, - HSKEW = 0x0200, - BCAST = 0x0400, - PIXMUX = 0x0800, - DBLCLK = 0x1000, - CLKDIV2 = 0x2000, - // FLAG_3D_MASK (0x1f<<14) - // FLAG_3D_NONE = 0x0; - // FLAG_3D_FRAME_PACKING = 0x4000, - // FLAG_3D_FIELD_ALTERNATIVE = 0x8000, - // FLAG_3D_LINE_ALTERNATIVE (3<<14) - // FLAG_3D_SIDE_BY_SIDE_FULL (4<<14) - // FLAG_3D_L_DEPTH (5<<14) - // FLAG_3D_L_DEPTH_GFX_GFX_DEPTH (6<<14) - // FLAG_3D_TOP_AND_BOTTOM (7<<14) - // FLAG_3D_SIDE_BY_SIDE_HALF (8<<14) - } - - [StructLayout(LayoutKind.Sequential)] - public struct EventContext - { - public int version; - public IntPtr vblank_handler; - public IntPtr page_flip_handler; - public static readonly int Version = 2; - } - [StructLayout(LayoutKind.Sequential)] - unsafe public struct drmFrameBuffer { - public uint fb_id; - public uint width, height; - public uint pitch; - public uint bpp; - public uint depth; - /* driver specific handle */ - public uint handle; - } - [StructLayout(LayoutKind.Sequential)] - unsafe internal struct drmPlaneRes { - public uint count_planes; - public uint *planes; - } - - public class GPUControler : IDisposable { - int fd_gpu = -1; - GBM.Device gbmDev; - GBM.Surface gbmSurf; - EGL.Context eglctx; - EGL.Surface eglSurf; - - Cairo.EGLDevice cairoDev; - public Cairo.GLSurface CairoSurf; - - Resources resources = null; - Connector connector = null; - Crtc currentCrtc = null; - ModeInfo currentMode, 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 diff --git a/testDrm/src/Linux/DRI/DRIControler.cs b/testDrm/src/Linux/DRI/DRIControler.cs new file mode 100644 index 00000000..a336309d --- /dev/null +++ b/testDrm/src/Linux/DRI/DRIControler.cs @@ -0,0 +1,555 @@ +// +// DRM.cs +// +// Author: +// Jean-Philippe Bruyère +// +// Copyright (c) 2013-2017 Jean-Philippe Bruyère +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using System.Runtime.InteropServices; +using System.Collections.Generic; +using System.Diagnostics; +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 + } + /// Video mode flags, bit compatible with the xorg definitions. + [Flags]public enum VideoMode + { + PHSYNC = 0x01, + NHSYNC = 0x02, + PVSYNC = 0x04, + NVSYNC = 0x08, + INTERLACE = 0x10, + DBLSCAN = 0x20, + CSYNC = 0x40, + PCSYNC = 0x80, + NCSYNC = 0x10, + HSKEW = 0x0200, + BCAST = 0x0400, + PIXMUX = 0x0800, + DBLCLK = 0x1000, + CLKDIV2 = 0x2000, + // FLAG_3D_MASK (0x1f<<14) + // FLAG_3D_NONE = 0x0; + // FLAG_3D_FRAME_PACKING = 0x4000, + // FLAG_3D_FIELD_ALTERNATIVE = 0x8000, + // FLAG_3D_LINE_ALTERNATIVE (3<<14) + // FLAG_3D_SIDE_BY_SIDE_FULL (4<<14) + // FLAG_3D_L_DEPTH (5<<14) + // FLAG_3D_L_DEPTH_GFX_GFX_DEPTH (6<<14) + // FLAG_3D_TOP_AND_BOTTOM (7<<14) + // FLAG_3D_SIDE_BY_SIDE_HALF (8<<14) + } + #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 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 @@ + + + + +